Skip to content

Commit e41adcf

Browse files
committed
Avoid an infinite recursion in beta_inc_inv by ensuring that search
direction is finite.
1 parent 8863a5f commit e41adcf

File tree

2 files changed

+61
-58
lines changed

2 files changed

+61
-58
lines changed

src/beta_inc.jl

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -919,28 +919,28 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
919919

920920
#Initial approx
921921

922-
r = sqrt(-log(pp^2))
922+
r = sqrt(-2*log(pp))
923923
pp_approx = r - @horner(r, 2.30753e+00, 0.27061e+00) / @horner(r, 1.0, .99229e+00, .04481e+00)
924924

925925
if a > 1.0 && b > 1.0
926926
r = (pp_approx^2 - 3.0)/6.0
927927
s = 1.0/(2*aa - 1.0)
928928
t = 1.0/(2*bb - 1.0)
929-
h = 2.0/(s+t)
930-
w = pp_approx*sqrt(h+r)/h - (t-s)*(r + 5.0/6.0 - 2.0/(3.0*h))
931-
x = aa/ (aa+bb*exp(w^2))
929+
h = 2.0/(s + t)
930+
w = pp_approx*sqrt(h + r)/h - (t - s)*(r + 5.0/6.0 - 2.0/(3.0*h))
931+
x = aa/(aa + bb*exp(w + w))
932932
else
933933
r = 2.0*bb
934934
t = 1.0/(9.0*bb)
935-
t = r*(1.0-t+pp_approx*sqrt(t))^3
935+
t = r*(1.0 - t + pp_approx*sqrt(t))^3
936936
if t <= 0.0
937-
x = -expm1((log((1.0-pp)*bb)+lb)/bb)
937+
x = -expm1((log((1.0 - pp)*bb) + lb)/bb)
938938
else
939-
t = (4.0*aa+r-2.0)/t
939+
t = (4.0*aa + r - 2.0)/t
940940
if t <= 1.0
941-
x = exp((log(pp*aa)+lb)/aa)
941+
x = exp((log(pp*aa) + lb)/aa)
942942
else
943-
x = 1.0 - 2.0/(t+1.0)
943+
x = 1.0 - 2.0/(t + 1.0)
944944
end
945945
end
946946
end
@@ -965,9 +965,10 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
965965

966966
#iterate
967967
while true
968-
pp_approx = beta_inc(aa,bb,x)[1]
968+
pp_approx = beta_inc(aa, bb, x)[1]
969969
xin = x
970-
pp_approx = (pp_approx-pp)*exp(lb+r*log(xin)+t*log1p(-xin))
970+
pp_approx = (pp_approx - pp)*min(floatmax(), exp(lb + r*log(xin) + t*log1p(-xin)))
971+
971972
if pp_approx * pp_approx_prev <= 0.0
972973
prev = max(sq, fpu)
973974
end
@@ -978,6 +979,7 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
978979
adj = g*pp_approx
979980
sq = adj^2
980981
tx = x - adj
982+
prev
981983
if (prev > sq && tx >= 0.0 && tx <= 1.0)
982984
break
983985
end
@@ -988,11 +990,11 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
988990

989991
if prev <= acu || pp_approx^2 <= acu
990992
x = tx
991-
return indx ? (1.0 - x, x) : (x, 1.0-x)
993+
return indx ? (1.0 - x, x) : (x, 1.0 - x)
992994
end
993995

994996
if tx == x
995-
return indx ? (1.0 - x, x) : (x, 1.0-x)
997+
return indx ? (1.0 - x, x) : (x, 1.0 - x)
996998
end
997999

9981000
x = tx

test/beta_inc.jl

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -216,49 +216,50 @@ end
216216

