/// <summary> /// Computes the logarithm of the Gamma function with double double precision. /// </summary> /// <param name="x">The argument, which must be non-negative.</param> /// <returns>The value of ln(Γ(x)).</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="x"/> is less than zero.</exception> /// <seealso cref="Meta.Numerics.Functions.AdvancedMath.LogGamma(double)"/> public static DoubleDouble LogGamma(DoubleDouble x) { if (x < DoubleDouble.Zero) { throw new ArgumentOutOfRangeException(nameof(x)); } else if (x < 0.5) { // Use x G(x) = G(1+x) to get G(x) from G(1+x) return(LogGammaOnePlus(x) - DoubleDouble.Log(x)); } else if (x < 1.5) { DoubleDouble y = x - 1.0; Debug.Assert(DoubleDouble.Abs(y) <= 0.5); return(LogGammaOnePlus(y)); } else if (x < 16.0) { return(LogGamma_ShiftToZetaSeries(x)); } else { return(LogGamma_ShiftToAsymptotic(x)); } }
private static DoubleDouble LogGamma_ShiftToZetaSeries(DoubleDouble x) { Debug.Assert(x >= 1.5); DoubleDouble s = DoubleDouble.Zero; while (x > 2.5) { x -= DoubleDouble.One; s += DoubleDouble.Log(x); } DoubleDouble y = x - 2.0; Debug.Assert(DoubleDouble.Abs(y) <= 0.5); return(LogGammaTwoPlus(y) + s); }