1 |
|
---|
2 | #include <math.h>
|
---|
3 | #include <float.h>
|
---|
4 |
|
---|
5 | #include <chemistry/qc/intv3/fjt.h>
|
---|
6 | #include <util/misc/formio.h>
|
---|
7 |
|
---|
8 | using namespace std;
|
---|
9 | using namespace sc;
|
---|
10 |
|
---|
11 | // this should only be used for x < a + 1
|
---|
12 | static double
|
---|
13 | mgamma_small_x(double a, double x)
|
---|
14 | {
|
---|
15 | const int nterm = 1000;
|
---|
16 | // n = 0
|
---|
17 | double xn = 1.0;
|
---|
18 | double an = a;
|
---|
19 | double c0 = xn/an;
|
---|
20 | int n = 1;
|
---|
21 | double sum = c0;
|
---|
22 | double contrib;
|
---|
23 | double c0eps = c0 * DBL_EPSILON;
|
---|
24 | do {
|
---|
25 | an *= a+n;
|
---|
26 | xn *= x;
|
---|
27 | contrib = xn/an;
|
---|
28 | n++;
|
---|
29 | sum += contrib;
|
---|
30 | } while(contrib > c0eps);
|
---|
31 | return sum * exp(-x);
|
---|
32 | }
|
---|
33 |
|
---|
34 | static double
|
---|
35 | Gamma_m(int m, double x)
|
---|
36 | {
|
---|
37 | double a = m+0.5;
|
---|
38 | const double tiny = DBL_EPSILON * DBL_EPSILON;
|
---|
39 | // iteration 0
|
---|
40 | double f = tiny;
|
---|
41 | double c = f;
|
---|
42 | double d = 0.0;
|
---|
43 | double delta;
|
---|
44 | // iteration 1 +
|
---|
45 | int j=1;
|
---|
46 | double ac = 1.0;
|
---|
47 | double bc = x + 1.0 - a;
|
---|
48 | do {
|
---|
49 | d = bc + ac * d;
|
---|
50 | if (d == 0.0) d = tiny;
|
---|
51 | c = bc + ac/c;
|
---|
52 | if (c == 0.0) c = tiny;
|
---|
53 | d = 1.0/d;
|
---|
54 | delta = c*d;
|
---|
55 | f = f*delta;
|
---|
56 | ac = - j * (j - a);
|
---|
57 | bc += 2.0;
|
---|
58 | j++;
|
---|
59 | } while (fabs(delta-1.0) > DBL_EPSILON);
|
---|
60 | return exp(-x)*pow(x,a)*f;
|
---|
61 | }
|
---|
62 |
|
---|
63 | static double
|
---|
64 | Gamma_m(int m)
|
---|
65 | {
|
---|
66 | double a = m+0.5;
|
---|
67 | const double c[6] = { 76.18009172947146,
|
---|
68 | -86.50532032941677,
|
---|
69 | 24.01409824083091,
|
---|
70 | -1.231739572450155,
|
---|
71 | 0.1208650973866179e-2,
|
---|
72 | -0.5395239384953e-5};
|
---|
73 | double x,y,tmp,ser;
|
---|
74 | int j;
|
---|
75 | y = x = a;
|
---|
76 | tmp = x + 5.5;
|
---|
77 | tmp -= (x+0.5)*log(tmp);
|
---|
78 | ser = 1.000000000190015;
|
---|
79 | for (j=0; j<=5; j++) ser += c[j]/++y;
|
---|
80 | return exp(-tmp+log(2.5066282746310005*ser/x));
|
---|
81 | }
|
---|
82 |
|
---|
83 | static double
|
---|
84 | gamma_m_large_x(int m, double x)
|
---|
85 | {
|
---|
86 | return Gamma_m(m) - Gamma_m(m,x);
|
---|
87 | }
|
---|
88 |
|
---|
89 | static double
|
---|
90 | mgamma_m(int m, double x)
|
---|
91 | {
|
---|
92 | double a = m+0.5;
|
---|
93 | if (x < a + 1.0) return mgamma_small_x(a,x);
|
---|
94 | return gamma_m_large_x(m,x)/pow(x,a);
|
---|
95 | }
|
---|
96 |
|
---|
97 | static double
|
---|
98 | Fjt(int j, double t)
|
---|
99 | {
|
---|
100 | //return gamma(j+0.5,sqrt(t))/(2.0*pow(t,j+0.5));
|
---|
101 | return 0.5 * mgamma_m(j,t);
|
---|
102 | }
|
---|
103 |
|
---|
104 | int
|
---|
105 | main(int,char**)
|
---|
106 | {
|
---|
107 | int maxj = 18;
|
---|
108 | Ref<FJT> fjt = new FJT(maxj+1);
|
---|
109 |
|
---|
110 | double tinc = 0.1;
|
---|
111 | for (double T=0.0; T<1000.0; T+=tinc) {
|
---|
112 | double *values = fjt->values(maxj,T);
|
---|
113 | for (int j=0; j<=maxj; j+=1) {
|
---|
114 | double v1 = values[j];
|
---|
115 | double v2 = Fjt(j,T);
|
---|
116 | double error = fabs((v1-v2)/v1);
|
---|
117 | if (error > DBL_EPSILON*10.0) {
|
---|
118 | cout << scprintf("F(%2d,%5.2f) = %15.12f %15.12f e = %18.15f",
|
---|
119 | j,T,v1,v2, error) << endl;
|
---|
120 | }
|
---|
121 | else {
|
---|
122 | cout << scprintf("F(%2d,%5.2f) = %15.12f %15.12f",
|
---|
123 | j,T,v1,v2) << endl;
|
---|
124 | }
|
---|
125 | }
|
---|
126 | if (T > 10.0) tinc = 10.0;
|
---|
127 | if (T > 100.0) tinc = 100.0;
|
---|
128 | }
|
---|
129 |
|
---|
130 | return 0;
|
---|
131 | }
|
---|