using System;
namespace Science.Mathematics.SpecialFunction
{
///
/// Bessel
///
public class Bessel
{
public Bessel()
{
}
public static double J0(double x)
{
double ax,z;
double xx,y,ans,ans1,ans2;
if ((ax=Math.Abs(x)) < 8.0)
{
y=x*x;
ans1=57568490574.0+y*(-13362590354.0+y*(651619640.7
+y*(-11214424.18+y*(77392.33017+y*(-184.9052456)))));
ans2=57568490411.0+y*(1029532985.0+y*(9494680.718
+y*(59272.64853+y*(267.8532712+y*1.0))));
ans=ans1/ans2;
}
else
{
z=8.0/ax;
y=z*z;
xx=ax-0.785398164;
ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4
+y*(-0.2073370639e-5+y*0.2093887211e-6)));
ans2 = -0.1562499995e-1+y*(0.1430488765e-3
+y*(-0.6911147651e-5+y*(0.7621095161e-6
-y*0.934935152e-7)));
ans=Math.Sqrt(0.636619772/ax)*(Math.Cos(xx)*ans1-z*Math.Sin(xx)*ans2);
}
return ans;
}
public static double Y0(double x)
{
double z;
double xx,y,ans,ans1,ans2;
if (x < 8.0)
{
y=x*x;
ans1 = -2957821389.0+y*(7062834065.0+y*(-512359803.6
+y*(10879881.29+y*(-86327.92757+y*228.4622733))));
ans2=40076544269.0+y*(745249964.8+y*(7189466.438
+y*(47447.26470+y*(226.1030244+y*1.0))));
ans=(ans1/ans2)+0.636619772*J0(x)*Math.Log(x);
}
else
{
z=8.0/x;
y=z*z;
xx=x-0.785398164;
ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4
+y*(-0.2073370639e-5+y*0.2093887211e-6)));
ans2 = -0.1562499995e-1+y*(0.1430488765e-3
+y*(-0.6911147651e-5+y*(0.7621095161e-6
+y*(-0.934945152e-7))));
ans=Math.Sqrt(0.636619772/x)*(Math.Sin(xx)*ans1+z*Math.Cos(xx)*ans2);
}
return ans;
}
public static double J1(double x)
{
double ax,z;
double xx,y,ans,ans1,ans2;
if ((ax=Math.Abs(x)) < 8.0)
{
y=x*x;
ans1=x*(72362614232.0+y*(-7895059235.0+y*(242396853.1
+y*(-2972611.439+y*(15704.48260+y*(-30.16036606))))));
ans2=144725228442.0+y*(2300535178.0+y*(18583304.74
+y*(99447.43394+y*(376.9991397+y*1.0))));
ans=ans1/ans2;
}
else
{
z=8.0/ax;
y=z*z;
xx=ax-2.356194491;
ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4
+y*(0.2457520174e-5+y*(-0.240337019e-6))));
ans2=0.04687499995+y*(-0.2002690873e-3
+y*(0.8449199096e-5+y*(-0.88228987e-6
+y*0.105787412e-6)));
ans=Math.Sqrt(0.636619772/ax)*(Math.Cos(xx)*ans1-z*Math.Sin(xx)*ans2);
if (x < 0.0) ans = -ans;
}
return ans;
}
public static double Y1(double x)
{
double z;
double xx,y,ans,ans1,ans2;
if (x < 8.0)
{
y=x*x;
ans1=x*(-0.4900604943e13+y*(0.1275274390e13
+y*(-0.5153438139e11+y*(0.7349264551e9
+y*(-0.4237922726e7+y*0.8511937935e4)))));
ans2=0.2499580570e14+y*(0.4244419664e12
+y*(0.3733650367e10+y*(0.2245904002e8
+y*(0.1020426050e6+y*(0.3549632885e3+y)))));
ans=(ans1/ans2)+0.636619772*(J1(x)*Math.Log(x)-1.0/x);
}
else
{
z=8.0/x;
y=z*z;
xx=x-2.356194491;
ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4
+y*(0.2457520174e-5+y*(-0.240337019e-6))));
ans2=0.04687499995+y*(-0.2002690873e-3
+y*(0.8449199096e-5+y*(-0.88228987e-6
+y*0.105787412e-6)));
ans=Math.Sqrt(0.636619772/x)*(Math.Sin(xx)*ans1+z*Math.Cos(xx)*ans2);
}
return ans;
}
public static double J(int n, double x)
{
double ACC = 40.0;
double BIGNO = 1.0e10;
double BIGNI = 1.0e-10;
int j,m;
bool jsum;
double ax,bj,bjm,bjp,sum,tox,ans;
if (n < 2) try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("Index n less than 2 in bessj");
}
ax=Math.Abs(x);
if (ax == 0.0)
return 0.0;
else if (ax > (double) n)
{
tox=2.0/ax;
bjm=J0(ax);
bj=J1(ax);
for (j=1;j0;j--)
{
bjm=j*tox*bj-bjp;
bjp=bj;
bj=bjm;
if (Math.Abs(bj) > BIGNO)
{
bj *= BIGNI;
bjp *= BIGNI;
ans *= BIGNI;
sum *= BIGNI;
}
if (jsum) sum += bj;
jsum=!jsum;
if (j == n) ans=bjp;
}
sum=2.0*sum-bj;
ans /= sum;
}
return x < 0.0 && (n%2)== 1 ? -ans : ans;
}
public static double Y(int n, double x)
{
int j;
double by,bym,byp,tox;
if (n < 2) try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("Index n less than 2 in bessy");
}
tox=2.0/x;
by=Y1(x);
bym=Y0(x);
for (j=1;j0;j--)
{
bim=bip+j*tox*bi;
bip=bi;
bi=bim;
if (Math.Abs(bi) > BIGNO)
{
ans *= BIGNI;
bi *= BIGNI;
bip *= BIGNI;
}
if (j == n) ans=bip;
}
ans *= I0(x)/bi;
return x < 0.0 && (n%2) == 1 ? -ans : ans;
}
}
public static double K(int n, double x)
{
int j;
double bk,bkm,bkp,tox;
if (n < 2) try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("Index n less than 2 in bessk");
}
tox=2.0/x;
bkm=K0(x);
bk=K1(x);
for (j=1;j MAXIT) try { throw new Science.Error(); }
catch (Science.Error e2)
{
e2.Write("x too large in bessjy; try asymptotic expansion");
}
rjl=isign*FPMIN;
rjpl=h*rjl;
rjl1=rjl;
rjp1=rjpl;
fact=xnu*xi;
for (l=nl;l>=1;l--)
{
rjtemp=fact*rjl+rjpl;
fact -= xi;
rjpl=fact*rjtemp-rjl;
rjl=rjtemp;
}
if (rjl == 0.0) rjl=EPS;
f=rjpl/rjl;
if (x < XMIN)
{
x2=0.5*x;
pimu=PI*xmu;
fact = (Math.Abs(pimu) < EPS ? 1.0 : pimu/Math.Sin(pimu));
d = -Math.Log(x2);
e=xmu*d;
fact2 = (Math.Abs(e) < EPS ? 1.0 : Math.Sinh(e)/e);
int NUSE1 = 7;
int NUSE2 = 8;
double gam1, gam2, gampl, gammi;
double xx;
double[] c1 = { -1.142022680371172e0,6.516511267076e-3,
3.08709017308e-4,-3.470626964e-6,6.943764e-9,
3.6780e-11,-1.36e-13};
double[] c2 = { 1.843740587300906e0,-0.076852840844786e0,
1.271927136655e-3,-4.971736704e-6,-3.3126120e-8,
2.42310e-10,-1.70e-13,-1.0e-15};
xx=8.0*x*x-1.0;
gam1=Chebev(-1.0,1.0,c1,NUSE1,xx);
gam2=Chebev(-1.0,1.0,c2,NUSE2,xx);
gampl= gam2-x*gam1;
gammi= gam2+x*gam1;
ff=2.0/PI*fact*(gam1*Math.Cosh(e)+gam2*fact2*d);
e=Math.Exp(e);
p=e/(gampl*PI);
q=1.0/(e*PI*gammi);
pimu2=0.5*pimu;
fact3 = (Math.Abs(pimu2) < EPS ? 1.0 : Math.Sin(pimu2)/pimu2);
r=PI*pimu2*fact3*fact3;
c=1.0;
d = -x2*x2;
sum=ff+r*q;
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);
del=c*(ff+r*q);
sum += del;
del1=c*p-i*del;
sum1 += del1;
if (Math.Abs(del) < (1.0+Math.Abs(sum))*EPS) break;
}
if (i > MAXIT) try { throw new Science.Error(); }
catch (Science.Error e3)
{
e3.Write("bessy series failed to converge");
}
rymu = -sum;
ry1 = -sum1*xi2;
rymup=xmu*xi*rymu-ry1;
rjmu=w/(rymup-f*rymu);
}
else
{
a=0.25-xmu2;
p = -0.5*xi;
q=1.0;
br=2.0*x;
bi=2.0;
fact=a*xi/(p*p+q*q);
cr=br+q*fact;
ci=bi+p*fact;
den=br*br+bi*bi;
dr=br/den;
di = -bi/den;
dlr=cr*dr-ci*di;
dli=cr*di+ci*dr;
temp=p*dlr-q*dli;
q=p*dli+q*dlr;
p=temp;
for (i=2;i<=MAXIT;i++)
{
a += 2*(i-1);
bi += 2.0;
dr=a*dr+br;
di=a*di+bi;
if (Math.Abs(dr)+Math.Abs(di) < FPMIN) dr=FPMIN;
fact=a/(cr*cr+ci*ci);
cr=br+cr*fact;
ci=bi-ci*fact;
if (Math.Abs(cr)+Math.Abs(ci) < FPMIN) cr=FPMIN;
den=dr*dr+di*di;
dr /= den;
di /= -den;
dlr=cr*dr-ci*di;
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) try { throw new Science.Error(); }
catch (Science.Error e4)
{
e4.Write("cf2 failed in bessjy");
}
gam=(p-f)/q;
rjmu=Math.Sqrt(w/((p-f)*gam+q));
rjmu=rjmu*Math.Sign(rjl);
rymu=rjmu*gam;
rymup=rymu*(p+q/gam);
ry1=xmu*xi*rymu-rymup;
}
fact=rjmu/rjl;
rj=rjl1*fact;
rjp=rjp1*fact;
for (i=1;i<=nl;i++)
{
rytemp=(xmu+i)*xi2*ry1-rymu;
rymu=ry1;
ry1=rytemp;
}
ry=rymu;
ryp=xnu*xi*rymu-ry1;
if(returnwhat == 1) return rj;
else if(returnwhat == 2) return ry;
else if(returnwhat == 3) return rjp;
else return ryp;
}
private static double Chebev(double a, double b, double[] c, int m, double x)
{
double d=0.0,dd=0.0,sv,y,y2;
int j;
if ((x - a) * (x - b) > 0.0) try { throw new Science.Error(); }
catch (Science.Error e5)
{
e5.Write("x not in range in routine chebev");
}
y2=2.0*(y=(2.0*x-a-b)/(b-a));
for (j=m-1;j>=1;j--)
{
sv=d;
d=y2*d-dd+c[j];
dd=sv;
}
return y*d-dd+0.5*c[0];
}
public static double I(double nu, double x)
{
return bessik(x,nu,1);
}
public static double K(double nu, double x)
{
return bessik(x,nu,2);
}
public static double DerivativeOfI(double nu, double x)
{
return bessik(x,nu,3);
}
public static double DerivativeOfK(double nu, double x)
{
return bessik(x,nu,4);
}
private static double bessik(double x, double xnu, int returnwhat)
{
double EPS = 1.0e-16;
double FPMIN = 1.0e-30;
int MAXIT = 10000;
double XMIN = 2.0;
double PI = 3.141592653589793;
double ri, rk, rip, rkp;
int i,l,nl;
double a,a1,b,c,d,del,del1,delh,dels,e,f,fact,fact2,ff,
h,p,pimu,q,q1,q2,qnew,ril,ril1,rimu,rip1,ripl,
ritemp,rk1,rkmu,rkmup,rktemp,s,sum,sum1,x2,xi,xi2,xmu,xmu2;
if (x <= 0.0 || xnu < 0.0) try { throw new Science.Error(); }
catch (Science.Error e6)
{
e6.Write("bad arguments in bessik");
}
nl=(int)(xnu+0.5);
xmu=xnu-nl;
xmu2=xmu*xmu;
xi=1.0/x;
xi2=2.0*xi;
h=xnu*xi;
if (h < FPMIN) h=FPMIN;
b=xi2*xnu;
d=0.0;
c=h;
for (i=1;i<=MAXIT;i++)
{
b += xi2;
d=1.0/(b+d);
c=b+1.0/c;
del=c*d;
h=del*h;
if (Math.Abs(del-1.0) < EPS) break;
}
if (x <= 0.0 || xnu < 0.0) try { throw new Science.Error(); }
catch (Science.Error e7)
{
e7.Write("x too large in bessik; try asymptotic expansion");
}
ril=FPMIN;
ripl=h*ril;
ril1=ril;
rip1=ripl;
fact=xnu*xi;
for (l=nl;l>=1;l--)
{
ritemp=fact*ril+ripl;
fact -= xi;
ripl=fact*ritemp+ril;
ril=ritemp;
}
f=ripl/ril;
if (x < XMIN)
{
x2=0.5*x;
pimu=PI*xmu;
fact = (Math.Abs(pimu) < EPS ? 1.0 : pimu/Math.Sin(pimu));
d = -Math.Log(x2);
e=xmu*d;
fact2 = (Math.Abs(e) < EPS ? 1.0 : Math.Sinh(e)/e);
int NUSE1 = 7;
int NUSE2 = 8;
double gam1, gam2, gampl, gammi;
double xx;
double[] c1 = { -1.142022680371172e0,6.516511267076e-3,
3.08709017308e-4,-3.470626964e-6,6.943764e-9,
3.6780e-11,-1.36e-13};
double[] c2 = { 1.843740587300906e0,-0.076852840844786e0,
1.271927136655e-3,-4.971736704e-6,-3.3126120e-8,
2.42310e-10,-1.70e-13,-1.0e-15};
xx=8.0*x*x-1.0;
gam1=Chebev(-1.0,1.0,c1,NUSE1,xx);
gam2=Chebev(-1.0,1.0,c2,NUSE2,xx);
gampl= gam2-x*gam1;
gammi= gam2+x*gam1;
ff=fact*(gam1*Math.Cosh(e)+gam2*fact2*d);
sum=ff;
e=Math.Exp(e);
p=0.5*e/gampl;
q=0.5/(e*gammi);
c=1.0;
d=x2*x2;
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);
del=c*ff;
sum += del;
del1=c*(p-i*ff);
sum1 += del1;
if (Math.Abs(del) < Math.Abs(sum)*EPS) break;
}
if (i > MAXIT) try { throw new Science.Error(); }
catch (Science.Error e8)
{
e8.Write("bessk series failed to converge");
}
rkmu=sum;
rk1=sum1*xi2;
}
else
{
b=2.0*(1.0+x);
d=1.0/b;
h=delh=d;
q1=0.0;
q2=1.0;
a1=0.25-xmu2;
q=c=a1;
a = -a1;
s=1.0+q*delh;
for (i=2;i<=MAXIT;i++)
{
a -= 2*(i-1);
c = -a*c/i;
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;
dels=q*delh;
s += dels;
if (Math.Abs(dels/s) < EPS) break;
}
if (i > MAXIT) try { throw new Science.Error(); }
catch (Science.Error e9)
{
e9.Write("bessik: failure to converge in cf2");
}
h=a1*h;
rkmu=Math.Sqrt(PI/(2.0*x))*Math.Exp(-x)/s;
rk1=rkmu*(xmu+x+0.5-h)*xi;
}
rkmup=xmu*xi*rkmu-rk1;
rimu=xi/(f*rkmu-rkmup);
ri=(rimu*ril1)/ril;
rip=(rimu*rip1)/ril;
for (i=1;i<=nl;i++)
{
rktemp=(xmu+i)*xi2*rk1+rkmu;
rkmu=rk1;
rk1=rktemp;
}
rk=rkmu;
rkp=xnu*xi*rkmu-rk1;
if(returnwhat == 1) return ri;
else if(returnwhat == 2) return rk;
else if(returnwhat == 3) return rip;
else return rkp;
}
public static double Ai(double x)
{
return airy(x,1);
}
public static double Bi(double x)
{
return airy(x,2);
}
public static double DerivativeOfAi(double x)
{
return airy(x,3);
}
public static double DerivativeOfBi(double x)
{
return airy(x,4);
}
private static double airy(double x, int what)
{
double THIRD = 1.0/3.0;
double TWOTHR = 2.0/3.0;
double ONOVRT = 0.57735027;
double ai, bi, aip, bip;
double absx,rootx,z;
absx=Math.Abs(x);
rootx=Math.Sqrt(absx);
z=TWOTHR*absx*rootx;
if (x > 0.0)
{
ai=rootx*ONOVRT*bessik(z,THIRD,2)/Math.PI;
bi=rootx*(bessik(z,THIRD,2)/Math.PI+2.0*ONOVRT*bessik(z,THIRD,1));
aip = -x*ONOVRT*bessik(z,TWOTHR,2)/Math.PI;
bip=x*(bessik(z,TWOTHR,2)/Math.PI+2.0*ONOVRT*bessik(z,TWOTHR,1));
}
else if (x < 0.0)
{
ai=0.5*rootx*(bessjy(z,THIRD,1)-ONOVRT*bessjy(z,THIRD,2));
bi = -0.5*rootx*(bessjy(z,THIRD,2)+ONOVRT*bessjy(z,THIRD,1));
aip=0.5*absx*(ONOVRT*bessjy(z,TWOTHR,2)+bessjy(z,TWOTHR,1));
bip=0.5*absx*(ONOVRT*bessjy(z,TWOTHR,1)-bessjy(z,TWOTHR,2));
}
else
{
ai=0.35502805;
bi=ai/ONOVRT;
aip = -0.25881940;
bip = -aip/ONOVRT;
}
if(what == 1) return ai;
else if(what == 2) return bi;
else if(what == 3) return aip;
else return bip;
}
public static double j(int n, double x)
{
return sphbes(n,x,1);
}
public static double y(int n, double x)
{
return sphbes(n,x,2);
}
public static double DerivativeOfj(int n, double x)
{
return sphbes(n,x,3);
}
public static double DerivativeOfy(int n, double x)
{
return sphbes(n,x,4);
}
private static double sphbes(int n, double x, int what)
{
double RTPIO2 = 1.2533141;
double sj, sy, sjp, syp;
double factor,order;
if (n < 0 || x <= 0.0) try { throw new Science.Error(); }
catch (Science.Error e10)
{
e10.Write("bad arguments in sphbes");
}
order=n+0.5;
factor=RTPIO2/Math.Sqrt(x);
sj=factor*bessjy(x,order,1);
sy=factor*bessjy(x,order,2);
sjp=factor*bessjy(x,order,3)-sj/(2.0*x);
syp=factor*bessjy(x,order,4)-sy/(2.0*x);
if(what == 1) return sj;
else if(what == 2) return sy;
else if(what == 3) return sjp;
else return syp;
}
}
}