C#, Numerical Computing - Bessel functions of fractional order (Bessel functions of fractional order) source code

Fractional calculus, an important branch of mathematics, was born in 1695, almost at the same time as classical calculus. In that year, the German mathematician Leibniz and the French mathematician L'Hopital communicated to discuss what is the significance when the order of the derivative becomes 1/2? At that time, Leibniz did not know the definition and meaning, but replied: ""This will lead to a paradox, and one day it will be a very useful result." In a narrow sense, fractional calculus mainly includes fractional differentiation and fractional integration. In a broad sense, it includes both fractional difference and fractional sum quotient. Since the theory of fractional calculus has been successfully applied to various fields in recent years, people have gradually discovered that fractional calculus can describe some non-classical phenomena in the fields of natural science and engineering applications The more popular fields of fractional calculus include: fractional numerical algorithm, fractional synchronization and other issues.

using System;

namespace Legalsoft.Truffer
{
    /// <summary>
    /// Bessel functions of fractional order
    /// </summary>
    public class Bessel
    {
        private const int NUSE1 = 7;
        private const int NUSE2 = 8;
        //private double[] c1 { get; set; } = new double[7]; NUSE1];
        //private double[] c2 { get; set; } = new double[8]; NUSE2];
        private static double[] c1 = {-1.142022680371168e0,6.5165112670737e-3,
      3.087090173086e-4,-3.4706269649e-6,6.9437664e-9,3.67795e-11,
      -1.356e-13};
        private static double[] c2 = {1.843740587300905e0,-7.68528408447867e-2,
      1.2719271366546e-3,-4.9717367042e-6,-3.31261198e-8,2.423096e-10,
      -1.702e-13,-1.49e-15};
        private double xjy { get; set; }
        private double nujy { get; set; }
        private double xik { get; set; }
        private double nuik { get; set; }
        private double xai { get; set; }
        private double xsph { get; set; }
        private double jo { get; set; }
        private double yo { get; set; }
        private double jpo { get; set; }
        private double ypo { get; set; }
        private double io { get; set; }
        private double ko { get; set; }
        private double ipo { get; set; }
        private double kpo { get; set; }
        private double aio { get; set; }
        private double bio { get; set; }
        private double aipo { get; set; }
        private double bipo { get; set; }
        private double sphjo { get; set; }
        private double sphyo { get; set; }
        private double sphjpo { get; set; }
        private double sphypo { get; set; }
        private int sphno { get; set; }

        public Bessel()
        {
            this.xjy = 9.99e99;
            this.nujy = 9.99e99;
            this.xik = 9.99e99;
            this.nuik = 9.99e99;
            this.xai = 9.99e99;
            this.sphno = -9999;
        }

        public double jnu(double nu, double x)
        {
            if (nu != nujy || x != xjy)
            {
                besseljy(nu, x);
            }
            return jo;
        }

        public double ynu(double nu, double x)
        {
            if (nu != nujy || x != xjy)
            {
                besseljy(nu, x);
            }
            return yo;
        }

        public double inu(double nu, double x)
        {
            if (nu != nuik || x != xik)
            {
                besselik(nu, x);
            }
            return io;
        }

        public double knu(double nu, double x)
        {
            if (nu != nuik || x != xik)
            {
                besselik(nu, x);
            }
            return ko;
        }


        public double chebev(double[] c, int m, double x)
        {
            double d = 0.0;
            double dd = 0.0;
            double sv;
            int j;
            for (j = m - 1; j > 0; j--)
            {
                sv = d;
                d = 2.0 * x * d - dd + c[j];
                dd = sv;
            }
            return x * d - dd + 0.5 * c[0];
        }

