Generalized hypergeometric functions#

Generalized hypergeometric function \({}_pF_q\)#

ctx.hyperg_pfq(a_s, b_s, z)#

where ctx is dec, mpm, fpm, gmp or apm.

Returns the generalized hypergeometric function pFq(a; b, c; z).

See also MathWorld [1121], MathWorld [298], Mpmath [780], Wikipedia [1494], NIST [27].

Evaluates the generalized hypergeometric function

\[\,_pF_q(a_1,\ldots,a_p; b_1,\ldots,b_q; z) = \sum_{n=0}^\infty \frac{(a_1)_n (a_2)_n \ldots (a_p)_n} {(b_1)_n(b_2)_n\ldots(b_q)_n} \frac{z^n}{n!}\]

where \((x)_n\) denotes the rising factorial (see rf()).

The parameters lists a_s and b_s may contain integers, real numbers, complex numbers, as well as exact fractions given in the form of tuples \((p, q)\). The function is optimized to handle integers and fractions more efficiently than arbitrary floating-point parameters (since rational parameters are by far the most common).

Examples

The parameters can be any combination of integers, fractions, floats and complex numbers:

>>> a, b, c, d, e = 1, (-1,2), pi, 3+4j, (2,3)
>>> x = 0.2j
>>> hyper([a,b],[c,d,e],x)
(0.9923571616434024810831887 - 0.005753848733883879742993122j)
>>> b, e = -0.5, mpf(2)/3
>>> fn = lambda n: rf(a,n)*rf(b,n)/rf(c,n)/rf(d,n)/rf(e,n)*x**n/fac(n)
>>> nsum(fn, [0, inf])
(0.9923571616434024810831887 - 0.005753848733883879742993122j)

The \(\,_0F_0\) and \(\,_1F_0\) series are just elementary functions:

>>> a, z = sqrt(2), +pi
>>> hyper([],[],z)
23.14069263277926900572909
>>> exp(z)
23.14069263277926900572909
>>> hyper([a],[],z)
(-0.09069132879922920160334114 + 0.3283224323946162083579656j)
>>> (1-z)**(-a)
(-0.09069132879922920160334114 + 0.3283224323946162083579656j)

If any \(a_k\) coefficient is a nonpositive integer, the series terminates into a finite polynomial:

>>> hyper([1,1,1,-3],[2,5],1)
0.7904761904761904761904762
>>> identify(_)
'(83/105)'

If any \(b_k\) is a nonpositive integer, the function is undefined (unless the series terminates before the division by zero occurs):

>>> hyper([1,1,1,-3],[-2,5],1)
Traceback (most recent call last):
  ...
ZeroDivisionError: pole in hypergeometric series
>>> hyper([1,1,1,-1],[-2,5],1)
1.1

Except for polynomial cases, the radius of convergence \(R\) of the hypergeometric series is either \(R = \infty\) (if \(p \le q\)), \(R = 1\) (if \(p = q+1\)), or \(R = 0\) (if \(p > q+1\)).

The analytic continuations of the functions with \(p = q+1\), i.e. \(\,_2F_1\), \(\,_3F_2\), \(\,_4F_3\), etc, are all implemented and therefore these functions can be evaluated for \(|z| \ge 1\). The shortcuts hyp2f1(), hyp3f2() are available to handle the most common cases (see their documentation), but functions of higher degree are also supported:

>>> hyper([1,2,3,4], [5,6,7], 1)   # 4F3 at finite-valued branch point
1.141783505526870731311423
>>> hyper([4,5,6,7], [1,2,3], 1)   # 4F3 at pole
+inf
>>> hyper([1,2,3,4,5], [6,7,8,9], 10)    # 5F4
(1.543998916527972259717257 - 0.5876309929580408028816365j)
>>> hyper([1,2,3,4,5,6], [7,8,9,10,11], 1j)   # 6F5
(0.9996565821853579063502466 + 0.0129721075905630604445669j)

Near \(z = 1\) with noninteger parameters:

>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','41/8'], 1)
2.219433352235586121250027
>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], 1)
+inf
>>> eps1 = extradps(6)(lambda: 1 - mpf('1e-6'))()
>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], eps1)
2923978034.412973409330956

Please note that, as currently implemented, evaluation of \(\,_pF_{p-1}\) with \(p \ge 3\) may be slow or inaccurate when \(|z-1|\) is small, for some parameter values.

Evaluation may be aborted if convergence appears to be too slow. The optional maxterms (limiting the number of series terms) and maxprec (limiting the internal precision) keyword arguments can be used to control evaluation:

>>> hyper([1,2,3], [4,5,6], 10000)
Traceback (most recent call last):
  ...
NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms.
>>> hyper([1,2,3], [4,5,6], 10000, maxterms=10**6)
7.622806053177969474396918e+4310

Additional options include force_series (which forces direct use of a hypergeometric series even if another evaluation function might work better) and asytol which controls the target tolerance for using asymptotic series.

