public static MultiPrecision <N> Log1p(MultiPrecision <N> x)
        {
            const int exp_threshold = 2;

            if (x.Exponent >= -exp_threshold)
            {
                return(MultiPrecision <Plus1 <N> > .Log(1 + x.Convert <Plus1 <N> >()).Convert <N>());
            }

            MultiPrecision <Plus1 <N> > x_expand = x.Convert <Plus1 <N> >();
            MultiPrecision <Plus1 <N> > w        = x_expand * x_expand;
            MultiPrecision <Plus1 <N> > y        = x_expand;
            MultiPrecision <Plus1 <N> > z        = w;
            MultiPrecision <Plus1 <N> > s        = x_expand - 1;

            for (long i = 2, f = 2; i < Bits; i += exp_threshold * 2, f += 2)
            {
                MultiPrecision <Plus1 <N> > dy = z * (s * f - 1) / checked (f * (f + 1));
                y += dy;

                if (dy.IsZero || y.Exponent - dy.Exponent > Bits)
                {
                    break;
                }

                z *= w;
            }

            return(y.Convert <N>());
        }
        public static MultiPrecision <N> Digamma(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> tanpi = TanPI(x);

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

                MultiPrecision <N> y = Digamma(1 - x) - PI / tanpi;

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

                    MultiPrecision <LanczosExpand <N> > y_ex = t - Consts.Gamma.Lanczos.G / s + a;

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

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

                    MultiPrecision <SterlingExpand <N> > p = MultiPrecision <SterlingExpand <N> > .Log(z_ex);

                    MultiPrecision <SterlingExpand <N> > s = DiffLogSterlingTerm(z_ex);

                    MultiPrecision <SterlingExpand <N> > y = p - 1 / (2 * z_ex) - s;

                    return(y.Convert <N>());
                }
            }
        }
        private static MultiPrecision <Plus1 <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 <Plus4 <N> > r =
                MultiPrecision <Plus4 <N> > .Exp(-z_ex) * MultiPrecision <Plus4 <N> > .Sqrt(MultiPrecision <Plus4 <N> > .PI / (2 * z_ex));

            MultiPrecision <Plus4 <N> > y = r * x;

            return(y.Convert <Plus1 <N> >());
        }
        public static MultiPrecision <N> Pow(MultiPrecision <N> x, long n)
        {
            if (x.IsNaN)
            {
                return(NaN);
            }

            if (n == 0)
            {
                return(One);
            }

            ulong n_abs = UIntUtil.Abs(n);
            MultiPrecision <Plus1 <N> > y = 1, z = x.Convert <Plus1 <N> >();

            while (n_abs > 0)
            {
                if ((n_abs & 1) == 1)
                {
                    y *= z;
                }

                z      *= z;
                n_abs >>= 1;
            }

            return(((n > 0) ? y : (1 / y)).Convert <N>());
        }
        public static MultiPrecision <N> BesselI(MultiPrecision <N> nu, MultiPrecision <N> x)
        {
            if (MultiPrecision <N> .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(MultiPrecision <N> .NaN);
            }

            if (nu.Sign == Sign.Minus && nu == MultiPrecision <N> .Truncate(nu))
            {
                return(BesselI(MultiPrecision <N> .Abs(nu), x));
            }

            if (nu - MultiPrecision <N> .Point5 == MultiPrecision <N> .Floor(nu))
            {
                long n = (long)MultiPrecision <N> .Floor(nu);

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

                    if (n == -2)
                    {
                        return(-(r * (MultiPrecision <Plus1 <N> > .Cosh(x_ex) / x_ex - MultiPrecision <Plus1 <N> > .Sinh(x_ex))).Convert <N>());
                    }
                    if (n == -1)
                    {
                        return((r * MultiPrecision <Plus1 <N> > .Cosh(x_ex)).Convert <N>());
                    }
                    if (n == 0)
                    {
                        MultiPrecision <N> y = (r * MultiPrecision <Plus1 <N> > .Sinh(x_ex)).Convert <N>();

                        return(y.IsNormal ? y : 0);
                    }
                    if (n == 1)
                    {
                        MultiPrecision <N> y = -(r * (MultiPrecision <Plus1 <N> > .Sinh(x_ex) / x_ex - MultiPrecision <Plus1 <N> > .Cosh(x_ex))).Convert <N>();

                        return(y.IsNormal ? y : 0);
                    }
                }
            }

            if (x < Consts.BesselIK.ApproxThreshold)
            {
                return(BesselINearZero(nu, x).Convert <N>());
            }
            else
            {
                return(BesselILimit(nu, x).Convert <N>());
            }
        }
        public static MultiPrecision <N> Expm1(MultiPrecision <N> x)
        {
            if (x.Exponent >= 0)
            {
                return(Exp(x) - 1);
            }

            MultiPrecision <Plus1 <N> > x_expand = x.Convert <Plus1 <N> >();
            MultiPrecision <Plus1 <N> > z        = x_expand;
            MultiPrecision <Plus1 <N> > y        = MultiPrecision <Plus1 <N> > .Zero;

            foreach (MultiPrecision <Plus1 <N> > t in MultiPrecision <Plus1 <N> > .TaylorSequence)
            {
                MultiPrecision <Plus1 <N> > dy = t * z;
                y += dy;

                if (dy.IsZero || y.Exponent - dy.Exponent > Bits)
                {
                    break;
                }

                z *= x_expand;
            }

            return(y.Convert <N>());
        }
        private static MultiPrecision <N> BesselKIntegerNuNearZero(int n, MultiPrecision <N> z)
        {
            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> > u    = 1;
            MultiPrecision <Double <N> > w    = z_ex * z_ex;

            MultiPrecision <Double <N> > r
                = MultiPrecisionSandbox <Double <N> > .BesselINearZero(n, z_ex).Convert <Double <N> >() * MultiPrecision <Double <N> > .Log(z_ex / 2);

            long r_exponent = r.Exponent;

            MultiPrecision <Double <N> > m = MultiPrecision <Double <N> > .Pow(z_ex / 2, n);

            MultiPrecision <Double <N> > x = 0, y = 0;

            Sign sign = Sign.Plus;

            for (int k = 0; k < int.MaxValue; k++, u *= w)
            {
                MultiPrecision <Double <N> > c = u * convergence_table.Value(k);

                y += c;

                if (k < n)
                {
                    if (sign == Sign.Plus)
                    {
                        x   += u * finite_table.Value(k);
                        sign = Sign.Minus;
                    }
                    else
                    {
                        x   -= u * finite_table.Value(k);
                        sign = Sign.Plus;
                    }
                    continue;
                }

                if (r.Exponent < -MultiPrecision <N> .Bits * 8 && (c.IsZero || y.Exponent - c.Exponent > MultiPrecision <Plus1 <N> > .Bits))
                {
                    break;
                }

                if (c.IsZero || Math.Min(y.Exponent - c.Exponent, r_exponent - c.Exponent - m.Exponent) > MultiPrecision <Double <N> > .Bits)
                {
                    break;
                }
            }

            MultiPrecision <Double <N> > d = (x / m + ((n & 1) == 0 ? 1 : -1) * (y * m - 2 * r)) / 2;

            return(d.Convert <N>());
        }
        private static MultiPrecision <Plus1 <N> > BesselJNearZero(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            Consts.BesselNearZeroCoef table = Consts.Bessel.NearZeroCoef(nu);

            MultiPrecision <Double <N> > z_ex = z.Convert <Double <N> >();
            MultiPrecision <Double <N> > u    = 1;
            MultiPrecision <Double <N> > w    = z_ex * z_ex;

            MultiPrecision <Double <N> > x = 0;

            Sign sign = Sign.Plus;

            for (int k = 0; k < int.MaxValue; k++, u *= w)
            {
                MultiPrecision <Double <N> > c = u * 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;
                }

                if (k >= MultiPrecision <N> .Bits && Math.Max(x.Exponent, c.Exponent) < -MultiPrecision <N> .Bits * 8)
                {
                    return(0);
                }
            }

            MultiPrecision <Double <N> > p;

            if (nu == MultiPrecision <N> .Truncate(nu))
            {
                int n = (int)nu;

                p = MultiPrecision <Double <N> > .Pow(z_ex / 2, n);
            }
            else
            {
                p = MultiPrecision <Double <N> > .Pow(z_ex / 2, nu.Convert <Double <N> >());
            }

            MultiPrecision <Double <N> > y = x * p;

            return(y.Convert <Plus1 <N> >());
        }
        private static MultiPrecision <N> BesselYNonIntegerNu(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            MultiPrecision <Plus1 <N> > bessel_j_pos = BesselJNearZero(nu, z);
            MultiPrecision <Plus1 <N> > bessel_j_neg = BesselJNearZero(-nu, z);

            (MultiPrecision <Plus1 <N> > sin, MultiPrecision <Plus1 <N> > cos) = Consts.Bessel.SinCos(nu);

            MultiPrecision <Plus1 <N> > y = (bessel_j_pos * cos - bessel_j_neg) / sin;

            return(y.Convert <N>());
        }
        private static MultiPrecision <N> BesselKNonIntegerNu(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            MultiPrecision <Plus1 <N> > bessel_i_pos = BesselINearZero(nu, z);
            MultiPrecision <Plus1 <N> > bessel_i_neg = BesselINearZero(-nu, z);

            (MultiPrecision <Plus1 <N> > sin, _) = Consts.Bessel.SinCos(nu);

            MultiPrecision <Plus1 <N> > y = MultiPrecision <Plus1 <N> > .PI * (bessel_i_neg - bessel_i_pos) / (2 * sin);

            return(y.Convert <N>());
        }
        private static MultiPrecision <N> BesselYNearZero(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            int n = (int)MultiPrecision <N> .Round(nu);

            if (nu != n)
            {
                MultiPrecision <N> dnu = nu - n;

                if (dnu.Exponent >= -16)
                {
                    return(BesselYNonIntegerNu(nu, z));
                }
                if (dnu.Exponent >= -32)
                {
                    return(MultiPrecisionSandbox <Plus1 <N> > .BesselYNonIntegerNu(nu.Convert <Plus1 <N> >(), z.Convert <Plus1 <N> >()).Convert <N>());
                }
                if (dnu.Exponent >= -48)
                {
                    return(MultiPrecisionSandbox <Plus2 <N> > .BesselYNonIntegerNu(nu.Convert <Plus2 <N> >(), z.Convert <Plus2 <N> >()).Convert <N>());
                }
                if (dnu.Exponent >= -80)
                {
                    return(MultiPrecisionSandbox <Plus4 <N> > .BesselYNonIntegerNu(nu.Convert <Plus4 <N> >(), z.Convert <Plus4 <N> >()).Convert <N>());
                }
                if (dnu.Exponent >= -144)
                {
                    return(MultiPrecisionSandbox <Plus8 <N> > .BesselYNonIntegerNu(nu.Convert <Plus8 <N> >(), z.Convert <Plus8 <N> >()).Convert <N>());
                }
                if (dnu.Exponent >= -272)
                {
                    return(MultiPrecisionSandbox <Plus16 <N> > .BesselYNonIntegerNu(nu.Convert <Plus16 <N> >(), z.Convert <Plus16 <N> >()).Convert <N>());
                }

                throw new ArgumentException(
                          "The calculation of the BesselY function value is invalid because it loses digits" +
                          " when nu is extremely close to an integer. (|nu - round(nu)| < 1.32 x 10^-82 and nu != round(nu))",
                          nameof(nu));
            }

            return(BesselYIntegerNuNearZero(n, z));
        }
        public static MultiPrecision <N> BesselK(MultiPrecision <N> nu, MultiPrecision <N> x)
        {
            if (MultiPrecision <N> .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(MultiPrecision <N> .NaN);
            }

            if (x.IsZero)
            {
                return(MultiPrecision <N> .PositiveInfinity);
            }
            if (nu.Sign == Sign.Minus)
            {
                return(BesselK(MultiPrecision <N> .Abs(nu), x));
            }

            if (nu - MultiPrecision <N> .Point5 == MultiPrecision <N> .Floor(nu))
            {
                long n = (long)MultiPrecision <N> .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 < Consts.BesselIK.ApproxThreshold)
            {
                return(BesselKNearZero(nu, x));
            }
            else
            {
                return(BesselKLimit(nu, x).Convert <N>());
            }
        }
        private static MultiPrecision <N> BesselYIntegerNuNearZero(int n, MultiPrecision <N> z)
        {
            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> > u    = 1;
            MultiPrecision <Double <N> > w    = z_ex * z_ex;

            MultiPrecision <Double <N> > r
                = 2 * BesselJNearZero(n, z).Convert <Double <N> >() * MultiPrecision <Double <N> > .Log(z_ex / 2);

            long r_exponent = MultiPrecision <Pow2.N4> .Sqrt(2 / (MultiPrecision <Pow2.N4> .PI * (z.Convert <Pow2.N4>() + MultiPrecision <Pow2.N4> .Point5))).Exponent;

            MultiPrecision <Double <N> > m = MultiPrecision <Double <N> > .Pow(z_ex / 2, n);

            MultiPrecision <Double <N> > x = 0, y = 0;

            Sign sign = Sign.Plus;

            for (int k = 0; k < int.MaxValue; k++, u *= w)
            {
                MultiPrecision <Double <N> > c = u * convergence_table.Value(k);

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

                if (k < n)
                {
                    y += u * finite_table.Value(k);
                    continue;
                }

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

            MultiPrecision <Double <N> > d = (r - y / m - x * m) / MultiPrecision <Double <N> > .PI;

            return(d.Convert <N>());
        }
Beispiel #14
0
        private static MultiPrecision <N> InverseErfcRootFinding(MultiPrecision <N> x)
        {
            MultiPrecision <N> s = 2 / Sqrt(PI);

            MultiPrecision <N> z0;

            if (Length <= 4)
            {
                const double a = 0.147;

                MultiPrecision <Pow2.N4> xl4 = x.Convert <Pow2.N4>();
                MultiPrecision <Pow2.N4> lg  = MultiPrecision <Pow2.N4> .Log((2 - xl4) *xl4);

                MultiPrecision <Pow2.N4> lga = 2 / (MultiPrecision <Pow2.N4> .PI * a) + lg / 2;

                z0 = MultiPrecision <Pow2.N4> .Sqrt(MultiPrecision <Pow2.N4> .Sqrt(lga *lga - lg / a) - lga).Convert <N>();
            }
            else
            {
                z0 = MultiPrecision <Pow2.N4> .InverseErfcRootFinding(x.Convert <Pow2.N4>()).Convert <N>();
            }

            MultiPrecision <N> erfc(MultiPrecision <N> z)
            {
                return(Erfc(z) - x);
            };
            (MultiPrecision <N>, MultiPrecision <N>) derfc(MultiPrecision <N> z)
            {
                MultiPrecision <N> d1 = -Exp(-z * z) * s;
                MultiPrecision <N> d2 = -2 * z * d1;

                return(d1, d2);
            };

            MultiPrecision <N> y = MultiPrecisionUtil.HalleyRootFinding(z0, erfc, derfc, break_overshoot: true);

            return(y);
        }
        private static MultiPrecision <Plus1 <N> > BesselYLimit(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> > w    = v * v;

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

            Sign sign = Sign.Plus;

            for (int k = 0; k <= Consts.BesselJY.LimitApproxTerms; k++, p *= w, q *= w)
            {
                MultiPrecision <Plus4 <N> > c = p * table.Value(k * 2);
                MultiPrecision <Plus4 <N> > s = q * table.Value(k * 2 + 1);

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

                if (!c.IsZero && x.Exponent - c.Exponent <= MultiPrecision <Plus1 <N> > .Bits)
                {
                    continue;
                }
                if (!s.IsZero && y.Exponent - s.Exponent <= MultiPrecision <Plus1 <N> > .Bits)
                {
                    continue;
                }

                break;
            }

            MultiPrecision <Plus4 <N> > omega = z_ex - (2 * nu.Convert <Plus4 <N> >() + 1) * MultiPrecision <Plus4 <N> > .PI / 4;
            MultiPrecision <Plus4 <N> > m     = x * MultiPrecision <Plus4 <N> > .Sin(omega) + y * MultiPrecision <Plus4 <N> > .Cos(omega);

            MultiPrecision <Plus4 <N> > t = m * MultiPrecision <Plus4 <N> > .Sqrt(2 / (MultiPrecision <Plus4 <N> > .PI *z_ex));

            return(t.Convert <Plus1 <N> >());
        }
Beispiel #16
0
        public static (MultiPrecision <N> y, int convergense_n) Erf(MultiPrecision <N> z)
        {
            MultiPrecision <Plus4 <N> > z_ex = z.Convert <Plus4 <N> >();
            MultiPrecision <Plus4 <N> > w = z_ex * z_ex, v = w;
            MultiPrecision <Plus4 <N> > c = MultiPrecision <Plus4 <N> > .Ldexp(z_ex, 1) / MultiPrecision <Plus4 <N> > .Sqrt(MultiPrecision <Plus4 <N> > .PI);

            MultiPrecision <Plus4 <N> > s = MultiPrecision <Plus4 <N> > .One;

            MultiPrecision <N> s_prev = null;

            int n = 1;

            while (s_prev != s.Convert <N>())
            {
                s_prev = s.Convert <N>();

                s += v / ErfTaylorSeries.Coef <Plus4 <N> >(n);

                v *= w;
                n++;
            }

            return((s * c).Convert <N>(), n - 1);
        }
        public static MultiPrecision <N> Pow(MultiPrecision <N> x, MultiPrecision <N> y)
        {
            if (x.Sign == Sign.Minus)
            {
                return(NaN);
            }

            if (y.IsZero)
            {
                return(x.IsNaN ? NaN : 1);
            }

            MultiPrecision <Plus1 <N> > z = MultiPrecision <Plus1 <N> > .Pow2(y.Convert <Plus1 <N> >() *MultiPrecision <Plus1 <N> > .Log2(x.Convert <Plus1 <N> >()));

            return(z.Convert <N>());
        }
        public static (MultiPrecision <N>[] cs, MultiPrecision <N>[] ds) Table(MultiPrecision <N> nu, int m)
        {
            BesselLimitCoef <Plus16 <N> > limitcoef = new(nu.Convert <Plus16 <N> >());

            MultiPrecision <N>[] cs = new MultiPrecision <N> [m + 1], ds = new MultiPrecision <N> [m + 1];

            for (int j = 0; j <= m; j++)
            {
                ds[j] = ShiftedLegendre.Table(m, m - j) / ((m - j + 1) * limitcoef.Value(m - j + 1)).Convert <N>();

                MultiPrecision <Plus16 <N> > sum = 0;

                for (int p = m - j; p <= m; p++)
                {
                    sum += ShiftedLegendre.Table(m, p) * limitcoef.Value(p - m + j) / ((p + 1) * limitcoef.Value(p + 1));
                }

                cs[j] = sum.Convert <N>();
            }

            return(cs, ds);
        }
        private static MultiPrecision <Plus1 <N> > BesselINearZero(MultiPrecision <N> nu, MultiPrecision <N> z)
        {
            Consts.BesselNearZeroCoef table = Consts.Bessel.NearZeroCoef(nu);

            MultiPrecision <Double <N> > z_ex = z.Convert <Double <N> >();
            MultiPrecision <Double <N> > u    = 1;
            MultiPrecision <Double <N> > w    = z_ex * z_ex;

            MultiPrecision <Double <N> > x = 0;

            for (int k = 0; k < int.MaxValue; k++, u *= w)
            {
                MultiPrecision <Double <N> > c = u * table.Value(k);

                x += c;

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

            MultiPrecision <Double <N> > p;

            if (nu == MultiPrecision <N> .Truncate(nu))
            {
                int n = (int)nu;

                p = MultiPrecision <Double <N> > .Pow(z_ex / 2, n);
            }
            else
            {
                p = MultiPrecision <Double <N> > .Pow(z_ex / 2, nu.Convert <Double <N> >());
            }

            MultiPrecision <Double <N> > y = x * p;

            return(y.Convert <Plus1 <N> >());
        }
        private static MultiPrecision <Plus1 <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 <Plus4 <N> > r =
                MultiPrecision <Plus4 <N> > .Exp(z_ex) / MultiPrecision <Plus4 <N> > .Sqrt(2 *MultiPrecision <Plus4 <N> > .PI *z_ex);

            MultiPrecision <Plus4 <N> > y = r * x;

            return(y.Convert <Plus1 <N> >());
        }
Beispiel #21
0
        public static MultiPrecision <N> Frac(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) + MultiPrecision <Plus4 <N> > .Ldexp(f, 1));
                MultiPrecision <Plus4 <N> > d0 = checked ((k + 1) * (k + 3)) + (4 * k + 6) * f;
                MultiPrecision <Plus4 <N> > d1 = MultiPrecision <Plus4 <N> > .Ldexp(c1, 1);

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

            MultiPrecision <Plus4 <N> > y = 1 / f;

            return(y.Convert <N>());
        }
