[ https://issues.apache.org/jira/browse/MATH-122?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Henri Yandell reopened MATH-122: -------------------------------- > New methods in RealMatrixImpl and changing indexing > --------------------------------------------------- > > Key: MATH-122 > URL: https://issues.apache.org/jira/browse/MATH-122 > Project: Commons Math > Issue Type: Improvement > Affects Versions: 1.0 Alpha > Environment: Operating System: All > Platform: All > Reporter: Kim van der Linde > Priority: Minor > > 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)); > } > } -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]