double expm1(double x) { double r, xx; if (!cephes_isfinite(x)) { if (cephes_isnan(x)) { return x; } else if (x > 0) { return x; } else { return -1.0; } } if ((x < -0.5) || (x > 0.5)) return (exp(x) - 1.0); xx = x * x; r = x * polevl(xx, EP, 2); r = r / (polevl(xx, EQ, 3) - r); return (r + r); }
/* Logarithm of Gamma function */ double lgam(double x) { double p, q, u, w, z; int i; sgngam = 1; if (!cephes_isfinite(x)) return x; if (x < -34.0) { q = -x; w = lgam(q); /* note this modifies sgngam! */ p = floor(q); if (p == q) { lgsing: mtherr("lgam", SING); return (NPY_INFINITY); } i = p; if ((i & 1) == 0) sgngam = -1; else sgngam = 1; z = q - p; if (z > 0.5) { p += 1.0; z = p - q; } z = q * sin(NPY_PI * z); if (z == 0.0) goto lgsing; /* z = log(NPY_PI) - log( z ) - w; */ z = LOGPI - log(z) - w; return (z); } if (x < 13.0) { z = 1.0; p = 0.0; u = x; while (u >= 3.0) { p -= 1.0; u = x + p; z *= u; } while (u < 2.0) { if (u == 0.0) goto lgsing; z /= u; p += 1.0; u = x + p; } if (z < 0.0) { sgngam = -1; z = -z; } else sgngam = 1; if (u == 2.0) return (log(z)); p -= 2.0; x = x + p; p = x * polevl(x, B, 5) / p1evl(x, C, 6); return (log(z) + p); } if (x > MAXLGM) { return (sgngam * NPY_INFINITY); } q = (x - 0.5) * log(x) - x + LS2PI; if (x > 1.0e8) return (q); p = 1.0 / (x * x); if (x >= 1000.0) q += ((7.9365079365079365079365e-4 * p - 2.7777777777777777777778e-3) * p + 0.0833333333333333333333) / x; else q += polevl(p, A, 4) / x; return (q); }
double Gamma(double x) { double p, q, z; int i; sgngam = 1; if (!cephes_isfinite(x)) { return x; } q = fabs(x); if (q > 33.0) { if (x < 0.0) { p = floor(q); if (p == q) { gamnan: mtherr("Gamma", OVERFLOW); return (NPY_INFINITY); } i = p; if ((i & 1) == 0) sgngam = -1; z = q - p; if (z > 0.5) { p += 1.0; z = q - p; } z = q * sin(NPY_PI * z); if (z == 0.0) { return (sgngam * NPY_INFINITY); } z = fabs(z); z = NPY_PI / (z * stirf(q)); } else { z = stirf(x); } return (sgngam * z); } z = 1.0; while (x >= 3.0) { x -= 1.0; z *= x; } while (x < 0.0) { if (x > -1.E-9) goto small; z /= x; x += 1.0; } while (x < 2.0) { if (x < 1.e-9) goto small; z /= x; x += 1.0; } if (x == 2.0) return (z); x -= 2.0; p = polevl(x, P, 6); q = polevl(x, Q, 7); return (z * p / q); small: if (x == 0.0) { goto gamnan; } else return (z / ((1.0 + 0.5772156649015329 * x) * x)); }