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/12/24 00:30:34 UTC

svn commit: r729174 - in /commons/proper/math/trunk/src: java/org/apache/commons/math/linear/DenseRealMatrix.java test/org/apache/commons/math/linear/DenseRealMatrixTest.java

Author: luc
Date: Tue Dec 23 15:30:33 2008
New Revision: 729174

URL: http://svn.apache.org/viewvc?rev=729174&view=rev
Log:
added new cache-friendly specializations of get/set/operate/premultiply methods

Modified:
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java
    commons/proper/math/trunk/src/test/org/apache/commons/math/linear/DenseRealMatrixTest.java

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java?rev=729174&r1=729173&r2=729174&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java Tue Dec 23 15:30:33 2008
@@ -44,7 +44,7 @@
     private static final long serialVersionUID = 4991895511313664478L;
 
     /** Block size. */
-    private static final int BLOCK_SIZE = 52;
+    public static final int BLOCK_SIZE = 52;
 
     /** Blocks of matrix entries. */
     private final double blocks[][];
@@ -647,6 +647,408 @@
     }
 
     /** {@inheritDoc} */
+    public void setSubMatrix(final double[][] subMatrix, final int row, final int column)
+        throws MatrixIndexException {
+
+        // safety checks
+        final int refLength = subMatrix[0].length;
+        if (refLength < 1) {
+            throw MathRuntimeException.createIllegalArgumentException("matrix must have at least one column",
+                                                                      null);             
+        }
+        final int endRow    = row + subMatrix.length - 1;
+        final int endColumn = column + refLength - 1;
+        checkSubMatrixIndex(row, endRow, column, endColumn);
+        for (final double[] subRow : subMatrix) {
+            if (subRow.length != refLength) {
+                throw MathRuntimeException.createIllegalArgumentException("some rows have length {0} while others have length {1}",
+                                                                          new Object[] {
+                                                                              refLength, subRow.length
+                                                                          }); 
+            }
+        }
+
+        // compute blocks bounds
+        final int blockStartRow    = row / BLOCK_SIZE;
+        final int blockEndRow      = (endRow + BLOCK_SIZE) / BLOCK_SIZE;
+        final int blockStartColumn = column / BLOCK_SIZE;
+        final int blockEndColumn   = (endColumn + BLOCK_SIZE) / BLOCK_SIZE;
+
+        // perform copy block-wise, to ensure good cache behavior
+        for (int iBlock = blockStartRow; iBlock < blockEndRow; ++iBlock) {
+            final int iHeight  = blockHeight(iBlock);
+            final int firstRow = iBlock * BLOCK_SIZE;
+            final int iStart   = Math.max(row,    firstRow);
+            final int iEnd     = Math.min(endRow + 1, firstRow + iHeight);
+
+            for (int jBlock = blockStartColumn; jBlock < blockEndColumn; ++jBlock) {
+                final int jWidth      = blockWidth(jBlock);
+                final int firstColumn = jBlock * BLOCK_SIZE;
+                final int jStart      = Math.max(column,    firstColumn);
+                final int jEnd        = Math.min(endColumn + 1, firstColumn + jWidth);
+                final int jLength     = jEnd - jStart;
+
+                // handle one block, row by row
+                final double[] block = blocks[iBlock * blockColumns + jBlock];
+                for (int i = iStart; i < iEnd; ++i) {
+                    System.arraycopy(subMatrix[i - row], jStart - column,
+                                     block, (i - firstRow) * jWidth + (jStart - firstColumn),
+                                     jLength);
+                }
+
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public RealMatrix getRowMatrix(final int row)
+        throws MatrixIndexException {
+
+        checkRowIndex(row);
+        final DenseRealMatrix out = new DenseRealMatrix(1, columns);
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int iBlock  = row / BLOCK_SIZE;
+        final int iRow    = row - iBlock * BLOCK_SIZE;
+        int outBlockIndex = 0;
+        int outIndex      = 0;
+        double[] outBlock = out.blocks[outBlockIndex];
+        for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+            final int jWidth     = blockWidth(jBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            final int available  = outBlock.length - outIndex;
+            if (jWidth > available) {
+                System.arraycopy(block, iRow * jWidth, outBlock, outIndex, available);
+                outBlock = out.blocks[++outBlockIndex];
+                System.arraycopy(block, iRow * jWidth, outBlock, 0, jWidth - available);
+                outIndex = jWidth - available;
+            } else {
+                System.arraycopy(block, iRow * jWidth, outBlock, outIndex, jWidth);
+                outIndex += jWidth;
+            }
+        }
+
+        return out;
+
+    }
+
+    /** {@inheritDoc} */
+    public void setRowMatrix(final int row, final RealMatrix matrix)
+        throws MatrixIndexException, InvalidMatrixException {
+        try {
+            setRowMatrix(row, (DenseRealMatrix) matrix);
+        } catch (ClassCastException cce) {
+            super.setRowMatrix(row, matrix);
+        }
+    }
+
+    /**
+     * Sets the entries in row number <code>row</code>
+     * as a row matrix.  Row indices start at 0.
+     *
+     * @param row the row to be set
+     * @param matrix row matrix (must have one row and the same number of columns
+     * as the instance)
+     * @throws MatrixIndexException if the specified row index is invalid
+     * @throws InvalidMatrixException if the matrix dimensions do not match one
+     * instance row
+     */
+    public void setRowMatrix(final int row, final DenseRealMatrix matrix)
+        throws MatrixIndexException, InvalidMatrixException {
+
+        checkRowIndex(row);
+        final int nCols = getColumnDimension();
+        if ((matrix.getRowDimension() != 1) ||
+            (matrix.getColumnDimension() != nCols)) {
+            throw new InvalidMatrixException("dimensions mismatch: got {0}x{1} but expected {2}x{3}",
+                                             new Object[] {
+                                                 matrix.getRowDimension(),
+                                                 matrix.getColumnDimension(),
+                                                 1, nCols
+                                             });
+        }
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int iBlock = row / BLOCK_SIZE;
+        final int iRow   = row - iBlock * BLOCK_SIZE;
+        int mBlockIndex  = 0;
+        int mIndex       = 0;
+        double[] mBlock  = matrix.blocks[mBlockIndex];
+        for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+            final int jWidth     = blockWidth(jBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            final int available  = mBlock.length - mIndex;
+            if (jWidth > available) {
+                System.arraycopy(mBlock, mIndex, block, iRow * jWidth, available);
+                mBlock = matrix.blocks[++mBlockIndex];
+                System.arraycopy(mBlock, 0, block, iRow * jWidth, jWidth - available);
+                mIndex = jWidth - available;
+            } else {
+                System.arraycopy(mBlock, mIndex, block, iRow * jWidth, jWidth);
+                mIndex += jWidth;
+           }
+        }
+
+    }
+    
+    /** {@inheritDoc} */
+    public RealMatrix getColumnMatrix(final int column)
+        throws MatrixIndexException {
+
+        checkColumnIndex(column);
+        final DenseRealMatrix out = new DenseRealMatrix(rows, 1);
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int jBlock  = column / BLOCK_SIZE;
+        final int jColumn = column - jBlock * BLOCK_SIZE;
+        final int jWidth  = blockWidth(jBlock);
+        int outBlockIndex = 0;
+        int outIndex      = 0;
+        double[] outBlock = out.blocks[outBlockIndex];
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            for (int i = 0; i < iHeight; ++i) {
+                if (outIndex >= outBlock.length) {
+                    outBlock = out.blocks[++outBlockIndex];
+                    outIndex = 0;
+                }
+                outBlock[outIndex++] = block[i * jWidth + jColumn];
+            }
+        }
+
+        return out;
+
+    }
+
+    /** {@inheritDoc} */
+    public void setColumnMatrix(final int column, final RealMatrix matrix)
+        throws MatrixIndexException, InvalidMatrixException {
+        try {
+            setColumnMatrix(column, (DenseRealMatrix) matrix);
+        } catch (ClassCastException cce) {
+            super.setColumnMatrix(column, matrix);
+        }
+    }
+
+    /**
+     * Sets the entries in column number <code>column</code>
+     * as a column matrix.  Column indices start at 0.
+     *
+     * @param column the column to be set
+     * @param matrix column matrix (must have one column and the same number of rows
+     * as the instance)
+     * @throws MatrixIndexException if the specified column index is invalid
+     * @throws InvalidMatrixException if the matrix dimensions do not match one
+     * instance column
+     */
+    void setColumnMatrix(final int column, final DenseRealMatrix matrix)
+        throws MatrixIndexException, InvalidMatrixException {
+
+        checkColumnIndex(column);
+        final int nRows = getRowDimension();
+        if ((matrix.getRowDimension() != nRows) ||
+            (matrix.getColumnDimension() != 1)) {
+            throw new InvalidMatrixException("dimensions mismatch: got {0}x{1} but expected {2}x{3}",
+                                             new Object[] {
+                                                 matrix.getRowDimension(),
+                                                 matrix.getColumnDimension(),
+                                                 nRows, 1
+                                             });
+        }
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int jBlock  = column / BLOCK_SIZE;
+        final int jColumn = column - jBlock * BLOCK_SIZE;
+        final int jWidth  = blockWidth(jBlock);
+        int mBlockIndex = 0;
+        int mIndex      = 0;
+        double[] mBlock = matrix.blocks[mBlockIndex];
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            for (int i = 0; i < iHeight; ++i) {
+                if (mIndex >= mBlock.length) {
+                    mBlock = matrix.blocks[++mBlockIndex];
+                    mIndex = 0;
+                }
+                block[i * jWidth + jColumn] = mBlock[mIndex++];
+            }
+        }
+
+    }
+    
+    /** {@inheritDoc} */
+    public RealVector getRowVector(final int row)
+        throws MatrixIndexException {
+
+        checkRowIndex(row);
+        final RealVectorImpl out = new RealVectorImpl(columns);
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int iBlock  = row / BLOCK_SIZE;
+        final int iRow    = row - iBlock * BLOCK_SIZE;
+        int outIndex      = 0;
+        double[] outData  = out.getDataRef();
+        for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+            final int jWidth     = blockWidth(jBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            System.arraycopy(block, iRow * jWidth, outData, outIndex, jWidth);
+            outIndex += jWidth;
+        }
+
+        return out;
+
+    }
+
+    /** {@inheritDoc} */
+    public void setRowVector(final int row, final RealVector vector)
+        throws MatrixIndexException, InvalidMatrixException {
+        try {
+            setRow(row, ((RealVectorImpl) vector).getDataRef());
+        } catch (ClassCastException cce) {
+            super.setRowVector(row, vector);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public RealVector getColumnVector(final int column)
+        throws MatrixIndexException {
+
+        checkColumnIndex(column);
+        final RealVectorImpl out = new RealVectorImpl(rows);
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int jBlock  = column / BLOCK_SIZE;
+        final int jColumn = column - jBlock * BLOCK_SIZE;
+        final int jWidth  = blockWidth(jBlock);
+        int outIndex      = 0;
+        double[] outData = out.getDataRef();
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            for (int i = 0; i < iHeight; ++i) {
+                outData[outIndex++] = block[i * jWidth + jColumn];
+            }
+        }
+
+        return out;
+
+    }
+
+    /** {@inheritDoc} */
+    public void setColumnVector(final int column, final RealVector vector)
+        throws MatrixIndexException, InvalidMatrixException {
+        try {
+            setColumn(column, ((RealVectorImpl) vector).getDataRef());
+        } catch (ClassCastException cce) {
+            super.setColumnVector(column, vector);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public double[] getRow(final int row)
+        throws MatrixIndexException {
+
+        checkRowIndex(row);
+        final double[] out = new double[columns];
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int iBlock  = row / BLOCK_SIZE;
+        final int iRow    = row - iBlock * BLOCK_SIZE;
+        int outIndex      = 0;
+        for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+            final int jWidth     = blockWidth(jBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            System.arraycopy(block, iRow * jWidth, out, outIndex, jWidth);
+            outIndex += jWidth;
+        }
+
+        return out;
+
+    }
+
+    /** {@inheritDoc} */
+    public void setRow(final int row, final double[] array)
+        throws MatrixIndexException, InvalidMatrixException {
+
+        checkRowIndex(row);
+        final int nCols = getColumnDimension();
+        if (array.length != nCols) {
+            throw new InvalidMatrixException("dimensions mismatch: got {0}x{1} but expected {2}x{3}",
+                                             new Object[] {
+                                                 1, array.length,
+                                                 1, nCols
+                                             });
+        }
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int iBlock  = row / BLOCK_SIZE;
+        final int iRow    = row - iBlock * BLOCK_SIZE;
+        int outIndex      = 0;
+        for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+            final int jWidth     = blockWidth(jBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            System.arraycopy(array, outIndex, block, iRow * jWidth, jWidth);
+            outIndex += jWidth;
+        }
+
+    }
+
+    /** {@inheritDoc} */
+    public double[] getColumn(final int column)
+        throws MatrixIndexException {
+
+        checkColumnIndex(column);
+        final double[] out = new double[rows];
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int jBlock  = column / BLOCK_SIZE;
+        final int jColumn = column - jBlock * BLOCK_SIZE;
+        final int jWidth  = blockWidth(jBlock);
+        int outIndex      = 0;
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            for (int i = 0; i < iHeight; ++i) {
+                out[outIndex++] = block[i * jWidth + jColumn];
+            }
+        }
+
+        return out;
+
+    }
+
+    /** {@inheritDoc} */
+    public void setColumn(final int column, final double[] array)
+        throws MatrixIndexException, InvalidMatrixException {
+
+        checkColumnIndex(column);
+        final int nRows = getRowDimension();
+        if (array.length != nRows) {
+            throw new InvalidMatrixException("dimensions mismatch: got {0}x{1} but expected {2}x{3}",
+                                             new Object[] {
+                                                 array.length, 1,
+                                                 nRows, 1
+                                             });
+        }
+
+        // perform copy block-wise, to ensure good cache behavior
+        final int jBlock  = column / BLOCK_SIZE;
+        final int jColumn = column - jBlock * BLOCK_SIZE;
+        final int jWidth  = blockWidth(jBlock);
+        int outIndex      = 0;
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            final double[] block = blocks[iBlock * blockColumns + jBlock];
+            for (int i = 0; i < iHeight; ++i) {
+                block[i * jWidth + jColumn] = array[outIndex++];
+            }
+        }
+
+    }
+
+    /** {@inheritDoc} */
     public double getEntry(final int row, final int column)
         throws MatrixIndexException {
         try {
@@ -768,20 +1170,21 @@
     public double[] operate(final double[] v)
         throws IllegalArgumentException {
 
-        final int nRows = this.getRowDimension();
-        final int nCols = this.getColumnDimension();
-        if (v.length != nCols) {
-            throw new IllegalArgumentException("vector has wrong length");
+        if (v.length != columns) {
+            throw MathRuntimeException.createIllegalArgumentException("vector length mismatch:" +
+                                                                      " got {0} but expected {1}",
+                                                                      new Object[] {
+                                                                          v.length, columns
+                                                                      });
         }
-        final double[] out = new double[nRows];
+        final double[] out = new double[rows];
 
         // perform multiplication block-wise, to ensure good cache behavior
-        int blockIndex = 0;
         for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int pStart = iBlock * BLOCK_SIZE;
+            final int pEnd   = Math.min(pStart + BLOCK_SIZE, rows);
             for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
-                final double[] block  = blocks[blockIndex];
-                final int      pStart = iBlock * BLOCK_SIZE;
-                final int      pEnd   = Math.min(pStart + BLOCK_SIZE, rows);
+                final double[] block  = blocks[iBlock * blockColumns + jBlock];
                 final int      qStart = jBlock * BLOCK_SIZE;
                 final int      qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
                 for (int p = pStart, k = 0; p < pEnd; ++p) {
@@ -800,7 +1203,6 @@
                     }
                     out[p] += sum;
                 }
-                ++blockIndex;
             }
         }
 
@@ -809,25 +1211,53 @@
     }
 
     /** {@inheritDoc} */
-    public RealVector operate(final RealVector v)
+    public double[] preMultiply(final double[] v)
         throws IllegalArgumentException {
-        try {
-            return operate((RealVectorImpl) v);
-        } catch (ClassCastException cce) {
-            return super.operate(v);
+
+        if (v.length != rows) {
+            throw MathRuntimeException.createIllegalArgumentException("vector length mismatch:" +
+                                                                      " got {0} but expected {1}",
+                                                                      new Object[] {
+                                                                          v.length, rows
+                                                                      });
         }
-    }
+        final double[] out = new double[columns];
+
+        // perform multiplication block-wise, to ensure good cache behavior
+        for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+            final int jWidth  = blockWidth(jBlock);
+            final int jWidth2 = jWidth  + jWidth;
+            final int jWidth3 = jWidth2 + jWidth;
+            final int jWidth4 = jWidth3 + jWidth;
+            final int qStart = jBlock * BLOCK_SIZE;
+            final int qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
+            for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+                final double[] block  = blocks[iBlock * blockColumns + jBlock];
+                final int      pStart = iBlock * BLOCK_SIZE;
+                final int      pEnd   = Math.min(pStart + BLOCK_SIZE, rows);
+                for (int q = qStart; q < qEnd; ++q) {
+                    int k = q - qStart;
+                    double sum = 0;
+                    int p = pStart;
+                    while (p < pEnd - 3) {
+                        sum += block[k]           * v[p]     +
+                               block[k + jWidth]  * v[p + 1] +
+                               block[k + jWidth2] * v[p + 2] +
+                               block[k + jWidth3] * v[p + 3];
+                        k += jWidth4;
+                        p += 4;
+                    }
+                    while (p < pEnd) {
+                        sum += block[k] * v[p++];
+                        k += jWidth;
+                    }
+                    out[q] += sum;
+                }
+            }
+        }
+
+        return out;
 
-    /**
-     * Returns the result of multiplying this by the vector <code>v</code>.
-     *
-     * @param v the vector to operate on
-     * @return this*v
-     * @throws IllegalArgumentException if columnDimension != v.size()
-     */
-    public RealVectorImpl operate(final RealVectorImpl v)
-        throws IllegalArgumentException {
-        return new RealVectorImpl(operate(v.getDataRef()), false);
     }
 
     /**

Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/linear/DenseRealMatrixTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/linear/DenseRealMatrixTest.java?rev=729174&r1=729173&r2=729174&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/org/apache/commons/math/linear/DenseRealMatrixTest.java (original)
+++ commons/proper/math/trunk/src/test/org/apache/commons/math/linear/DenseRealMatrixTest.java Tue Dec 23 15:30:33 2008
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.math.linear;
 
+import java.util.Arrays;
 import java.util.Random;
 
 import junit.framework.Test;
@@ -332,6 +333,32 @@
         }      
     }
 
+    public void testOperateLarge() {
+        int p = (7 * DenseRealMatrix.BLOCK_SIZE) / 2;
+        int q = (5 * DenseRealMatrix.BLOCK_SIZE) / 2;
+        int r =  3 * DenseRealMatrix.BLOCK_SIZE;
+        Random random = new Random(111007463902334l);
+        RealMatrix m1 = createRandomMatrix(random, p, q);
+        RealMatrix m2 = createRandomMatrix(random, q, r);
+        RealMatrix m1m2 = m1.multiply(m2);
+        for (int i = 0; i < r; ++i) {
+            checkArrays(m1m2.getColumn(i), m1.operate(m2.getColumn(i)));
+        }
+    }
+
+    public void testOperatePremultiplyLarge() {
+        int p = (7 * DenseRealMatrix.BLOCK_SIZE) / 2;
+        int q = (5 * DenseRealMatrix.BLOCK_SIZE) / 2;
+        int r =  3 * DenseRealMatrix.BLOCK_SIZE;
+        Random random = new Random(111007463902334l);
+        RealMatrix m1 = createRandomMatrix(random, p, q);
+        RealMatrix m2 = createRandomMatrix(random, q, r);
+        RealMatrix m1m2 = m1.multiply(m2);
+        for (int i = 0; i < p; ++i) {
+            checkArrays(m1m2.getRow(i), m2.preMultiply(m1.getRow(i)));
+        }
+    }
+
     /** test issue MATH-209 */
     public void testMath209() {
         RealMatrix a = new DenseRealMatrix(new double[][] {
@@ -507,14 +534,31 @@
         }
     }
     
+    public void testGetSetMatrixLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        RealMatrix sub = new DenseRealMatrix(n - 4, n - 4).scalarAdd(1);
+
+        m.setSubMatrix(sub.getData(), 2, 2);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if ((i < 2) || (i > n - 3) || (j < 2) || (j > n - 3)) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        assertEquals(sub, m.getSubMatrix(2, n - 3, 2, n - 3));
+
+    }
+    
     public void testGetRowMatrix() {
-        RealMatrix m = new DenseRealMatrix(subTestData);
+        RealMatrix m     = new DenseRealMatrix(subTestData);
         RealMatrix mRow0 = new DenseRealMatrix(subRow0);
         RealMatrix mRow3 = new DenseRealMatrix(subRow3);
-        assertEquals("Row0", mRow0, 
-                m.getRowMatrix(0));
-        assertEquals("Row3", mRow3, 
-                m.getRowMatrix(3));
+        assertEquals("Row0", mRow0, m.getRowMatrix(0));
+        assertEquals("Row3", mRow3, m.getRowMatrix(3));
         try {
             m.getRowMatrix(-1);
             fail("Expecting MatrixIndexException");
@@ -528,7 +572,7 @@
             // expected
         }
     }
-    
+
     public void testSetRowMatrix() {
         RealMatrix m = new DenseRealMatrix(subTestData);
         RealMatrix mRow3 = new DenseRealMatrix(subRow3);
@@ -549,6 +593,25 @@
         }
     }
     
