import javax.swing.*;

public class B_spline2
{ // cubic B-spline interpolation
  public double x[];
  public double f[];
  public double k[];
  int N;
  int n1;
  int m;
  double B[];
  double B2[];
  double a[];
  
  public B_spline2(double xi[],double yi[])
  {   N=yi.length-1;
      n1=N+7;
	  x=new double[N+1];
	  f=new double[N+1];
	  k=new double[n1];
      for(int i=0;i<=N;i++)
      {x[i]=xi[i];f[i]=yi[i];k[i+3]=x[i];
      }
      double dx=(x[N]-x[0]);
      k[0]=x[0]-6.0*dx;
      k[1]=x[0]-4.0*dx;
      k[2]=x[0]-2.0*dx;
      k[N+4]=x[N]+2.0*dx;
      k[N+5]=x[N]+4.0*dx;
      k[N+6]=x[N]+6.0*dx;
      m=5;  
      B=new double[N+7];
      B2=new double[N+7];
      A();
  }
  
public  double[] B(double t)
{ 
double b[][]=new double[m][N+7];
for(int i=0;i<k.length-1;i++)
{if(t>=k[i] && t<k[i+1]) b[1][i]=1;
 else b[1][i]=0.0;
}
for(int n=2;n<m;n++)
{
for(int i=0;i<k.length-4;i++)
{
b[n][i]=(t-k[i])/(k[i+n-1]-k[i])*b[n-1][i]+(k[i+n]-t)/(k[i+n]-k[i+1])*b[n-1][i+1];
B[i]=b[n][i];
}
}
return B;
}

public void A()
{
B2[0]=6.0/(k[4]-k[2])/(k[4]-k[1]);
B2[1]=-6.0/(k[4]-k[2])*(1.0/((k[5]-k[2])+1.0/(k[4]-k[1]) ));
B2[2]=6.0/(k[4]-k[2])/(k[5]-k[2]);
B2[N]=6.0/(k[N+4]-k[N+2])/(k[N+4]-k[N+1]);
B2[N+1]=6.0/(k[N+4]-k[N+2])*(1.0/((k[N+5]-k[N+2])+1.0/(k[N+4]-k[N+1]) ));
B2[N+2]=6.0/(k[N+4]-k[N+2])/(k[N+5]-k[N+2]);
double AA[][]=new double[N+3][N+3];
double BB[]=new double[N+3];
AA[0][0]=B2[0];
AA[0][1]=B2[1]; 
AA[0][2]=B2[2];
BB[0]=0;
AA[N+2][N]=B2[N];
AA[N+2][N+1]=B2[N+1];
AA[N+2][N+2]=B2[N+2];
BB[N+2]=0;
for(int j=0;j<=N;j++)
{ B=B(k[j+3]);
  for(int i=0;i<=N+2;i++)
  { AA[j+1][i]=B[i];}
  BB[j+1]=f[j];
}
a=pivotlugauss(AA,BB);
}


public double S(double x)
{ B=B(x);
  double ss=0;
  for(int i=0;i<=N+2;i++)
  {ss+=a[i]*B[i];}
  return ss;
}

 public static  double[][]  funcB_Spline(double xi[],double yi[],int aradegersayisi)
 {
     B_spline b1=new B_spline(xi,yi);
     double aa[][]=b1.funcB_Spline(aradegersayisi);	
     return aa; 
 }
  
 public  double[][]  funcB_Spline(int aradegersayisi)
 {
	//aradegersayisi:  x--o--o--x--o--o--x zincirinde x deneysel noktalar ise
	// ara değer sayısı 2 dir
	int n=x.length;
	int nn=(n-1)*(aradegersayisi+1)+1;
	double z[][]=new double[2][nn];
    double dx=0;
    int k=0;
    int i;
    for(i=0;i<(n-1);i++)
       {  z[0][k]=x[i];z[1][k]=S(z[0][k]);k++;
          for(int j=0;j<aradegersayisi;j++) 
             {dx=(x[i+1]-x[i])/((double)aradegersayisi+1.0);
          z[0][k]=z[0][k-1]+dx;z[1][k]=S(z[0][k]);k++;}
       }
       z[0][k]=x[i];z[1][k]=S(z[0][k]);
    return z;
 } 
 
  public static double[] pivotlugauss(double a[][],double b[])
  { //kısmi pivotlu gauss eleme yöntemi
  int n=b.length;	  
  double x[]=new double[n];
  double carpan=0;
  double toplam=0;
  double buyuk;
  double dummy=0;
  //gauss eleme
  int i,j,k,p,ii,jj;
  //System.out.println("Orijinal Matris :\n"+Matrix.toString(a));
  for(k=0;k<(n-1);k++)
  { //pivotlama
	p=k;
	buyuk=Math.abs(a[k][k]);
	for(ii=k+1;ii<n;ii++)
	{  dummy=Math.abs(a[ii][k]);
	   if(dummy > buyuk) {buyuk=dummy;p=ii;}
	}
	if(p!=k)
	{ for(jj=k;jj<n;jj++)
	  { dummy=a[p][jj];
	    a[p][jj]=a[k][jj];
	    a[k][jj]=dummy;
	  }
	  dummy=b[p];
	  b[p]=b[k];
	  b[k]=dummy;
	}
	  //System.out.println("pivotlu Matris : k="+k+"\n"+Matrix.toString(a));
	//gauss elemeyi çözme  
    for(i=k+1;i<n;i++)
    {  carpan=a[i][k]/a[k][k];
       a[i][k]=0;
       for(j=k+1;j<n;j++)
       {   a[i][j]-=carpan*a[k][j]; }
           b[i]   =b[i]   -carpan*b[k];
	}
  }
  //System.out.println("elimine prosesibitmiş matris : \n"+Matrix.toString(a));
  //geriye doğru yerine koyma
  x[n-1]=b[n-1]/a[n-1][n-1];
  for(i=n-2;i>=0;i--)
  {
    toplam=0;
    for(j=i+1;j<n;j++)
    {  toplam+=a[i][j]*x[j];}
    x[i]=(b[i]-toplam)/a[i][i];
  }
  return x;
  }
    
  public static void main(String[] arg)
  {  
     //double a[][]=({0.0,  0.6 ,1.5 ,1.7 ,1.9 ,2.1,2.3 ,2.6 ,2.8,3.0 ,3.6 ,4.7  ,5.2  ,5.7  ,5.8  , 6.0 , 6.4 ,6.9,7.6,8.0};
      //             {-0.8,-0.34,0.59,0.59,0.23,0.1,0.28,1.03,1.5,1.44,0.74,-0.82,-1.27,-0.92,-0.92,-1.04,-0.79,-0.06,1.0,0.0}};
     String dosya=JOptionPane.showInputDialog("dosya ismini giriniz");
     double a[][]=Text.readDoubleT(dosya);
     int aradegersayisi=5;
     double aa[][]=funcB_Spline(a[0],a[1],10);
     Plot1 pp=new Plot1(a[0],a[1]);
     pp.setPlotType(0,24);
     pp.setColor(0,0,0,255);
     pp.addData(aa[0],aa[1]);
     pp.plot();
  }
}