Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

gamma.cxx

Go to the documentation of this file.
00001 // Gamma function 
00002 
00003 #include "reconstruction/gamma.h"
00004 
00005 
00006 #include <cmath>
00007 
00008 double LnGamma(double z)
00009 {
00010    // Computation of ln[gamma(z)] for all z>0.
00011    //
00012    // The algorithm is based on the article by C.Lanczos [1] as denoted in
00013    // Numerical Recipes 2nd ed. on p. 207 (W.H.Press et al.).
00014    //
00015    // [1] C.Lanczos, SIAM Journal of Numerical Analysis B1 (1964), 86.
00016    //
00017    // The accuracy of the result is better than 2e-10.
00018    //
00019    //--- Nve 14-nov-1998 UU-SAP Utrecht
00020 
00021    if (z<=0) return 0;
00022 
00023    // Coefficients for the series expansion
00024 
00025    double c[7]= { 2.5066282746310005, 76.18009172947146, -86.50532032941677
00026                    ,24.01409824083091,  -1.231739572450155, 0.1208650973866179e-2
00027                    ,-0.5395239384953e-5};
00028 
00029    double x   = z;
00030    double y   = x;
00031    double tmp = x+5.5;
00032    tmp = (x+0.5)*log(tmp)-tmp;
00033    double ser = 1.000000000190015;
00034    for (int i=1; i<7; i++) {
00035       y   += 1;
00036       ser += c[i]/y;
00037    }
00038    double v = tmp+log(c[0]*ser/x);
00039    return v;
00040 }
00041 
00042 
00043 //______________________________________________________________________________
00044  double Gamma(double a,double x)
00045 {
00046    // Computation of the incomplete gamma function P(a,x)
00047    //
00048    // The algorithm is based on the formulas and code as denoted in
00049    // Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.).
00050    //
00051    //--- Nve 14-nov-1998 UU-SAP Utrecht
00052 
00053    if (a <= 0 || x <= 0) return 0;
00054 
00055    if (x < (a+1)) return GamSer(a,x);
00056    else           return GamCf(a,x);
00057 }
00058 
00059 //______________________________________________________________________________
00060  double GamCf(double a,double x)
00061 {
00062    // Computation of the incomplete gamma function P(a,x)
00063    // via its continued fraction representation.
00064    //
00065    // The algorithm is based on the formulas and code as denoted in
00066    // Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.).
00067    //
00068    //--- Nve 14-nov-1998 UU-SAP Utrecht
00069 
00070    int itmax    = 100;      // Maximum number of iterations
00071    double eps   = 3.e-7;    // Relative accuracy
00072    double fpmin = 1.e-30;   // Smallest double value allowed here
00073 
00074    if (a <= 0 || x <= 0) return 0;
00075 
00076    double gln = LnGamma(a);
00077    double b   = x+1-a;
00078    double c   = 1/fpmin;
00079    double d   = 1/b;
00080    double h   = d;
00081    double an,del;
00082    for (int i=1; i<=itmax; i++) {
00083       an = double(-i)*(double(i)-a);
00084       b += 2;
00085       d  = an*d+b;
00086       if (abs(d) < fpmin) d = fpmin;
00087       c = b+an/c;
00088       if (abs(c) < fpmin) c = fpmin;
00089       d   = 1/d;
00090       del = d*c;
00091       h   = h*del;
00092       if (abs(del-1) < eps) break;
00093       //if (i==itmax) cout << "*GamCf(a,x)* a too large or itmax too small" << endl;
00094    }
00095    
00096    double v = exp(-x+a*log(x)-gln)*h;
00097    return (1-v);
00098 }
00099 
00100 //______________________________________________________________________________
00101  double GamSer(double a,double x)
00102 {
00103    // Computation of the incomplete gamma function P(a,x)
00104    // via its series representation.
00105    //
00106    // The algorithm is based on the formulas and code as denoted in
00107    // Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.).
00108    //
00109    //--- Nve 14-nov-1998 UU-SAP Utrecht
00110 
00111    int itmax  = 100;   // Maximum number of iterations
00112    double eps = 3.e-7; // Relative accuracy
00113 
00114    if (a <= 0 || x <= 0) return 0;
00115 
00116    double gln = LnGamma(a);
00117    double ap  = a;
00118    double sum = 1/a;
00119    double del = sum;
00120    for (int n=1; n<=itmax; n++) {
00121       ap  += 1;
00122       del  = del*x/ap;
00123       sum += del;
00124       if (abs(del) < abs(sum*eps)) break;
00125       //if (n==itmax) cout << "*GamSer(a,x)* a too large or itmax too small" << endl;
00126    }
00127    double v = sum*exp(-x+a*log(x)-gln);
00128    return v;
00129 }

Generated at Wed Nov 21 12:20:43 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000