You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2008/06/01 18:22:20 UTC

svn commit: r662241 [1/2] - in /commons/proper/math/branches/MATH_2_0/src: java/org/apache/commons/math/linear/ site/xdoc/ test/org/apache/commons/math/linear/

Author: luc
Date: Sun Jun  1 09:22:19 2008
New Revision: 662241

URL: http://svn.apache.org/viewvc?rev=662241&view=rev
Log:
Improved linear RealMatrixImpl and BigMatrixImpl performances.
The main changes are the following ones:
 - use directly the storage array when possible for
   diadic operations (add, subtract, multiply), as
   suggested by Phil, this avoids the cost of the
   generic getEntry method
 - replaced custom indices checks by simple use of
   the JVM checks and ArrayIndexOutOfBoundException
 - put row arrays reference in local variables to
   avoid multiple checks in double loops
 - use final variables where possible
 - removed unneeded array copying
 - added a constructor to build a matrix from an
   array without copying it where it makes sense

The speed gain is about 3X for multiplication. Performances
for this operation are now on par with Jama.

Modified:
    commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/BigMatrixImpl.java
    commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/MatrixUtils.java
    commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/RealMatrixImpl.java
    commons/proper/math/branches/MATH_2_0/src/site/xdoc/changes.xml
    commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/BigMatrixImplTest.java
    commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/MatrixUtilsTest.java
    commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/QRDecompositionImplTest.java
    commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java

