/// <summary> /// Upper incomplete gamma fraction /// <para>Γ(a,z) = (z^a * e^-z) * UpperFraction(a,z)</para> /// <para>Q(a,z) = (z^a * e^-z)/Γ(a) * UpperFraction(a,z)</para> /// </summary> /// <param name="a"></param> /// <param name="z"></param> /// <returns></returns> public static double UpperFraction(double a, double z) { double z0 = z - a + 1; int k = 0; Func <(double, double)> f = () => { k++; return(k * (a - k), z0 + 2 * k); }; return(1.0 / ContinuedFraction.Eval(z0, f)); }
/// <summary> /// Return En(x) using continued fractions: /// <para>En(x) = e^-x/(x + n + ContinuedFraction(-k * (k + n - 1), x + n + 2*k) k={1, ∞}</para> /// </summary> /// <param name="n"></param> /// <param name="x">Requires x > 0</param> /// <returns></returns> /// <seealso href="http://functions.wolfram.com/GammaBetaErf/ExpIntegralE/10/0004/"/> public static double En_Fraction(int n, double x) { double b = n + x; double k = 0; Func <(double, double)> fracF = () => { ++k; return(-k * (k + n - 1), b + 2 * k); }; double frac = ContinuedFraction.Eval(b, fracF); return(Math.Exp(-x) / frac); }
/// <summary> /// Evaluate the incomplete beta via the continued fraction representation /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="normalised"></param> /// <returns></returns> /// <remarks> /// Continued fraction for Ibeta- See: http://dlmf.nist.gov/8.17.E22 /// Converges rapidly when x < (a+1)/(a+b+2); for x > (a+1)/(a+b+2) || 1-x < (b+1)/(a+b+2), use I{1-x}(a, b) /// Continued fraction for the incomplete beta used when a > 1 and b > 1 /// <para>According to NR this is O(sqrt(max(a,b))</para> /// </remarks> public static double Fraction2(double a, double b, double x, double y, bool normalised) { Debug.Assert(x <= a / (a + b) || y <= b / (a + b)); double result = PowerTerms(a, b, x, y, normalised); if (result == 0) { return(result); } // Define the continued fraction function int m = 0; Func <(double an, double bn)> fracF = () => { double aN = (a + m - 1) * (a + b + m - 1) * m * (b - m) * x * x; double denom = (a + 2 * m - 1); aN /= denom * denom; double bN = m; bN += (m * (b - m) * x) / (a + 2 * m - 1); bN += ((a + m) * (a - (a + b) * x + 1 + m * (2 - x))) / (a + 2 * m + 1); ++m; return(aN, bN); }; var(_, b0) = fracF(); // get b0 - skip a0; double fract = ContinuedFraction.Eval(b0, fracF); #if EXTRA_DEBUG double cvg = (a + 1) / (a + b + 2); Debug.WriteLine("CF B({0}, {1}, {2}): cvg = {3}; iterations = {4}", a, b, x, cvg, m); #endif return(result / fract); }