/// <summary> /// Inverse of incomplete beta integral. /// </summary> /// /// <example> /// Please see <see cref="Beta"/> /// </example> /// public static double IncompleteInverse(double aa, double bb, double yy0) { double a, b, y0, d, y, x, x0, x1, lgm, yp, di, dithresh, yl, yh; int i, dir; bool nflg; bool rflg; if (yy0 <= 0) { return(0.0); } if (yy0 >= 1.0) { return(1.0); } if (aa <= 1.0 || bb <= 1.0) { nflg = true; dithresh = 4.0 * Constants.DoubleEpsilon; rflg = false; a = aa; b = bb; y0 = yy0; x = a / (a + b); y = Incomplete(a, b, x); goto ihalve; } else { nflg = false; dithresh = 1.0e-4; } /* approximation to inverse function */ yp = -Normal.Inverse(yy0); if (yy0 > 0.5) { rflg = true; a = bb; b = aa; y0 = 1.0 - yy0; yp = -yp; } else { rflg = false; a = aa; b = bb; y0 = yy0; } lgm = (yp * yp - 3.0) / 6.0; x0 = 2.0 / (1.0 / (2.0 * a - 1.0) + 1.0 / (2.0 * b - 1.0)); y = yp * Math.Sqrt(x0 + lgm) / x0 - (1.0 / (2.0 * b - 1.0) - 1.0 / (2.0 * a - 1.0)) * (lgm + 5.0 / 6.0 - 2.0 / (3.0 * x0)); y = 2.0 * y; if (y < Constants.LogMin) { x0 = 1.0; throw new ArithmeticException("underflow"); } x = a / (a + b * Math.Exp(y)); y = Incomplete(a, b, x); yp = (y - y0) / y0; if (Math.Abs(yp) < 1.0e-2) { goto newt; } ihalve: /* Resort to interval halving if not close enough */ x0 = 0.0; yl = 0.0; x1 = 1.0; yh = 1.0; di = 0.5; dir = 0; for (i = 0; i < 400; i++) { if (i != 0) { x = x0 + di * (x1 - x0); if (x == 1.0) { x = 1.0 - Constants.DoubleEpsilon; } y = Incomplete(a, b, x); yp = (x1 - x0) / (x1 + x0); if (Math.Abs(yp) < dithresh) { x0 = x; goto newt; } } if (y < y0) { x0 = x; yl = y; if (dir < 0) { dir = 0; di = 0.5; } else if (dir > 1) { di = 0.5 * di + 0.5; } else { di = (y0 - y) / (yh - yl); } dir += 1; if (x0 > 0.75) { if (rflg) { rflg = false; a = aa; b = bb; y0 = yy0; } else { rflg = true; a = bb; b = aa; y0 = 1.0 - yy0; } x = 1.0 - x; y = Incomplete(a, b, x); goto ihalve; } } else { x1 = x; if (rflg && x1 < Constants.DoubleEpsilon) { x0 = 0.0; goto done; } yh = y; if (dir > 0) { dir = 0; di = 0.5; } else if (dir < -1) { di = 0.5 * di; } else { di = (y - y0) / (yh - yl); } dir -= 1; } } if (x0 >= 1.0) { x0 = 1.0 - Constants.DoubleEpsilon; goto done; } if (x == 0.0) { throw new ArithmeticException("underflow"); } newt: if (nflg) { goto done; } x0 = x; lgm = Gamma.Log(a + b) - Gamma.Log(a) - Gamma.Log(b); for (i = 0; i < 10; i++) { /* Compute the function at this point. */ if (i != 0) { y = Incomplete(a, b, x0); } /* Compute the derivative of the function at this point. */ d = (a - 1.0) * Math.Log(x0) + (b - 1.0) * Math.Log(1.0 - x0) + lgm; if (d < Constants.LogMin) { throw new ArithmeticException("underflow"); } d = Math.Exp(d); /* compute the step to the next approximation of x */ d = (y - y0) / d; x = x0; x0 = x0 - d; if (x0 <= 0.0) { throw new ArithmeticException("underflow"); } if (x0 >= 1.0) { x0 = 1.0 - Constants.DoubleEpsilon; goto done; } if (Math.Abs(d / x0) < 64.0 * Constants.DoubleEpsilon) { goto done; } } done: if (rflg) { if (x0 <= Double.Epsilon) { x0 = 1.0 - Double.Epsilon; } else { x0 = 1.0 - x0; } } return(x0); }
/// <summary> /// Incomplete (regularized) Beta function Ix(a, b). /// </summary> /// /// <example> /// Please see <see cref="Beta"/> /// </example> /// public static double Incomplete(double a, double b, double x) { double aa, bb, t, xx, xc, w, y; bool flag; if (a <= 0.0) { throw new ArgumentOutOfRangeException("a", "Lower limit must be greater than zero."); } if (b <= 0.0) { throw new ArgumentOutOfRangeException("b", "Upper limit must be greater than zero."); } if ((x <= 0.0) || (x >= 1.0)) { if (x == 0.0) { return(0.0); } if (x == 1.0) { return(1.0); } throw new ArgumentOutOfRangeException("x", "Value must be between 0 and 1."); } flag = false; if ((b * x) <= 1.0 && x <= 0.95) { t = PowerSeries(a, b, x); return(t); } w = 1.0 - x; if (x > (a / (a + b))) { flag = true; aa = b; bb = a; xc = x; xx = w; } else { aa = a; bb = b; xc = w; xx = x; } if (flag && (bb * xx) <= 1.0 && xx <= 0.95) { t = PowerSeries(aa, bb, xx); if (t <= Constants.DoubleEpsilon) { t = 1.0 - Constants.DoubleEpsilon; } else { t = 1.0 - t; } return(t); } y = xx * (aa + bb - 2.0) - (aa - 1.0); if (y < 0.0) { w = Incbcf(aa, bb, xx); } else { w = Incbd(aa, bb, xx) / xc; } y = aa * System.Math.Log(xx); t = bb * System.Math.Log(xc); if ((aa + bb) < Gamma.GammaMax && System.Math.Abs(y) < Constants.LogMax && System.Math.Abs(t) < Constants.LogMax) { t = System.Math.Pow(xc, bb); t *= System.Math.Pow(xx, aa); t /= aa; t *= w; t *= Gamma.Function(aa + bb) / (Gamma.Function(aa) * Gamma.Function(bb)); if (flag) { if (t <= Constants.DoubleEpsilon) { t = 1.0 - Constants.DoubleEpsilon; } else { t = 1.0 - t; } } return(t); } y += t + Gamma.Log(aa + bb) - Gamma.Log(aa) - Gamma.Log(bb); y += System.Math.Log(w / aa); if (y < Constants.LogMin) { t = 0.0; } else { t = System.Math.Exp(y); } if (flag) { if (t <= Constants.DoubleEpsilon) { t = 1.0 - Constants.DoubleEpsilon; } else { t = 1.0 - t; } } return(t); }
/// <summary> /// Returns the log factorial of a number (ln(n!)) /// </summary> /// public static double LogFactorial(double n) { return(Gamma.Log(n + 1.0)); }
/// <summary> /// Natural logarithm of the Beta function. /// </summary> /// /// <example> /// Please see <see cref="Beta"/> /// </example> /// public static double Log(double a, double b) { return(Gamma.Log(a) + Gamma.Log(b) - Gamma.Log(a + b)); }
/// <summary> /// Returns the extended factorial definition of a real number. /// </summary> /// public static double Factorial(double n) { return(Gamma.Function(n + 1.0)); }