Skip to content

Commit 6e0f1dc

Browse files
quildtidedevmotion
andauthored
Fix InverseGaussian cdf overflows (JuliaStats#1882)
* Fix inversegaussian cdf overflows * Update src/univariate/continuous/inversegaussian.jl Co-authored-by: David Widmann <devmotion@users.noreply.github.com> * Update src/univariate/continuous/inversegaussian.jl Co-authored-by: David Widmann <devmotion@users.noreply.github.com> * Fix missing parentheses * Move parentheses * Move new tests to dedicated inversegaussian file * Add ccdf tests --------- Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
1 parent 47c040b commit 6e0f1dc

File tree

3 files changed

+27
-3
lines changed

3 files changed

+27
-3
lines changed

src/univariate/continuous/inversegaussian.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ function cdf(d::InverseGaussian, x::Real)
9999
y = max(x, 0)
100100
u = sqrt/ y)
101101
v = y / μ
102-
z = normcdf(u * (v - 1)) + exp(2λ / μ) * normcdf(-u * (v + 1))
102+
# 2λ/μ and normlogcdf(-u*(v+1)) are similar magnitude, opp. sign
103+
# truncating to [0, 1] as an additional precaution
104+
# Ref https://github.com/JuliaStats/Distributions.jl/issues/1873
105+
z = clamp(normcdf(u * (v - 1)) + exp(2λ / μ + normlogcdf(-u * (v + 1))), 0, 1)
103106

104107
# otherwise `NaN` is returned for `+Inf`
105108
return isinf(x) && x > 0 ? one(z) : z
@@ -110,7 +113,10 @@ function ccdf(d::InverseGaussian, x::Real)
110113
y = max(x, 0)
111114
u = sqrt/ y)
112115
v = y / μ
113-
z = normccdf(u * (v - 1)) - exp(2λ / μ) * normcdf(-u * (v + 1))
116+
# 2λ/μ and normlogcdf(-u*(v+1)) are similar magnitude, opp. sign
117+
# truncating to [0, 1] as an additional precaution
118+
# Ref https://github.com/JuliaStats/Distributions.jl/issues/1873
119+
z = clamp(normccdf(u * (v - 1)) - exp(2λ / μ + normlogcdf(-u * (v + 1))), 0, 1)
114120

115121
# otherwise `NaN` is returned for `+Inf`
116122
return isinf(x) && x > 0 ? zero(z) : z

test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ const tests = [
9696
"eachvariate",
9797
"univariate/continuous/triangular",
9898
"statsapi",
99+
"univariate/continuous/inversegaussian",
99100

100101
### missing files compared to /src:
101102
# "common",
@@ -137,7 +138,6 @@ const tests = [
137138
# "univariate/continuous/generalizedextremevalue",
138139
# "univariate/continuous/generalizedpareto",
139140
# "univariate/continuous/inversegamma",
140-
# "univariate/continuous/inversegaussian",
141141
# "univariate/continuous/ksdist",
142142
# "univariate/continuous/ksonesided",
143143
# "univariate/continuous/levy",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
@testset "InverseGaussian cdf outside of [0, 1] (#1873)" begin
2+
for d in [
3+
InverseGaussian(1.65, 590),
4+
InverseGaussian(0.5, 1000)
5+
]
6+
for x in [0.02, 1.0, 20.0, 300.0]
7+
p = cdf(d, x)
8+
@test 0.0 <= p <= 1.0
9+
@test p exp(logcdf(d, x))
10+
11+
q = ccdf(d, x)
12+
@test 0.0 <= q <= 1.0
13+
@test q exp(logccdf(d, x))
14+
15+
@test (p + q) 1
16+
end
17+
end
18+
end

0 commit comments

Comments
 (0)