public class derivative_coef
{ // Reference :"Generation of Finite Difference Formulas on Arbitrary Spaced Grids", 
  // Bength Fornberg, Mathematics of Computation, Volume 51, Number 184, October 1988
  // pages 699-706
double c[][][];
double alpha[];
double h;
int M;

public void setH(double hi)
{h=hi;}
public void coef_out(int N)
{  double a[][]=new double[alpha.length][2];
   for(int i=0;i<alpha.length;i++)
   {a[i][0]=alpha[i];
    a[i][1]=c[M][i][N];
   }
   String s1="Derivative coefficients for order of the highest derivative M = "+M;
   String s[]={""+'\u0394'+"x","C"};
	Text.print(a,s,s1);
}
public void coef_out()
{  double a[][]=new double[alpha.length][M+1];
   String s[]=new String[M+1];
   s[0]=""+'\u0394'+"x";
   for(int j=1;j<=M;j++)
   {s[j]="C"+j;}
   for(int i=0;i<alpha.length;i++)
   {a[i][0]=alpha[i];
    for(int j=1;j<=M;j++)
    a[i][j]=c[M][i][j];
   }
    String s1="Derivative coefficients for order of the highest derivative M = "+M;
	Text.print(a,s,s1);
}
public void setOrder(int Mi)
{M=Mi;}

public  derivative_coef()
{
h=0.01;
double x0=0;
M=20;
double alphai[]={0,1,-1,2,-2,3,-3,4,-4,5,-5,6,-6,7,-7,8,-8,9,-9,10,-10,11,-11,12,-12,13,-13,14,-14,15,
-15,16,-16,17,-17,18,-18,19,-19,20,-20,21,-21,22,-22,23,-23,24,-24,25,-25,26,-26,27,-27,28,-28,29,-29,30,-30};
alpha=alphai;
int N=alpha.length-1;
// M   degree of highest derivative
// N+1 number of coefficients 
double delta[][][]=new double[N+1][N+1][M+1];
double c1,c2,c3;
delta[0][0][0]=1.0;
c1=1.0;
//for(int i=0;i<alpha.length;i++)
//{System.out.println(i+" "+alpha[i]);}
for(int n=1;n<=N;n++)
{  c2=1;
   for(int nu=0;nu<=(n-1);nu++)
   {c3=alpha[n]-alpha[nu];
    c2=c2*c3;
    if(n<=M) delta[n-1][nu][n]=0.0;
    for(int m=0;m<=Math.min(n,M);m++)
    {   //System.out.println("n="+n+"m="+m+"nu="+nu);
        if(m==0)
        { delta[n][nu][m]=((alpha[n]-x0)*delta[n-1][nu][m])/c3;}
        else
        {delta[n][nu][m]=((alpha[n]-x0)*delta[n-1][nu][m]-m*delta[n-1][nu][m-1])/c3;}
    }//next m
   }//next nu
   for(int m=0;m<=Math.min(n,M);m++)
   {   if(m==0)
	   {delta[n][n][m]=c1/c2*(-(alpha[n-1]-x0)*delta[n-1][n-1][m]);}
	   else
	   {delta[n][n][m]=c1/c2*(m*delta[n-1][n-1][m-1]-(alpha[n-1]-x0)*delta[n-1][n-1][m]);}   
   }//next m
   c1=c2;
}//next n
c=delta;
}
double func(double x)
{ double y=x*x-2;
  return y;
}

double dfunc(int N,double x)
{// order of the maximum derivative
 // N order of derivative
  double deriv=0;
  double h1=1/h;
  double h2=1;
  for(int j=0;j<N;j++)
  {h2*=h1;}
  for(int i=0;i<c[0].length;i++)
  {deriv+=c[M][i][N]*func(x+alpha[i]*h);}
  return deriv*h2; 
}

public static void main(String arg[])
{  derivative_coef f=new derivative_coef();
   f.setOrder(20); 
   System.out.println(f.dfunc(3,1.0));
   f.coef_out();
}
}