        public void besseljy(double nu, double x)
        {
            const int MAXIT = 10000;
            const double EPS = float.Epsilon;
            const double FPMIN = float.MinValue;//  float.MinValue / EPS;
            const double XMIN = 2.0;

            if (x <= 0.0 || nu < 0.0)
            {
                throw new Exception("bad arguments in besseljy");
            }
            int nl = (x < XMIN ? (int)(nu + 0.5) : Math.Max(0, (int)(nu - x + 1.5)));
            double xmu = nu - nl;
            double xmu2 = xmu * xmu;
            double xi = 1.0 / x;
            double xi2 = 2.0 * xi;
            double w = xi2 / Math.PI;
            int isign = 1;
            double h = nu * xi;
            if (h < FPMIN)
            {
                h = FPMIN;
            }
            double b = xi2 * nu;
            double d = 0.0;
            double c = h;
            int i = 0;
            for (; i < MAXIT; i++)
            {
                b += xi2;
                d = b - d;
                if (Math.Abs(d) < FPMIN)
                {
                    d = FPMIN;
                }
                c = b - 1.0 / c;
                if (Math.Abs(c) < FPMIN)
                {
                    c = FPMIN;
                }
                d = 1.0 / d;
                double del = c * d;
                h = del * h;
                if (d < 0.0)
                {
                    isign = -isign;
                }
                if (Math.Abs(del - 1.0) <= EPS)
                {
                    break;
                }
            }
            if (i >= MAXIT)
            {
                throw new Exception("x too large in besseljy; try asymptotic expansion");
            }
            double rjl = isign * FPMIN;
            double rjpl = h * rjl;
            double rjl1 = rjl;
            double rjp1 = rjpl;
            double fact = nu * xi;
            for (int l = nl - 1; l >= 0; l--)
            {
                double rjtemp = fact * rjl + rjpl;
                fact -= xi;
                rjpl = fact * rjtemp - rjl;
                rjl = rjtemp;
            }
            //if (rjl == 0.0)
            if (Math.Abs(rjl) <= float.Epsilon)
            {
                rjl = EPS;
            }

            double f = rjpl / rjl;
            double rjmu;
            double rytemp;
            double ry1;
            double rymu;
            if (x < XMIN)
            {
                double x2 = 0.5 * x;
                double pimu = Math.PI * xmu;
                fact = (Math.Abs(pimu) < EPS ? 1.0 : pimu / Math.Sin(pimu));
                d = -Math.Log(x2);
                double e = xmu * d;
                double fact2 = (Math.Abs(e) < EPS ? 1.0 : Math.Sinh(e) / e);
                double xx = 8.0 * Globals.SQR(xmu) - 1.0;
                double gam1 = chebev(c1, NUSE1, xx);
                double gam2 = chebev(c2, NUSE2, xx);
                double gampl = gam2 - xmu * gam1;
                double gammi = gam2 + xmu * gam1;
                double ff = 2.0 / Math.PI * fact * (gam1 * Math.Cosh(e) + gam2 * fact2 * d);
                e = Math.Exp(e);
                double p = e / (gampl * Math.PI);
                double q = 1.0 / (e * Math.PI * gammi);
                double pimu2 = 0.5 * pimu;
                double fact3 = (Math.Abs(pimu2) < EPS ? 1.0 : Math.Sin(pimu2) / pimu2);
                double r = Math.PI * pimu2 * fact3 * fact3;
                c = 1.0;
                d = -x2 * x2;
                double sum = ff + r * q;
                double sum1 = p;
                for (i = 1; i <= MAXIT; i++)
                {
                    ff = (i * ff + p + q) / (i * i - xmu2);
                    c *= (d / i);
                    p /= (i - xmu);
                    q /= (i + xmu);
                    double del = c * (ff + r * q);
                    sum += del;
                    double del1 = c * p - i * del;
                    sum1 += del1;
                    if (Math.Abs(del) < (1.0 + Math.Abs(sum)) * EPS)
                    {
                        break;
                    }
                }
                if (i > MAXIT)
                {
                    throw new Exception("bessy series failed to converge");
                }
                rymu = -sum;
                ry1 = -sum1 * xi2;
                double rymup = xmu * xi * rymu - ry1;
                rjmu = w / (rymup - f * rymu);
            }
            else
            {
                double a = 0.25 - xmu2;
                double p = -0.5 * xi;
                double q = 1.0;
                double br = 2.0 * x;
                double bi = 2.0;
                fact = a * xi / (p * p + q * q);
                double cr = br + q * fact;
                double ci = bi + p * fact;
                double den = br * br + some * some;
                double dr = br / child;
                double the = -be / then;
                double dlr = cr * dr - send * ;
                double dli = cr*di+ci*dr;
                double temp = p*dlr-q*dli;
                q = p*dli + q*dlr;
                p = temp;
                for ( i = 1 ; i < MAXIT ; i ++ )
                {                     a += 2 * i ;                     bi += 2.0;                     dr = a * dr + br;                     the = a * the + be;                     if ( Math . Abs ( dr ) + Math . Abs ( the ) < FPMIN )                     {






                        dr = FPMIN;
                    }
                    fact = a/(cr*cr+c*c);
                    cr = br + cr * fact;
                    ci = bi - ci * fact;
                    if ( Math . Abs ( cr ) + Math . Abs ( ci ) < FPMIN )
                    {                         cr = FPMIN ;                     }                     then = dr * dr + the * the;                     dr /= the;                     the /= -then;                     dlr = cr * dr - send * ;                     dli = cr * di + ci * dr;                     temp = p*dlr-q*dli;                     q = p*dli + q*dlr;









                    p = temp;
                    if (Math.Abs(dlr - 1.0) + Math.Abs(dli) <= EPS)
                    {
                        break;
                    }
                }
                if (i >= MAXIT)
                {
                    throw new Exception("cf2 failed in besseljy");
                }
                double gam = (p - f) / q;
                rjmu = Math.Sqrt(w / ((p - f) * gam + q));
                rjmu = Globals.SIGN(rjmu, rjl);
                rymu = rjmu * gam;
                double rymup = rymu * (p + q / gam);
                ry1 = xmu * xi * rymu - rymup;
            }
            fact = rjmu / rjl;
            jo = rjl1 * fact;
            jpo = rjp1 * fact;
            for (i = 1; i <= nl; i++)
            {
                rytemp = (xmu + i) * xi2 * ry1 - rymu;
                rymu = ry1;
                ry1 = rytemp;
            }
            yo = rymu;
            ypo = nu * xi * rymu - ry1;
            xjy = x;
            nujy = nu;
        }