Modified: commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/BigMatrixImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/BigMatrixImpl.java?rev=662241&r1=662240&r2=662241&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/BigMatrixImpl.java (original)
+++ commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/BigMatrixImpl.java Sun Jun  1 09:22:19 2008
@@ -106,8 +106,9 @@
     /**
      * Create a new BigMatrix using <code>d</code> as the underlying
      * data array.
-     * <p>
-     * The input array is copied, not referenced.</p>
+     * <p>The input array is copied, not referenced. This constructor has
+     * the same effect as calling {@link #BigMatrixImpl(BigDecimal[][], boolean)}
+     * with the second argument set to <code>true</code>.</p>
      *
      * @param d data for new matrix
      * @throws IllegalArgumentException if <code>d</code> is not rectangular
@@ -118,12 +119,52 @@
         this.copyIn(d);
         lu = null;
     }
-    
+
+    /**
+     * Create a new BigMatrix using the input array as the underlying
+     * data array.
+     * <p>If an array is built specially in order to be embedded in a
+     * BigMatrix and not used directly, the <code>copyArray</code> may be
+     * set to <code>false</code. This will prevent the copying and improve
+     * performance as no new array will be built and no data will be copied.</p>
+     * @param d data for new matrix
+     * @param copyArray if true, the input array will be copied, otherwise
+     * it will be referenced
+     * @throws IllegalArgumentException if <code>d</code> is not rectangular
+     *  (not all rows have the same length) or empty
+     * @throws NullPointerException if <code>d</code> is null
+     * @see #BigMatrix(BigDecimal[][])
+     */
+    public BigMatrixImpl(BigDecimal[][] d, boolean copyArray) {
+        if (copyArray) {
+            copyIn(d);
+        } else {
+            if (d == null) {
+                throw new NullPointerException();
+            }   
+            final int nRows = d.length;
+            if (nRows == 0) {
+                throw new IllegalArgumentException("Matrix must have at least one row."); 
+            }
+            final int nCols = d[0].length;
+            if (nCols == 0) {
+                throw new IllegalArgumentException("Matrix must have at least one column."); 
+            }
+            for (int r = 1; r < nRows; r++) {
+                if (d[r].length != nCols) {
+                    throw new IllegalArgumentException("All input rows must have the same length.");
+                }
+            }       
+            data = d;
+        }
+        lu = null;
+    }
+
     /**
      * Create a new BigMatrix using <code>d</code> as the underlying
      * data array.
-     * <p>
-     * The input array is copied, not referenced.</p>
+     * <p>Since the underlying array will hold <code>BigDecimal</code>
+     * instances, it will be created.</p>
      *
      * @param d data for new matrix
      * @throws IllegalArgumentException if <code>d</code> is not rectangular
@@ -131,12 +172,12 @@
      * @throws NullPointerException if <code>d</code> is null
      */
     public BigMatrixImpl(double[][] d) {
-        int nRows = d.length;
+        final int nRows = d.length;
         if (nRows == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one row."); 
         }
-        int nCols = d[0].length;
+        final int nCols = d[0].length;
         if (nCols == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one column."); 
@@ -161,12 +202,12 @@
      * @throws NullPointerException if <code>d</code> is null
      */
     public BigMatrixImpl(String[][] d) {
-        int nRows = d.length;
+        final int nRows = d.length;
         if (nRows == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one row."); 
         }
-        int nCols = d[0].length;
+        final int nCols = d[0].length;
         if (nCols == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one column."); 
@@ -191,7 +232,7 @@
      * @param v column vector holding data for new matrix
      */
     public BigMatrixImpl(BigDecimal[] v) {
-        int nRows = v.length;
+        final int nRows = v.length;
         data = new BigDecimal[nRows][1];
         for (int row = 0; row < nRows; row++) {
             data[row][0] = v[row];
@@ -204,7 +245,7 @@
      * @return  the cloned matrix
      */
     public BigMatrix copy() {
-        return new BigMatrixImpl(this.copyOut());
+        return new BigMatrixImpl(this.copyOut(), false);
     }
     
     /**
@@ -212,47 +253,107 @@
      *
      * @param m    matrix to be added
      * @return     this + m
-     * @exception  IllegalArgumentException if m is not the same size as this
+     * @throws  IllegalArgumentException if m is not the same size as this
      */
     public BigMatrix add(BigMatrix m) throws IllegalArgumentException {
-        if (this.getColumnDimension() != m.getColumnDimension() ||
-                this.getRowDimension() != m.getRowDimension()) {
+        try {
+            return add((BigMatrixImpl) m);
+        } catch (ClassCastException cce) {
+            final int rowCount    = getRowDimension();
+            final int columnCount = getColumnDimension();
+            if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
+                throw new IllegalArgumentException("matrix dimension mismatch");
+            }
+            final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
+            for (int row = 0; row < rowCount; row++) {
+                final BigDecimal[] dataRow    = data[row];
+                final BigDecimal[] outDataRow = outData[row];
+                for (int col = 0; col < columnCount; col++) {
+                    outDataRow[col] = dataRow[col].add(m.getEntry(row, col));
+                }  
+            }
+            return new BigMatrixImpl(outData, false);
+        }
+    }
+
+    /**
+     * 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 BigMatrixImpl add(BigMatrixImpl m) throws IllegalArgumentException {
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
             throw new IllegalArgumentException("matrix dimension mismatch");
         }
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
+        final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final BigDecimal[] dataRow    = data[row];
+            final BigDecimal[] mRow       = m.data[row];
+            final BigDecimal[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col].add(m.getEntry(row, col));
-            }
+                outDataRow[col] = dataRow[col].add(mRow[col]);
+            }  
         }
-        return new BigMatrixImpl(outData);
+        return new BigMatrixImpl(outData, false);
     }
-    
+
     /**
      * Compute  this minus <code>m</code>.
      *
      * @param m    matrix to be subtracted
      * @return     this + m
-     * @exception  IllegalArgumentException if m is not the same size as *this
+     * @throws  IllegalArgumentException if m is not the same size as this
      */
     public BigMatrix subtract(BigMatrix m) throws IllegalArgumentException {
-        if (this.getColumnDimension() != m.getColumnDimension() ||
-                this.getRowDimension() != m.getRowDimension()) {
+        try {
+            return subtract((BigMatrixImpl) m);
+        } catch (ClassCastException cce) {
+            final int rowCount    = getRowDimension();
+            final int columnCount = getColumnDimension();
+            if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
+                throw new IllegalArgumentException("matrix dimension mismatch");
+            }
+            final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
+            for (int row = 0; row < rowCount; row++) {
+                final BigDecimal[] dataRow    = data[row];
+                final BigDecimal[] outDataRow = outData[row];
+                for (int col = 0; col < columnCount; col++) {
+                    outDataRow[col] = dataRow[col].subtract(getEntry(row, col));
+                }  
+            }
+            return new BigMatrixImpl(outData, false);
+        }
+    }
+
+    /**
+     * 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 BigMatrixImpl subtract(BigMatrixImpl m) throws IllegalArgumentException {
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
             throw new IllegalArgumentException("matrix dimension mismatch");
         }
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
+        final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final BigDecimal[] dataRow    = data[row];
+            final BigDecimal[] mRow       = m.data[row];
+            final BigDecimal[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col].subtract(m.getEntry(row, col));
-            }
+                outDataRow[col] = dataRow[col].subtract(mRow[col]);
+            }  
         }
-        return new BigMatrixImpl(outData);
+        return new BigMatrixImpl(outData, false);
     }
-    
+
     /**
      * Returns the result of adding d to each entry of this.
      *
@@ -260,34 +361,38 @@
      * @return     d + this
      */
     public BigMatrix scalarAdd(BigDecimal d) {
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final BigDecimal[] dataRow    = data[row];
+            final BigDecimal[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col].add(d);
+                outDataRow[col] = dataRow[col].add(d);
             }
         }
-        return new BigMatrixImpl(outData);
+        return new BigMatrixImpl(outData, false);
     }
-    
+
     /**
-     * Returns the result multiplying each entry of this by <code>d</code>
+     * Returns the result of multiplying each entry of this by <code>d</code>
      * @param d  value to multiply all entries by
      * @return d * this
      */
     public BigMatrix scalarMultiply(BigDecimal d) {
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        final BigDecimal[][] outData = new BigDecimal[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final BigDecimal[] dataRow    = data[row];
+            final BigDecimal[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col].multiply(d);
+                outDataRow[col] = dataRow[col].multiply(d);
             }
         }
-        return new BigMatrixImpl(outData);
+        return new BigMatrixImpl(outData, false);
     }
-    
+
     /**
      * Returns the result of postmultiplying this by <code>m</code>.
      * @param m    matrix to postmultiply by
@@ -296,26 +401,60 @@
      *             if columnDimension(this) != rowDimension(m)
      */
     public BigMatrix multiply(BigMatrix m) throws IllegalArgumentException {
+        try {
+            return multiply((BigMatrixImpl) m);
+        } catch (ClassCastException cce) {
+            if (this.getColumnDimension() != m.getRowDimension()) {
+                throw new IllegalArgumentException("Matrices are not multiplication compatible.");
+            }
+            final int nRows = this.getRowDimension();
+            final int nCols = m.getColumnDimension();
+            final int nSum = this.getColumnDimension();
+            final BigDecimal[][] outData = new BigDecimal[nRows][nCols];
+            for (int row = 0; row < nRows; row++) {
+                final BigDecimal[] dataRow    = data[row];
+                final BigDecimal[] outDataRow = outData[row];
+                for (int col = 0; col < nCols; col++) {
+                    BigDecimal sum = ZERO;
+                    for (int i = 0; i < nSum; i++) {
+                        sum = sum.add(dataRow[i].multiply(m.getEntry(i, col)));
+                    }
+                    outDataRow[col] = sum;
+                }
+            }
+            return new BigMatrixImpl(outData, false);
+        }
+    }
+
+    /**
+     * 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 BigMatrixImpl multiply(BigMatrixImpl 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();
-        BigDecimal[][] outData = new BigDecimal[nRows][nCols];
-        BigDecimal sum = ZERO;
+        final int nRows = this.getRowDimension();
+        final int nCols = m.getColumnDimension();
+        final int nSum = this.getColumnDimension();
+        final BigDecimal[][] outData = new BigDecimal[nRows][nCols];
         for (int row = 0; row < nRows; row++) {
+            final BigDecimal[] dataRow    = data[row];
+            final BigDecimal[] outDataRow = outData[row];
             for (int col = 0; col < nCols; col++) {
-                sum = ZERO;
+                BigDecimal sum = ZERO;
                 for (int i = 0; i < nSum; i++) {
-                    sum = sum.add(data[row][i].multiply(m.getEntry(i, col)));
+                    sum = sum.add(dataRow[i].multiply(m.data[i][col]));
                 }
-                outData[row][col] = sum;
+                outDataRow[col] = sum;
             }
-        }
-        return new BigMatrixImpl(outData);
+        }            
+        return new BigMatrixImpl(outData, false);
     }
-    
+
     /**
      * Returns the result premultiplying this by <code>m</code>.
      * @param m    matrix to premultiply by
@@ -326,7 +465,7 @@
     public BigMatrix preMultiply(BigMatrix m) throws IllegalArgumentException {
         return m.multiply(this);
     }
-    
+
     /**
      * Returns matrix entries as a two-dimensional array.
      * <p>
@@ -347,11 +486,11 @@
      * @return    2-dimensional array of entries
      */
     public double[][] getDataAsDoubleArray() {
-        int nRows = getRowDimension();
-        int nCols = getColumnDimension();
-        double d[][] = new double[nRows][nCols];
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
+        final double d[][] = new double[nRows][nCols];
         for (int i = 0; i < nRows; i++) {
-            for (int j=0; j<nCols;j++) {
+            for (int j = 0; j < nCols; j++) {
                 d[i][j] = data[i][j].doubleValue();
             }
         }
@@ -437,23 +576,23 @@
      *         specified rows and columns
      * @exception MatrixIndexException if row or column selections are not valid
      */
-    public BigMatrix getSubMatrix(int startRow, int endRow, int startColumn,
-            int endColumn) throws MatrixIndexException {
+    public BigMatrix getSubMatrix(int startRow, int endRow,
+                                  int startColumn, int endColumn)
+        throws MatrixIndexException {
         if (startRow < 0 || startRow > endRow || endRow > data.length ||
                 startColumn < 0 || startColumn > endColumn ||
                 endColumn > data[0].length ) {
             throw new MatrixIndexException(
             "invalid row or column index selection");
         }
-        BigMatrixImpl subMatrix = new BigMatrixImpl(endRow - startRow+1,
-                endColumn - startColumn+1);
-        BigDecimal[][] subMatrixData = subMatrix.getDataRef();
+        final BigDecimal[][] subMatrixData =
+            new BigDecimal[endRow - startRow + 1][endColumn - startColumn + 1];
         for (int i = startRow; i <= endRow; i++) {
-            for (int j = startColumn; j <= endColumn; j++) {
-                subMatrixData[i - startRow][j - startColumn] = data[i][j];
-            }
+            System.arraycopy(data[i], startColumn,
+                    subMatrixData[i - startRow], 0,
+                    endColumn - startColumn + 1);
         }
-        return subMatrix;
+        return new BigMatrixImpl(subMatrixData, false);
     }
     
     /**
@@ -468,25 +607,26 @@
      *     are not valid
      */
     public BigMatrix getSubMatrix(int[] selectedRows, int[] selectedColumns)
-    throws MatrixIndexException {
+        throws MatrixIndexException {
         if (selectedRows.length * selectedColumns.length == 0) {
             throw new MatrixIndexException(
             "selected row and column index arrays must be non-empty");
         }
-        BigMatrixImpl subMatrix = new BigMatrixImpl(selectedRows.length,
-                selectedColumns.length);
-        BigDecimal[][] subMatrixData = subMatrix.getDataRef();
+        final BigDecimal[][] subMatrixData =
+            new BigDecimal[selectedRows.length][selectedColumns.length];
         try  {
             for (int i = 0; i < selectedRows.length; i++) {
+                final BigDecimal[] subI = subMatrixData[i];
+                final BigDecimal[] dataSelectedI = data[selectedRows[i]];
                 for (int j = 0; j < selectedColumns.length; j++) {
-                    subMatrixData[i][j] = data[selectedRows[i]][selectedColumns[j]];
+                    subI[j] = dataSelectedI[selectedColumns[j]];
                 }
             }
         }
         catch (ArrayIndexOutOfBoundsException e) {
             throw new MatrixIndexException("matrix dimension mismatch");
         }
-        return subMatrix;
+        return new BigMatrixImpl(subMatrixData, false);
     } 
     
     /**
@@ -522,12 +662,12 @@
             throw new MatrixIndexException
             ("invalid row or column index selection");          
         }
-        int nRows = subMatrix.length;
+        final int nRows = subMatrix.length;
         if (nRows == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one row."); 
         }
-        int nCols = subMatrix[0].length;
+        final int nCols = subMatrix[0].length;
         if (nCols == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one column."); 
@@ -566,10 +706,10 @@
         if ( !isValidCoordinate( row, 0)) {
             throw new MatrixIndexException("illegal row argument");
         }
-        int ncols = this.getColumnDimension();
-        BigDecimal[][] out = new BigDecimal[1][ncols]; 
+        final int ncols = this.getColumnDimension();
+        final BigDecimal[][] out = new BigDecimal[1][ncols]; 
         System.arraycopy(data[row], 0, out[0], 0, ncols);
-        return new BigMatrixImpl(out);
+        return new BigMatrixImpl(out, false);
     } 
     
     /**
@@ -584,12 +724,12 @@
         if ( !isValidCoordinate( 0, column)) {
             throw new MatrixIndexException("illegal column argument");
         }
-        int nRows = this.getRowDimension();
-        BigDecimal[][] out = new BigDecimal[nRows][1]; 
+        final int nRows = this.getRowDimension();
+        final BigDecimal[][] out = new BigDecimal[nRows][1]; 
         for (int row = 0; row < nRows; row++) {
             out[row][0] = data[row][column];
         }
-        return new BigMatrixImpl(out);
+        return new BigMatrixImpl(out, false);
     }
     
     /**
@@ -606,8 +746,8 @@
         if ( !isValidCoordinate( row, 0 ) ) {
             throw new MatrixIndexException("illegal row argument");
         }
-        int ncols = this.getColumnDimension();
-        BigDecimal[] out = new BigDecimal[ncols];
+        final int ncols = this.getColumnDimension();
+        final BigDecimal[] out = new BigDecimal[ncols];
         System.arraycopy(data[row], 0, out, 0, ncols);
         return out;
     }
@@ -627,8 +767,8 @@
         if ( !isValidCoordinate( row, 0 ) ) {
             throw new MatrixIndexException("illegal row argument");
         }
-        int ncols = this.getColumnDimension();
-        double[] out = new double[ncols];
+        final int ncols = this.getColumnDimension();
+        final double[] out = new double[ncols];
         for (int i=0;i<ncols;i++) {
             out[i] = data[row][i].doubleValue();
         }
@@ -649,8 +789,8 @@
         if ( !isValidCoordinate(0, col) ) {
             throw new MatrixIndexException("illegal column argument");
         }
-        int nRows = this.getRowDimension();
-        BigDecimal[] out = new BigDecimal[nRows];
+        final int nRows = this.getRowDimension();
+        final BigDecimal[] out = new BigDecimal[nRows];
         for (int i = 0; i < nRows; i++) {
             out[i] = data[i][col];
         }
@@ -672,8 +812,8 @@
         if ( !isValidCoordinate( 0, col ) ) {
             throw new MatrixIndexException("illegal column argument");
         }
-        int nrows = this.getRowDimension();
-        double[] out = new double[nrows];
+        final int nrows = this.getRowDimension();
+        final double[] out = new double[nrows];
         for (int i=0;i<nrows;i++) {
             out[i] = data[i][col].doubleValue();
         }
@@ -697,10 +837,11 @@
      */
     public BigDecimal getEntry(int row, int column)
     throws MatrixIndexException {
-        if (!isValidCoordinate(row,column)) {
+        try {
+            return data[row][column];
+        } catch (ArrayIndexOutOfBoundsException e) {
             throw new MatrixIndexException("matrix entry does not exist");
         }
-        return data[row][column];
     }
     
     /**
@@ -729,16 +870,16 @@
      * @return transpose matrix
      */
     public BigMatrix transpose() {
-        int nRows = this.getRowDimension();
-        int nCols = this.getColumnDimension();
-        BigMatrixImpl out = new BigMatrixImpl(nCols, nRows);
-        BigDecimal[][] outData = out.getDataRef();
+        final int nRows = this.getRowDimension();
+        final int nCols = this.getColumnDimension();
+        final BigDecimal[][] outData = new BigDecimal[nCols][nRows];
         for (int row = 0; row < nRows; row++) {
+            final BigDecimal[] dataRow = data[row];
             for (int col = 0; col < nCols; col++) {
-                outData[col][row] = data[row][col];
+                outData[col][row] = dataRow[col];
             }
         }
-        return out;
+        return new BigMatrixImpl(outData, false);
     }
     
     /**
@@ -748,8 +889,7 @@
      * @throws InvalidMatrixException if this is not invertible
      */
     public BigMatrix inverse() throws InvalidMatrixException {
-        return solve(MatrixUtils.createBigIdentityMatrix
-                (this.getRowDimension()));
+        return solve(MatrixUtils.createBigIdentityMatrix(getRowDimension()));
     }
     
     /**
@@ -846,9 +986,9 @@
         if (v.length != this.getColumnDimension()) {
             throw new IllegalArgumentException("vector has wrong length");
         }
-        int nRows = this.getRowDimension();
-        int nCols = this.getColumnDimension();
-        BigDecimal[] out = new BigDecimal[v.length];
+        final int nRows = this.getRowDimension();
+        final int nCols = this.getColumnDimension();
+        final BigDecimal[] out = new BigDecimal[v.length];
         for (int row = 0; row < nRows; row++) {
             BigDecimal sum = ZERO;
             for (int i = 0; i < nCols; i++) {
@@ -867,8 +1007,8 @@
      * @throws IllegalArgumentException if columnDimension != v.size()
      */
     public BigDecimal[] operate(double[] v) throws IllegalArgumentException {
-        BigDecimal bd[] = new BigDecimal[v.length];
-        for (int i=0;i<bd.length;i++) {
+        final BigDecimal bd[] = new BigDecimal[v.length];
+        for (int i = 0; i < bd.length; i++) {
             bd[i] = new BigDecimal(v[i]);
         }
         return operate(bd);
@@ -882,12 +1022,12 @@
      * @throws IllegalArgumentException if rowDimension != v.size()
      */
     public BigDecimal[] preMultiply(BigDecimal[] v) throws IllegalArgumentException {
-        int nRows = this.getRowDimension();
+        final int nRows = this.getRowDimension();
         if (v.length != nRows) {
             throw new IllegalArgumentException("vector has wrong length");
         }
-        int nCols = this.getColumnDimension();
-        BigDecimal[] out = new BigDecimal[nCols];
+        final int nCols = this.getColumnDimension();
+        final BigDecimal[] out = new BigDecimal[nCols];
         for (int col = 0; col < nCols; col++) {
             BigDecimal sum = ZERO;
             for (int i = 0; i < nRows; i++) {
@@ -910,13 +1050,13 @@
      * @throws InvalidMatrixException if this matrix is not square or is singular
      */
     public BigDecimal[] solve(BigDecimal[] b) throws IllegalArgumentException, InvalidMatrixException {
-        int nRows = this.getRowDimension();
+        final int nRows = this.getRowDimension();
         if (b.length != nRows) {
             throw new IllegalArgumentException("constant vector has wrong length");
         }
-        BigMatrix bMatrix = new BigMatrixImpl(b);
-        BigDecimal[][] solution = ((BigMatrixImpl) (solve(bMatrix))).getDataRef();
-        BigDecimal[] out = new BigDecimal[nRows];
+        final BigMatrix bMatrix = new BigMatrixImpl(b);
+        final BigDecimal[][] solution = ((BigMatrixImpl) (solve(bMatrix))).getDataRef();
+        final BigDecimal[] out = new BigDecimal[nRows];
         for (int row = 0; row < nRows; row++) {
             out[row] = solution[row][0];
         }
@@ -935,8 +1075,8 @@
      * @throws InvalidMatrixException if this matrix is not square or is singular
      */
     public BigDecimal[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException {
-        BigDecimal bd[] = new BigDecimal[b.length];
-        for (int i=0;i<bd.length;i++) {
+        final BigDecimal bd[] = new BigDecimal[b.length];
+        for (int i = 0; i < bd.length; i++) {
             bd[i] = new BigDecimal(b[i]);
         }
         return solve(bd);
@@ -964,41 +1104,48 @@
             throw new InvalidMatrixException("Matrix is singular.");
         }
         
-        int nCol = this.getColumnDimension();
-        int nColB = b.getColumnDimension();
-        int nRowB = b.getRowDimension();
+        final int nCol = this.getColumnDimension();
+        final int nColB = b.getColumnDimension();
+        final int nRowB = b.getRowDimension();
         
         // Apply permutations to b
-        BigDecimal[][] bp = new BigDecimal[nRowB][nColB];
+        final BigDecimal[][] bp = new BigDecimal[nRowB][nColB];
         for (int row = 0; row < nRowB; row++) {
+            final BigDecimal[] bpRow = bp[row];
             for (int col = 0; col < nColB; col++) {
-                bp[row][col] = b.getEntry(permutation[row], col);
+                bpRow[col] = b.getEntry(permutation[row], col);
             }
         }
         
         // Solve LY = b
         for (int col = 0; col < nCol; col++) {
             for (int i = col + 1; i < nCol; i++) {
+                final BigDecimal[] bpI = bp[i];
+                final BigDecimal[] luI = lu[i];
                 for (int j = 0; j < nColB; j++) {
-                    bp[i][j] = bp[i][j].subtract(bp[col][j].multiply(lu[i][col]));
+                    bpI[j] = bpI[j].subtract(bp[col][j].multiply(luI[col]));
                 }
             }
         }
         
         // Solve UX = Y
         for (int col = nCol - 1; col >= 0; col--) {
+            final BigDecimal[] bpCol = bp[col];
+            final BigDecimal luDiag = lu[col][col];
             for (int j = 0; j < nColB; j++) {
-                bp[col][j] = bp[col][j].divide(lu[col][col], scale, roundingMode);
+                bpCol[j] = bpCol[j].divide(luDiag, scale, roundingMode);
             }
             for (int i = 0; i < col; i++) {
+                final BigDecimal[] bpI = bp[i];
+                final BigDecimal[] luI = lu[i];
                 for (int j = 0; j < nColB; j++) {
-                    bp[i][j] = bp[i][j].subtract(bp[col][j].multiply(lu[i][col]));
+                    bpI[j] = bpI[j].subtract(bp[col][j].multiply(luI[col]));
                 }
             }
         }
-        
-        BigMatrixImpl outMat = new BigMatrixImpl(bp);
-        return outMat;
+
+        return new BigMatrixImpl(bp, false);
+
     }
     
     /**
@@ -1021,8 +1168,8 @@
      */
     public void luDecompose() throws InvalidMatrixException {
         
-        int nRows = this.getRowDimension();
-        int nCols = this.getColumnDimension();
+        final int nRows = this.getRowDimension();
+        final int nCols = this.getColumnDimension();
         if (nRows != nCols) {
             throw new InvalidMatrixException("LU decomposition requires that the matrix be square.");
         }
@@ -1042,22 +1189,24 @@
             
             // upper
             for (int row = 0; row < col; row++) {
-                sum = lu[row][col];
+                final BigDecimal[] luRow = lu[row];
+                sum = luRow[col];
                 for (int i = 0; i < row; i++) {
-                    sum = sum.subtract(lu[row][i].multiply(lu[i][col]));
+                    sum = sum.subtract(luRow[i].multiply(lu[i][col]));
                 }
-                lu[row][col] = sum;
+                luRow[col] = sum;
             }
             
             // lower
             int max = col; // permutation row
             BigDecimal largest = ZERO;
             for (int row = col; row < nRows; row++) {
-                sum = lu[row][col];
+                final BigDecimal[] luRow = lu[row];
+                sum = luRow[col];
                 for (int i = 0; i < col; i++) {
-                    sum = sum.subtract(lu[row][i].multiply(lu[i][col]));
+                    sum = sum.subtract(luRow[i].multiply(lu[i][col]));
                 }
-                lu[row][col] = sum;
+                luRow[col] = sum;
                 
                 // maintain best permutation choice
                 if (sum.abs().compareTo(largest) == 1) {
@@ -1086,9 +1235,11 @@
                 parity = -parity;
             }
             
-            //Divide the lower elements by the "winning" diagonal elt.
+            // Divide the lower elements by the "winning" diagonal elt.
+            final BigDecimal luDiag = lu[col][col];
             for (int row = col + 1; row < nRows; row++) {
-                lu[row][col] = lu[row][col].divide(lu[col][col], scale, roundingMode);
+                final BigDecimal[] luRow = lu[row];
+                luRow[col] = luRow[col].divide(luDiag, scale, roundingMode);
             }
             
         }
@@ -1104,12 +1255,14 @@
         res.append("BigMatrixImpl{");
         if (data != null) {
             for (int i = 0; i < data.length; i++) {
-                if (i > 0)
+                if (i > 0) {
                     res.append(",");
+                }
                 res.append("{");
                 for (int j = 0; j < data[0].length; j++) {
-                    if (j > 0)
+                    if (j > 0) {
                         res.append(",");
+                    }
                     res.append(data[i][j]);
                 } 
                 res.append("}");
@@ -1135,15 +1288,16 @@
         if (object instanceof BigMatrixImpl == false) {
             return false;
         }
-        BigMatrix m = (BigMatrix) object;
-        int nRows = getRowDimension();
-        int nCols = getColumnDimension();
+        final BigMatrix m = (BigMatrix) object;
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
         if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
             return false;
         }
         for (int row = 0; row < nRows; row++) {
+            final BigDecimal[] dataRow = data[row];
             for (int col = 0; col < nCols; col++) {
-                if (!data[row][col].equals(m.getEntry(row, col))) {
+                if (!dataRow[col].equals(m.getEntry(row, col))) {
                     return false;
                 }
             }
@@ -1158,14 +1312,15 @@
      */
     public int hashCode() {
         int ret = 7;
-        int nRows = getRowDimension();
-        int nCols = getColumnDimension();
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
         ret = ret * 31 + nRows;
         ret = ret * 31 + nCols;
         for (int row = 0; row < nRows; row++) {
+            final BigDecimal[] dataRow = data[row];
             for (int col = 0; col < nCols; col++) {
                 ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * 
-                data[row][col].hashCode();
+                dataRow[col].hashCode();
             }
         }   
         return ret;
@@ -1220,7 +1375,7 @@
      * @return the permutation
      */
     protected int[] getPermutation() {
-        int[] out = new int[permutation.length];
+        final int[] out = new int[permutation.length];
         System.arraycopy(permutation, 0, out, 0, permutation.length);
         return out;
     }
@@ -1233,8 +1388,8 @@
      * @return a copy of the underlying data array.
      */
     private BigDecimal[][] copyOut() {
-        int nRows = this.getRowDimension();
-        BigDecimal[][] out = new BigDecimal[nRows][this.getColumnDimension()];
+        final int nRows = this.getRowDimension();
+        final BigDecimal[][] out = new BigDecimal[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);
@@ -1262,12 +1417,14 @@
      * @param in data to copy in
      */
     private void copyIn(double[][] in) {
-        int nRows = in.length;
-        int nCols = in[0].length;
+        final int nRows = in.length;
+        final int nCols = in[0].length;
         data = new BigDecimal[nRows][nCols];
         for (int i = 0; i < nRows; i++) {
-            for (int j=0; j < nCols; j++) {
-                data[i][j] = new BigDecimal(in[i][j]);
+            final BigDecimal[] dataI = data[i];
+            final double[] inI = in[i];
+            for (int j = 0; j < nCols; j++) {
+                dataI[j] = new BigDecimal(inI[j]);
             }
         }
         lu = null;
@@ -1280,12 +1437,14 @@
      * @param in data to copy in
      */
     private void copyIn(String[][] in) {
-        int nRows = in.length;
-        int nCols = in[0].length;
+        final int nRows = in.length;
+        final int nCols = in[0].length;
         data = new BigDecimal[nRows][nCols];
         for (int i = 0; i < nRows; i++) {
-            for (int j=0; j < nCols; j++) {
-                data[i][j] = new BigDecimal(in[i][j]);
+            final BigDecimal[] dataI = data[i];
+            final String[] inI = in[i];
+            for (int j = 0; j < nCols; j++) {
+                dataI[j] = new BigDecimal(inI[j]);
             }
         }
         lu = null;
@@ -1299,9 +1458,8 @@
      * @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();
-        
+        final int nRows = this.getRowDimension();
+        final int nCols = this.getColumnDimension();
         return !(row < 0 || row >= nRows || col < 0 || col >= nCols);
     }
     

Modified: commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/MatrixUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/MatrixUtils.java?rev=662241&r1=662240&r2=662241&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/MatrixUtils.java (original)
+++ commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/MatrixUtils.java Sun Jun  1 09:22:19 2008
@@ -18,6 +18,7 @@
 package org.apache.commons.math.linear;
 
 import java.math.BigDecimal;
+import java.util.Arrays;
 
 /**
  * A collection of static methods that operate on or return matrices.
@@ -41,12 +42,33 @@
      * @return  RealMatrix containing the values of the array
      * @throws IllegalArgumentException if <code>data</code> is not rectangular
      *  (not all rows have the same length) or empty
-     * @throws NullPointerException if data is null
+     * @throws NullPointerException if <code>data</code> is null
+     * @see #createRealMatrix(double[][], boolean)
      */
     public static RealMatrix createRealMatrix(double[][] data) {
         return new RealMatrixImpl(data);
     }
-    
+
+    /**
+     * Returns a {@link RealMatrix} whose entries are the the values in the
+     * the input array.
+     * <p>If an array is built specially in order to be embedded in a
+     * RealMatrix and not used directly, the <code>copyArray</code> may be
+     * set to <code>false</code. This will prevent the copying and improve
+     * performance as no new array will be built and no data will be copied.</p>
+     * @param data data for new matrix
+     * @param copyArray if true, the input array will be copied, otherwise
+     * it will be referenced
+     * @return  RealMatrix containing the values of the array
+     * @throws IllegalArgumentException if <code>data</code> is not rectangular
+     *  (not all rows have the same length) or empty
+     * @throws NullPointerException if <code>data</code> is null
+     * @see #createRealMatrix(double[][])
+     */
+    public static RealMatrix createRealMatrix(double[][] data, boolean copyArray) {
+        return new RealMatrixImpl(data, copyArray);
+    }
+
     /**
      * Returns <code>dimension x dimension</code> identity matrix.
      *
@@ -56,14 +78,11 @@
      * @since 1.1
      */
     public static RealMatrix createRealIdentityMatrix(int dimension) {
-        RealMatrixImpl out = new RealMatrixImpl(dimension, dimension);
-        double[][] d = out.getDataRef();
+        double[][] d = new double[dimension][dimension];
         for (int row = 0; row < dimension; row++) {
-            for (int col = 0; col < dimension; col++) {
-                d[row][col] = row == col ? 1d : 0d;
-            }
+            d[row][row] = 1d;
         }
-        return out;
+        return new RealMatrixImpl(d, false);
     }
     
     /**
@@ -93,7 +112,27 @@
     public static BigMatrix createBigMatrix(BigDecimal[][] data) {
         return new BigMatrixImpl(data);
     }
-    
+
+    /**
+     * Returns a {@link BigMatrix} whose entries are the the values in the
+     * the input array.
+     * <p>If an array is built specially in order to be embedded in a
+     * BigMatrix and not used directly, the <code>copyArray</code> may be
+     * set to <code>false</code. This will prevent the copying and improve
+     * performance as no new array will be built and no data will be copied.</p>
+     * @param data data for new matrix
+     * @param copyArray if true, the input array will be copied, otherwise
+     * it will be referenced
+     * @return  BigMatrix containing the values of the array
+     * @throws IllegalArgumentException if <code>data</code> is not rectangular
+     *  (not all rows have the same length) or empty
+     * @throws NullPointerException if <code>data</code> is null
+     * @see #createRealMatrix(double[][])
+     */
+    public static BigMatrix createBigMatrix(BigDecimal[][] data, boolean copyArray) {
+        return new BigMatrixImpl(data, copyArray);
+    }
+
     /**
      * Returns a {@link BigMatrix} whose entries are the the values in the
      * the input array.  The input array is copied, not referenced.
@@ -118,10 +157,10 @@
      * @throws NullPointerException if <code>rowData</code>is null
      */
     public static RealMatrix createRowRealMatrix(double[] rowData) {
-        int nCols = rowData.length;
-        double[][] data = new double[1][nCols];
+        final int nCols = rowData.length;
+        final double[][] data = new double[1][nCols];
         System.arraycopy(rowData, 0, data[0], 0, nCols);
-        return new RealMatrixImpl(data);
+        return new RealMatrixImpl(data, false);
     }
     
     /**
@@ -134,10 +173,12 @@
      * @throws NullPointerException if <code>rowData</code>is null
      */
     public static BigMatrix createRowBigMatrix(double[] rowData) {
-        int nCols = rowData.length;
-        double[][] data = new double[1][nCols];
-        System.arraycopy(rowData, 0, data[0], 0, nCols);
-        return new BigMatrixImpl(data);
+        final int nCols = rowData.length;
+        final BigDecimal[][] data = new BigDecimal[1][nCols];
+        for (int i = 0; i < nCols; ++i) {
+            data[0][i] = new BigDecimal(rowData[i]);
+        }
+        return new BigMatrixImpl(data, false);
     }
     
     /**
@@ -150,10 +191,10 @@
      * @throws NullPointerException if <code>rowData</code>is null
      */
     public static BigMatrix createRowBigMatrix(BigDecimal[] rowData) {
-        int nCols = rowData.length;
-        BigDecimal[][] data = new BigDecimal[1][nCols];
+        final int nCols = rowData.length;
+        final BigDecimal[][] data = new BigDecimal[1][nCols];
         System.arraycopy(rowData, 0, data[0], 0, nCols);
-        return new BigMatrixImpl(data);
+        return new BigMatrixImpl(data, false);
     }
     
     /**
@@ -166,10 +207,12 @@
      * @throws NullPointerException if <code>rowData</code>is null
      */
     public static BigMatrix createRowBigMatrix(String[] rowData) {
-        int nCols = rowData.length;
-        String[][] data = new String[1][nCols];
-        System.arraycopy(rowData, 0, data[0], 0, nCols);
-        return new BigMatrixImpl(data);
+        final int nCols = rowData.length;
+        final BigDecimal[][] data = new BigDecimal[1][nCols];
+        for (int i = 0; i < nCols; ++i) {
+            data[0][i] = new BigDecimal(rowData[i]);
+        }
+        return new BigMatrixImpl(data, false);
     }
     
     /**
@@ -182,12 +225,12 @@
      * @throws NullPointerException if <code>columnData</code>is null
      */
     public static RealMatrix createColumnRealMatrix(double[] columnData) {
-        int nRows = columnData.length;
-        double[][] data = new double[nRows][1];
+        final int nRows = columnData.length;
+        final double[][] data = new double[nRows][1];
         for (int row = 0; row < nRows; row++) {
             data[row][0] = columnData[row];
         }
-        return new RealMatrixImpl(data);
+        return new RealMatrixImpl(data, false);
     }
     
     /**
@@ -200,12 +243,12 @@
      * @throws NullPointerException if <code>columnData</code>is null
      */
     public static BigMatrix createColumnBigMatrix(double[] columnData) {
-        int nRows = columnData.length;
-        double[][] data = new double[nRows][1];
+        final int nRows = columnData.length;
+        final BigDecimal[][] data = new BigDecimal[nRows][1];
         for (int row = 0; row < nRows; row++) {
-            data[row][0] = columnData[row];
+            data[row][0] = new BigDecimal(columnData[row]);
         }
-        return new BigMatrixImpl(data);
+        return new BigMatrixImpl(data, false);
     }
     
     /**
@@ -218,12 +261,12 @@
      * @throws NullPointerException if <code>columnData</code>is null
      */
     public static BigMatrix createColumnBigMatrix(BigDecimal[] columnData) {
-        int nRows = columnData.length;
-        BigDecimal[][] data = new BigDecimal[nRows][1];
+        final int nRows = columnData.length;
+        final BigDecimal[][] data = new BigDecimal[nRows][1];
         for (int row = 0; row < nRows; row++) {
             data[row][0] = columnData[row];
         }
-        return new BigMatrixImpl(data);
+        return new BigMatrixImpl(data, false);
     }
     
     /**
@@ -237,11 +280,11 @@
      */
     public static BigMatrix createColumnBigMatrix(String[] columnData) {
         int nRows = columnData.length;
-        String[][] data = new String[nRows][1];
+        final BigDecimal[][] data = new BigDecimal[nRows][1];
         for (int row = 0; row < nRows; row++) {
-            data[row][0] = columnData[row];
+            data[row][0] = new BigDecimal(columnData[row]);
         }
-        return new BigMatrixImpl(data);
+        return new BigMatrixImpl(data, false);
     }
     
     /**
@@ -253,14 +296,13 @@
      * @since 1.1
      */
     public static BigMatrix createBigIdentityMatrix(int dimension) {
-        BigMatrixImpl out = new BigMatrixImpl(dimension, dimension);
-        BigDecimal[][] d = out.getDataRef();
+        final BigDecimal[][] d = new BigDecimal[dimension][dimension];
         for (int row = 0; row < dimension; row++) {
-            for (int col = 0; col < dimension; col++) {
-                d[row][col] = row == col ? BigMatrixImpl.ONE : BigMatrixImpl.ZERO;
-            }
+            final BigDecimal[] dRow = d[row];
+            Arrays.fill(dRow, BigMatrixImpl.ZERO);
+            dRow[row] = BigMatrixImpl.ONE;
         }
-        return out;
+        return new BigMatrixImpl(d, false);
     }
     
 }

Modified: commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/RealMatrixImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/RealMatrixImpl.java?rev=662241&r1=662240&r2=662241&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/RealMatrixImpl.java (original)
+++ commons/proper/math/branches/MATH_2_0/src/java/org/apache/commons/math/linear/RealMatrixImpl.java Sun Jun  1 09:22:19 2008
@@ -52,7 +52,7 @@
 public class RealMatrixImpl implements RealMatrix, Serializable {
     
     /** Serializable version identifier */
-    private static final long serialVersionUID = 4237564493130426188L;
+    private static final long serialVersionUID = -4828886979278117018L;
 
     /** Entries of the matrix */
     private double data[][] = null;
@@ -97,16 +97,58 @@
     /**
      * Create a new RealMatrix using the input array as the underlying
      * data array.
-     * <p>
-     * The input array is copied, not referenced.</p>
+     * <p>The input array is copied, not referenced. This constructor has
+     * the same effect as calling {@link #RealMatrixImpl(double[][], boolean)}
+     * with the second argument set to <code>true</code>.</p>
      *
      * @param d data for new matrix
      * @throws IllegalArgumentException if <code>d</code> is not rectangular
      *  (not all rows have the same length) or empty
      * @throws NullPointerException if <code>d</code> is null
+     * @see #RealMatrixImpl(double[][], boolean)
      */
     public RealMatrixImpl(double[][] d) {
-        this.copyIn(d);
+        copyIn(d);
+        lu = null;
+    }
+
+    /**
+     * Create a new RealMatrix using the input array as the underlying
+     * data array.
+     * <p>If an array is built specially in order to be embedded in a
+     * RealMatrix and not used directly, the <code>copyArray</code> may be
+     * set to <code>false</code. This will prevent the copying and improve
+     * performance as no new array will be built and no data will be copied.</p>
+     * @param d data for new matrix
+     * @param copyArray if true, the input array will be copied, otherwise
+     * it will be referenced
+     * @throws IllegalArgumentException if <code>d</code> is not rectangular
+     *  (not all rows have the same length) or empty
+     * @throws NullPointerException if <code>d</code> is null
+     * @see #RealMatrixImpl(double[][])
+     */
+    public RealMatrixImpl(double[][] d, boolean copyArray) {
+        if (copyArray) {
+            copyIn(d);
+        } else {
+            if (d == null) {
+                throw new NullPointerException();
+            }   
+            final int nRows = d.length;
+            if (nRows == 0) {
+                throw new IllegalArgumentException("Matrix must have at least one row."); 
+            }
+            final int nCols = d[0].length;
+            if (nCols == 0) {
+                throw new IllegalArgumentException("Matrix must have at least one column."); 
+            }
+            for (int r = 1; r < nRows; r++) {
+                if (d[r].length != nCols) {
+                    throw new IllegalArgumentException("All input rows must have the same length.");
+                }
+            }       
+            data = d;
+        }
         lu = null;
     }
 
@@ -114,13 +156,12 @@
      * 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.</p>
+     * <p>The input array is copied, not referenced.</p>
      *
      * @param v column vector holding data for new matrix
      */
     public RealMatrixImpl(double[] v) {
-        int nRows = v.length;
+        final int nRows = v.length;
         data = new double[nRows][1];
         for (int row = 0; row < nRows; row++) {
             data[row][0] = v[row];
@@ -133,7 +174,7 @@
      * @return  the cloned matrix
      */
     public RealMatrix copy() {
-        return new RealMatrixImpl(this.copyOut());
+        return new RealMatrixImpl(copyOut(), false);
     }
 
     /**
@@ -144,19 +185,49 @@
      * @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()) {
+        try {
+            return add((RealMatrixImpl) m);
+        } catch (ClassCastException cce) {
+            final int rowCount    = getRowDimension();
+            final int columnCount = getColumnDimension();
+            if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
+                throw new IllegalArgumentException("matrix dimension mismatch");
+            }
+            final double[][] outData = new double[rowCount][columnCount];
+            for (int row = 0; row < rowCount; row++) {
+                final double[] dataRow    = data[row];
+                final double[] outDataRow = outData[row];
+                for (int col = 0; col < columnCount; col++) {
+                    outDataRow[col] = dataRow[col] + m.getEntry(row, col);
+                }  
+            }
+            return new RealMatrixImpl(outData, false);
+        }
+    }
+
+    /**
+     * 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 RealMatrixImpl add(RealMatrixImpl m) throws IllegalArgumentException {
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
             throw new IllegalArgumentException("matrix dimension mismatch");
         }
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        double[][] outData = new double[rowCount][columnCount];
+        final double[][] outData = new double[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final double[] dataRow    = data[row];
+            final double[] mRow       = m.data[row];
+            final double[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col] + m.getEntry(row, col);
+                outDataRow[col] = dataRow[col] + mRow[col];
             }  
         }
-        return new RealMatrixImpl(outData);
+        return new RealMatrixImpl(outData, false);
     }
 
     /**
@@ -167,19 +238,49 @@
      * @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()) {
+        try {
+            return subtract((RealMatrixImpl) m);
+        } catch (ClassCastException cce) {
+            final int rowCount    = getRowDimension();
+            final int columnCount = getColumnDimension();
+            if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
+                throw new IllegalArgumentException("matrix dimension mismatch");
+            }
+            final double[][] outData = new double[rowCount][columnCount];
+            for (int row = 0; row < rowCount; row++) {
+                final double[] dataRow    = data[row];
+                final double[] outDataRow = outData[row];
+                for (int col = 0; col < columnCount; col++) {
+                    outDataRow[col] = dataRow[col] - m.getEntry(row, col);
+                }  
+            }
+            return new RealMatrixImpl(outData, false);
+        }
+    }
+
+    /**
+     * 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 RealMatrixImpl subtract(RealMatrixImpl m) throws IllegalArgumentException {
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        if (columnCount != m.getColumnDimension() || rowCount != m.getRowDimension()) {
             throw new IllegalArgumentException("matrix dimension mismatch");
         }
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        double[][] outData = new double[rowCount][columnCount];
+        final double[][] outData = new double[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final double[] dataRow    = data[row];
+            final double[] mRow       = m.data[row];
+            final double[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col] - m.getEntry(row, col);
-            }
+                outDataRow[col] = dataRow[col] - mRow[col];
+            }  
         }
-        return new RealMatrixImpl(outData);
+        return new RealMatrixImpl(outData, false);
     }
 
     /**
@@ -189,32 +290,36 @@
      * @return     d + this
      */
     public RealMatrix scalarAdd(double d) {
-        int rowCount = this.getRowDimension();
-        int columnCount = this.getColumnDimension();
-        double[][] outData = new double[rowCount][columnCount];
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        final double[][] outData = new double[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final double[] dataRow    = data[row];
+            final double[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col] + d;
+                outDataRow[col] = dataRow[col] + d;
             }
         }
-        return new RealMatrixImpl(outData);
+        return new RealMatrixImpl(outData, false);
     }
 
     /**
-     * Returns the result multiplying each entry of this by <code>d</code>
+     * Returns the result of 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];
+        final int rowCount    = getRowDimension();
+        final int columnCount = getColumnDimension();
+        final double[][] outData = new double[rowCount][columnCount];
         for (int row = 0; row < rowCount; row++) {
+            final double[] dataRow    = data[row];
+            final double[] outDataRow = outData[row];
             for (int col = 0; col < columnCount; col++) {
-                outData[row][col] = data[row][col] * d;
+                outDataRow[col] = dataRow[col] * d;
             }
         }
-        return new RealMatrixImpl(outData);
+        return new RealMatrixImpl(outData, false);
     }
 
     /**
@@ -225,28 +330,62 @@
      *             if columnDimension(this) != rowDimension(m)
      */
     public RealMatrix multiply(RealMatrix m) throws IllegalArgumentException {
+        try {
+            return multiply((RealMatrixImpl) m);
+        } catch (ClassCastException cce) {
+            if (this.getColumnDimension() != m.getRowDimension()) {
+                throw new IllegalArgumentException("Matrices are not multiplication compatible.");
+            }
+            final int nRows = this.getRowDimension();
+            final int nCols = m.getColumnDimension();
+            final int nSum = this.getColumnDimension();
+            final double[][] outData = new double[nRows][nCols];
+            for (int row = 0; row < nRows; row++) {
+                final double[] dataRow    = data[row];
+                final double[] outDataRow = outData[row];
+                for (int col = 0; col < nCols; col++) {
+                    double sum = 0;
+                    for (int i = 0; i < nSum; i++) {
+                        sum += dataRow[i] * m.getEntry(i, col);
+                    }
+                    outDataRow[col] = sum;
+                }
+            }
+            return new RealMatrixImpl(outData, false);
+        }
+    }
+
+    /**
+     * 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 RealMatrixImpl multiply(RealMatrixImpl 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[][] outData = new double[nRows][nCols];
-        double sum = 0;
+        final int nRows = this.getRowDimension();
+        final int nCols = m.getColumnDimension();
+        final int nSum = this.getColumnDimension();
+        final double[][] outData = new double[nRows][nCols];
         for (int row = 0; row < nRows; row++) {
+            final double[] dataRow    = data[row];
+            final double[] outDataRow = outData[row];
             for (int col = 0; col < nCols; col++) {
-                sum = 0;
+                double sum = 0;
                 for (int i = 0; i < nSum; i++) {
-                    sum += data[row][i] * m.getEntry(i, col);
+                    sum += dataRow[i] * m.data[i][col];
                 }
-                outData[row][col] = sum;
+                outDataRow[col] = sum;
             }
-        }
-        return new RealMatrixImpl(outData);
+        }            
+        return new RealMatrixImpl(outData, false);
     }
 
     /**
-     * Returns the result premultiplying this by <code>m</code>.
+     * Returns the result of premultiplying this by <code>m</code>.
      * @param m    matrix to premultiply by
      * @return     m * this
      * @throws     IllegalArgumentException
@@ -306,23 +445,23 @@
      *         specified rows and columns
      * @exception MatrixIndexException if row or column selections are not valid
      */
-    public RealMatrix getSubMatrix(int startRow, int endRow, int startColumn,
-            int endColumn) throws MatrixIndexException {
+    public RealMatrix getSubMatrix(int startRow, int endRow,
+                                   int startColumn, int endColumn)
+        throws MatrixIndexException {
         if (startRow < 0 || startRow > endRow || endRow > data.length ||
              startColumn < 0 || startColumn > endColumn ||
-             endColumn > data[0].length ) {
+             endColumn > data[0].length) {
             throw new MatrixIndexException(
                     "invalid row or column index selection");
         }
-        RealMatrixImpl subMatrix = new RealMatrixImpl(endRow - startRow+1,
-                endColumn - startColumn+1);
-        double[][] subMatrixData = subMatrix.getDataRef();
+        final double[][] subMatrixData =
+            new double[endRow - startRow + 1][endColumn - startColumn + 1];
         for (int i = startRow; i <= endRow; i++) {
-            for (int j = startColumn; j <= endColumn; j++) {
-                    subMatrixData[i - startRow][j - startColumn] = data[i][j];
-                }
-            }
-        return subMatrix;
+            System.arraycopy(data[i], startColumn,
+                             subMatrixData[i - startRow], 0,
+                             endColumn - startColumn + 1);
+        }
+        return new RealMatrixImpl(subMatrixData, false);
     }
     
     /**
@@ -337,25 +476,25 @@
      *     are not valid
      */
     public RealMatrix getSubMatrix(int[] selectedRows, int[] selectedColumns)
-    throws MatrixIndexException {
+        throws MatrixIndexException {
         if (selectedRows.length * selectedColumns.length == 0) {
             throw new MatrixIndexException(
                     "selected row and column index arrays must be non-empty");
         }
-        RealMatrixImpl subMatrix = new RealMatrixImpl(selectedRows.length,
-                selectedColumns.length);
-        double[][] subMatrixData = subMatrix.getDataRef();
+        final double[][] subMatrixData =
+            new double[selectedRows.length][selectedColumns.length];
         try  {
             for (int i = 0; i < selectedRows.length; i++) {
+                final double[] subI = subMatrixData[i];
+                final double[] dataSelectedI = data[selectedRows[i]];
                 for (int j = 0; j < selectedColumns.length; j++) {
-                    subMatrixData[i][j] = data[selectedRows[i]][selectedColumns[j]];
+                    subI[j] = dataSelectedI[selectedColumns[j]];
                 }
             }
-        }
-        catch (ArrayIndexOutOfBoundsException e) {
+        } catch (ArrayIndexOutOfBoundsException e) {
             throw new MatrixIndexException("matrix dimension mismatch");
         }
-        return subMatrix;
+        return new RealMatrixImpl(subMatrixData, false);
     } 
 
     /**
@@ -391,12 +530,12 @@
             throw new MatrixIndexException
                 ("invalid row or column index selection");          
         }
-        int nRows = subMatrix.length;
+        final int nRows = subMatrix.length;
         if (nRows == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one row."); 
         }
-        int nCols = subMatrix[0].length;
+        final int nCols = subMatrix[0].length;
         if (nCols == 0) {
             throw new IllegalArgumentException(
             "Matrix must have at least one column."); 
@@ -435,10 +574,10 @@
         if ( !isValidCoordinate( row, 0)) {
             throw new MatrixIndexException("illegal row argument");
         }
-        int ncols = this.getColumnDimension();
-        double[][] out = new double[1][ncols]; 
+        final int ncols = this.getColumnDimension();
+        final double[][] out = new double[1][ncols]; 
         System.arraycopy(data[row], 0, out[0], 0, ncols);
-        return new RealMatrixImpl(out);
+        return new RealMatrixImpl(out, false);
     }
     
     /**
@@ -453,12 +592,12 @@
         if ( !isValidCoordinate( 0, column)) {
             throw new MatrixIndexException("illegal column argument");
         }
-        int nRows = this.getRowDimension();
-        double[][] out = new double[nRows][1]; 
+        final int nRows = this.getRowDimension();
+        final double[][] out = new double[nRows][1]; 
         for (int row = 0; row < nRows; row++) {
             out[row][0] = data[row][column];
         }
-        return new RealMatrixImpl(out);
+        return new RealMatrixImpl(out, false);
     }
 
      /**
@@ -475,8 +614,8 @@
         if ( !isValidCoordinate( row, 0 ) ) {
             throw new MatrixIndexException("illegal row argument");
         }
-        int ncols = this.getColumnDimension();
-        double[] out = new double[ncols];
+        final int ncols = this.getColumnDimension();
+        final double[] out = new double[ncols];
         System.arraycopy(data[row], 0, out, 0, ncols);
         return out;
     }
@@ -495,8 +634,8 @@
         if ( !isValidCoordinate(0, col) ) {
             throw new MatrixIndexException("illegal column argument");
         }
-        int nRows = this.getRowDimension();
-        double[] out = new double[nRows];
+        final int nRows = this.getRowDimension();
+        final double[] out = new double[nRows];
         for (int row = 0; row < nRows; row++) {
             out[row] = data[row][col];
         }
@@ -520,10 +659,11 @@
      */
     public double getEntry(int row, int column)
         throws MatrixIndexException {
-        if (!isValidCoordinate(row,column)) {
+        try {
+            return data[row][column];
+        } catch (ArrayIndexOutOfBoundsException e) {
             throw new MatrixIndexException("matrix entry does not exist");
         }
-        return data[row][column];
     }
 
     /**
@@ -532,16 +672,16 @@
      * @return transpose matrix
      */
     public RealMatrix transpose() {
-        int nRows = this.getRowDimension();
-        int nCols = this.getColumnDimension();
-        RealMatrixImpl out = new RealMatrixImpl(nCols, nRows);
-        double[][] outData = out.getDataRef();
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
+        final double[][] outData = new double[nCols][nRows];
         for (int row = 0; row < nRows; row++) {
+            final double[] dataRow = data[row];
             for (int col = 0; col < nCols; col++) {
-                outData[col][row] = data[row][col];
+                outData[col][row] = dataRow[col];
             }
         }
-        return out;
+        return new RealMatrixImpl(outData, false);
     }
 
     /**
@@ -551,8 +691,7 @@
      * @throws InvalidMatrixException if this is not invertible
      */
     public RealMatrix inverse() throws InvalidMatrixException {
-        return solve(MatrixUtils.createRealIdentityMatrix
-                (this.getRowDimension()));
+        return solve(MatrixUtils.createRealIdentityMatrix(getRowDimension()));
     }
 
     /**
@@ -632,16 +771,17 @@
      * @return resulting vector
      */
     public double[] operate(double[] v) throws IllegalArgumentException {
-        if (v.length != this.getColumnDimension()) {
+        final int nRows = this.getRowDimension();
+        final int nCols = this.getColumnDimension();
+        if (v.length != nCols) {
             throw new IllegalArgumentException("vector has wrong length");
         }
-        int nRows = this.getRowDimension();
-        int nCols = this.getColumnDimension();
-        double[] out = new double[v.length];
+        final double[] out = new double[v.length];
         for (int row = 0; row < nRows; row++) {
+            final double[] dataRow = data[row];
             double sum = 0;
             for (int i = 0; i < nCols; i++) {
-                sum += data[row][i] * v[i];
+                sum += dataRow[i] * v[i];
             }
             out[row] = sum;
         }
@@ -654,12 +794,12 @@
      * @return resulting matrix
      */
     public double[] preMultiply(double[] v) throws IllegalArgumentException {
-        int nRows = this.getRowDimension();
+        final int nRows = this.getRowDimension();
         if (v.length != nRows) {
             throw new IllegalArgumentException("vector has wrong length");
         }
-        int nCols = this.getColumnDimension();
-        double[] out = new double[nCols];
+        final int nCols = this.getColumnDimension();
+        final double[] out = new double[nCols];
         for (int col = 0; col < nCols; col++) {
             double sum = 0;
             for (int i = 0; i < nRows; i++) {
@@ -682,13 +822,13 @@
      * @throws InvalidMatrixException if this matrix is not square or is singular
      */
     public double[] solve(double[] b) throws IllegalArgumentException, InvalidMatrixException {
-        int nRows = this.getRowDimension();
+        final 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];
+        final RealMatrix bMatrix = new RealMatrixImpl(b);
+        final double[][] solution = ((RealMatrixImpl) (solve(bMatrix))).getDataRef();
+        final double[] out = new double[nRows];
         for (int row = 0; row < nRows; row++) {
             out[row] = solution[row][0];
         }
@@ -717,41 +857,48 @@
             throw new InvalidMatrixException("Matrix is singular.");
         }
 
-        int nCol = this.getColumnDimension();
-        int nColB = b.getColumnDimension();
-        int nRowB = b.getRowDimension();
+        final int nCol  = this.getColumnDimension();
+        final int nColB = b.getColumnDimension();
+        final int nRowB = b.getRowDimension();
 
         // Apply permutations to b
-        double[][] bp = new double[nRowB][nColB];
+        final double[][] bp = new double[nRowB][nColB];
         for (int row = 0; row < nRowB; row++) {
+            final double[] bpRow = bp[row];
             for (int col = 0; col < nColB; col++) {
-                bp[row][col] = b.getEntry(permutation[row], col);
+                bpRow[col] = b.getEntry(permutation[row], col);
             }
         }
 
         // Solve LY = b
         for (int col = 0; col < nCol; col++) {
             for (int i = col + 1; i < nCol; i++) {
+                final double[] bpI = bp[i];
+                final double[] luI = lu[i];
                 for (int j = 0; j < nColB; j++) {
-                    bp[i][j] -= bp[col][j] * lu[i][col];
+                    bpI[j] -= bp[col][j] * luI[col];
                 }
             }
         }
 
         // Solve UX = Y
         for (int col = nCol - 1; col >= 0; col--) {
+            final double[] bpCol = bp[col];
+            final double luDiag = lu[col][col];
             for (int j = 0; j < nColB; j++) {
-                bp[col][j] /= lu[col][col];
+                bpCol[j] /= luDiag;
             }
             for (int i = 0; i < col; i++) {
+                final double[] bpI = bp[i];
+                final double[] luI = lu[i];
                 for (int j = 0; j < nColB; j++) {
-                    bp[i][j] -= bp[col][j] * lu[i][col];
+                    bpI[j] -= bp[col][j] * luI[col];
                 }
             }
         }
 
-        RealMatrixImpl outMat = new RealMatrixImpl(bp);
-        return outMat;
+        return new RealMatrixImpl(bp, false);
+
     }
 
     /**
@@ -774,12 +921,12 @@
      */
     public void luDecompose() throws InvalidMatrixException {
 
-        int nRows = this.getRowDimension();
-        int nCols = this.getColumnDimension();
+        final int nRows = this.getRowDimension();
+        final int nCols = this.getColumnDimension();
         if (nRows != nCols) {
             throw new InvalidMatrixException("LU decomposition requires that the matrix be square.");
         }
-        lu = this.getData();
+        lu = getData();
 
         // Initialize permutation array and parity
         permutation = new int[nRows];
@@ -795,22 +942,24 @@
 
             // upper
             for (int row = 0; row < col; row++) {
-                sum = lu[row][col];
+                final double[] luRow = lu[row];
+                sum = luRow[col];
                 for (int i = 0; i < row; i++) {
-                    sum -= lu[row][i] * lu[i][col];
+                    sum -= luRow[i] * lu[i][col];
                 }
-                lu[row][col] = sum;
+                luRow[col] = sum;
             }
 
             // lower
             int max = col; // permutation row
             double largest = 0d;
             for (int row = col; row < nRows; row++) {
-                sum = lu[row][col];
+                final double[] luRow = lu[row];
+                sum = luRow[col];
                 for (int i = 0; i < col; i++) {
-                    sum -= lu[row][i] * lu[i][col];
+                    sum -= luRow[i] * lu[i][col];
                 }
-                lu[row][col] = sum;
+                luRow[col] = sum;
 
                 // maintain best permutation choice
                 if (Math.abs(sum) > largest) {
@@ -839,9 +988,10 @@
                 parity = -parity;
             }
 
-            //Divide the lower elements by the "winning" diagonal elt.
+            // Divide the lower elements by the "winning" diagonal elt.
+            final double luDiag = lu[col][col];
             for (int row = col + 1; row < nRows; row++) {
-                lu[row][col] /= lu[col][col];
+                lu[row][col] /= luDiag;
             }
         }
     }
@@ -855,12 +1005,14 @@
         res.append("RealMatrixImpl{");
         if (data != null) {
             for (int i = 0; i < data.length; i++) {
-                if (i > 0)
+                if (i > 0) {
                     res.append(",");
+                }
                 res.append("{");
                 for (int j = 0; j < data[0].length; j++) {
-                    if (j > 0)
+                    if (j > 0) {
                         res.append(",");
+                    }
                     res.append(data[i][j]);
                 } 
                 res.append("}");
@@ -887,14 +1039,15 @@
             return false;
         }
         RealMatrix m = (RealMatrix) object;
-        int nRows = getRowDimension();
-        int nCols = getColumnDimension();
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
         if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) {
             return false;
         }
         for (int row = 0; row < nRows; row++) {
+            final double[] dataRow = data[row];
             for (int col = 0; col < nCols; col++) {
-                if (Double.doubleToLongBits(data[row][col]) != 
+                if (Double.doubleToLongBits(dataRow[col]) != 
                     Double.doubleToLongBits(m.getEntry(row, col))) {
                     return false;
                 }
@@ -910,14 +1063,15 @@
      */
     public int hashCode() {
         int ret = 7;
-        int nRows = getRowDimension();
-        int nCols = getColumnDimension();
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
         ret = ret * 31 + nRows;
         ret = ret * 31 + nCols;
         for (int row = 0; row < nRows; row++) {
-           for (int col = 0; col < nCols; col++) {
+            final double[] dataRow = data[row];
+            for (int col = 0; col < nCols; col++) {
                ret = ret * 31 + (11 * (row+1) + 17 * (col+1)) * 
-                   MathUtils.hash(data[row][col]);
+                   MathUtils.hash(dataRow[col]);
            }
         }
         return ret;
@@ -972,7 +1126,7 @@
      * @return the permutation
      */
     protected int[] getPermutation() {
-        int[] out = new int[permutation.length];
+        final int[] out = new int[permutation.length];
         System.arraycopy(permutation, 0, out, 0, permutation.length);
         return out;
     }
@@ -985,8 +1139,8 @@
      * @return a copy of the underlying data array.
      */
     private double[][] copyOut() {
-        int nRows = this.getRowDimension();
-        double[][] out = new double[nRows][this.getColumnDimension()];
+        final int nRows = this.getRowDimension();
+        final 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);
@@ -1016,9 +1170,8 @@
      * @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();
-
+        final int nRows = getRowDimension();
+        final int nCols = getColumnDimension();
         return !(row < 0 || row > nRows - 1 || col < 0 || col > nCols -1);
     }
 

Modified: commons/proper/math/branches/MATH_2_0/src/site/xdoc/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0/src/site/xdoc/changes.xml?rev=662241&r1=662240&r2=662241&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_0/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/branches/MATH_2_0/src/site/xdoc/changes.xml Sun Jun  1 09:22:19 2008
@@ -39,6 +39,10 @@
   </properties>
   <body>
     <release version="2.0" date="TBD" description="TBD">
+      <action dev="luc" type="update" >
+        Greatly improved RealMatrixImpl and BigMatrixImpl performances,
+        both in terms of speed and in terms of temporary memory footprint.
+      </action>
       <action dev="luc" type="add" issue="MATH-203" due-to="Mauro Talevi">
         Added Mauro's patch to support multiple regression.
       </action>

Modified: commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/BigMatrixImplTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/BigMatrixImplTest.java?rev=662241&r1=662240&r2=662241&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/BigMatrixImplTest.java (original)
+++ commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/BigMatrixImplTest.java Sun Jun  1 09:22:19 2008
@@ -156,9 +156,12 @@
     
     /** test copy functions */
     public void testCopyFunctions() {
-        BigMatrixImpl m = new BigMatrixImpl(testData);
-        BigMatrixImpl m2 = new BigMatrixImpl(m.getData());
-        assertEquals(m2,m);
+        BigMatrixImpl m1 = new BigMatrixImpl(testData);
+        BigMatrixImpl m2 = new BigMatrixImpl(m1.getData());
+        assertEquals(m2,m1);
+        BigMatrixImpl m3 = new BigMatrixImpl(testData);
+        BigMatrixImpl m4 = new BigMatrixImpl(m3.getData(), false);
+        assertEquals(m4,m3);
     }
     
     /** test constructors */
@@ -166,9 +169,13 @@
         BigMatrix m1 = new BigMatrixImpl(testData);
         BigMatrix m2 = new BigMatrixImpl(testDataString);
         BigMatrix m3 = new BigMatrixImpl(asBigDecimal(testData));
+        BigMatrix m4 = new BigMatrixImpl(asBigDecimal(testData), true);
+        BigMatrix m5 = new BigMatrixImpl(asBigDecimal(testData), false);
         assertClose("double, string", m1, m2, Double.MIN_VALUE);
         assertClose("double, BigDecimal", m1, m3, Double.MIN_VALUE);
         assertClose("string, BigDecimal", m2, m3, Double.MIN_VALUE);
+        assertClose("double, BigDecimal/true", m1, m4, Double.MIN_VALUE);
+        assertClose("double, BigDecimal/false", m1, m5, Double.MIN_VALUE);
         try {
             new BigMatrixImpl(new String[][] {{"0", "hello", "1"}});
             fail("Expecting NumberFormatException");
@@ -212,7 +219,7 @@
     public void testAdd() {
         BigMatrixImpl m = new BigMatrixImpl(testData);
         BigMatrixImpl mInv = new BigMatrixImpl(testDataInv);
-        BigMatrixImpl mPlusMInv = (BigMatrixImpl)m.add(mInv);
+        BigMatrix mPlusMInv = m.add(mInv);
         double[][] sumEntries = asDouble(mPlusMInv.getData());
         for (int row = 0; row < m.getRowDimension(); row++) {
             for (int col = 0; col < m.getColumnDimension(); col++) {

Modified: commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/MatrixUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/MatrixUtilsTest.java?rev=662241&r1=662240&r2=662241&view=diff
==============================================================================
--- commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/MatrixUtilsTest.java (original)
+++ commons/proper/math/branches/MATH_2_0/src/test/org/apache/commons/math/linear/MatrixUtilsTest.java Sun Jun  1 09:22:19 2008
@@ -65,6 +65,10 @@
     public void testCreateRealMatrix() {
         assertEquals(new RealMatrixImpl(testData), 
                 MatrixUtils.createRealMatrix(testData));
+        assertEquals(new RealMatrixImpl(testData, false), 
+                MatrixUtils.createRealMatrix(testData, true));
+        assertEquals(new RealMatrixImpl(testData, true), 
+                MatrixUtils.createRealMatrix(testData, false));
         try {
             MatrixUtils.createRealMatrix(new double[][] {{1}, {1,2}});  // ragged
             fail("Expecting IllegalArgumentException");
@@ -88,6 +92,10 @@
     public void testCreateBigMatrix() {
         assertEquals(new BigMatrixImpl(testData), 
                 MatrixUtils.createBigMatrix(testData));
+        assertEquals(new BigMatrixImpl(BigMatrixImplTest.asBigDecimal(testData), true), 
+                MatrixUtils.createBigMatrix(BigMatrixImplTest.asBigDecimal(testData), false));
+        assertEquals(new BigMatrixImpl(BigMatrixImplTest.asBigDecimal(testData), false), 
+                MatrixUtils.createBigMatrix(BigMatrixImplTest.asBigDecimal(testData), true));
         assertEquals(new BigMatrixImpl(bigColMatrix), 
                 MatrixUtils.createBigMatrix(bigColMatrix));
         assertEquals(new BigMatrixImpl(stringColMatrix),