TMB Documentation  v1.9.11
gamma_cody.cpp
1 /* From http://www.netlib.org/specfun/gamma Fortran translated by f2c,...
2  * ------------------------------##### Martin Maechler, ETH Zurich
3  *
4  *=========== was part of ribesl (Bessel I(.))
5  *=========== ~~~~~~
6  */
7 
8 // used in bessel_i.c and bessel_j.c, hidden if possible.
9 
10 template<class Float>
11 Float attribute_hidden Rf_gamma_cody(Float x)
12 {
13 /* ----------------------------------------------------------------------
14 
15  This routine calculates the GAMMA function for a float argument X.
16  Computation is based on an algorithm outlined in reference [1].
17  The program uses rational functions that approximate the GAMMA
18  function to at least 20 significant decimal digits. Coefficients
19  for the approximation over the interval (1,2) are unpublished.
20  Those for the approximation for X >= 12 are from reference [2].
21  The accuracy achieved depends on the arithmetic system, the
22  compiler, the intrinsic functions, and proper selection of the
23  machine-dependent constants.
24 
25  *******************************************************************
26 
27  Error returns
28 
29  The program returns the value XINF for singularities or
30  when overflow would occur. The computation is believed
31  to be free of underflow and overflow.
32 
33  Intrinsic functions required are:
34 
35  INT, DBLE, EXP, LOG, REAL, SIN
36 
37 
38  References:
39  [1] "An Overview of Software Development for Special Functions",
40  W. J. Cody, Lecture Notes in Mathematics, 506,
41  Numerical Analysis Dundee, 1975, G. A. Watson (ed.),
42  Springer Verlag, Berlin, 1976.
43 
44  [2] Computer Approximations, Hart, Et. Al., Wiley and sons, New York, 1968.
45 
46  Latest modification: October 12, 1989
47 
48  Authors: W. J. Cody and L. Stoltz
49  Applied Mathematics Division
50  Argonne National Laboratory
51  Argonne, IL 60439
52  ----------------------------------------------------------------------*/
53 
54 /* ----------------------------------------------------------------------
55  Mathematical constants
56  ----------------------------------------------------------------------*/
57  const static double sqrtpi = .9189385332046727417803297; /* == ??? */
58 
59 /* *******************************************************************
60 
61  Explanation of machine-dependent constants
62 
63  beta - radix for the floating-point representation
64  maxexp - the smallest positive power of beta that overflows
65  XBIG - the largest argument for which GAMMA(X) is representable
66  in the machine, i.e., the solution to the equation
67  GAMMA(XBIG) = beta**maxexp
68  XINF - the largest machine representable floating-point number;
69  approximately beta**maxexp
70  EPS - the smallest positive floating-point number such that 1.0+EPS > 1.0
71  XMININ - the smallest positive floating-point number such that
72  1/XMININ is machine representable
73 
74  Approximate values for some important machines are:
75 
76  beta maxexp XBIG
77 
78  CRAY-1 (S.P.) 2 8191 966.961
79  Cyber 180/855
80  under NOS (S.P.) 2 1070 177.803
81  IEEE (IBM/XT,
82  SUN, etc.) (S.P.) 2 128 35.040
83  IEEE (IBM/XT,
84  SUN, etc.) (D.P.) 2 1024 171.624
85  IBM 3033 (D.P.) 16 63 57.574
86  VAX D-Format (D.P.) 2 127 34.844
87  VAX G-Format (D.P.) 2 1023 171.489
88 
89  XINF EPS XMININ
90 
91  CRAY-1 (S.P.) 5.45E+2465 7.11E-15 1.84E-2466
92  Cyber 180/855
93  under NOS (S.P.) 1.26E+322 3.55E-15 3.14E-294
94  IEEE (IBM/XT,
95  SUN, etc.) (S.P.) 3.40E+38 1.19E-7 1.18E-38
96  IEEE (IBM/XT,
97  SUN, etc.) (D.P.) 1.79D+308 2.22D-16 2.23D-308
98  IBM 3033 (D.P.) 7.23D+75 2.22D-16 1.39D-76
99  VAX D-Format (D.P.) 1.70D+38 1.39D-17 5.88D-39
100  VAX G-Format (D.P.) 8.98D+307 1.11D-16 1.12D-308
101 
102  *******************************************************************
103 
104  ----------------------------------------------------------------------
105  Machine dependent parameters
106  ----------------------------------------------------------------------
107  */
108 
109 
110  const static double xbig = 171.624;
111  /* ML_POSINF == const double xinf = 1.79e308;*/
112  /* DBL_EPSILON = const double eps = 2.22e-16;*/
113  /* DBL_MIN == const double xminin = 2.23e-308;*/
114 
115  /*----------------------------------------------------------------------
116  Numerator and denominator coefficients for rational minimax
117  approximation over (1,2).
118  ----------------------------------------------------------------------*/
119  const static double p[8] = {
120  -1.71618513886549492533811,
121  24.7656508055759199108314,-379.804256470945635097577,
122  629.331155312818442661052,866.966202790413211295064,
123  -31451.2729688483675254357,-36144.4134186911729807069,
124  66456.1438202405440627855 };
125  const static double q[8] = {
126  -30.8402300119738975254353,
127  315.350626979604161529144,-1015.15636749021914166146,
128  -3107.77167157231109440444,22538.1184209801510330112,
129  4755.84627752788110767815,-134659.959864969306392456,
130  -115132.259675553483497211 };
131  /*----------------------------------------------------------------------
132  Coefficients for minimax approximation over (12, INF).
133  ----------------------------------------------------------------------*/
134  const static double c[7] = {
135  -.001910444077728,8.4171387781295e-4,
136  -5.952379913043012e-4,7.93650793500350248e-4,
137  -.002777777777777681622553,.08333333333333333331554247,
138  .0057083835261 };
139 
140  /* Local variables */
141  int i, n;
142  int parity;/*logical*/
143  Float fact, xden, xnum, y, z, yi, res, sum, ysq;
144 
145  parity = (0);
146  fact = 1.;
147  n = 0;
148  y = x;
149  if (y <= 0.) {
150  /* -------------------------------------------------------------
151  Argument is negative
152  ------------------------------------------------------------- */
153  y = -x;
154  yi = trunc(y);
155  res = y - yi;
156  if (res != 0.) {
157  if (yi != trunc(yi * .5) * 2.)
158  parity = (1);
159  fact = -M_PI / sinpi(res);
160  y += 1.;
161  } else {
162  return(ML_POSINF);
163  }
164  }
165  /* -----------------------------------------------------------------
166  Argument is positive
167  -----------------------------------------------------------------*/
168  if (y < DBL_EPSILON) {
169  /* --------------------------------------------------------------
170  Argument < EPS
171  -------------------------------------------------------------- */
172  if (y >= DBL_MIN) {
173  res = 1. / y;
174  } else {
175  return(ML_POSINF);
176  }
177  } else if (y < 12.) {
178  yi = y;
179  if (y < 1.) {
180  /* ---------------------------------------------------------
181  EPS < argument < 1
182  --------------------------------------------------------- */
183  z = y;
184  y += 1.;
185  } else {
186  /* -----------------------------------------------------------
187  1 <= argument < 12, reduce argument if necessary
188  ----------------------------------------------------------- */
189  n = (int) trunc(y) - 1;
190  y -= (double) n;
191  z = y - 1.;
192  }
193  /* ---------------------------------------------------------
194  Evaluate approximation for 1. < argument < 2.
195  ---------------------------------------------------------*/
196  xnum = 0.;
197  xden = 1.;
198  for (i = 0; i < 8; ++i) {
199  xnum = (xnum + p[i]) * z;
200  xden = xden * z + q[i];
201  }
202  res = xnum / xden + 1.;
203  if (yi < y) {
204  /* --------------------------------------------------------
205  Adjust result for case 0. < argument < 1.
206  -------------------------------------------------------- */
207  res /= yi;
208  } else if (yi > y) {
209  /* ----------------------------------------------------------
210  Adjust result for case 2. < argument < 12.
211  ---------------------------------------------------------- */
212  for (i = 0; i < n; ++i) {
213  res *= y;
214  y += 1.;
215  }
216  }
217  } else {
218  /* -------------------------------------------------------------
219  Evaluate for argument >= 12.,
220  ------------------------------------------------------------- */
221  if (y <= xbig) {
222  ysq = y * y;
223  sum = c[6];
224  for (i = 0; i < 6; ++i) {
225  sum = sum / ysq + c[i];
226  }
227  sum = sum / y - y + sqrtpi;
228  sum += (y - .5) * log(y);
229  res = exp(sum);
230  } else {
231  return(ML_POSINF);
232  }
233  }
234  /* ----------------------------------------------------------------------
235  Final adjustments and return
236  ----------------------------------------------------------------------*/
237  if (parity)
238  res = -res;
239  if (fact != 1.)
240  res = fact / res;
241  return res;
242 }
243 
Type sum(Vector< Type > x)
Definition: convenience.hpp:33
License: GPL v2