JuliaMath / HypergeometricFunctions.jl

A Julia package for calculating hypergeometric functions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Poor numerical stability for large x

the-noble-argon opened this issue · comments

I've been trying to use this package for evaluating some probability density functions. However, I keep running into stability issues with large values of x. For example, when calculating 1F1(8.9,0.5,x) which is a typical occurrence, I would see something like this if I plotted the two functions offered by this package and compared it to GSL.jl. The Drummond method starts faltering at about 12, while pFq starts giving out at 17. Meanwhile GSL won't start giving out until about 700 which is far beyond what I need for most density function evaluations (I'd be happy at about 300, because at that point, I could use asymptotic relationships).

Hypergeometrics
l

Hi @the-noble-argon, thanks for reporting this issue. The rational approximation methods (pFqdrummond and pFqweniger) are meant for general-purpose analytic continuation. Will they fail sooner than a method that uses asymptotic information? Sure! Are they pretty good for general parameter vectors alpha and beta? Arguably better than Taylor series. To be sure, you can always blast it with more precision.

For example, if we allow ourselves to use this asymptotic formula for 1F1 (https://functions.wolfram.com/HypergeometricFunctions/Hypergeometric1F1/06/02/0005/) then we get equivalent results to GSL. Do we know what extra information GSL is using?

julia> gamma(b)/gamma(b-a)*(-z+0.0im)^(-a)*HypergeometricFunctions.pFqweniger([a, a-b+1], Float64[], -inv(z)) + gamma(b)/gamma(a)*exp(z)*z^(a-b)*HypergeometricFunctions.pFqweniger([b-a, 1-a], Float64[], inv(z))
1.019761119013075e42 + 2.0851791216892105e-13im

julia> pFq([big"8.9"], [big"0.5"], big"70.0")
1.0197611190130736062331038605237850040299542640718586092065478670951388292065e+42

Implementing all known transformation formulas is quite a big deal.

For pFq's that are entire, the Maclaurin series works well in the right-half plane, but not the left:

julia> HypergeometricFunctions.pFqmaclaurin([8.9], [0.5], 70.0)
1.0197611190130733e42

julia> pFq([big"8.9"], [big"0.5"], big"70.0")
1.0197611190130736062331038605237850040299542640718586092065478670951388292065e+42

julia> HypergeometricFunctions.pFqmaclaurin([8.9], [0.5], -70.0)
3.1189144044908764e24

julia> pFq([big"8.9"], [big"0.5"], big"-70.0")
-8.036868482005555378465040729238108540137167249027470698216173807370577234385018e-12

Rational approximations for pFq's that are entire run into a stability issue when evaluating for large (and generally positive real part) z because even if the poles scatter to infinity as one increases the type (degree, degree), the evaluation point may be close to a pole of a rational approximant of a specific type.

Maybe the real issue here is to case out 1F1, as pointed out in #32.

I don't know if this issue is formally closable, but _₁F₁(a, b, z) and HypergeometricFunctions.M(a, b, z) are added and special cased in pFq. This is for version 0.3.7 which will be tagged soon.

Excellent, this works perfectly! They give out at the exact same point, which is well beyond the point where I can apply the appropriate asymptotic expression myself (in logarithmic format). Thank you so much!