* SYNOPSIS:
*
* long double x, y, tgammal();
- * extern int signgam;
*
* y = tgammal( x );
*
* 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
Peak error = 1.83e-20
Relative error spread = 8.4e-23
*/
-static long double P[8] = {
+static const long double P[8] = {
4.212760487471622013093E-5L,
4.542931960608009155600E-4L,
4.092666828394035500949E-3L,
8.378004301573126728826E-1L,
1.000000000000000000009E0L,
};
-static long double Q[9] = {
+static const long double Q[9] = {
-1.397148517476170440917E-5L,
2.346584059160635244282E-4L,
-1.237799246653152231188E-3L,
};
/*
-static long double P[] = {
+static const long double P[] = {
-3.01525602666895735709e0L,
-3.25157411956062339893e1L,
-2.92929976820724030353e2L,
-5.99650230220855581642e4L,
-7.15743521530849602425e4L
};
-static long double Q[] = {
+static const long double Q[] = {
1.00000000000000000000e0L,
-1.67955233807178858919e1L,
8.85946791747759881659e1L,
Peak error = 9.44e-21
Relative error spread = 8.8e-4
*/
-static long double STIR[9] = {
+static const long double STIR[9] = {
7.147391378143610789273E-4L,
-2.363848809501759061727E-5L,
-5.950237554056330156018E-4L,
* 0 < x < 0.03125
* Peak relative error 4.2e-23
*/
-static long double S[9] = {
+static const long double S[9] = {
-1.193945051381510095614E-3L,
7.220599478036909672331E-3L,
-9.622023360406271645744E-3L,
* Peak relative error 5.16e-23
* Relative error spread = 2.5e-24
*/
-static long double SN[9] = {
+static const long double SN[9] = {
1.133374167243894382010E-3L,
7.220837261893170325704E-3L,
9.621911155035976733706E-3L,
{
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);
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;