Skip to content

Commit

Permalink
Limit number of Newton iterations in beta_inc_inv and allow much
Browse files Browse the repository at this point in the history
smaller starting values.
  • Loading branch information
andreasnoack committed Mar 17, 2022
1 parent ce58a13 commit 37c0c62
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
14 changes: 10 additions & 4 deletions src/beta_inc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,9 @@ function beta_inc_inv(a::Real, b::Real, p::Real, q::Real)
end

function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)

maxiter = 30

#change tail if necessary
if p > 0.5
y, x = _beta_inc_inv(b, a, q, p)
Expand Down Expand Up @@ -968,8 +971,8 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
sq = 1.0
prev = 1.0

if x < 0.0001
x = 0.0001
if x < 1e-200
x = 1e-200
end
if x > .9999
x = .9999
Expand Down Expand Up @@ -1001,7 +1004,7 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
acu = exp10(iex)

#iterate
while true
for i in 1:maxiter
p_approx = beta_inc(a, b, x)[1]
xin = x
p_approx = (p_approx - p)*min(
Expand All @@ -1026,7 +1029,7 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
end

#check if current estimate is acceptable

prev, acu, p_approx, x, tx
if prev <= acu || p_approx^2 <= acu
x = tx
return (x, 1.0 - x)
Expand All @@ -1039,6 +1042,9 @@ function _beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64=1-p)
x = tx
p_approx_prev = p_approx
end

@debug "Newton iterations didn't converge in $maxiter iterations. The result might have reduced precision."
return (x, 1.0 - x)
end

function _beta_inc_inv(a::T, b::T, p::T) where {T<:Union{Float16, Float32}}
Expand Down
6 changes: 6 additions & 0 deletions test/beta_inc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -299,4 +299,10 @@ end
@test first(beta_inc_inv(1.0, 1.0, 1e-21)) 1e-21
@test beta_inc_inv(1.0e30, 1.0, 0.49) == (1.0, 0.0)
end

@testset "Avoid infinite loops" begin
# See https://github.com/JuliaStats/StatsFuns.jl/issues/133#issuecomment-1069602721
y = 2.0e-280
@test beta_inc(2.0, 1.0, beta_inc_inv(2.0, 1.0, y, 1.0)[1])[1] y
end
end

0 comments on commit 37c0c62

Please sign in to comment.