import Jama.*;

/**
 * The Algorithm class controls all the math for the steepest descent program
 * @author Anton Sigety
 */

public class Algorithm{  

  private static int count;
  private static double acc;
  /**
   * Controller calculates the actial steepest descent and count the iterations it takes to 
   * find the steepest descent
   * @param a An n x n matrix A 
   * @param b An n x 1 matrix b
   * @param x An n x 1 matrix x, always defined by the user
   * @param accuracy Sets the accuracy level to check for steepest descent
   */
  public static void calculate(double[][] a, double[][] b, double[][] x, double accuracy) {
    
    acc = accuracy;
    
    Matrix matrixA = new Matrix(a);
    Matrix matrixB = new Matrix(b);
    Matrix total = new Matrix(x);
    Matrix num = null;
    Matrix denom = null;
    Matrix frac = null;
    Matrix dot = null;
    Matrix inverseDenom = null;
       
    count = 0;
    
    ResultsPanel.clearText();
    ResultsPanel.setText("Matrix a: \n");
    HistoryPanel.setText("Matrix a: \n");
     for (int row=0; row < a.length; row++){
          for (int col=0; col < a[row].length; col++){
            ResultsPanel.setText(a[row][col] + " ");
            HistoryPanel.setText(a[row][col] + " ");
          }
          ResultsPanel.setText("\n");
          HistoryPanel.setText("\n");
        }
     ResultsPanel.setText("\n");
     HistoryPanel.setText("\n");
     ResultsPanel.setText("Matrix b: \n");
     HistoryPanel.setText("Matrix b \n");
     for (int row=0; row < b.length; row++){
          for (int col=0; col < b[row].length; col++){
            ResultsPanel.setText(b[row][col] + " ");
            HistoryPanel.setText(b[row][col] + " ");
          }
          ResultsPanel.setText("\n");
          HistoryPanel.setText("\n");
        }
     ResultsPanel.setText("\n");
     HistoryPanel.setText("\n");
     ResultsPanel.setText("Matix xo: \n");
     HistoryPanel.setText("Matix xo: \n");
     for (int row=0; row < x.length; row++){
          for (int col=0; col < x[row].length; col++){
            ResultsPanel.setText(x[row][col] + " ");
            HistoryPanel.setText(x[row][col] + " ");
          }
          ResultsPanel.setText("\n");
          HistoryPanel.setText("\n");
        }
     ResultsPanel.setText("\n");
     HistoryPanel.setText("\n");
    
    do {
      num = ((matrixA.times(total)).plus(matrixB)).times(-1);// calculates the numerator and is used by the while loop to check for accuracy(2x1)
      dot = ((num.transpose()).times(num));//dots the numerator with itself(1x1)
      acc = Math.sqrt(dot.get(0,0));//squareroot of the accuracy(c)
      denom = (num.transpose()).times(matrixA.times(num));// calculates the denomonator(1x1)
      inverseDenom = denom.inverse();//invert the denominator(1x1)
      frac = (dot).times(inverseDenom);//calculates the fraction of num/denom(1x1)
      total = (num.times(frac)).plus(total);// divides the numerator by the denominator and adds Xo(2x1)
      
      count++;//incrament iterations

    } while(acc >= accuracy);

    double[][] answer = total.getArray();
    ResultsPanel.setText("Matrix x: \n");
    HistoryPanel.setText("Matrix x: \n");
    for (int row=0; row < answer.length; row++){
          for (int col=0; col < answer[row].length; col++){
            ResultsPanel.setText(answer[row][col] + " ");
            HistoryPanel.setText(answer[row][col] + " ");
          }
          ResultsPanel.setText("\n");
          HistoryPanel.setText("\n");
        }
    ResultsPanel.setText("\n");
    HistoryPanel.setText("\n");
    
    ResultsPanel.setText("Total number of iterations was:" + count);
    HistoryPanel.setText("Total number of iterations was:" + count);
    HistoryPanel.setText("\n------------------------------------------------------------------------------- \n");
   }// closes Calculate method 
}//closes Algorithm class
