Go to the documentation of this file.00001 #include "mbl_gamma.h"
00002 #include <vcl_iostream.h>
00003 #include <vcl_cmath.h>
00004 #include <vcl_cstdlib.h>
00005
00006 const int MAX_ITS = 200;
00007 const double EPS = 3.0e-7;
00008 const double FPMIN = 1.0e-30;
00009
00010 double mbl_log_gamma(double xx)
00011 {
00012 double x,y,tmp,ser;
00013 static double cof[6]={76.18009172947146,-86.50532032941677,
00014 24.01409824083091,-1.231739572450155,
00015 0.1208650973866179e-2,-0.5395239384953e-5};
00016 int j;
00017
00018 y=x=xx;
00019 tmp=x+5.5;
00020 tmp -= (x+0.5)*vcl_log(tmp);
00021 ser=1.000000000190015;
00022 for (j=0;j<=5;j++) ser += cof[j]/++y;
00023 return -tmp+vcl_log(2.5066282746310005*ser/x);
00024 }
00025
00026
00027 static double mbl_gamma_ser(double a, double x)
00028 {
00029 int n;
00030 double sum,del,ap,gln;
00031
00032 gln=mbl_log_gamma(a);
00033 if (x>0)
00034 {
00035 ap=a;
00036 del=sum=1.0/a;
00037 for (n=1;n<=MAX_ITS;n++)
00038 {
00039 ++ap;
00040 del *= x/ap;
00041 sum += del;
00042 if (vcl_fabs(del) < vcl_fabs(sum)*EPS)
00043 {
00044 return sum*vcl_exp(-x+a*vcl_log(x)-(gln));
00045 }
00046 }
00047 vcl_cerr<<"mbl_gamma_ser : Failed to converge."<<vcl_endl;
00048 vcl_cerr<<"a = "<<a<<" x= "<<x<<vcl_endl;
00049 vcl_cerr<<"Returning best guess."<<vcl_endl;
00050
00051 }
00052 else
00053 {
00054 if (x < 0.0)
00055 {
00056 vcl_cerr<<"mbl_gamma_ser : x less than 0"<<vcl_endl;
00057 vcl_abort();
00058 }
00059 }
00060
00061 return 0.0;
00062 }
00063
00064
00065 static double NR_log_gamma_cf(double a, double x)
00066 {
00067 int i;
00068 double an,b,c,d,del,h,gln;
00069
00070 gln=mbl_log_gamma(a);
00071 b=x+1.0-a;
00072 c=1.0/FPMIN;
00073 d=1.0/b;
00074 h=d;
00075 for (i=1;i<=MAX_ITS;i++)
00076 {
00077 an = -i*(i-a);
00078 b += 2.0;
00079 d=an*d+b;
00080 if (vcl_fabs(d) < FPMIN) d=FPMIN;
00081 c=b+an/c;
00082 if (vcl_fabs(c) < FPMIN) c=FPMIN;
00083 d=1.0/d;
00084 del=d*c;
00085 h *= del;
00086 if (vcl_fabs(del-1.0) < EPS) break;
00087 }
00088 if (i > MAX_ITS)
00089 {
00090 vcl_cerr<<"NR_log_gamma_cf : Failed to converge."<<vcl_endl;
00091 vcl_abort();
00092 }
00093 return -x+a*vcl_log(x)-(gln)+vcl_log(h);
00094 }
00095
00096 static double mbl_gamma_cf(double a, double x)
00097 {
00098 int i;
00099 double an,b,c,d,del,h,gln;
00100
00101 gln=mbl_log_gamma(a);
00102 b=x+1.0-a;
00103 c=1.0/FPMIN;
00104 d=1.0/b;
00105 h=d;
00106 for (i=1;i<=MAX_ITS;i++)
00107 {
00108 an = -i*(i-a);
00109 b += 2.0;
00110 d=an*d+b;
00111 if (vcl_fabs(d) < FPMIN) d=FPMIN;
00112 c=b+an/c;
00113 if (vcl_fabs(c) < FPMIN) c=FPMIN;
00114 d=1.0/d;
00115 del=d*c;
00116 h *= del;
00117 if (vcl_fabs(del-1.0) < EPS) break;
00118 }
00119 if (i > MAX_ITS)
00120 {
00121 vcl_cerr<<"mbl_gamma_cf : Failed to converge. a="<<a<<" x="<<x<<vcl_endl;
00122 return 1.0;
00123 }
00124 return vcl_exp(-x+a*vcl_log(x)-(gln))*h;
00125 }
00126
00127 double mbl_gamma_p(double a, double x)
00128 {
00129 #ifndef NDEBUG
00130 if ((x < 0.0) || (a <= 0.0))
00131 {
00132 vcl_cerr<<"mbl_gamma_p : Invalid arguments."<<vcl_endl;
00133 vcl_abort();
00134 }
00135 #endif
00136
00137 if (x < (a+1.0))
00138 {
00139 return mbl_gamma_ser(a,x);
00140 }
00141 else
00142 {
00143 return 1 - mbl_gamma_cf(a,x);
00144 }
00145 }
00146
00147 double mbl_gamma_q(double a, double x)
00148 {
00149 #ifndef NDEBUG
00150 if ((x < 0.0) || (a <= 0.0))
00151 {
00152 vcl_cerr<<"mbl_gamma_q : Invalid arguments."<<vcl_endl;
00153 vcl_abort();
00154 }
00155 #endif
00156
00157 if (x < (a+1.0))
00158 {
00159 return 1.0-mbl_gamma_ser(a,x);
00160 }
00161 else
00162 {
00163 return mbl_gamma_cf(a,x);
00164 }
00165 }
00166
00167 double mbl_log_gamma_q(double a, double x)
00168 {
00169 #ifndef NDEBUG
00170 if ((x < 0.0) || (a <= 0.0))
00171 {
00172 vcl_cerr<<"mbl_log_gamma_q : Invalid arguments."<<vcl_endl;
00173 vcl_abort();
00174 }
00175 #endif
00176
00177 if (x < (a+1.0))
00178 {
00179 return vcl_log(1.0 - mbl_gamma_ser(a,x));
00180 }
00181 else
00182 {
00183 return NR_log_gamma_cf(a,x);
00184 }
00185 }