Пример #1
0
        private static MultiPrecision <N> BesselKLimit(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            Consts.BesselLimitCoef table = Consts.Bessel.LimitCoef(nu);

            MultiPrecision <Plus4 <N> > z_ex = z.Convert <Plus4 <N> >();
            MultiPrecision <Plus4 <N> > v    = 1 / z_ex;

            MultiPrecision <Plus4 <N> > x = 0, p = 1;

            for (int k = 0; k <= Consts.BesselIK.LimitApproxTerms; k++, p *= v)
            {
                MultiPrecision <Plus4 <N> > c = p * table.Value(k);

                x += c;

                if (c.IsZero || x.Exponent - c.Exponent > MultiPrecision <Plus1 <N> > .Bits)
                {
                    break;
                }
            }

            MultiPrecision <Plus1 <N> > z_ex1 = z.Convert <Plus1 <N> >();
            MultiPrecision <Plus1 <N> > r     =
                MultiPrecision <Plus1 <N> > .Exp(-z_ex1) * MultiPrecision <Plus1 <N> > .Sqrt(MultiPrecision <Plus1 <N> > .PI / (2 * z_ex1));

            MultiPrecision <Plus1 <N> > y = r * x.Convert <Plus1 <N> >();

            return(y.Convert <N>());
        }
Пример #2
0
        public static MultiPrecision <N> Gamma(MultiPrecision <N> x)
        {
            if (x.IsNaN || (x.Sign == Sign.Minus && !x.IsFinite))
            {
                return(NaN);
            }

            if (x.IsZero || (x.Sign == Sign.Plus && !x.IsFinite))
            {
                return(PositiveInfinity);
            }

            if (x.Sign == Sign.Minus || x.Exponent < -1)
            {
                MultiPrecision <N> sinpi = SinPI(x);

                if (sinpi.IsZero)
                {
                    return(NaN);
                }

                MultiPrecision <N> y = PI / (sinpi * Gamma(1 - x));

                return(y);
            }
            else
            {
                if (x < Consts.Gamma.Threshold)
                {
                    MultiPrecision <LanczosExpand <N> > a = LanczosAg(x);
                    MultiPrecision <LanczosExpand <N> > s = x.Convert <LanczosExpand <N> >() - MultiPrecision <LanczosExpand <N> > .Point5;
                    MultiPrecision <LanczosExpand <N> > t = (s + Consts.Gamma.Lanczos.G) / MultiPrecision <LanczosExpand <N> > .E;

                    MultiPrecision <LanczosExpand <N> > y_ex = MultiPrecision <LanczosExpand <N> > .Pow(t, s) * a;

                    MultiPrecision <N> y = y_ex.Convert <N>();

                    return(y);
                }
                else
                {
                    MultiPrecision <SterlingExpand <N> > z_ex = x.Convert <SterlingExpand <N> >();

                    MultiPrecision <SterlingExpand <N> > r = MultiPrecision <SterlingExpand <N> > .Sqrt(2 *MultiPrecision <SterlingExpand <N> > .PI / z_ex);

                    MultiPrecision <SterlingExpand <N> > p = MultiPrecision <SterlingExpand <N> > .Pow(z_ex / MultiPrecision <SterlingExpand <N> > .E, z_ex);

                    MultiPrecision <SterlingExpand <N> > s = MultiPrecision <SterlingExpand <N> > .Exp(SterlingTerm(z_ex));

                    MultiPrecision <SterlingExpand <N> > y = r * p * s;

                    return(y.Convert <N>());
                }
            }
        }
