@@ -665,7 +665,7 @@ function gamma_inc_fsum(a::Float64, x::Float64)
665
665
end
666
666
667
667
"""
668
- gamma_inc_inv_psmall(a,p )
668
+ gamma_inc_inv_psmall(a, logr )
669
669
670
670
Compute `x0` - initial approximation when `p` is small.
671
671
Here we invert the series in Eqn (2.20) in the paper and write the inversion problem as:
@@ -675,8 +675,7 @@ x = r\\left[1 + a\\sum_{k=1}^{\\infty}\\frac{(-x)^{n}}{(a+n)n!}\\right]^{-1/a},
675
675
where ``r = (p\\ Gamma(1+a))^{1/a}``
676
676
Inverting this relation we obtain ``x = r + \\ sum_{k=2}^{\\ infty}c_{k}r^{k}``.
677
677
"""
678
- function gamma_inc_inv_psmall (a:: Float64 , p:: Float64 )
679
- logr = (1.0 / a)* (log (p) + logabsgamma (a + 1.0 )[1 ])
678
+ function gamma_inc_inv_psmall (a:: Float64 , logr:: Float64 )
680
679
r = exp (logr)
681
680
ap1 = a + 1.0
682
681
ap1² = ap1* ap1
@@ -726,19 +725,19 @@ function gamma_inc_inv_qsmall(a::Float64, q::Float64)
726
725
end
727
726
728
727
"""
729
- gamma_inc_inv_asmall(a,p,q, pcase)
730
-
731
- Compute `x0` - initial approximation when `a` is small.
732
- Here the solution `x` of ``P(a,x)=p`` satisfies ``x_{l} < x < x_{u}``
733
- where ``x_{l} = (p\\ Gamma(a+1))^{1/a}`` and ``x_{u} = -\\ log{(1 - p\\ Gamma(a+1))}``, and is used as starting value for Newton iteration.
734
- """
735
- function gamma_inc_inv_asmall (a:: Float64 , p :: Float64 , q :: Float64 , pcase:: Bool )
736
- logp = ( pcase) ? log (p ) : log1p (- q )
737
- return exp ((1.0 / a) * ( logp + loggamma1p (a)))
728
+ gamma_inc_inv_asmall(a, minpq, pcase)
729
+
730
+ Compute `x0` - initial approximation when `a` is small.
731
+ Here the solution `x` of ``P(a,x)=p`` satisfies ``x_{l} < x < x_{u}``
732
+ where ``x_{l} = (p\\ Gamma(a+1))^{1/a}`` and ``x_{u} = -\\ log{(1 - p\\ Gamma(a+1))}``, and is used as starting value for Newton iteration.
733
+ """
734
+ function gamma_inc_inv_asmall (a:: Float64 , minpq :: Float64 , pcase:: Bool )
735
+ logp = pcase ? log (minpq ) : log1p (- minpq )
736
+ return exp ((logp + loggamma1p (a)) / a )
738
737
end
739
738
740
739
"""
741
- gamma_inc_inv_alarge(a,porq,s )
740
+ gamma_inc_inv_alarge(a, minpq, pcase )
742
741
743
742
Compute `x0` - initial approximation when `a` is large.
744
743
The inversion problem is rewritten as :
@@ -753,9 +752,10 @@ and it is possible to expand:
753
752
which is calculated by coeff1, coeff2 and coeff3 functions below.
754
753
This returns a tuple `(x0,fp)`, where `fp` is computed since it's an approximation for the coefficient after inverting the original power series.
755
754
"""
756
- function gamma_inc_inv_alarge (a:: Float64 , porq:: Float64 , s:: Integer )
757
- r = erfcinv (2 * porq)
758
- eta = s* r/ sqrt (a* 0.5 )
755
+ function gamma_inc_inv_alarge (a:: Float64 , minpq:: Float64 , pcase:: Bool )
756
+ r = erfcinv (2 * minpq)
757
+ s = r/ sqrt (a* 0.5 )
758
+ eta = pcase ? - s : s
759
759
eta += (coeff1 (eta) + (coeff2 (eta) + coeff3 (eta)/ a)/ a)/ a
760
760
x0 = a* lambdaeta (eta)
761
761
fp = - sqrt (inv2π* a)* exp (- 0.5 * a* eta* eta)/ gammax (a)
@@ -921,43 +921,41 @@ See also: [`gamma_inc(a,x,ind)`](@ref SpecialFunctions.gamma_inc).
921
921
"""
922
922
gamma_inc_inv (a:: Real , p:: Real , q:: Real ) = _gamma_inc_inv (promote (float (a), float (p), float (q))... )
923
923
924
- function _gamma_inc_inv (a:: Float64 , p:: Float64 , q:: Float64 )
925
-
924
+ function _gamma_inc_inv (a:: T , p:: T , q:: T ) where {T<: Real }
926
925
if p + q != 1
927
926
throw (ArgumentError (" p + q must equal one but is $(p + q) " ))
928
927
end
929
928
930
929
if iszero (p)
931
- return 0.0
930
+ return zero (T)
932
931
elseif iszero (q)
933
- return Inf
932
+ return T ( Inf )
934
933
end
935
934
936
- if p < 0.5
937
- pcase = true
938
- porq = p
939
- s = - 1
940
- else
941
- pcase = false
942
- porq = q
943
- s = 1
944
- end
935
+ pcase = p < 0.5
936
+ minpq = pcase ? p : q
937
+
938
+ return __gamma_inc_inv (a, minpq, pcase)
939
+ end
940
+
941
+ function __gamma_inc_inv (a:: Float64 , minpq:: Float64 , pcase:: Bool )
945
942
haseta = false
946
943
947
- logr = (1.0 / a)* (log (p) + logabsgamma (a + 1.0 )[1 ])
944
+ logp = pcase ? log (minpq) : log1p (- minpq)
945
+ logr = (1.0 / a)* (logp + logabsgamma (a + 1.0 )[1 ])
948
946
if logr < log (0.2 * (1 + a)) # small value of p
949
- x0 = gamma_inc_inv_psmall (a, p )
950
- elseif ((q < min (0.02 , exp (- 1.5 * a)/ gamma (a))) && ( a < 10 )) # small q
951
- x0 = gamma_inc_inv_qsmall (a, q )
952
- elseif abs (porq - 0.5 ) < 1.0e-05
947
+ x0 = gamma_inc_inv_psmall (a, logr )
948
+ elseif ! pcase && minpq < min (0.02 , exp (- 1.5 * a)/ gamma (a)) && a < 10 # small q
949
+ x0 = gamma_inc_inv_qsmall (a, minpq )
950
+ elseif abs (minpq - 0.5 ) < 1.0e-05
953
951
x0 = a - 1.0 / 3.0 + (8.0 / 405.0 + 184.0 / 25515.0 / a)/ a
954
952
elseif abs (a - 1.0 ) < 1.0e-4
955
- x0 = pcase ? - log1p (- p ) : - log (q )
953
+ x0 = pcase ? - log1p (- minpq ) : - log (minpq )
956
954
elseif a < 1.0 # small value of a
957
- x0 = gamma_inc_inv_asmall (a, p, q , pcase)
955
+ x0 = gamma_inc_inv_asmall (a, minpq , pcase)
958
956
else # large a
959
957
haseta = true
960
- x0, fp = gamma_inc_inv_alarge (a, porq, s )
958
+ x0, fp = gamma_inc_inv_alarge (a, minpq, pcase )
961
959
end
962
960
963
961
t = 1
@@ -981,7 +979,7 @@ function _gamma_inc_inv(a::Float64, p::Float64, q::Float64)
981
979
982
980
px, qx = gamma_inc (a, x, 0 )
983
981
984
- ck1 = pcase ? - r* (px - p ) : r* (qx - q )
982
+ ck1 = pcase ? - r* (px - minpq ) : r* (qx - minpq )
985
983
if a > 0.05
986
984
ck2 = (x - a + 1.0 )/ (2.0 * x)
987
985
@@ -1014,16 +1012,8 @@ function _gamma_inc_inv(a::Float64, p::Float64, q::Float64)
1014
1012
return x
1015
1013
end
1016
1014
1017
- function _gamma_inc_inv (a:: T , p:: T , q:: T ) where {T <: Union{Float16, Float32} }
1018
- if p + q != one (T)
1019
- throw (ArgumentError (" p + q must equal one but was $(p + q) " ))
1020
- end
1021
- p64, q64 = if p < q
1022
- (Float64 (p), 1 - Float64 (p))
1023
- else
1024
- (1 - Float64 (q), Float64 (q))
1025
- end
1026
- return T (_gamma_inc_inv (Float64 (a), p64, q64))
1015
+ function __gamma_inc_inv (a:: T , minpq:: T , pcase:: Bool ) where {T<: Union{Float16,Float32} }
1016
+ return T (__gamma_inc_inv (Float64 (a), Float64 (minpq), pcase))
1027
1017
end
1028
1018
1029
1019
# like promote(x,y), but don't complexify real values
0 commit comments