/**
   * Returns the result of postmultiplying {@code this} by {@code m}.
   *
   * @param m matrix to postmultiply by
   * @return {@code this * m}
   * @throws DimensionMismatchException if {@code columnDimension(this) != rowDimension(m)}
   */
  public Array2DRowRealMatrix multiply(final Array2DRowRealMatrix m)
      throws DimensionMismatchException {
    MatrixUtils.checkMultiplicationCompatible(this, m);

    final int nRows = this.getRowDimension();
    final int nCols = m.getColumnDimension();
    final int nSum = this.getColumnDimension();

    final double[][] outData = new double[nRows][nCols];
    // Will hold a column of "m".
    final double[] mCol = new double[nSum];
    final double[][] mData = m.data;

    // Multiply.
    for (int col = 0; col < nCols; col++) {
      // Copy all elements of column "col" of "m" so that
      // will be in contiguous memory.
      for (int mRow = 0; mRow < nSum; mRow++) {
        mCol[mRow] = mData[mRow][col];
      }

      for (int row = 0; row < nRows; row++) {
        final double[] dataRow = data[row];
        double sum = 0;
        for (int i = 0; i < nSum; i++) {
          sum += dataRow[i] * mCol[i];
        }
        outData[row][col] = sum;
      }
    }

    return new Array2DRowRealMatrix(outData, false);
  }
  /**
   * Function to compute Cholesky decomposition of the given input matrix. The input must be a real
   * symmetric positive-definite matrix.
   *
   * @param in commons-math3 Array2DRowRealMatrix
   * @return matrix block
   * @throws DMLRuntimeException if DMLRuntimeException occurs
   */
  private static MatrixBlock computeCholesky(Array2DRowRealMatrix in) throws DMLRuntimeException {
    if (!in.isSquare())
      throw new DMLRuntimeException(
          "Input to cholesky() must be square matrix -- given: a "
              + in.getRowDimension()
              + "x"
              + in.getColumnDimension()
              + " matrix.");

    CholeskyDecomposition cholesky = new CholeskyDecomposition(in);
    RealMatrix rmL = cholesky.getL();

    return DataConverter.convertToMatrixBlock(rmL.getData());
  }
  /**
   * Function to compute matrix inverse via matrix decomposition.
   *
   * @param in commons-math3 Array2DRowRealMatrix
   * @return matrix block
   * @throws DMLRuntimeException if DMLRuntimeException occurs
   */
  private static MatrixBlock computeMatrixInverse(Array2DRowRealMatrix in)
      throws DMLRuntimeException {
    if (!in.isSquare())
      throw new DMLRuntimeException(
          "Input to inv() must be square matrix -- given: a "
              + in.getRowDimension()
              + "x"
              + in.getColumnDimension()
              + " matrix.");

    QRDecomposition qrdecompose = new QRDecomposition(in);
    DecompositionSolver solver = qrdecompose.getSolver();
    RealMatrix inverseMatrix = solver.getInverse();

    return DataConverter.convertToMatrixBlock(inverseMatrix.getData());
  }