When \(p > q+1\), hyper computes the (iterated) Borel sum of the divergent series. For \(\,_2F_0\) the Borel sum has an analytic solution and can be computed efficiently (see hyp2f0()). For higher degrees, the functions is evaluated first by attempting to sum it directly as an asymptotic series (this only works for tiny \(|z|\)), and then by evaluating the Borel regularized sum using numerical integration. Except for special parameter combinations, this can be extremely slow.

>>> hyper([1,1], [], 0.5)          # regularization of 2F0
(1.340965419580146562086448 + 0.8503366631752726568782447j)
>>> hyper([1,1,1,1], [1], 0.5)     # regularization of 4F1
(1.108287213689475145830699 + 0.5327107430640678181200491j)

With the following magnitude of argument, the asymptotic series for \(\,_3F_1\) gives only a few digits. Using Borel summation, hyper can produce a value with full accuracy:

>>> mp.dps = 15
>>> hyper([2,0.5,4], [5.25], '0.08', force_series=True)
Traceback (most recent call last):
  ...
NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms.
>>> hyper([2,0.5,4], [5.25], '0.08', asytol=1e-4)
1.0725535790737
>>> hyper([2,0.5,4], [5.25], '0.08')
(1.07269542893559 + 5.54668863216891e-5j)
>>> hyper([2,0.5,4], [5.25], '-0.08', asytol=1e-4)
0.946344925484879
>>> hyper([2,0.5,4], [5.25], '-0.08')
0.946312503737771
>>> mp.dps = 25
>>> hyper([2,0.5,4], [5.25], '-0.08')
0.9463125037377662296700858

Note that with the positive \(z\) value, there is a complex part in the correct result, which falls below the tolerance of the asymptotic series.

By default, a parameter that appears in both a_s and b_s will be removed unless it is a nonpositive integer. This generally speeds up evaluation by producing a hypergeometric function of lower order. This optimization can be disabled by passing eliminate=False.

>>> hyper([1,2,3], [4,5,3], 10000)
1.268943190440206905892212e+4321
>>> hyper([1,2,3], [4,5,3], 10000, eliminate=False)
Traceback (most recent call last):
  ...
NoConvergence: Hypergeometric series converges too slowly. Try increasing maxterms.
>>> hyper([1,2,3], [4,5,3], 10000, eliminate=False, maxterms=10**6)
1.268943190440206905892212e+4321

If a nonpositive integer \(-n\) appears in both a_s and b_s, this parameter cannot be unambiguously removed since it creates a term 0 / 0. In this case the hypergeometric series is understood to terminate before the division by zero occurs. This convention is consistent with Mathematica. An alternative convention of eliminating the parameters can be toggled with eliminate_all=True:

>>> hyper([2,-1], [-1], 3)
7.0
>>> hyper([2,-1], [-1], 3, eliminate_all=True)
0.25
>>> hyper([2], [], 3)
0.25

Generalized hypergeometric function \({}_2F_3\)#

ctx.hyperg_2f3(a1, a2, b1, b2, b3, z)#

where ctx is dec, mpm, fpm, gmp or apm.

Returns the generalized hypergeometric function 2F3().

See also MathWorld [1119], MathWorld [296], Mpmath [778], Wikipedia [1494], NIST [27].

Gives the hypergeometric function \(\,_2F_3(a_1,a_2;b_1,b_2,b_3; z)\). The call hyp2f3(a1,a2,b1,b2,b3,z) is equivalent to hyper([a1,a2],[b1,b2,b3],z).

Evaluation works for arbitrarily large arguments:

>>> from mpfunlab import *
>>> mp.dps = 25; mp.pretty = True
>>> a1,a2,b1,b2,b3 = 1.5, (-1,3), 2.25, 4, (1,5)
>>> hyp2f3(a1,a2,b1,b2,b3,10**20)
-4.169178177065714963568963e+8685889590
>>> hyp2f3(a1,a2,b1,b2,b3,-10**20)
7064472.587757755088178629
>>> hyp2f3(a1,a2,b1,b2,b3,10**20*j)
(-5.163368465314934589818543e+6141851415 + 1.783578125755972803440364e+6141851416j)
>>> hyp2f3(2+3j, -2j, 0.5j, 4j, -1-j, 10-20j)
(-2280.938956687033150740228 + 13620.97336609573659199632j)
>>> hyp2f3(2+3j, -2j, 0.5j, 4j, -1-j, 10000000-20000000j)
(4.849835186175096516193e+3504 - 3.365981529122220091353633e+3504j)

Generalized hypergeometric function \({}_3F_2\)#

ctx.hyperg_3f2(a1, a2, a3, b1, b2, z)#

where ctx is dec, mpm, fpm, gmp or apm.

Returns the generalized hypergeometric function 3F2().

See also MathWorld [1120], MathWorld [297], Mpmath [779], Wikipedia [1494], NIST [27].

