tgamma.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  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)
  5. approximation method:
  6. (x - 0.5) S(x)
  7. Gamma(x) = (x + g - 0.5) * ----------------
  8. exp(x + g - 0.5)
  9. with
  10. a1 a2 a3 aN
  11. S(x) ~= [ a0 + ----- + ----- + ----- + ... + ----- ]
  12. x + 1 x + 2 x + 3 x + N
  13. with a0, a1, a2, a3,.. aN constants which depend on g.
  14. for x < 0 the following reflection formula is used:
  15. Gamma(x)*Gamma(-x) = -pi/(x sin(pi x))
  16. most ideas and constants are from boost and python
  17. */
  18. #include "libm.h"
  19. static const double pi = 3.141592653589793238462643383279502884;
  20. /* sin(pi x) with x > 0x1p-100, if sin(pi*x)==0 the sign is arbitrary */
  21. static double sinpi(double x)
  22. {
  23. int n;
  24. /* argument reduction: x = |x| mod 2 */
  25. /* spurious inexact when x is odd int */
  26. x = x * 0.5;
  27. x = 2 * (x - floor(x));
  28. /* reduce x into [-.25,.25] */
  29. n = 4 * x;
  30. n = (n+1)/2;
  31. x -= n * 0.5;
  32. x *= pi;
  33. switch (n) {
  34. default: /* case 4 */
  35. case 0:
  36. return __sin(x, 0, 0);
  37. case 1:
  38. return __cos(x, 0);
  39. case 2:
  40. return __sin(-x, 0, 0);
  41. case 3:
  42. return -__cos(x, 0);
  43. }
  44. }
  45. #define N 12
  46. //static const double g = 6.024680040776729583740234375;
  47. static const double gmhalf = 5.524680040776729583740234375;
  48. static const double Snum[N+1] = {
  49. 23531376880.410759688572007674451636754734846804940,
  50. 42919803642.649098768957899047001988850926355848959,
  51. 35711959237.355668049440185451547166705960488635843,
  52. 17921034426.037209699919755754458931112671403265390,
  53. 6039542586.3520280050642916443072979210699388420708,
  54. 1439720407.3117216736632230727949123939715485786772,
  55. 248874557.86205415651146038641322942321632125127801,
  56. 31426415.585400194380614231628318205362874684987640,
  57. 2876370.6289353724412254090516208496135991145378768,
  58. 186056.26539522349504029498971604569928220784236328,
  59. 8071.6720023658162106380029022722506138218516325024,
  60. 210.82427775157934587250973392071336271166969580291,
  61. 2.5066282746310002701649081771338373386264310793408,
  62. };
  63. static const double Sden[N+1] = {
  64. 0, 39916800, 120543840, 150917976, 105258076, 45995730, 13339535,
  65. 2637558, 357423, 32670, 1925, 66, 1,
  66. };
  67. /* n! for small integer n */
  68. static const double fact[] = {
  69. 1, 1, 2, 6, 24, 120, 720, 5040.0, 40320.0, 362880.0, 3628800.0, 39916800.0,
  70. 479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0, 20922789888000.0,
  71. 355687428096000.0, 6402373705728000.0, 121645100408832000.0,
  72. 2432902008176640000.0, 51090942171709440000.0, 1124000727777607680000.0,
  73. };
  74. /* S(x) rational function for positive x */
  75. static double S(double x)
  76. {
  77. double_t num = 0, den = 0;
  78. int i;
  79. /* to avoid overflow handle large x differently */
  80. if (x < 8)
  81. for (i = N; i >= 0; i--) {
  82. num = num * x + Snum[i];
  83. den = den * x + Sden[i];
  84. }
  85. else
  86. for (i = 0; i <= N; i++) {
  87. num = num / x + Snum[i];
  88. den = den / x + Sden[i];
  89. }
  90. return num/den;
  91. }
  92. double tgamma(double x)
  93. {
  94. union {double f; uint64_t i;} u = {x};
  95. double absx, y;
  96. double_t dy, z, r;
  97. uint32_t ix = u.i>>32 & 0x7fffffff;
  98. int sign = u.i>>63;
  99. /* special cases */
  100. if (ix >= 0x7ff00000)
  101. /* tgamma(nan)=nan, tgamma(inf)=inf, tgamma(-inf)=nan with invalid */
  102. return x + INFINITY;
  103. if (ix < (0x3ff-54)<<20)
  104. /* |x| < 2^-54: tgamma(x) ~ 1/x, +-0 raises div-by-zero */
  105. return 1/x;
  106. /* integer arguments */
  107. /* raise inexact when non-integer */
  108. if (x == floor(x)) {
  109. if (sign)
  110. return 0/0.0;
  111. if (x <= sizeof fact/sizeof *fact)
  112. return fact[(int)x - 1];
  113. }
  114. /* x >= 172: tgamma(x)=inf with overflow */
  115. /* x =< -184: tgamma(x)=+-0 with underflow */
  116. if (ix >= 0x40670000) { /* |x| >= 184 */
  117. if (sign) {
  118. FORCE_EVAL((float)(0x1p-126/x));
  119. if (floor(x) * 0.5 == floor(x * 0.5))
  120. return 0;
  121. return -0.0;
  122. }
  123. x *= 0x1p1023;
  124. return x;
  125. }
  126. absx = sign ? -x : x;
  127. /* handle the error of x + g - 0.5 */
  128. y = absx + gmhalf;
  129. if (absx > gmhalf) {
  130. dy = y - absx;
  131. dy -= gmhalf;
  132. } else {
  133. dy = y - gmhalf;
  134. dy -= absx;
  135. }
  136. z = absx - 0.5;
  137. r = S(absx) * exp(-y);
  138. if (x < 0) {
  139. /* reflection formula for negative x */
  140. /* sinpi(absx) is not 0, integers are already handled */
  141. r = -pi / (sinpi(absx) * absx * r);
  142. dy = -dy;
  143. z = -z;
  144. }
  145. r += dy * (gmhalf+0.5) * r / y;
  146. z = pow(y, 0.5*z);
  147. y = r * z * z;
  148. return y;
  149. }
  150. #if 0
  151. double __lgamma_r(double x, int *sign)
  152. {
  153. double r, absx;
  154. *sign = 1;
  155. /* special cases */
  156. if (!isfinite(x))
  157. /* lgamma(nan)=nan, lgamma(+-inf)=inf */
  158. return x*x;
  159. /* integer arguments */
  160. if (x == floor(x) && x <= 2) {
  161. /* n <= 0: lgamma(n)=inf with divbyzero */
  162. /* n == 1,2: lgamma(n)=0 */
  163. if (x <= 0)
  164. return 1/0.0;
  165. return 0;
  166. }
  167. absx = fabs(x);
  168. /* lgamma(x) ~ -log(|x|) for tiny |x| */
  169. if (absx < 0x1p-54) {
  170. *sign = 1 - 2*!!signbit(x);
  171. return -log(absx);
  172. }
  173. /* use tgamma for smaller |x| */
  174. if (absx < 128) {
  175. x = tgamma(x);
  176. *sign = 1 - 2*!!signbit(x);
  177. return log(fabs(x));
  178. }
  179. /* second term (log(S)-g) could be more precise here.. */
  180. /* or with stirling: (|x|-0.5)*(log(|x|)-1) + poly(1/|x|) */
  181. r = (absx-0.5)*(log(absx+gmhalf)-1) + (log(S(absx)) - (gmhalf+0.5));
  182. if (x < 0) {
  183. /* reflection formula for negative x */
  184. x = sinpi(absx);
  185. *sign = 2*!!signbit(x) - 1;
  186. r = log(pi/(fabs(x)*absx)) - r;
  187. }
  188. return r;
  189. }
  190. weak_alias(__lgamma_r, lgamma_r);
  191. #endif