+    public void testGetSetRowMatrixLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        RealMatrix sub = new DenseRealMatrix(1, n).scalarAdd(1);
+
+        m.setRowMatrix(2, sub);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if (i != 2) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        assertEquals(sub, m.getRowMatrix(2));
+
+    }
+    
     public void testGetColumnMatrix() {
         RealMatrix m = new DenseRealMatrix(subTestData);
         RealMatrix mColumn1 = new DenseRealMatrix(subColumn1);
@@ -589,6 +652,25 @@
         }
     }
 
+    public void testGetSetColumnMatrixLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        RealMatrix sub = new DenseRealMatrix(n, 1).scalarAdd(1);
+
+        m.setColumnMatrix(2, sub);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if (j != 2) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        assertEquals(sub, m.getColumnMatrix(2));
+
+    }
+    
     public void testGetRowVector() {
         RealMatrix m = new DenseRealMatrix(subTestData);
         RealVector mRow0 = new RealVectorImpl(subRow0[0]);
@@ -628,6 +710,25 @@
             // expected
         }
     }
+
+    public void testGetSetRowVectorLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        RealVector sub = new RealVectorImpl(n, 1.0);
+
+        m.setRowVector(2, sub);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if (i != 2) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        assertEquals(sub, m.getRowVector(2));
+
+    }
     
     public void testGetColumnVector() {
         RealMatrix m = new DenseRealMatrix(subTestData);
@@ -669,6 +770,25 @@
         }
     }
 
