@@ -712,19 +712,24 @@ end
712
712
# Wikipedia : https://en.wikipedia.org/wiki/Beta_function#Incomplete_beta_function
713
713
714
714
"""
715
- beta_inc(a, b, x[ , y] )
715
+ beta_inc(a, b, x, y=1-x )
716
716
717
- Returns a tuple ``(I_{x}(a,b),1.0-I_{x}(a,b))`` where the Regularized Incomplete Beta Function is given by:
717
+ Return a tuple ``(I_{x}(a,b), 1-I_{x}(a,b))`` where ``I_{x}(a,b)`` is the regularized
718
+ incomplete beta function given by
718
719
```math
719
720
I_{x}(a,b) = \\ frac{1}{B(a,b)} \\ int_{0}^{x} t^{a-1}(1-t)^{b-1} dt,
720
721
```
721
722
where ``B(a,b) = \\ Gamma(a)\\ Gamma(b)/\\ Gamma(a+b)``.
722
723
723
724
External links: [DLMF](https://dlmf.nist.gov/8.17.1), [Wikipedia](https://en.wikipedia.org/wiki/Beta_function#Incomplete_beta_function)
724
725
725
- See also: [`beta_inc_inv(a, b, p, q) `](@ref SpecialFunctions.beta_inc_inv )
726
+ See also: [`beta_inc_inv`](@ref)
726
727
"""
727
- function beta_inc (a:: Float64 , b:: Float64 , x:: Float64 , y:: Float64 )
728
+ function beta_inc (a:: Real , b:: Real , x:: Real , y:: Real = 1 - x)
729
+ return _beta_inc (map (float, promote (a, b, x, y))... )
730
+ end
731
+
732
+ function _beta_inc (a:: Float64 , b:: Float64 , x:: Float64 , y:: Float64 )
728
733
p = 0.0
729
734
q = 0.0
730
735
# lambda = a - (a+b)*x
@@ -878,69 +883,63 @@ function beta_inc(a::Float64, b::Float64, x::Float64, y::Float64)
878
883
return ind ? (q, p) : (p, q)
879
884
end
880
885
881
- beta_inc (a:: Real , b:: Real , x:: Real ) = beta_inc (a, b, x, 1 - x)
882
- function beta_inc (a :: T , b :: T , x :: T , y :: T ) where {T <: Union{Float16, Float32} }
883
- T .( beta_inc ( Float64 (a ), Float64 (b), Float64 (x), Float64 (y)) )
886
+ function _beta_inc (a:: T , b:: T , x:: T , y :: T ) where {T <: Union{Float16, Float32} }
887
+ p, q = _beta_inc ( Float64 (a), Float64 (b), Float64 (x), Float64 (y))
888
+ T (p ), T (q )
884
889
end
885
- beta_inc (a:: Real , b:: Real , x:: Real , y:: Real ) = beta_inc (promote (float (a), float (b), float (x), float (y))... )
886
- beta_inc (a:: T , b:: T , x:: T , y:: T ) where {T<: AbstractFloat } = throw (MethodError (beta_inc,(a, b, x, y," " )))
890
+
887
891
888
892
# GW Cran, KJ Martin, GE Thomas, Remark AS R19 and Algorithm AS 109: A Remark on Algorithms AS 63: The Incomplete Beta Integral and AS 64: Inverse of the Incomplete Beta Integeral,
889
893
# Applied Statistics,
890
894
# Volume 26, Number 1, 1977, pages 111-114.
891
895
892
896
"""
893
- beta_inc_inv(a, b, p, q, lb=logbeta(a,b)[1] )
897
+ beta_inc_inv(a, b, p, q=1-p )
894
898
895
- Computes inverse of incomplete beta function. Given `a`,`b` and ``I_{x}(a,b) = p`` find `x` and return tuple `(x,y)`.
899
+ Return a tuple `(x, 1-x)` where `x` satisfies ``I_{x}(a, b) = p``, i.e., `x` is the inverse
900
+ of the regularized incomplete beta function ``I_{x}(a, b)``.
896
901
897
- See also: [`beta_inc(a,b,x) `](@ref SpecialFunctions.beta_inc )
902
+ See also: [`beta_inc`](@ref)
898
903
"""
899
- function beta_inc_inv (a:: Float64 , b:: Float64 , p:: Float64 , q:: Float64 ; lb = logbeta (a,b)[1 ])
900
- fpu = 1e-30
901
- x = p
902
- if p == 0.0
903
- return (0.0 , 1.0 )
904
- elseif p == 1.0
905
- return (1.0 , 0.0 )
906
- end
904
+ function beta_inc_inv (a:: Real , b:: Real , p:: Real , q:: Real = 1 - p)
905
+ return _beta_inc_inv (map (float, promote (a, b, p, q))... )
906
+ end
907
907
908
+ function _beta_inc_inv (a:: Float64 , b:: Float64 , p:: Float64 , q:: Float64 )
908
909
# change tail if necessary
909
-
910
910
if p > 0.5
911
- pp = q
912
- aa = b
913
- bb = a
914
- indx = true
915
- else
916
- pp = p
917
- aa = a
918
- bb = b
919
- indx = false
911
+ y, x = _beta_inc_inv (b, a, q, p)
912
+ return x, y
920
913
end
921
914
922
- # Initial approx
915
+ if p == 0.0
916
+ return (0.0 , 1.0 )
917
+ end
923
918
924
- r = sqrt (- 2 * log (pp))
925
- pp_approx = r - @horner (r, 2.30753e+00 , 0.27061e+00 ) / @horner (r, 1.0 , .99229e+00 , .04481e+00 )
919
+ # Initial approx
920
+ x = p
921
+ r = sqrt (- 2 * log (p))
922
+ p_approx = r - @horner (r, 2.30753e+00 , 0.27061e+00 ) / @horner (r, 1.0 , .99229e+00 , .04481e+00 )
923
+ fpu = 1e-30
924
+ lb = logbeta (a, b)
926
925
927
926
if a > 1.0 && b > 1.0
928
- r = (pp_approx ^ 2 - 3.0 )/ 6.0
929
- s = 1.0 / (2 * aa - 1.0 )
930
- t = 1.0 / (2 * bb - 1.0 )
927
+ r = (p_approx ^ 2 - 3.0 )/ 6.0
928
+ s = 1.0 / (2 * a - 1.0 )
929
+ t = 1.0 / (2 * b - 1.0 )
931
930
h = 2.0 / (s + t)
932
- w = pp_approx * sqrt (h + r)/ h - (t - s)* (r + 5.0 / 6.0 - 2.0 / (3.0 * h))
933
- x = aa / (aa + bb * exp (w + w))
931
+ w = p_approx * sqrt (h + r)/ h - (t - s)* (r + 5.0 / 6.0 - 2.0 / (3.0 * h))
932
+ x = a / (a + b * exp (w + w))
934
933
else
935
- r = 2.0 * bb
936
- t = 1.0 / (9.0 * bb )
937
- t = r* (1.0 - t + pp_approx * sqrt (t))^ 3
934
+ r = 2.0 * b
935
+ t = 1.0 / (9.0 * b )
936
+ t = r* (1.0 - t + p_approx * sqrt (t))^ 3
938
937
if t <= 0.0
939
- x = - expm1 ((log ((1.0 - pp) * bb ) + lb)/ bb )
938
+ x = - expm1 ((log ((1.0 - p) * b ) + lb)/ b )
940
939
else
941
- t = (4.0 * aa + r - 2.0 )/ t
940
+ t = (4.0 * a + r - 2.0 )/ t
942
941
if t <= 1.0
943
- x = exp ((log (pp * aa ) + lb)/ aa )
942
+ x = exp ((log (p * a ) + lb)/ a )
944
943
else
945
944
x = 1.0 - 2.0 / (t + 1.0 )
946
945
end
@@ -949,9 +948,9 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
949
948
950
949
# solve x using modified newton-raphson iteration
951
950
952
- r = 1.0 - aa
953
- t = 1.0 - bb
954
- pp_approx_prev = 0.0
951
+ r = 1.0 - a
952
+ t = 1.0 - b
953
+ p_approx_prev = 0.0
955
954
sq = 1.0
956
955
prev = 1.0
957
956
@@ -962,23 +961,23 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
962
961
x = .9999
963
962
end
964
963
965
- iex = max (- 5.0 / aa ^ 2 - 1.0 / pp ^ 0.2 - 13.0 , - 30.0 )
964
+ iex = max (- 5.0 / a ^ 2 - 1.0 / p ^ 0.2 - 13.0 , - 30.0 )
966
965
acu = 10.0 ^ iex
967
966
968
967
# iterate
969
968
while true
970
- pp_approx = beta_inc (aa, bb , x)[1 ]
969
+ p_approx = beta_inc (a, b , x)[1 ]
971
970
xin = x
972
- pp_approx = (pp_approx - pp )* min (floatmax (), exp (lb + r* log (xin) + t* log1p (- xin)))
971
+ p_approx = (p_approx - p )* min (floatmax (), exp (lb + r* log (xin) + t* log1p (- xin)))
973
972
974
- if pp_approx * pp_approx_prev <= 0.0
973
+ if p_approx * p_approx_prev <= 0.0
975
974
prev = max (sq, fpu)
976
975
end
977
976
g = 1.0
978
977
979
- tx = x - g* pp_approx
978
+ tx = x - g* p_approx
980
979
while true
981
- adj = g* pp_approx
980
+ adj = g* p_approx
982
981
sq = adj^ 2
983
982
tx = x - adj
984
983
if (prev > sq && tx >= 0.0 && tx <= 1.0 )
@@ -989,18 +988,22 @@ function beta_inc_inv(a::Float64, b::Float64, p::Float64, q::Float64; lb = logbe
989
988
990
989
# check if current estimate is acceptable
991
990
992
- if prev <= acu || pp_approx ^ 2 <= acu
991
+ if prev <= acu || p_approx ^ 2 <= acu
993
992
x = tx
994
- return indx ? ( 1.0 - x, x) : (x, 1.0 - x)
993
+ return (x, 1.0 - x)
995
994
end
996
995
997
996
if tx == x
998
- return indx ? ( 1.0 - x, x) : (x, 1.0 - x)
997
+ return (x, 1.0 - x)
999
998
end
1000
999
1001
1000
x = tx
1002
- pp_approx_prev = pp_approx
1001
+ p_approx_prev = p_approx
1003
1002
end
1004
1003
end
1005
1004
1006
- beta_inc_inv (a:: Float64 , b:: Float64 , p:: Float64 ) = beta_inc_inv (a, b, p, 1.0 - p)
1005
+ function _beta_inc_inv (a:: T , b:: T , p:: T , q:: T ) where {T<: Union{Float16, Float32} }
1006
+ x, y = _beta_inc_inv (Float64 (a), Float64 (b), Float64 (p), Float64 (q))
1007
+ T (x), T (y)
1008
+ end
1009
+
0 commit comments