Пример #3
0
        public static MultiPrecision <N> BesselK(MultiPrecision <N> nu, MultiPrecision <N> x)
        {
            if (Abs(nu) > 64)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(nu),
                          "In the calculation of the Bessel function, nu with an absolute value greater than 64 is not supported."
                          );
            }
            if (nu.IsNaN || x.IsNaN || x.Sign == Sign.Minus)
            {
                return(NaN);
            }

            if (nu.Sign == Sign.Minus)
            {
                return(BesselK(Abs(nu), x));
            }

            if (nu - Point5 == Floor(nu))
            {
                long n = (long)Floor(nu);

                if (n >= 0 && n < 2)
                {
                    MultiPrecision <Plus1 <N> > x_ex = x.Convert <Plus1 <N> >();
                    MultiPrecision <Plus1 <N> > r    = MultiPrecision <Plus1 <N> > .Exp(-x_ex) * MultiPrecision <Plus1 <N> > .Sqrt(MultiPrecision <Plus1 <N> > .PI / (2 * x_ex));

                    if (n == 0)
                    {
                        return(r.Convert <N>());
                    }
                    if (n == 1)
                    {
                        return((r * (1 + 1 / x_ex)).Convert <N>());
                    }
                }
            }

            if (x.Exponent <= -0x1000000)
            {
                return(nu.IsZero ? PositiveInfinity : NaN);
            }

            if (x < Consts.BesselIK.ApproxThreshold)
            {
                return(BesselKNearZero(nu, x));
            }
            else
            {
                return(BesselKLimit(nu, x));
            }
        }
Пример #4
0
        private static MultiPrecision <N> BesselILimit(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            Consts.BesselLimitCoef table = Consts.Bessel.LimitCoef(nu);

            MultiPrecision <Plus4 <N> > z_ex = z.Convert <Plus4 <N> >();
            MultiPrecision <Plus4 <N> > v    = 1 / z_ex;

            MultiPrecision <Plus4 <N> > x = 0, p = 1;

            Sign sign = Sign.Plus;

            for (int k = 0; k <= Consts.BesselIK.LimitApproxTerms; k++, p *= v)
            {
                MultiPrecision <Plus4 <N> > c = p * table.Value(k);

                if (sign == Sign.Plus)
                {
                    x   += c;
                    sign = Sign.Minus;
                }
                else
                {
                    x   -= c;
                    sign = Sign.Plus;
                }

                if (c.IsZero || x.Exponent - c.Exponent > MultiPrecision <Plus1 <N> > .Bits)
                {
                    break;
                }
            }

            MultiPrecision <Plus1 <N> > z_ex1 = z.Convert <Plus1 <N> >();
            MultiPrecision <Plus1 <N> > r     =
                MultiPrecision <Plus1 <N> > .Exp(z_ex1) / MultiPrecision <Plus1 <N> > .Sqrt(2 *MultiPrecision <Plus1 <N> > .PI *z_ex1);

            MultiPrecision <Plus1 <N> > y = r * x.Convert <Plus1 <N> >();

            return(y.Convert <N>());
        }
        private static MultiPrecision <Plus4 <N> > ErfcContinueFractionalApprox(MultiPrecision <N> z, long n)
        {
            MultiPrecision <Plus4 <N> > z_ex = z.Convert <Plus4 <N> >();
            MultiPrecision <Plus4 <N> > w    = z_ex * z_ex;

            MultiPrecision <Plus4 <N> > f =
                (MultiPrecision <Plus4 <N> > .Sqrt(25 + w * (440 + w * (488 + w * 16 * (10 + w))))
                 - 5 + w * 4 * (1 + w))
                / (20 + w * 8);

            for (long k = checked (4 * n - 3); k >= 1; k -= 4)
            {
                MultiPrecision <Plus4 <N> > c0 = (k + 2) * f;
                MultiPrecision <Plus4 <N> > c1 = w * ((k + 3) + 2 * f);
                MultiPrecision <Plus4 <N> > d0 = checked ((k + 1) * (k + 3)) + (4 * k + 6) * f;
                MultiPrecision <Plus4 <N> > d1 = 2 * c1;

                f = w + k * (c0 + c1) / (d0 + d1);
            }

            MultiPrecision <Plus4 <N> > y = z_ex * MultiPrecision <Plus4 <N> > .Exp(-w) * Consts.Erf.C / f;

            return(y);
        }