static Sterling() { int terms; switch (Length) { case <= 4: terms = 32; break; case <= 8: terms = 60; break; case <= 16: terms = 134; break; case <= 32: terms = 294; break; case <= 64: terms = 640; break; case <= 128: terms = 1262; break; case <= 256: terms = 2608; break; default: throw new ArgumentOutOfRangeException(nameof(Length)); } logbias = MultiPrecision <SterlingExpand <N> > .Log( MultiPrecision <SterlingExpand <N> > .Sqrt(MultiPrecision <SterlingExpand <N> > .PI * 2) ); coef = new MultiPrecision <SterlingExpand <N> > [terms]; for (int i = 0, k = 1; i < coef.Length; i++, k++) { coef[i] = MultiPrecision <SterlingExpand <N> > .BernoulliSequence(k) / checked ((2 * k) * (2 * k - 1)); } #if DEBUG Trace.WriteLine($"Gamma.Sterling<{Length}> initialized."); #endif }
public static MultiPrecision <N> LogGamma(MultiPrecision <N> x) { if (x.IsNaN || x.IsZero || x.Sign == Sign.Minus) { return(NaN); } if (!x.IsFinite) { return(PositiveInfinity); } if (x.Exponent < -1) { return(Log(Gamma(x))); } if ((x - 1).Exponent <= -Bits / 8) { x -= 1; return(x * (-226800 * EulerGamma + x * (18900 * (PI * PI) + x * (-75600 * Zeta3 + x * (630 * Pow(PI, 4) + x * (-45360 * Zeta5 + x * (40 * Pow(PI, 6) + x * (-32400 * Zeta7 + x * (3 * Pow(PI, 8))))))))) / 226800); } if ((x - 2).Exponent <= -Bits / 8) { x -= 2; return(x * (226800 * (1 - EulerGamma) + x * (18900 * ((PI * PI) - 6) + x * (75600 * (1 - Zeta3) + x * (630 * (Pow(PI, 4) - 90) + x * (45360 * (1 - Zeta5) + x * (40 * (Pow(PI, 6) - 945) + x * (32400 * (1 - Zeta7) + x * (3 * (Pow(PI, 8) - 9450))))))))) / 226800); } if (x < Consts.Gamma.Threshold) { MultiPrecision <LanczosExpand <N> > a = MultiPrecision <LanczosExpand <N> > .Log(LanczosAg(x)); MultiPrecision <LanczosExpand <N> > s = x.Convert <LanczosExpand <N> >() - MultiPrecision <LanczosExpand <N> > .Point5; MultiPrecision <LanczosExpand <N> > t = MultiPrecision <LanczosExpand <N> > .Log(s + Consts.Gamma.Lanczos.G); MultiPrecision <LanczosExpand <N> > y_ex = a + s * (t - 1); MultiPrecision <N> y = y_ex.Convert <N>(); return(y); } else { MultiPrecision <SterlingExpand <N> > z_ex = x.Convert <SterlingExpand <N> >(); MultiPrecision <SterlingExpand <N> > p = (z_ex - MultiPrecision <SterlingExpand <N> > .Point5) * MultiPrecision <SterlingExpand <N> > .Log(z_ex); MultiPrecision <SterlingExpand <N> > s = SterlingTerm(z_ex); MultiPrecision <SterlingExpand <N> > y = Consts.Gamma.Sterling.LogBias - z_ex + p + s; return(y.Convert <N>()); } }
private static MultiPrecision <N> BesselKIntegerNuNearZero(int n, MultiPrecision <N> z) { Consts.BesselNearZeroCoef nearzero_table = Consts.Bessel.NearZeroCoef(n); Consts.BesselIntegerFiniteTermCoef finite_table = Consts.Bessel.IntegerFiniteTermCoef(n); Consts.BesselIntegerConvergenceTermCoef convergence_table = Consts.Bessel.IntegerConvergenceTermCoef(n); MultiPrecision <Double <N> > z_ex = z.Convert <Double <N> >(); MultiPrecision <Double <N> > m = MultiPrecision <Double <N> > .Pow(z_ex / 2, n), inv_mm = 1 / (m * m); MultiPrecision <Double <N> > u = m, v = 2 * m * MultiPrecision <Double <N> > .Log(z_ex / 2); MultiPrecision <Double <N> > w = z_ex * z_ex; MultiPrecision <Double <N> > x = 0; bool probably_convergenced = false; Sign sign = Sign.Plus; for (int k = 0; k < int.MaxValue; k++, u *= w, v *= w) { MultiPrecision <Double <N> > c_pos = u * convergence_table.Value(k); MultiPrecision <Double <N> > c_neg = v * nearzero_table.Value(k); MultiPrecision <Double <N> > c = c_pos - c_neg; if ((n & 1) == 0) { x += c; } else { x -= c; } if (k < n) { MultiPrecision <Double <N> > d = u * inv_mm * finite_table.Value(k); if (sign == Sign.Plus) { x += d; sign = Sign.Minus; } else { x -= d; sign = Sign.Plus; } } else { if (c.IsZero || x.Exponent - c.Exponent > MultiPrecision <Plus1 <N> > .Bits) { if (probably_convergenced) { break; } else { probably_convergenced = true; continue; } } probably_convergenced = false; } } MultiPrecision <N> y = x.Convert <N>() / 2; return(y); }