dgamma.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* dgamma.f -- translated by f2c (version 20100827).
  2. This file no longer depends on f2c.
  3. */
  4. #include "slatec-internal.hpp"
  5. #include <tuple>
  6. /* Table of constant values */
  7. static integer const c__3 = 3;
  8. static integer const c__42 = 42;
  9. static integer const c__4 = 4;
  10. static integer const c__2 = 2;
  11. static integer const c__1 = 1;
  12. /* Initialized data */
  13. static double const gamcs[42] = { .008571195590989331421920062399942,
  14. .004415381324841006757191315771652,
  15. .05685043681599363378632664588789,
  16. -.004219835396418560501012500186624,
  17. .001326808181212460220584006796352,
  18. -1.893024529798880432523947023886e-4,
  19. 3.606925327441245256578082217225e-5,
  20. -6.056761904460864218485548290365e-6,
  21. 1.055829546302283344731823509093e-6,
  22. -1.811967365542384048291855891166e-7,
  23. 3.117724964715322277790254593169e-8,
  24. -5.354219639019687140874081024347e-9,
  25. 9.19327551985958894688778682594e-10,
  26. -1.577941280288339761767423273953e-10,
  27. 2.707980622934954543266540433089e-11,
  28. -4.646818653825730144081661058933e-12,
  29. 7.973350192007419656460767175359e-13,
  30. -1.368078209830916025799499172309e-13,
  31. 2.347319486563800657233471771688e-14,
  32. -4.027432614949066932766570534699e-15,
  33. 6.910051747372100912138336975257e-16,
  34. -1.185584500221992907052387126192e-16,
  35. 2.034148542496373955201026051932e-17,
  36. -3.490054341717405849274012949108e-18,
  37. 5.987993856485305567135051066026e-19,
  38. -1.027378057872228074490069778431e-19,
  39. 1.762702816060529824942759660748e-20,
  40. -3.024320653735306260958772112042e-21,
  41. 5.188914660218397839717833550506e-22,
  42. -8.902770842456576692449251601066e-23,
  43. 1.527474068493342602274596891306e-23,
  44. -2.620731256187362900257328332799e-24,
  45. 4.496464047830538670331046570666e-25,
  46. -7.714712731336877911703901525333e-26,
  47. 1.323635453126044036486572714666e-26,
  48. -2.270999412942928816702313813333e-27,
  49. 3.896418998003991449320816639999e-28,
  50. -6.685198115125953327792127999999e-29,
  51. 1.146998663140024384347613866666e-29,
  52. -1.967938586345134677295103999999e-30,
  53. 3.376448816585338090334890666666e-31,
  54. -5.793070335782135784625493333333e-32 };
  55. static double const pi = 3.1415926535897932384626433832795;
  56. static double const sq2pil = .91893853320467274178032973640562;
  57. static float const r__1 = (float) d1mach_(3) * (float).1;
  58. static integer const ngam = initds_(gamcs, &c__42, &r__1);
  59. static double const dxrel = sqrt(d1mach_(4));
  60. static std::tuple<double, double> const xboth = ([]() { double a, b; dgamlm_(&a, &b); return std::make_tuple(a, b); })();
  61. static double const xmin = std::get<0>(xboth);
  62. static double const xmax = std::get<1>(xboth);
  63. double dgamma_(double const *x)
  64. {
  65. /* System generated locals */
  66. integer i__1;
  67. double ret_val, d__1, d__2;
  68. /* Local variables */
  69. integer i__, n;
  70. double y;
  71. double sinpiy;
  72. /* ***BEGIN PROLOGUE DGAMMA */
  73. /* ***PURPOSE Compute the complete Gamma function. */
  74. /* ***LIBRARY SLATEC (FNLIB) */
  75. /* ***CATEGORY C7A */
  76. /* ***TYPE DOUBLE PRECISION (GAMMA-S, DGAMMA-D, CGAMMA-C) */
  77. /* ***KEYWORDS COMPLETE GAMMA FUNCTION, FNLIB, SPECIAL FUNCTIONS */
  78. /* ***AUTHOR Fullerton, W., (LANL) */
  79. /* ***DESCRIPTION */
  80. /* DGAMMA(X) calculates the double precision complete Gamma function */
  81. /* for double precision argument X. */
  82. /* Series for GAM on the interval 0. to 1.00000E+00 */
  83. /* with weighted error 5.79E-32 */
  84. /* log weighted error 31.24 */
  85. /* significant figures required 30.00 */
  86. /* decimal places required 32.05 */
  87. /* ***REFERENCES (NONE) */
  88. /* ***ROUTINES CALLED D1MACH, D9LGMC, DCSEVL, DGAMLM, INITDS, XERMSG */
  89. /* ***REVISION HISTORY (YYMMDD) */
  90. /* 770601 DATE WRITTEN */
  91. /* 890531 Changed all specific intrinsics to generic. (WRB) */
  92. /* 890911 Removed unnecessary intrinsics. (WRB) */
  93. /* 890911 REVISION DATE from Version 3.2 */
  94. /* 891214 Prologue converted to Version 4.0 format. (BAB) */
  95. /* 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ) */
  96. /* 920618 Removed space from variable name. (RWC, WRB) */
  97. /* ***END PROLOGUE DGAMMA */
  98. /* ***FIRST EXECUTABLE STATEMENT DGAMMA */
  99. y = abs(*x);
  100. if (y > 10.) {
  101. goto L50;
  102. }
  103. /* COMPUTE GAMMA(X) FOR -XBND .LE. X .LE. XBND. REDUCE INTERVAL AND FIND */
  104. /* GAMMA(1+Y) FOR 0.0 .LE. Y .LT. 1.0 FIRST OF ALL. */
  105. n = (integer) (*x);
  106. if (*x < 0.) {
  107. --n;
  108. }
  109. y = *x - n;
  110. --n;
  111. d__1 = y * 2. - 1.;
  112. ret_val = dcsevl_(&d__1, gamcs, &ngam) + .9375;
  113. if (n == 0) {
  114. return ret_val;
  115. }
  116. if (n > 0) {
  117. goto L30;
  118. }
  119. /* COMPUTE GAMMA(X) FOR X .LT. 1.0 */
  120. n = -n;
  121. if (*x == 0.) {
  122. xermsg_("SLATEC", "DGAMMA", "X IS 0", &c__4, &c__2, (ftnlen)6, (
  123. ftnlen)6, (ftnlen)6);
  124. }
  125. if (*x < (float)0. && *x + n - 2 == 0.) {
  126. xermsg_("SLATEC", "DGAMMA", "X IS A NEGATIVE INTEGER", &c__4, &c__2, (
  127. ftnlen)6, (ftnlen)6, (ftnlen)23);
  128. }
  129. d__2 = *x - .5;
  130. if (*x < -.5 && (d__1 = (*x - f2c::d_int(&d__2)) / *x, abs(d__1)) < dxrel) {
  131. xermsg_("SLATEC", "DGAMMA", "ANSWER LT HALF PRECISION BECAUSE X TOO \
  132. NEAR NEGATIVE INTEGER", &c__1, &c__1, (ftnlen)6, (ftnlen)6, (ftnlen)60);
  133. }
  134. i__1 = n;
  135. for (i__ = 1; i__ <= i__1; ++i__) {
  136. ret_val /= *x + i__ - 1;
  137. /* L20: */
  138. }
  139. return ret_val;
  140. /* GAMMA(X) FOR X .GE. 2.0 AND X .LE. 10.0 */
  141. L30:
  142. i__1 = n;
  143. for (i__ = 1; i__ <= i__1; ++i__) {
  144. ret_val = (y + i__) * ret_val;
  145. /* L40: */
  146. }
  147. return ret_val;
  148. /* GAMMA(X) FOR ABS(X) .GT. 10.0. RECALL Y = ABS(X). */
  149. L50:
  150. if (*x > xmax) {
  151. xermsg_("SLATEC", "DGAMMA", "X SO BIG GAMMA OVERFLOWS", &c__3, &c__2,
  152. (ftnlen)6, (ftnlen)6, (ftnlen)24);
  153. }
  154. ret_val = 0.;
  155. if (*x < xmin) {
  156. xermsg_("SLATEC", "DGAMMA", "X SO SMALL GAMMA UNDERFLOWS", &c__2, &
  157. c__1, (ftnlen)6, (ftnlen)6, (ftnlen)27);
  158. }
  159. if (*x < xmin) {
  160. return ret_val;
  161. }
  162. ret_val = exp((y - .5) * log(y) - y + sq2pil + d9lgmc_(&y));
  163. if (*x > 0.) {
  164. return ret_val;
  165. }
  166. d__2 = *x - .5;
  167. if ((d__1 = (*x - f2c::d_int(&d__2)) / *x, abs(d__1)) < dxrel) {
  168. xermsg_("SLATEC", "DGAMMA", "ANSWER LT HALF PRECISION, X TOO NEAR NE\
  169. GATIVE INTEGER", &c__1, &c__1, (ftnlen)6, (ftnlen)6, (ftnlen)53);
  170. }
  171. sinpiy = sin(pi * y);
  172. if (sinpiy == 0.) {
  173. xermsg_("SLATEC", "DGAMMA", "X IS A NEGATIVE INTEGER", &c__4, &c__2, (
  174. ftnlen)6, (ftnlen)6, (ftnlen)23);
  175. }
  176. ret_val = -pi / (y * sinpiy * ret_val);
  177. return ret_val;
  178. } /* dgamma_ */