Beispiel #22
0
            static int plot(StreamWriter sw, decimal nu, int min_matchbits, decimal z)
            {
                MultiPrecision <N> t = MultiPrecisionSandbox <N> .BesselJ(nu, z);

                MultiPrecision <Plus1 <N> > s = MultiPrecisionSandbox <Plus1 <N> > .BesselJ(nu, z);

                sw.WriteLine($"  z: {z}");
                sw.WriteLine($"  f : {t}");
                sw.WriteLine($"  {t.ToHexcode()}");
                sw.WriteLine($"  {s.ToHexcode()}");

                MultiPrecision <N> err = MultiPrecision <N> .Abs(t - s.Convert <N>());

                sw.WriteLine($"  err : {err}");

                for (int keepbits = MultiPrecision <N> .Bits; keepbits >= 0; keepbits--)
                {
                    if (keepbits == 0)
                    {
                        min_matchbits = 0;
                    }
                    else if (MultiPrecision <N> .RoundMantissa(t, MultiPrecision <N> .Bits - keepbits) == MultiPrecision <N> .RoundMantissa(s.Convert <N>(), MultiPrecision <N> .Bits - keepbits))
                    {
                        sw.WriteLine($"  matchbits : {keepbits}");

                        if (keepbits < min_matchbits)
                        {
                            min_matchbits = keepbits;
                        }

                        break;
                    }
                }

                return(min_matchbits);
            }
