SpecFuncCephes.cxx

Go to the documentation of this file.
00001 //
00002 //
00003 // gamma and related functions from Cephes library
00004 // see:  http://www.netlib.org/cephes
00005 // 
00006 // Copyright 1985, 1987, 2000 by Stephen L. Moshier
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 /* log( sqrt( 2*pi ) ) */
00030 static double LS2PI  =  0.91893853320467274178;
00031 
00032 
00033 // incomplete gamma function (complement integral) 
00034 //  igamc(a,x)   =   1 - igam(a,x)
00035 //
00036 //                            inf.
00037 //                              -
00038 //                     1       | |  -t  a-1
00039 //               =   -----     |   e   t   dt.
00040 //                    -      | |
00041 //                   | (a)    -
00042 //                             x
00043 //
00044 //
00045 
00046 // In this implementation both arguments must be positive.
00047 // The integral is evaluated by either a power series or
00048 // continued fraction expansion, depending on the relative
00049 // values of a and x.
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    // LM: for negative values returns 0.0
00058    // This is correct if a is a negative integer since Gamma(-n) = +/- inf
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 /* continued fraction */
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 /* left tail of incomplete gamma function:
00118  *
00119  *          inf.      k
00120  *   a  -x   -       x
00121  *  x  e     >   ----------
00122  *           -     -
00123  *          k=0   | (a+k+1)
00124  *
00125  */
00126 
00127 double igam( double a, double x )
00128 {
00129    double ans, ax, c, r;
00130 
00131    // LM: for negative values returns 1.0 instead of zero
00132    // This is correct if a is a negative integer since Gamma(-n) = +/- inf
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 /* Compute  x**a * exp(-x) / gamma(a)  */
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 /* power series */
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 /* Logarithm of gamma function */
00166 /* A[]: Stirling's formula expansion of log gamma
00167  * B[], C[]: log gamma function between 2 and 3
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 /* 1.00000000000000000000E0, */
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 )//_unur_FP_same(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 /*      z = log(ROOT::Math::Pi()) - log( z ) - w;*/
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 /* Stirling's formula for the gamma function */
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())        /* sqrt(2*pi) */
00315 /* Stirling formula for the gamma function */
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 /*   #define kMAXSTIR kMAXLOG/log(kMAXLOG)  */
00325 
00326    if( x > kMAXSTIR )
00327    { /* Avoid overflow in pow() */
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 //#define kMAXLGM 2.556348e305
00425 
00426 /*---------------------------------------------------------------------------*/
00427 /* implementation based on cephes log gamma */
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 /* inplementation of the incomplete beta function */
00436 /**
00437  * DESCRIPTION:
00438  *
00439  * Returns incomplete beta integral of the arguments, evaluated
00440  * from zero to x.  The function is defined as
00441  *
00442  *                  x
00443  *     -            -
00444  *    | (a+b)      | |  a-1     b-1
00445  *  -----------    |   t   (1-t)   dt.
00446  *   -     -     | |
00447  *  | (a) | (b)   -
00448  *                 0
00449  *
00450  * The domain of definition is 0 <= x <= 1.  In this
00451  * implementation a and b are restricted to positive values.
00452  * The integral from x to 1 may be obtained by the symmetry
00453  * relation
00454  *
00455  *    1 - incbet( a, b, x )  =  incbet( b, a, 1-x ).
00456  *
00457  * The integral is evaluated by a continued fraction expansion
00458  * or, when b*x is small, by a power series.
00459  *
00460  * ACCURACY:
00461  *
00462  * Tested at uniformly distributed random points (a,b,x) with a and b
00463  * in "domain" and x between 0 and 1.
00464  *                                        Relative error
00465  * arithmetic   domain     # trials      peak         rms
00466  *    IEEE      0,5         10000       6.9e-15     4.5e-16
00467  *    IEEE      0,85       250000       2.2e-13     1.7e-14
00468  *    IEEE      0,1000      30000       5.3e-12     6.3e-13
00469  *    IEEE      0,10000    250000       9.3e-11     7.1e-12
00470  *    IEEE      0,100000    10000       8.7e-10     4.8e-11
00471  * Outputs smaller than the IEEE gradual underflow threshold
00472  * were excluded from these statistics.
00473  *
00474  * ERROR MESSAGES:
00475  *   message         condition      value returned
00476  * incbet domain      x<0, x>1          0.0
00477  * incbet underflow                     0.0
00478  *
00479  *  Cephes Math Library, Release 2.8:  June, 2000
00480  * Copyright 1984, 1995, 2000 by Stephen L. Moshier
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    // LM: changed: for X > 1 return 1.
00493    if  (xx <= 0.0)  return( 0.0 );
00494    if ( xx >= 1.0)  return( 1.0 );
00495 
00496    flag = 0;
00497 
00498 /* - to test if that way is better for large b/  (comment out from Cephes version)
00499    if( (bb * xx) <= 1.0 && xx <= 0.95)
00500    {
00501    t = pseries(aa, bb, xx);
00502    goto done;
00503    }
00504 
00505 **/
00506    w = 1.0 - xx;
00507 
00508 /* Reverse a and b if x is greater than the mean. */
00509 /* aa,bb > 1 -> sharp rise at x=aa/(aa+bb) */
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 /* Choose expansion for better convergence. */
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 /* Multiply w by the factor
00540    a      b   _             _     _
00541    x  (1-x)   | (a+b) / ( a | (a) | (b) ) .   */
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 /* Resort to logarithms.  */
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 /* Continued fraction expansion #1
00578  * for incomplete beta integral
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 /* Continued fraction expansion #2
00671  * for incomplete beta integral
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 /* Power series for incomplete beta integral.
00764    Use when b*x is small and x not too close to 1.  */
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 /* for evaluation of error function */
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 /* 1.00000000000000000000E0,*/
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 /* 1.00000000000000000000E0,*/
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 /* 1.00000000000000000000E0,*/
00861    3.35617141647503099647E1,
00862    5.21357949780152679795E2,
00863    4.59432382970980127987E3,
00864    2.26290000613890934246E4,
00865    4.92673942608635921086E4
00866 };
00867 
00868 /*---------------------------------------------------------------------------*/
00869 /* complementary error function */
00870 /* For small x, erfc(x) = 1 - erf(x); otherwise rational */
00871 /* approximations are computed. */
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 /* error function */
00923 /* For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise */
00924 /* erf(x) = 1 - erfc(x). */
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 } // end namespace Cephes
00939 
00940 
00941 /*---------------------------------------------------------------------------*/
00942 
00943 /*---------------------------------------------------------------------------*/
00944 /* Routines used within this implementation */
00945 
00946 
00947 /*
00948  * calculates a value of a polynomial of the form:
00949  * a[0]x^N+a[1]x^(N-1) + ... + a[N]
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  * calculates a value of a polynomial of the form:
00965  * x^N+a[0]x^(N-1) + ... + a[N-1]
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 } // end namespace Math
00981 } // end namespace ROOT
00982 

Generated on Tue Jul 5 14:34:26 2011 for ROOT_528-00b_version by  doxygen 1.5.1