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