2 "A Precision Approximation of the Gamma Function" - Cornelius Lanczos (1964)
3 "Lanczos Implementation of the Gamma Function" - Paul Godfrey (2001)
4 "An Analysis of the Lanczos Gamma Approximation" - Glendon Ralph Pugh (2004)
9 Gamma(x) = (x + g - 0.5) * ----------------
14 S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ]
15 x + 1 x + 2 x + 3 x + N
17 with a0, a1, a2, a3,.. aN constants which depend on g.
19 for x < 0 the following reflection formula is used:
21 Gamma(x)*Gamma(-x) = -pi/(x sin(pi x))
23 most ideas and constants are from boost and python
27 static const double pi
= 3.141592653589793238462643383279502884;
29 /* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */
30 static double sinpi(double x
)
34 /* argument reduction: x = |x| mod 2 */
35 /* spurious inexact when x is odd int */
37 x
= 2 * (x
- floor(x
));
39 /* reduce x into [-.25,.25] */
48 return __sin(x
, 0, 0);
52 return __sin(-x
, 0, 0);
59 //static const double g = 6.024680040776729583740234375;
60 static const double gmhalf
= 5.524680040776729583740234375;
61 static const double Snum
[N
+1] = {
62 23531376880.410759688572007674451636754734846804940,
63 42919803642.649098768957899047001988850926355848959,
64 35711959237.355668049440185451547166705960488635843,
65 17921034426.037209699919755754458931112671403265390,
66 6039542586.3520280050642916443072979210699388420708,
67 1439720407.3117216736632230727949123939715485786772,
68 248874557.86205415651146038641322942321632125127801,
69 31426415.585400194380614231628318205362874684987640,
70 2876370.6289353724412254090516208496135991145378768,
71 186056.26539522349504029498971604569928220784236328,
72 8071.6720023658162106380029022722506138218516325024,
73 210.82427775157934587250973392071336271166969580291,
74 2.5066282746310002701649081771338373386264310793408,
76 static const double Sden
[N
+1] = {
77 0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535,
78 2637558, 357423, 32670, 1925, 66, 1,
80 /* n! for small integer n */
81 static const double fact
[] = {
82 1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0,
83 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0,
84 355687428096000.0, 6402373705728000.0, 121645100408832000.0,
85 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
88 /* S(x) rational function for positive x */
89 static double S(double x
)
91 double_t num
= 0, den
= 0;
94 /* to avoid overflow handle large x differently */
96 for (i
= N
; i
>= 0; i
--) {
97 num
= num
* x
+ Snum
[i
];
98 den
= den
* x
+ Sden
[i
];
101 for (i
= 0; i
<= N
; i
++) {
102 num
= num
/ x
+ Snum
[i
];
103 den
= den
/ x
+ Sden
[i
];
108 double tgamma(double x
)
110 union {double f
; uint64_t i
;} u
= {x
};
113 uint32_t ix
= u
.i
>>32 & 0x7fffffff;
117 if (ix
>= 0x7ff00000)
118 /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */
120 if (ix
< (0x3ff-54)<<20)
121 /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */
124 /* integer arguments */
125 /* raise inexact when non-integer */
129 if (x
<= sizeof fact
/sizeof *fact
)
130 return fact
[(int)x
- 1];
133 /* x >= 172: tgamma(x)=inf with overflow */
134 /* x =< -184: tgamma(x)=+-0 with underflow */
135 if (ix
>= 0x40670000) { /* |x| >= 184 */
137 FORCE_EVAL((float)(0x1p
-126/x
));
138 if (floor(x
) * 0.5 == floor(x
* 0.5))
146 absx
= sign
? -x
: x
;
148 /* handle the error of x + g - 0.5 */
159 r
= S(absx
) * exp(-y
);
161 /* reflection formula for negative x */
162 /* sinpi(absx) is not 0, integers are already handled */
163 r
= -pi
/ (sinpi(absx
) * absx
* r
);
167 r
+= dy
* (gmhalf
+0.5) * r
/ y
;
174 double __lgamma_r(double x
, int *sign
)
182 /* lgamma(nan)=nan, lgamma(+-inf)=inf */
185 /* integer arguments */
186 if (x
== floor(x
) && x
<= 2) {
187 /* n <= 0: lgamma(n)=inf with divbyzero */
188 /* n == 1,2: lgamma(n)=0 */
196 /* lgamma(x) ~ -log(|x|) for tiny |x| */
197 if (absx
< 0x1p
-54) {
198 *sign
= 1 - 2*!!signbit(x
);
202 /* use tgamma for smaller |x| */
205 *sign
= 1 - 2*!!signbit(x
);
209 /* second term (log(S)-g) could be more precise here.. */
210 /* or with stirling: (|x|-0.5)*(log(|x|)-1) + poly(1/|x|) */
211 r
= (absx
-0.5)*(log(absx
+gmhalf
)-1) + (log(S(absx
)) - (gmhalf
+0.5));
213 /* reflection formula for negative x */
215 *sign
= 2*!!signbit(x
) - 1;
216 r
= log(pi
/(fabs(x
)*absx
)) - r
;
221 weak_alias(__lgamma_r
, lgamma_r
);