00001
00002
00003 #include "reconstruction/gamma.h"
00004
00005
00006 #include <cmath>
00007
00008 double LnGamma(double z)
00009 {
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 if (z<=0) return 0;
00022
00023
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
00047
00048
00049
00050
00051
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
00063
00064
00065
00066
00067
00068
00069
00070 int itmax = 100;
00071 double eps = 3.e-7;
00072 double fpmin = 1.e-30;
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
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
00104
00105
00106
00107
00108
00109
00110
00111 int itmax = 100;
00112 double eps = 3.e-7;
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
00126 }
00127 double v = sum*exp(-x+a*log(x)-gln);
00128 return v;
00129 }