From 1331649f84d468f612b49cbb6c9feca9616e464d Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Thu, 19 Dec 2024 10:33:49 -0600 Subject: [PATCH 1/3] Special case Geometric(OneHalf()) --- src/univariate/discrete/geometric.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/univariate/discrete/geometric.jl b/src/univariate/discrete/geometric.jl index f7f940ee4..8f92c552e 100644 --- a/src/univariate/discrete/geometric.jl +++ b/src/univariate/discrete/geometric.jl @@ -34,7 +34,9 @@ function Geometric(p::Real; check_args::Bool=true) return Geometric{typeof(p)}(p) end -Geometric() = Geometric{Float64}(0.5) +struct OneHalf <: Real end +Geometric() = Geometric{OneHalf}(OneHalf()) +Base.getproperty(d::Geometric{OneHalf}, s::Symbol) = s == :p ? 0.5 : getfield(d, s) @distr_support Geometric 0 Inf @@ -137,6 +139,7 @@ cf(d::Geometric, t::Real) = laplace_transform(d, -t*im) ### Sampling rand(rng::AbstractRNG, d::Geometric) = floor(Int,-randexp(rng) / log1p(-d.p)) +rand(rng::AbstractRNG, ::Geometric{OneHalf}) = leading_zeros(rand(rng, UInt)) ### Model Fitting From 44bbde7a272bfd7f18eca3bbbba2276e10941914 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Fri, 20 Dec 2024 07:14:27 -0600 Subject: [PATCH 2/3] Remove OneHalf and branch at sample time --- src/univariate/discrete/geometric.jl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/univariate/discrete/geometric.jl b/src/univariate/discrete/geometric.jl index 8f92c552e..0d8ecbf8e 100644 --- a/src/univariate/discrete/geometric.jl +++ b/src/univariate/discrete/geometric.jl @@ -34,9 +34,7 @@ function Geometric(p::Real; check_args::Bool=true) return Geometric{typeof(p)}(p) end -struct OneHalf <: Real end -Geometric() = Geometric{OneHalf}(OneHalf()) -Base.getproperty(d::Geometric{OneHalf}, s::Symbol) = s == :p ? 0.5 : getfield(d, s) +Geometric() = Geometric{Float64}(0.5) @distr_support Geometric 0 Inf @@ -138,8 +136,14 @@ cf(d::Geometric, t::Real) = laplace_transform(d, -t*im) ### Sampling -rand(rng::AbstractRNG, d::Geometric) = floor(Int,-randexp(rng) / log1p(-d.p)) -rand(rng::AbstractRNG, ::Geometric{OneHalf}) = leading_zeros(rand(rng, UInt)) +# Inlining is required to hoist the d.p == 0.5 check when generating in bulk +@inline function rand(rng::AbstractRNG, d::Geometric) + if d.p == 0.5 + leading_zeros(rand(rng, UInt)) # This branch is a performance optimization + else + floor(Int,-randexp(rng) / log1p(-d.p)) + end +end ### Model Fitting From 55be7f699b453410b4fd19a9a7af6183223de8f0 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Fri, 20 Dec 2024 07:19:29 -0600 Subject: [PATCH 3/3] Use 1//2 instead of 0.5 --- src/univariate/discrete/geometric.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/univariate/discrete/geometric.jl b/src/univariate/discrete/geometric.jl index 0d8ecbf8e..20043e60f 100644 --- a/src/univariate/discrete/geometric.jl +++ b/src/univariate/discrete/geometric.jl @@ -136,9 +136,9 @@ cf(d::Geometric, t::Real) = laplace_transform(d, -t*im) ### Sampling -# Inlining is required to hoist the d.p == 0.5 check when generating in bulk +# Inlining is required to hoist the d.p == 1//2 check when generating in bulk @inline function rand(rng::AbstractRNG, d::Geometric) - if d.p == 0.5 + if d.p == 1//2 leading_zeros(rand(rng, UInt)) # This branch is a performance optimization else floor(Int,-randexp(rng) / log1p(-d.p))