package ppmrmn;

public class ComplexMat {

  protected static int n;  // taille des matrices carrées
  public double re[][] = new double[n][n];  // partie réelle
  public double im[][] = new double[n][n];  // partie imaginaire

  //Fixe la taille des matrices carrées
  public static void setTailleMatrice (int i) {
    n = i;
  }

  //Fixe la taille des matrices carrées
  public static int getN() {
    return n;
  }

  public ComplexMat(double preal[][], double pimag[][]) {
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        re[i][j] = preal[i][j];
        im[i][j] = pimag[i][j];
      }
  }

  public ComplexMat(double preal[][]) {
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        re[i][j] = preal[i][j];
        im[i][j] = 0;
      }
  }

  public ComplexMat() {
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        re[i][j] = 0;
        im[i][j] = 0;
      }
  }

  public ComplexMat mult(ComplexMat a, ComplexMat b) {
    ComplexMat c = new ComplexMat();
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        for (int k = 0; k < n; k++) {
          c.re[i][j] += a.re[i][k]*b.re[k][j] - a.im[i][k]*b.im[k][j];
          c.im[i][j] += a.re[i][k]*b.im[k][j] + a.im[i][k]*b.re[k][j];
        }
//    System.out.println("complex-complex");
    return c;
  }

  public ComplexMat matConjugue(ComplexMat a) {
    ComplexMat c = new ComplexMat();
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        c.re[i][j] = a.re[i][j];
        c.im[i][j] = -a.im[i][j];
      }
    return c;
  }

  //Matrice contenant un seul element complexe non nul pour echo Hahn
  public ComplexMat matSingle(ComplexMat a, int row, int col) {
    ComplexMat c = new ComplexMat();
    c.re[row][col] = a.re[row][col];
    c.im[row][col] = a.im[row][col];
    return c;
  }

  public ComplexMat matCopier(ComplexMat a) {
    ComplexMat c = new ComplexMat();
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        c.re[i][j] = a.re[i][j];
        c.im[i][j] = a.im[i][j];
      }
    return c;
  }

  //Matrice contenant 4 elements complexes non nuls pour echo de Solomon
  public ComplexMat matQuatre(ComplexMat a, int row, int col) {
    ComplexMat c = new ComplexMat();
    //attention les huit ligne de code doivent apparaitre dans cet ordre
    //sinon problème avec IE5.5 sous Windows 98
    c.re[n - row - 1][col] = a.re[n - row - 1][col];
    c.im[n - row - 1][col] = a.im[n - row - 1][col];

    c.re[row][col] = a.re[row][col];
    c.im[row][col] = a.im[row][col];

    c.re[n - row - 1][n - col - 1] = a.re[n - row - 1][n - col - 1];
    c.im[n - row - 1][n - col - 1] = a.im[n - row - 1][n - col - 1];

    c.re[row][n - col - 1] = a.re[row][n - col - 1];
    c.im[row][n - col - 1] = a.im[row][n - col - 1];

    return c;
  }

  public ComplexMat matRotation(ComplexMat a, double phase){
    ComplexMat c = new ComplexMat();
    double cs, sn;
    for (int i = 0; i < n; i++){
        c.re[i][i] = a.re[i][i];
        c.im[i][i] = a.im[i][i];
    }
    for (int i = 0; i < n - 1; i++)
      for (int j = i + 1; j < n; j++) {
        cs = Math.cos((j - i)*phase);  //colonne - ligne contrairement au formule mathematique
        sn = Math.sin((j - i)*phase);  //exp(-ip*phase) avec p = ligne - colonne
        c.re[i][j] = a.re[i][j]*cs - a.im[i][j]*sn;
        c.im[i][j] = a.re[i][j]*sn + a.im[i][j]*cs;
      }
    for (int j = 0; j < n - 1; j++)
      for (int i = j + 1; i < n; i++) {
        c.re[i][j] =  c.re[j][i];
        c.im[i][j] = -c.im[j][i];
      }
    return c;
  }

  //Matrice contenant 2 elements complexes non nuls pour echo de Solomon DQ
  public ComplexMat matDeux(ComplexMat a, int row, int col) {
    ComplexMat c = new ComplexMat();
    if (((row + col) % 2) == 0){
      c.re[row][col] = a.re[row][col];
      c.im[row][col] = a.im[row][col];

      c.re[n - row - 1][n - col - 1] = a.re[n - row - 1][n - col - 1];
      c.im[n - row - 1][n - col - 1] = a.im[n - row - 1][n - col - 1];
    }
    else{
      c.re[n - row - 1][col] = a.re[n - row - 1][col];
      c.im[n - row - 1][col] = a.im[n - row - 1][col];

      c.re[row][n - col - 1] = a.re[row][n - col - 1];
      c.im[row][n - col - 1] = a.im[row][n - col - 1];

    }
    return c;
  }

  //les coherences impaires sont annulées
  public ComplexMat matSimpEvenQ(ComplexMat a){
    ComplexMat c = new ComplexMat();
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        c.re[i][j] = a.re[i][j];
        c.im[i][j] = a.im[i][j];
      }
    for (int i = 0; i < n; i++){
      if (i % 2 == 1){
        for (int j = 0; j < (n/2); j++) {
          c.re[i][2*j] = 0;
          c.im[i][2*j] = 0;
        }
      }
      else{
        for (int j = 0; j < (n/2); j++) {
          c.re[i][2*j + 1] = 0;
          c.im[i][2*j + 1] = 0;
        }
      }
    }
    return c;
  }

  //les coherences paires sont annulées
  public ComplexMat matSimpOddQ(ComplexMat a){
    ComplexMat c = new ComplexMat();
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        c.re[i][j] = a.re[i][j];
        c.im[i][j] = a.im[i][j];
      }
    for (int i = 0; i < n; i++){
      if (i % 2 == 1){
        for (int j = 0; j < (n/2); j++) {
          c.re[i][2*j + 1] = 0;
          c.im[i][2*j + 1] = 0;
        }
      }
      else{
        for (int j = 0; j < (n/2); j++) {
          c.re[i][2*j] = 0;
          c.im[i][2*j] = 0;
        }
      }
    }
    return c;
  }

  public ComplexMat matAddition(ComplexMat a, ComplexMat b) {
  ComplexMat c = new ComplexMat();
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++) {
      c.re[i][j] = a.re[i][j] + b.re[i][j];
      c.im[i][j] = a.im[i][j] + b.im[i][j];
    }
    return c;
  }

  public ComplexMat matOppose(ComplexMat a) {
    ComplexMat c = new ComplexMat();
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        c.re[i][j] = -a.re[i][j];
        c.im[i][j] = -a.im[i][j];
      }
    return c;
  }

}

