import java.util.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;

public class conjugate_gradient2
{
public static double VT_V(double [] left)
{
//multiplies 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  VT_X(double [] left,double [] right)
{
//multiplys a vector transpose with a vector	
int n=left.length;
double tot=0;
for(int i=0;i<n;i++)
  {
  tot+=left[i]*right[i];
  }
return tot;  
}
public static double[][] multiply(double left,double[][] right)
{
//multiplying a matrix with a constant
int i,j;
int n=right.length;
int m=right[0].length;
double b[][];
b=new double[n][m];
for(i=0;i<n;i++)
  {
  for(j=0;j<m;j++)
    b[i][j]=right[i][j]*left;
  }
return b;
//end of multiplying a matrix with a constant double
}
public static double[] multiply(double[] left,double[][] right)
{
//multiplication of one vector with one matrix
int ii,jj,i,j,k;
int m2=right[0].length;
int n2=right.length;
int m1=left.length;
double[] b;
b=new double[m1];
 if(n2 != m1)
 {
 System.out.println("inner matrix dimensions must agree");
 for(ii=0;ii<n2;ii++)
   {
     b[ii]=0;
   }
   return b;
 }
 for(i=0;i<m2;i++)
   {
     b[i]=0;
     for(k=0;k<m1;k++)
	b[i]+=right[i][k]*left[k];
   }
return b;
//end of multiply of a vector and a matrix
}

public static double[] multiply(double[][] left,double[] right)
{
//multiplication of one matrix with one vector
int ii,jj,i,j,k;
int m1=left[0].length;
int n1=left.length;
int m2=right.length;
double[] b;
b=new double[m2];
 if(n1 != m2)
 {
 System.out.println("inner matrix dimensions must agree");
 for(ii=0;ii<n1;ii++)
   {
     b[ii]=0;
   }
   return b;
 }
 for(i=0;i<m1;i++)
   {
     b[i]=0;
     for(k=0;k<n1;k++)
	b[i]+=left[i][k]*right[k];
   }
return b;
//end of multiply of a matrix and a vector
}
public static double[] multiply(double left,double[] right)
{
//multiplying a vector with a constant
int i;
int n=right.length;
double b[];
b=new double[n];
for(i=0;i<n;i++)
  {
  b[i]=left*right[i];
  }
return b;
}
public static double[] substract(double[] left,double[] right)
{
//addition of two vectors
int n1=left.length;
int n2=right.length;
int nMax;
int i;
if(n1>=n2) nMax=n1;
else       nMax=n2;
double b[];
b=new double[nMax];
for(i=0;i<n1;i++)
  {
    b[i]=b[i]+left[i];
  }
for(i=0;i<n2;i++)
  {
    b[i]=b[i]-right[i];
  }
return b;
//end of vector substraction method
}
public static double[] add(double[] left,double[] right)
{
//addition of two vectors
int n1=left.length;
int n2=right.length;
int nMax;
int i;
if(n1>=n2) nMax=n1;
else       nMax=n2;
double b[];
b=new double[nMax];
for(i=0;i<n1;i++)
  {
    b[i]=b[i]+left[i];
  }
for(i=0;i<n2;i++)
  {
    b[i]=b[i]+right[i];
  }
return b;
//end of vector addition method
}
public static double[] equals(double[] left)
{
//addition of two vectors
int n1=left.length;
double b[];
b=new double[n1];
for(int i=0;i<n1;i++)
  {
    b[i]=left[i];
  }
return b;
//end of vector equal method
}
public static double norm(double v[])
{return Math.sqrt(normkare(v));}

public static double normkare(double v[])
{
// vector norm
double total=0;;
for(int i=0;i<v.length;i++)
  {total+=v[i]*v[i];}
return total;
}

public static double VT_G_V(double V[],double G[][])
{
  double x1[]=multiply(V,G);
  return VT_X(V,x1);
}

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[][] D(double A[][])
{
//Diagonal elements of matrix
int n=A.length;
double b[][];
b=new double[n][n];
for(int i=0;i<n;i++)
    b[i][i]=A[i][i];
return b;
}

public static double[][] invsqrtD(double A[][])
{
//square root of Diagonal elements of a matrix
int n=A.length;
double b[][];
b=new double[n][n];
for(int i=0;i<n;i++)
    b[i][i]=1.0/Math.sqrt(A[i][i]);
return b;
}


public static double[] cunjugate_gradient(double x[],double A[][],double b[],double C[][])
{ // iterative system of equation solution
double eps=1.0e-30;
int n=x.length;	
double r[]=new double[n];
double re[]=new double[n];
double v[]=new double[n];
double w[]=new double[n];
double u[]=new double[n];
double t;
double alfa,beta,s;
r=substract(b,multiply(A,x));
v=equals(r);
w=multiply(C,r);
alfa=normkare(w);
do
  {
  if(norm(v)<eps) return x;	  
  re=equals(r);
  u=multiply(A,v);
  t=alfa/VT_X(v,u);
  x=add(x,multiply(t,v));
  r=substract(r,multiply(t,u));
  w=multiply(C,r);
  beta=normkare(w);
  if(beta<eps) 
  {if(norm(r)<eps) return x;}	  
  s=beta/alfa;
  v=add(multiply(C,w),multiply(s,v));
  alfa=beta;  
  }while(norm(r)>eps && beta>eps);
  
return x;
}
  public static void main(String args[]) throws IOException
  {
  double A[][]={{0.2,0.1,1,1,0},{0.1,4,-1,1,-1},{1,-1,60,0,-2},{1,1,0,8,4},{0,-1,-2,4,700}};
  double b[]={1,2,3,4,5};
  double x[]={0,0,0,0,0};
  double D[][]=invsqrtD(A);
  System.out.println("Konjuge 5gradyan metodu : \n"+Matrix.toString(D));
  x=cunjugate_gradient(x,A,b,D); 
  System.out.println("Konjuge gradyan metodu : \n"+Matrix.toStringT(x));
  }
}