xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/tr1/modified_bessel_func.tcc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // Special functions -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2006, 2007, 2008, 2009, 2010
4*e4b17023SJohn Marino // Free Software Foundation, Inc.
5*e4b17023SJohn Marino //
6*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
7*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
8*e4b17023SJohn Marino // terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino // any later version.
11*e4b17023SJohn Marino //
12*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*e4b17023SJohn Marino // GNU General Public License for more details.
16*e4b17023SJohn Marino //
17*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
18*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
19*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
22*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
23*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino /** @file tr1/modified_bessel_func.tcc
27*e4b17023SJohn Marino  *  This is an internal header file, included by other library headers.
28*e4b17023SJohn Marino  *  Do not attempt to use it directly. @headername{tr1/cmath}
29*e4b17023SJohn Marino  */
30*e4b17023SJohn Marino 
31*e4b17023SJohn Marino //
32*e4b17023SJohn Marino // ISO C++ 14882 TR1: 5.2  Special functions
33*e4b17023SJohn Marino //
34*e4b17023SJohn Marino 
35*e4b17023SJohn Marino // Written by Edward Smith-Rowland.
36*e4b17023SJohn Marino //
37*e4b17023SJohn Marino // References:
38*e4b17023SJohn Marino //   (1) Handbook of Mathematical Functions,
39*e4b17023SJohn Marino //       Ed. Milton Abramowitz and Irene A. Stegun,
40*e4b17023SJohn Marino //       Dover Publications,
41*e4b17023SJohn Marino //       Section 9, pp. 355-434, Section 10 pp. 435-478
42*e4b17023SJohn Marino //   (2) The Gnu Scientific Library, http://www.gnu.org/software/gsl
43*e4b17023SJohn Marino //   (3) Numerical Recipes in C, by W. H. Press, S. A. Teukolsky,
44*e4b17023SJohn Marino //       W. T. Vetterling, B. P. Flannery, Cambridge University Press (1992),
45*e4b17023SJohn Marino //       2nd ed, pp. 246-249.
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino #ifndef _GLIBCXX_TR1_MODIFIED_BESSEL_FUNC_TCC
48*e4b17023SJohn Marino #define _GLIBCXX_TR1_MODIFIED_BESSEL_FUNC_TCC 1
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino #include "special_function_util.h"
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default)
53*e4b17023SJohn Marino {
54*e4b17023SJohn Marino namespace tr1
55*e4b17023SJohn Marino {
56*e4b17023SJohn Marino   // [5.2] Special functions
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino   // Implementation-space details.
59*e4b17023SJohn Marino   namespace __detail
60*e4b17023SJohn Marino   {
61*e4b17023SJohn Marino   _GLIBCXX_BEGIN_NAMESPACE_VERSION
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino     /**
64*e4b17023SJohn Marino      *   @brief  Compute the modified Bessel functions @f$ I_\nu(x) @f$ and
65*e4b17023SJohn Marino      *           @f$ K_\nu(x) @f$ and their first derivatives
66*e4b17023SJohn Marino      *           @f$ I'_\nu(x) @f$ and @f$ K'_\nu(x) @f$ respectively.
67*e4b17023SJohn Marino      *           These four functions are computed together for numerical
68*e4b17023SJohn Marino      *           stability.
69*e4b17023SJohn Marino      *
70*e4b17023SJohn Marino      *   @param  __nu  The order of the Bessel functions.
71*e4b17023SJohn Marino      *   @param  __x   The argument of the Bessel functions.
72*e4b17023SJohn Marino      *   @param  __Inu  The output regular modified Bessel function.
73*e4b17023SJohn Marino      *   @param  __Knu  The output irregular modified Bessel function.
74*e4b17023SJohn Marino      *   @param  __Ipnu  The output derivative of the regular
75*e4b17023SJohn Marino      *                   modified Bessel function.
76*e4b17023SJohn Marino      *   @param  __Kpnu  The output derivative of the irregular
77*e4b17023SJohn Marino      *                   modified Bessel function.
78*e4b17023SJohn Marino      */
79*e4b17023SJohn Marino     template <typename _Tp>
80*e4b17023SJohn Marino     void
__bessel_ik(const _Tp __nu,const _Tp __x,_Tp & __Inu,_Tp & __Knu,_Tp & __Ipnu,_Tp & __Kpnu)81*e4b17023SJohn Marino     __bessel_ik(const _Tp __nu, const _Tp __x,
82*e4b17023SJohn Marino                 _Tp & __Inu, _Tp & __Knu, _Tp & __Ipnu, _Tp & __Kpnu)
83*e4b17023SJohn Marino     {
84*e4b17023SJohn Marino       if (__x == _Tp(0))
85*e4b17023SJohn Marino         {
86*e4b17023SJohn Marino           if (__nu == _Tp(0))
87*e4b17023SJohn Marino             {
88*e4b17023SJohn Marino               __Inu = _Tp(1);
89*e4b17023SJohn Marino               __Ipnu = _Tp(0);
90*e4b17023SJohn Marino             }
91*e4b17023SJohn Marino           else if (__nu == _Tp(1))
92*e4b17023SJohn Marino             {
93*e4b17023SJohn Marino               __Inu = _Tp(0);
94*e4b17023SJohn Marino               __Ipnu = _Tp(0.5L);
95*e4b17023SJohn Marino             }
96*e4b17023SJohn Marino           else
97*e4b17023SJohn Marino             {
98*e4b17023SJohn Marino               __Inu = _Tp(0);
99*e4b17023SJohn Marino               __Ipnu = _Tp(0);
100*e4b17023SJohn Marino             }
101*e4b17023SJohn Marino           __Knu = std::numeric_limits<_Tp>::infinity();
102*e4b17023SJohn Marino           __Kpnu = -std::numeric_limits<_Tp>::infinity();
103*e4b17023SJohn Marino           return;
104*e4b17023SJohn Marino         }
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino       const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
107*e4b17023SJohn Marino       const _Tp __fp_min = _Tp(10) * std::numeric_limits<_Tp>::epsilon();
108*e4b17023SJohn Marino       const int __max_iter = 15000;
109*e4b17023SJohn Marino       const _Tp __x_min = _Tp(2);
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino       const int __nl = static_cast<int>(__nu + _Tp(0.5L));
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino       const _Tp __mu = __nu - __nl;
114*e4b17023SJohn Marino       const _Tp __mu2 = __mu * __mu;
115*e4b17023SJohn Marino       const _Tp __xi = _Tp(1) / __x;
116*e4b17023SJohn Marino       const _Tp __xi2 = _Tp(2) * __xi;
117*e4b17023SJohn Marino       _Tp __h = __nu * __xi;
118*e4b17023SJohn Marino       if ( __h < __fp_min )
119*e4b17023SJohn Marino         __h = __fp_min;
120*e4b17023SJohn Marino       _Tp __b = __xi2 * __nu;
121*e4b17023SJohn Marino       _Tp __d = _Tp(0);
122*e4b17023SJohn Marino       _Tp __c = __h;
123*e4b17023SJohn Marino       int __i;
124*e4b17023SJohn Marino       for ( __i = 1; __i <= __max_iter; ++__i )
125*e4b17023SJohn Marino         {
126*e4b17023SJohn Marino           __b += __xi2;
127*e4b17023SJohn Marino           __d = _Tp(1) / (__b + __d);
128*e4b17023SJohn Marino           __c = __b + _Tp(1) / __c;
129*e4b17023SJohn Marino           const _Tp __del = __c * __d;
130*e4b17023SJohn Marino           __h *= __del;
131*e4b17023SJohn Marino           if (std::abs(__del - _Tp(1)) < __eps)
132*e4b17023SJohn Marino             break;
133*e4b17023SJohn Marino         }
134*e4b17023SJohn Marino       if (__i > __max_iter)
135*e4b17023SJohn Marino         std::__throw_runtime_error(__N("Argument x too large "
136*e4b17023SJohn Marino                                        "in __bessel_jn; "
137*e4b17023SJohn Marino                                        "try asymptotic expansion."));
138*e4b17023SJohn Marino       _Tp __Inul = __fp_min;
139*e4b17023SJohn Marino       _Tp __Ipnul = __h * __Inul;
140*e4b17023SJohn Marino       _Tp __Inul1 = __Inul;
141*e4b17023SJohn Marino       _Tp __Ipnu1 = __Ipnul;
142*e4b17023SJohn Marino       _Tp __fact = __nu * __xi;
143*e4b17023SJohn Marino       for (int __l = __nl; __l >= 1; --__l)
144*e4b17023SJohn Marino         {
145*e4b17023SJohn Marino           const _Tp __Inutemp = __fact * __Inul + __Ipnul;
146*e4b17023SJohn Marino           __fact -= __xi;
147*e4b17023SJohn Marino           __Ipnul = __fact * __Inutemp + __Inul;
148*e4b17023SJohn Marino           __Inul = __Inutemp;
149*e4b17023SJohn Marino         }
150*e4b17023SJohn Marino       _Tp __f = __Ipnul / __Inul;
151*e4b17023SJohn Marino       _Tp __Kmu, __Knu1;
152*e4b17023SJohn Marino       if (__x < __x_min)
153*e4b17023SJohn Marino         {
154*e4b17023SJohn Marino           const _Tp __x2 = __x / _Tp(2);
155*e4b17023SJohn Marino           const _Tp __pimu = __numeric_constants<_Tp>::__pi() * __mu;
156*e4b17023SJohn Marino           const _Tp __fact = (std::abs(__pimu) < __eps
157*e4b17023SJohn Marino                             ? _Tp(1) : __pimu / std::sin(__pimu));
158*e4b17023SJohn Marino           _Tp __d = -std::log(__x2);
159*e4b17023SJohn Marino           _Tp __e = __mu * __d;
160*e4b17023SJohn Marino           const _Tp __fact2 = (std::abs(__e) < __eps
161*e4b17023SJohn Marino                             ? _Tp(1) : std::sinh(__e) / __e);
162*e4b17023SJohn Marino           _Tp __gam1, __gam2, __gampl, __gammi;
163*e4b17023SJohn Marino           __gamma_temme(__mu, __gam1, __gam2, __gampl, __gammi);
164*e4b17023SJohn Marino           _Tp __ff = __fact
165*e4b17023SJohn Marino                    * (__gam1 * std::cosh(__e) + __gam2 * __fact2 * __d);
166*e4b17023SJohn Marino           _Tp __sum = __ff;
167*e4b17023SJohn Marino           __e = std::exp(__e);
168*e4b17023SJohn Marino           _Tp __p = __e / (_Tp(2) * __gampl);
169*e4b17023SJohn Marino           _Tp __q = _Tp(1) / (_Tp(2) * __e * __gammi);
170*e4b17023SJohn Marino           _Tp __c = _Tp(1);
171*e4b17023SJohn Marino           __d = __x2 * __x2;
172*e4b17023SJohn Marino           _Tp __sum1 = __p;
173*e4b17023SJohn Marino           int __i;
174*e4b17023SJohn Marino           for (__i = 1; __i <= __max_iter; ++__i)
175*e4b17023SJohn Marino             {
176*e4b17023SJohn Marino               __ff = (__i * __ff + __p + __q) / (__i * __i - __mu2);
177*e4b17023SJohn Marino               __c *= __d / __i;
178*e4b17023SJohn Marino               __p /= __i - __mu;
179*e4b17023SJohn Marino               __q /= __i + __mu;
180*e4b17023SJohn Marino               const _Tp __del = __c * __ff;
181*e4b17023SJohn Marino               __sum += __del;
182*e4b17023SJohn Marino               const _Tp __del1 = __c * (__p - __i * __ff);
183*e4b17023SJohn Marino               __sum1 += __del1;
184*e4b17023SJohn Marino               if (std::abs(__del) < __eps * std::abs(__sum))
185*e4b17023SJohn Marino                 break;
186*e4b17023SJohn Marino             }
187*e4b17023SJohn Marino           if (__i > __max_iter)
188*e4b17023SJohn Marino             std::__throw_runtime_error(__N("Bessel k series failed to converge "
189*e4b17023SJohn Marino                                            "in __bessel_jn."));
190*e4b17023SJohn Marino           __Kmu = __sum;
191*e4b17023SJohn Marino           __Knu1 = __sum1 * __xi2;
192*e4b17023SJohn Marino         }
193*e4b17023SJohn Marino       else
194*e4b17023SJohn Marino         {
195*e4b17023SJohn Marino           _Tp __b = _Tp(2) * (_Tp(1) + __x);
196*e4b17023SJohn Marino           _Tp __d = _Tp(1) / __b;
197*e4b17023SJohn Marino           _Tp __delh = __d;
198*e4b17023SJohn Marino           _Tp __h = __delh;
199*e4b17023SJohn Marino           _Tp __q1 = _Tp(0);
200*e4b17023SJohn Marino           _Tp __q2 = _Tp(1);
201*e4b17023SJohn Marino           _Tp __a1 = _Tp(0.25L) - __mu2;
202*e4b17023SJohn Marino           _Tp __q = __c = __a1;
203*e4b17023SJohn Marino           _Tp __a = -__a1;
204*e4b17023SJohn Marino           _Tp __s = _Tp(1) + __q * __delh;
205*e4b17023SJohn Marino           int __i;
206*e4b17023SJohn Marino           for (__i = 2; __i <= __max_iter; ++__i)
207*e4b17023SJohn Marino             {
208*e4b17023SJohn Marino               __a -= 2 * (__i - 1);
209*e4b17023SJohn Marino               __c = -__a * __c / __i;
210*e4b17023SJohn Marino               const _Tp __qnew = (__q1 - __b * __q2) / __a;
211*e4b17023SJohn Marino               __q1 = __q2;
212*e4b17023SJohn Marino               __q2 = __qnew;
213*e4b17023SJohn Marino               __q += __c * __qnew;
214*e4b17023SJohn Marino               __b += _Tp(2);
215*e4b17023SJohn Marino               __d = _Tp(1) / (__b + __a * __d);
216*e4b17023SJohn Marino               __delh = (__b * __d - _Tp(1)) * __delh;
217*e4b17023SJohn Marino               __h += __delh;
218*e4b17023SJohn Marino               const _Tp __dels = __q * __delh;
219*e4b17023SJohn Marino               __s += __dels;
220*e4b17023SJohn Marino               if ( std::abs(__dels / __s) < __eps )
221*e4b17023SJohn Marino                 break;
222*e4b17023SJohn Marino             }
223*e4b17023SJohn Marino           if (__i > __max_iter)
224*e4b17023SJohn Marino             std::__throw_runtime_error(__N("Steed's method failed "
225*e4b17023SJohn Marino                                            "in __bessel_jn."));
226*e4b17023SJohn Marino           __h = __a1 * __h;
227*e4b17023SJohn Marino           __Kmu = std::sqrt(__numeric_constants<_Tp>::__pi() / (_Tp(2) * __x))
228*e4b17023SJohn Marino                 * std::exp(-__x) / __s;
229*e4b17023SJohn Marino           __Knu1 = __Kmu * (__mu + __x + _Tp(0.5L) - __h) * __xi;
230*e4b17023SJohn Marino         }
231*e4b17023SJohn Marino 
232*e4b17023SJohn Marino       _Tp __Kpmu = __mu * __xi * __Kmu - __Knu1;
233*e4b17023SJohn Marino       _Tp __Inumu = __xi / (__f * __Kmu - __Kpmu);
234*e4b17023SJohn Marino       __Inu = __Inumu * __Inul1 / __Inul;
235*e4b17023SJohn Marino       __Ipnu = __Inumu * __Ipnu1 / __Inul;
236*e4b17023SJohn Marino       for ( __i = 1; __i <= __nl; ++__i )
237*e4b17023SJohn Marino         {
238*e4b17023SJohn Marino           const _Tp __Knutemp = (__mu + __i) * __xi2 * __Knu1 + __Kmu;
239*e4b17023SJohn Marino           __Kmu = __Knu1;
240*e4b17023SJohn Marino           __Knu1 = __Knutemp;
241*e4b17023SJohn Marino         }
242*e4b17023SJohn Marino       __Knu = __Kmu;
243*e4b17023SJohn Marino       __Kpnu = __nu * __xi * __Kmu - __Knu1;
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino       return;
246*e4b17023SJohn Marino     }
247*e4b17023SJohn Marino 
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino     /**
250*e4b17023SJohn Marino      *   @brief  Return the regular modified Bessel function of order
251*e4b17023SJohn Marino      *           \f$ \nu \f$: \f$ I_{\nu}(x) \f$.
252*e4b17023SJohn Marino      *
253*e4b17023SJohn Marino      *   The regular modified cylindrical Bessel function is:
254*e4b17023SJohn Marino      *   @f[
255*e4b17023SJohn Marino      *    I_{\nu}(x) = \sum_{k=0}^{\infty}
256*e4b17023SJohn Marino      *              \frac{(x/2)^{\nu + 2k}}{k!\Gamma(\nu+k+1)}
257*e4b17023SJohn Marino      *   @f]
258*e4b17023SJohn Marino      *
259*e4b17023SJohn Marino      *   @param  __nu  The order of the regular modified Bessel function.
260*e4b17023SJohn Marino      *   @param  __x   The argument of the regular modified Bessel function.
261*e4b17023SJohn Marino      *   @return  The output regular modified Bessel function.
262*e4b17023SJohn Marino      */
263*e4b17023SJohn Marino     template<typename _Tp>
264*e4b17023SJohn Marino     _Tp
__cyl_bessel_i(const _Tp __nu,const _Tp __x)265*e4b17023SJohn Marino     __cyl_bessel_i(const _Tp __nu, const _Tp __x)
266*e4b17023SJohn Marino     {
267*e4b17023SJohn Marino       if (__nu < _Tp(0) || __x < _Tp(0))
268*e4b17023SJohn Marino         std::__throw_domain_error(__N("Bad argument "
269*e4b17023SJohn Marino                                       "in __cyl_bessel_i."));
270*e4b17023SJohn Marino       else if (__isnan(__nu) || __isnan(__x))
271*e4b17023SJohn Marino         return std::numeric_limits<_Tp>::quiet_NaN();
272*e4b17023SJohn Marino       else if (__x * __x < _Tp(10) * (__nu + _Tp(1)))
273*e4b17023SJohn Marino         return __cyl_bessel_ij_series(__nu, __x, +_Tp(1), 200);
274*e4b17023SJohn Marino       else
275*e4b17023SJohn Marino         {
276*e4b17023SJohn Marino           _Tp __I_nu, __K_nu, __Ip_nu, __Kp_nu;
277*e4b17023SJohn Marino           __bessel_ik(__nu, __x, __I_nu, __K_nu, __Ip_nu, __Kp_nu);
278*e4b17023SJohn Marino           return __I_nu;
279*e4b17023SJohn Marino         }
280*e4b17023SJohn Marino     }
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino 
283*e4b17023SJohn Marino     /**
284*e4b17023SJohn Marino      *   @brief  Return the irregular modified Bessel function
285*e4b17023SJohn Marino      *           \f$ K_{\nu}(x) \f$ of order \f$ \nu \f$.
286*e4b17023SJohn Marino      *
287*e4b17023SJohn Marino      *   The irregular modified Bessel function is defined by:
288*e4b17023SJohn Marino      *   @f[
289*e4b17023SJohn Marino      *      K_{\nu}(x) = \frac{\pi}{2}
290*e4b17023SJohn Marino      *                   \frac{I_{-\nu}(x) - I_{\nu}(x)}{\sin \nu\pi}
291*e4b17023SJohn Marino      *   @f]
292*e4b17023SJohn Marino      *   where for integral \f$ \nu = n \f$ a limit is taken:
293*e4b17023SJohn Marino      *   \f$ lim_{\nu \to n} \f$.
294*e4b17023SJohn Marino      *
295*e4b17023SJohn Marino      *   @param  __nu  The order of the irregular modified Bessel function.
296*e4b17023SJohn Marino      *   @param  __x   The argument of the irregular modified Bessel function.
297*e4b17023SJohn Marino      *   @return  The output irregular modified Bessel function.
298*e4b17023SJohn Marino      */
299*e4b17023SJohn Marino     template<typename _Tp>
300*e4b17023SJohn Marino     _Tp
__cyl_bessel_k(const _Tp __nu,const _Tp __x)301*e4b17023SJohn Marino     __cyl_bessel_k(const _Tp __nu, const _Tp __x)
302*e4b17023SJohn Marino     {
303*e4b17023SJohn Marino       if (__nu < _Tp(0) || __x < _Tp(0))
304*e4b17023SJohn Marino         std::__throw_domain_error(__N("Bad argument "
305*e4b17023SJohn Marino                                       "in __cyl_bessel_k."));
306*e4b17023SJohn Marino       else if (__isnan(__nu) || __isnan(__x))
307*e4b17023SJohn Marino         return std::numeric_limits<_Tp>::quiet_NaN();
308*e4b17023SJohn Marino       else
309*e4b17023SJohn Marino         {
310*e4b17023SJohn Marino           _Tp __I_nu, __K_nu, __Ip_nu, __Kp_nu;
311*e4b17023SJohn Marino           __bessel_ik(__nu, __x, __I_nu, __K_nu, __Ip_nu, __Kp_nu);
312*e4b17023SJohn Marino           return __K_nu;
313*e4b17023SJohn Marino         }
314*e4b17023SJohn Marino     }
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino     /**
318*e4b17023SJohn Marino      *   @brief  Compute the spherical modified Bessel functions
319*e4b17023SJohn Marino      *           @f$ i_n(x) @f$ and @f$ k_n(x) @f$ and their first
320*e4b17023SJohn Marino      *           derivatives @f$ i'_n(x) @f$ and @f$ k'_n(x) @f$
321*e4b17023SJohn Marino      *           respectively.
322*e4b17023SJohn Marino      *
323*e4b17023SJohn Marino      *   @param  __n  The order of the modified spherical Bessel function.
324*e4b17023SJohn Marino      *   @param  __x  The argument of the modified spherical Bessel function.
325*e4b17023SJohn Marino      *   @param  __i_n  The output regular modified spherical Bessel function.
326*e4b17023SJohn Marino      *   @param  __k_n  The output irregular modified spherical
327*e4b17023SJohn Marino      *                  Bessel function.
328*e4b17023SJohn Marino      *   @param  __ip_n  The output derivative of the regular modified
329*e4b17023SJohn Marino      *                   spherical Bessel function.
330*e4b17023SJohn Marino      *   @param  __kp_n  The output derivative of the irregular modified
331*e4b17023SJohn Marino      *                   spherical Bessel function.
332*e4b17023SJohn Marino      */
333*e4b17023SJohn Marino     template <typename _Tp>
334*e4b17023SJohn Marino     void
__sph_bessel_ik(const unsigned int __n,const _Tp __x,_Tp & __i_n,_Tp & __k_n,_Tp & __ip_n,_Tp & __kp_n)335*e4b17023SJohn Marino     __sph_bessel_ik(const unsigned int __n, const _Tp __x,
336*e4b17023SJohn Marino                     _Tp & __i_n, _Tp & __k_n, _Tp & __ip_n, _Tp & __kp_n)
337*e4b17023SJohn Marino     {
338*e4b17023SJohn Marino       const _Tp __nu = _Tp(__n) + _Tp(0.5L);
339*e4b17023SJohn Marino 
340*e4b17023SJohn Marino       _Tp __I_nu, __Ip_nu, __K_nu, __Kp_nu;
341*e4b17023SJohn Marino       __bessel_ik(__nu, __x, __I_nu, __K_nu, __Ip_nu, __Kp_nu);
342*e4b17023SJohn Marino 
343*e4b17023SJohn Marino       const _Tp __factor = __numeric_constants<_Tp>::__sqrtpio2()
344*e4b17023SJohn Marino                          / std::sqrt(__x);
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino       __i_n = __factor * __I_nu;
347*e4b17023SJohn Marino       __k_n = __factor * __K_nu;
348*e4b17023SJohn Marino       __ip_n = __factor * __Ip_nu - __i_n / (_Tp(2) * __x);
349*e4b17023SJohn Marino       __kp_n = __factor * __Kp_nu - __k_n / (_Tp(2) * __x);
350*e4b17023SJohn Marino 
351*e4b17023SJohn Marino       return;
352*e4b17023SJohn Marino     }
353*e4b17023SJohn Marino 
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino     /**
356*e4b17023SJohn Marino      *   @brief  Compute the Airy functions
357*e4b17023SJohn Marino      *           @f$ Ai(x) @f$ and @f$ Bi(x) @f$ and their first
358*e4b17023SJohn Marino      *           derivatives @f$ Ai'(x) @f$ and @f$ Bi(x) @f$
359*e4b17023SJohn Marino      *           respectively.
360*e4b17023SJohn Marino      *
361*e4b17023SJohn Marino      *   @param  __n  The order of the Airy functions.
362*e4b17023SJohn Marino      *   @param  __x  The argument of the Airy functions.
363*e4b17023SJohn Marino      *   @param  __i_n  The output Airy function.
364*e4b17023SJohn Marino      *   @param  __k_n  The output Airy function.
365*e4b17023SJohn Marino      *   @param  __ip_n  The output derivative of the Airy function.
366*e4b17023SJohn Marino      *   @param  __kp_n  The output derivative of the Airy function.
367*e4b17023SJohn Marino      */
368*e4b17023SJohn Marino     template <typename _Tp>
369*e4b17023SJohn Marino     void
__airy(const _Tp __x,_Tp & __Ai,_Tp & __Bi,_Tp & __Aip,_Tp & __Bip)370*e4b17023SJohn Marino     __airy(const _Tp __x,
371*e4b17023SJohn Marino            _Tp & __Ai, _Tp & __Bi, _Tp & __Aip, _Tp & __Bip)
372*e4b17023SJohn Marino     {
373*e4b17023SJohn Marino       const _Tp __absx = std::abs(__x);
374*e4b17023SJohn Marino       const _Tp __rootx = std::sqrt(__absx);
375*e4b17023SJohn Marino       const _Tp __z = _Tp(2) * __absx * __rootx / _Tp(3);
376*e4b17023SJohn Marino 
377*e4b17023SJohn Marino       if (__isnan(__x))
378*e4b17023SJohn Marino         return std::numeric_limits<_Tp>::quiet_NaN();
379*e4b17023SJohn Marino       else if (__x > _Tp(0))
380*e4b17023SJohn Marino         {
381*e4b17023SJohn Marino           _Tp __I_nu, __Ip_nu, __K_nu, __Kp_nu;
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino           __bessel_ik(_Tp(1) / _Tp(3), __z, __I_nu, __K_nu, __Ip_nu, __Kp_nu);
384*e4b17023SJohn Marino           __Ai = __rootx * __K_nu
385*e4b17023SJohn Marino                / (__numeric_constants<_Tp>::__sqrt3()
386*e4b17023SJohn Marino                 * __numeric_constants<_Tp>::__pi());
387*e4b17023SJohn Marino           __Bi = __rootx * (__K_nu / __numeric_constants<_Tp>::__pi()
388*e4b17023SJohn Marino                  + _Tp(2) * __I_nu / __numeric_constants<_Tp>::__sqrt3());
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino           __bessel_ik(_Tp(2) / _Tp(3), __z, __I_nu, __K_nu, __Ip_nu, __Kp_nu);
391*e4b17023SJohn Marino           __Aip = -__x * __K_nu
392*e4b17023SJohn Marino                 / (__numeric_constants<_Tp>::__sqrt3()
393*e4b17023SJohn Marino                  * __numeric_constants<_Tp>::__pi());
394*e4b17023SJohn Marino           __Bip = __x * (__K_nu / __numeric_constants<_Tp>::__pi()
395*e4b17023SJohn Marino                       + _Tp(2) * __I_nu
396*e4b17023SJohn Marino                       / __numeric_constants<_Tp>::__sqrt3());
397*e4b17023SJohn Marino         }
398*e4b17023SJohn Marino       else if (__x < _Tp(0))
399*e4b17023SJohn Marino         {
400*e4b17023SJohn Marino           _Tp __J_nu, __Jp_nu, __N_nu, __Np_nu;
401*e4b17023SJohn Marino 
402*e4b17023SJohn Marino           __bessel_jn(_Tp(1) / _Tp(3), __z, __J_nu, __N_nu, __Jp_nu, __Np_nu);
403*e4b17023SJohn Marino           __Ai = __rootx * (__J_nu
404*e4b17023SJohn Marino                     - __N_nu / __numeric_constants<_Tp>::__sqrt3()) / _Tp(2);
405*e4b17023SJohn Marino           __Bi = -__rootx * (__N_nu
406*e4b17023SJohn Marino                     + __J_nu / __numeric_constants<_Tp>::__sqrt3()) / _Tp(2);
407*e4b17023SJohn Marino 
408*e4b17023SJohn Marino           __bessel_jn(_Tp(2) / _Tp(3), __z, __J_nu, __N_nu, __Jp_nu, __Np_nu);
409*e4b17023SJohn Marino           __Aip = __absx * (__N_nu / __numeric_constants<_Tp>::__sqrt3()
410*e4b17023SJohn Marino                           + __J_nu) / _Tp(2);
411*e4b17023SJohn Marino           __Bip = __absx * (__J_nu / __numeric_constants<_Tp>::__sqrt3()
412*e4b17023SJohn Marino                           - __N_nu) / _Tp(2);
413*e4b17023SJohn Marino         }
414*e4b17023SJohn Marino       else
415*e4b17023SJohn Marino         {
416*e4b17023SJohn Marino           //  Reference:
417*e4b17023SJohn Marino           //    Abramowitz & Stegun, page 446 section 10.4.4 on Airy functions.
418*e4b17023SJohn Marino           //  The number is Ai(0) = 3^{-2/3}/\Gamma(2/3).
419*e4b17023SJohn Marino           __Ai = _Tp(0.35502805388781723926L);
420*e4b17023SJohn Marino           __Bi = __Ai * __numeric_constants<_Tp>::__sqrt3();
421*e4b17023SJohn Marino 
422*e4b17023SJohn Marino           //  Reference:
423*e4b17023SJohn Marino           //    Abramowitz & Stegun, page 446 section 10.4.5 on Airy functions.
424*e4b17023SJohn Marino           //  The number is Ai'(0) = -3^{-1/3}/\Gamma(1/3).
425*e4b17023SJohn Marino           __Aip = -_Tp(0.25881940379280679840L);
426*e4b17023SJohn Marino           __Bip = -__Aip * __numeric_constants<_Tp>::__sqrt3();
427*e4b17023SJohn Marino         }
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino       return;
430*e4b17023SJohn Marino     }
431*e4b17023SJohn Marino 
432*e4b17023SJohn Marino   _GLIBCXX_END_NAMESPACE_VERSION
433*e4b17023SJohn Marino   } // namespace std::tr1::__detail
434*e4b17023SJohn Marino }
435*e4b17023SJohn Marino }
436*e4b17023SJohn Marino 
437*e4b17023SJohn Marino #endif // _GLIBCXX_TR1_MODIFIED_BESSEL_FUNC_TCC
438