Skip to content

Commit 39d0f98

Browse files
committed
Adjust tolerance instead of number of iterations
1 parent 37c0c62 commit 39d0f98

File tree

1 file changed

+8
-26
lines changed

1 file changed

+8
-26
lines changed

src/beta_inc.jl

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -919,9 +919,6 @@ function beta_inc_inv(a::Real, b::Real, p::Real, q::Real)
919919
end
920920

921921
function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
922-
923-
maxiter = 30
924-
925922
#change tail if necessary
926923
if p > 0.5
927924
y, x = _beta_inc_inv(b, a, q, p)
@@ -937,7 +934,6 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
937934
r = sqrt(-2*log(p))
938935
p_approx = r - @horner(r, 2.30753e+00, 0.27061e+00) / @horner(r, 1.0, .99229e+00, .04481e+00)
939936
fpu = floatmin(Float64)
940-
sae = log10(fpu)
941937
lb = logbeta(a, b)
942938

943939
if a > 1.0 && b > 1.0
@@ -971,12 +967,7 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
971967
sq = 1.0
972968
prev = 1.0
973969

974-
if x < 1e-200
975-
x = 1e-200
976-
end
977-
if x > .9999
978-
x = .9999
979-
end
970+
x = clamp(x, fpu, prevfloat(1.0))
980971

981972
# This first argument was proposed in
982973
#
@@ -1000,11 +991,11 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
1000991
# The idea with the -5.0/a^2 - 1.0/p^0.2 - 34.0 correction is to
1001992
# use -2r - 2 (for 16 digits) for large values of a and p but use
1002993
# a much smaller tolerance for small values of a and p.
1003-
iex = max(-5.0/a^2 - 1.0/p^0.2 - 34.0, sae)
1004-
acu = exp10(iex)
994+
iex = -5.0/a^2 - 1.0/p^0.2 - 34.0
995+
acu = max(exp10(iex), 10 * fpu) # 10 * fpu instead of fpu avoids hangs for small values
1005996

1006997
#iterate
1007-
for i in 1:maxiter
998+
while true
1008999
p_approx = beta_inc(a, b, x)[1]
10091000
xin = x
10101001
p_approx = (p_approx - p)*min(
@@ -1015,21 +1006,15 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
10151006
if p_approx * p_approx_prev <= 0.0
10161007
prev = max(sq, fpu)
10171008
end
1018-
g = 1.0
10191009

1020-
tx = x - g*p_approx
1021-
while true
1022-
adj = g*p_approx
1023-
sq = adj^2
1010+
adj = p_approx
1011+
tx = x - adj
1012+
while prev <= (sq = adj^2) || tx < 0.0 || tx > 1.0
1013+
adj /= 3.0
10241014
tx = x - adj
1025-
if (prev > sq && tx >= 0.0 && tx <= 1.0)
1026-
break
1027-
end
1028-
g /= 3.0
10291015
end
10301016

10311017
#check if current estimate is acceptable
1032-
prev, acu, p_approx, x, tx
10331018
if prev <= acu || p_approx^2 <= acu
10341019
x = tx
10351020
return (x, 1.0 - x)
@@ -1042,9 +1027,6 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
10421027
x = tx
10431028
p_approx_prev = p_approx
10441029
end
1045-
1046-
@debug "Newton iterations didn't converge in $maxiter iterations. The result might have reduced precision."
1047-
return (x, 1.0 - x)
10481030
end
10491031

10501032
function _beta_inc_inv(a::T, b::T, p::T) where {T<:Union{Float16, Float32}}

0 commit comments

Comments
 (0)