Пример #1
0
                    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
                    }
Пример #2
0
        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>());
            }
        }
Пример #3
0
        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);
        }