/lib/libc/mingw/math/tgammaf.c

https://github.com/ziglang/zig · C · 196 lines · 152 code · 18 blank · 26 comment · 29 complexity · bd2f429f4ef9847adbfd0deebf6eb226 MD5 · raw file

  1. /**
  2. * This file has no copyright assigned and is placed in the Public Domain.
  3. * This file is part of the mingw-w64 runtime package.
  4. * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  5. */
  6. #include "cephes_mconf.h"
  7. /* define MAXGAM 34.84425627277176174 */
  8. /* Stirling's formula for the gamma function
  9. * gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) )
  10. * .028 < 1/x < .1
  11. * relative error < 1.9e-11
  12. */
  13. static const float STIR[] = {
  14. -2.705194986674176E-003,
  15. 3.473255786154910E-003,
  16. 8.333331788340907E-002,
  17. };
  18. static const float MAXSTIR = 26.77;
  19. static const float SQTPIF = 2.50662827463100050242; /* sqrt( 2 pi ) */
  20. static float stirf(float);
  21. /* Gamma function computed by Stirling's formula,
  22. * sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x))
  23. * The polynomial STIR is valid for 33 <= x <= 172.
  24. */
  25. static float stirf( float x )
  26. {
  27. float y, w, v;
  28. w = 1.0/x;
  29. w = 1.0 + w * polevlf(w, STIR, 2);
  30. y = expf(-x);
  31. if (x > MAXSTIR)
  32. { /* Avoid overflow in pow() */
  33. v = powf(x, 0.5 * x - 0.25);
  34. y *= v;
  35. y *= v;
  36. }
  37. else
  38. {
  39. y = powf(x, x - 0.5) * y;
  40. }
  41. y = SQTPIF * y * w;
  42. return (y);
  43. }
  44. /* gamma(x+2), 0 < x < 1 */
  45. static const float P[] = {
  46. 1.536830450601906E-003,
  47. 5.397581592950993E-003,
  48. 4.130370201859976E-003,
  49. 7.232307985516519E-002,
  50. 8.203960091619193E-002,
  51. 4.117857447645796E-001,
  52. 4.227867745131584E-001,
  53. 9.999999822945073E-001,
  54. };
  55. float __tgammaf_r( float x, int* sgngamf);
  56. float __tgammaf_r( float x, int* sgngamf)
  57. {
  58. float p, q, z, nz;
  59. int i, direction, negative;
  60. #ifdef NANS
  61. if (isnan(x))
  62. return (x);
  63. #endif
  64. #ifdef INFINITIES
  65. #ifdef NANS
  66. if (x == INFINITYF)
  67. return (x);
  68. if (x == -INFINITYF)
  69. return (NANF);
  70. #else
  71. if (!isfinite(x))
  72. return (x);
  73. #endif
  74. #endif
  75. if (x == 0.0)
  76. return copysignf(HUGE_VALF, x);
  77. *sgngamf = 1;
  78. negative = 0;
  79. nz = 0.0;
  80. if (x < 0.0)
  81. {
  82. negative = 1;
  83. q = -x;
  84. p = floorf(q);
  85. if (p == q)
  86. {
  87. gsing:
  88. _SET_ERRNO(EDOM);
  89. mtherr("tgammaf", SING);
  90. #ifdef NANS
  91. return (NAN);
  92. #else
  93. return (MAXNUMF);
  94. #endif
  95. }
  96. i = p;
  97. if ((i & 1) == 0)
  98. *sgngamf = -1;
  99. nz = q - p;
  100. if (nz > 0.5)
  101. {
  102. p += 1.0;
  103. nz = q - p;
  104. }
  105. nz = q * sinf(PIF * nz);
  106. if (nz == 0.0)
  107. {
  108. _SET_ERRNO(ERANGE);
  109. mtherr("tgamma", OVERFLOW);
  110. #ifdef INFINITIES
  111. return(*sgngamf * INFINITYF);
  112. #else
  113. return(*sgngamf * MAXNUMF);
  114. #endif
  115. }
  116. if (nz < 0)
  117. nz = -nz;
  118. x = q;
  119. }
  120. if (x >= 10.0)
  121. {
  122. z = stirf(x);
  123. }
  124. if (x < 2.0)
  125. direction = 1;
  126. else
  127. direction = 0;
  128. z = 1.0;
  129. while (x >= 3.0)
  130. {
  131. x -= 1.0;
  132. z *= x;
  133. }
  134. /*
  135. while (x < 0.0)
  136. {
  137. if (x > -1.E-4)
  138. goto Small;
  139. z *=x;
  140. x += 1.0;
  141. }
  142. */
  143. while (x < 2.0)
  144. {
  145. if (x < 1.e-4)
  146. goto Small;
  147. z *=x;
  148. x += 1.0;
  149. }
  150. if (direction)
  151. z = 1.0/z;
  152. if (x == 2.0)
  153. return (z);
  154. x -= 2.0;
  155. p = z * polevlf(x, P, 7);
  156. gdone:
  157. if (negative)
  158. {
  159. p = *sgngamf * PIF/(nz * p );
  160. }
  161. return (p);
  162. Small:
  163. if (x == 0.0)
  164. {
  165. goto gsing;
  166. }
  167. else
  168. {
  169. p = z / ((1.0 + 0.5772156649015329 * x) * x);
  170. goto gdone;
  171. }
  172. }
  173. /* This is the C99 version */
  174. float tgammaf(float x)
  175. {
  176. int local_sgngamf = 0;
  177. return (__tgammaf_r(x, &local_sgngamf));
  178. }