X-Git-Url: http://nsz.repo.hu/git/?p=musl;a=blobdiff_plain;f=src%2Fmath%2Ftgammal.c;h=5c1a02a6399692ca60037f346e4e1be1f8163f19;hp=1b8fddea1a3c5c4b4af89c815165291a7bf48d89;hb=d8a7619e371ff0f226200f6316abb46dd1192f3d;hpb=9e2a895aaaa4a3985e94ae4f3e24c1af65f9bb34 diff --git a/src/math/tgammal.c b/src/math/tgammal.c index 1b8fddea..5c1a02a6 100644 --- a/src/math/tgammal.c +++ b/src/math/tgammal.c @@ -21,7 +21,6 @@ * SYNOPSIS: * * long double x, y, tgammal(); - * extern int signgam; * * y = tgammal( x ); * @@ -29,10 +28,7 @@ * DESCRIPTION: * * Returns gamma function of the argument. The result is - * correctly signed, and the sign (+1 or -1) is also - * returned in a global (extern) variable named signgam. - * This variable is also filled in by the logarithmic gamma - * function lgamma(). + * correctly signed. * * Arguments |x| <= 13 are reduced by recurrence and the function * approximated by a rational function of degree 7/8 in the @@ -183,18 +179,18 @@ static long double stirf(long double x) { long double y, w, v; - w = 1.0L/x; + w = 1.0/x; /* For large x, use rational coefficients from the analytical expansion. */ - if (x > 1024.0L) + if (x > 1024.0) w = (((((6.97281375836585777429E-5L * w + 7.84039221720066627474E-4L) * w - 2.29472093621399176955E-4L) * w - 2.68132716049382716049E-3L) * w + 3.47222222222222222222E-3L) * w + 8.33333333333333333333E-2L) * w - + 1.0L; + + 1.0; else - w = 1.0L + w * __polevll(w, STIR, 8); + w = 1.0 + w * __polevll(w, STIR, 8); y = expl(x); if (x > MAXSTIR) { /* Avoid overflow in pow() */ v = powl(x, 0.5L * x - 0.25L); @@ -209,77 +205,69 @@ static long double stirf(long double x) long double tgammal(long double x) { long double p, q, z; - int i; - signgam = 1; - if (isnan(x)) - return NAN; - if (x == INFINITY) - return INFINITY; - if (x == -INFINITY) - return x - x; + if (!isfinite(x)) + return x + INFINITY; + q = fabsl(x); - if (q > 13.0L) { - if (q > MAXGAML) - goto goverf; - if (x < 0.0L) { + if (q > 13.0) { + if (x < 0.0) { p = floorl(q); - if (p == q) - return (x - x) / (x - x); - i = p; - if ((i & 1) == 0) - signgam = -1; z = q - p; - if (z > 0.5L) { - p += 1.0L; - z = q - p; - } - z = q * sinl(PIL * z); - z = fabsl(z) * stirf(q); - if (z <= PIL/LDBL_MAX) { -goverf: - return signgam * INFINITY; + if (z == 0) + return 0 / z; + if (q > MAXGAML) { + z = 0; + } else { + if (z > 0.5) { + p += 1.0; + z = q - p; + } + z = q * sinl(PIL * z); + z = fabsl(z) * stirf(q); + z = PIL/z; } - z = PIL/z; + if (0.5 * p == floorl(q * 0.5)) + z = -z; + } else if (x > MAXGAML) { + z = x * 0x1p16383L; } else { z = stirf(x); } - return signgam * z; + return z; } - z = 1.0L; - while (x >= 3.0L) { - x -= 1.0L; + z = 1.0; + while (x >= 3.0) { + x -= 1.0; z *= x; } while (x < -0.03125L) { z /= x; - x += 1.0L; + x += 1.0; } if (x <= 0.03125L) goto small; - while (x < 2.0L) { + while (x < 2.0) { z /= x; - x += 1.0L; + x += 1.0; } - if (x == 2.0L) + if (x == 2.0) return z; - x -= 2.0L; + x -= 2.0; p = __polevll(x, P, 7); q = __polevll(x, Q, 8); z = z * p / q; - if(z < 0) - signgam = -1; return z; small: - if (x == 0.0L) - return (x - x) / (x - x); - if (x < 0.0L) { + /* z==1 if x was originally +-0 */ + if (x == 0 && z != 1) + return x / x; + if (x < 0.0) { x = -x; q = z / (x * __polevll(x, SN, 8)); - signgam = -1; } else q = z / (x * __polevll(x, S, 8)); return q;