The function is defined for \(|z| < 1\) as

\[\,_3F_2(a_1,a_2,a_3,b_1,b_2,z) = \sum_{k=0}^{\infty} \frac{(a_1)_k (a_2)_k (a_3)_k}{(b_1)_k (b_2)_k} \frac{z^k}{k!}.\]

and for \(|z| \ge 1\) by analytic continuation. The analytic structure of this function is similar to that of \(\,_2F_1\), generally with a singularity at \(z = 1\) and a branch cut on \((1, \infty)\).

Evaluation is supported inside, on, and outside the circle of convergence \(|z| = 1\):

>>> from mpfunlab import *
>>> mp.dps = 25; mp.pretty = True
>>> hyp3f2(1,2,3,4,5,0.25)
1.083533123380934241548707
>>> hyp3f2(1,2+2j,3,4,5,-10+10j)
(0.1574651066006004632914361 - 0.03194209021885226400892963j)
>>> hyp3f2(1,2,3,4,5,-10)
0.3071141169208772603266489
>>> hyp3f2(1,2,3,4,5,10)
(-0.4857045320523947050581423 - 0.5988311440454888436888028j)
>>> hyp3f2(0.25,1,1,2,1.5,1)
1.157370995096772047567631
>>> (8-pi-2*ln2)/3
1.157370995096772047567631
>>> hyp3f2(1+j,0.5j,2,1,-2j,-1)
(1.74518490615029486475959 + 0.1454701525056682297614029j)
>>> hyp3f2(1+j,0.5j,2,1,-2j,sqrt(j))
(0.9829816481834277511138055 - 0.4059040020276937085081127j)
>>> hyp3f2(-3,2,1,-5,4,1)
1.41
>>> hyp3f2(-3,2,1,-5,4,2)
2.12

Evaluation very close to the unit circle:

>>> hyp3f2(1,2,3,4,5,'1.0001')
(1.564877796743282766872279 - 3.76821518787438186031973e-11j)
>>> hyp3f2(1,2,3,4,5,'1+0.0001j')
(1.564747153061671573212831 + 0.0001305757570366084557648482j)
>>> hyp3f2(1,2,3,4,5,'0.9999')
1.564616644881686134983664
>>> hyp3f2(1,2,3,4,5,'-0.9999')
0.7823896253461678060196207

Note

Evaluation for \(|z-1|\) small can currently be inaccurate or slow for some parameter combinations.

For various parameter combinations, \(\,_3F_2\) admits representation in terms of hypergeometric functions of lower degree, or in terms of simpler functions:

>>> for a, b, z in [(1,2,-1), (2,0.5,1)]:
...     hyp2f1(a,b,a+b+0.5,z)**2
...     hyp3f2(2*a,a+b,2*b,a+b+0.5,2*a+2*b,z)
...
0.4246104461966439006086308
0.4246104461966439006086308
7.111111111111111111111111
7.111111111111111111111111

>>> z = 2+3j
>>> hyp3f2(0.5,1,1.5,2,2,z)
(0.7621440939243342419729144 + 0.4249117735058037649915723j)
>>> 4*(pi-2*ellipe(z))/(pi*z)
(0.7621440939243342419729144 + 0.4249117735058037649915723j)

Generalized hypergeometric function \({}_2F_2\)#

ctx.hyperg_2f2(a1, a2, b1, b2, z)#

where ctx is dec, mpm, fpm, gmp or apm.

Returns the generalized hypergeometric function 2F2(a; b, c; z).

See also MathWorld [1118], MathWorld [295], Mpmath [777], Wikipedia [1494], NIST [27].

Gives the hypergeometric function \(\,_2F_2(a_1,a_2;b_1,b_2; z)\). The call hyp2f2(a1,a2,b1,b2,z) is equivalent to hyper([a1,a2],[b1,b2],z).

Evaluation works for complex and arbitrarily large arguments:

>>> from mpfunlab import *
>>> mp.dps = 25; mp.pretty = True
>>> a, b, c, d = 1.5, (-1,3), 2.25, 4
>>> hyp2f2(a, b, c, d, 10**20)
-5.275758229007902299823821e+43429448190325182663
>>> hyp2f2(a, b, c, d, -10**20)
2561445.079983207701073448
>>> hyp2f2(a, b, c, d, 10**20*j)
(2218276.509664121194836667 - 1280722.539991603850462856j)
>>> hyp2f2(2+3j, -2j, 0.5j, 4j, 10-20j)
(80500.68321405666957342788 - 20346.82752982813540993502j)

Generalized hypergeometric function \(\,_2F_0\)#

ctx.hyperg_2f0(a, b, z)#

where ctx is dec, mpm, fpm, gmp or apm.

Returns the generalized hypergeometric function 2F0(a, b; z). See also Wikipedia [1411], MathWorld [1031], NIST [21], BoostMath [162], Mpmath [688].