11# functions related to gamma distribution
22
3+ using HypergeometricFunctions: drummond1F1
4+
35# R implementations
4- # For pdf and logpdf we use the Julia implementation
56using . RFunctions:
6- gammacdf,
7- gammaccdf,
8- gammalogcdf,
9- gammalogccdf,
10- gammainvcdf,
11- gammainvccdf,
7+ # gammapdf,
8+ # gammalogpdf,
9+ # gammacdf,
10+ # gammaccdf,
11+ # gammalogcdf,
12+ # gammalogccdf,
13+ # gammainvcdf,
14+ # gammainvccdf,
1215 gammainvlogcdf,
1316 gammainvlogccdf
1417
@@ -22,3 +25,80 @@ function gammalogpdf(k::T, θ::T, x::T) where {T<:Real}
2225 val = - loggamma(k) + xlogy(k - 1 , xθ) - log(θ) - xθ
2326 return x < 0 ? oftype(val, - Inf ) : val
2427end
28+
29+ function gammacdf(k:: T , θ:: T , x:: T ) where {T<: Real }
30+ # Handle the degenerate case
31+ if iszero(k)
32+ return float(last(promote(x, x >= 0 )))
33+ end
34+ return first(gamma_inc(k, max(0 , x)/ θ))
35+ end
36+ gammacdf(k:: Real , θ:: Real , x:: Real ) = gammacdf(map(float, promote(k, θ, x)). .. )
37+
38+ function gammaccdf(k:: T , θ:: T , x:: T ) where {T<: Real }
39+ # Handle the degenerate case
40+ if iszero(k)
41+ return float(last(promote(x, x < 0 )))
42+ end
43+ return last(gamma_inc(k, max(0 , x)/ θ))
44+ end
45+ gammaccdf(k:: Real , θ:: Real , x:: Real ) = gammaccdf(map(float, promote(k, θ, x)). .. )
46+
47+ gammalogcdf(k:: Real , θ:: Real , x:: Real ) = _gammalogcdf(map(float, promote(k, θ, x)). .. )
48+
49+ # Implemented via the non-log version. For tiny values, we recompute the result with
50+ # loggamma. In that situation, there is little risk of significant cancellation.
51+ function _gammalogcdf(k:: Float64 , θ:: Float64 , x:: Float64 )
52+ # Handle the degenerate case
53+ if iszero(k)
54+ return log(x >= 0 )
55+ end
56+
57+ xdθ = max(0 , x)/ θ
58+ l, u = gamma_inc(k, xdθ)
59+ if l < floatmin(Float64) && isfinite(k) && isfinite(xdθ)
60+ return - log(k) + k* log(xdθ) - xdθ + log(drummond1F1(1.0 , 1 + k, xdθ)) - loggamma(k)
61+ elseif l < 0.7
62+ return log(l)
63+ else
64+ return log1p(- u)
65+ end
66+ end
67+ function _gammalogcdf(k:: T , θ:: T , x:: T ) where {T<: Union{Float16,Float32} }
68+ return T(_gammalogcdf(Float64(k), Float64(θ), Float64(x)))
69+ end
70+
71+ gammalogccdf(k:: Real , θ:: Real , x:: Real ) = _gammalogccdf(map(float, promote(k, θ, x)). .. )
72+
73+ # Implemented via the non-log version. For tiny values, we recompute the result with
74+ # loggamma. In that situation, there is little risk of significant cancellation.
75+ function _gammalogccdf(k:: Float64 , θ:: Float64 , x:: Float64 )
76+ # Handle the degenerate case
77+ if iszero(k)
78+ return log(x < 0 )
79+ end
80+
81+ xdθ = max(0 , x)/ θ
82+ l, u = gamma_inc(k, xdθ)
83+ if u < floatmin(Float64)
84+ return loggamma(k, xdθ) - loggamma(k)
85+ elseif u < 0.7
86+ return log(u)
87+ else
88+ return log1p(- l)
89+ end
90+ end
91+
92+ function _gammalogccdf(k:: T , θ:: T , x:: T ) where {T<: Union{Float16,Float32} }
93+ return T(_gammalogccdf(Float64(k), Float64(θ), Float64(x)))
94+ end
95+
96+ function gammainvcdf(k:: Real , θ:: Real , p:: Real )
97+ _k, _θ, _p = promote(k, θ, p)
98+ return _θ* gamma_inc_inv(_k, _p, 1 - _p)
99+ end
100+
101+ function gammainvccdf(k:: Real , θ:: Real , p:: Real )
102+ _k, _θ, _p = promote(k, θ, p)
103+ return _θ* gamma_inc_inv(_k, 1 - _p, _p)
104+ end
0 commit comments