1 // Special functions -*- C++ -*-
3 // Copyright (C) 2006-2007
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
31 /** @file tr1/exp_integral.tcc
32 * This is an internal header file, included by other library headers.
33 * You should not attempt to use it directly.
37 // ISO C++ 14882 TR1: 5.2 Special functions
40 // Written by Edward Smith-Rowland based on:
42 // (1) Handbook of Mathematical Functions,
43 // Ed. by Milton Abramowitz and Irene A. Stegun,
44 // Dover Publications, New-York, Section 5, pp. 228-251.
45 // (2) The Gnu Scientific Library, http://www.gnu.org/software/gsl
46 // (3) Numerical Recipes in C, by W. H. Press, S. A. Teukolsky,
47 // W. T. Vetterling, B. P. Flannery, Cambridge University Press (1992),
48 // 2nd ed, pp. 222-225.
51 #ifndef _TR1_EXP_INTEGRAL_TCC
52 #define _TR1_EXP_INTEGRAL_TCC 1
54 #include "special_function_util.h"
58 _GLIBCXX_BEGIN_NAMESPACE(_GLIBCXX_TR1)
60 // [5.2] Special functions
63 * @ingroup tr1_math_spec_func
68 // Implementation-space details.
74 * @brief Return the exponential integral @f$ E_1(x) @f$
75 * by series summation. This should be good
78 * The exponential integral is given by
80 * E_1(x) = \int_{1}^{\infty} \frac{e^{-xt}}{t} dt
83 * @param __x The argument of the exponential integral function.
84 * @return The exponential integral.
86 template<typename _Tp>
88 __expint_E1_series(const _Tp __x)
90 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
94 const unsigned int __max_iter = 100;
95 for (unsigned int __i = 1; __i < __max_iter; ++__i)
97 __term *= - __x / __i;
98 if (std::abs(__term) < __eps)
100 if (__term >= _Tp(0))
101 __esum += __term / __i;
103 __osum += __term / __i;
106 return - __esum - __osum
107 - __numeric_constants<_Tp>::__gamma_e() - std::log(__x);
112 * @brief Return the exponential integral @f$ E_1(x) @f$
113 * by asymptotic expansion.
115 * The exponential integral is given by
117 * E_1(x) = \int_{1}^\infty \frac{e^{-xt}}{t} dt
120 * @param __x The argument of the exponential integral function.
121 * @return The exponential integral.
123 template<typename _Tp>
125 __expint_E1_asymp(const _Tp __x)
130 const unsigned int __max_iter = 1000;
131 for (unsigned int __i = 1; __i < __max_iter; ++__i)
134 __term *= - __i / __x;
135 if (std::abs(__term) > std::abs(__prev))
137 if (__term >= _Tp(0))
143 return std::exp(- __x) * (__esum + __osum) / __x;
148 * @brief Return the exponential integral @f$ E_n(x) @f$
149 * by series summation.
151 * The exponential integral is given by
153 * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt
156 * @param __n The order of the exponential integral function.
157 * @param __x The argument of the exponential integral function.
158 * @return The exponential integral.
160 template<typename _Tp>
162 __expint_En_series(const unsigned int __n, const _Tp __x)
164 const unsigned int __max_iter = 100;
165 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
166 const int __nm1 = __n - 1;
167 _Tp __ans = (__nm1 != 0
168 ? _Tp(1) / __nm1 : -std::log(__x)
169 - __numeric_constants<_Tp>::__gamma_e());
171 for (int __i = 1; __i <= __max_iter; ++__i)
173 __fact *= -__x / _Tp(__i);
176 __del = -__fact / _Tp(__i - __nm1);
179 _Tp __psi = -_TR1_GAMMA_TCC;
180 for (int __ii = 1; __ii <= __nm1; ++__ii)
181 __psi += _Tp(1) / _Tp(__ii);
182 __del = __fact * (__psi - std::log(__x));
185 if (std::abs(__del) < __eps * std::abs(__ans))
188 std::__throw_runtime_error(__N("Series summation failed "
189 "in __expint_En_series."));
194 * @brief Return the exponential integral @f$ E_n(x) @f$
195 * by continued fractions.
197 * The exponential integral is given by
199 * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt
202 * @param __n The order of the exponential integral function.
203 * @param __x The argument of the exponential integral function.
204 * @return The exponential integral.
206 template<typename _Tp>
208 __expint_En_cont_frac(const unsigned int __n, const _Tp __x)
210 const unsigned int __max_iter = 100;
211 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
212 const _Tp __fp_min = std::numeric_limits<_Tp>::min();
213 const int __nm1 = __n - 1;
214 _Tp __b = __x + _Tp(__n);
215 _Tp __c = _Tp(1) / __fp_min;
216 _Tp __d = _Tp(1) / __b;
218 for ( unsigned int __i = 1; __i <= __max_iter; ++__i )
220 _Tp __a = -_Tp(__i * (__nm1 + __i));
222 __d = _Tp(1) / (__a * __d + __b);
223 __c = __b + __a / __c;
224 const _Tp __del = __c * __d;
226 if (std::abs(__del - _Tp(1)) < __eps)
228 const _Tp __ans = __h * std::exp(-__x);
232 std::__throw_runtime_error(__N("Continued fraction failed "
233 "in __expint_En_cont_frac."));
238 * @brief Return the exponential integral @f$ E_n(x) @f$
239 * by recursion. Use upward recursion for @f$ x < n @f$
240 * and downward recursion (Miller's algorithm) otherwise.
242 * The exponential integral is given by
244 * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt
247 * @param __n The order of the exponential integral function.
248 * @param __x The argument of the exponential integral function.
249 * @return The exponential integral.
251 template<typename _Tp>
253 __expint_En_recursion(const unsigned int __n, const _Tp __x)
256 _Tp __E1 = __expint_E1(__x);
259 // Forward recursion is stable only for n < x.
261 for (unsigned int __j = 2; __j < __n; ++__j)
262 __En = (std::exp(-__x) - __x * __En) / _Tp(__j - 1);
266 // Backward recursion is stable only for n >= x.
268 const int __N = __n + 20; // TODO: Check this starting number.
270 for (int __j = __N; __j > 0; --__j)
272 __En = (std::exp(-__x) - __j * __En) / __x;
276 _Tp __norm = __En / __E1;
284 * @brief Return the exponential integral @f$ Ei(x) @f$
285 * by series summation.
287 * The exponential integral is given by
289 * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt
292 * @param __x The argument of the exponential integral function.
293 * @return The exponential integral.
295 template<typename _Tp>
297 __expint_Ei_series(const _Tp __x)
301 const unsigned int __max_iter = 1000;
302 for (unsigned int __i = 1; __i < __max_iter; ++__i)
305 __sum += __term / __i;
306 if (__term < std::numeric_limits<_Tp>::epsilon() * __sum)
310 return __numeric_constants<_Tp>::__gamma_e() + __sum + std::log(__x);
315 * @brief Return the exponential integral @f$ Ei(x) @f$
316 * by asymptotic expansion.
318 * The exponential integral is given by
320 * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt
323 * @param __x The argument of the exponential integral function.
324 * @return The exponential integral.
326 template<typename _Tp>
328 __expint_Ei_asymp(const _Tp __x)
332 const unsigned int __max_iter = 1000;
333 for (unsigned int __i = 1; __i < __max_iter; ++__i)
337 if (__term < std::numeric_limits<_Tp>::epsilon())
339 if (__term >= __prev)
344 return std::exp(__x) * __sum / __x;
349 * @brief Return the exponential integral @f$ Ei(x) @f$.
351 * The exponential integral is given by
353 * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt
356 * @param __x The argument of the exponential integral function.
357 * @return The exponential integral.
359 template<typename _Tp>
361 __expint_Ei(const _Tp __x)
364 return -__expint_E1(-__x);
365 else if (__x < -std::log(std::numeric_limits<_Tp>::epsilon()))
366 return __expint_Ei_series(__x);
368 return __expint_Ei_asymp(__x);
373 * @brief Return the exponential integral @f$ E_1(x) @f$.
375 * The exponential integral is given by
377 * E_1(x) = \int_{1}^\infty \frac{e^{-xt}}{t} dt
380 * @param __x The argument of the exponential integral function.
381 * @return The exponential integral.
383 template<typename _Tp>
385 __expint_E1(const _Tp __x)
388 return -__expint_Ei(-__x);
389 else if (__x < _Tp(1))
390 return __expint_E1_series(__x);
391 else if (__x < _Tp(100)) // TODO: Find a good asymptotic switch point.
392 return __expint_En_cont_frac(1, __x);
394 return __expint_E1_asymp(__x);
399 * @brief Return the exponential integral @f$ E_n(x) @f$
400 * for large argument.
402 * The exponential integral is given by
404 * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt
407 * This is something of an extension.
409 * @param __n The order of the exponential integral function.
410 * @param __x The argument of the exponential integral function.
411 * @return The exponential integral.
413 template<typename _Tp>
415 __expint_asymp(const unsigned int __n, const _Tp __x)
419 for (unsigned int __i = 1; __i <= __n; ++__i)
422 __term *= -(__n - __i + 1) / __x;
423 if (std::abs(__term) > std::abs(__prev))
428 return std::exp(-__x) * __sum / __x;
433 * @brief Return the exponential integral @f$ E_n(x) @f$
436 * The exponential integral is given by
438 * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt
441 * This is something of an extension.
443 * @param __n The order of the exponential integral function.
444 * @param __x The argument of the exponential integral function.
445 * @return The exponential integral.
447 template<typename _Tp>
449 __expint_large_n(const unsigned int __n, const _Tp __x)
451 const _Tp __xpn = __x + __n;
452 const _Tp __xpn2 = __xpn * __xpn;
455 for (unsigned int __i = 1; __i <= __n; ++__i)
458 __term *= (__n - 2 * (__i - 1) * __x) / __xpn2;
459 if (std::abs(__term) < std::numeric_limits<_Tp>::epsilon())
464 return std::exp(-__x) * __sum / __xpn;
469 * @brief Return the exponential integral @f$ E_n(x) @f$.
471 * The exponential integral is given by
473 * E_n(x) = \int_{1}^\infty \frac{e^{-xt}}{t^n} dt
475 * This is something of an extension.
477 * @param __n The order of the exponential integral function.
478 * @param __x The argument of the exponential integral function.
479 * @return The exponential integral.
481 template<typename _Tp>
483 __expint(const unsigned int __n, const _Tp __x)
485 // Return NaN on NaN input.
487 return std::numeric_limits<_Tp>::quiet_NaN();
488 else if (__n <= 1 && __x == _Tp(0))
489 return std::numeric_limits<_Tp>::infinity();
492 _Tp __E0 = std::exp(__x) / __x;
496 _Tp __E1 = __expint_E1(__x);
501 return _Tp(1) / static_cast<_Tp>(__n - 1);
503 _Tp __En = __expint_En_recursion(__n, __x);
511 * The exponential integral @f$ Ei(x) @f$.
513 * The exponential integral is given by
515 * Ei(x) = -\int_{-x}^\infty \frac{e^t}{t} dt
518 * @param __x The argument of the exponential integral function.
519 * @return The exponential integral.
521 template<typename _Tp>
523 __expint(const _Tp __x)
526 return std::numeric_limits<_Tp>::quiet_NaN();
528 return __expint_Ei(__x);
531 } // namespace std::tr1::__detail
533 /* @} */ // group tr1_math_spec_func
535 _GLIBCXX_END_NAMESPACE
538 #endif // _TR1_EXP_INTEGRAL_TCC