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