using System;
using System.Collections;
namespace Science.Mathematics.SpecialFunction
{
///
/// Hypergeometric
///
public class Hypergeometric
{
public Hypergeometric()
{
}
private static Complex aa,bb,cc,z0,dz;
public static Complex Hypergeometric2F1(Complex a, Complex b, Complex c, Complex z)
{
double EPS = 1.0e-6;
Complex ans;
Complex[] y = new Complex[2];
double[] yy= new Double[4];
if (z.Real*z.Real+z.Imaginary*z.Imaginary <= 0.25)
{
hypser(a,b,c,z);
ans = series;
y[1] = deriv;
return ans;
}
else if (z.Real < 0.0) z0=new Complex(-0.5,0.0);
else if (z.Real <= 1.0) z0=new Complex(0.5,0.0);
else z0=new Complex(0.0,z.Imaginary >= 0.0 ? 0.5 : -0.5);
aa=a;
bb=b;
cc=c;
dz=(z - z0);
hypser(aa,bb,cc,z0);
y[0]=series;
y[1]=deriv;
yy[0]=y[0].Real;
yy[1]=y[0].Imaginary;
yy[2]=y[1].Real;
yy[3]=y[1].Imaginary;
Function der = new Function(hypdrv);
odeint(yy,4,0.0,1.0,EPS,0.1,0.0001,der);
y[0]=new Complex(yy[0],yy[1]);
return y[0];
}
private static double[] hypdrv(double s, double[] yy)
{
Complex ONE = new Complex(1.0,0.0);
double[] dyyds = new Double[4];
Complex z;
Complex[] y = new Complex[2];
Complex[] dyds = new Complex[2];
y[0]=new Complex(yy[0],yy[1]);
y[1]=new Complex(yy[2],yy[3]);
z=(z0 + (s * dz));
dyds[0]=(y[1] * dz);
dyds[1]=((((aa*bb)*y[0]) -
((cc - (((aa + bb) + ONE) * z)) * y[1])) *
(dz / (z * (ONE - z))));
dyyds[0]=dyds[0].Real;
dyyds[1]=dyds[0].Imaginary;
dyyds[2]=dyds[1].Real;
dyyds[3]=dyds[1].Imaginary;
return dyyds;
}
private static Complex series, deriv;
private static void hypser(Complex a, Complex b,
Complex c, Complex z)
{
Complex ONE = new Complex(1.0,0.0);
int n;
Complex aa,bb,cc,fac,temp;
deriv = new Complex(0.0,0.0);
fac=new Complex(1.0,0.0);
temp=fac;
aa=a;
bb=b;
cc=c;
for (n=1;n<=1000;n++)
{
fac=(fac * (aa * (bb / cc)));
deriv.Real+=fac.Real;
deriv.Imaginary+=fac.Imaginary;
fac=(fac * ((1.0/n)* z));
series=(temp + fac);
if (series.Real == temp.Real && series.Imaginary == temp.Imaginary) return;
temp= series;
aa=(aa + ONE);
bb=(bb + ONE);
cc=(cc + ONE);
}
try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("convergence failure in hypser");
}
}
private static ArrayList xp = new ArrayList(1);
private static ArrayList[] yp;
private static double dxsav=0.0;
private static int nok, nbad;
private static void odeint(double[] ystart, int nvar, double x1, double x2, double eps, double h1,
double hmin, Function derivs)
{
int MAXSTP = 10000;
double TINY = 1.0e-30;
yp = new ArrayList[nvar];
for(int j = 0; j < nvar; j++) yp[j] = new ArrayList(1);
int nstp,i;
double xsav,x,h;
double[] yscal,y,dydx;
yscal=new Double[nvar];
y=new Double[nvar];
dydx=new Double[nvar];
x=x1;
h=Math.Sign(x2-x1)*h1;
nok = nbad = 0;
for (i=0;i Math.Abs(dxsav))
{
xp.Add(x);
for (i=0;i 0.0) h=x2-x;
rkqs(y,dydx,nvar,x,h,eps,yscal,derivs);
x = xout;
if (hdid == h) ++nok; else ++nbad;
if ((x-x2)*(x2-x1) >= 0.0)
{
for (i=0;i 1.0)
{
h=SAFETY*h*Math.Pow(errmax,PSHRNK);
if (h < 0.1*h) h *= 0.1;
xnew=x+h;
if (xnew == x) try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("stepsize underflow in rkqs");
}
continue;
}
else
{
if (errmax > ERRCON) hnext=SAFETY*h*Math.Pow(errmax,PGROW);
else hnext=5.0*h;
xout = x + (hdid=h);
for (i=0;i