math/doc/html/math_toolkit/hypergeometric/hypergeometric_1f1.html
2019-10-31 17:55:35 +00:00

793 lines
49 KiB
HTML

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Hypergeometric 1F1</title>
<link rel="stylesheet" href="../../math.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../index.html" title="Math Toolkit 2.11.0">
<link rel="up" href="../hypergeometric.html" title="Hypergeometric Functions">
<link rel="prev" href="hypergeometric_2f0.html" title="Hypergeometric 2F0">
<link rel="next" href="hypergeometric_pfq.html" title="Hypergeometric pFq">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="hypergeometric_2f0.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../hypergeometric.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="hypergeometric_pfq.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="math_toolkit.hypergeometric.hypergeometric_1f1"></a><a class="link" href="hypergeometric_1f1.html" title="Hypergeometric 1F1">Hypergeometric
<sub>1</sub><span class="emphasis"><em>F</em></span><sub>1</sub></a>
</h3></div></div></div>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">hypergeometric_1F1</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span> <span class="special">{</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">hypergeometric_1F1</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">hypergeometric_1F1</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">,</span> <span class="keyword">const</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&amp;);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">hypergeometric_1F1_regularized</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">hypergeometric_1F1_regularized</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">,</span> <span class="keyword">const</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&amp;);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">log_hypergeometric_1F1</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">log_hypergeometric_1F1</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">,</span> <span class="keyword">const</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&amp;);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">log_hypergeometric_1F1</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">,</span> <span class="keyword">int</span><span class="special">*</span> <span class="identifier">sign</span><span class="special">);</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T3</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&gt;</span>
<a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">log_hypergeometric_1F1</span><span class="special">(</span><span class="identifier">T1</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">T2</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">T3</span> <span class="identifier">z</span><span class="special">,</span> <span class="keyword">int</span><span class="special">*</span> <span class="identifier">sign</span><span class="special">,</span> <span class="keyword">const</span> <a class="link" href="../../policy.html" title="Chapter&#160;20.&#160;Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&amp;);</span>
<span class="special">}}</span> <span class="comment">// namespaces</span>
</pre>
<h5>
<a name="math_toolkit.hypergeometric.hypergeometric_1f1.h0"></a>
<span class="phrase"><a name="math_toolkit.hypergeometric.hypergeometric_1f1.description"></a></span><a class="link" href="hypergeometric_1f1.html#math_toolkit.hypergeometric.hypergeometric_1f1.description">Description</a>
</h5>
<p>
</p>
<div>
<script type="text/javascript" src="../../../graphs/hypergeometric_1f1/plotlyjs-bundle.js"></script>
</div>
<p>
</p>
<p>
The function <code class="computeroutput"><span class="identifier">hypergeometric_1F1</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span>
<span class="identifier">b</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span></code> returns
the non-singular solution to <a href="https://en.wikipedia.org/wiki/Confluent_hypergeometric_function" target="_top">Kummer's
equation</a>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_2.svg" width="181" height="34"></object></span>
</p></blockquote></div>
<p>
which for |<span class="emphasis"><em>z</em></span>| &lt; 1 has the hypergeometric series expansion
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_1.svg" width="234" height="38"></object></span>
</p></blockquote></div>
<p>
where (<span class="emphasis"><em>a</em></span>)<sub><span class="emphasis"><em>n</em></span></sub> denotes rising factorial.
This function has the same definition as Mathematica's <code class="computeroutput"><span class="identifier">Hypergeometric1F1</span><span class="special">[</span><span class="identifier">a</span><span class="special">,</span>
<span class="identifier">b</span><span class="special">,</span> <span class="identifier">z</span><span class="special">]</span></code> and
Maple's <code class="computeroutput"><span class="identifier">KummerM</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span></code>.
</p>
<p>
The "regularized" versions of the function return:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_17.svg" width="313" height="44"></object></span>
</p></blockquote></div>
<p>
The "log" versions of the function return:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_18.svg" width="119" height="20"></object></span>
</p></blockquote></div>
<p>
When the optional <code class="computeroutput"><span class="identifier">sign</span></code> argument
is supplied it is set on exit to either +1 or -1 depending on the sign of
<sub>1</sub><span class="emphasis"><em>F</em></span><sub>1</sub>(<span class="emphasis"><em>a</em></span>, <span class="emphasis"><em>b</em></span>,
<span class="emphasis"><em>z</em></span>).
</p>
<p>
Both the regularized and the logarithmic versions of these functions return
results without the spurious under/overflow that plague naive implementations.
</p>
<h5>
<a name="math_toolkit.hypergeometric.hypergeometric_1f1.h1"></a>
<span class="phrase"><a name="math_toolkit.hypergeometric.hypergeometric_1f1.known_issues"></a></span><a class="link" href="hypergeometric_1f1.html#math_toolkit.hypergeometric.hypergeometric_1f1.known_issues">Known
Issues</a>
</h5>
<p>
This function is still very much the subject of active research, and a full
range of methods capable of calculating the function over its entire domain
are not yet available. We have worked extremely hard to ensure that problem
domains result in an exception being thrown (an <a class="link" href="../error_handling.html#math_toolkit.error_handling.evaluation_error">evaluation_error</a>)
rather than return a garbage result. Domains that are still unsolved include:
</p>
<div class="informaltable"><table class="table">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
domain
</p>
</th>
<th>
<p>
comment
</p>
</th>
<th>
<p>
example
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_13.svg" width="101" height="16"></object></span>
</p>
</td>
<td>
<p>
<span class="emphasis"><em>a, b</em></span> and <span class="emphasis"><em>z</em></span> all large.
</p>
</td>
<td>
<p>
<sub>1</sub>F<sub>1</sub>(-814723.75, -13586.87890625, -15.87335205078125)
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_14.svg" width="89" height="16"></object></span>
</p>
</td>
<td>
<p>
<span class="emphasis"><em>a &lt; b</em></span>, <span class="emphasis"><em>b &gt; z</em></span>, this
is really the same domain as above.
</p>
</td>
<td>
</td>
</tr>
<tr>
<td>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_15.svg" width="78" height="16"></object></span>
</p>
</td>
<td>
<p>
There is a gap in between methods where no reliable implementation
is possible, the issue becomes much worse for <span class="emphasis"><em>a</em></span>,
<span class="emphasis"><em>b</em></span> and <span class="emphasis"><em>z</em></span> all large.
</p>
</td>
<td>
<p>
<sub>1</sub>F<sub>1</sub>(9057.91796875, -1252.51318359375, 15.87335205078125)
</p>
</td>
</tr>
<tr>
<td>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_16.svg" width="98" height="18"></object></span>
</p>
</td>
<td>
<p>
This domain is mostly handled by A&amp;S 13.3.6 (see implementation
notes below), but there are some values where either that series
is non-convergent (most particularly for <span class="emphasis"><em>b</em></span>
&lt; 0) or where the series becomes divergent after a few terms
limiting the precision that can be achieved.
</p>
</td>
<td>
<p>
<sub>1</sub>F<sub>1</sub>(-5.9981750131794866e-15, 0.499999999999994, -240.42092034220695)
</p>
</td>
</tr>
</tbody>
</table></div>
<p>
The following graph illustrates the problem area for <span class="emphasis"><em>b &lt; 0</em></span>
and <span class="emphasis"><em>a,z &gt; 0</em></span>:
</p>
<p>
</p>
<div>
<script type="text/javascript" src="../../../graphs/hypergeometric_1f1/negative_b_incalculable.js"></script>
<div id="fce5fa05-942c-4973-941f-2f3d25bcecb3" style="width: 800px; height: 600px;" class="plotly-graph-div"></div>
<script type="text/javascript">
(function(){
window.PLOTLYENV={'BASE_URL': 'https://plot.ly'};
var gd = document.getElementById('fce5fa05-942c-4973-941f-2f3d25bcecb3')
var resizeDebounce = null;
function resizePlot() {
var bb = gd.getBoundingClientRect();
Plotly.relayout(gd, {
width: bb.width,
height: bb.height
});
}
window.addEventListener('resize', function() {
if (resizeDebounce) {
window.clearTimeout(resizeDebounce);
}
resizeDebounce = window.setTimeout(resizePlot, 100);
});
Plotly.plot(gd, {
data: negative_b_incalculable.data,
layout: negative_b_incalculable.layout,
frames: negative_b_incalculable.frames,
config: {"showLink": true, "linkText": "Export to plot.ly", "mapboxAccessToken": "pk.eyJ1IjoiY2hyaWRkeXAiLCJhIjoiY2lxMnVvdm5iMDA4dnhsbTQ5aHJzcGs0MyJ9.X9o_rzNLNesDxdra4neC_A"}
});
}());
</script>
</div>
<p>
</p>
<h5>
<a name="math_toolkit.hypergeometric.hypergeometric_1f1.h2"></a>
<span class="phrase"><a name="math_toolkit.hypergeometric.hypergeometric_1f1.testing"></a></span><a class="link" href="hypergeometric_1f1.html#math_toolkit.hypergeometric.hypergeometric_1f1.testing">Testing</a>
</h5>
<p>
There are 3 main groups of tests:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Spot tests for special inputs with known values.
</li>
<li class="listitem">
Sanity checks which use integrals of hypergeometric functions of known
value. These are particularly useful since for fixed <span class="emphasis"><em>a</em></span>
and <span class="emphasis"><em>b</em></span> they evaluate <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a,b,z)</em></span>
for all <span class="emphasis"><em>z</em></span>.
</li>
<li class="listitem">
Testing against values precomputed using arbitrary precision arithmetic
and the <span class="emphasis"><em>pFq</em></span> series.
</li>
</ul></div>
<p>
We also have a <a href="../../../../tools/hypergeometric_1F1_error_plot.cpp" target="_top">small
program</a> for testing random values over a user-specified domain of
<span class="emphasis"><em>a</em></span>, <span class="emphasis"><em>b</em></span> and <span class="emphasis"><em>z</em></span>,
this program is also used for the error rate plots below and has been extremely
useful in fine-tuning the implementation.
</p>
<p>
It should be noted however, that there are some domains for large negative
<span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> that have poor test coverage
as we were simply unable to compute test values in reasonable time: it is
not uncommon for the <span class="emphasis"><em>pFq</em></span> series to cancel many hundreds
of digits and sometimes into the thousands of digits.
</p>
<h5>
<a name="math_toolkit.hypergeometric.hypergeometric_1f1.h3"></a>
<span class="phrase"><a name="math_toolkit.hypergeometric.hypergeometric_1f1.errors"></a></span><a class="link" href="hypergeometric_1f1.html#math_toolkit.hypergeometric.hypergeometric_1f1.errors">Errors</a>
</h5>
<p>
We divide the domain of <sub>1</sub><span class="emphasis"><em>F</em></span><sub>1</sub> up into several domains to
explain the error rates.
</p>
<p>
In the following graphs we ran 100000 random test cases over each domain,
note that the scatter plots show only the very worst errors as otherwise
the graphs are both incomprehensible and virtually unplottable (as in sudden
browser death).
</p>
<p>
For 0 &lt; 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 for performance reasons. Even so the errors
rates are broadly acceptable, while the scatter graph shows where the worst
errors are located:
</p>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../graphs/hypergeometric_1f1/positive_abz_bins.svg" width="567" height="320"></object></span>
</p>
<div>
<script type="text/javascript" src="../../../graphs/hypergeometric_1f1/positive_abz.js"></script>
<div id="87d8c26d-c743-4b69-8576-64f861bb7262" style="width: 800px; height: 600px;" class="plotly-graph-div"></div>
<script type="text/javascript">
(function () {
window.PLOTLYENV = { 'BASE_URL': 'https://plot.ly' };
var gd = document.getElementById('87d8c26d-c743-4b69-8576-64f861bb7262')
var resizeDebounce = null;
function resizePlot() {
var bb = gd.getBoundingClientRect();
Plotly.relayout(gd, {
width: bb.width,
height: bb.height
});
}
window.addEventListener('resize', function () {
if (resizeDebounce) {
window.clearTimeout(resizeDebounce);
}
resizeDebounce = window.setTimeout(resizePlot, 100);
});
Plotly.plot(gd, {
data: positive_abz.data,
layout: positive_abz.layout,
frames: positive_abz.frames,
config: { "showLink": true, "linkText": "Export to plot.ly", "mapboxAccessToken": "pk.eyJ1IjoiY2hyaWRkeXAiLCJhIjoiY2lxMnVvdm5iMDA4dnhsbTQ5aHJzcGs0MyJ9.X9o_rzNLNesDxdra4neC_A" }
});
}());
</script>
</div>
<p>
</p>
<p>
For -1000 &lt; a &lt; 0 and 0 &lt; b,z &lt; 1000 the maximum error rates
are higher, but most are still low, and the worst errors are fairly evenly
distributed:
</p>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../graphs/hypergeometric_1f1/negative_a_bins.svg" width="567" height="331"></object></span>
</p>
<div>
<script type="text/javascript" src="../../../graphs/hypergeometric_1f1/negative_a.js"></script>
<div id="cc677464-acba-4deb-b026-ef0ea03f1259" style="width: 800px; height: 600px;" class="plotly-graph-div"></div>
<script type="text/javascript">
(function () {
window.PLOTLYENV = { 'BASE_URL': 'https://plot.ly' };
var gd = document.getElementById('cc677464-acba-4deb-b026-ef0ea03f1259')
var resizeDebounce = null;
function resizePlot() {
var bb = gd.getBoundingClientRect();
Plotly.relayout(gd, {
width: bb.width,
height: bb.height
});
}
window.addEventListener('resize', function () {
if (resizeDebounce) {
window.clearTimeout(resizeDebounce);
}
resizeDebounce = window.setTimeout(resizePlot, 100);
});
Plotly.plot(gd, {
data: negative_a.data,
layout: negative_a.layout,
frames: negative_a.frames,
config: { "showLink": true, "linkText": "Export to plot.ly", "mapboxAccessToken": "pk.eyJ1IjoiY2hyaWRkeXAiLCJhIjoiY2lxMnVvdm5iMDA4dnhsbTQ5aHJzcGs0MyJ9.X9o_rzNLNesDxdra4neC_A" }
});
}());
</script>
</div>
<p>
</p>
<p>
For -1000 &lt; <span class="emphasis"><em>b</em></span> &lt; 0 and <span class="emphasis"><em>a</em></span>,<span class="emphasis"><em>z</em></span>
&gt; 0 the errors are mostly low at double precision except near the "unimplementable
zone". Note however, that the some of the methods used here fail to
converge to much better than double precision.
</p>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../graphs/hypergeometric_1f1/negative_b_bins.svg" width="567" height="319"></object></span>
</p>
<div>
<script type="text/javascript" src="../../../graphs/hypergeometric_1f1/negative_b.js"></script>
<div id="49ba2424-47a3-454d-ba72-b46ded00693f" style="width: 800px; height: 600px;" class="plotly-graph-div"></div>
<script type="text/javascript">
(function(){
window.PLOTLYENV={'BASE_URL': 'https://plot.ly'};
var gd = document.getElementById('49ba2424-47a3-454d-ba72-b46ded00693f')
var resizeDebounce = null;
function resizePlot() {
var bb = gd.getBoundingClientRect();
Plotly.relayout(gd, {
width: bb.width,
height: bb.height
});
}
window.addEventListener('resize', function() {
if (resizeDebounce) {
window.clearTimeout(resizeDebounce);
}
resizeDebounce = window.setTimeout(resizePlot, 100);
});
Plotly.plot(gd, {
data: negative_b.data,
layout: negative_b.layout,
frames: negative_b.frames,
config: {"showLink": true, "linkText": "Export to plot.ly", "mapboxAccessToken": "pk.eyJ1IjoiY2hyaWRkeXAiLCJhIjoiY2lxMnVvdm5iMDA4dnhsbTQ5aHJzcGs0MyJ9.X9o_rzNLNesDxdra4neC_A"}
});
}());
</script>
</div>
<p>
</p>
<p>
For both <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> less than zero,
the errors the worst errors are clustered in a "difficult zone"
with <span class="emphasis"><em>b &lt; a</em></span> and <span class="emphasis"><em>z</em></span> &#8776; <span class="emphasis"><em>a</em></span>:
</p>
<p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../graphs/hypergeometric_1f1/negative_ab_bins.svg" width="461" height="280"></object></span>
<body>
<script type="text/javascript" src="../../../graphs/hypergeometric_1f1/negative_ab.js"></script>
<div id="2867e84a-7d1d-4110-b28a-fb718dbd65ca" style="width: 800px; height: 600px;" class="plotly-graph-div"></div>
<script type="text/javascript">
(function(){
window.PLOTLYENV={'BASE_URL': 'https://plot.ly'};
var gd = document.getElementById('2867e84a-7d1d-4110-b28a-fb718dbd65ca')
var resizeDebounce = null;
function resizePlot() {
var bb = gd.getBoundingClientRect();
Plotly.relayout(gd, {
width: bb.width,
height: bb.height
});
}
window.addEventListener('resize', function() {
if (resizeDebounce) {
window.clearTimeout(resizeDebounce);
}
resizeDebounce = window.setTimeout(resizePlot, 100);
});
Plotly.plot(gd, {
data: negative_ab.data,
layout: negative_ab.layout,
frames: negative_ab.frames,
config: {"showLink": true, "linkText": "Export to plot.ly", "mapboxAccessToken": "pk.eyJ1IjoiY2hyaWRkeXAiLCJhIjoiY2lxMnVvdm5iMDA4dnhsbTQ5aHJzcGs0MyJ9.X9o_rzNLNesDxdra4neC_A"}
});
}());
</script>
</body>
</p>
<h5>
<a name="math_toolkit.hypergeometric.hypergeometric_1f1.h4"></a>
<span class="phrase"><a name="math_toolkit.hypergeometric.hypergeometric_1f1.implementation"></a></span><a class="link" href="hypergeometric_1f1.html#math_toolkit.hypergeometric.hypergeometric_1f1.implementation">Implementation</a>
</h5>
<p>
The implementation for this function is remarkably complex; readers will
have to refer to the code for the transitions between methods, as we can
only give an overview here.
</p>
<p>
In almost all cases where <span class="emphasis"><em>z &lt; 0</em></span> we use <a href="https://en.wikipedia.org/wiki/Confluent_hypergeometric_function" target="_top">Kummer's
relation</a> to make <span class="emphasis"><em>z</em></span> positive:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_12.svg" width="189" height="16"></object></span>
</p></blockquote></div>
<p>
The main series representation
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_1.svg" width="234" height="38"></object></span>
</p></blockquote></div>
<p>
is used only when
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
we are sure that it is convergent and not subject to excessive cancellation,
and
</li>
<li class="listitem">
there is no other better method available.
</li>
</ul></div>
<p>
The implementation of this series is complicated by the fact that for <span class="emphasis"><em>b</em></span>
&lt; 0 then what appears to be a fully converged series can in fact suddenly
jump back to life again as <span class="emphasis"><em>b</em></span> crosses the origin.
</p>
<p>
A&amp;S 13.3.6 gives
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_3.svg" width="614" height="39"></object></span>
</p></blockquote></div>
<p>
which is particularly useful for <span class="emphasis"><em>a &#8773; b</em></span> and <span class="emphasis"><em>z
&gt; 0</em></span>, or <span class="emphasis"><em>a</em></span> &#8810; 1, and <span class="emphasis"><em>z
&lt; 0</em></span>.
</p>
<p>
Then we have Tricomi's approximation (given in simplified form in A&amp;S
13.3.7) <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(7)</a>
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_4.svg" width="356" height="38"></object></span>
</p></blockquote></div>
<p>
with
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_5.svg" width="390" height="33"></object></span>
</p></blockquote></div>
<p>
and
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_6.svg" width="370" height="16"></object></span>
</p></blockquote></div>
<p>
With <span class="emphasis"><em>E<sub>v</sub></em></span> defined as:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_7.svg" width="149" height="86"></object></span>
</p></blockquote></div>
<p>
This approximation is especially effective when <span class="emphasis"><em>a &lt; 0</em></span>.
</p>
<p>
For <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> both large and positive
and somewhat similar in size then an expansion in terms of gamma functions
can be used <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(6)</a>:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_8.svg" width="349" height="43"></object></span>
</p></blockquote></div>
<p>
For <span class="emphasis"><em>z</em></span> large we have the asymptotic expansion:
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_9.svg" width="261" height="43"></object></span>
</p></blockquote></div>
<p>
which is a special case of the gamma function expansion above.
</p>
<p>
In the situation where <code class="computeroutput"><span class="identifier">ab</span><span class="special">/</span><span class="identifier">z</span></code> is reasonably
small then Luke's rational approximation is used - this is too complex to
document here, refer either to the code or the original paper <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(3)</a>.
</p>
<p>
The special case <sub>1</sub><span class="emphasis"><em>F</em></span><sub>1</sub>(1, <span class="emphasis"><em>b</em></span>, -<span class="emphasis"><em>z</em></span>)
is treated via Luke's Pade approximation <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(3)</a>.
</p>
<p>
That effectively completes the "direct" methods used, the remaining
areas are treated indirectly via recurrence relations. These require extreme
care in their use, as they often change the direction of stability, or else
are not stable at all. Sometimes this is a well defined and characterized
change in direction: for example with <span class="emphasis"><em>a,b</em></span> and <span class="emphasis"><em>z</em></span>
all positive recurrence on <span class="emphasis"><em>a</em></span> via
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_10.svg" width="429" height="16"></object></span>
</p></blockquote></div>
<p>
abruptly changes from stable forwards recursion to stable backwards if <span class="emphasis"><em>2a-b+z</em></span>
changes sign. Thus recurrence on <span class="emphasis"><em>a</em></span>, even when <sub>1</sub><span class="emphasis"><em>F</em></span><sub>1</sub>(<span class="emphasis"><em>a</em></span>+<span class="emphasis"><em>N</em></span>,
<span class="emphasis"><em>b</em></span>, <span class="emphasis"><em>z</em></span>) is strictly increasing, needs
careful handling as <span class="emphasis"><em>a</em></span> &#8594; 0.
</p>
<p>
The transitory nature of the stable recurrence relations is well documented
in the literature, for example <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(10)</a>
gives many examples, including the anomalous behaviour of recurrence on
<span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> for large <span class="emphasis"><em>z</em></span>
as first documented by Gauchi <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(12)</a>.
Gauchi also provides the definitive reference on 3-term recurrence relations
in general in <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(11)</a>.
</p>
<p>
Unfortunately, not all recurrence stabilities are so well defined. For example,
when considering <sub>1</sub>F<sub>1</sub>(<span class="emphasis"><em>a</em></span>, -<span class="emphasis"><em>b</em></span>, <span class="emphasis"><em>z</em></span>)
it would be convenient to use the continued fractions associated with the
recurrence relations to calculate <sub>1</sub>F<sub>1</sub>(<span class="emphasis"><em>a</em></span>, -<span class="emphasis"><em>b</em></span>,
<span class="emphasis"><em>z</em></span>) / <sub>1</sub>F<sub>1</sub>(<span class="emphasis"><em>a</em></span>, 1-<span class="emphasis"><em>b</em></span>,
<span class="emphasis"><em>z</em></span>) and then normalize either by iterating forwards on
<span class="emphasis"><em>b</em></span> until <span class="emphasis"><em>b &gt; 0</em></span> and comparison
with a reference value, or by using the Wronskian
</p>
<div class="blockquote"><blockquote class="blockquote"><p>
<span class="inlinemediaobject"><object type="image/svg+xml" data="../../../equations/hypergeometric_1f1_11.svg" width="564" height="33"></object></span>
</p></blockquote></div>
<p>
which is of course the well known Miller's method <a class="link" href="hypergeometric_refs.html" title="Hypergeometric References">(12)</a>.
</p>
<p>
Unfortunately, stable forwards recursion on <span class="emphasis"><em>b</em></span> is stable
only for <span class="emphasis"><em>|b| &lt;&lt; |z|</em></span>, as <span class="emphasis"><em>|b|</em></span>
increases in magnitude it passes through a region where recursion is unstable
in both directions before eventually becoming stable in the backwards direction
(at least for a while!). This transition is moderated not by a change of
sign in the recurrence coefficients themselves, but by a change in the behaviour
of the <span class="emphasis"><em>values</em></span> of <sub>1</sub>F<sub>1</sub> - from alternating in sign when
<span class="emphasis"><em>|b|</em></span> is small to having the same sign when <span class="emphasis"><em>b</em></span>
is larger. During the actual transition, <sub>1</sub>F<sub>1</sub> will either pass through a zero
or a minima depending on whether b is even or odd (if there is a minima at
<sub>1</sub>F<sub>1</sub>(a, b, z) then there is necessarily a zero at <sub>1</sub>F<sub>1</sub>(a+1, b+1, z) as per
the <a href="https://dlmf.nist.gov/13.3#E15" target="_top">derivative of the function</a>).
As a result the behaviour of the recurrence relations is almost impossible
to reason about in this area, and we are left to using heuristic based approaches
to "guess" which region we are in.
</p>
<p>
In this implementation we use recurrence relations as follows:
</p>
<p>
For <span class="emphasis"><em>a,b,z &gt; 0</em></span> and large we can either:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Make <span class="emphasis"><em>0 &lt; a &lt; 1</em></span> and <span class="emphasis"><em>b &gt; z</em></span>
and evaluate the defining series directly, or
</li>
<li class="listitem">
The gamma function approximation has decent convergence and accuracy
for <span class="emphasis"><em>2b - 1 &lt; a &lt; 2b &lt; z</em></span>, so we can move
<span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span> into this region, or
</li>
<li class="listitem">
We can recurse on <span class="emphasis"><em>b</em></span> alone so that <span class="emphasis"><em>b-1
&lt; a &lt; b</em></span> and use A&amp;S 13.3.6 as long as <span class="emphasis"><em>z</em></span>
is not too large.
</li>
</ul></div>
<p>
For <span class="emphasis"><em>b &lt; 0</em></span> and <span class="emphasis"><em>a</em></span> tiny we would
normally use A&amp;S 13.3.6, but when that is non-convergent for some inputs
we can use the forward recurrence relation on <span class="emphasis"><em>b</em></span> to calculate
the ratio <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a, -b, z)/<sub>1</sub>F<sub>1</sub>(a, 1-b, z)</em></span> and then iterate
forwards until <span class="emphasis"><em>b &gt; 0</em></span> and compute a reference value
and normalize (Millers Method). In the same domain when <span class="emphasis"><em>b</em></span>
is near -1 we can use a single backwards recursion on <span class="emphasis"><em>b</em></span>
to compute <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a, -b, z)</em></span> from <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a, 2-b,
z)</em></span> and <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(<span class="emphasis"><em>a</em></span>, 1-<span class="emphasis"><em>b</em></span>,
<span class="emphasis"><em>z</em></span>)</em></span> even though technically we are recursing
in the unstable direction.
</p>
<p>
For <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(-N, b, z)</em></span> and integer <span class="emphasis"><em>N</em></span>
then backwards recursion from <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(0, b, z)</em></span> and <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(-1,
b, z)</em></span> works well.
</p>
<p>
For <span class="emphasis"><em>a</em></span> or <span class="emphasis"><em>b</em></span> &lt; 0 and if all the
direct methods have failed, then we use various fallbacks:
</p>
<p>
For <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(-a, b, z)</em></span> we can use backwards recursion on
<span class="emphasis"><em>a</em></span> as long as <span class="emphasis"><em>b &gt; z</em></span>, otherwise
a more complex scheme is required which starts from <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(-a + N,
b + M, z)</em></span>, and recurses backwards in up to 3 stages: first on
<span class="emphasis"><em>a</em></span>, then on <span class="emphasis"><em>a</em></span> and <span class="emphasis"><em>b</em></span>
together, and finally on <span class="emphasis"><em>b</em></span> alone.
</p>
<p>
For <span class="emphasis"><em>b &lt; 0</em></span> we have no good methods in some domains
(see the unsolved issues above). However in some circumstances we can either
use:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
3-stage backwards recursion on both <span class="emphasis"><em>a</em></span>, <span class="emphasis"><em>a</em></span>
and <span class="emphasis"><em>b</em></span> and then <span class="emphasis"><em>b</em></span> as above.
</li>
<li class="listitem">
Calculate the ratio <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a, b, z) / <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a-1, b-1,
z)</em></span></em></span> via backwards recurrence when z is small, and
then normalize via the Wronskian above (Miller's method).
</li>
<li class="listitem">
Calculate the ratio <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a, b, z) / <span class="emphasis"><em><sub>1</sub>F<sub>1</sub>(a+1, b+1,
z)</em></span></em></span> via forwards recurrence when z is large, and
then normalize by iterating until b &gt; 1 and comparing to a reference
value.
</li>
</ul></div>
<p>
The latter two methods use a lookup table to determine whether inputs are
in either of the domains or neither. Unfortunately the methods are basically
limited to double precision: calculation of the ratios require iteration
<span class="emphasis"><em>towards</em></span> the no-mans-land between the two methods where
iteration is unstable in both directions. As a result, only low-precision
results which require few iterations to calculate the ratio are available.
</p>
<p>
If all else fails, then we use a checked series summation which will raise
an <a class="link" href="../error_handling.html#math_toolkit.error_handling.evaluation_error">evaluation_error</a>
if more than half the digits are destroyed by cancellation.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2006-2019 Nikhar
Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Matthew Pulver, Johan
R&#229;de, Gautam Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg,
Daryle Walker and Xiaogang Zhang<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="hypergeometric_2f0.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../hypergeometric.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="hypergeometric_pfq.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>