Beispiel #23
0
        public void EllipticPiNm8Test()
        {
            double[] expecteds =
            {
                0.52359877559829887308,
                0.52361475639377532997,
                0.52366272074128880844,
                0.52374273462815274607,
                0.52385490838114581024,
                0.52399939719209866599,
                0.52417640186118694473,
                0.52438616976555954257,
                0.52462899606334110795,
                0.52490522514563837006,
                0.52521525235200198986,
                0.52555952596790562569,
                0.52593854952626698859,
                0.52635288443892738952,
                0.52680315298841529070,
                0.52729004171535052445,
                0.52781430524262411711,
                0.52837677058416400379,
                0.52897834199385032548,
                0.52962000641919511826,
                0.53030283963501802994,
                0.53102801314486087814,
                0.53179680195269445973,
                0.53261059332508282122,
                0.53347089668500800162,
                0.53437935480380414133,
                0.53533775648808807655,
                0.53634805099544981306,
                0.53741236445756644652,
                0.53853301864435841984,
                0.53971255247043596415,
                0.54095374672878443102,
                0.54225965264085163513,
                0.54363362494277720172,
                0.54507936039220636429,
                0.54660094278934898288,
                0.54820289587370921307,
                0.54989024580334764637,
                0.55166859537297942914,
                0.55354421271730801107,
                0.55552413802833870482,
                0.55761631286354090184,
                0.55982973804182544789,
                0.56217466807193891665,
                0.56466285276448362514,
                0.56730784049447278680,
                0.57012536304555373922,
                0.57313382992762836141,
                0.57635497187872458145,
                0.57981469118170348280,
                0.58354420423768448898,
                0.58758160614621523694,
                0.59197405975158949141,
                0.59678093501819213678,
                0.60207844231460657556,
                0.60796670501020061368,
                0.61458099891081150171,
                0.62211050868074325640,
                0.63083159131603928834,
                0.64117154563336814677,
                0.65384423879725213546,
                0.67018408727482935680,
                0.69317792535594728369,
                0.73232569786838977337
            };

            const double n = -8;

            for (int i = 0; i < 64; i++)
            {
                decimal k = i / 64m;

                double expected = expecteds[i];

                MultiPrecision <Pow2.N4> y4 = MultiPrecision <Pow2.N4> .EllipticPi(n, k);

                MultiPrecision <Pow2.N8> y8 = MultiPrecision <Pow2.N8> .EllipticPi(n, k);

                MultiPrecision <Pow2.N16> y16 = MultiPrecision <Pow2.N16> .EllipticPi(n, k);

                MultiPrecision <Pow2.N32> y32 = MultiPrecision <Pow2.N32> .EllipticPi(n, k);

                Console.WriteLine(k);
                Console.WriteLine(y4);
                Console.WriteLine(y4.ToHexcode());
                Console.WriteLine(y8.ToHexcode());
                Console.WriteLine(y16.ToHexcode());
                Console.WriteLine(y32.ToHexcode());

                Assert.AreEqual(expected, (double)y4, expected * 1e-15);
                Assert.IsTrue(MultiPrecision <Pow2.N4> .NearlyEqualBits(y4, y8.Convert <Pow2.N4>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N8> .NearlyEqualBits(y8, y16.Convert <Pow2.N8>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N16> .NearlyEqualBits(y16, y32.Convert <Pow2.N16>(), 1));
            }
        }
Beispiel #24
0
        public void EllipticPikp50Test()
        {
            double[] expecteds =
            {
                0.39151541427194962716,
                0.39225307898379602412,
                0.39299488668739780067,
                0.39374087616413515348,
                0.39449108670451362898,
                0.39524555811677923107,
                0.39600433073571222311,
                0.39676744543160401816,
                0.39753494361942167695,
                0.39830686726816466182,
                0.39908325891041862864,
                0.39986416165211117591,
                0.40064961918247461291,
                0.40143967578422095536,
                0.40223437634393450876,
                0.40303376636268755661,
                0.40383789196688483225,
                0.40464679991934262079,
                0.40546053763060851046,
                0.40627915317052799134,
                0.40710269528006428456,
                0.40793121338337797601,
                0.40876475760017322611,
                0.40960337875831753185,
                0.41044712840674222853,
                0.41129605882863113712,
                0.41215022305490498991,
                0.41300967487800950069,
                0.41387446886601518832,
                0.41474466037703731318,
                0.41562030557398454567,
                0.41650146143964525444,
                0.41738818579212058076,
                0.41828053730061375323,
                0.41917857550158539569,
                0.42008236081528489050,
                0.42099195456266817976,
                0.42190741898271271877,
                0.42282881725014064052,
                0.42375621349356154631,
                0.42468967281404670753,
                0.42562926130414684684,
                0.42657504606736606480,
                0.42752709523810488997,
                0.42848547800208585850,
                0.42945026461727547299,
                0.43042152643531685069,
                0.43139933592348784916,
                0.43238376668719995364,
                0.43337489349305372514,
                0.43437279229246714336,
                0.43537754024589373355,
                0.43638921574764794344,
                0.43740789845135583574,
                0.43843366929604978407,
                0.43946661053292650755,
                0.44050680575278845168,
                0.44155433991418922248,
                0.44260929937230450786,
                0.44367177190855067617,
                0.44474184676097402852,
                0.44581961465543449936,
                0.44690516783760845150,
                0.44799860010583609737,
                0.44910000684484000092,
                0.45020948506034207441,
                0.45132713341460748459,
                0.45245305226294492378,
                0.45358734369119378641,
                0.45473011155422992181,
                0.45588146151552281204,
                0.45704150108777825119,
                0.45821033967470188299,
                0.45938808861392028803,
                0.46057486122109770426,
                0.46177077283528791689,
                0.46297594086556236901,
                0.46419048483895712601,
                0.46541452644978297759,
                0.46664818961034468524,
                0.46789160050311718294,
                0.46914488763442841921,
                0.47040818188970049355,
                0.47168161659030279297,
                0.47296532755207298061,
                0.47425945314556393201,
                0.47556413435807706096,
                0.47687951485754493110,
                0.47820574105832861724,
                0.47954296218899796770,
                0.48089133036216573151,
                0.48225100064644945977,
                0.48362213114063817459,
                0.48500488305014403010,
                0.48639942076582257540,
                0.48780591194524877756,
                0.48922452759653968269,
                0.49065544216481849335,
                0.49209883362141893254,
                0.49355488355593305658,
                0.49502377727121018479,
                0.49650570388141934249,
                0.49800085641329258031,
                0.49950943191067174837,
                0.50103163154248678417,
                0.50256766071429933247,
                0.50411772918355156966,
                0.50568205117866647248,
                0.50726084552215246747,
                0.50885433575787244453,
                0.51046275028264453488,
                0.51208632248234986200,
                0.51372529087273069873,
                0.51537989924507112718,
                0.51705039681696142915,
                0.51873703838835705981,
                0.52044008450315320806,
                0.52215980161650665409,
                0.52389646226814793402,
                0.52565034526193874846,
                0.52742173585194214686,
                0.52921092593528632390,
                0.53101821425211692305,
                0.53284390659294760421,
                0.53468831601373434818,
                0.53655176305901559602,
                0.53843457599347791547,
                0.54033709104232551285,
                0.54225965264085163513,
                0.54420261369363080708,
                0.54616633584377300016,
                0.54815118975270431795,
                0.55015755539096369842,
                0.55218582234053157307,
                0.55423639010923449276,
                0.55630966845779954205,
                0.55840607774016404068,
                0.56052604925767970322,
                0.56267002562788623745,
                0.56483846116856746138,
                0.56703182229784357349,
                0.56925058795109639733,
                0.57149525001557043447,
                0.57376631378354160508,
                0.57606429842499786013,
                0.57838973748083165542,
                0.58074317937760385111,
                0.58312518796500222587,
                0.58553634307718578420,
                0.58797724111927872467,
                0.59044849568035569256,
                0.59295073817434316048,
                0.59548461851035089674,
                0.59805080579404296588,
                0.60064998906176006946,
                0.60328287804921483854,
                0.60595020399669953998,
                0.60865272049287222239,
                0.61139120435932332978,
                0.61416645657827104561,
                0.61697930326589096394,
                0.61983059669395506894,
                0.62272121636263747800,
                0.62565207012754110922,
                0.62862409538421162136,
                0.63163826031363401888,
                0.63469556519245472555,
                0.63779704377193936973,
                0.64094376472996582054,
                0.64413683320066518293,
                0.64737739238666272300,
                0.65066662525923850669,
                0.65400575635212660514,
                0.65739605365510504857,
                0.66083883061399961411,
                0.66433544824423669223,
                0.66788731736563796958,
                0.67149590096675702510,
                0.67516271670772019679,
                0.67888933957125684357,
                0.68267740467239364325,
                0.68652861023815079786,
                0.69044472076952273483,
                0.69442757039906078974,
                0.69847906645851015894,
                0.70260119327219901891,
                0.70679601619324635229,
                0.71106568590116043605,
                0.71541244298105758788,
                0.71983862280655803802,
                0.72434666075043232641,
                0.72893909774929959168,
                0.73361858625114359763,
                0.73838789657714174111,
                0.74324992373232882859,
                0.74820769470297770912,
                0.75326437628231457300,
                0.75842328347034535482,
                0.76368788849820542975,
                0.76906183053261966124,
                0.77454892612184486982,
                0.78015318045094345387,
                0.78587879948149891441,
                0.79173020305903936064,
                0.79771203908060827881,
                0.80382919882525699475,
                0.81008683356189728132,
                0.81649037256213929476,
                0.82304554266067503682,
                0.82975838952271390907,
                0.83663530079724217667,
                0.84368303135682261894,
                0.85090873084969754269,
                0.85831997381860602196,
                0.86592479267356303705,
                0.87373171384357052461,
                0.88174979747566483527,
                0.88998868109983569125,
                0.89845862773635315787,
                0.90717057898931811435,
                0.91613621374849809513,
                0.92536801321276081183,
                0.93487933305513503866,
                0.94468448367470165185,
                0.95479881962778670259,
                0.96523883950474394881,
                0.97602229772443872744,
                0.98716832996311040700,
                0.99869759422592885941,
                1.0106324299186293446,
                1.0229970376960460493,
                1.0358176833704014299,
                1.0491229297753223260,
                1.0629439012277066659,
                1.0773145861418566953,
                1.0922721844711713307,
                1.1078575080369107147,
                1.1241154435222068440,
                1.1410954900555225259,
                1.1588523860034766843,
                1.1774468430005661827,
                1.1969464095796224804,
                1.2174264923240208789,
                1.2389715696379424894,
                1.2616766425694954149,
                1.2856489793787537301,
                1.3110102267770174743,
                1.3378989824739080544,
                1.3664739530045968945,
                1.3969178608922344119,
                1.4294423206281103030,
                1.4642939805979271642,
                1.5017623383916399836,
                1.5421897960602253947,
                1.5859847552927187373,
                1.6336389011844131988,
                1.6857503548125960429,
                1.7430552034230875194,
                1.8064712412205729527,
                1.8771599299166708295,
                1.9566162791192362073,
                2.0468028359333301478,
                2.1503558644945609607,
                2.2709146622933868486,
                2.4136715042011946407,
                2.5863411458761695616,
                2.8009892401268232472,
                3.0777924131600616977,
                3.4537195109187421402,
                4.0061518665671908603,
                4.9359533239463205273,
                7.0434078792100644325
            };

            const double k = 0.5;

            for (int i = -256; i < 16; i++)
            {
                decimal n = i / 16m;

                double expected = expecteds[i + 256];

                MultiPrecision <Pow2.N4> y4 = MultiPrecision <Pow2.N4> .EllipticPi(n, k);

                MultiPrecision <Pow2.N8> y8 = MultiPrecision <Pow2.N8> .EllipticPi(n, k);

                MultiPrecision <Pow2.N16> y16 = MultiPrecision <Pow2.N16> .EllipticPi(n, k);

                MultiPrecision <Pow2.N32> y32 = MultiPrecision <Pow2.N32> .EllipticPi(n, k);

                Console.WriteLine(k);
                Console.WriteLine(y4);
                Console.WriteLine(y4.ToHexcode());
                Console.WriteLine(y8.ToHexcode());
                Console.WriteLine(y16.ToHexcode());
                Console.WriteLine(y32.ToHexcode());

                Assert.AreEqual(expected, (double)y4, expected * 1e-15);
                Assert.IsTrue(MultiPrecision <Pow2.N4> .NearlyEqualBits(y4, y8.Convert <Pow2.N4>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N8> .NearlyEqualBits(y8, y16.Convert <Pow2.N8>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N16> .NearlyEqualBits(y16, y32.Convert <Pow2.N16>(), 1));
            }
        }
        public static MultiPrecision <N> Log(MultiPrecision <N> x)
        {
            MultiPrecision <Plus1 <N> > y = MultiPrecision <Plus1 <N> > .Log2(x.Convert <Plus1 <N> >()) * MultiPrecision <Plus1 <N> > .Ln2;

            return(y.Convert <N>());
        }
Beispiel #26
0
        public void EllipticKTest()
        {
            double[] expecteds =
            {
                1.5707963267948966192,
                1.5708922137626348384,
                1.5711800327950414382,
                1.5716602590854044625,
                1.5723336873167065823,
                1.5732014357326469747,
                1.5742649518971571344,
                1.5755260202037926323,
                1.5769867712158131421,
                1.5786496929386844702,
                1.5805176441495632799,
                1.5825938699335270894,
                1.5848820196044282199,
                1.5873861672199078079,
                1.5901108349360414470,
                1.5930610194881743919,
                1.5962422221317835101,
                1.5996604824319273643,
                1.6033224163535283547,
                1.6072352591792112210,
                1.6114069138689479181,
                1.6158460055790900447,
                1.6205619431809133463,
                1.6255649887647804235,
                1.6308663362907171768,
                1.6364782007562008756,
                1.6424139195055974161,
                1.6486880676135124582,
                1.6553165896497853013,
                1.6623169505942065935,
                1.6697083092365505436,
                1.6775117181011207095,
                1.6857503548125960429,
                1.6944497909214828361,
                1.7036383055993221024,
                1.7133472533849584282,
                1.7236114974339794600,
                1.7344699226581490085,
                1.7459660469667769180,
                1.7581487538531659485,
                1.7710731762515814444,
                1.7848017705587752735,
                1.7994056318875859810,
                1.8149661183461979700,
                1.8315768754231192499,
                1.8493463844468008136,
                1.8684012062736826855,
                1.8888901602273695618,
                1.9109897807518291966,
                1.9349115498481339540,
                1.9609116453188370344,
                1.9893043310480998110,
                2.0204807505101105943,
                2.0549359644344846108,
                2.0933089821785136758,
                2.1364440658135019426,
                2.1854884692782236869,
                2.2420560837698999062,
                2.3085186232456553532,
                2.3885657507906773322,
                2.4884004914010351610,
                2.6196934131113362507,
                2.8087438358654412952,
                3.1398110351826142968,
            };

            for (int i = 0; i < 64; i++)
            {
                decimal k = i / 64m;

                double expected = expecteds[i];

                MultiPrecision <Pow2.N4> y4 = MultiPrecision <Pow2.N4> .EllipticK(k);

                MultiPrecision <Pow2.N8> y8 = MultiPrecision <Pow2.N8> .EllipticK(k);

                MultiPrecision <Pow2.N16> y16 = MultiPrecision <Pow2.N16> .EllipticK(k);

                MultiPrecision <Pow2.N32> y32 = MultiPrecision <Pow2.N32> .EllipticK(k);

                Console.WriteLine(k);
                Console.WriteLine(y4);
                Console.WriteLine(y4.ToHexcode());
                Console.WriteLine(y8.ToHexcode());
                Console.WriteLine(y16.ToHexcode());
                Console.WriteLine(y32.ToHexcode());

                Assert.AreEqual(expected, (double)y4, expected * 1e-15);
                Assert.IsTrue(MultiPrecision <Pow2.N4> .NearlyEqualBits(y4, y8.Convert <Pow2.N4>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N8> .NearlyEqualBits(y8, y16.Convert <Pow2.N8>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N16> .NearlyEqualBits(y16, y32.Convert <Pow2.N16>(), 1));
            }
        }
        public static MultiPrecision <N> Exp(MultiPrecision <N> x)
        {
            MultiPrecision <Plus1 <N> > y = MultiPrecision <Plus1 <N> > .Pow2(x.Convert <Plus1 <N> >() *MultiPrecision <Plus1 <N> > .LbE);

            return(y.Convert <N>());
        }
Beispiel #28
0
        public void EllipticENearOneTest()
        {
            const int exponent = -32;

            {
                MultiPrecision <Pow2.N4>[] ks =
                {
                    MultiPrecision <Pow2.N4> .BitDecrement(1),
                    MultiPrecision <Pow2.N4> .BitDecrement(1 - MultiPrecision <Pow2.N4> .Ldexp(1,exponent)),
                    1 - MultiPrecision <Pow2.N4> .Ldexp(1,                                       exponent),
                    MultiPrecision <Pow2.N4> .BitIncrement(1 - MultiPrecision <Pow2.N4> .Ldexp(1,exponent)),
                };

                foreach (var k in ks)
                {
                    MultiPrecision <Pow2.N4> y4 = MultiPrecision <Pow2.N4> .EllipticE(k);

                    MultiPrecision <Pow2.N8> y8 = MultiPrecision <Pow2.N8> .EllipticE(k.Convert <Pow2.N8>());

                    Console.WriteLine(k.ToHexcode());
                    Console.WriteLine(y4);
                    Console.WriteLine(y4.ToHexcode());
                    Console.WriteLine(y8.ToHexcode());

                    Assert.IsTrue(MultiPrecision <Pow2.N4> .NearlyEqualBits(y4, y8.Convert <Pow2.N4>(), 32));
                }
            }

            {
                MultiPrecision <Pow2.N8>[] ks =
                {
                    MultiPrecision <Pow2.N8> .BitDecrement(1),
                    MultiPrecision <Pow2.N8> .BitDecrement(1 - MultiPrecision <Pow2.N8> .Ldexp(1,exponent)),
                    1 - MultiPrecision <Pow2.N8> .Ldexp(1,                                       exponent),
                    MultiPrecision <Pow2.N8> .BitIncrement(1 - MultiPrecision <Pow2.N8> .Ldexp(1,exponent)),
                };

                foreach (var k in ks)
                {
                    MultiPrecision <Pow2.N8> y8 = MultiPrecision <Pow2.N8> .EllipticE(k);

                    MultiPrecision <Pow2.N16> y16 = MultiPrecision <Pow2.N16> .EllipticE(k.Convert <Pow2.N16>());

                    Console.WriteLine(k.ToHexcode());
                    Console.WriteLine(y8);
                    Console.WriteLine(y8.ToHexcode());
                    Console.WriteLine(y16.ToHexcode());

                    Assert.IsTrue(MultiPrecision <Pow2.N8> .NearlyEqualBits(y8, y16.Convert <Pow2.N8>(), 64));
                }
            }

            {
                MultiPrecision <Pow2.N16>[] ks =
                {
                    MultiPrecision <Pow2.N16> .BitDecrement(1),
                    MultiPrecision <Pow2.N16> .BitDecrement(1 - MultiPrecision <Pow2.N16> .Ldexp(1,exponent)),
                    1 - MultiPrecision <Pow2.N16> .Ldexp(1,                                        exponent),
                    MultiPrecision <Pow2.N16> .BitIncrement(1 - MultiPrecision <Pow2.N16> .Ldexp(1,exponent)),
                };

                foreach (var k in ks)
                {
                    MultiPrecision <Pow2.N16> y16 = MultiPrecision <Pow2.N16> .EllipticE(k);

                    MultiPrecision <Pow2.N32> y32 = MultiPrecision <Pow2.N32> .EllipticE(k.Convert <Pow2.N32>());

                    Console.WriteLine(k.ToHexcode());
                    Console.WriteLine(y16);
                    Console.WriteLine(y16.ToHexcode());
                    Console.WriteLine(y32.ToHexcode());

                    Assert.IsTrue(MultiPrecision <Pow2.N16> .NearlyEqualBits(y16, y32.Convert <Pow2.N16>(), 128));
                }
            }

            {
                MultiPrecision <Pow2.N32>[] ks =
                {
                    MultiPrecision <Pow2.N32> .BitDecrement(1),
                    MultiPrecision <Pow2.N32> .BitDecrement(1 - MultiPrecision <Pow2.N32> .Ldexp(1,exponent)),
                    1 - MultiPrecision <Pow2.N32> .Ldexp(1,                                        exponent),
                    MultiPrecision <Pow2.N32> .BitIncrement(1 - MultiPrecision <Pow2.N32> .Ldexp(1,exponent)),
                };

                foreach (var k in ks)
                {
                    MultiPrecision <Pow2.N32> y32 = MultiPrecision <Pow2.N32> .EllipticE(k);

                    MultiPrecision <Pow2.N64> y64 = MultiPrecision <Pow2.N64> .EllipticE(k.Convert <Pow2.N64>());

                    Console.WriteLine(k.ToHexcode());
                    Console.WriteLine(y32);
                    Console.WriteLine(y32.ToHexcode());
                    Console.WriteLine(y64.ToHexcode());

                    Assert.IsTrue(MultiPrecision <Pow2.N32> .NearlyEqualBits(y32, y64.Convert <Pow2.N32>(), 256));
                }
            }
        }
        public static MultiPrecision <N> BesselY(MultiPrecision <N> nu, MultiPrecision <N> x)
        {
            if (MultiPrecision <N> .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)
            {
                return(MultiPrecision <N> .NaN);
            }

            if (x.Sign == Sign.Minus)
            {
                if (nu != MultiPrecision <N> .Truncate(nu))
                {
                    return(MultiPrecision <N> .NaN);
                }

                long n = (long)nu;
                return(((n & 1L) == 0) ? BesselY(nu, MultiPrecision <N> .Abs(x)) : -BesselY(nu, MultiPrecision <N> .Abs(x)));
            }

            if (!x.IsFinite)
            {
                return(0);
            }
            if (x.IsZero)
            {
                return(MultiPrecision <N> .NegativeInfinity);
            }
            if (nu.Sign == Sign.Minus && nu == MultiPrecision <N> .Truncate(nu))
            {
                long n = (long)nu;
                return(((n & 1L) == 0) ? BesselY(MultiPrecision <N> .Abs(nu), x) : -BesselY(MultiPrecision <N> .Abs(nu), x));
            }

            if (nu - MultiPrecision <N> .Point5 == MultiPrecision <N> .Floor(nu))
            {
                long n = (long)MultiPrecision <N> .Floor(nu);

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

                    if (n == -2)
                    {
                        MultiPrecision <N> y = -(envelope * (MultiPrecision <Plus1 <N> > .Sin(x_ex) / x_ex - MultiPrecision <Plus1 <N> > .Cos(x_ex))).Convert <N>();

                        return(y.IsNormal ? y : 0);
                    }
                    if (n == -1)
                    {
                        MultiPrecision <N> y = (envelope * MultiPrecision <Plus1 <N> > .Sin(x_ex)).Convert <N>();

                        return(y.IsNormal ? y : 0);
                    }
                    if (n == 0)
                    {
                        return(-(envelope * MultiPrecision <Plus1 <N> > .Cos(x_ex)).Convert <N>());
                    }
                    if (n == 1)
                    {
                        return(-(envelope * (MultiPrecision <Plus1 <N> > .Cos(x_ex) / x_ex + MultiPrecision <Plus1 <N> > .Sin(x_ex))).Convert <N>());
                    }
                }
            }

            if (MultiPrecision <N> .Length <= 4)
            {
                return(MultiPrecisionSandbox <Plus1 <N> > .BesselY(nu.Convert <Plus1 <N> >(), x.Convert <Plus1 <N> >()).Convert <N>());
            }

            if (x < Consts.BesselJY.ApproxThreshold)
            {
                return(BesselYNearZero(nu, x));
            }
            else
            {
                return(BesselYLimit(nu, x).Convert <N>());
            }
        }
Beispiel #30
0
        public void EllipticPiNm16Test()
        {
            double[] expecteds =
            {
                0.38097406892397619970,
                0.38098314754086177820,
                0.38101039532045358360,
                0.38105584810542028882,
                0.38111956582031698510,
                0.38120163275372443937,
                0.38130215795723625446,
                0.38142127576537016045,
                0.38155914644176689072,
                0.38171595695842382836,
                0.38189192191621758443,
                0.38208728461663012041,
                0.38230231829644162900,
                0.38253732753923039144,
                0.38279264987987244046,
                0.38306865762091791181,
                0.38336575988280300376,
                0.38368440491341630798,
                0.38402508268667225715,
                0.38438832782456945401,
                0.38477472288287031056,
                0.38518490204720559458,
                0.38561955529429864669,
                0.38607943308238611057,
                0.38656535164611732401,
                0.38707819898465896277,
                0.38761894164793849050,
                0.38818863244559176712,
                0.38878841922707987807,
                0.38941955491068760549,
                0.39008340897510269613,
                0.39078148067180717558,
                0.39151541427194962716,
                0.39228701673081825824,
                0.39309827824062298463,
                0.39395139625354005693,
                0.39484880369932717617,
                0.39579320230543788792,
                0.39678760216643525605,
                0.39783536902308613957,
                0.39894028112720089648,
                0.40010659812510402977,
                0.40133914514694661335,
                0.40264341632346655677,
                0.40402570338908765656,
                0.40549325705620916156,
                0.40705449174638346894,
                0.40871924848961337235,
                0.41049913707580003354,
                0.41240798805166135253,
                0.41446245991277721587,
                0.41668287034659028686,
                0.41909435895045648028,
                0.42172855429869097232,
                0.42462603368819289781,
                0.42784007695174618246,
                0.43144263037859565014,
                0.43553425691628467050,
                0.44026177805293553049,
                0.44585208702517352752,
                0.45268404643879583524,
                0.46146549411780511216,
                0.47377998736883166354,
                0.49466160925454855009
            };

            const double n = -16;

            for (int i = 0; i < 64; i++)
            {
                decimal k = i / 64m;

                double expected = expecteds[i];

                MultiPrecision <Pow2.N4> y4 = MultiPrecision <Pow2.N4> .EllipticPi(n, k);

                MultiPrecision <Pow2.N8> y8 = MultiPrecision <Pow2.N8> .EllipticPi(n, k);

                MultiPrecision <Pow2.N16> y16 = MultiPrecision <Pow2.N16> .EllipticPi(n, k);

                MultiPrecision <Pow2.N32> y32 = MultiPrecision <Pow2.N32> .EllipticPi(n, k);

                Console.WriteLine(k);
                Console.WriteLine(y4);
                Console.WriteLine(y4.ToHexcode());
                Console.WriteLine(y8.ToHexcode());
                Console.WriteLine(y16.ToHexcode());
                Console.WriteLine(y32.ToHexcode());

                Assert.AreEqual(expected, (double)y4, expected * 1e-15);
                Assert.IsTrue(MultiPrecision <Pow2.N4> .NearlyEqualBits(y4, y8.Convert <Pow2.N4>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N8> .NearlyEqualBits(y8, y16.Convert <Pow2.N8>(), 1));
                Assert.IsTrue(MultiPrecision <Pow2.N16> .NearlyEqualBits(y16, y32.Convert <Pow2.N16>(), 1));
            }
        }