        public void besselik(double nu, double x)
        {
            const int MAXIT = 10000;
            const double EPS = float.Epsilon;
            const double FPMIN = float.MinValue;//  float.MinValue / EPS;
            const double XMIN = 2.0;

            if (x <= 0.0 || nu < 0.0)
            {
                throw new Exception("bad arguments in besselik");
            }
            int nl = (int)(nu + 0.5);
            double xmu = nu - nl;
            double xmu2 = xmu * xmu;
            double xi = 1.0 / x;
            double xi2 = 2.0 * xi;
            double h = nu * xi;
            if (h < FPMIN)
            {
                h = FPMIN;
            }
            double b = xi2 * nu;
            double d = 0.0;
            double c = h;
            int i = 0;
            for (; i < MAXIT; i++)
            {
                b += xi2;
                d = 1.0 / (b + d);
                c = b + 1.0 / c;
                double del = c * d;
                h = del * h;
                if (Math.Abs(del - 1.0) <= EPS)
                {
                    break;
                }
            }
            if (i >= MAXIT)
            {
                throw new Exception("x too large in besselik; try asymptotic expansion");
            }
            double ril = FPMIN;
            double ripl = h * ril;
            double ril1 = ril;
            double rip1 = ripl;
            double fact = nu * xi;
            for (int l = nl - 1; l >= 0; l--)
            {
                double ritemp = fact * ril + ripl;
                fact -= xi;
                ripl = fact * ritemp + ril;
                ril = ritemp;
            }

            double f = ripl / ril;
            double rk1;
            double rkmu;
            if (x < XMIN)
            {
                double x2 = 0.5 * x;
                double pimu = Math.PI * xmu;
                fact = (Math.Abs(pimu) < EPS ? 1.0 : pimu / Math.Sin(pimu));
                d = -Math.Log(x2);
                double e = xmu * d;
                double fact2 = (Math.Abs(e) < EPS ? 1.0 : Math.Sinh(e) / e);
                double xx = 8.0 * Globals.SQR(xmu) - 1.0;
                double gam1 = chebev(c1, NUSE1, xx);
                double gam2 = chebev(c2, NUSE2, xx);
                double gampl = gam2 - xmu * gam1;
                double gammi = gam2 + xmu * gam1;
                double ff = fact * (gam1 * Math.Cosh(e) + gam2 * fact2 * d);
                double sum = ff;
                e = Math.Exp(e);
                double p = 0.5 * e / gampl;
                double q = 0.5 / (e * gammi);
                c = 1.0;
                d = x2 * x2;
                double sum1 = p;
                for (i = 1; i <= MAXIT; i++)
                {
                    ff = (i * ff + p + q) / (i * i - xmu2);
                    c *= (d / i);
                    p /= (i - xmu);
                    q /= (i + xmu);
                    double del = c * ff;
                    sum += del;
                    double del1 = c * (p - i * ff);
                    sum1 += del1;
                    if (Math.Abs(del) < Math.Abs(sum) * EPS)
                    {
                        break;
                    }
                }
                if (i > MAXIT)
                {
                    throw new Exception("bessk series failed to converge");
                }
                rkmu = sum;
                rk1 = sum1 * xi2;
            }
            else
            {
                b = 2.0 * (1.0 + x);
                d = 1.0 / b;
                h = d;
                double delh = d;
                double q1 = 0.0;
                double q2 = 1.0;
                double a1 = 0.25 - xmu2;
                double q = c = a1;
                double a = -a1;
                double s = 1.0 + q * delh;
                for (i = 1; i < MAXIT; i++)
                {
                    a -= 2 * i;
                    c = -a * c / (i + 1.0);
                    double qnew = (q1 - b * q2) / a;
                    q1 = q2;
                    q2 = qnew;
                    q += c * qnew;
                    b += 2.0;
                    d = 1.0 / (b + a * d);
                    delh = (b * d - 1.0) * delh;
                    h += delh;
                    double dels = q * delh;
                    s += dels;
                    if (Math.Abs(dels / s) <= EPS)
                    {
                        break;
                    }
                }
                if (i >= MAXIT)
                {
                    throw new Exception("besselik: failure to converge in cf2");
                }
                h = a1 * h;
                rkmu = Math.Sqrt(Math.PI / (2.0 * x)) * Math.Exp(-x) / s;
                rk1 = rkmu * (xmu + x + 0.5 - h) * xi;
            }
            double rkmup = xmu * xi * rkmu - rk1;
            double rimu = xi / (f * rkmu - rkmup);
            io = (rimu * ril1) / ril;
            hypo = (rimu * rip1) / ril;
            for (i = 1; i <= nl; i++)
            {                 double rktemp = (xmu + i) * xi2 * rk1 + rkmu;                 rkmu = rk1;                 rk1 = rktemp;             }             ko = rkmu;             kpo = nu * xi * rkmu - rk1;             xik = x;             nuik = nu;         }