+    public void testGetSetColumnVectorLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        RealVector sub = new RealVectorImpl(n, 1.0);
+
+        m.setColumnVector(2, sub);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if (j != 2) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        assertEquals(sub, m.getColumnVector(2));
+
+    }
+    
     private RealVector columnToVector(double[][] column) {
         double[] data = new double[column.length];
         for (int i = 0; i < data.length; ++i) {
@@ -713,6 +833,26 @@
             // expected
         }
     }
+
+    public void testGetSetRowLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        double[] sub = new double[n];
+        Arrays.fill(sub, 1.0);
+
+        m.setRow(2, sub);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if (i != 2) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        checkArrays(sub, m.getRow(2));
+
+    }
     
     public void testGetColumn() {
         RealMatrix m = new DenseRealMatrix(subTestData);
@@ -754,6 +894,26 @@
         }
     }
 
+    public void testGetSetColumnLarge() {
+        int n = 3 * DenseRealMatrix.BLOCK_SIZE;
+        RealMatrix m = new DenseRealMatrix(n, n);
+        double[] sub = new double[n];
+        Arrays.fill(sub, 1.0);
+
+        m.setColumn(2, sub);
+        for (int i = 0; i < n; ++i) {
+            for (int j = 0; j < n; ++j) {
+                if (j != 2) {
+                    assertEquals(0.0, m.getEntry(i, j), 0.0);
+                } else {
+                    assertEquals(1.0, m.getEntry(i, j), 0.0);
+                }
+            }
+        }
+        checkArrays(sub, m.getColumn(2));
+
+    }
+    
     private double[] columnToArray(double[][] column) {
         double[] data = new double[column.length];
         for (int i = 0; i < data.length; ++i) {