00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "SpecFuncCephes.h"
00011 #include "Math/Math.h"
00012
00013
00014 #include <cmath>
00015
00016 #include <limits>
00017
00018
00019
00020 namespace ROOT {
00021 namespace Math {
00022
00023 namespace Cephes {
00024
00025
00026 static double kBig = 4.503599627370496e15;
00027 static double kBiginv = 2.22044604925031308085e-16;
00028
00029
00030 static double LS2PI = 0.91893853320467274178;
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 double igamc( double a, double x )
00052 {
00053
00054 double ans, ax, c, yc, r, t, y, z;
00055 double pk, pkm1, pkm2, qk, qkm1, qkm2;
00056
00057
00058
00059 if (a <= 0) return 0.0;
00060
00061 if (x <= 0) return 1.0;
00062
00063 if( (x < 1.0) || (x < a) )
00064 return( 1.0 - igam(a,x) );
00065
00066 ax = a * std::log(x) - x - lgam(a);
00067 if( ax < -kMAXLOG )
00068 return( 0.0 );
00069
00070 ax = std::exp(ax);
00071
00072
00073 y = 1.0 - a;
00074 z = x + y + 1.0;
00075 c = 0.0;
00076 pkm2 = 1.0;
00077 qkm2 = x;
00078 pkm1 = x + 1.0;
00079 qkm1 = z * x;
00080 ans = pkm1/qkm1;
00081
00082 do
00083 {
00084 c += 1.0;
00085 y += 1.0;
00086 z += 2.0;
00087 yc = y * c;
00088 pk = pkm1 * z - pkm2 * yc;
00089 qk = qkm1 * z - qkm2 * yc;
00090 if(qk)
00091 {
00092 r = pk/qk;
00093 t = std::abs( (ans - r)/r );
00094 ans = r;
00095 }
00096 else
00097 t = 1.0;
00098 pkm2 = pkm1;
00099 pkm1 = pk;
00100 qkm2 = qkm1;
00101 qkm1 = qk;
00102 if( std::abs(pk) > kBig )
00103 {
00104 pkm2 *= kBiginv;
00105 pkm1 *= kBiginv;
00106 qkm2 *= kBiginv;
00107 qkm1 *= kBiginv;
00108 }
00109 }
00110 while( t > kMACHEP );
00111
00112 return( ans * ax );
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 double igam( double a, double x )
00128 {
00129 double ans, ax, c, r;
00130
00131
00132
00133 if (a <= 0) return 1.0;
00134
00135 if (x <= 0) return 0.0;
00136
00137 if( (x > 1.0) && (x > a ) )
00138 return( 1.0 - igamc(a,x) );
00139
00140
00141 ax = a * std::log(x) - x - lgam(a);
00142 if( ax < -kMAXLOG )
00143 return( 0.0 );
00144
00145 ax = std::exp(ax);
00146
00147
00148 r = a;
00149 c = 1.0;
00150 ans = 1.0;
00151
00152 do
00153 {
00154 r += 1.0;
00155 c *= x/r;
00156 ans += c;
00157 }
00158 while( c/ans > kMACHEP );
00159
00160 return( ans * ax/a );
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170 static double A[] = {
00171 8.11614167470508450300E-4,
00172 -5.95061904284301438324E-4,
00173 7.93650340457716943945E-4,
00174 -2.77777777730099687205E-3,
00175 8.33333333333331927722E-2
00176 };
00177
00178 static double B[] = {
00179 -1.37825152569120859100E3,
00180 -3.88016315134637840924E4,
00181 -3.31612992738871184744E5,
00182 -1.16237097492762307383E6,
00183 -1.72173700820839662146E6,
00184 -8.53555664245765465627E5
00185 };
00186
00187 static double C[] = {
00188
00189 -3.51815701436523470549E2,
00190 -1.70642106651881159223E4,
00191 -2.20528590553854454839E5,
00192 -1.13933444367982507207E6,
00193 -2.53252307177582951285E6,
00194 -2.01889141433532773231E6
00195 };
00196
00197 double lgam( double x )
00198 {
00199 double p, q, u, w, z;
00200 int i;
00201
00202 int sgngam = 1;
00203
00204 if (x >= std::numeric_limits<double>::infinity())
00205 return(std::numeric_limits<double>::infinity());
00206
00207 if( x < -34.0 )
00208 {
00209 q = -x;
00210 w = lgam(q);
00211 p = std::floor(q);
00212 if( p==q )
00213 return (std::numeric_limits<double>::infinity());
00214 i = (int) p;
00215 if( (i & 1) == 0 )
00216 sgngam = -1;
00217 else
00218 sgngam = 1;
00219 z = q - p;
00220 if( z > 0.5 )
00221 {
00222 p += 1.0;
00223 z = p - q;
00224 }
00225 z = q * std::sin( ROOT::Math::Pi() * z );
00226 if( z == 0 )
00227 return (std::numeric_limits<double>::infinity());
00228
00229 z = std::log(ROOT::Math::Pi()) - std::log( z ) - w;
00230 return( z );
00231 }
00232
00233 if( x < 13.0 )
00234 {
00235 z = 1.0;
00236 p = 0.0;
00237 u = x;
00238 while( u >= 3.0 )
00239 {
00240 p -= 1.0;
00241 u = x + p;
00242 z *= u;
00243 }
00244 while( u < 2.0 )
00245 {
00246 if( u == 0 )
00247 return (std::numeric_limits<double>::infinity());
00248 z /= u;
00249 p += 1.0;
00250 u = x + p;
00251 }
00252 if( z < 0.0 )
00253 {
00254 sgngam = -1;
00255 z = -z;
00256 }
00257 else
00258 sgngam = 1;
00259 if( u == 2.0 )
00260 return( std::log(z) );
00261 p -= 2.0;
00262 x = x + p;
00263 p = x * Polynomialeval(x, B, 5 ) / Polynomial1eval( x, C, 6);
00264 return( std::log(z) + p );
00265 }
00266
00267 if( x > kMAXLGM )
00268 return( sgngam * std::numeric_limits<double>::infinity() );
00269
00270 q = ( x - 0.5 ) * std::log(x) - x + LS2PI;
00271 if( x > 1.0e8 )
00272 return( q );
00273
00274 p = 1.0/(x*x);
00275 if( x >= 1000.0 )
00276 q += (( 7.9365079365079365079365e-4 * p
00277 - 2.7777777777777777777778e-3) *p
00278 + 0.0833333333333333333333) / x;
00279 else
00280 q += Polynomialeval( p, A, 4 ) / x;
00281 return( q );
00282 }
00283
00284
00285 static double P[] = {
00286 1.60119522476751861407E-4,
00287 1.19135147006586384913E-3,
00288 1.04213797561761569935E-2,
00289 4.76367800457137231464E-2,
00290 2.07448227648435975150E-1,
00291 4.94214826801497100753E-1,
00292 9.99999999999999996796E-1
00293 };
00294 static double Q[] = {
00295 -2.31581873324120129819E-5,
00296 5.39605580493303397842E-4,
00297 -4.45641913851797240494E-3,
00298 1.18139785222060435552E-2,
00299 3.58236398605498653373E-2,
00300 -2.34591795718243348568E-1,
00301 7.14304917030273074085E-2,
00302 1.00000000000000000320E0
00303 };
00304
00305
00306 static double STIR[5] = {
00307 7.87311395793093628397E-4,
00308 -2.29549961613378126380E-4,
00309 -2.68132617805781232825E-3,
00310 3.47222221605458667310E-3,
00311 8.33333333333482257126E-2,
00312 };
00313
00314 #define SQTPI std::sqrt(2*ROOT::Math::Pi())
00315
00316 static double stirf( double x)
00317 {
00318 double y, w, v;
00319
00320 w = 1.0/x;
00321 w = 1.0 + w * Polynomialeval( w, STIR, 4 );
00322 y = exp(x);
00323
00324
00325
00326 if( x > kMAXSTIR )
00327 {
00328 v = pow( x, 0.5 * x - 0.25 );
00329 y = v * (v / y);
00330 }
00331 else
00332 {
00333 y = pow( x, x - 0.5 ) / y;
00334 }
00335 y = SQTPI * y * w;
00336 return( y );
00337 }
00338
00339 double gamma( double x )
00340 {
00341 double p, q, z;
00342 int i;
00343
00344 int sgngam = 1;
00345
00346 if (x >=std::numeric_limits<double>::infinity())
00347 return(x);
00348
00349 q = std::abs(x);
00350
00351 if( q > 33.0 )
00352 {
00353 if( x < 0.0 )
00354 {
00355 p = std::floor(q);
00356 if( p == q )
00357 {
00358 return( sgngam * std::numeric_limits<double>::infinity());
00359 }
00360 i = (int) p;
00361 if( (i & 1) == 0 )
00362 sgngam = -1;
00363 z = q - p;
00364 if( z > 0.5 )
00365 {
00366 p += 1.0;
00367 z = q - p;
00368 }
00369 z = q * std::sin( ROOT::Math::Pi() * z );
00370 if( z == 0 )
00371 {
00372 return( sgngam * std::numeric_limits<double>::infinity());
00373 }
00374 z = std::abs(z);
00375 z = ROOT::Math::Pi()/(z * stirf(q) );
00376 }
00377 else
00378 {
00379 z = stirf(x);
00380 }
00381 return( sgngam * z );
00382 }
00383
00384 z = 1.0;
00385 while( x >= 3.0 )
00386 {
00387 x -= 1.0;
00388 z *= x;
00389 }
00390
00391 while( x < 0.0 )
00392 {
00393 if( x > -1.E-9 )
00394 goto small;
00395 z /= x;
00396 x += 1.0;
00397 }
00398
00399 while( x < 2.0 )
00400 {
00401 if( x < 1.e-9 )
00402 goto small;
00403 z /= x;
00404 x += 1.0;
00405 }
00406
00407 if( x == 2.0 )
00408 return(z);
00409
00410 x -= 2.0;
00411 p = Polynomialeval( x, P, 6 );
00412 q = Polynomialeval( x, Q, 7 );
00413 return( z * p / q );
00414
00415 small:
00416 if( x == 0 )
00417 return( std::numeric_limits<double>::infinity() );
00418 else
00419 return( z/((1.0 + 0.5772156649015329 * x) * x) );
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 double beta(double z, double w)
00429 {
00430 return std::exp(ROOT::Math::Cephes::lgam(z) + ROOT::Math::Cephes::lgam(w)- ROOT::Math::Cephes::lgam(z+w) );
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 double incbet( double aa, double bb, double xx )
00485 {
00486 double a, b, t, x, xc, w, y;
00487 int flag;
00488
00489 if( aa <= 0.0 || bb <= 0.0 )
00490 return( 0.0 );
00491
00492
00493 if (xx <= 0.0) return( 0.0 );
00494 if ( xx >= 1.0) return( 1.0 );
00495
00496 flag = 0;
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 w = 1.0 - xx;
00507
00508
00509
00510 if( xx > (aa/(aa+bb)) )
00511 {
00512 flag = 1;
00513 a = bb;
00514 b = aa;
00515 xc = xx;
00516 x = w;
00517 }
00518 else
00519 {
00520 a = aa;
00521 b = bb;
00522 xc = w;
00523 x = xx;
00524 }
00525
00526 if( flag == 1 && (b * x) <= 1.0 && x <= 0.95)
00527 {
00528 t = pseries(a, b, x);
00529 goto done;
00530 }
00531
00532
00533 y = x * (a+b-2.0) - (a-1.0);
00534 if( y < 0.0 )
00535 w = incbcf( a, b, x );
00536 else
00537 w = incbd( a, b, x ) / xc;
00538
00539
00540
00541
00542
00543 y = a * std::log(x);
00544 t = b * std::log(xc);
00545 if( (a+b) < kMAXSTIR && std::abs(y) < kMAXLOG && std::abs(t) < kMAXLOG )
00546 {
00547 t = pow(xc,b);
00548 t *= pow(x,a);
00549 t /= a;
00550 t *= w;
00551 t *= ROOT::Math::Cephes::gamma(a+b) / (ROOT::Math::Cephes::gamma(a) * ROOT::Math::Cephes::gamma(b));
00552 goto done;
00553 }
00554
00555 y += t + lgam(a+b) - lgam(a) - lgam(b);
00556 y += std::log(w/a);
00557 if( y < kMINLOG )
00558 t = 0.0;
00559 else
00560 t = std::exp(y);
00561
00562 done:
00563
00564 if( flag == 1 )
00565 {
00566 if( t <= kMACHEP )
00567 t = 1.0 - kMACHEP;
00568 else
00569 t = 1.0 - t;
00570 }
00571 return( t );
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581 double incbcf( double a, double b, double x )
00582 {
00583 double xk, pk, pkm1, pkm2, qk, qkm1, qkm2;
00584 double k1, k2, k3, k4, k5, k6, k7, k8;
00585 double r, t, ans, thresh;
00586 int n;
00587
00588 k1 = a;
00589 k2 = a + b;
00590 k3 = a;
00591 k4 = a + 1.0;
00592 k5 = 1.0;
00593 k6 = b - 1.0;
00594 k7 = k4;
00595 k8 = a + 2.0;
00596
00597 pkm2 = 0.0;
00598 qkm2 = 1.0;
00599 pkm1 = 1.0;
00600 qkm1 = 1.0;
00601 ans = 1.0;
00602 r = 1.0;
00603 n = 0;
00604 thresh = 3.0 * kMACHEP;
00605 do
00606 {
00607
00608 xk = -( x * k1 * k2 )/( k3 * k4 );
00609 pk = pkm1 + pkm2 * xk;
00610 qk = qkm1 + qkm2 * xk;
00611 pkm2 = pkm1;
00612 pkm1 = pk;
00613 qkm2 = qkm1;
00614 qkm1 = qk;
00615
00616 xk = ( x * k5 * k6 )/( k7 * k8 );
00617 pk = pkm1 + pkm2 * xk;
00618 qk = qkm1 + qkm2 * xk;
00619 pkm2 = pkm1;
00620 pkm1 = pk;
00621 qkm2 = qkm1;
00622 qkm1 = qk;
00623
00624 if( qk !=0 )
00625 r = pk/qk;
00626 if( r != 0 )
00627 {
00628 t = std::abs( (ans - r)/r );
00629 ans = r;
00630 }
00631 else
00632 t = 1.0;
00633
00634 if( t < thresh )
00635 goto cdone;
00636
00637 k1 += 1.0;
00638 k2 += 1.0;
00639 k3 += 2.0;
00640 k4 += 2.0;
00641 k5 += 1.0;
00642 k6 -= 1.0;
00643 k7 += 2.0;
00644 k8 += 2.0;
00645
00646 if( (std::abs(qk) + std::abs(pk)) > kBig )
00647 {
00648 pkm2 *= kBiginv;
00649 pkm1 *= kBiginv;
00650 qkm2 *= kBiginv;
00651 qkm1 *= kBiginv;
00652 }
00653 if( (std::abs(qk) < kBiginv) || (std::abs(pk) < kBiginv) )
00654 {
00655 pkm2 *= kBig;
00656 pkm1 *= kBig;
00657 qkm2 *= kBig;
00658 qkm1 *= kBig;
00659 }
00660 }
00661 while( ++n < 300 );
00662
00663 cdone:
00664 return(ans);
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674 double incbd( double a, double b, double x )
00675 {
00676 double xk, pk, pkm1, pkm2, qk, qkm1, qkm2;
00677 double k1, k2, k3, k4, k5, k6, k7, k8;
00678 double r, t, ans, z, thresh;
00679 int n;
00680
00681 k1 = a;
00682 k2 = b - 1.0;
00683 k3 = a;
00684 k4 = a + 1.0;
00685 k5 = 1.0;
00686 k6 = a + b;
00687 k7 = a + 1.0;;
00688 k8 = a + 2.0;
00689
00690 pkm2 = 0.0;
00691 qkm2 = 1.0;
00692 pkm1 = 1.0;
00693 qkm1 = 1.0;
00694 z = x / (1.0-x);
00695 ans = 1.0;
00696 r = 1.0;
00697 n = 0;
00698 thresh = 3.0 * kMACHEP;
00699 do
00700 {
00701
00702 xk = -( z * k1 * k2 )/( k3 * k4 );
00703 pk = pkm1 + pkm2 * xk;
00704 qk = qkm1 + qkm2 * xk;
00705 pkm2 = pkm1;
00706 pkm1 = pk;
00707 qkm2 = qkm1;
00708 qkm1 = qk;
00709
00710 xk = ( z * k5 * k6 )/( k7 * k8 );
00711 pk = pkm1 + pkm2 * xk;
00712 qk = qkm1 + qkm2 * xk;
00713 pkm2 = pkm1;
00714 pkm1 = pk;
00715 qkm2 = qkm1;
00716 qkm1 = qk;
00717
00718 if( qk != 0 )
00719 r = pk/qk;
00720 if( r != 0 )
00721 {
00722 t = std::abs( (ans - r)/r );
00723 ans = r;
00724 }
00725 else
00726 t = 1.0;
00727
00728 if( t < thresh )
00729 goto cdone;
00730
00731 k1 += 1.0;
00732 k2 -= 1.0;
00733 k3 += 2.0;
00734 k4 += 2.0;
00735 k5 += 1.0;
00736 k6 += 1.0;
00737 k7 += 2.0;
00738 k8 += 2.0;
00739
00740 if( (std::abs(qk) + std::abs(pk)) > kBig )
00741 {
00742 pkm2 *= kBiginv;
00743 pkm1 *= kBiginv;
00744 qkm2 *= kBiginv;
00745 qkm1 *= kBiginv;
00746 }
00747 if( (std::abs(qk) < kBiginv) || (std::abs(pk) < kBiginv) )
00748 {
00749 pkm2 *= kBig;
00750 pkm1 *= kBig;
00751 qkm2 *= kBig;
00752 qkm1 *= kBig;
00753 }
00754 }
00755 while( ++n < 300 );
00756 cdone:
00757 return(ans);
00758 }
00759
00760
00761
00762
00763
00764
00765
00766 double pseries( double a, double b, double x )
00767 {
00768 double s, t, u, v, n, t1, z, ai;
00769
00770 ai = 1.0 / a;
00771 u = (1.0 - b) * x;
00772 v = u / (a + 1.0);
00773 t1 = v;
00774 t = u;
00775 n = 2.0;
00776 s = 0.0;
00777 z = kMACHEP * ai;
00778 while( std::abs(v) > z )
00779 {
00780 u = (n - b) * x / n;
00781 t *= u;
00782 v = t / (a + n);
00783 s += v;
00784 n += 1.0;
00785 }
00786 s += t1;
00787 s += ai;
00788
00789 u = a * log(x);
00790 if( (a+b) < kMAXSTIR && std::abs(u) < kMAXLOG )
00791 {
00792 t = gamma(a+b)/(gamma(a)*gamma(b));
00793 s = s * t * pow(x,a);
00794 }
00795 else
00796 {
00797 t = lgam(a+b) - lgam(a) - lgam(b) + u + std::log(s);
00798 if( t < kMINLOG )
00799 s = 0.0;
00800 else
00801 s = std::exp(t);
00802 }
00803 return(s);
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813 static double erfP[] = {
00814 2.46196981473530512524E-10,
00815 5.64189564831068821977E-1,
00816 7.46321056442269912687E0,
00817 4.86371970985681366614E1,
00818 1.96520832956077098242E2,
00819 5.26445194995477358631E2,
00820 9.34528527171957607540E2,
00821 1.02755188689515710272E3,
00822 5.57535335369399327526E2
00823 };
00824 static double erfQ[] = {
00825
00826 1.32281951154744992508E1,
00827 8.67072140885989742329E1,
00828 3.54937778887819891062E2,
00829 9.75708501743205489753E2,
00830 1.82390916687909736289E3,
00831 2.24633760818710981792E3,
00832 1.65666309194161350182E3,
00833 5.57535340817727675546E2
00834 };
00835 static double erfR[] = {
00836 5.64189583547755073984E-1,
00837 1.27536670759978104416E0,
00838 5.01905042251180477414E0,
00839 6.16021097993053585195E0,
00840 7.40974269950448939160E0,
00841 2.97886665372100240670E0
00842 };
00843 static double erfS[] = {
00844
00845 2.26052863220117276590E0,
00846 9.39603524938001434673E0,
00847 1.20489539808096656605E1,
00848 1.70814450747565897222E1,
00849 9.60896809063285878198E0,
00850 3.36907645100081516050E0
00851 };
00852 static double erfT[] = {
00853 9.60497373987051638749E0,
00854 9.00260197203842689217E1,
00855 2.23200534594684319226E3,
00856 7.00332514112805075473E3,
00857 5.55923013010394962768E4
00858 };
00859 static double erfU[] = {
00860
00861 3.35617141647503099647E1,
00862 5.21357949780152679795E2,
00863 4.59432382970980127987E3,
00864 2.26290000613890934246E4,
00865 4.92673942608635921086E4
00866 };
00867
00868
00869
00870
00871
00872
00873
00874 double erfc( double a )
00875 {
00876 double p,q,x,y,z;
00877
00878
00879 if( a < 0.0 )
00880 x = -a;
00881 else
00882 x = a;
00883
00884 if( x < 1.0 )
00885 return( 1.0 - ROOT::Math::Cephes::erf(a) );
00886
00887 z = -a * a;
00888
00889 if( z < -kMAXLOG )
00890 {
00891 under:
00892 if( a < 0 )
00893 return( 2.0 );
00894 else
00895 return( 0.0 );
00896 }
00897
00898 z = exp(z);
00899
00900 if( x < 8.0 )
00901 {
00902 p = Polynomialeval( x, erfP, 8 );
00903 q = Polynomial1eval( x, erfQ, 8 );
00904 }
00905 else
00906 {
00907 p = Polynomialeval( x, erfR, 5 );
00908 q = Polynomial1eval( x, erfS, 6 );
00909 }
00910 y = (z * p)/q;
00911
00912 if( a < 0 )
00913 y = 2.0 - y;
00914
00915 if( y == 0 )
00916 goto under;
00917
00918 return(y);
00919 }
00920
00921
00922
00923
00924
00925
00926 double erf( double x)
00927 {
00928 double y, z;
00929
00930 if( std::abs(x) > 1.0 )
00931 return( 1.0 - ROOT::Math::Cephes::erfc(x) );
00932 z = x * x;
00933 y = x * Polynomialeval( z, erfT, 4 ) / Polynomial1eval( z, erfU, 5 );
00934 return( y );
00935
00936 }
00937
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951 double Polynomialeval(double x, double* a, unsigned int N)
00952 {
00953 if (N==0) return a[0];
00954 else
00955 {
00956 double pom = a[0];
00957 for (unsigned int i=1; i <= N; i++)
00958 pom = pom *x + a[i];
00959 return pom;
00960 }
00961 }
00962
00963
00964
00965
00966
00967 double Polynomial1eval(double x, double* a, unsigned int N)
00968 {
00969 if (N==0) return a[0];
00970 else
00971 {
00972 double pom = x + a[0];
00973 for (unsigned int i=1; i < N; i++)
00974 pom = pom *x + a[i];
00975 return pom;
00976 }
00977 }
00978
00979
00980 }
00981 }
00982