exp_integral.tcc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef _GLIBCXX_TR1_EXP_INTEGRAL_TCC
00047 #define _GLIBCXX_TR1_EXP_INTEGRAL_TCC 1
00048
00049 #include "special_function_util.h"
00050
00051 namespace std
00052 {
00053 namespace tr1
00054 {
00055
00056
00057
00058
00059 namespace __detail
00060 {
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 template<typename _Tp>
00076 _Tp
00077 __expint_E1_series(const _Tp __x)
00078 {
00079 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00080 _Tp __term = _Tp(1);
00081 _Tp __esum = _Tp(0);
00082 _Tp __osum = _Tp(0);
00083 const unsigned int __max_iter = 100;
00084 for (unsigned int __i = 1; __i < __max_iter; ++__i)
00085 {
00086 __term *= - __x / __i;
00087 if (std::abs(__term) < __eps)
00088 break;
00089 if (__term >= _Tp(0))
00090 __esum += __term / __i;
00091 else
00092 __osum += __term / __i;
00093 }
00094
00095 return - __esum - __osum
00096 - __numeric_constants<_Tp>::__gamma_e() - std::log(__x);
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 template<typename _Tp>
00113 _Tp
00114 __expint_E1_asymp(const _Tp __x)
00115 {
00116 _Tp __term = _Tp(1);
00117 _Tp __esum = _Tp(1);
00118 _Tp __osum = _Tp(0);
00119 const unsigned int __max_iter = 1000;
00120 for (unsigned int __i = 1; __i < __max_iter; ++__i)
00121 {
00122 _Tp __prev = __term;
00123 __term *= - __i / __x;
00124 if (std::abs(__term) > std::abs(__prev))
00125 break;
00126 if (__term >= _Tp(0))
00127 __esum += __term;
00128 else
00129 __osum += __term;
00130 }
00131
00132 return std::exp(- __x) * (__esum + __osum) / __x;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 template<typename _Tp>
00150 _Tp
00151 __expint_En_series(const unsigned int __n, const _Tp __x)
00152 {
00153 const unsigned int __max_iter = 100;
00154 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00155 const int __nm1 = __n - 1;
00156 _Tp __ans = (__nm1 != 0
00157 ? _Tp(1) / __nm1 : -std::log(__x)
00158 - __numeric_constants<_Tp>::__gamma_e());
00159 _Tp __fact = _Tp(1);
00160 for (int __i = 1; __i <= __max_iter; ++__i)
00161 {
00162 __fact *= -__x / _Tp(__i);
00163 _Tp __del;
00164 if ( __i != __nm1 )
00165 __del = -__fact / _Tp(__i - __nm1);
00166 else
00167 {
00168 _Tp __psi = -_TR1_GAMMA_TCC;
00169 for (int __ii = 1; __ii <= __nm1; ++__ii)
00170 __psi += _Tp(1) / _Tp(__ii);
00171 __del = __fact * (__psi - std::log(__x));
00172 }
00173 __ans += __del;
00174 if (std::abs(__del) < __eps * std::abs(__ans))
00175 return __ans;
00176 }
00177 std::__throw_runtime_error(__N("Series summation failed "
00178 "in __expint_En_series."));
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 template<typename _Tp>
00196 _Tp
00197 __expint_En_cont_frac(const unsigned int __n, const _Tp __x)
00198 {
00199 const unsigned int __max_iter = 100;
00200 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00201 const _Tp __fp_min = std::numeric_limits<_Tp>::min();
00202 const int __nm1 = __n - 1;
00203 _Tp __b = __x + _Tp(__n);
00204 _Tp __c = _Tp(1) / __fp_min;
00205 _Tp __d = _Tp(1) / __b;
00206 _Tp __h = __d;
00207 for ( unsigned int __i = 1; __i <= __max_iter; ++__i )
00208 {
00209 _Tp __a = -_Tp(__i * (__nm1 + __i));
00210 __b += _Tp(2);
00211 __d = _Tp(1) / (__a * __d + __b);
00212 __c = __b + __a / __c;
00213 const _Tp __del = __c * __d;
00214 __h *= __del;
00215 if (std::abs(__del - _Tp(1)) < __eps)
00216 {
00217 const _Tp __ans = __h * std::exp(-__x);
00218 return __ans;
00219 }
00220 }
00221 std::__throw_runtime_error(__N("Continued fraction failed "
00222 "in __expint_En_cont_frac."));
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 template<typename _Tp>
00241 _Tp
00242 __expint_En_recursion(const unsigned int __n, const _Tp __x)
00243 {
00244 _Tp __En;
00245 _Tp __E1 = __expint_E1(__x);
00246 if (__x < _Tp(__n))
00247 {
00248
00249 __En = __E1;
00250 for (unsigned int __j = 2; __j < __n; ++__j)
00251 __En = (std::exp(-__x) - __x * __En) / _Tp(__j - 1);
00252 }
00253 else
00254 {
00255
00256 __En = _Tp(1);
00257 const int __N = __n + 20;
00258 _Tp __save = _Tp(0);
00259 for (int __j = __N; __j > 0; --__j)
00260 {
00261 __En = (std::exp(-__x) - __j * __En) / __x;
00262 if (__j == __n)
00263 __save = __En;
00264 }
00265 _Tp __norm = __En / __E1;
00266 __En /= __norm;
00267 }
00268
00269 return __En;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 template<typename _Tp>
00285 _Tp
00286 __expint_Ei_series(const _Tp __x)
00287 {
00288 _Tp __term = _Tp(1);
00289 _Tp __sum = _Tp(0);
00290 const unsigned int __max_iter = 1000;
00291 for (unsigned int __i = 1; __i < __max_iter; ++__i)
00292 {
00293 __term *= __x / __i;
00294 __sum += __term / __i;
00295 if (__term < std::numeric_limits<_Tp>::epsilon() * __sum)
00296 break;
00297 }
00298
00299 return __numeric_constants<_Tp>::__gamma_e() + __sum + std::log(__x);
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 template<typename _Tp>
00316 _Tp
00317 __expint_Ei_asymp(const _Tp __x)
00318 {
00319 _Tp __term = _Tp(1);
00320 _Tp __sum = _Tp(1);
00321 const unsigned int __max_iter = 1000;
00322 for (unsigned int __i = 1; __i < __max_iter; ++__i)
00323 {
00324 _Tp __prev = __term;
00325 __term *= __i / __x;
00326 if (__term < std::numeric_limits<_Tp>::epsilon())
00327 break;
00328 if (__term >= __prev)
00329 break;
00330 __sum += __term;
00331 }
00332
00333 return std::exp(__x) * __sum / __x;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 template<typename _Tp>
00349 _Tp
00350 __expint_Ei(const _Tp __x)
00351 {
00352 if (__x < _Tp(0))
00353 return -__expint_E1(-__x);
00354 else if (__x < -std::log(std::numeric_limits<_Tp>::epsilon()))
00355 return __expint_Ei_series(__x);
00356 else
00357 return __expint_Ei_asymp(__x);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 template<typename _Tp>
00373 _Tp
00374 __expint_E1(const _Tp __x)
00375 {
00376 if (__x < _Tp(0))
00377 return -__expint_Ei(-__x);
00378 else if (__x < _Tp(1))
00379 return __expint_E1_series(__x);
00380 else if (__x < _Tp(100))
00381 return __expint_En_cont_frac(1, __x);
00382 else
00383 return __expint_E1_asymp(__x);
00384 }
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 template<typename _Tp>
00403 _Tp
00404 __expint_asymp(const unsigned int __n, const _Tp __x)
00405 {
00406 _Tp __term = _Tp(1);
00407 _Tp __sum = _Tp(1);
00408 for (unsigned int __i = 1; __i <= __n; ++__i)
00409 {
00410 _Tp __prev = __term;
00411 __term *= -(__n - __i + 1) / __x;
00412 if (std::abs(__term) > std::abs(__prev))
00413 break;
00414 __sum += __term;
00415 }
00416
00417 return std::exp(-__x) * __sum / __x;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 template<typename _Tp>
00437 _Tp
00438 __expint_large_n(const unsigned int __n, const _Tp __x)
00439 {
00440 const _Tp __xpn = __x + __n;
00441 const _Tp __xpn2 = __xpn * __xpn;
00442 _Tp __term = _Tp(1);
00443 _Tp __sum = _Tp(1);
00444 for (unsigned int __i = 1; __i <= __n; ++__i)
00445 {
00446 _Tp __prev = __term;
00447 __term *= (__n - 2 * (__i - 1) * __x) / __xpn2;
00448 if (std::abs(__term) < std::numeric_limits<_Tp>::epsilon())
00449 break;
00450 __sum += __term;
00451 }
00452
00453 return std::exp(-__x) * __sum / __xpn;
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 template<typename _Tp>
00471 _Tp
00472 __expint(const unsigned int __n, const _Tp __x)
00473 {
00474
00475 if (__isnan(__x))
00476 return std::numeric_limits<_Tp>::quiet_NaN();
00477 else if (__n <= 1 && __x == _Tp(0))
00478 return std::numeric_limits<_Tp>::infinity();
00479 else
00480 {
00481 _Tp __E0 = std::exp(__x) / __x;
00482 if (__n == 0)
00483 return __E0;
00484
00485 _Tp __E1 = __expint_E1(__x);
00486 if (__n == 1)
00487 return __E1;
00488
00489 if (__x == _Tp(0))
00490 return _Tp(1) / static_cast<_Tp>(__n - 1);
00491
00492 _Tp __En = __expint_En_recursion(__n, __x);
00493
00494 return __En;
00495 }
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 template<typename _Tp>
00511 inline _Tp
00512 __expint(const _Tp __x)
00513 {
00514 if (__isnan(__x))
00515 return std::numeric_limits<_Tp>::quiet_NaN();
00516 else
00517 return __expint_Ei(__x);
00518 }
00519
00520 }
00521 }
00522 }
00523
00524 #endif // _GLIBCXX_TR1_EXP_INTEGRAL_TCC