예제 #1
0
        public static MultiPrecision <N> BesselJ(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)
            {
                return(NaN);
            }

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

                long n = (long)nu;
                return(((n & 1L) == 0) ? BesselJ(nu, Abs(x)) : -BesselJ(nu, Abs(x)));
            }

            if (!x.IsFinite)
            {
                return(0);
            }
            if (x.Exponent >= Bits)
            {
                return(NaN);
            }

            if (nu.Sign == Sign.Minus && nu == Truncate(nu))
            {
                long n = (long)nu;
                return(((n & 1L) == 0) ? BesselJ(Abs(nu), x) : -BesselJ(Abs(nu), x));
            }

            if (nu - Point5 == Floor(nu))
            {
                long n = (long)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)
                    {
                        return(-(envelope * (MultiPrecision <Plus1 <N> > .Cos(x_ex) / x_ex + MultiPrecision <Plus1 <N> > .Sin(x_ex))).Convert <N>());
                    }
                    if (n == -1)
                    {
                        return((envelope * MultiPrecision <Plus1 <N> > .Cos(x_ex)).Convert <N>());
                    }
                    if (n == 0)
                    {
                        MultiPrecision <N> y = (envelope * MultiPrecision <Plus1 <N> > .Sin(x_ex)).Convert <N>();

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

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

            if (x.Exponent <= -0x1000000)
            {
                return(nu.IsZero ? 1 : ((nu.Sign == Sign.Plus || nu == Truncate(nu)) ? 0 : NaN));
            }

            if (x < Consts.BesselJY.ApproxThreshold)
            {
                return(MultiPrecision <Plus2 <N> > .BesselJNearZero(nu.Convert <Plus2 <N> >(), x.Convert <Plus2 <N> >()).Convert <N>());
            }
            else
            {
                return(BesselJLimit(nu, x));
            }
        }