/**
   * Solves for x in Ax = b, where x is this vector (nx1), A is mxn, b is mx1, and A =
   * U*W*transpose(V); U,W,V must be precomputed and can be found by taking the singular value
   * decomposition (SVD) of A using the method SVD found in the GMatrix class.
   *
   * @param U The U matrix produced by the GMatrix method SVD
   * @param W The W matrix produced by the GMatrix method SVD
   * @param V The V matrix produced by the GMatrix method SVD
   * @param b The b vector in the linear equation Ax = b
   */
  public final void SVDBackSolve(GMatrix U, GMatrix W, GMatrix V, GVector b) {
    if (!(U.nRow == b.getSize() && U.nRow == U.nCol && U.nRow == W.nRow)) {
      throw new MismatchedSizeException(VecMathI18N.getString("GVector15"));
    }

    if (!(W.nCol == values.length && W.nCol == V.nCol && W.nCol == V.nRow)) {
      throw new MismatchedSizeException(VecMathI18N.getString("GVector23"));
    }

    GMatrix tmp = new GMatrix(U.nRow, W.nCol);
    tmp.mul(U, V);
    tmp.mulTransposeRight(U, W);
    tmp.invert();
    mul(tmp, b);
  }
  /**
   * LU Decomposition Back Solve; this method takes the LU matrix and the permutation vector
   * produced by the GMatrix method LUD and solves the equation (LU)*x = b by placing the solution
   * vector x into this vector. This vector should be the same length or longer than b.
   *
   * @param LU The matrix into which the lower and upper decompostions have been placed
   * @param b The b vector in the equation (LU)*x = b
   * @param permutation The row permuations that were necessary to produce the LU matrix parameter
   */
  public final void LUDBackSolve(GMatrix LU, GVector b, GVector permutation) {
    int size = LU.nRow * LU.nCol;

    double[] temp = new double[size];
    double[] result = new double[size];
    int[] row_perm = new int[b.getSize()];
    int i, j;

    if (LU.nRow != b.getSize()) {
      throw new MismatchedSizeException(VecMathI18N.getString("GVector16"));
    }

    if (LU.nRow != permutation.getSize()) {
      throw new MismatchedSizeException(VecMathI18N.getString("GVector24"));
    }

    if (LU.nRow != LU.nCol) {
      throw new MismatchedSizeException(VecMathI18N.getString("GVector25"));
    }

    for (i = 0; i < LU.nRow; i++) {
      for (j = 0; j < LU.nCol; j++) {
        temp[i * LU.nCol + j] = LU.values[i][j];
      }
    }

    for (i = 0; i < size; i++) result[i] = 0.0;
    for (i = 0; i < LU.nRow; i++) result[i * LU.nCol] = b.values[i];
    for (i = 0; i < LU.nCol; i++) row_perm[i] = (int) permutation.values[i];

    GMatrix.luBacksubstitution(LU.nRow, temp, row_perm, result);

    for (i = 0; i < LU.nRow; i++) this.values[i] = result[i * LU.nCol];
  }
  /**
   * Multiplies the transpose of vector v1 (ie, v1 becomes a row vector with respect to the
   * multiplication) times matrix m1 and places the result into this vector (this =
   * transpose(v1)*m1). The result is technically a row vector, but the GVector class only knows
   * about column vectors, and so the result is stored as a column vector.
   *
   * @param m1 The matrix in the multiplication
   * @param v1 The vector that is temporarily transposed
   */
  public final void mul(GVector v1, GMatrix m1) {
    if (m1.getNumRow() != v1.length)
      throw new MismatchedSizeException(VecMathI18N.getString("GVector12"));

    if (length != m1.getNumCol())
      throw new MismatchedSizeException(VecMathI18N.getString("GVector13"));

    double v[];
    if (v1 != this) {
      v = v1.values;
    } else {
      v = (double[]) values.clone();
    }

    for (int j = length - 1; j >= 0; j--) {
      values[j] = 0.0;
      for (int i = v1.length - 1; i >= 0; i--) {
        values[j] += m1.values[i][j] * v[i];
      }
    }
  }