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