DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT <http://issues.apache.org/bugzilla/show_bug.cgi?id=30897>. ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE.
http://issues.apache.org/bugzilla/show_bug.cgi?id=30897 New methods in RealMatrixImpl and changing indexing Summary: New methods in RealMatrixImpl and changing indexing Product: Commons Version: 1.0 Alpha Platform: All OS/Version: All Status: NEW Severity: Enhancement Priority: Other Component: Math AssignedTo: [EMAIL PROTECTED] ReportedBy: [EMAIL PROTECTED] Numbering of the rows and columns is as default for an JAVA array, starting with 0 with the higest value for either row-1 or column-1. This facilitates programming of modules which give back an array to construct subMatrices from the original matrix. This change affects the folowing old methods: getRow(int row) getColumn(int column) isValidCoordinate(int row, int col) setEntry(...) getEntry(...) /* * Copyright 2003-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.math.linear; import java.io.Serializable; /** * Implementation for RealMatrix using a double[][] array to store entries * and <a href="http://www.math.gatech.edu/~bourbaki/math2601/Web-notes/2num.pdf"> * LU decompostion</a> to support linear system * solution and inverse. * <p> * The LU decompostion is performed as needed, to support the following operations: <ul> * <li>solve</li> * <li>isSingular</li> * <li>getDeterminant</li> * <li>inverse</li> </ul> * <p> * <strong>Usage note</strong>:<br> * The LU decomposition is stored and reused on subsequent calls. If matrix * data are modified using any of the public setXxx methods, the saved * decomposition is discarded. If data are modified via references to the * underlying array obtained using <code>getDataRef()</code>, then the stored * LU decomposition will not be discarded. In this case, you need to * explicitly invoke <code>LUDecompose()</code> to recompute the decomposition * before using any of the methods above. * * <p> Numbering of the rows and columns is as default for an JAVA array, starting with 0 * with the higest value for either row-1 or column-1. This facilitates programming of * modules which give back an array to construct subMatrices from the original matrix. * * @version $Revision: 1.26 $ $Date: 2004/08/22 01:42:58 $ */ public class RealMatrixImpl implements RealMatrix, Serializable { /** Serializable version identifier */ static final long serialVersionUID = 4237564493130426188L; /** Entries of the matrix */ private double data[][] = null; /** Entries of cached LU decomposition. * All updates to data (other than luDecompose()) *must* set this to null */ private double lu[][] = null; /** Permutation associated with LU decompostion */ private int[] permutation = null; /** Parity of the permutation associated with the LU decomposition */ private int parity = 1; /** Bound to determine effective singularity in LU decomposition */ protected static double TOO_SMALL = 10E-12; /** * Creates a matrix with no data */ public RealMatrixImpl() { } /** * Create a new RealMatrix with the supplied row and column dimensions. * * @param rowDimension the number of rows in the new matrix * @param columnDimension the number of columns in the new matrix */ public RealMatrixImpl(int rowDimension, int columnDimension) { data = new double[rowDimension][columnDimension]; lu = null; } /** * Create a new RealMatrix using the <code>data</code> as the underlying * data array. * <p> * The input array is copied, not referenced. * * @param d data for new matrix */ public RealMatrixImpl(double[][] d) { this.copyIn(d); lu = null; } /** * Create a new (column) RealMatrix using <code>v</code> as the * data for the unique column of the <code>v.length x 1</code> matrix * created. * <p> * The input array is copied, not referenced. * * @param v column vector holding data for new matrix */ public RealMatrixImpl(double[] v) { int nRows = v.length; data = new double[nRows][1]; for (int row = 0; row < nRows; row++) { data[row][0] = v[row]; } } /** * Create a new RealMatrix which is a copy of this. * * @return the cloned matrix */ public RealMatrix copy() { return new RealMatrixImpl(this.copyOut()); } /** * Compute the sum of this and <code>m</code>. * * @param m matrix to be added * @return this + m * @throws IllegalArgumentException if m is not the same size as this */ public RealMatrix add(RealMatrix m) throws IllegalArgumentException { if (this.getColumnDimension() != m.getColumnDimension() || this.getRowDimension() != m.getRowDimension()) { throw new IllegalArgumentException("matrix dimension mismatch"); } int rowCount = this.getRowDimension(); int columnCount = this.getColumnDimension(); double[][] outData = new double[rowCount][columnCount]; double[][] mData = m.getData(); for (int row = 0; row < rowCount; row++) { for (int col = 0; col < columnCount; col++) { outData[row][col] = data[row][col] + mData[row][col]; } } return new RealMatrixImpl(outData); } /** * Compute this minus <code>m</code>. * * @param m matrix to be subtracted * @return this + m * @throws IllegalArgumentException if m is not the same size as *this */ public RealMatrix subtract(RealMatrix m) throws IllegalArgumentException { if (this.getColumnDimension() != m.getColumnDimension() || this.getRowDimension() != m.getRowDimension()) { throw new IllegalArgumentException("matrix dimension mismatch"); } int rowCount = this.getRowDimension(); int columnCount = this.getColumnDimension(); double[][] outData = new double[rowCount][columnCount]; double[][] mData = m.getData(); for (int row = 0; row < rowCount; row++) { for (int col = 0; col < columnCount; col++) { outData[row][col] = data[row][col] - mData[row][col]; } } return new RealMatrixImpl(outData); } /** * Returns the result of adding d to each entry of this. * * @param d value to be added to each entry * @return d + this */ public RealMatrix scalarAdd(double d) { int rowCount = this.getRowDimension(); int columnCount = this.getColumnDimension(); double[][] outData = new double[rowCount][columnCount]; for (int row = 0; row < rowCount; row++) { for (int col = 0; col < columnCount; col++) { outData[row][col] = data[row][col] + d; } } return new RealMatrixImpl(outData); } /** * Returns the result multiplying each entry of this by <code>d</code> * @param d value to multiply all entries by * @return d * this */ public RealMatrix scalarMultiply(double d) { int rowCount = this.getRowDimension(); int columnCount = this.getColumnDimension(); double[][] outData = new double[rowCount][columnCount]; for (int row = 0; row < rowCount; row++) { for (int col = 0; col < columnCount; col++) { outData[row][col] = data[row][col] * d; } } return new RealMatrixImpl(outData); } /** * Returns the result of postmultiplying this by <code>m</code>. * @param m matrix to postmultiply by * @return this*m * @throws IllegalArgumentException * if columnDimension(this) != rowDimension(m) */ public RealMatrix multiply(RealMatrix m) throws IllegalArgumentException { if (this.getColumnDimension() != m.getRowDimension()) { throw new IllegalArgumentException("Matrices are not multiplication compatible."); } int nRows = this.getRowDimension(); int nCols = m.getColumnDimension(); int nSum = this.getColumnDimension(); double[][] mData = m.getData(); double[][] outData = new double[nRows][nCols]; double sum = 0; for (int row = 0; row < nRows; row++) { for (int col = 0; col < nCols; col++) { sum = 0; for (int i = 0; i < nSum; i++) { sum += data[row][i] * mData[i][col]; } outData[row][col] = sum; } } return new RealMatrixImpl(outData); } /** * Returns the result premultiplying this by <code>m</code>. * @param m matrix to premultiply by * @return m * this * @throws IllegalArgumentException * if rowDimension(this) != columnDimension(m) */ public RealMatrix preMultiply(RealMatrix m) throws IllegalArgumentException { return m.multiply(this); } /** * Returns matrix entries as a two-dimensional array. * <p> * Makes a fresh copy of the underlying data. * * @return 2-dimensional array of entries */ public double[][] getData() { return copyOut(); } /** * Overwrites the underlying data for the matrix * with a fresh copy of <code>inData</code>. * * @param inData 2-dimensional array of entries */ public void setData(double[][] inData) { copyIn(inData); lu = null; } /** * Returns a reference to the underlying data array. * <p> * Does not make a fresh copy of the underlying data. * * @return 2-dimensional array of entries */ public double[][] getDataRef() { return data; } /** * Overwrites the underlying data for the matrix * with a reference to <code>inData</code>. * <p> * Does not make a fresh copy of <code>data</code>. * * @param inData 2-dimensional array of entries */ public void setDataRef(double[][] inData) { this.data = inData; lu = null; } /** * * @return norm */ public double getNorm() { double maxColSum = 0; for (int col = 0; col < this.getColumnDimension(); col++) { double sum = 0; for (int row = 0; row < this.getRowDimension(); row++) { sum += Math.abs(data[row][col]); } maxColSum = Math.max(maxColSum, sum); } return maxColSum; } /** * Returns the entries in row number <code>row</code> as an array. * * @param row the row to be fetched * @return array of entries in the row * @throws MatrixIndexException if the specified row is greater * than the number of rows in this matrix */ public double[] getRow(int row) throws MatrixIndexException { if ( !isValidCoordinate( row, 0 ) ) { throw new MatrixIndexException("illegal row argument"); } int ncols = this.getColumnDimension(); double[] out = new double[ncols]; System.arraycopy(data[row], 0, out, 0, ncols); return out; } /** * Returns the entries in row number <code>row</code> as a RealMatrix object. * * @param row the row to be fetched * @return RealMatrix with only one row * @throws MatrixIndexException if the specified row is greater * than the number of rows in this matrix */ public RealMatrix getRowMatrix(int row) throws MatrixIndexException { if ( !isValidCoordinate( row, 0 ) ) { throw new MatrixIndexException("illegal row argument"); } int ncols = this.getColumnDimension(); double[][] out = new double[1][ncols]; for (int y = 0; y<ncols; y++) { out[0][y] = data[row][y]; } return new RealMatrixImpl(out); } /** * Returns the entries in column number <code>col</code> as an array. * * @param col column to fetch * @return array of entries in the column * @throws MatrixIndexException if the specified column is greater * than the number of columns in this matrix */ public double[] getColumn(int col) throws MatrixIndexException { if ( !isValidCoordinate(0, col) ) { throw new MatrixIndexException("illegal column argument"); } int nRows = this.getRowDimension(); double[] out = new double[nRows]; for (int row = 0; row < nRows; row++) { out[row] = data[row][col]; } return out; } /** * Returns the entries in column number <code>col</code> as a RealMatrix object. * * @param col column to fetch * @return RealMatrix with only one column * @throws MatrixIndexException if the specified column is greater * than the number of columns in this matrix */ public RealMatrix getColumnMatrix(int col) throws MatrixIndexException { if ( !isValidCoordinate(0, col) ) { throw new MatrixIndexException("illegal row argument"); } int nRows = this.getRowDimension(); double[][] out = new double[nRows][1]; for (int y = 0; y<nRows ; y++) { out[y][0] = data[y][col]; } return new RealMatrixImpl(out); } /** * Returns the entry in the specified row and column. * * @param row row location of entry to be fetched * @param column column location of entry to be fetched * @return matrix entry in row,column * @throws MatrixIndexException if the specified coordinate is outside * the dimensions of this matrix */ public double getEntry(int row, int column) throws MatrixIndexException { if (!isValidCoordinate(row,column)) { throw new MatrixIndexException("matrix entry does not exist"); } return data[row][column]; } /** * Sets the entry in the specified row and column to the specified value. * * @param row row location of entry to be set * @param column column location of entry to be set * @param value value to set * @throws MatrixIndexException if the specified coordinate is outside * he dimensions of this matrix */ public void setEntry(int row, int column, double value) throws MatrixIndexException { if (!isValidCoordinate(row,column)) { throw new MatrixIndexException("matrix entry does not exist"); } data[row][column] = value; lu = null; } /** * Returns the transpose matrix. * * @return transpose matrix */ public RealMatrix transpose() { int nRows = this.getRowDimension(); int nCols = this.getColumnDimension(); RealMatrixImpl out = new RealMatrixImpl(nCols, nRows); double[][] outData = out.getDataRef(); for (int row = 0; row < nRows; row++) { for (int col = 0; col < nCols; col++) { outData[col][row] = data[row][col]; } } return out; } /** * Returns the inverse matrix if this matrix is invertible. * * @return inverse matrix * @throws InvalidMatrixException if this is not invertible */ public RealMatrix inverse() throws InvalidMatrixException { return solve(getIdentity(this.getRowDimension())); } /** * @return determinant * @throws InvalidMatrixException if matrix is not square */ public double getDeterminant() throws InvalidMatrixException { if (!isSquare()) { throw new InvalidMatrixException("matrix is not square"); } if (isSingular()) { // note: this has side effect of attempting LU decomp if lu == null return 0d; } else { double det = parity; for (int i = 0; i < this.getRowDimension(); i++) { det *= lu[i][i]; } return det; } } /** * @return true if the matrix is square (rowDimension = columnDimension) */ public boolean isSquare() { return (this.getColumnDimension() == this.getRowDimension()); } /** * @return true if the matrix is singular */ public boolean isSingular() { if (lu == null) { try { luDecompose(); return false; } catch (InvalidMatrixException ex) { return true; } } else { // LU decomp must have been successfully performed return false; // so the matrix is not singular } } /** * @return rowDimension */ public int getRowDimension() { return data.length; } /** * @return columnDimension */ public int getColumnDimension() { return data[0].length; } /** * @return trace * @throws IllegalArgumentException if the matrix is not square */ public double getTrace() throws IllegalArgumentException { if (!isSquare()) { throw new IllegalArgumentException("matrix is not square"); } double trace = data[0][0]; for (int i = 1; i < this.getRowDimension(); i++) { trace += data[i][i]; } return trace; } /** * @param v vector to operate on * @throws IllegalArgumentException if columnDimension != v.length * @return resulting vector */ public double[] operate(double[] v) throws IllegalArgumentException { if (v.length != this.getColumnDimension()) { throw new IllegalArgumentException("vector has wrong length"); } int nRows = this.getRowDimension(); int nCols = this.getColumnDimension(); double[] out = new double[v.length]; for (int row = 0; row < nRows; row++) { double sum = 0; for (int i = 0; i < nCols; i++) { sum += data[row][i] * v[i]; } out[row] = sum; } return out; } /** * @param v vector to premultiply by * @throws IllegalArgumentException if rowDimension != v.length * @return resulting matrix */ public double[] preMultiply(double[] v) throws IllegalArgumentException { int nRows = this.getRowDimension(); if (v.length != nRows) { throw new IllegalArgumentException("vector has wrong length"); } int nCols = this.getColumnDimension(); double[] out = new double[nCols]; for (int col = 0; col < nCols; col++) { double sum = 0; for (int i = 0; i < nRows; i++) { sum += data[i][col] * v[i]; } out[col] = sum; } return out; } /** * Returns a matrix of (column) solution vectors for linear systems with * coefficient matrix = this and constant vectors = columns of * <code>b</code>. * * @param b array of constant forming RHS of linear systems to * to solve * @return solution array * @throws IllegalArgumentException if this.rowDimension != row dimension * @throws InvalidMatrixException if this matrix is not square or is singular */ public double[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException { int nRows = this.getRowDimension(); if (b.length != nRows) { throw new IllegalArgumentException("constant vector has wrong length"); } RealMatrix bMatrix = new RealMatrixImpl(b); double[][] solution = ((RealMatrixImpl) (solve(bMatrix))).getDataRef(); double[] out = new double[nRows]; for (int row = 0; row < nRows; row++) { out[row] = solution[row][0]; } return out; } /** * Returns a matrix of (column) solution vectors for linear systems with * coefficient matrix = this and constant vectors = columns of * <code>b</code>. * * @param b matrix of constant vectors forming RHS of linear systems to * to solve * @return matrix of solution vectors * @throws IllegalArgumentException if this.rowDimension != row dimension * @throws InvalidMatrixException if this matrix is not square or is singular */ public RealMatrix solve(RealMatrix b) throws IllegalArgumentException, InvalidMatrixException { if (b.getRowDimension() != this.getRowDimension()) { throw new IllegalArgumentException("Incorrect row dimension"); } if (!this.isSquare()) { throw new InvalidMatrixException("coefficient matrix is not square"); } if (this.isSingular()) { // side effect: compute LU decomp throw new InvalidMatrixException("Matrix is singular."); } int nCol = this.getColumnDimension(); int nColB = b.getColumnDimension(); int nRowB = b.getRowDimension(); // Apply permutations to b double[][] bv = b.getData(); double[][] bp = new double[nRowB][nColB]; for (int row = 0; row < nRowB; row++) { for (int col = 0; col < nColB; col++) { bp[row][col] = bv[permutation[row]][col]; } } bv = null; // Solve LY = b for (int col = 0; col < nCol; col++) { for (int i = col + 1; i < nCol; i++) { for (int j = 0; j < nColB; j++) { bp[i][j] -= bp[col][j] * lu[i][col]; } } } // Solve UX = Y for (int col = nCol - 1; col >= 0; col--) { for (int j = 0; j < nColB; j++) { bp[col][j] /= lu[col][col]; } for (int i = 0; i < col; i++) { for (int j = 0; j < nColB; j++) { bp[i][j] -= bp[col][j] * lu[i][col]; } } } RealMatrixImpl outMat = new RealMatrixImpl(bp); return outMat; } /** * Computes a new * <a href="http://www.math.gatech.edu/~bourbaki/math2601/Web-notes/2num.pdf"> * LU decompostion</a> for this matrix, storing the result for use by other methods. * <p> * <strong>Implementation Note</strong>:<br> * Uses <a href="http://www.damtp.cam.ac.uk/user/fdl/people/sd/lectures/nummeth98/linear.htm"> * Crout's algortithm</a>, with partial pivoting. * <p> * <strong>Usage Note</strong>:<br> * This method should rarely be invoked directly. Its only use is * to force recomputation of the LU decomposition when changes have been * made to the underlying data using direct array references. Changes * made using setXxx methods will trigger recomputation when needed * automatically. * * @throws InvalidMatrixException if the matrix is non-square or singular. */ public void luDecompose() throws InvalidMatrixException { int nRows = this.getRowDimension(); int nCols = this.getColumnDimension(); if (nRows != nCols) { throw new InvalidMatrixException("LU decomposition requires that the matrix be square."); } lu = this.getData(); // Initialize permutation array and parity permutation = new int[nRows]; for (int row = 0; row < nRows; row++) { permutation[row] = row; } parity = 1; // Loop over columns for (int col = 0; col < nCols; col++) { double sum = 0; // upper for (int row = 0; row < col; row++) { sum = lu[row][col]; for (int i = 0; i < row; i++) { sum -= lu[row][i] * lu[i][col]; } lu[row][col] = sum; } // lower int max = col; // permutation row double largest = 0d; for (int row = col; row < nRows; row++) { sum = lu[row][col]; for (int i = 0; i < col; i++) { sum -= lu[row][i] * lu[i][col]; } lu[row][col] = sum; // maintain best permutation choice if (Math.abs(sum) > largest) { largest = Math.abs(sum); max = row; } } // Singularity check if (Math.abs(lu[max][col]) < TOO_SMALL) { lu = null; throw new InvalidMatrixException("matrix is singular"); } // Pivot if necessary if (max != col) { double tmp = 0; for (int i = 0; i < nCols; i++) { tmp = lu[max][i]; lu[max][i] = lu[col][i]; lu[col][i] = tmp; } int temp = permutation[max]; permutation[max] = permutation[col]; permutation[col] = temp; parity = -parity; } //Divide the lower elements by the "winning" diagonal elt. for (int row = col + 1; row < nRows; row++) { lu[row][col] /= lu[col][col]; } } } /** * Gives the means of each row of the matrix. * @return the row means */ public double[] rowMeans() { int rowCount = this.getRowDimension(); int columnCount = this.getColumnDimension(); double[] means = new double[rowCount]; for (int x = 0; x<rowCount; x++) { for (int y = 0; y<columnCount; y++) { means[x] += data[x][y]/columnCount; } } return means; } /** * Gives the means of each colums of the matrix. * @return the column means */ public double[] columnMeans() { int rowCount = this.getRowDimension(); int columnCount = this.getColumnDimension(); double[] means = new double[columnCount]; for (int x = 0; x<rowCount; x++) { for (int y = 0; y<columnCount; y++) { means[y] += data[x][y]/rowCount; } } return means; } /** * Get a submatrix. Rows and columns are indicated counting from 1 to n, NOT from 0 to n-1. * @param startRow Initial row index * @param endRow Final row index * @param startColumn Initial column index * @param endColumn Final column index * @return The subMatrix containing the data of the specified rows and columns * @exception MatrixIndexException matrix dimension mismatch */ public RealMatrix getSubMatrix (int startRow, int endRow, int startColumn, int endColumn) throws MatrixIndexException { RealMatrixImpl subMatrix = new RealMatrixImpl(endRow-startRow+1,endColumn-startColumn+1); double[][] subMatrixData = subMatrix.getDataRef(); try { for (int i = startRow; i < endRow; i++) { for (int j = startColumn; j < endColumn; j++) { subMatrixData[i-startRow][j-startColumn] = data[i][j]; } } } catch(ArrayIndexOutOfBoundsException e) { throw new MatrixIndexException("matrix dimension mismatch"); } return subMatrix; } /** * Get a submatrix. Rows and columns are indicated counting from 1 to n, NOT from 0 to n-1. * @param rows Array of row indices. * @param columns Array of column indices. * @return The subMatrix containing the data of the specified rows and columns * @exception MatrixIndexException matrix dimension mismatch */ public RealMatrix getSubMatrix (int[] rows, int[] columns) throws MatrixIndexException { RealMatrixImpl subMatrix = new RealMatrixImpl(rows.length,columns.length); double[][] subMatrixData = subMatrix.getDataRef(); try { for (int i = 0; i < rows.length; i++) { for (int j = 0; j < columns.length; j++) { subMatrixData[i][j] = data[rows[i]][columns[j]]; } } } catch(ArrayIndexOutOfBoundsException e) { throw new MatrixIndexException("matrix dimension mismatch"); } return subMatrix ; } /** * Get a submatrix. Rows and columns are indicated counting from 1 to n, NOT from 0 to n-1. * @param startRow Initial row index * @param endRow Final row index * @param columns Array of column indices. * @return The subMatrix containing the data of the specified rows and columns * @exception MatrixIndexException matrix dimension mismatch */ public RealMatrix getSubMatrix (int startRow, int endRow, int[] columns) throws MatrixIndexException { RealMatrixImpl subMatrix = new RealMatrixImpl(endRow-startRow+1,columns.length); double[][] subMatrixData = subMatrix.getDataRef(); try { for (int i = startRow; i < endRow; i++) { for (int j = 0; j < columns.length; j++) { subMatrixData[i-startRow][j] = data[i][columns[j]]; } } } catch(ArrayIndexOutOfBoundsException e) { throw new MatrixIndexException("matrix dimension mismatch"); } return subMatrix; } /** * Get a submatrix. Rows and columns are indicated counting from 1 to n, NOT from 0 to n-1. * @param rows Array of row indices. * @param startColumn Initial column index * @param endColumn Final column index * @return The subMatrix containing the data of the specified rows and columns * @exception MatrixIndexException matrix dimension mismatch */ public RealMatrix getSubMatrix (int[] rows, int startColumn, int endColumn) throws MatrixIndexException { RealMatrixImpl subMatrix = new RealMatrixImpl(rows.length,endColumn-startColumn+1); double[][] subMatrixData = subMatrix.getDataRef(); try { for (int i = 0; i < rows.length; i++) { for (int j = startColumn; j <= endColumn; j++) { subMatrixData[i][j-startColumn] = data[rows[i]][j]; //System.out.println(""+rows[i]+", "+j+": "+data[rows[i]][j]); } } } catch(ArrayIndexOutOfBoundsException e) { throw new MatrixIndexException("matrix dimension mismatch"); } return subMatrix; } /** * * @see java.lang.Object#toString() */ public String toString() { StringBuffer res = new StringBuffer(); res.append("RealMatrixImpl{"); for (int i = 0; i < data.length; i++) { if (i > 0) res.append(","); res.append("{"); for (int j = 0; j < data[0].length; j++) { if (j > 0) res.append(","); res.append(data[i][j]); } //for res.append("}"); } //for res.append("}"); return res.toString(); } //toString //------------------------ Protected methods /** * Returns <code>dimension x dimension</code> identity matrix. * * @param dimension dimension of identity matrix to generate * @return identity matrix */ protected RealMatrix getIdentity(int dimension) { RealMatrixImpl out = new RealMatrixImpl(dimension, dimension); double[][] d = out.getDataRef(); for (int row = 0; row < dimension; row++) { for (int col = 0; col < dimension; col++) { d[row][col] = row == col ? 1d : 0d; } } return out; } /** * Returns the LU decomposition as a RealMatrix. * Returns a fresh copy of the cached LU matrix if this has been computed; * otherwise the composition is computed and cached for use by other methods. * Since a copy is returned in either case, changes to the returned matrix do not * affect the LU decomposition property. * <p> * The matrix returned is a compact representation of the LU decomposition. * Elements below the main diagonal correspond to entries of the "L" matrix; * elements on and above the main diagonal correspond to entries of the "U" * matrix. * <p> * Example: <pre> * * Returned matrix L U * 2 3 1 1 0 0 2 3 1 * 5 4 6 5 1 0 0 4 6 * 1 7 8 1 7 1 0 0 8 * </pre> * * The L and U matrices satisfy the matrix equation LU = permuteRows(this), <br> * where permuteRows reorders the rows of the matrix to follow the order determined * by the <a href=#getPermutation()>permutation</a> property. * * @return LU decomposition matrix * @throws InvalidMatrixException if the matrix is non-square or singular. */ protected RealMatrix getLUMatrix() throws InvalidMatrixException { if (lu == null) { luDecompose(); } return new RealMatrixImpl(lu); } /** * Returns the permutation associated with the lu decomposition. * The entries of the array represent a permutation of the numbers 0, ... , nRows - 1. * <p> * Example: * permutation = [1, 2, 0] means current 2nd row is first, current third row is second * and current first row is last. * <p> * Returns a fresh copy of the array. * * @return the permutation */ protected int[] getPermutation() { int[] out = new int[permutation.length]; System.arraycopy(permutation, 0, out, 0, permutation.length); return out; } //------------------------ Private methods /** * Returns a fresh copy of the underlying data array. * * @return a copy of the underlying data array. */ private double[][] copyOut() { int nRows = this.getRowDimension(); double[][] out = new double[nRows][this.getColumnDimension()]; // can't copy 2-d array in one shot, otherwise get row references for (int i = 0; i < nRows; i++) { System.arraycopy(data[i], 0, out[i], 0, data[i].length); } return out; } /** * Replaces data with a fresh copy of the input array. * * @param in data to copy in */ private void copyIn(double[][] in) { int nRows = in.length; int nCols = in[0].length; data = new double[nRows][nCols]; System.arraycopy(in, 0, data, 0, in.length); for (int i = 0; i < nRows; i++) { System.arraycopy(in[i], 0, data[i], 0, nCols); } lu = null; } /** * Tests a given coordinate as being valid or invalid * * @param row the row index. * @param col the column index. * @return true if the coordinate is with the current dimensions */ private boolean isValidCoordinate(int row, int col) { int nRows = this.getRowDimension(); int nCols = this.getColumnDimension(); return !(row < 0 || row > (nRows-1) || col < 0 || col > (nCols-1)); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
