xref: /csrg-svn/lib/libm/common_source/gamma.c (revision 56953)
1*56953Sbostic /*-
2*56953Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*56953Sbostic  * All rights reserved.
4*56953Sbostic  *
5*56953Sbostic  * %sccs.include.redist.c%
6*56953Sbostic  */
7*56953Sbostic 
8*56953Sbostic #ifndef lint
9*56953Sbostic static char sccsid[] = "@(#)gamma.c	5.1 (Berkeley) 12/02/92";
10*56953Sbostic #endif /* not lint */
11*56953Sbostic 
12*56953Sbostic #include <math.h>
13*56953Sbostic #include <errno.h>
14*56953Sbostic 
15*56953Sbostic /* METHOD:
16*56953Sbostic  * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x))
17*56953Sbostic  * 	At negative integers, return +Inf, and set errno.
18*56953Sbostic  *
19*56953Sbostic  * x < 6.5: use one of two rational approximation,
20*56953Sbostic  *	to log(G(x)), expanded around 2 for x near integral;
21*56953Sbostic  *	around the minimum for x near half-integral.  The two
22*56953Sbostic  *	regions overlap.
23*56953Sbostic  *	In the range [2.0, 2.5], it is necessary to expand around 2.
24*56953Sbostic  *	In the range ~[1.462-.22, 1.462+.25], the expansion around
25*56953Sbostic  *	the minimum is necessary to get <1ulp accuracy.
26*56953Sbostic  *
27*56953Sbostic  * x >= 6.5: Use the asymptotic approximation (Stirling's formula.)
28*56953Sbostic  *
29*56953Sbostic  *	log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x))
30*56953Sbostic  *
31*56953Sbostic  *	Keep extra precision in multiplying (x-.5)(log(x)-1), to
32*56953Sbostic  *	avoid premature round-off.
33*56953Sbostic  *
34*56953Sbostic  * Special values:  NaN, +/-Inf, 0, Negative Integers.
35*56953Sbostic  *	Neg integer: Set overflow trap; return +Inf; errno = EDOM
36*56953Sbostic  *	+Inf: Return +Inf; errno = ERANGE;
37*56953Sbostic  *	-Inf: Return +Inf; errno = EDOM;
38*56953Sbostic  *	NaN:  Return NaN; errno = EDOM;
39*56953Sbostic */
40*56953Sbostic #define x0 .461632144968362356785
41*56953Sbostic #define LEFT -.3955078125
42*56953Sbostic #define a0_hi 0.88560319441088874992
43*56953Sbostic #define a0_lo -.00000000000000004996427036469019695
44*56953Sbostic #define lns2pi_hi 0.418945312500000
45*56953Sbostic #define lns2pi_lo -.000006779295327258219670263595
46*56953Sbostic 
47*56953Sbostic #define UNDERFL (1e-1020 * 1e-1020)
48*56953Sbostic double small_gam(double);
49*56953Sbostic double smaller_gam(double);
50*56953Sbostic struct Double large_gam(double);
51*56953Sbostic double neg_gam(double);
52*56953Sbostic struct Double ratfun_gam(double, double);
53*56953Sbostic /**
54*56953Sbostic #define NP 5
55*56953Sbostic static double P[] = {
56*56953Sbostic 	0.57410538218150719558252603747,
57*56953Sbostic 	0.24541366696467897812183878159,
58*56953Sbostic 	0.00513973619299223308948265654,
59*56953Sbostic 	0.00129391688253677823901288679,
60*56953Sbostic 	0.00222188711638167000692045683
61*56953Sbostic };
62*56953Sbostic #define NQ 9
63*56953Sbostic static double Q[] = {
64*56953Sbostic 	1.33984375,
65*56953Sbostic 	0.981446340605471312379393111769,
66*56953Sbostic 	-0.19172028764767945485658628968,
67*56953Sbostic 	-0.13543838178180836462338731962,
68*56953Sbostic 	0.028432780865671299780350622655,
69*56953Sbostic 	0.004720852857293747484312973484,
70*56953Sbostic 	-0.00162320758342873413572482466,
71*56953Sbostic 	8.63879091186865255905247274e-05,
72*56953Sbostic 	5.67776543645974456238616906e-06,
73*56953Sbostic 	-1.1130244665113561369974706e-08
74*56953Sbostic };
75*56953Sbostic /**/
76*56953Sbostic #define P0	.621389571821820863029017800727g
77*56953Sbostic #define P1	.265757198651533466104979197553,
78*56953Sbostic #define P2	.00553859446429917461063308081748,
79*56953Sbostic #define P3	.00138456698304096573887145282811,
80*56953Sbostic #define P4	.00240659950032711365819348969808
81*56953Sbostic 
82*56953Sbostic #define Q0	1.4501953125
83*56953Sbostic #define Q1	1.06258521948016171343454061571
84*56953Sbostic #define Q2	-.207474561943859936441469926649
85*56953Sbostic #define Q3	-.146734131782005422506287573015
86*56953Sbostic #define Q4	.0307878176156175520361557573779
87*56953Sbostic #define Q5	.00512449347980666221336054633184
88*56953Sbostic #define Q6	-.00176012741431666995019222898833
89*56953Sbostic #define Q7	.0000935021023573788935372153030556
90*56953Sbostic #define Q8	.00000613275507472443958924745652239
91*56953Sbostic 
92*56953Sbostic #define Pa0	.0833333333333333148296162562474
93*56953Sbostic #define Pa1	-.00277777777774548123579378966497
94*56953Sbostic #define Pa2	.000793650778754435631476282786423
95*56953Sbostic #define Pa3	-.000595235082566672847950717262222
96*56953Sbostic #define Pa4	.000841428560346653702135821806252
97*56953Sbostic #define Pa5	-.00189773526463879200348872089421
98*56953Sbostic #define Pa6	.00569394463439411649408050664078
99*56953Sbostic #define Pa7	-.0144705562421428915453880392761
100*56953Sbostic 
101*56953Sbostic static struct Double	large_gam __P((double));
102*56953Sbostic static double	 	neg_gam __P((double));
103*56953Sbostic static struct Double	ratfun_gam __P((double, double));
104*56953Sbostic static double	 	small_gam __P((double));
105*56953Sbostic static double	 	smaller_gam __P((double));
106*56953Sbostic 
107*56953Sbostic double
108*56953Sbostic gamma(x)
109*56953Sbostic 	double x;
110*56953Sbostic {
111*56953Sbostic 	double zero = 0;
112*56953Sbostic 	struct Double u;
113*56953Sbostic 	if (x > 6 + x0 + LEFT) {
114*56953Sbostic 		if(x > 171.63)
115*56953Sbostic 			return(1.0/zero);
116*56953Sbostic 		u = large_gam(x);
117*56953Sbostic 		return(exp__D(u.a, u.b));
118*56953Sbostic 	} else if (x >= 1.0 + LEFT + x0)
119*56953Sbostic 		return (small_gam(x));
120*56953Sbostic 	else if (x > 1e-18)
121*56953Sbostic 		return (smaller_gam(x));
122*56953Sbostic 	else if(x > 0) {
123*56953Sbostic 		1 + 1e-20;	/* raise inexact flag */
124*56953Sbostic 		return(1/x);
125*56953Sbostic 	}
126*56953Sbostic 	else if (x <= 0)
127*56953Sbostic 		return (neg_gam(x));
128*56953Sbostic 	else {				/* x = NaN */
129*56953Sbostic 		errno = EDOM;
130*56953Sbostic 		return (x);
131*56953Sbostic 	}
132*56953Sbostic }
133*56953Sbostic 
134*56953Sbostic /* TRUNC sets trailing bits in a floating-point number to zero.
135*56953Sbostic  * is a temporary variable.
136*56953Sbostic */
137*56953Sbostic 
138*56953Sbostic #if defined(vax) || defined(tahoe)
139*56953Sbostic #define _IEEE	0
140*56953Sbostic #define TRUNC(x) (double) (float) (x)
141*56953Sbostic #else
142*56953Sbostic #define _IEEE	1
143*56953Sbostic #define TRUNC(x) *(((int *) &x) + 1) &= 0xf8000000
144*56953Sbostic #define infnan(x) 0.0
145*56953Sbostic #endif
146*56953Sbostic 
147*56953Sbostic /* Accurate to max(ulp(1/128) absolute, 2^-75 relative) error. */
148*56953Sbostic static struct Double
149*56953Sbostic large_gam(x)
150*56953Sbostic 	double x;
151*56953Sbostic {
152*56953Sbostic 	double z, p;
153*56953Sbostic 	int i;
154*56953Sbostic 	struct Double t, u, v;
155*56953Sbostic 	pua = (long *) &u.a, pua++;
156*56953Sbostic 	pva = (long *) &v.a, pva++;
157*56953Sbostic 	if (x == infinity()) {
158*56953Sbostic 		u.b = 0, u.a = x;
159*56953Sbostic 		return u;
160*56953Sbostic 	}
161*56953Sbostic 	z = 1.0/(x*x);
162*56953Sbostic 	p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*Pa5+z*(Pa6+z*Pa7)))));
163*56953Sbostic 	p = p/x;			/* |e| < 2.8e-18 */
164*56953Sbostic 					/* 0 < p < 1/64 (at x = 5.5) */
165*56953Sbostic 	u = log__D(x);
166*56953Sbostic 	u.a -= 1.0;
167*56953Sbostic 	v.a = (x -= .5);
168*56953Sbostic 	TRUNC(v.a);
169*56953Sbostic 	v.b = x - v.a;
170*56953Sbostic 	t.a = v.a*u.a;			/* t = (x-.5)*(log(x)-1) */
171*56953Sbostic 	t.b = v.b*u.a + x*u.b;
172*56953Sbostic 	/* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */
173*56953Sbostic 	t.b += lns2pi_lo; t.b += p;	/* small pieces ( < 1/64, assuming t < 1e14) */
174*56953Sbostic 	u.a = lns2pi_hi + t.b; u.a += t.a;
175*56953Sbostic 	u.b = t.a - u.a;
176*56953Sbostic 	u.b += lns2pi_hi; u.b += t.b;
177*56953Sbostic 	return (u);
178*56953Sbostic }
179*56953Sbostic /* Good to < 1 ulp.  (provably .90 ulp; .87 ulp on 1,000,000 runs.)
180*56953Sbostic    It also has correct monotonicity.
181*56953Sbostic  */
182*56953Sbostic static double
183*56953Sbostic small_gam(x)
184*56953Sbostic 	double x;
185*56953Sbostic {
186*56953Sbostic 	double y, t;
187*56953Sbostic 	struct Double yy, r;
188*56953Sbostic 	pt = ((long *) &t)+1;
189*56953Sbostic 	pra = ((long *) &r.a)+1;
190*56953Sbostic 	y = x - 1;
191*56953Sbostic 	if (y <= 1.0 + (LEFT + x0)) {
192*56953Sbostic 		yy = ratfun_gam(y - x0, 0);
193*56953Sbostic 		return (yy.a + yy.b);
194*56953Sbostic 	}
195*56953Sbostic 	r.a = y--;
196*56953Sbostic 	TRUNC(r.a);
197*56953Sbostic 	yy.a = r.a - 1.0;
198*56953Sbostic 	yy.b = r.b = y - yy.a;
199*56953Sbostic 	for (; --y > 1.0 + (LEFT + x0); yy.a--) {
200*56953Sbostic 			t = r.a*yy.a;
201*56953Sbostic 			r.b = r.a*yy.b + y*r.b;
202*56953Sbostic 			r.a = t + r.b;
203*56953Sbostic 			TRUNC(r.a);
204*56953Sbostic 			t -= r.a;
205*56953Sbostic 			r.b += t;
206*56953Sbostic 	}				/* now want r * gamma(y); */
207*56953Sbostic 	yy = ratfun_gam(y - x0, 0);
208*56953Sbostic 	y = r.b*(yy.a+yy.b) + r.a*yy.b;
209*56953Sbostic 	y += yy.a*r.a;
210*56953Sbostic 	return (y);
211*56953Sbostic }
212*56953Sbostic /* Good on (0, 1+x0+LEFT].  Accurate to 1ulp on [.25+x0+LEFT, 1+x0+LEFT].
213*56953Sbostic  * Below this, x+LEFT-x0 introduces additional rounding errror of .5ulp.
214*56953Sbostic  */
215*56953Sbostic static double
216*56953Sbostic smaller_gam(x)
217*56953Sbostic 	double x;
218*56953Sbostic {
219*56953Sbostic 	double t, d;
220*56953Sbostic 	struct Double r, xx;
221*56953Sbostic 	if (x < x0 + LEFT) {
222*56953Sbostic 		t = x, TRUNC(t);
223*56953Sbostic 		d = (t+x)*(x-t);
224*56953Sbostic 		t *= t;
225*56953Sbostic 		xx.a = ((d+t) + x), TRUNC(xx.a);
226*56953Sbostic 		xx.b = x - xx.a; xx.b += t; xx.b += d;
227*56953Sbostic 		t = (1.0-x0); t += x;
228*56953Sbostic 		d = (1.0-x0); d -= t; d += x;
229*56953Sbostic 		x = xx.a + xx.b;
230*56953Sbostic 	} else {
231*56953Sbostic 		xx.a =  x, TRUNC(xx.a);
232*56953Sbostic 		xx.b = x - xx.a;
233*56953Sbostic 		t = x - x0;
234*56953Sbostic 		d = (-x0 -t); d += x;
235*56953Sbostic 	}
236*56953Sbostic 	r = ratfun_gam(t, d);
237*56953Sbostic 	d = r.a/x, TRUNC(d);
238*56953Sbostic 	r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b;
239*56953Sbostic 	return (d + r.a/x);
240*56953Sbostic }
241*56953Sbostic /* returns (z+c)^2 * P(z)/Q(z) + a0 */
242*56953Sbostic static struct Double
243*56953Sbostic ratfun_gam(z, c)
244*56953Sbostic 	double z, c;
245*56953Sbostic {
246*56953Sbostic 	int i;
247*56953Sbostic 	double p, q, hi, lo;
248*56953Sbostic 	struct Double r;
249*56953Sbostic 
250*56953Sbostic 	q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8)))))));
251*56953Sbostic 	p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4)));
252*56953Sbostic 
253*56953Sbostic 	/* return r.a + r.b = a0 + (z+c)^2 * p/q, with r.a truncated to 26 bits. */
254*56953Sbostic 	p = p/q;
255*56953Sbostic 	hi = z, TRUNC(hi);		/* hi+lo ~= z + c */
256*56953Sbostic 		lo = z - hi; lo += c;
257*56953Sbostic 	lo *= (hi+z);			/* q+lo = (z+c)*(z+c) */
258*56953Sbostic 	q = hi*hi;
259*56953Sbostic 	hi = (q + lo), TRUNC(hi);	/* hi+lo = q+lo */
260*56953Sbostic 		q -= hi;
261*56953Sbostic 		lo += q;
262*56953Sbostic 	z = p, TRUNC(z);		/* z+q = p */
263*56953Sbostic 		q = p - z;
264*56953Sbostic 	lo = lo*p + hi*q + a0_lo;
265*56953Sbostic 	hi *= z;
266*56953Sbostic 	r.a = hi + a0_hi, TRUNC(r.a);
267*56953Sbostic 	r.b = ((a0_hi-r.a) + hi) + lo;
268*56953Sbostic 	return (r);
269*56953Sbostic }
270*56953Sbostic #define lpi_hi 1.1447298858494001638
271*56953Sbostic #define lpi_lo .0000000000000000102659511627078262
272*56953Sbostic /* Error: within 3.5 ulp for x < 171.  For large x, see lgamma. */
273*56953Sbostic static double
274*56953Sbostic neg_gam(x)
275*56953Sbostic 	double x;
276*56953Sbostic {
277*56953Sbostic 	int sgn = 1;
278*56953Sbostic 	struct Double lg, lsine;
279*56953Sbostic 	double y, z, one = 1.0, zero = 0.0;
280*56953Sbostic 	y = floor(x + .5);
281*56953Sbostic 	if (y == x) {
282*56953Sbostic 		if (-x == infinity()) {	/* G(-inf) = NaN */
283*56953Sbostic 			errno = EDOM;
284*56953Sbostic 			return (signaling_nan(0));
285*56953Sbostic 		}
286*56953Sbostic 		errno = ERANGE;
287*56953Sbostic 		return (one/zero);	/* G(-(integer) -> oo */
288*56953Sbostic 	}
289*56953Sbostic 	z = fabs(x - y);
290*56953Sbostic 	y = ceil(x);
291*56953Sbostic 	if (y*.5 == ceil(.5*y)) {
292*56953Sbostic 		sgn = -1;
293*56953Sbostic 		printf("neg\n");
294*56953Sbostic 	}
295*56953Sbostic 	if (x < 1 - (6 + x0 + LEFT)) {
296*56953Sbostic 		if(x < -190) {
297*56953Sbostic 			UNDERFL;
298*56953Sbostic 			z = .5*ceil(x);
299*56953Sbostic 			if (z==ceil(z)) return (-0);
300*56953Sbostic 			else return (0);
301*56953Sbostic 		}
302*56953Sbostic 		y = 1 - x;
303*56953Sbostic 		if (1 - y == x) {
304*56953Sbostic 			lg = large_gam(y);
305*56953Sbostic 			lsine = log__D(sin(M_PI*z));
306*56953Sbostic 		} else {
307*56953Sbostic 			x = -x;
308*56953Sbostic 			lg = large_gam(x);
309*56953Sbostic 			lsine = log__D(x*sin(M_PI*z));
310*56953Sbostic 		}
311*56953Sbostic 		lg.b += lsine.b - lpi_lo;
312*56953Sbostic 		y = (-(lg.b + lsine.a) + lpi_hi) - lg.a;
313*56953Sbostic 		z = -lg.a - y; z+= lpi_hi; z -= lsine.a; z -= lg.b;
314*56953Sbostic 		y = exp__D(y, z);
315*56953Sbostic 		if(sgn < 0) y = -y;
316*56953Sbostic 		return (y);
317*56953Sbostic 	}
318*56953Sbostic 	y = 1-x;
319*56953Sbostic 	if (1-y == x)
320*56953Sbostic 		y = ngamma(y);
321*56953Sbostic 	else		/* 1-x is inexact */
322*56953Sbostic 		y = -x*ngamma(-x);
323*56953Sbostic 	if (sgn < 0) y = -y;
324*56953Sbostic 	return (M_PI / (y*sin(M_PI*z)));
325*56953Sbostic }
326