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