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/exp_integral.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 based on: 36*e4b17023SJohn Marino // 37*e4b17023SJohn Marino // (1) Handbook of Mathematical Functions, 38*e4b17023SJohn Marino // Ed. by Milton Abramowitz and Irene A. Stegun, 39*e4b17023SJohn Marino // Dover Publications, New-York, Section 5, pp. 228-251. 40*e4b17023SJohn Marino // (2) The Gnu Scientific Library, http://www.gnu.org/software/gsl 41*e4b17023SJohn Marino // (3) Numerical Recipes in C, by W. H. Press, S. A. Teukolsky, 42*e4b17023SJohn Marino // W. T. Vetterling, B. P. Flannery, Cambridge University Press (1992), 43*e4b17023SJohn Marino // 2nd ed, pp. 222-225. 44*e4b17023SJohn Marino // 45*e4b17023SJohn Marino 46*e4b17023SJohn Marino #ifndef _GLIBCXX_TR1_EXP_INTEGRAL_TCC 47*e4b17023SJohn Marino #define _GLIBCXX_TR1_EXP_INTEGRAL_TCC 1 48*e4b17023SJohn Marino 49*e4b17023SJohn Marino #include "special_function_util.h" 50*e4b17023SJohn Marino 51*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default) 52*e4b17023SJohn Marino { 53*e4b17023SJohn Marino namespace tr1 54*e4b17023SJohn Marino { 55*e4b17023SJohn Marino // [5.2] Special functions 56*e4b17023SJohn Marino 57*e4b17023SJohn Marino // Implementation-space details. 58*e4b17023SJohn Marino namespace __detail 59*e4b17023SJohn Marino { 60*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION 61*e4b17023SJohn Marino 62*e4b17023SJohn Marino template<typename _Tp> _Tp __expint_E1(const _Tp); 63*e4b17023SJohn Marino 64*e4b17023SJohn Marino /** 65*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_1(x) @f$ 66*e4b17023SJohn Marino * by series summation. This should be good 67*e4b17023SJohn Marino * for @f$ x < 1 @f$. 68*e4b17023SJohn Marino * 69*e4b17023SJohn Marino * The exponential integral is given by 70*e4b17023SJohn Marino * \f[ 71*e4b17023SJohn Marino * E_1(x) = \int_{1}^{\infty} \frac{e^{-xt}}{t} dt 72*e4b17023SJohn Marino * \f] 73*e4b17023SJohn Marino * 74*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 75*e4b17023SJohn Marino * @return The exponential integral. 76*e4b17023SJohn Marino */ 77*e4b17023SJohn Marino template<typename _Tp> 78*e4b17023SJohn Marino _Tp __expint_E1_series(const _Tp __x)79*e4b17023SJohn Marino __expint_E1_series(const _Tp __x) 80*e4b17023SJohn Marino { 81*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 82*e4b17023SJohn Marino _Tp __term = _Tp(1); 83*e4b17023SJohn Marino _Tp __esum = _Tp(0); 84*e4b17023SJohn Marino _Tp __osum = _Tp(0); 85*e4b17023SJohn Marino const unsigned int __max_iter = 100; 86*e4b17023SJohn Marino for (unsigned int __i = 1; __i < __max_iter; ++__i) 87*e4b17023SJohn Marino { 88*e4b17023SJohn Marino __term *= - __x / __i; 89*e4b17023SJohn Marino if (std::abs(__term) < __eps) 90*e4b17023SJohn Marino break; 91*e4b17023SJohn Marino if (__term >= _Tp(0)) 92*e4b17023SJohn Marino __esum += __term / __i; 93*e4b17023SJohn Marino else 94*e4b17023SJohn Marino __osum += __term / __i; 95*e4b17023SJohn Marino } 96*e4b17023SJohn Marino 97*e4b17023SJohn Marino return - __esum - __osum 98*e4b17023SJohn Marino - __numeric_constants<_Tp>::__gamma_e() - std::log(__x); 99*e4b17023SJohn Marino } 100*e4b17023SJohn Marino 101*e4b17023SJohn Marino 102*e4b17023SJohn Marino /** 103*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_1(x) @f$ 104*e4b17023SJohn Marino * by asymptotic expansion. 105*e4b17023SJohn Marino * 106*e4b17023SJohn Marino * The exponential integral is given by 107*e4b17023SJohn Marino * \f[ 108*e4b17023SJohn Marino * E_1(x) = \int_{1}^\infty \frac{e^{-xt}}{t} dt 109*e4b17023SJohn Marino * \f] 110*e4b17023SJohn Marino * 111*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 112*e4b17023SJohn Marino * @return The exponential integral. 113*e4b17023SJohn Marino */ 114*e4b17023SJohn Marino template<typename _Tp> 115*e4b17023SJohn Marino _Tp __expint_E1_asymp(const _Tp __x)116*e4b17023SJohn Marino __expint_E1_asymp(const _Tp __x) 117*e4b17023SJohn Marino { 118*e4b17023SJohn Marino _Tp __term = _Tp(1); 119*e4b17023SJohn Marino _Tp __esum = _Tp(1); 120*e4b17023SJohn Marino _Tp __osum = _Tp(0); 121*e4b17023SJohn Marino const unsigned int __max_iter = 1000; 122*e4b17023SJohn Marino for (unsigned int __i = 1; __i < __max_iter; ++__i) 123*e4b17023SJohn Marino { 124*e4b17023SJohn Marino _Tp __prev = __term; 125*e4b17023SJohn Marino __term *= - __i / __x; 126*e4b17023SJohn Marino if (std::abs(__term) > std::abs(__prev)) 127*e4b17023SJohn Marino break; 128*e4b17023SJohn Marino if (__term >= _Tp(0)) 129*e4b17023SJohn Marino __esum += __term; 130*e4b17023SJohn Marino else 131*e4b17023SJohn Marino __osum += __term; 132*e4b17023SJohn Marino } 133*e4b17023SJohn Marino 134*e4b17023SJohn Marino return std::exp(- __x) * (__esum + __osum) / __x; 135*e4b17023SJohn Marino } 136*e4b17023SJohn Marino 137*e4b17023SJohn Marino 138*e4b17023SJohn Marino /** 139*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_n(x) @f$ 140*e4b17023SJohn Marino * by series summation. 141*e4b17023SJohn Marino * 142*e4b17023SJohn Marino * The exponential integral is given by 143*e4b17023SJohn Marino * \f[ 144*e4b17023SJohn Marino * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt 145*e4b17023SJohn Marino * \f] 146*e4b17023SJohn Marino * 147*e4b17023SJohn Marino * @param __n The order of the exponential integral function. 148*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 149*e4b17023SJohn Marino * @return The exponential integral. 150*e4b17023SJohn Marino */ 151*e4b17023SJohn Marino template<typename _Tp> 152*e4b17023SJohn Marino _Tp __expint_En_series(const unsigned int __n,const _Tp __x)153*e4b17023SJohn Marino __expint_En_series(const unsigned int __n, const _Tp __x) 154*e4b17023SJohn Marino { 155*e4b17023SJohn Marino const unsigned int __max_iter = 100; 156*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 157*e4b17023SJohn Marino const int __nm1 = __n - 1; 158*e4b17023SJohn Marino _Tp __ans = (__nm1 != 0 159*e4b17023SJohn Marino ? _Tp(1) / __nm1 : -std::log(__x) 160*e4b17023SJohn Marino - __numeric_constants<_Tp>::__gamma_e()); 161*e4b17023SJohn Marino _Tp __fact = _Tp(1); 162*e4b17023SJohn Marino for (int __i = 1; __i <= __max_iter; ++__i) 163*e4b17023SJohn Marino { 164*e4b17023SJohn Marino __fact *= -__x / _Tp(__i); 165*e4b17023SJohn Marino _Tp __del; 166*e4b17023SJohn Marino if ( __i != __nm1 ) 167*e4b17023SJohn Marino __del = -__fact / _Tp(__i - __nm1); 168*e4b17023SJohn Marino else 169*e4b17023SJohn Marino { 170*e4b17023SJohn Marino _Tp __psi = -__numeric_constants<_Tp>::gamma_e(); 171*e4b17023SJohn Marino for (int __ii = 1; __ii <= __nm1; ++__ii) 172*e4b17023SJohn Marino __psi += _Tp(1) / _Tp(__ii); 173*e4b17023SJohn Marino __del = __fact * (__psi - std::log(__x)); 174*e4b17023SJohn Marino } 175*e4b17023SJohn Marino __ans += __del; 176*e4b17023SJohn Marino if (std::abs(__del) < __eps * std::abs(__ans)) 177*e4b17023SJohn Marino return __ans; 178*e4b17023SJohn Marino } 179*e4b17023SJohn Marino std::__throw_runtime_error(__N("Series summation failed " 180*e4b17023SJohn Marino "in __expint_En_series.")); 181*e4b17023SJohn Marino } 182*e4b17023SJohn Marino 183*e4b17023SJohn Marino 184*e4b17023SJohn Marino /** 185*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_n(x) @f$ 186*e4b17023SJohn Marino * by continued fractions. 187*e4b17023SJohn Marino * 188*e4b17023SJohn Marino * The exponential integral is given by 189*e4b17023SJohn Marino * \f[ 190*e4b17023SJohn Marino * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt 191*e4b17023SJohn Marino * \f] 192*e4b17023SJohn Marino * 193*e4b17023SJohn Marino * @param __n The order of the exponential integral function. 194*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 195*e4b17023SJohn Marino * @return The exponential integral. 196*e4b17023SJohn Marino */ 197*e4b17023SJohn Marino template<typename _Tp> 198*e4b17023SJohn Marino _Tp __expint_En_cont_frac(const unsigned int __n,const _Tp __x)199*e4b17023SJohn Marino __expint_En_cont_frac(const unsigned int __n, const _Tp __x) 200*e4b17023SJohn Marino { 201*e4b17023SJohn Marino const unsigned int __max_iter = 100; 202*e4b17023SJohn Marino const _Tp __eps = std::numeric_limits<_Tp>::epsilon(); 203*e4b17023SJohn Marino const _Tp __fp_min = std::numeric_limits<_Tp>::min(); 204*e4b17023SJohn Marino const int __nm1 = __n - 1; 205*e4b17023SJohn Marino _Tp __b = __x + _Tp(__n); 206*e4b17023SJohn Marino _Tp __c = _Tp(1) / __fp_min; 207*e4b17023SJohn Marino _Tp __d = _Tp(1) / __b; 208*e4b17023SJohn Marino _Tp __h = __d; 209*e4b17023SJohn Marino for ( unsigned int __i = 1; __i <= __max_iter; ++__i ) 210*e4b17023SJohn Marino { 211*e4b17023SJohn Marino _Tp __a = -_Tp(__i * (__nm1 + __i)); 212*e4b17023SJohn Marino __b += _Tp(2); 213*e4b17023SJohn Marino __d = _Tp(1) / (__a * __d + __b); 214*e4b17023SJohn Marino __c = __b + __a / __c; 215*e4b17023SJohn Marino const _Tp __del = __c * __d; 216*e4b17023SJohn Marino __h *= __del; 217*e4b17023SJohn Marino if (std::abs(__del - _Tp(1)) < __eps) 218*e4b17023SJohn Marino { 219*e4b17023SJohn Marino const _Tp __ans = __h * std::exp(-__x); 220*e4b17023SJohn Marino return __ans; 221*e4b17023SJohn Marino } 222*e4b17023SJohn Marino } 223*e4b17023SJohn Marino std::__throw_runtime_error(__N("Continued fraction failed " 224*e4b17023SJohn Marino "in __expint_En_cont_frac.")); 225*e4b17023SJohn Marino } 226*e4b17023SJohn Marino 227*e4b17023SJohn Marino 228*e4b17023SJohn Marino /** 229*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_n(x) @f$ 230*e4b17023SJohn Marino * by recursion. Use upward recursion for @f$ x < n @f$ 231*e4b17023SJohn Marino * and downward recursion (Miller's algorithm) otherwise. 232*e4b17023SJohn Marino * 233*e4b17023SJohn Marino * The exponential integral is given by 234*e4b17023SJohn Marino * \f[ 235*e4b17023SJohn Marino * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt 236*e4b17023SJohn Marino * \f] 237*e4b17023SJohn Marino * 238*e4b17023SJohn Marino * @param __n The order of the exponential integral function. 239*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 240*e4b17023SJohn Marino * @return The exponential integral. 241*e4b17023SJohn Marino */ 242*e4b17023SJohn Marino template<typename _Tp> 243*e4b17023SJohn Marino _Tp __expint_En_recursion(const unsigned int __n,const _Tp __x)244*e4b17023SJohn Marino __expint_En_recursion(const unsigned int __n, const _Tp __x) 245*e4b17023SJohn Marino { 246*e4b17023SJohn Marino _Tp __En; 247*e4b17023SJohn Marino _Tp __E1 = __expint_E1(__x); 248*e4b17023SJohn Marino if (__x < _Tp(__n)) 249*e4b17023SJohn Marino { 250*e4b17023SJohn Marino // Forward recursion is stable only for n < x. 251*e4b17023SJohn Marino __En = __E1; 252*e4b17023SJohn Marino for (unsigned int __j = 2; __j < __n; ++__j) 253*e4b17023SJohn Marino __En = (std::exp(-__x) - __x * __En) / _Tp(__j - 1); 254*e4b17023SJohn Marino } 255*e4b17023SJohn Marino else 256*e4b17023SJohn Marino { 257*e4b17023SJohn Marino // Backward recursion is stable only for n >= x. 258*e4b17023SJohn Marino __En = _Tp(1); 259*e4b17023SJohn Marino const int __N = __n + 20; // TODO: Check this starting number. 260*e4b17023SJohn Marino _Tp __save = _Tp(0); 261*e4b17023SJohn Marino for (int __j = __N; __j > 0; --__j) 262*e4b17023SJohn Marino { 263*e4b17023SJohn Marino __En = (std::exp(-__x) - __j * __En) / __x; 264*e4b17023SJohn Marino if (__j == __n) 265*e4b17023SJohn Marino __save = __En; 266*e4b17023SJohn Marino } 267*e4b17023SJohn Marino _Tp __norm = __En / __E1; 268*e4b17023SJohn Marino __En /= __norm; 269*e4b17023SJohn Marino } 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino return __En; 272*e4b17023SJohn Marino } 273*e4b17023SJohn Marino 274*e4b17023SJohn Marino /** 275*e4b17023SJohn Marino * @brief Return the exponential integral @f$ Ei(x) @f$ 276*e4b17023SJohn Marino * by series summation. 277*e4b17023SJohn Marino * 278*e4b17023SJohn Marino * The exponential integral is given by 279*e4b17023SJohn Marino * \f[ 280*e4b17023SJohn Marino * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt 281*e4b17023SJohn Marino * \f] 282*e4b17023SJohn Marino * 283*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 284*e4b17023SJohn Marino * @return The exponential integral. 285*e4b17023SJohn Marino */ 286*e4b17023SJohn Marino template<typename _Tp> 287*e4b17023SJohn Marino _Tp __expint_Ei_series(const _Tp __x)288*e4b17023SJohn Marino __expint_Ei_series(const _Tp __x) 289*e4b17023SJohn Marino { 290*e4b17023SJohn Marino _Tp __term = _Tp(1); 291*e4b17023SJohn Marino _Tp __sum = _Tp(0); 292*e4b17023SJohn Marino const unsigned int __max_iter = 1000; 293*e4b17023SJohn Marino for (unsigned int __i = 1; __i < __max_iter; ++__i) 294*e4b17023SJohn Marino { 295*e4b17023SJohn Marino __term *= __x / __i; 296*e4b17023SJohn Marino __sum += __term / __i; 297*e4b17023SJohn Marino if (__term < std::numeric_limits<_Tp>::epsilon() * __sum) 298*e4b17023SJohn Marino break; 299*e4b17023SJohn Marino } 300*e4b17023SJohn Marino 301*e4b17023SJohn Marino return __numeric_constants<_Tp>::__gamma_e() + __sum + std::log(__x); 302*e4b17023SJohn Marino } 303*e4b17023SJohn Marino 304*e4b17023SJohn Marino 305*e4b17023SJohn Marino /** 306*e4b17023SJohn Marino * @brief Return the exponential integral @f$ Ei(x) @f$ 307*e4b17023SJohn Marino * by asymptotic expansion. 308*e4b17023SJohn Marino * 309*e4b17023SJohn Marino * The exponential integral is given by 310*e4b17023SJohn Marino * \f[ 311*e4b17023SJohn Marino * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt 312*e4b17023SJohn Marino * \f] 313*e4b17023SJohn Marino * 314*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 315*e4b17023SJohn Marino * @return The exponential integral. 316*e4b17023SJohn Marino */ 317*e4b17023SJohn Marino template<typename _Tp> 318*e4b17023SJohn Marino _Tp __expint_Ei_asymp(const _Tp __x)319*e4b17023SJohn Marino __expint_Ei_asymp(const _Tp __x) 320*e4b17023SJohn Marino { 321*e4b17023SJohn Marino _Tp __term = _Tp(1); 322*e4b17023SJohn Marino _Tp __sum = _Tp(1); 323*e4b17023SJohn Marino const unsigned int __max_iter = 1000; 324*e4b17023SJohn Marino for (unsigned int __i = 1; __i < __max_iter; ++__i) 325*e4b17023SJohn Marino { 326*e4b17023SJohn Marino _Tp __prev = __term; 327*e4b17023SJohn Marino __term *= __i / __x; 328*e4b17023SJohn Marino if (__term < std::numeric_limits<_Tp>::epsilon()) 329*e4b17023SJohn Marino break; 330*e4b17023SJohn Marino if (__term >= __prev) 331*e4b17023SJohn Marino break; 332*e4b17023SJohn Marino __sum += __term; 333*e4b17023SJohn Marino } 334*e4b17023SJohn Marino 335*e4b17023SJohn Marino return std::exp(__x) * __sum / __x; 336*e4b17023SJohn Marino } 337*e4b17023SJohn Marino 338*e4b17023SJohn Marino 339*e4b17023SJohn Marino /** 340*e4b17023SJohn Marino * @brief Return the exponential integral @f$ Ei(x) @f$. 341*e4b17023SJohn Marino * 342*e4b17023SJohn Marino * The exponential integral is given by 343*e4b17023SJohn Marino * \f[ 344*e4b17023SJohn Marino * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt 345*e4b17023SJohn Marino * \f] 346*e4b17023SJohn Marino * 347*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 348*e4b17023SJohn Marino * @return The exponential integral. 349*e4b17023SJohn Marino */ 350*e4b17023SJohn Marino template<typename _Tp> 351*e4b17023SJohn Marino _Tp __expint_Ei(const _Tp __x)352*e4b17023SJohn Marino __expint_Ei(const _Tp __x) 353*e4b17023SJohn Marino { 354*e4b17023SJohn Marino if (__x < _Tp(0)) 355*e4b17023SJohn Marino return -__expint_E1(-__x); 356*e4b17023SJohn Marino else if (__x < -std::log(std::numeric_limits<_Tp>::epsilon())) 357*e4b17023SJohn Marino return __expint_Ei_series(__x); 358*e4b17023SJohn Marino else 359*e4b17023SJohn Marino return __expint_Ei_asymp(__x); 360*e4b17023SJohn Marino } 361*e4b17023SJohn Marino 362*e4b17023SJohn Marino 363*e4b17023SJohn Marino /** 364*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_1(x) @f$. 365*e4b17023SJohn Marino * 366*e4b17023SJohn Marino * The exponential integral is given by 367*e4b17023SJohn Marino * \f[ 368*e4b17023SJohn Marino * E_1(x) = \int_{1}^\infty \frac{e^{-xt}}{t} dt 369*e4b17023SJohn Marino * \f] 370*e4b17023SJohn Marino * 371*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 372*e4b17023SJohn Marino * @return The exponential integral. 373*e4b17023SJohn Marino */ 374*e4b17023SJohn Marino template<typename _Tp> 375*e4b17023SJohn Marino _Tp __expint_E1(const _Tp __x)376*e4b17023SJohn Marino __expint_E1(const _Tp __x) 377*e4b17023SJohn Marino { 378*e4b17023SJohn Marino if (__x < _Tp(0)) 379*e4b17023SJohn Marino return -__expint_Ei(-__x); 380*e4b17023SJohn Marino else if (__x < _Tp(1)) 381*e4b17023SJohn Marino return __expint_E1_series(__x); 382*e4b17023SJohn Marino else if (__x < _Tp(100)) // TODO: Find a good asymptotic switch point. 383*e4b17023SJohn Marino return __expint_En_cont_frac(1, __x); 384*e4b17023SJohn Marino else 385*e4b17023SJohn Marino return __expint_E1_asymp(__x); 386*e4b17023SJohn Marino } 387*e4b17023SJohn Marino 388*e4b17023SJohn Marino 389*e4b17023SJohn Marino /** 390*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_n(x) @f$ 391*e4b17023SJohn Marino * for large argument. 392*e4b17023SJohn Marino * 393*e4b17023SJohn Marino * The exponential integral is given by 394*e4b17023SJohn Marino * \f[ 395*e4b17023SJohn Marino * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt 396*e4b17023SJohn Marino * \f] 397*e4b17023SJohn Marino * 398*e4b17023SJohn Marino * This is something of an extension. 399*e4b17023SJohn Marino * 400*e4b17023SJohn Marino * @param __n The order of the exponential integral function. 401*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 402*e4b17023SJohn Marino * @return The exponential integral. 403*e4b17023SJohn Marino */ 404*e4b17023SJohn Marino template<typename _Tp> 405*e4b17023SJohn Marino _Tp __expint_asymp(const unsigned int __n,const _Tp __x)406*e4b17023SJohn Marino __expint_asymp(const unsigned int __n, const _Tp __x) 407*e4b17023SJohn Marino { 408*e4b17023SJohn Marino _Tp __term = _Tp(1); 409*e4b17023SJohn Marino _Tp __sum = _Tp(1); 410*e4b17023SJohn Marino for (unsigned int __i = 1; __i <= __n; ++__i) 411*e4b17023SJohn Marino { 412*e4b17023SJohn Marino _Tp __prev = __term; 413*e4b17023SJohn Marino __term *= -(__n - __i + 1) / __x; 414*e4b17023SJohn Marino if (std::abs(__term) > std::abs(__prev)) 415*e4b17023SJohn Marino break; 416*e4b17023SJohn Marino __sum += __term; 417*e4b17023SJohn Marino } 418*e4b17023SJohn Marino 419*e4b17023SJohn Marino return std::exp(-__x) * __sum / __x; 420*e4b17023SJohn Marino } 421*e4b17023SJohn Marino 422*e4b17023SJohn Marino 423*e4b17023SJohn Marino /** 424*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_n(x) @f$ 425*e4b17023SJohn Marino * for large order. 426*e4b17023SJohn Marino * 427*e4b17023SJohn Marino * The exponential integral is given by 428*e4b17023SJohn Marino * \f[ 429*e4b17023SJohn Marino * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt 430*e4b17023SJohn Marino * \f] 431*e4b17023SJohn Marino * 432*e4b17023SJohn Marino * This is something of an extension. 433*e4b17023SJohn Marino * 434*e4b17023SJohn Marino * @param __n The order of the exponential integral function. 435*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 436*e4b17023SJohn Marino * @return The exponential integral. 437*e4b17023SJohn Marino */ 438*e4b17023SJohn Marino template<typename _Tp> 439*e4b17023SJohn Marino _Tp __expint_large_n(const unsigned int __n,const _Tp __x)440*e4b17023SJohn Marino __expint_large_n(const unsigned int __n, const _Tp __x) 441*e4b17023SJohn Marino { 442*e4b17023SJohn Marino const _Tp __xpn = __x + __n; 443*e4b17023SJohn Marino const _Tp __xpn2 = __xpn * __xpn; 444*e4b17023SJohn Marino _Tp __term = _Tp(1); 445*e4b17023SJohn Marino _Tp __sum = _Tp(1); 446*e4b17023SJohn Marino for (unsigned int __i = 1; __i <= __n; ++__i) 447*e4b17023SJohn Marino { 448*e4b17023SJohn Marino _Tp __prev = __term; 449*e4b17023SJohn Marino __term *= (__n - 2 * (__i - 1) * __x) / __xpn2; 450*e4b17023SJohn Marino if (std::abs(__term) < std::numeric_limits<_Tp>::epsilon()) 451*e4b17023SJohn Marino break; 452*e4b17023SJohn Marino __sum += __term; 453*e4b17023SJohn Marino } 454*e4b17023SJohn Marino 455*e4b17023SJohn Marino return std::exp(-__x) * __sum / __xpn; 456*e4b17023SJohn Marino } 457*e4b17023SJohn Marino 458*e4b17023SJohn Marino 459*e4b17023SJohn Marino /** 460*e4b17023SJohn Marino * @brief Return the exponential integral @f$ E_n(x) @f$. 461*e4b17023SJohn Marino * 462*e4b17023SJohn Marino * The exponential integral is given by 463*e4b17023SJohn Marino * \f[ 464*e4b17023SJohn Marino * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt 465*e4b17023SJohn Marino * \f] 466*e4b17023SJohn Marino * This is something of an extension. 467*e4b17023SJohn Marino * 468*e4b17023SJohn Marino * @param __n The order of the exponential integral function. 469*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 470*e4b17023SJohn Marino * @return The exponential integral. 471*e4b17023SJohn Marino */ 472*e4b17023SJohn Marino template<typename _Tp> 473*e4b17023SJohn Marino _Tp __expint(const unsigned int __n,const _Tp __x)474*e4b17023SJohn Marino __expint(const unsigned int __n, const _Tp __x) 475*e4b17023SJohn Marino { 476*e4b17023SJohn Marino // Return NaN on NaN input. 477*e4b17023SJohn Marino if (__isnan(__x)) 478*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 479*e4b17023SJohn Marino else if (__n <= 1 && __x == _Tp(0)) 480*e4b17023SJohn Marino return std::numeric_limits<_Tp>::infinity(); 481*e4b17023SJohn Marino else 482*e4b17023SJohn Marino { 483*e4b17023SJohn Marino _Tp __E0 = std::exp(__x) / __x; 484*e4b17023SJohn Marino if (__n == 0) 485*e4b17023SJohn Marino return __E0; 486*e4b17023SJohn Marino 487*e4b17023SJohn Marino _Tp __E1 = __expint_E1(__x); 488*e4b17023SJohn Marino if (__n == 1) 489*e4b17023SJohn Marino return __E1; 490*e4b17023SJohn Marino 491*e4b17023SJohn Marino if (__x == _Tp(0)) 492*e4b17023SJohn Marino return _Tp(1) / static_cast<_Tp>(__n - 1); 493*e4b17023SJohn Marino 494*e4b17023SJohn Marino _Tp __En = __expint_En_recursion(__n, __x); 495*e4b17023SJohn Marino 496*e4b17023SJohn Marino return __En; 497*e4b17023SJohn Marino } 498*e4b17023SJohn Marino } 499*e4b17023SJohn Marino 500*e4b17023SJohn Marino 501*e4b17023SJohn Marino /** 502*e4b17023SJohn Marino * @brief Return the exponential integral @f$ Ei(x) @f$. 503*e4b17023SJohn Marino * 504*e4b17023SJohn Marino * The exponential integral is given by 505*e4b17023SJohn Marino * \f[ 506*e4b17023SJohn Marino * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt 507*e4b17023SJohn Marino * \f] 508*e4b17023SJohn Marino * 509*e4b17023SJohn Marino * @param __x The argument of the exponential integral function. 510*e4b17023SJohn Marino * @return The exponential integral. 511*e4b17023SJohn Marino */ 512*e4b17023SJohn Marino template<typename _Tp> 513*e4b17023SJohn Marino inline _Tp __expint(const _Tp __x)514*e4b17023SJohn Marino __expint(const _Tp __x) 515*e4b17023SJohn Marino { 516*e4b17023SJohn Marino if (__isnan(__x)) 517*e4b17023SJohn Marino return std::numeric_limits<_Tp>::quiet_NaN(); 518*e4b17023SJohn Marino else 519*e4b17023SJohn Marino return __expint_Ei(__x); 520*e4b17023SJohn Marino } 521*e4b17023SJohn Marino 522*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION 523*e4b17023SJohn Marino } // namespace std::tr1::__detail 524*e4b17023SJohn Marino } 525*e4b17023SJohn Marino } 526*e4b17023SJohn Marino 527*e4b17023SJohn Marino #endif // _GLIBCXX_TR1_EXP_INTEGRAL_TCC 528