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 #ifndef _GLIBCXX_TR1_ELL_INTEGRAL_TCC
00049 #define _GLIBCXX_TR1_ELL_INTEGRAL_TCC 1
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
00076
00077 template<typename _Tp>
00078 _Tp
00079 __ellint_rf(const _Tp __x, const _Tp __y, const _Tp __z)
00080 {
00081 const _Tp __min = std::numeric_limits<_Tp>::min();
00082 const _Tp __max = std::numeric_limits<_Tp>::max();
00083 const _Tp __lolim = _Tp(5) * __min;
00084 const _Tp __uplim = __max / _Tp(5);
00085
00086 if (__x < _Tp(0) || __y < _Tp(0) || __z < _Tp(0))
00087 std::__throw_domain_error(__N("Argument less than zero "
00088 "in __ellint_rf."));
00089 else if (__x + __y < __lolim || __x + __z < __lolim
00090 || __y + __z < __lolim)
00091 std::__throw_domain_error(__N("Argument too small in __ellint_rf"));
00092 else
00093 {
00094 const _Tp __c0 = _Tp(1) / _Tp(4);
00095 const _Tp __c1 = _Tp(1) / _Tp(24);
00096 const _Tp __c2 = _Tp(1) / _Tp(10);
00097 const _Tp __c3 = _Tp(3) / _Tp(44);
00098 const _Tp __c4 = _Tp(1) / _Tp(14);
00099
00100 _Tp __xn = __x;
00101 _Tp __yn = __y;
00102 _Tp __zn = __z;
00103
00104 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00105 const _Tp __errtol = std::pow(__eps, _Tp(1) / _Tp(6));
00106 _Tp __mu;
00107 _Tp __xndev, __yndev, __zndev;
00108
00109 const unsigned int __max_iter = 100;
00110 for (unsigned int __iter = 0; __iter < __max_iter; ++__iter)
00111 {
00112 __mu = (__xn + __yn + __zn) / _Tp(3);
00113 __xndev = 2 - (__mu + __xn) / __mu;
00114 __yndev = 2 - (__mu + __yn) / __mu;
00115 __zndev = 2 - (__mu + __zn) / __mu;
00116 _Tp __epsilon = std::max(std::abs(__xndev), std::abs(__yndev));
00117 __epsilon = std::max(__epsilon, std::abs(__zndev));
00118 if (__epsilon < __errtol)
00119 break;
00120 const _Tp __xnroot = std::sqrt(__xn);
00121 const _Tp __ynroot = std::sqrt(__yn);
00122 const _Tp __znroot = std::sqrt(__zn);
00123 const _Tp __lambda = __xnroot * (__ynroot + __znroot)
00124 + __ynroot * __znroot;
00125 __xn = __c0 * (__xn + __lambda);
00126 __yn = __c0 * (__yn + __lambda);
00127 __zn = __c0 * (__zn + __lambda);
00128 }
00129
00130 const _Tp __e2 = __xndev * __yndev - __zndev * __zndev;
00131 const _Tp __e3 = __xndev * __yndev * __zndev;
00132 const _Tp __s = _Tp(1) + (__c1 * __e2 - __c2 - __c3 * __e3) * __e2
00133 + __c4 * __e3;
00134
00135 return __s / std::sqrt(__mu);
00136 }
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 template<typename _Tp>
00157 _Tp
00158 __comp_ellint_1_series(const _Tp __k)
00159 {
00160
00161 const _Tp __kk = __k * __k;
00162
00163 _Tp __term = __kk / _Tp(4);
00164 _Tp __sum = _Tp(1) + __term;
00165
00166 const unsigned int __max_iter = 1000;
00167 for (unsigned int __i = 2; __i < __max_iter; ++__i)
00168 {
00169 __term *= (2 * __i - 1) * __kk / (2 * __i);
00170 if (__term < std::numeric_limits<_Tp>::epsilon())
00171 break;
00172 __sum += __term;
00173 }
00174
00175 return __numeric_constants<_Tp>::__pi_2() * __sum;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 template<typename _Tp>
00195 _Tp
00196 __comp_ellint_1(const _Tp __k)
00197 {
00198
00199 if (__isnan(__k))
00200 return std::numeric_limits<_Tp>::quiet_NaN();
00201 else if (std::abs(__k) >= _Tp(1))
00202 return std::numeric_limits<_Tp>::quiet_NaN();
00203 else
00204 return __ellint_rf(_Tp(0), _Tp(1) - __k * __k, _Tp(1));
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 template<typename _Tp>
00223 _Tp
00224 __ellint_1(const _Tp __k, const _Tp __phi)
00225 {
00226
00227 if (__isnan(__k) || __isnan(__phi))
00228 return std::numeric_limits<_Tp>::quiet_NaN();
00229 else if (std::abs(__k) > _Tp(1))
00230 std::__throw_domain_error(__N("Bad argument in __ellint_1."));
00231 else
00232 {
00233
00234 const int __n = std::floor(__phi / __numeric_constants<_Tp>::__pi()
00235 + _Tp(0.5L));
00236 const _Tp __phi_red = __phi
00237 - __n * __numeric_constants<_Tp>::__pi();
00238
00239 const _Tp __s = std::sin(__phi_red);
00240 const _Tp __c = std::cos(__phi_red);
00241
00242 const _Tp __F = __s
00243 * __ellint_rf(__c * __c,
00244 _Tp(1) - __k * __k * __s * __s, _Tp(1));
00245
00246 if (__n == 0)
00247 return __F;
00248 else
00249 return __F + _Tp(2) * __n * __comp_ellint_1(__k);
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 template<typename _Tp>
00270 _Tp
00271 __comp_ellint_2_series(const _Tp __k)
00272 {
00273
00274 const _Tp __kk = __k * __k;
00275
00276 _Tp __term = __kk;
00277 _Tp __sum = __term;
00278
00279 const unsigned int __max_iter = 1000;
00280 for (unsigned int __i = 2; __i < __max_iter; ++__i)
00281 {
00282 const _Tp __i2m = 2 * __i - 1;
00283 const _Tp __i2 = 2 * __i;
00284 __term *= __i2m * __i2m * __kk / (__i2 * __i2);
00285 if (__term < std::numeric_limits<_Tp>::epsilon())
00286 break;
00287 __sum += __term / __i2m;
00288 }
00289
00290 return __numeric_constants<_Tp>::__pi_2() * (_Tp(1) - __sum);
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 template<typename _Tp>
00318 _Tp
00319 __ellint_rd(const _Tp __x, const _Tp __y, const _Tp __z)
00320 {
00321 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00322 const _Tp __errtol = std::pow(__eps / _Tp(8), _Tp(1) / _Tp(6));
00323 const _Tp __min = std::numeric_limits<_Tp>::min();
00324 const _Tp __max = std::numeric_limits<_Tp>::max();
00325 const _Tp __lolim = _Tp(2) / std::pow(__max, _Tp(2) / _Tp(3));
00326 const _Tp __uplim = std::pow(_Tp(0.1L) * __errtol / __min, _Tp(2) / _Tp(3));
00327
00328 if (__x < _Tp(0) || __y < _Tp(0))
00329 std::__throw_domain_error(__N("Argument less than zero "
00330 "in __ellint_rd."));
00331 else if (__x + __y < __lolim || __z < __lolim)
00332 std::__throw_domain_error(__N("Argument too small "
00333 "in __ellint_rd."));
00334 else
00335 {
00336 const _Tp __c0 = _Tp(1) / _Tp(4);
00337 const _Tp __c1 = _Tp(3) / _Tp(14);
00338 const _Tp __c2 = _Tp(1) / _Tp(6);
00339 const _Tp __c3 = _Tp(9) / _Tp(22);
00340 const _Tp __c4 = _Tp(3) / _Tp(26);
00341
00342 _Tp __xn = __x;
00343 _Tp __yn = __y;
00344 _Tp __zn = __z;
00345 _Tp __sigma = _Tp(0);
00346 _Tp __power4 = _Tp(1);
00347
00348 _Tp __mu;
00349 _Tp __xndev, __yndev, __zndev;
00350
00351 const unsigned int __max_iter = 100;
00352 for (unsigned int __iter = 0; __iter < __max_iter; ++__iter)
00353 {
00354 __mu = (__xn + __yn + _Tp(3) * __zn) / _Tp(5);
00355 __xndev = (__mu - __xn) / __mu;
00356 __yndev = (__mu - __yn) / __mu;
00357 __zndev = (__mu - __zn) / __mu;
00358 _Tp __epsilon = std::max(std::abs(__xndev), std::abs(__yndev));
00359 __epsilon = std::max(__epsilon, std::abs(__zndev));
00360 if (__epsilon < __errtol)
00361 break;
00362 _Tp __xnroot = std::sqrt(__xn);
00363 _Tp __ynroot = std::sqrt(__yn);
00364 _Tp __znroot = std::sqrt(__zn);
00365 _Tp __lambda = __xnroot * (__ynroot + __znroot)
00366 + __ynroot * __znroot;
00367 __sigma += __power4 / (__znroot * (__zn + __lambda));
00368 __power4 *= __c0;
00369 __xn = __c0 * (__xn + __lambda);
00370 __yn = __c0 * (__yn + __lambda);
00371 __zn = __c0 * (__zn + __lambda);
00372 }
00373
00374 _Tp __ea = __xndev * __yndev;
00375 _Tp __eb = __zndev * __zndev;
00376 _Tp __ec = __ea - __eb;
00377 _Tp __ed = __ea - _Tp(6) * __eb;
00378 _Tp __ef = __ed + __ec + __ec;
00379 _Tp __s1 = __ed * (-__c1 + __c3 * __ed
00380 / _Tp(3) - _Tp(3) * __c4 * __zndev * __ef
00381 / _Tp(2));
00382 _Tp __s2 = __zndev
00383 * (__c2 * __ef
00384 + __zndev * (-__c3 * __ec - __zndev * __c4 - __ea));
00385
00386 return _Tp(3) * __sigma + __power4 * (_Tp(1) + __s1 + __s2)
00387 / (__mu * std::sqrt(__mu));
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 template<typename _Tp>
00405 _Tp
00406 __comp_ellint_2(const _Tp __k)
00407 {
00408
00409 if (__isnan(__k))
00410 return std::numeric_limits<_Tp>::quiet_NaN();
00411 else if (std::abs(__k) == 1)
00412 return _Tp(1);
00413 else if (std::abs(__k) > _Tp(1))
00414 std::__throw_domain_error(__N("Bad argument in __comp_ellint_2."));
00415 else
00416 {
00417 const _Tp __kk = __k * __k;
00418
00419 return __ellint_rf(_Tp(0), _Tp(1) - __kk, _Tp(1))
00420 - __kk * __ellint_rd(_Tp(0), _Tp(1) - __kk, _Tp(1)) / _Tp(3);
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 template<typename _Tp>
00439 _Tp
00440 __ellint_2(const _Tp __k, const _Tp __phi)
00441 {
00442
00443 if (__isnan(__k) || __isnan(__phi))
00444 return std::numeric_limits<_Tp>::quiet_NaN();
00445 else if (std::abs(__k) > _Tp(1))
00446 std::__throw_domain_error(__N("Bad argument in __ellint_2."));
00447 else
00448 {
00449
00450 const int __n = std::floor(__phi / __numeric_constants<_Tp>::__pi()
00451 + _Tp(0.5L));
00452 const _Tp __phi_red = __phi
00453 - __n * __numeric_constants<_Tp>::__pi();
00454
00455 const _Tp __kk = __k * __k;
00456 const _Tp __s = std::sin(__phi_red);
00457 const _Tp __ss = __s * __s;
00458 const _Tp __sss = __ss * __s;
00459 const _Tp __c = std::cos(__phi_red);
00460 const _Tp __cc = __c * __c;
00461
00462 const _Tp __E = __s
00463 * __ellint_rf(__cc, _Tp(1) - __kk * __ss, _Tp(1))
00464 - __kk * __sss
00465 * __ellint_rd(__cc, _Tp(1) - __kk * __ss, _Tp(1))
00466 / _Tp(3);
00467
00468 if (__n == 0)
00469 return __E;
00470 else
00471 return __E + _Tp(2) * __n * __comp_ellint_2(__k);
00472 }
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 template<typename _Tp>
00498 _Tp
00499 __ellint_rc(const _Tp __x, const _Tp __y)
00500 {
00501 const _Tp __min = std::numeric_limits<_Tp>::min();
00502 const _Tp __max = std::numeric_limits<_Tp>::max();
00503 const _Tp __lolim = _Tp(5) * __min;
00504 const _Tp __uplim = __max / _Tp(5);
00505
00506 if (__x < _Tp(0) || __y < _Tp(0) || __x + __y < __lolim)
00507 std::__throw_domain_error(__N("Argument less than zero "
00508 "in __ellint_rc."));
00509 else
00510 {
00511 const _Tp __c0 = _Tp(1) / _Tp(4);
00512 const _Tp __c1 = _Tp(1) / _Tp(7);
00513 const _Tp __c2 = _Tp(9) / _Tp(22);
00514 const _Tp __c3 = _Tp(3) / _Tp(10);
00515 const _Tp __c4 = _Tp(3) / _Tp(8);
00516
00517 _Tp __xn = __x;
00518 _Tp __yn = __y;
00519
00520 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00521 const _Tp __errtol = std::pow(__eps / _Tp(30), _Tp(1) / _Tp(6));
00522 _Tp __mu;
00523 _Tp __sn;
00524
00525 const unsigned int __max_iter = 100;
00526 for (unsigned int __iter = 0; __iter < __max_iter; ++__iter)
00527 {
00528 __mu = (__xn + _Tp(2) * __yn) / _Tp(3);
00529 __sn = (__yn + __mu) / __mu - _Tp(2);
00530 if (std::abs(__sn) < __errtol)
00531 break;
00532 const _Tp __lambda = _Tp(2) * std::sqrt(__xn) * std::sqrt(__yn)
00533 + __yn;
00534 __xn = __c0 * (__xn + __lambda);
00535 __yn = __c0 * (__yn + __lambda);
00536 }
00537
00538 _Tp __s = __sn * __sn
00539 * (__c3 + __sn*(__c1 + __sn * (__c4 + __sn * __c2)));
00540
00541 return (_Tp(1) + __s) / std::sqrt(__mu);
00542 }
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 template<typename _Tp>
00569 _Tp
00570 __ellint_rj(const _Tp __x, const _Tp __y, const _Tp __z, const _Tp __p)
00571 {
00572 const _Tp __min = std::numeric_limits<_Tp>::min();
00573 const _Tp __max = std::numeric_limits<_Tp>::max();
00574 const _Tp __lolim = std::pow(_Tp(5) * __min, _Tp(1)/_Tp(3));
00575 const _Tp __uplim = _Tp(0.3L)
00576 * std::pow(_Tp(0.2L) * __max, _Tp(1)/_Tp(3));
00577
00578 if (__x < _Tp(0) || __y < _Tp(0) || __z < _Tp(0))
00579 std::__throw_domain_error(__N("Argument less than zero "
00580 "in __ellint_rj."));
00581 else if (__x + __y < __lolim || __x + __z < __lolim
00582 || __y + __z < __lolim || __p < __lolim)
00583 std::__throw_domain_error(__N("Argument too small "
00584 "in __ellint_rj"));
00585 else
00586 {
00587 const _Tp __c0 = _Tp(1) / _Tp(4);
00588 const _Tp __c1 = _Tp(3) / _Tp(14);
00589 const _Tp __c2 = _Tp(1) / _Tp(3);
00590 const _Tp __c3 = _Tp(3) / _Tp(22);
00591 const _Tp __c4 = _Tp(3) / _Tp(26);
00592
00593 _Tp __xn = __x;
00594 _Tp __yn = __y;
00595 _Tp __zn = __z;
00596 _Tp __pn = __p;
00597 _Tp __sigma = _Tp(0);
00598 _Tp __power4 = _Tp(1);
00599
00600 const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
00601 const _Tp __errtol = std::pow(__eps / _Tp(8), _Tp(1) / _Tp(6));
00602
00603 _Tp __lambda, __mu;
00604 _Tp __xndev, __yndev, __zndev, __pndev;
00605
00606 const unsigned int __max_iter = 100;
00607 for (unsigned int __iter = 0; __iter < __max_iter; ++__iter)
00608 {
00609 __mu = (__xn + __yn + __zn + _Tp(2) * __pn) / _Tp(5);
00610 __xndev = (__mu - __xn) / __mu;
00611 __yndev = (__mu - __yn) / __mu;
00612 __zndev = (__mu - __zn) / __mu;
00613 __pndev = (__mu - __pn) / __mu;
00614 _Tp __epsilon = std::max(std::abs(__xndev), std::abs(__yndev));
00615 __epsilon = std::max(__epsilon, std::abs(__zndev));
00616 __epsilon = std::max(__epsilon, std::abs(__pndev));
00617 if (__epsilon < __errtol)
00618 break;
00619 const _Tp __xnroot = std::sqrt(__xn);
00620 const _Tp __ynroot = std::sqrt(__yn);
00621 const _Tp __znroot = std::sqrt(__zn);
00622 const _Tp __lambda = __xnroot * (__ynroot + __znroot)
00623 + __ynroot * __znroot;
00624 const _Tp __alpha1 = __pn * (__xnroot + __ynroot + __znroot)
00625 + __xnroot * __ynroot * __znroot;
00626 const _Tp __alpha2 = __alpha1 * __alpha1;
00627 const _Tp __beta = __pn * (__pn + __lambda)
00628 * (__pn + __lambda);
00629 __sigma += __power4 * __ellint_rc(__alpha2, __beta);
00630 __power4 *= __c0;
00631 __xn = __c0 * (__xn + __lambda);
00632 __yn = __c0 * (__yn + __lambda);
00633 __zn = __c0 * (__zn + __lambda);
00634 __pn = __c0 * (__pn + __lambda);
00635 }
00636
00637 _Tp __ea = __xndev * (__yndev + __zndev) + __yndev * __zndev;
00638 _Tp __eb = __xndev * __yndev * __zndev;
00639 _Tp __ec = __pndev * __pndev;
00640 _Tp __e2 = __ea - _Tp(3) * __ec;
00641 _Tp __e3 = __eb + _Tp(2) * __pndev * (__ea - __ec);
00642 _Tp __s1 = _Tp(1) + __e2 * (-__c1 + _Tp(3) * __c3 * __e2 / _Tp(4)
00643 - _Tp(3) * __c4 * __e3 / _Tp(2));
00644 _Tp __s2 = __eb * (__c2 / _Tp(2)
00645 + __pndev * (-__c3 - __c3 + __pndev * __c4));
00646 _Tp __s3 = __pndev * __ea * (__c2 - __pndev * __c3)
00647 - __c2 * __pndev * __ec;
00648
00649 return _Tp(3) * __sigma + __power4 * (__s1 + __s2 + __s3)
00650 / (__mu * std::sqrt(__mu));
00651 }
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 template<typename _Tp>
00672 _Tp
00673 __comp_ellint_3(const _Tp __k, const _Tp __nu)
00674 {
00675
00676 if (__isnan(__k) || __isnan(__nu))
00677 return std::numeric_limits<_Tp>::quiet_NaN();
00678 else if (__nu == _Tp(1))
00679 return std::numeric_limits<_Tp>::infinity();
00680 else if (std::abs(__k) > _Tp(1))
00681 std::__throw_domain_error(__N("Bad argument in __comp_ellint_3."));
00682 else
00683 {
00684 const _Tp __kk = __k * __k;
00685
00686 return __ellint_rf(_Tp(0), _Tp(1) - __kk, _Tp(1))
00687 - __nu
00688 * __ellint_rj(_Tp(0), _Tp(1) - __kk, _Tp(1), _Tp(1) + __nu)
00689 / _Tp(3);
00690 }
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 template<typename _Tp>
00712 _Tp
00713 __ellint_3(const _Tp __k, const _Tp __nu, const _Tp __phi)
00714 {
00715
00716 if (__isnan(__k) || __isnan(__nu) || __isnan(__phi))
00717 return std::numeric_limits<_Tp>::quiet_NaN();
00718 else if (std::abs(__k) > _Tp(1))
00719 std::__throw_domain_error(__N("Bad argument in __ellint_3."));
00720 else
00721 {
00722
00723 const int __n = std::floor(__phi / __numeric_constants<_Tp>::__pi()
00724 + _Tp(0.5L));
00725 const _Tp __phi_red = __phi
00726 - __n * __numeric_constants<_Tp>::__pi();
00727
00728 const _Tp __kk = __k * __k;
00729 const _Tp __s = std::sin(__phi_red);
00730 const _Tp __ss = __s * __s;
00731 const _Tp __sss = __ss * __s;
00732 const _Tp __c = std::cos(__phi_red);
00733 const _Tp __cc = __c * __c;
00734
00735 const _Tp __Pi = __s
00736 * __ellint_rf(__cc, _Tp(1) - __kk * __ss, _Tp(1))
00737 - __nu * __sss
00738 * __ellint_rj(__cc, _Tp(1) - __kk * __ss, _Tp(1),
00739 _Tp(1) + __nu * __ss) / _Tp(3);
00740
00741 if (__n == 0)
00742 return __Pi;
00743 else
00744 return __Pi + _Tp(2) * __n * __comp_ellint_3(__k, __nu);
00745 }
00746 }
00747
00748 }
00749 }
00750 }
00751
00752 #endif // _GLIBCXX_TR1_ELL_INTEGRAL_TCC
00753