import java.io.*;
import javax.swing.*;

class SCO13F
{  // Jacobi eigenvalue calculation method
public static double[][] I(int n)
{
//unit matrix
double b[][];
b=new double[n][n];
for(int i=0;i<n;i++)
    b[i][i]=1.0;
return b;
}

public static double[][] multiply(double[][] left,double right)
{
//multiplying a matrix with a constant
int i,j;
int n=left.length;
int m=left[0].length;
double b[][];
b=new double[n][m];
for(i=0;i<n;i++)
  {
  for(j=0;j<m;j++)
    b[i][j]=left[i][j]*right;
  }
return b;
//end of multiplying a matrix with a constant double
}

public static double[][] multiply(double[][] left,double[][] right)
{
//multiplication of two matrices
int ii,jj,i,j,k;
int m1=left[0].length;
int n1=left.length;
int m2=right[0].length;
int n2=right.length;
double[][] b;
b=new double[m1][n2];
 if(n1 != m2)
 {
 System.out.println("inner matrix dimensions must agree");
 for(ii=0;ii<n1;ii++)
   {
   for(jj=0;jj<m2;jj++)
     b[ii][jj]=0;
   }
   return b;
 }
 for(i=0;i<m1;i++)
   {
   for(j=0;j<n2;j++)
     {
     for(k=0;k<n1;k++)
	    b[i][j]+=left[i][k]*right[k][j];
     }
   }
return b;
//end of multiply of two matrices
}

public static double[][] substract(double[][] left,double[][] right)
{
//addition of two matrices
int n1=left.length;
int m1=left[0].length;
int n2=right.length;
int m2=right[0].length;
int nMax,mMax;
int i,j;
if(m1>=m2) mMax=m1;
else       mMax=m2;
if(n1>=n2) nMax=n1;
else       nMax=n2;
double b[][];
b=new double[nMax][mMax];
for(i=0;i<n1;i++)
  {
  for(j=0;j<m1;j++)
    {
    b[i][j]=b[i][j]+left[i][j];
    }
  }
for(i=0;i<n2;i++)
  {
  for(j=0;j<m2;j++)
    {
    b[i][j]=b[i][j]-right[i][j];
    }
  }
return b;
//end of matrix substraction method
}

public static double[][] T(double [][] left)
{
//transpose matrix (if A=a(i,j) T(A)=a(j,i)
int i,j;
int n=left.length;
int m=left[0].length;
double b[][];
b=new double[m][n];
for(i=0;i<n;i++)
  {
  for(j=0;j<m;j++)
    {
    b[j][i]=left[i][j];
    }
  }
return b;
}

public static double VT_V(double [] left)
{
//multiply a vector transpose with a vector	
int n=left.length;
double tot=0;
for(int i=0;i<n;i++)
  {
  tot+=left[i]*left[i];
  }
return tot;  
}

public static double[][] V_VT(double [] left)
{
//multiplys a vector transpose with a vector	
int n=left.length;
double aa[][]=new double[n][n];
for(int i=0;i<n;i++)
  {
  for(int j=0;j<n;j++)
    {
	aa[i][j]=left[i]*left[j];
	}
  }
return aa;  
}
	
  public static double[] eigen_QR(double A[][])
  {
   B=Householder(A);	  
   double eps=1e-15;
   double err=1;
   int i=0;
   int n=A.length;
   do
   {
    fi=0.5*Math.atan(2.0*A[p][q]/(A[p][p]-A[q][q]));
    //if(fi<0) fi+=Math.PI/2;
    R=I(n);
    R[p][p]=Math.cos(fi);
    R[q][q]=Math.cos(fi);
    R[p][q]=-Math.sin(fi);
    R[q][p]=Math.sin(fi);
    P=multiply(P,R);
    A=multiply(T(R),multiply(A,R));
    max=-9.99e100;
    for(int i=0;i<n;i++)
   {for(int j=i+1;j<n;j++){if(Math.abs(A[i][j])>max) {max=Math.abs(A[i][j]);p=i;q=j;}}}  
    } while(Math.abs(A[p][q]) > eps );
   double lambda[]=new double[n];
   for(int i=0;i<n;i++) {lambda[i]=A[i][i];}
   return lambda;
  }
  
  public static double sgn(double x)
  {return x/Math.abs(x);}
  
  public static double[][] Householder(double A[][])
  { //Householder transformation
   int n=A.length;
   double Q[][]=I(n);
   double alpha;
   double toplam;
   double u[]=new double[n];   
   double C[][]=new double[n][n];
   double P[][]=new double[n][n];
   double B[][]=new double[n][n];
   double cc;
   for(int k=0;k<(n-2);k++)
   {
      toplam=0;
      for(int j=k+1;j<n;j++) {toplam+=A[j][k]*A[j][k];}
      toplam=Math.sqrt(toplam);	   
      alpha=sgn(A[k+1][k])*toplam;
      for(int j=0;j<n;j++) 
      {   if(j<=k) u[j]=0.0;
          else if(j==k+1) u[j]=A[j][k]+alpha;
          else u[j]=A[j][k];
      }
      C=V_VT(u);
      cc=2.0/VT_V(u);
      C=multiply(C,cc);
      P=substract(I(n),C);
      Q=multiply(Q,P);
      A=multiply(P,multiply(A,P));         
   }
   return A;     
   }
  
	
  public static void main(String args[]) throws IOException
  {
  //Sınır değer hesapları
  double c[];
  c=new double[3];
  //double a[][]={{8,-1,3,-1},{-1,6,2,0},{3,2,9,1},{-1,0,1,7}};
  double a[][]={{3,-1,0},{-1,2,-1},{0,-1,3}};
  String s="Orijinal matris : \n";
  s+=Matrix.toString(a);
  c=eigen_jacobi(a);
  s+="sınır değer vektörü \n";
  s+=Matrix.toStringT(c);
  JOptionPane.showMessageDialog(null,s,
     "Jacobi simetrik eigenvalue metodu : ",JOptionPane.PLAIN_MESSAGE);
 }
}
