xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/tr1/exp_integral.tcc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // Special functions -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2006, 2007, 2008, 2009, 2010
4*e4b17023SJohn Marino // Free Software Foundation, Inc.
5*e4b17023SJohn Marino //
6*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
7*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
8*e4b17023SJohn Marino // terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino // any later version.
11*e4b17023SJohn Marino //
12*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*e4b17023SJohn Marino // GNU General Public License for more details.
16*e4b17023SJohn Marino //
17*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
18*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
19*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
22*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
23*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino /** @file tr1/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