/* * Asymptotic expansion for ln(|B(a, b)|) for a > ASYMP_FACTOR*max(|b|, 1). */ static double lbeta_asymp(double a, double b, int *sgn) { double r = lgam_sgn(b, sgn); r -= b * log(a); r += b*(1-b)/(2*a); r += b*(1-b)*(1-2*b)/(12*a*a); r += - b*b*(1-b)*(1-b)/(12*a*a*a); return r; }
static double jvs(double n, double x) { double t, u, y, z, k; int ex, sgngam; z = -x * x / 4.0; u = 1.0; y = u; k = 1.0; t = 1.0; while (t > MACHEP) { u *= z / (k * (n + k)); y += u; k += 1.0; if (y != 0) t = fabs(u / y); } #if CEPHES_DEBUG printf("power series=%.5e ", y); #endif t = frexp(0.5 * x, &ex); ex = ex * n; if ((ex > -1023) && (ex < 1023) && (n > 0.0) && (n < (MAXGAM - 1.0))) { t = pow(0.5 * x, n) / gamma(n + 1.0); #if CEPHES_DEBUG printf("pow(.5*x, %.4e)/gamma(n+1)=%.5e\n", n, t); #endif y *= t; } else { #if CEPHES_DEBUG z = n * log(0.5 * x); k = lgam(n + 1.0); t = z - k; printf("log pow=%.5e, lgam(%.4e)=%.5e\n", z, n + 1.0, k); #else t = n * log(0.5 * x) - lgam_sgn(n + 1.0, &sgngam); #endif if (y < 0) { sgngam = -sgngam; y = -y; } t += log(y); #if CEPHES_DEBUG printf("log y=%.5e\n", log(y)); #endif if (t < -MAXLOG) { return (0.0); } if (t > MAXLOG) { mtherr("Jv", OVERFLOW); return (NPY_INFINITY); } y = sgngam * exp(t); } return (y); }
double beta(double a, double b) { double y; int sign = 1; if (a <= 0.0) { if (a == floor(a)) { if (a == (int)a) { return beta_negint((int)a, b); } else { goto overflow; } } } if (b <= 0.0) { if (b == floor(b)) { if (b == (int)b) { return beta_negint((int)b, a); } else { goto overflow; } } } if (fabs(a) < fabs(b)) { y = a; a = b; b = y; } if (fabs(a) > ASYMP_FACTOR * fabs(b) && a > ASYMP_FACTOR) { /* Avoid loss of precision in lgam(a + b) - lgam(a) */ y = lbeta_asymp(a, b, &sign); return sign * exp(y); } y = a + b; if (fabs(y) > MAXGAM || fabs(a) > MAXGAM || fabs(b) > MAXGAM) { int sgngam; y = lgam_sgn(y, &sgngam); sign *= sgngam; /* keep track of the sign */ y = lgam_sgn(b, &sgngam) - y; sign *= sgngam; y = lgam_sgn(a, &sgngam) + y; sign *= sgngam; if (y > MAXLOG) { goto overflow; } return (sign * exp(y)); } y = Gamma(y); a = Gamma(a); b = Gamma(b); if (y == 0.0) goto overflow; if (fabs(fabs(a) - fabs(y)) > fabs(fabs(b) - fabs(y))) { y = b / y; y *= a; } else { y = a / y; y *= b; } return (y); overflow: mtherr("beta", OVERFLOW); return (sign * CEPHES_INFINITY); }