xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/tr1/exp_integral.tcc (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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