Skip to content

Commit feccbf4

Browse files
authored
Merge pull request #315 from JuliaMath/an/gamma_inc_inv
Some fixes for gamma_inc_inv
2 parents cd39372 + 7104036 commit feccbf4

File tree

2 files changed

+144
-28
lines changed

2 files changed

+144
-28
lines changed

src/gamma_inc.jl

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,17 @@ See also: [`gamma_inc(a,x,ind)`](@ref SpecialFunctions.gamma_inc).
919919
gamma_inc_inv(a::Real, p::Real, q::Real) = _gamma_inc_inv(promote(float(a), float(p), float(q))...)
920920

921921
function _gamma_inc_inv(a::Float64, p::Float64, q::Float64)
922+
923+
if p + q != 1
924+
throw(ArgumentError("p + q must equal one but is $(p + q)"))
925+
end
926+
927+
if iszero(p)
928+
return 0.0
929+
elseif iszero(q)
930+
return Inf
931+
end
932+
922933
if p < 0.5
923934
pcase = true
924935
porq = p
@@ -943,41 +954,54 @@ function _gamma_inc_inv(a::Float64, p::Float64, q::Float64)
943954
x0 = gamma_inc_inv_asmall(a, p, q, pcase)
944955
else #large a
945956
haseta = true
946-
(x0,fp) = gamma_inc_inv_alarge(a, porq, s)
957+
x0, fp = gamma_inc_inv_alarge(a, porq, s)
947958
end
948959

949960
t = 1
950961
x = x0
951962
n = 1
952963
logabsgam = logabsgamma(a)[1]
953-
#Newton-like higher order iteration with upper limit as 15.
964+
# Newton-like higher order iteration with upper limit as 15.
954965
while t > 1.0e-15 && n < 15
955966
x = x0
956967
= x*x
957968
if !haseta
958969
dlnr = (1.0 - a)*log(x) + x + logabsgam
959970
if dlnr > log(floatmax(Float64)/1000.0)
960-
n = 20
971+
break
961972
else
962973
r = exp(dlnr)
963974
end
964975
else
965976
r = -(1/fp)*x
966977
end
967978

968-
(px, qx) = gamma_inc(a, x, 0)
969-
ck1 = pcase ? -r*(px-p) : r*(qx-q)
970-
ck2 = (x - a + 1.0)/(2.0*x)
971-
ck3 = (@horner(x, @horner(a, 1, -3, 2), @horner(a, 4, -4), 2))/(6*x²)
972-
r = ck1
973-
if a > 0.1
974-
x0 = @horner(r, x, 1.0, ck2, ck3)
975-
else
976-
if a > 0.05
977-
x0 = @horner(r, x, 1.0, ck2)
979+
px, qx = gamma_inc(a, x, 0)
980+
981+
ck1 = pcase ? -r*(px - p) : r*(qx - q)
982+
if a > 0.05
983+
ck2 = (x - a + 1.0)/(2.0*x)
984+
985+
# This check is not in the invincgam subroutine from IncgamFI but it probably
986+
# should be since the routine fails to compute a finite value for very small p
987+
if !isfinite(ck2)
988+
break
989+
end
990+
991+
if a > 0.1
992+
ck3 = (@horner(x, @horner(a, 1, -3, 2), @horner(a, 4, -4), 2))/(6*x²)
993+
994+
# This check is not in the invincgam subroutine from IncgamFI but it probably
995+
# should be since the routine fails to compute a finite value for very small p
996+
if !isfinite(ck3)
997+
break
998+
end
999+
x0 = @horner(ck1, x, 1.0, ck2, ck3)
9781000
else
979-
x0 = x + r
1001+
x0 = @horner(ck1, x, 1.0, ck2)
9801002
end
1003+
else
1004+
x0 = x + ck1
9811005
end
9821006

9831007
t = abs(x/x0 - 1.0)

0 commit comments

Comments
 (0)