// OPPOSITE
 // Opposite of a Phasor matrix
 public PhasorMatrix opposite() {
   PhasorMatrix opp = PhasorMatrix.copy(this);
   for (int i = 0; i < this.nrow; i++) {
     for (int j = 0; j < this.ncol; j++) {
       opp.matrix[i][j] = this.matrix[i][j].times(Phasor.minusOne());
     }
   }
   return opp;
 }
 // COMPLEX CONJUGATE
 // Complex Conjugate of a Phasor matrix
 public PhasorMatrix conjugate() {
   PhasorMatrix conj = PhasorMatrix.copy(this);
   for (int i = 0; i < this.nrow; i++) {
     for (int j = 0; j < this.ncol; j++) {
       conj.matrix[i][j] = this.matrix[i][j].conjugate();
     }
   }
   return conj;
 }
  // LU DECOMPOSITION OF COMPLEX MATRIX A
  // For details of LU decomposition
  // See Numerical Recipes, The Art of Scientific Computing
  // by W H Press, S A Teukolsky, W T Vetterling & B P Flannery
  // Cambridge University Press,   http://www.nr.com/
  // PhasorMatrix ludmat is the returned LU decompostion
  // int[] index is the vector of row permutations
  // dswap returns +1.0 for even number of row interchanges
  //       returns -1.0 for odd number of row interchanges
  public PhasorMatrix luDecomp() {
    if (this.nrow != this.ncol) throw new IllegalArgumentException("A matrix is not square");
    int n = this.nrow;
    int imax = 0;
    double dum = 0.0D, temp = 0.0D, big = 0.0D;
    double[] vv = new double[n];
    Phasor sum = new Phasor();
    Phasor dumm = new Phasor();

    PhasorMatrix ludmat = PhasorMatrix.copy(this);
    Phasor[][] ludarray = ludmat.getArrayReference();

    ludmat.dswap = 1.0;
    for (int i = 0; i < n; i++) {
      big = 0.0;
      for (int j = 0; j < n; j++) {
        if ((temp = ludarray[i][j].abs()) > big) big = temp;
      }
      if (big == 0.0) throw new ArithmeticException("Singular matrix");
      vv[i] = 1.0 / big;
    }
    for (int j = 0; j < n; j++) {
      for (int i = 0; i < j; i++) {
        sum = Phasor.copy(ludarray[i][j]);
        for (int k = 0; k < i; k++) sum.minusEquals(ludarray[i][k].times(ludarray[k][j]));
        ludarray[i][j] = Phasor.copy(sum);
      }
      big = 0.0;
      for (int i = j; i < n; i++) {
        sum = Phasor.copy(ludarray[i][j]);
        for (int k = 0; k < j; k++) {
          sum.minusEquals(ludarray[i][k].times(ludarray[k][j]));
        }
        ludarray[i][j] = Phasor.copy(sum);
        if ((dum = vv[i] * sum.abs()) >= big) {
          big = dum;
          imax = i;
        }
      }
      if (j != imax) {
        for (int k = 0; k < n; k++) {
          dumm = Phasor.copy(ludarray[imax][k]);
          ludarray[imax][k] = Phasor.copy(ludarray[j][k]);
          ludarray[j][k] = Phasor.copy(dumm);
        }
        ludmat.dswap = -ludmat.dswap;
        vv[imax] = vv[j];
      }
      ludmat.index[j] = imax;

      if (ludarray[j][j].isZero()) {
        ludarray[j][j].reset(TINY, 0.0D);
      }
      if (j != n - 1) {
        dumm = ludarray[j][j].inverse();
        for (int i = j + 1; i < n; i++) {
          ludarray[i][j].timesEquals(dumm);
        }
      }
    }
    return ludmat;
  }
 // ADJOIN
 // Adjoin of a Phasor matrix
 public PhasorMatrix adjoin() {
   PhasorMatrix adj = PhasorMatrix.copy(this);
   adj = adj.transpose();
   adj = adj.conjugate();
   return adj;
 }