1 | // Visit http://www.johndcook.com/stand_alone_code.html for the source of this code and more like it. |
---|
2 | // Modified for the DANSE project. |
---|
3 | |
---|
4 | #include <math.h> |
---|
5 | |
---|
6 | #include "gamma_win.h" |
---|
7 | |
---|
8 | // Note that the functions Gamma and LogGamma are mutually dependent. |
---|
9 | |
---|
10 | double gamma(double x) |
---|
11 | { |
---|
12 | // Split the function domain into three intervals: |
---|
13 | // (0, 0.001), [0.001, 12), and (12, infinity) |
---|
14 | |
---|
15 | /////////////////////////////////////////////////////////////////////////// |
---|
16 | // First interval: (0, 0.001) |
---|
17 | // |
---|
18 | // For small x, 1/Gamma(x) has power series x + gamma x^2 - ... |
---|
19 | // So in this range, 1/Gamma(x) = x + gamma x^2 with error on the order of x^3. |
---|
20 | // The relative error over this interval is less than 6e-7. |
---|
21 | |
---|
22 | const double gamma = 0.577215664901532860606512090; // Euler's gamma constant |
---|
23 | double y; |
---|
24 | int arg_was_less_than_one = 0; |
---|
25 | int n = 0; |
---|
26 | // numerator coefficients for approximation over the interval (1,2) |
---|
27 | static const double p[] = |
---|
28 | { |
---|
29 | -1.71618513886549492533811E+0, |
---|
30 | 2.47656508055759199108314E+1, |
---|
31 | -3.79804256470945635097577E+2, |
---|
32 | 6.29331155312818442661052E+2, |
---|
33 | 8.66966202790413211295064E+2, |
---|
34 | -3.14512729688483675254357E+4, |
---|
35 | -3.61444134186911729807069E+4, |
---|
36 | 6.64561438202405440627855E+4 |
---|
37 | }; |
---|
38 | // denominator coefficients for approximation over the interval (1,2) |
---|
39 | static const double q[] = |
---|
40 | { |
---|
41 | -3.08402300119738975254353E+1, |
---|
42 | 3.15350626979604161529144E+2, |
---|
43 | -1.01515636749021914166146E+3, |
---|
44 | -3.10777167157231109440444E+3, |
---|
45 | 2.25381184209801510330112E+4, |
---|
46 | 4.75584627752788110767815E+3, |
---|
47 | -1.34659959864969306392456E+5, |
---|
48 | -1.15132259675553483497211E+5 |
---|
49 | }; |
---|
50 | double num = 0.0; |
---|
51 | double den = 1.0; |
---|
52 | int i; |
---|
53 | double z; |
---|
54 | double result; |
---|
55 | |
---|
56 | if (x < 0.001) |
---|
57 | return 1.0/(x*(1.0 + gamma*x)); |
---|
58 | |
---|
59 | /////////////////////////////////////////////////////////////////////////// |
---|
60 | // Second interval: [0.001, 12) |
---|
61 | |
---|
62 | if (x < 12.0) |
---|
63 | { |
---|
64 | // The algorithm directly approximates gamma over (1,2) and uses |
---|
65 | // reduction identities to reduce other arguments to this interval. |
---|
66 | |
---|
67 | y = x; |
---|
68 | |
---|
69 | if (y < 1.0) arg_was_less_than_one = 1; |
---|
70 | |
---|
71 | // Add or subtract integers as necessary to bring y into (1,2) |
---|
72 | // Will correct for this below |
---|
73 | if (arg_was_less_than_one==1) { |
---|
74 | y += 1.0; |
---|
75 | } else { |
---|
76 | n = (int) (floor(y)) - 1; // will use n later |
---|
77 | y -= n; |
---|
78 | } |
---|
79 | |
---|
80 | z = y - 1; |
---|
81 | for (i = 0; i < 8; i++) { |
---|
82 | num = (num + p[i])*z; |
---|
83 | den = den*z + q[i]; |
---|
84 | } |
---|
85 | result = num/den + 1.0; |
---|
86 | |
---|
87 | // Apply correction if argument was not initially in (1,2) |
---|
88 | if (arg_was_less_than_one==1) { |
---|
89 | // Use identity gamma(z) = gamma(z+1)/z |
---|
90 | // The variable "result" now holds gamma of the original y + 1 |
---|
91 | // Thus we use y-1 to get back the orginal y. |
---|
92 | result /= (y-1.0); |
---|
93 | } else { |
---|
94 | // Use the identity gamma(z+n) = z*(z+1)* ... *(z+n-1)*gamma(z) |
---|
95 | for (i = 0; i < n; i++) |
---|
96 | result *= y++; |
---|
97 | } |
---|
98 | |
---|
99 | return result; |
---|
100 | } |
---|
101 | |
---|
102 | return exp(lgamma(x)); |
---|
103 | } |
---|
104 | |
---|
105 | double lgamma (double x) |
---|
106 | { |
---|
107 | static const double c[8] = |
---|
108 | { |
---|
109 | 1.0/12.0, |
---|
110 | -1.0/360.0, |
---|
111 | 1.0/1260.0, |
---|
112 | -1.0/1680.0, |
---|
113 | 1.0/1188.0, |
---|
114 | -691.0/360360.0, |
---|
115 | 1.0/156.0, |
---|
116 | -3617.0/122400.0 |
---|
117 | }; |
---|
118 | double z = 1.0/(x*x); |
---|
119 | double sum = c[7]; |
---|
120 | static const double halfLogTwoPi = 0.91893853320467274178032973640562; |
---|
121 | double series; |
---|
122 | double logGamma; |
---|
123 | int i; |
---|
124 | |
---|
125 | if (x < 12.0) { |
---|
126 | return log(fabs(gamma(x))); |
---|
127 | } |
---|
128 | |
---|
129 | // Abramowitz and Stegun 6.1.41 |
---|
130 | // Asymptotic series should be good to at least 11 or 12 figures |
---|
131 | // For error analysis, see Whittiker and Watson |
---|
132 | // A Course in Modern Analysis (1927), page 252 |
---|
133 | |
---|
134 | for (i=6; i >= 0; i--) { |
---|
135 | sum *= z; |
---|
136 | sum += c[i]; |
---|
137 | } |
---|
138 | series = sum/x; |
---|
139 | logGamma = (x - 0.5)*log(x) - x + halfLogTwoPi + series; |
---|
140 | return logGamma; |
---|
141 | } |
---|