217217
@testset "inverse of incomplete beta" begin
218218
f(a,b,p) = beta_inc_inv(a,b,p)[1]
219-
@test f(.5,.5,0.6376856085851985E-01) 0.01
220-
@test f(.5,.5,0.20483276469913355) 0.1
221-
@test f(.5,.5,1.0000) 1.0000
222-
@test f(1.0,.5,0.0) 0.00
223-
@test f(1.0,.5,0.5012562893380045E-02) 0.01
224-
@test f(1.0,.5,0.5131670194948620E-01) 0.1
225-
@test f(1.0,.5, 0.2928932188134525) 0.5
226-
@test f(1.0,1.0,.5) 0.5
227-
@test f(2.0,2.0,.028) 0.1
228-
@test f(2.0,2.0,0.104) 0.2
229-
@test f(2.0,2.0,.216) 0.3
230-
@test f(2.0,2.0,.352) 0.4
231-
@test f(2.0,2.0,.5) 0.5
232-
@test f(2.0,2.0,0.648) 0.6
233-
@test f(2.0,2.0,0.784) 0.7
234-
@test f(2.0,2.0,0.896) 0.8
235-
@test f(2.0,2.0,.972) 0.9
236-
@test f(5.5,5.0,0.4361908850559777) .5
237-
@test f(10.0,.5,0.1516409096347099) 0.9
238-
@test f(10.0,5.0,0.8978271484375000E-01) 0.5
239-
@test f(10.0,5.0,1.00) 1.00
240-
@test f(10.0,10.0,.5) .5
241-
@test f(20.0,5.0,0.4598773297575791) 0.8
242-
@test f(20.0,10.0,0.2146816102371739) 0.6
243-
@test f(20.0,10.0,0.9507364826957875) 0.8
244-
@test f(20.0,20.0,.5) .5
245-
@test f(20.0,20.0,0.8979413687105918) 0.6
246-
@test f(30.0,10.0,0.2241297491808366) 0.7
247-
@test f(30.0,10.0,0.7586405487192086) 0.8
248-
@test f(40.0,20.0,0.7001783247477069) 0.7
249-
@test f(1.0,0.5,0.5131670194948620E-01) 0.1
250-
@test f(1.0,0.5,0.1055728090000841) 0.2
251-
@test f(1.0,0.5,0.1633399734659245) 0.3
252-
@test f(1.0,0.5,0.2254033307585166) 0.4
253-
@test f(1.0,2.0,.36) 0.2
254-
@test f(1.0,3.0,.488) 0.2
255-
@test f(1.0,4.0,.5904) 0.2
256-
@test f(1.0,5.0,.67232) 0.2
257-
@test f(2.0,2.0,.216) 0.3
258-
@test f(3.0,2.0,0.837e-1) 0.3
259-
@test f(4.0,2.0,0.3078e-1) 0.3
260-
@test f(5.0,2.0,0.10935e-1) 0.3
261-
@test f(1.30625000,11.75620000,0.9188846846205182) 0.225609
262-
@test f(1.30625000,11.75620000,0.21053116418502513) 0.033557
263-
@test f(1.30625000,11.75620000,0.18241165418408148) 0.029522
219+
@test f(.5, .5, 0.6376856085851985E-01) 0.01
220+
@test f(.5, .5, 0.20483276469913355) 0.1
221+
@test f(.5, .5, 1.0000) 1.0000
222+
@test f(1.0, .5, 0.0) 0.00
223+
@test f(1.0, .5, 0.5012562893380045E-02) 0.01
224+
@test f(1.0, .5, 0.5131670194948620E-01) 0.1
225+
@test f(1.0, .5, 0.2928932188134525) 0.5
226+
@test f(1.0, 1.0, .5) 0.5
227+
@test f(2.0, 2.0, .028) 0.1
228+
@test f(2.0, 2.0, 0.104) 0.2
229+
@test f(2.0, 2.0, .216) 0.3
230+
@test f(2.0, 2.0, .352) 0.4
231+
@test f(2.0, 2.0, .5) 0.5
232+
@test f(2.0, 2.0, 0.648) 0.6
233+
@test f(2.0, 2.0, 0.784) 0.7
234+
@test f(2.0, 2.0, 0.896) 0.8
235+
@test f(2.0, 2.0, .972) 0.9
236+
@test f(5.5, 5.0, 0.4361908850559777) .5
237+
@test f(10.0, .5, 0.1516409096347099) 0.9
238+
@test f(10.0, 5.0, 0.8978271484375000E-01) 0.5
239+
@test f(10.0, 5.0, 1.00) 1.00
240+
@test f(10.0, 10.0, .5) .5
241+
@test f(20.0, 5.0, 0.4598773297575791) 0.8
242+
@test f(20.0, 10.0, 0.2146816102371739) 0.6
243+
@test f(20.0, 10.0, 0.9507364826957875) 0.8
244+
@test f(20.0, 20.0, .5) .5
245+
@test f(20.0, 20.0, 0.8979413687105918) 0.6
246+
@test f(30.0, 10.0, 0.2241297491808366) 0.7
247+
@test f(30.0, 10.0, 0.7586405487192086) 0.8
248+
@test f(40.0, 20.0, 0.7001783247477069) 0.7
249+
@test f(1.0, 0.5, 0.5131670194948620E-01) 0.1
250+
@test f(1.0, 0.5, 0.1055728090000841) 0.2
251+
@test f(1.0, 0.5, 0.1633399734659245) 0.3
252+
@test f(1.0, 0.5, 0.2254033307585166) 0.4
253+
@test f(1.0, 2.0, .36) 0.2
254+
@test f(1.0, 3.0, .488) 0.2
255+
@test f(1.0, 4.0, .5904) 0.2
256+
@test f(1.0, 5.0, .67232) 0.2
257+
@test f(2.0, 2.0, .216) 0.3
258+
@test f(3.0, 2.0, 0.837e-1) 0.3
259+
@test f(4.0, 2.0, 0.3078e-1) 0.3
260+
@test f(5.0, 2.0, 0.10935e-1) 0.3
261+
@test f(1.30625000, 11.75620000, 0.9188846846205182) 0.225609
262+
@test f(1.30625000, 11.75620000, 0.21053116418502513) 0.033557
263+
@test f(1.30625000, 11.75620000, 0.18241165418408148) 0.029522
264+
@test f(1000.0, 2.0, 9.0797754e-317) 0.48 # This one is a bit slow (but also hard)
264265
end

0 commit comments

Comments
 (0)