• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section:hypergeometric Hypergeometric Functions]
2
3[section:hypergeometric_1f0 Hypergeometric [sub 1]/F/[sub 0] ]
4
5   #include <boost/math/special_functions/hypergeometric_1F0.hpp>
6
7   namespace boost { namespace math {
8
9   template <class T1, class T2>
10   ``__sf_result`` hypergeometric_1F0(T1 a, T2 z);
11
12   template <class T1, class T2, class ``__Policy``>
13   ``__sf_result`` hypergeometric_1F0(T1 a, T2 z, const ``__Policy``&);
14
15   }} // namespaces
16
17[h4 Description]
18
19The function `hypergeometric_1F0` returns the result of:
20
21[equation hyper_1f0]
22
23The return type of these functions is computed using the __arg_promotion_rules
24when `T1` and `T2` are different types.
25
26[optional_policy]
27
28The functions return the result of __domain_error whenever the result is
29undefined or complex.  This occurs for `z == 1` or `1 - z < 0` and `a` not an integer.
30
31[h4 Implementation]
32
33The implementation is trivial:
34
35[expression ['[sub 1]F[sub 0](a, z) = (1-z)[super -a]]]
36
37[endsect] [/section:hyper_geometric_1f0 Hypergeometric [sub 1]/F/[sub 0] ]
38
39[section:hypergeometric_0f1 Hypergeometric [sub 0]/F/[sub 1] ]
40
41   #include <boost/math/special_functions/hypergeometric_0F1.hpp>
42
43   namespace boost { namespace math {
44
45   template <class T1, class T2>
46   ``__sf_result`` hypergeometric_0F1(T1 b, T2 z);
47
48   template <class T1, class T2, class ``__Policy``>
49   ``__sf_result`` hypergeometric_0F1(T1 b, T2 z, const ``__Policy``&);
50
51   }} // namespaces
52
53[h4 Description]
54
55The function `hypergeometric_0F1` returns the result of
56
57[equation hyper_0f1]
58
59The return type of these functions is computed using the __arg_promotion_rules
60when `T1` and `T2` are different types.
61
62[optional_policy]
63
64The functions return the result of __domain_error whenever the result is
65undefined or complex.
66This occurs only when `b` is an integer <= 0.
67
68[h4 Implementation]
69
70The function is implemented via its defining series wherever convergent.
71
72For a divergent series we use the continued fraction as long as the result is not too small:
73
74[equation hyper_0f1_cf]
75
76and one of the Bessel function relations otherwise:
77
78[equation hyper_0f1_bessel_j]
79
80[equation hyper_0f1_bessel_i]
81
82[endsect] [/section:hypergeometric_0f1 Hypergeometric [sub 0]/F/[sub 1] ]
83
84[section:hypergeometric_2f0 Hypergeometric [sub 2]/F/[sub 0]]
85
86   #include <boost/math/special_functions/hypergeometric_2F0.hpp>
87
88   namespace boost { namespace math {
89
90   template <class T1, class T2, class T3>
91   ``__sf_result`` hypergeometric_2F0(T1 a1, T2 a2, T3 z);
92
93   template <class T1, class T2, class T3, class ``__Policy``>
94   ``__sf_result`` hypergeometric_2F0(T1 a1, T2 a2, T3 z, const ``__Policy``&);
95
96   }}
97
98[h4 Description]
99
100The function `hypergeometric_2F0` returns the result of
101
102[equation hyper_2f0]
103
104The return type of these functions is computed using the __arg_promotion_rules
105when `T1` and `T2` are different types.
106
107[optional_policy]
108
109The functions return the result of __domain_error whenever the result is
110undefined or complex.  The valid domain for this function occurs only when one of `a1` or
111`a2` is a negative integer: ie the polynomial case.
112
113[h4 Implementation]
114
115When `a1 == a2 - 0.5` then the function is implemented in terms of the Hermite polynomial:
116
117[equation hyper_2f0_hermite]
118
119When both `a1` and `a2` are integers then the function is implemented in terms of the associated-Laguerre polynomial:
120
121[equation hyper_2f0_laguerre]
122
123If the defining series is divergent, we use the continued fraction
124
125[equation hyper_2f0_cf]
126
127Otherwise we use the defining series.
128
129[endsect] [/section:hyper_geometric_1f0 Hypergeometric [sub 2]/F/[sub 0]]
130
131[section:hypergeometric_1f1 Hypergeometric [sub 1]/F/[sub 1]]
132
133
134   #include <boost/math/special_functions/hypergeometric_1F1.hpp>
135
136   namespace boost { namespace math {
137
138   template <class T1, class T2, class T3>
139   ``__sf_result`` hypergeometric_1F1(T1 a, T2 b, T3 z);
140
141   template <class T1, class T2, class T3, class ``__Policy``>
142   ``__sf_result`` hypergeometric_1F1(T1 a, T2 b, T3 z, const ``__Policy``&);
143
144   template <class T1, class T2, class T3>
145   ``__sf_result`` hypergeometric_1F1_regularized(T1 a, T2 b, T3 z);
146
147   template <class T1, class T2, class T3, class ``__Policy``>
148   ``__sf_result`` hypergeometric_1F1_regularized(T1 a, T2 b, T3 z, const ``__Policy``&);
149
150   template <class T1, class T2, class T3>
151   ``__sf_result`` log_hypergeometric_1F1(T1 a, T2 b, T3 z);
152
153   template <class T1, class T2, class T3, class ``__Policy``>
154   ``__sf_result`` log_hypergeometric_1F1(T1 a, T2 b, T3 z, const ``__Policy``&);
155
156   template <class T1, class T2, class T3>
157   ``__sf_result`` log_hypergeometric_1F1(T1 a, T2 b, T3 z, int* sign);
158
159   template <class T1, class T2, class T3, class ``__Policy``>
160   ``__sf_result`` log_hypergeometric_1F1(T1 a, T2 b, T3 z, int* sign, const ``__Policy``&);
161
162   }} // namespaces
163
164[h4 Description]
165
166[? __build_html '''<?dbhtml-include href="'''__base_path__'''/graphs/hypergeometric_1f1/script_include.html"?>''']
167
168The function `hypergeometric_1F1(a, b, z)` returns the non-singular solution to
169[@https://en.wikipedia.org/wiki/Confluent_hypergeometric_function Kummer's equation]
170
171[:[/\large $$z \frac{d^2 w}{d z^2} + (b-z) \frac{dw}{dz} - aw = 0 $$]
172[$../equations/hypergeometric_1f1_2.svg]]
173
174which for |/z/| < 1 has the hypergeometric series expansion
175
176[:[$../equations/hypergeometric_1f1_1.svg]]
177
178where (/a/)[sub /n/] denotes rising factorial.
179This function has the same definition as Mathematica's `Hypergeometric1F1[a, b, z]` and Maple's `KummerM(a, b, z)`.
180
181The "regularized" versions of the function return:
182
183[:[/ \Large  $$ \textbf{M}(a, b; z) = \frac{{_1F_1}(a, b; z)}{\Gamma(b)} = \sum_{n=0}^{\infty} \frac{(a)_n z^n}{\Gamma(b+n) n!} $$]
184[$../equations/hypergeometric_1f1_17.svg]]
185
186The "log" versions of the function return:
187
188[:[/ \Large  $$ \ln(|_1F_1(a, b, z)|) $$ ]
189[$../equations/hypergeometric_1f1_18.svg]]
190
191When the optional `sign` argument is supplied it is set on exit to either +1 or -1 depending on the sign of [sub 1]/F/[sub 1](/a/, /b/, /z/).
192
193Both the regularized and the logarithmic versions of these functions return results without the spurious
194under/overflow that plague naive implementations.
195
196[h4 Known Issues]
197
198This function is still very much the subject of active research,
199and a full range of methods capable of calculating the function
200over its entire domain are not yet available.
201We have worked extremely hard to ensure that problem domains result in an exception being thrown
202(an __evaluation_error) rather than return a garbage result.
203Domains that are still unsolved include:
204
205[table
206[[domain][comment][example]]
207[[ [/\large  $$_1F_1(-a, -b; -z)$$] [$../equations/hypergeometric_1f1_13.svg]][ /a, b/ and /z/ all large.][[sub 1]F[sub 1](-814723.75, -13586.87890625, -15.87335205078125)]]
208[[ [/\large  $$_1F_1(-a, -b; z)$$] [$../equations/hypergeometric_1f1_14.svg]][ /a < b/, /b > z/, this is really the same domain as above.][ ]]
209[[ [/\large  $$_1F_1(a, -b; z)$$] [$../equations/hypergeometric_1f1_15.svg]][ There is a gap in between methods where no reliable implementation is possible, the issue becomes much worse for /a/, /b/ and /z/ all large.][[sub 1]F[sub 1](9057.91796875, -1252.51318359375, 15.87335205078125)]]
210[[ [/\large  $$_1F_1(a_{tiny}, b; -z)$$] [$../equations/hypergeometric_1f1_16.svg]  ][This domain is mostly handled by A&S 13.3.6 (see implementation notes below), but there
211      are some values where either that series is non-convergent (most particularly for /b/ < 0)
212      or where the series becomes divergent after a few terms limiting the precision that can be achieved.][[sub 1]F[sub 1](-5.9981750131794866e-15, 0.499999999999994, -240.42092034220695)]]
213]
214
215The following graph illustrates the problem area for /b < 0/ and /a,z > 0/:
216
217[? __build_html '''<?dbhtml-include href="'''__base_path__'''/graphs/hypergeometric_1f1/negative_b_incalculable.html"?>''']
218[?! __build_html [$../graphs/hypergeometric_1f1/negative_b_incalculable.png]]
219
220[h4 Testing]
221
222There are 3 main groups of tests:
223
224* Spot tests for special inputs with known values.
225* Sanity checks which use integrals of hypergeometric functions of known value.  These are particularly useful
226since for fixed ['a] and ['b] they evaluate ['[sub 1]F[sub 1](a,b,z)] for all /z/.
227* Testing against values precomputed using arbitrary precision arithmetic and the /pFq/ series.
228
229We also have a [@../../tools/hypergeometric_1F1_error_plot.cpp small program] for testing random values over a user-specified domain of /a/, /b/ and /z/, this program
230is also used for the error rate plots below and has been extremely useful in fine-tuning the implementation.
231
232It should be noted however, that there are some domains for large negative /a/ and /b/ that have poor test coverage as we were
233simply unable to compute test values in reasonable time: it is not uncommon for the /pFq/ series to cancel many hundreds of digits
234and sometimes into the thousands of digits.
235
236[h4 Errors]
237
238We divide the domain of [sub 1]/F/[sub 1] up into several domains to explain the error rates.
239
240In the following graphs we ran 100000 random test cases over each domain, note that the scatter plots show only the very worst errors
241as otherwise the graphs are both incomprehensible and virtually unplottable (as in sudden browser death).
242
243For 0 < a,b,z the error rates are trivially small unless we are forced to take steps to avoid very-slow convergence and use a method other than direct evaluation of the series
244for performance reasons.  Even so the errors rates are broadly acceptable, while the scatter graph shows where the worst errors are located:
245
246[$../graphs/hypergeometric_1f1/positive_abz_bins.svg]
247[? __build_html '''<?dbhtml-include href="'''__base_path__'''/graphs/hypergeometric_1f1/positive_abz.html"?>''']
248[?! __build_html [$../graphs/hypergeometric_1f1/positive_abz.png]]
249
250For -1000 < a < 0 and 0 < b,z < 1000 the maximum error rates are higher, but most are still low, and the worst errors are fairly evenly distributed:
251
252[$../graphs/hypergeometric_1f1/negative_a_bins.svg]
253[? __build_html '''<?dbhtml-include href="'''__base_path__'''/graphs/hypergeometric_1f1/negative_a.html"?>''']
254[?! __build_html [$../graphs/hypergeometric_1f1/negative_a.png]]
255
256For -1000 < /b/ < 0 and /a/,/z/ > 0 the errors are mostly low at double precision except near the "unimplementable zone".
257Note however, that the some of the methods used here fail to converge to much better than double precision.
258
259[$../graphs/hypergeometric_1f1/negative_b_bins.svg]
260[? __build_html '''<?dbhtml-include href="'''__base_path__'''/graphs/hypergeometric_1f1/negative_b.html"?>''']
261[?! __build_html [$../graphs/hypergeometric_1f1/negative_b.png]]
262
263For both /a/ and /b/ less than zero, the errors the worst errors are clustered in a "difficult zone" with /b < a/ and /z/ [asymp] /a/:
264
265[$../graphs/hypergeometric_1f1/negative_ab_bins.svg]
266[? __build_html '''<?dbhtml-include href="'''__base_path__'''/graphs/hypergeometric_1f1/negative_ab.html"?>''']
267[?! __build_html [$../graphs/hypergeometric_1f1/negative_ab.png]]
268
269
270[h4 Implementation]
271
272The implementation for this function is remarkably complex;
273readers will have to refer to the code for the transitions between methods, as we can only give an overview here.
274
275In almost all cases where /z < 0/ we use [@https://en.wikipedia.org/wiki/Confluent_hypergeometric_function Kummer's relation]
276to make /z/ positive:
277
278[:[/\large  $$_1F_1(a, b; -z) = e^{-z} {_1F_1}(a, b; z)$$]
279[$../equations/hypergeometric_1f1_12.svg]]
280
281The main series representation
282
283[:[$../equations/hypergeometric_1f1_1.svg]]
284
285is used only when
286
287* we are sure that it is convergent and not subject to excessive cancellation, and
288* there is no other better method available.
289
290The implementation of this series is complicated by the fact that for /b/ < 0 then what appears to be a fully converged series can in fact suddenly jump back
291to life again as /b/ crosses the origin.
292
293A&S 13.3.6 gives
294
295[:[/\large $$_1F_1(a, b; z) = e^{ \frac{z}{2} } \Gamma(b-a- \frac{1}{2} ) ( \frac{z}{4})^{a-b+ \frac{1}{2}} \sum_{n=0}^{\infty} \frac{(2b-2a-1)_n(b-2a)_n(b-a-\frac{1}{2}+n)}{n!(b)_n} (-1)^n I_{b-a-\frac{1}{2}+n}(\frac{z}{2})$$]
296[$../equations/hypergeometric_1f1_3.svg]]
297
298which is particularly useful for ['a [cong] b] and ['z > 0], or /a/ \u226a 1, and ['z < 0].
299
300Then we have Tricomi's approximation (given in simplified form in A&S 13.3.7) [link math_toolkit.hypergeometric.hypergeometric_refs (7)]
301
302[:[/\large $$_1F_1(a, b; z) = \Gamma(b) e^{ \frac{1}{2} z} \sum_{n=0}^{\infty} 2^{-n}z^n A_n(a,b) E_{b-1+n}(z(\frac{b}{2}-a)) $$]
303[$../equations/hypergeometric_1f1_4.svg]]
304
305with
306
307[:[/\large $$A_0(a,b) = 1, A_1(a,b) = 0, A_2(a,b) = \frac{b}{2}, A_3(a,b)= - \frac{1}{3}(b-2a)  $$]
308[$../equations/hypergeometric_1f1_5.svg]]
309
310and
311
312[:[/\large $$(n+1)A_{n+1} = (n+b-1)A_{n-1} - (b-2a)A_{n-2} \quad;\quad n \geq 2 $$]
313[$../equations/hypergeometric_1f1_6.svg]]
314
315With ['E[sub v]] defined as:
316
317[:[/
318\begin{equation*}
319\begin{split}
320E_v(z) & = z^{-\frac{1}{2}v} J_v(2 \sqrt{z})\\
321E_v(-z) & = z^{-\frac{1}{2}v} I_v(2 \sqrt{z})\\
322E_v(0) & = \frac{1}{\Gamma(v + 1)}
323\end{split}
324\end{equation*}]
325[$../equations/hypergeometric_1f1_7.svg]]
326
327This approximation is especially effective when ['a < 0].
328
329For /a/ and /b/ both large and positive and somewhat similar in size then an expansion in terms of gamma functions can be used [link math_toolkit.hypergeometric.hypergeometric_refs (6)]:
330
331[:[/\large  $$_1F_1(a, b; x) = \frac{1}{B(a, b-a)} e^x \sum_{k=0}^{\infty} \frac{(1-a)_k}{k!} \frac{\gamma(b-a+k, x)}{x^{b-a+k}} $$]
332[$../equations/hypergeometric_1f1_8.svg]]
333
334For /z/ large we have the asymptotic expansion:
335
336[:[/\large  $$_1F_1(a, b; x) \approx \frac{e^x x^{a-b}}{\Gamma(a)} \sum_{k=0}^{\infty} \frac{(1-a)_k(b-a)_k}{k! x^k} $$]
337[$../equations/hypergeometric_1f1_9.svg]]
338
339which is a special case of the gamma function expansion above.
340
341In the situation where `ab/z` is reasonably small then Luke's rational approximation is used - this is too complex to document
342here, refer either to the code or the original paper [link math_toolkit.hypergeometric.hypergeometric_refs (3)].
343
344The special case [sub 1]/F/[sub 1](1, /b/, -/z/) is treated via Luke's Pade approximation [link math_toolkit.hypergeometric.hypergeometric_refs (3)].
345
346That effectively completes the "direct" methods used, the remaining areas are treated indirectly via recurrence relations.
347These require extreme care in their use, as they often change the direction of stability, or else are not stable at all.
348Sometimes this is a well defined and characterized change in direction: for example with /a,b/ and /z/ all positive recurrence on /a/ via
349
350[:[/\large  $$(b-a) _1F_1(a-1, b; z) + (2a-b+z) _1F_1(a, b; z) -a _1F_1(a+1, b; z) = 0 $$]
351[$../equations/hypergeometric_1f1_10.svg]]
352
353abruptly changes from stable forwards recursion to stable backwards if /2a-b+z/ changes sign.
354Thus recurrence on /a/, even when [sub 1]/F/[sub 1](/a/+/N/, /b/, /z/) is strictly increasing, needs careful handling as /a/ \u2192 0.
355
356The transitory nature of the stable recurrence relations is well documented in the literature,
357for example [link math_toolkit.hypergeometric.hypergeometric_refs (10)]
358gives many examples, including the anomalous behaviour of recurrence on /a/ and /b/ for large /z/ as first documented by
359Gauchi [link math_toolkit.hypergeometric.hypergeometric_refs (12)].
360Gauchi also provides the definitive reference on 3-term recurrence relations
361in general in [link math_toolkit.hypergeometric.hypergeometric_refs (11)].
362
363Unfortunately, not all recurrence stabilities are so well defined.
364For example, when considering [sub 1]F[sub 1](/a/, -/b/, /z/) it would be convenient to use
365the continued fractions associated with the recurrence relations to calculate [sub 1]F[sub 1](/a/, -/b/, /z/) / [sub 1]F[sub 1](/a/, 1-/b/, /z/)
366and then normalize
367either by iterating forwards on /b/ until /b > 0/ and comparison with a reference value, or by using the Wronskian
368
369[:[/\large  $$_1F_1(a, b; z) \frac{d}{dz}z^{1-b}_1F_1(1+a-b, 2-b; z) - z^{1-b}_1F_1(1+a-b, 2-b; z)\frac{d}{dz}{_1F_1}(a, b; z) = (1-b)z^{-b}e^z,$$]
370[$../equations/hypergeometric_1f1_11.svg]]
371
372which is of course the well known Miller's method [link math_toolkit.hypergeometric.hypergeometric_refs (12)].
373
374Unfortunately, stable forwards recursion on /b/ is stable only for /|b| << |z|/, as /|b|/ increases in magnitude it passes through a region
375where recursion is unstable in both directions before eventually becoming stable in the backwards direction (at least for a while!).
376This transition is moderated not by a change of sign in the recurrence coefficients themselves, but by a change in the behaviour of the ['values] of [sub 1]F[sub 1] -
377from alternating in sign when ['|b|] is small to having the same sign when /b/ is larger.  During the actual transition, [sub 1]F[sub 1] will either
378pass through a zero or a minima depending on whether b is even or odd (if there is a minima at [sub 1]F[sub 1](a, b, z) then there is necessarily a zero
379at [sub 1]F[sub 1](a+1, b+1, z) as per the [@https://dlmf.nist.gov/13.3#E15 derivative of the function]).
380As a result the behaviour of the recurrence relations
381is almost impossible to reason about in this area, and we are left to using heuristic based approaches to "guess" which region we are in.
382
383In this implementation we use recurrence relations as follows:
384
385For /a,b,z > 0/ and large we can either:
386
387* Make /0 < a < 1/ and /b > z/ and evaluate the defining series directly, or
388* The gamma function approximation has decent convergence and accuracy for /2b - 1 < a < 2b < z/, so we can move /a/ and /b/ into this region, or
389* We can recurse on /b/ alone so that /b-1 < a < b/ and use A&S 13.3.6 as long as /z/ is not too large.
390
391For ['b < 0] and ['a] tiny we would normally use A&S 13.3.6, but when that is non-convergent for some inputs we can use the forward recurrence relation on ['b] to
392calculate the ratio ['[sub 1]F[sub 1](a, -b, z)/[sub 1]F[sub 1](a, 1-b, z)] and then iterate forwards until ['b > 0] and compute a reference value
393and normalize (Millers Method).
394In the same domain when ['b] is near -1 we can use a single backwards recursion on /b/ to compute ['[sub 1]F[sub 1](a, -b, z)]
395from ['[sub 1]F[sub 1](a, 2-b, z)] and ['[sub 1]F[sub 1](/a/, 1-/b/, /z/)] even though technically we are recursing in the unstable direction.
396
397For ['[sub 1]F[sub 1](-N, b, z)] and integer /N/ then backwards recursion from ['[sub 1]F[sub 1](0, b, z)] and ['[sub 1]F[sub 1](-1, b, z)] works well.
398
399For /a/ or /b/ < 0 and if all the direct methods have failed, then we use various fallbacks:
400
401For ['[sub 1]F[sub 1](-a, b, z)] we can use backwards recursion on /a/ as long as ['b > z], otherwise a more complex scheme is required
402which starts from ['[sub 1]F[sub 1](-a + N, b + M, z)], and recurses backwards in up to 3 stages: first on /a/, then on /a/ and /b/ together,
403and finally on /b/ alone.
404
405For /b < 0/ we have no good methods in some domains (see the unsolved issues above).
406However in some circumstances we can either use:
407
408* 3-stage backwards recursion on both /a/, /a/ and /b/ and then /b/ as above.
409* Calculate the ratio ['[sub 1]F[sub 1](a, b, z) / ['[sub 1]F[sub 1](a-1, b-1, z)]] via backwards recurrence when z is small, and then normalize via the Wronskian above (Miller's method).
410* Calculate the ratio ['[sub 1]F[sub 1](a, b, z) / ['[sub 1]F[sub 1](a+1, b+1, z)]] via forwards recurrence when z is large, and then normalize by iterating until b > 1 and comparing to a reference value.
411
412The latter two methods use a lookup table to determine whether inputs are in either of the domains or neither.  Unfortunately the methods are basically
413limited to double precision: calculation of the ratios require iteration ['towards] the no-mans-land between the two methods where iteration is unstable in
414both directions.  As a result, only low-precision results which require few iterations to calculate the ratio are available.
415
416If all else fails, then we use a checked series summation which will raise an __evaluation_error if more than half the digits
417are destroyed by cancellation.
418
419[endsect]  [/section:hyper_geometric_1f1 Hypergeometric [sub 1]/F/[sub 1]]
420
421[section:hypergeometric_pfq Hypergeometric [sub p]F[sub q]]
422
423   #include <boost/math/special_functions/hypergeometric_pFq.hpp>
424
425   namespace boost { namespace math {
426
427   template <class Seq, class Real>
428   ``__sf_result`` hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error, const Policy& pol);
429
430   template <class Seq, class Real>
431   ``__sf_result`` hypergeometric_pFq(const Seq& aj, const Seq& bj, const Real& z, Real* p_abs_error = 0);
432
433   template <class R, class Real>
434   ``__sf_result`` hypergeometric_pFq(const std::initializer_list<R>& aj, const std::initializer_list<R>& bj, const Real& z, Real* p_abs_error, const Policy& pol);
435
436   template <class R, class Real>
437   ``__sf_result`` hypergeometric_pFq(const std::initializer_list<R>& aj, const std::initializer_list<R>& bj, const Real& z, Real* p_abs_error = 0);
438
439   template <class Seq, class Real, class Policy>
440   Real hypergeometric_pFq_precision(const Seq& aj, const Seq& bj, Real z, unsigned digits10, double timeout, const Policy& pol);
441
442   template <class Seq, class Real>
443   Real hypergeometric_pFq_precision(const Seq& aj, const Seq& bj, const Real& z, unsigned digits10, double timeout = 0.5);
444
445   template <class Real, class Policy>
446   Real hypergeometric_pFq_precision(const std::initializer_list<Real>& aj, const std::initializer_list<Real>& bj, const Real& z, unsigned digits10, double timeout, const Policy& pol);
447
448   template <class Real>
449   Real hypergeometric_pFq_precision(const std::initializer_list<Real>& aj, const std::initializer_list<Real>& bj, const Real& z, unsigned digits10, double timeout = 0.5);
450
451   }} // namespaces
452
453[h4 Description]
454
455The function `hypergeometric_pFq` returns the result of:
456
457[:[/\Large  $$ {}_pF_q\left(\left\{a_1, \ldots, a_p\right\}, \left\{b_1, \ldots, b_q\right\}; z\right)=\sum_{n=0}^{\infty} \frac{\prod_{j=1}^{p}\left(a_j\right)_n}{\prod_{j=1}^{q}\left(b_{j}\right)_n} \frac{z^n}{n!} $$]
458[$../equations/hypergeometric_pfq_1.svg]]
459
460It is most naturally used via initializer lists as in:
461
462   double h = hypergeometric_pFq({2,3,4}, {5,6,7,8}, z);  // Calculate 3F4
463
464The optional ['p_abs_error] argument calculates an estimate of the absolute error in the result from the
465L1 norm of the sum, plus some other factors (see implementation below).
466
467You should divide this value by the result to get an estimate of ['relative error].
468
469It should be noted that the error estimates are rather crude - the error can be significantly underestimated
470in some circumstances, and over-estimated in others.
471
472The `hypergeometric_pFq_precision` functions will calculate `pFq` to a specified number of decimal places, and if `timeout`
473is reached then they raise an __evaluation_error.  Note that while these functions are defined as templates, they
474require type `Real` to be a *variable-precision* floating-point type: in practice the only type currently supported
475(as of July 2019) is `boost::multiprecision::mpfr_float`.  Typical usage would be:
476
477
478   typedef boost::multiprecision::mpfr_float mp_type;
479   //
480   // Calculate 2F2 to 20 decimal places using a 10 second timeout:
481   //
482   mp_type result = boost::math::hypergeometric_pFq_precision(
483     { mp_type(a1), mp_type(a2) }, { mp_type(b1), mp_type(b2) }, mp_type(z), 20, 10.0
484     );
485   //
486   // Convert the result back to a double:
487   //
488   double d_result = static_cast<double>(result);
489
490[h4 Implementation]
491
492This function is implemented by direct summation of the series; summation normally starts with the zeroth term,
493but will skip forward and sum outward (ie in both forward and backward directions) from some term /N/ when
494required.  This is particularly important when some of the /b/ arguments are negative, as in this situation
495the sum undergoes "false-convergence", and then diverges again as each b[sub j] passes the origin.  Consequently,
496were you to plot the magnitude of the terms in the sum, you would see them pass through a series of
497minima and maxima before finally converging to zero at infinity.  For some values of /p/ and /q/ we
498can compute where the maxima occur, and therefore sum only the terms that will have an impact on the
499result.  For other /p/ and /q/ values, predicting the exact locations of the maxima is not so easy, and we
500simply restart summation at the point where each b[sub j] passes the origin: this will eventually reach
501all the significant terms of the sum, but the key word may well be "eventually".
502
503The error term /p_abs_error/ is normally simply the sum of the absolute values of each term multiplied
504by machine epsilon for type `Real`.  However,
505if it was necessary for the summation to skip forward, then /p_abs_error/ is adjusted to account for the
506error inherent in calculating the N'th term via logarithms.
507
508[endsect] [/section:pFq Hypergeometric [sub p]F[sub q]]
509
510[section:hypergeometric_refs Hypergeometric References]
511
512# Beals, Richard, and Roderick Wong. ['Special functions: a graduate text.] Vol. 126. Cambridge University Press, 2010.
513# Pearson, John W., Sheehan Olver, and Mason A. Porter. ['Numerical methods for the computation of the confluent and Gauss hypergeometric functions.] Numerical Algorithms 74.3 (2017): 821-866.
514# Luke, Yudell L. ['Algorithms for Rational Approximations for a Confluent Hypergeometric Function  II.] MISSOURI UNIV KANSAS CITY DEPT OF MATHEMATICS, 1976.
515# Derezinski, Jan. ['Hypergeometric type functions and their symmetries.] Annales Henri Poincar[eacute]. Vol. 15. No. 8. Springer Basel, 2014.
516# Keith E. Muller ['Computing the confluent hypergeometric function, M(a, b, x)].  Numer. Math. 90: 179-196 (2001).
517# Carlo Morosi, Livio Pizzocchero. ['On the expansion of the Kummer function in terms of incomplete Gamma functions.]  Arch. Inequal. Appl. 2 (2004), 49-72.
518# Jose Luis Lopez, Nico M. Temme. ['Asymptotics and numerics of polynomials used in Tricomi and Buchholz expansions of Kummer functions]. Numerische Mathematik, August 2010.
519# Javier Sesma.  ['The Temme's sum rule for confluent hypergeometric functions revisited].  Journal of Computational and Applied Mathematics 163 (2004) 429-431.
520# Javier Segura, Nico M. Temme.  ['Numerically satisfactory solutions of Kummer recurrence relations].  Numer. Math. (2008) 111:109-119.
521# Alfredo Deano, Javier Segura. ['Transitory Minimal Solutions Of Hypergeometric Recursions And Pseudoconvergence of Associated Continued Fractions].  Mathematics of Computation, Volume 76, Number 258, April 2007.
522# W. Gautschi. ['Computational aspects of three-term recurrence relations]. SIAM Review 9, no.1 (1967) 24-82.
523# W. Gautschi. ['Anomalous convergence of a continued fraction for ratios of Kummer functions]. Math. Comput., 31, no.140 (1977) 994-999.
524# British Association for the Advancement of Science: ['Bessel functions, Part II, Mathematical Tables vol. X]. Cambridge (1952).
525
526
527[endsect] [/section:hypergeometric_refs Hypergeometric References]
528
529[endsect] [/section:hypergeometric Hypergeometric Functions]
530
531[/  Copyright 2017 John Maddock.
532  Distributed under the Boost Software License, Version 1.0.
533  (See accompanying file LICENSE_1_0.txt or copy at
534  http://www.boost.org/LICENSE_1_0.txt).
535]