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