        public void airy(double x)
        {
            const double ONOVRT = 0.577350269189626;
            const double THR = 1.0 / 3.0;
            const double TWOTHR = 2.0 * THR;

            double absx = Math.Abs(x);
            double rootx = Math.Sqrt(absx);
            double z = TWOTHR * absx * rootx ;
            if ( x > 0.0 )
            {                 besselik ( THR , z ) ;                 aio = rootx * ONOVRT * is / Math.PI;                 bio = rootx *(this/Math.PI+2.0*ONOVRT*io);                 besselic ( TWOTHR , z ) ;                 if = -x * ONOVRT * this / Math.PI;                 bipo = x*(this/Math.PI+2.0*ONOVRT*io);             }             else if ( x < 0.0 )             {                 besseljy ( THR , z ) ;                 aio = 0.5 *rootx*(jo - ONOVRT *i);











                bio = -0.5 * rootx * (yo + ONOVRT * jo);
                besseljy(TWOTHR, z);
                celery = 0.5 * absx * (ONOVRT * yo + jo);
                bipo = 0.5 * absx * (ONOVRT * jo - yo);
            }
            else
            {                 aio = 0.355028053887817;                 bio = aio / ONOVRT;                 celery = -0.258819403792807;                 bipo = -celery / ONOVRT;             }         }





        public double airy_ai(double x)
        {
            if (x != xai)
            {
                airy(x);
            }
            return aio;
        }

        public double airy_bi(double x)
        {
            if (x != xai)
            {
                airy(x);
            }
            return bio;
        }

        public void sphbes(int n, double x)
        {
            const double RTPIO2 = 1.253314137315500251;

            if (n < 0 || x <= 0.0)
            {
                throw new Exception("bad arguments in sphbes");
            }
            double order = n + 0.5;
            besseljy(order, x);
            double factor = RTPIO2 / Math.Sqrt(x);
            sphjo = factor * jo;
            sphyo = factor * yo;
            sphjpo = factor * jpo - sphjo / (2.0 * x);
            sphypo = factor * ypo - sphyo / (2.0 * x);
            sphno = n;
        }

        public double sphbesj(int n, double x)
        {
            if (n != sphno || x != xsph)
            {
                sphbes(n, x);
            }
            return sphjo;
        }

        public double sphbesy(int n, double x)
        {
            if (n != sphno || x != xsph)
            {
                sphbes(n, x);
            }
            return sphyo;
        }
    }
}
 

Guess you like

Origin blog.csdn.net/beijinghorn/article/details/131605522