/// <summary> /// Returns the Laczos approximation of Γ(z) /// </summary> public static double Tgamma(double x) { Debug.Assert(x > 0); // check for large x to avoid potential Inf/Inf below if (x > DoubleLimits.MaxGamma + 1) { return(double.PositiveInfinity); } // use the Lanczos approximation double xgh = x + (Lanczos.G - 0.5); double result = Lanczos.Series(x); if (x > MaxPowerTermX) { // we're going to overflow unless this is done with care: double hp = Math.Pow(xgh, (x / 2) - 0.25); result *= (hp / Math.Exp(xgh)); result *= hp; } else { result *= (Math.Pow(xgh, x - 0.5) / Math.Exp(xgh)); } return(result); }
/// <summary> /// Returns Γ(z)/Γ(z+delta) using the Lanczos approximation /// </summary> public static double TgammaDeltaRatio(double x, double delta) { Debug.Assert(x > 0 && delta + x > 0); // Compute Γ(x)/Γ(x+Δ), which reduces to: // // ((x+g-0.5)/(x+Δ+g-0.5))^(x-0.5) * (x+Δ+g-0.5)^-Δ * e^Δ * (Sum(x)/Sum(x+Δ)) // = (1+Δ/(x+g-0.5))^-(x-0.5) * (x+Δ+g-0.5)^-Δ * e^Δ * (Sum(x)/Sum(x+Δ)) double xgh = x + (Lanczos.G - 0.5); double xdgh = x + delta + (Lanczos.G - 0.5); double mu = delta / xgh; double result = Lanczos.Series(x) / Lanczos.Series(x + delta); result *= (Math.Abs(mu) < 0.5) ? Math.Exp((0.5 - x) * Math2.Log1p(mu)) : Math.Pow(xgh / xdgh, x - 0.5); result *= Math.Pow(Math.E / xdgh, delta); return(result); }