@@ -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)
@@ -925,43 +925,41 @@ See also: [`gamma_inc(a,x,ind)`](@ref SpecialFunctions.gamma_inc).
925
925
"""
926
926
gamma_inc_inv (a:: Real , p:: Real , q:: Real ) = _gamma_inc_inv (promote (float (a), float (p), float (q))... )
927
927
928
- function _gamma_inc_inv (a:: Float64 , p:: Float64 , q:: Float64 )
929
-
928
+ function _gamma_inc_inv (a:: T , p:: T , q:: T ) where {T<: Real }
930
929
if p + q != 1
931
930
throw (ArgumentError (" p + q must equal one but is $(p + q) " ))
932
931
end
933
932
934
933
if iszero (p)
935
- return 0.0
934
+ return zero (T)
936
935
elseif iszero (q)
937
- return Inf
936
+ return T ( Inf )
938
937
end
939
938
940
- if p < 0.5
941
- pcase = true
942
- porq = p
943
- s = - 1
944
- else
945
- pcase = false
946
- porq = q
947
- s = 1
948
- end
939
+ pcase = p < 0.5
940
+ minpq = pcase ? p : q
941
+
942
+ return __gamma_inc_inv (a, minpq, pcase)
943
+ end
944
+
945
+ function __gamma_inc_inv (a:: Float64 , minpq:: Float64 , pcase:: Bool )
949
946
haseta = false
950
947
951
- logr = (1.0 / a)* (log (p) + logabsgamma (a + 1.0 )[1 ])
948
+ logp = pcase ? log (minpq) : log1p (- minpq)
949
+ logr = (1.0 / a)* (logp + logabsgamma (a + 1.0 )[1 ])
952
950
if logr < log (0.2 * (1 + a)) # small value of p
953
- x0 = gamma_inc_inv_psmall (a, p )
954
- elseif ((q < min (0.02 , exp (- 1.5 * a)/ gamma (a))) && ( a < 10 )) # small q
955
- x0 = gamma_inc_inv_qsmall (a, q )
956
- elseif abs (porq - 0.5 ) < 1.0e-05
951
+ x0 = gamma_inc_inv_psmall (a, logr )
952
+ elseif ! pcase && minpq < min (0.02 , exp (- 1.5 * a)/ gamma (a)) && a < 10 # small q
953
+ x0 = gamma_inc_inv_qsmall (a, minpq )
954
+ elseif abs (minpq - 0.5 ) < 1.0e-05
957
955
x0 = a - 1.0 / 3.0 + (8.0 / 405.0 + 184.0 / 25515.0 / a)/ a
958
956
elseif abs (a - 1.0 ) < 1.0e-4
959
- x0 = pcase ? - log1p (- p ) : - log (q )
957
+ x0 = pcase ? - log1p (- minpq ) : - log (minpq )
960
958
elseif a < 1.0 # small value of a
961
- x0 = gamma_inc_inv_asmall (a, p, q , pcase)
959
+ x0 = gamma_inc_inv_asmall (a, minpq , pcase)
962
960
else # large a
963
961
haseta = true
964
- x0, fp = gamma_inc_inv_alarge (a, porq, s )
962
+ x0, fp = gamma_inc_inv_alarge (a, minpq, pcase )
965
963
end
966
964
967
965
t = 1
@@ -985,7 +983,7 @@ function _gamma_inc_inv(a::Float64, p::Float64, q::Float64)
985
983
986
984
px, qx = gamma_inc (a, x, 0 )
987
985
988
- ck1 = pcase ? - r* (px - p ) : r* (qx - q )
986
+ ck1 = pcase ? - r* (px - minpq ) : r* (qx - minpq )
989
987
if a > 0.05
990
988
ck2 = (x - a + 1.0 )/ (2.0 * x)
991
989
@@ -1018,16 +1016,8 @@ function _gamma_inc_inv(a::Float64, p::Float64, q::Float64)
1018
1016
return x
1019
1017
end
1020
1018
1021
- function _gamma_inc_inv (a:: T , p:: T , q:: T ) where {T <: Union{Float16, Float32} }
1022
- if p + q != one (T)
1023
- throw (ArgumentError (" p + q must equal one but was $(p + q) " ))
1024
- end
1025
- p64, q64 = if p < q
1026
- (Float64 (p), 1 - Float64 (p))
1027
- else
1028
- (1 - Float64 (q), Float64 (q))
1029
- end
1030
- return T (_gamma_inc_inv (Float64 (a), p64, q64))
1019
+ function __gamma_inc_inv (a:: T , minpq:: T , pcase:: Bool ) where {T<: Union{Float16,Float32} }
1020
+ return T (__gamma_inc_inv (Float64 (a), Float64 (minpq), pcase))
1031
1021
end
1032
1022
1033
1023
# like promote(x,y), but don't complexify real values
0 commit comments