1 1.9 christos /* $NetBSD: n_gamma.c,v 1.9 2013/11/09 21:41:03 christos Exp $ */ 2 1.1 ragge /*- 3 1.1 ragge * Copyright (c) 1992, 1993 4 1.1 ragge * The Regents of the University of California. All rights reserved. 5 1.1 ragge * 6 1.1 ragge * Redistribution and use in source and binary forms, with or without 7 1.1 ragge * modification, are permitted provided that the following conditions 8 1.1 ragge * are met: 9 1.1 ragge * 1. Redistributions of source code must retain the above copyright 10 1.1 ragge * notice, this list of conditions and the following disclaimer. 11 1.1 ragge * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 ragge * notice, this list of conditions and the following disclaimer in the 13 1.1 ragge * documentation and/or other materials provided with the distribution. 14 1.5 agc * 3. Neither the name of the University nor the names of its contributors 15 1.1 ragge * may be used to endorse or promote products derived from this software 16 1.1 ragge * without specific prior written permission. 17 1.1 ragge * 18 1.1 ragge * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 1.1 ragge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 1.1 ragge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 1.1 ragge * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 1.1 ragge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 1.1 ragge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 1.1 ragge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 1.1 ragge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 1.1 ragge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 1.1 ragge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 1.1 ragge * SUCH DAMAGE. 29 1.1 ragge */ 30 1.1 ragge 31 1.1 ragge #ifndef lint 32 1.2 ragge #if 0 33 1.1 ragge static char sccsid[] = "@(#)gamma.c 8.1 (Berkeley) 6/4/93"; 34 1.2 ragge #endif 35 1.1 ragge #endif /* not lint */ 36 1.1 ragge 37 1.1 ragge /* 38 1.1 ragge * This code by P. McIlroy, Oct 1992; 39 1.1 ragge * 40 1.6 wiz * The financial support of UUNET Communications Services is gratefully 41 1.1 ragge * acknowledged. 42 1.1 ragge */ 43 1.1 ragge 44 1.1 ragge #include <math.h> 45 1.1 ragge #include "mathimpl.h" 46 1.1 ragge #include <errno.h> 47 1.1 ragge 48 1.1 ragge /* METHOD: 49 1.1 ragge * x < 0: Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x)) 50 1.1 ragge * At negative integers, return +Inf, and set errno. 51 1.1 ragge * 52 1.1 ragge * x < 6.5: 53 1.1 ragge * Use argument reduction G(x+1) = xG(x) to reach the 54 1.1 ragge * range [1.066124,2.066124]. Use a rational 55 1.1 ragge * approximation centered at the minimum (x0+1) to 56 1.1 ragge * ensure monotonicity. 57 1.1 ragge * 58 1.1 ragge * x >= 6.5: Use the asymptotic approximation (Stirling's formula) 59 1.1 ragge * adjusted for equal-ripples: 60 1.1 ragge * 61 1.1 ragge * log(G(x)) ~= (x-.5)*(log(x)-1) + .5(log(2*pi)-1) + 1/x*P(1/(x*x)) 62 1.1 ragge * 63 1.1 ragge * Keep extra precision in multiplying (x-.5)(log(x)-1), to 64 1.1 ragge * avoid premature round-off. 65 1.1 ragge * 66 1.1 ragge * Special values: 67 1.1 ragge * non-positive integer: Set overflow trap; return +Inf; 68 1.1 ragge * x > 171.63: Set overflow trap; return +Inf; 69 1.1 ragge * NaN: Set invalid trap; return NaN 70 1.1 ragge * 71 1.1 ragge * Accuracy: Gamma(x) is accurate to within 72 1.1 ragge * x > 0: error provably < 0.9ulp. 73 1.1 ragge * Maximum observed in 1,000,000 trials was .87ulp. 74 1.1 ragge * x < 0: 75 1.1 ragge * Maximum observed error < 4ulp in 1,000,000 trials. 76 1.1 ragge */ 77 1.1 ragge 78 1.4 matt static double neg_gam (double); 79 1.4 matt static double small_gam (double); 80 1.4 matt static double smaller_gam (double); 81 1.4 matt static struct Double large_gam (double); 82 1.4 matt static struct Double ratfun_gam (double, double); 83 1.1 ragge 84 1.1 ragge /* 85 1.1 ragge * Rational approximation, A0 + x*x*P(x)/Q(x), on the interval 86 1.1 ragge * [1.066.., 2.066..] accurate to 4.25e-19. 87 1.1 ragge */ 88 1.1 ragge #define LEFT -.3955078125 /* left boundary for rat. approx */ 89 1.1 ragge #define x0 .461632144968362356785 /* xmin - 1 */ 90 1.1 ragge 91 1.1 ragge #define a0_hi 0.88560319441088874992 92 1.1 ragge #define a0_lo -.00000000000000004996427036469019695 93 1.1 ragge #define P0 6.21389571821820863029017800727e-01 94 1.1 ragge #define P1 2.65757198651533466104979197553e-01 95 1.1 ragge #define P2 5.53859446429917461063308081748e-03 96 1.1 ragge #define P3 1.38456698304096573887145282811e-03 97 1.1 ragge #define P4 2.40659950032711365819348969808e-03 98 1.1 ragge #define Q0 1.45019531250000000000000000000e+00 99 1.1 ragge #define Q1 1.06258521948016171343454061571e+00 100 1.1 ragge #define Q2 -2.07474561943859936441469926649e-01 101 1.1 ragge #define Q3 -1.46734131782005422506287573015e-01 102 1.1 ragge #define Q4 3.07878176156175520361557573779e-02 103 1.1 ragge #define Q5 5.12449347980666221336054633184e-03 104 1.1 ragge #define Q6 -1.76012741431666995019222898833e-03 105 1.1 ragge #define Q7 9.35021023573788935372153030556e-05 106 1.1 ragge #define Q8 6.13275507472443958924745652239e-06 107 1.1 ragge /* 108 1.1 ragge * Constants for large x approximation (x in [6, Inf]) 109 1.1 ragge * (Accurate to 2.8*10^-19 absolute) 110 1.1 ragge */ 111 1.1 ragge #define lns2pi_hi 0.418945312500000 112 1.1 ragge #define lns2pi_lo -.000006779295327258219670263595 113 1.1 ragge #define Pa0 8.33333333333333148296162562474e-02 114 1.1 ragge #define Pa1 -2.77777777774548123579378966497e-03 115 1.1 ragge #define Pa2 7.93650778754435631476282786423e-04 116 1.1 ragge #define Pa3 -5.95235082566672847950717262222e-04 117 1.1 ragge #define Pa4 8.41428560346653702135821806252e-04 118 1.1 ragge #define Pa5 -1.89773526463879200348872089421e-03 119 1.1 ragge #define Pa6 5.69394463439411649408050664078e-03 120 1.1 ragge #define Pa7 -1.44705562421428915453880392761e-02 121 1.1 ragge 122 1.7 christos static const double zero = 0., one = 1.0, tiny = _TINY; 123 1.1 ragge /* 124 1.1 ragge * TRUNC sets trailing bits in a floating-point number to zero. 125 1.1 ragge * is a temporary variable. 126 1.1 ragge */ 127 1.3 matt #if defined(__vax__) || defined(tahoe) 128 1.1 ragge #define _IEEE 0 129 1.1 ragge #define TRUNC(x) x = (double) (float) (x) 130 1.1 ragge #else 131 1.4 matt static int endian; 132 1.1 ragge #define _IEEE 1 133 1.1 ragge #define TRUNC(x) *(((int *) &x) + endian) &= 0xf8000000 134 1.1 ragge #define infnan(x) 0.0 135 1.1 ragge #endif 136 1.1 ragge 137 1.1 ragge double 138 1.8 abs gamma(double x) 139 1.1 ragge { 140 1.2 ragge double b; 141 1.1 ragge struct Double u; 142 1.4 matt #if _IEEE 143 1.4 matt int endian = (*(int *) &one) ? 1 : 0; 144 1.4 matt #endif 145 1.1 ragge 146 1.1 ragge if (x >= 6) { 147 1.1 ragge if(x > 171.63) 148 1.1 ragge return(one/zero); 149 1.1 ragge u = large_gam(x); 150 1.1 ragge return(__exp__D(u.a, u.b)); 151 1.3 matt } else if (x >= 1.0 + LEFT + x0) { 152 1.1 ragge return (small_gam(x)); 153 1.3 matt } else if (x > 1.e-17) { 154 1.1 ragge return (smaller_gam(x)); 155 1.3 matt } else if (x > -1.e-17) { 156 1.3 matt if (x == 0.0) { 157 1.1 ragge if (!_IEEE) return (infnan(ERANGE)); 158 1.1 ragge else return (one/x); 159 1.3 matt } 160 1.2 ragge b =one+1e-20; /* Raise inexact flag. ??? -ragge */ 161 1.9 christos __USE(b); 162 1.1 ragge return (one/x); 163 1.1 ragge } else if (!finite(x)) { 164 1.1 ragge if (_IEEE) /* x = NaN, -Inf */ 165 1.1 ragge return (x*x); 166 1.1 ragge else 167 1.1 ragge return (infnan(EDOM)); 168 1.1 ragge } else 169 1.1 ragge return (neg_gam(x)); 170 1.1 ragge } 171 1.1 ragge /* 172 1.1 ragge * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error. 173 1.1 ragge */ 174 1.1 ragge static struct Double 175 1.4 matt large_gam(double x) 176 1.1 ragge { 177 1.1 ragge double z, p; 178 1.1 ragge struct Double t, u, v; 179 1.1 ragge 180 1.1 ragge z = one/(x*x); 181 1.1 ragge p = Pa0+z*(Pa1+z*(Pa2+z*(Pa3+z*(Pa4+z*(Pa5+z*(Pa6+z*Pa7)))))); 182 1.1 ragge p = p/x; 183 1.1 ragge 184 1.1 ragge u = __log__D(x); 185 1.1 ragge u.a -= one; 186 1.1 ragge v.a = (x -= .5); 187 1.1 ragge TRUNC(v.a); 188 1.1 ragge v.b = x - v.a; 189 1.1 ragge t.a = v.a*u.a; /* t = (x-.5)*(log(x)-1) */ 190 1.1 ragge t.b = v.b*u.a + x*u.b; 191 1.1 ragge /* return t.a + t.b + lns2pi_hi + lns2pi_lo + p */ 192 1.1 ragge t.b += lns2pi_lo; t.b += p; 193 1.1 ragge u.a = lns2pi_hi + t.b; u.a += t.a; 194 1.1 ragge u.b = t.a - u.a; 195 1.1 ragge u.b += lns2pi_hi; u.b += t.b; 196 1.1 ragge return (u); 197 1.1 ragge } 198 1.1 ragge /* 199 1.1 ragge * Good to < 1 ulp. (provably .90 ulp; .87 ulp on 1,000,000 runs.) 200 1.1 ragge * It also has correct monotonicity. 201 1.1 ragge */ 202 1.1 ragge static double 203 1.4 matt small_gam(double x) 204 1.1 ragge { 205 1.2 ragge double y, ym1, t; 206 1.1 ragge struct Double yy, r; 207 1.1 ragge y = x - one; 208 1.1 ragge ym1 = y - one; 209 1.1 ragge if (y <= 1.0 + (LEFT + x0)) { 210 1.1 ragge yy = ratfun_gam(y - x0, 0); 211 1.1 ragge return (yy.a + yy.b); 212 1.1 ragge } 213 1.1 ragge r.a = y; 214 1.1 ragge TRUNC(r.a); 215 1.1 ragge yy.a = r.a - one; 216 1.1 ragge y = ym1; 217 1.1 ragge yy.b = r.b = y - yy.a; 218 1.1 ragge /* Argument reduction: G(x+1) = x*G(x) */ 219 1.1 ragge for (ym1 = y-one; ym1 > LEFT + x0; y = ym1--, yy.a--) { 220 1.1 ragge t = r.a*yy.a; 221 1.1 ragge r.b = r.a*yy.b + y*r.b; 222 1.1 ragge r.a = t; 223 1.1 ragge TRUNC(r.a); 224 1.1 ragge r.b += (t - r.a); 225 1.1 ragge } 226 1.1 ragge /* Return r*gamma(y). */ 227 1.1 ragge yy = ratfun_gam(y - x0, 0); 228 1.1 ragge y = r.b*(yy.a + yy.b) + r.a*yy.b; 229 1.1 ragge y += yy.a*r.a; 230 1.1 ragge return (y); 231 1.1 ragge } 232 1.1 ragge /* 233 1.1 ragge * Good on (0, 1+x0+LEFT]. Accurate to 1ulp. 234 1.1 ragge */ 235 1.1 ragge static double 236 1.4 matt smaller_gam(double x) 237 1.1 ragge { 238 1.1 ragge double t, d; 239 1.1 ragge struct Double r, xx; 240 1.1 ragge if (x < x0 + LEFT) { 241 1.1 ragge t = x, TRUNC(t); 242 1.1 ragge d = (t+x)*(x-t); 243 1.1 ragge t *= t; 244 1.1 ragge xx.a = (t + x), TRUNC(xx.a); 245 1.1 ragge xx.b = x - xx.a; xx.b += t; xx.b += d; 246 1.1 ragge t = (one-x0); t += x; 247 1.1 ragge d = (one-x0); d -= t; d += x; 248 1.1 ragge x = xx.a + xx.b; 249 1.1 ragge } else { 250 1.1 ragge xx.a = x, TRUNC(xx.a); 251 1.1 ragge xx.b = x - xx.a; 252 1.1 ragge t = x - x0; 253 1.1 ragge d = (-x0 -t); d += x; 254 1.1 ragge } 255 1.1 ragge r = ratfun_gam(t, d); 256 1.1 ragge d = r.a/x, TRUNC(d); 257 1.1 ragge r.a -= d*xx.a; r.a -= d*xx.b; r.a += r.b; 258 1.1 ragge return (d + r.a/x); 259 1.1 ragge } 260 1.1 ragge /* 261 1.1 ragge * returns (z+c)^2 * P(z)/Q(z) + a0 262 1.1 ragge */ 263 1.1 ragge static struct Double 264 1.4 matt ratfun_gam(double z, double c) 265 1.1 ragge { 266 1.1 ragge double p, q; 267 1.1 ragge struct Double r, t; 268 1.1 ragge 269 1.1 ragge q = Q0 +z*(Q1+z*(Q2+z*(Q3+z*(Q4+z*(Q5+z*(Q6+z*(Q7+z*Q8))))))); 270 1.1 ragge p = P0 + z*(P1 + z*(P2 + z*(P3 + z*P4))); 271 1.1 ragge 272 1.1 ragge /* return r.a + r.b = a0 + (z+c)^2*p/q, with r.a truncated to 26 bits. */ 273 1.1 ragge p = p/q; 274 1.1 ragge t.a = z, TRUNC(t.a); /* t ~= z + c */ 275 1.1 ragge t.b = (z - t.a) + c; 276 1.1 ragge t.b *= (t.a + z); 277 1.1 ragge q = (t.a *= t.a); /* t = (z+c)^2 */ 278 1.1 ragge TRUNC(t.a); 279 1.1 ragge t.b += (q - t.a); 280 1.1 ragge r.a = p, TRUNC(r.a); /* r = P/Q */ 281 1.1 ragge r.b = p - r.a; 282 1.1 ragge t.b = t.b*p + t.a*r.b + a0_lo; 283 1.1 ragge t.a *= r.a; /* t = (z+c)^2*(P/Q) */ 284 1.1 ragge r.a = t.a + a0_hi, TRUNC(r.a); 285 1.1 ragge r.b = ((a0_hi-r.a) + t.a) + t.b; 286 1.1 ragge return (r); /* r = a0 + t */ 287 1.1 ragge } 288 1.1 ragge 289 1.1 ragge static double 290 1.4 matt neg_gam(double x) 291 1.1 ragge { 292 1.1 ragge int sgn = 1; 293 1.1 ragge struct Double lg, lsine; 294 1.1 ragge double y, z; 295 1.1 ragge 296 1.1 ragge y = floor(x + .5); 297 1.3 matt if (y == x) { /* Negative integer. */ 298 1.1 ragge if(!_IEEE) 299 1.1 ragge return (infnan(ERANGE)); 300 1.1 ragge else 301 1.1 ragge return (one/zero); 302 1.3 matt } 303 1.1 ragge z = fabs(x - y); 304 1.1 ragge y = .5*ceil(x); 305 1.1 ragge if (y == ceil(y)) 306 1.1 ragge sgn = -1; 307 1.1 ragge if (z < .25) 308 1.1 ragge z = sin(M_PI*z); 309 1.1 ragge else 310 1.1 ragge z = cos(M_PI*(0.5-z)); 311 1.1 ragge /* Special case: G(1-x) = Inf; G(x) may be nonzero. */ 312 1.1 ragge if (x < -170) { 313 1.1 ragge if (x < -190) 314 1.1 ragge return ((double)sgn*tiny*tiny); 315 1.1 ragge y = one - x; /* exact: 128 < |x| < 255 */ 316 1.1 ragge lg = large_gam(y); 317 1.1 ragge lsine = __log__D(M_PI/z); /* = TRUNC(log(u)) + small */ 318 1.1 ragge lg.a -= lsine.a; /* exact (opposite signs) */ 319 1.1 ragge lg.b -= lsine.b; 320 1.1 ragge y = -(lg.a + lg.b); 321 1.1 ragge z = (y + lg.a) + lg.b; 322 1.1 ragge y = __exp__D(y, z); 323 1.1 ragge if (sgn < 0) y = -y; 324 1.1 ragge return (y); 325 1.1 ragge } 326 1.1 ragge y = one-x; 327 1.1 ragge if (one-y == x) 328 1.1 ragge y = gamma(y); 329 1.1 ragge else /* 1-x is inexact */ 330 1.1 ragge y = -x*gamma(-x); 331 1.1 ragge if (sgn < 0) y = -y; 332 1.1 ragge return (M_PI / (y*z)); 333 1.1 ragge } 334