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/27 21:55:12 UTC

svn commit: r729673 - in /commons/proper/math/trunk/src: java/org/apache/commons/math/linear/ site/xdoc/ test/org/apache/commons/math/linear/

Author: luc
Date: Sat Dec 27 12:55:12 2008
New Revision: 729673

URL: http://svn.apache.org/viewvc?rev=729673&view=rev
Log:
Added method to walk matrix entries with or without changing them in the
visitor design pattern sense. Two different orders can be used, row by row
of following internal storage. Internal order should be preferred when no
specific order is needed, because it will be more cache efficient.

Added:
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java   (with props)
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java   (with props)
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java   (with props)
Modified:
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/AbstractRealMatrix.java
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrix.java
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixImpl.java
    commons/proper/math/trunk/src/site/xdoc/changes.xml
    commons/proper/math/trunk/src/test/org/apache/commons/math/linear/DenseRealMatrixTest.java
    commons/proper/math/trunk/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/AbstractRealMatrix.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/AbstractRealMatrix.java?rev=729673&r1=729672&r2=729673&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/AbstractRealMatrix.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/AbstractRealMatrix.java Sat Dec 27 12:55:12 2008
@@ -691,6 +691,90 @@
     }
 
     /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixChangingVisitor visitor)
+        throws MatrixVisitorException {
+        final int rows    = getRowDimension();
+        final int columns = getColumnDimension();
+        for (int row = 0; row < rows; ++row) {
+            for (int column = 0; column < columns; ++column) {
+                final double oldValue = getEntry(row, column);
+                final double newValue = visitor.visit(row, column, oldValue);
+                setEntry(row, column, newValue);
+            }
+        }
+        lu = null;
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixPreservingVisitor visitor)
+        throws MatrixVisitorException {
+        final int rows    = getRowDimension();
+        final int columns = getColumnDimension();
+        for (int row = 0; row < rows; ++row) {
+            for (int column = 0; column < columns; ++column) {
+                visitor.visit(row, column, getEntry(row, column));
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixChangingVisitor visitor,
+                               final int startRow, final int endRow,
+                               final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int row = startRow; row <= endRow; ++row) {
+            for (int column = startColumn; column <= endColumn; ++column) {
+                final double oldValue = getEntry(row, column);
+                final double newValue = visitor.visit(row, column, oldValue);
+                setEntry(row, column, newValue);
+            }
+        }
+        lu = null;
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixPreservingVisitor visitor,
+                               final int startRow, final int endRow,
+                               final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int row = startRow; row <= endRow; ++row) {
+            for (int column = startColumn; column <= endColumn; ++column) {
+                visitor.visit(row, column, getEntry(row, column));
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixChangingVisitor visitor)
+        throws MatrixVisitorException {
+        walkInRowOrder(visitor);
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixPreservingVisitor visitor)
+        throws MatrixVisitorException {
+        walkInRowOrder(visitor);
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixChangingVisitor visitor,
+                                    final int startRow, final int endRow,
+                                    final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixPreservingVisitor visitor,
+                                    final int startRow, final int endRow,
+                                    final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        walkInRowOrder(visitor, startRow, endRow, startColumn, endColumn);
+    }
+
+    /** {@inheritDoc} */
     @Deprecated
     public double[] solve(final double[] b)
         throws IllegalArgumentException, InvalidMatrixException {

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=729673&r1=729672&r2=729673&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 Sat Dec 27 12:55:12 2008
@@ -23,12 +23,35 @@
 import org.apache.commons.math.MathRuntimeException;
 
 /**
- * Implementation of RealMatrix using a flat arrays to store square blocks of the matrix.
+ * Cache-friendly implementation of RealMatrix using a flat arrays to store
+ * square blocks of the matrix.
  * <p>
- * This implementation is cache-friendly. Square blocks are stored as small arrays and allow
- * efficient traversal of data both in row major direction and columns major direction. This
- * greatly increases performances for algorithms that use crossed directions loops like
- * multiplication or transposition.
+ * This implementation is specially designed to be cache-friendly. Square blocks are
+ * stored as small arrays and allow efficient traversal of data both in row major direction
+ * and columns major direction, one block at a time. This greatly increases performances
+ * for algorithms that use crossed directions loops like multiplication or transposition.
+ * </p>
+ * <p>
+ * The size of square blocks is a static parameter. It may be tuned according to the cache
+ * size of the target computer processor. As a rule of thumbs, it should be the largest
+ * value that allows three blocks to be simultaneously cached (this is necessary for example
+ * for matrix multiplication). The default value is to use 52x52 blocks which is well suited
+ * for processors with 64k L1 cache (one block holds 2704 values or 21632 bytes). This value
+ * could be lowered to 36x36 for processors with 32k L1 cache.
+ * </p>
+ * <p>
+ * The regular blocks represent {@link #BLOCK_SIZE} x {@link #BLOCK_SIZE} squares. Blocks
+ * at right hand side and bottom side which may be smaller to fit matrix dimensions. The square
+ * blocks are flattened in row major order in single dimension arrays which are therefore
+ * {@link #BLOCK_SIZE}<sup>2</sup> elements long for regular blocks. The blocks are themselves
+ * organized in row major order.
+ * </p>
+ * <p>
+ * As an example, for a block size of 52x52, a 100x60 matrix would be stored in 4 blocks.
+ * Block 0 would be a double[2704] array holding the upper left 52x52 square, block 1 would be
+ * a double[416] array holding the upper right 52x8 rectangle, block 2 would be a double[2496]
+ * array holding the lower left 48x52 rectangle and block 3 would be a double[384] array
+ * holding the lower right 48x8 rectangle.
  * </p>
  * <p>
  * The layout complexity overhead versus simple mapping of matrices to java
@@ -1260,6 +1283,184 @@
 
     }
 
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixChangingVisitor visitor)
+        throws MatrixVisitorException {
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int pStart = iBlock * BLOCK_SIZE;
+            final int pEnd   = Math.min(pStart + BLOCK_SIZE, rows);
+            for (int p = pStart; p < pEnd; ++p) {
+                for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+                    final int jWidth = blockWidth(jBlock);
+                    final int qStart = jBlock * BLOCK_SIZE;
+                    final int qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
+                    final double[] block = blocks[iBlock * blockColumns + jBlock];
+                    for (int q = qStart, k = (p - pStart) * jWidth; q < qEnd; ++q, ++k) {
+                        block[k] = visitor.visit(p, q, block[k]);
+                    }
+                }
+             }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixPreservingVisitor visitor)
+        throws MatrixVisitorException {
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int pStart = iBlock * BLOCK_SIZE;
+            final int pEnd   = Math.min(pStart + BLOCK_SIZE, rows);
+            for (int p = pStart; p < pEnd; ++p) {
+                for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+                    final int jWidth = blockWidth(jBlock);
+                    final int qStart = jBlock * BLOCK_SIZE;
+                    final int qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
+                    final double[] block = blocks[iBlock * blockColumns + jBlock];
+                    for (int q = qStart, k = (p - pStart) * jWidth; q < qEnd; ++q, ++k) {
+                        visitor.visit(p, q, block[k]);
+                    }
+                }
+             }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixChangingVisitor visitor,
+                               final int startRow, final int endRow,
+                               final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock) {
+            final int p0     = iBlock * BLOCK_SIZE;
+            final int pStart = Math.max(startRow, p0);
+            final int pEnd   = Math.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
+            for (int p = pStart; p < pEnd; ++p) {
+                for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock) {
+                    final int jWidth = blockWidth(jBlock);
+                    final int q0     = jBlock * BLOCK_SIZE;
+                    final int qStart = Math.max(startColumn, q0);
+                    final int qEnd   = Math.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
+                    final double[] block = blocks[iBlock * blockColumns + jBlock];
+                    for (int q = qStart, k = (p - p0) * jWidth + qStart - q0; q < qEnd; ++q, ++k) {
+                        block[k] = visitor.visit(p, q, block[k]);
+                    }
+                }
+             }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixPreservingVisitor visitor,
+                               final int startRow, final int endRow,
+                               final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock) {
+            final int p0     = iBlock * BLOCK_SIZE;
+            final int pStart = Math.max(startRow, p0);
+            final int pEnd   = Math.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
+            for (int p = pStart; p < pEnd; ++p) {
+                for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock) {
+                    final int jWidth = blockWidth(jBlock);
+                    final int q0     = jBlock * BLOCK_SIZE;
+                    final int qStart = Math.max(startColumn, q0);
+                    final int qEnd   = Math.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
+                    final double[] block = blocks[iBlock * blockColumns + jBlock];
+                    for (int q = qStart, k = (p - p0) * jWidth + qStart - q0; q < qEnd; ++q, ++k) {
+                        visitor.visit(p, q, block[k]);
+                    }
+                }
+             }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixChangingVisitor visitor)
+        throws MatrixVisitorException {
+        for (int iBlock = 0, blockIndex = 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, ++blockIndex) {
+                final int qStart = jBlock * BLOCK_SIZE;
+                final int qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
+                final double[] block = blocks[blockIndex];
+                for (int p = pStart, k = 0; p < pEnd; ++p) {
+                    for (int q = qStart; q < qEnd; ++q, ++k) {
+                        block[k] = visitor.visit(p, q, block[k]);
+                    }
+                }
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixPreservingVisitor visitor)
+        throws MatrixVisitorException {
+        for (int iBlock = 0, blockIndex = 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, ++blockIndex) {
+                final int qStart = jBlock * BLOCK_SIZE;
+                final int qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
+                final double[] block = blocks[blockIndex];
+                for (int p = pStart, k = 0; p < pEnd; ++p) {
+                    for (int q = qStart; q < qEnd; ++q, ++k) {
+                        visitor.visit(p, q, block[k]);
+                    }
+                }
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixChangingVisitor visitor,
+                                    final int startRow, final int endRow,
+                                    final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock) {
+            final int p0     = iBlock * BLOCK_SIZE;
+            final int pStart = Math.max(startRow, p0);
+            final int pEnd   = Math.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
+            for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock) {
+                final int jWidth = blockWidth(jBlock);
+                final int q0     = jBlock * BLOCK_SIZE;
+                final int qStart = Math.max(startColumn, q0);
+                final int qEnd   = Math.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
+                final double[] block = blocks[iBlock * blockColumns + jBlock];
+                for (int p = pStart; p < pEnd; ++p) {
+                    for (int q = qStart, k = (p - p0) * jWidth + qStart - q0; q < qEnd; ++q, ++k) {
+                        block[k] = visitor.visit(p, q, block[k]);
+                    }
+                }
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInInternalOrder(final RealMatrixPreservingVisitor visitor,
+                                    final int startRow, final int endRow,
+                                    final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int iBlock = startRow / BLOCK_SIZE; iBlock < 1 + endRow / BLOCK_SIZE; ++iBlock) {
+            final int p0     = iBlock * BLOCK_SIZE;
+            final int pStart = Math.max(startRow, p0);
+            final int pEnd   = Math.min((iBlock + 1) * BLOCK_SIZE, 1 + endRow);
+            for (int jBlock = startColumn / BLOCK_SIZE; jBlock < 1 + endColumn / BLOCK_SIZE; ++jBlock) {
+                final int jWidth = blockWidth(jBlock);
+                final int q0     = jBlock * BLOCK_SIZE;
+                final int qStart = Math.max(startColumn, q0);
+                final int qEnd   = Math.min((jBlock + 1) * BLOCK_SIZE, 1 + endColumn);
+                final double[] block = blocks[iBlock * blockColumns + jBlock];
+                for (int p = pStart; p < pEnd; ++p) {
+                    for (int q = qStart, k = (p - p0) * jWidth + qStart - q0; q < qEnd; ++q, ++k) {
+                        visitor.visit(p, q, block[k]);
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * Get the height of a block.
      * @param blockRow row index (in block sense) of the block

Added: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java?rev=729673&view=auto
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java (added)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java Sat Dec 27 12:55:12 2008
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.linear;
+
+import org.apache.commons.math.MathRuntimeException;
+
+/**
+ * Thrown when a visitor encounters an error while processing a matrix entry.
+ * @version $Revision$ $Date$
+ */
+public class MatrixVisitorException extends MathRuntimeException {
+
+    /** Serializable version identifier */
+    private static final long serialVersionUID = 3814333035048617048L;
+
+    /**
+     * Constructs a new instance with specified formatted detail message.
+     * @param pattern format specifier
+     * @param arguments format arguments
+     */
+    public MatrixVisitorException(final String pattern, final Object[] arguments) {
+      super(pattern, arguments);
+    }
+
+}

Propchange: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/MatrixVisitorException.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrix.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrix.java?rev=729673&r1=729672&r2=729673&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrix.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrix.java Sat Dec 27 12:55:12 2008
@@ -129,9 +129,9 @@
      * counting from 0 to n-1.
      *
      * @param startRow Initial row index
-     * @param endRow Final row index
+     * @param endRow Final row index (inclusive)
      * @param startColumn Initial column index
-     * @param endColumn Final column index
+     * @param endColumn Final column index (inclusive)
      * @return The subMatrix containing the data of the
      *         specified rows and columns
      * @exception MatrixIndexException  if the indices are not valid
@@ -499,6 +499,163 @@
     RealVector preMultiply(RealVector v) throws IllegalArgumentException;
 
     /**
+     * Visit (and possibly change) all matrix entries in row order.
+     * @param visitor visitor used to process all matrix entries
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInRowOrder(RealMatrixChangingVisitor visitor) throws MatrixVisitorException;
+
+    /**
+     * Visit (but don't change) all matrix entries in row order.
+     * @param visitor visitor used to process all matrix entries
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInRowOrder(RealMatrixPreservingVisitor visitor) throws MatrixVisitorException;
+
+    /**
+     * Visit (and possibly change) all matrix entries in row order.
+     * @param visitor visitor used to process all matrix entries
+     * @param startRow Initial row index
+     * @param endRow Final row index (inclusive)
+     * @param startColumn Initial column index
+     * @param endColumn Final column index
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @exception MatrixIndexException  if the indices are not valid
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInRowOrder(RealMatrixChangingVisitor visitor,
+                        int startRow, int endRow, int startColumn, int endColumn)
+        throws MatrixIndexException, MatrixVisitorException;
+
+    /**
+     * Visit (but don't change) all matrix entries in row order.
+     * @param visitor visitor used to process all matrix entries
+     * @param startRow Initial row index
+     * @param endRow Final row index (inclusive)
+     * @param startColumn Initial column index
+     * @param endColumn Final column index
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @exception MatrixIndexException  if the indices are not valid
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInRowOrder(RealMatrixPreservingVisitor visitor,
+                        int startRow, int endRow, int startColumn, int endColumn)
+        throws MatrixIndexException, MatrixVisitorException;
+
+    /**
+     * Visit (and possibly change) all matrix entries in row order.
+     * <p>The matrix internal order depends on the exact matrix class. It may be
+     * different from traditional row order, but is generally faster. If there is no need
+     * for an explicit walk order, this method should be preferred to the {@link
+     * #walkInRowOrder(RealMatrixChangingVisitor)} one.</p>
+     * @param visitor visitor used to process all matrix entries
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInInternalOrder(RealMatrixChangingVisitor visitor) throws MatrixVisitorException;
+
+    /**
+     * Visit (but don't change) all matrix entries in row order.
+     * <p>The matrix internal order depends on the exact matrix class. It may be
+     * different from traditional row order, but is generally faster. If there is no need
+     * for an explicit walk order, this method should be preferred to the {@link
+     * #walkInRowOrder(RealMatrixPreservingVisitor)} one.</p>
+     * @param visitor visitor used to process all matrix entries
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInInternalOrder(RealMatrixPreservingVisitor visitor) throws MatrixVisitorException;
+
+    /**
+     * Visit (and possibly change) all matrix entries in row order.
+     * <p>The matrix internal order depends on the exact matrix class. It may be
+     * different from traditional row order, but is generally faster. If there is no need
+     * for an explicit walk order, this method should be preferred to the {@link
+     * #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)} one.</p>
+     * @param visitor visitor used to process all matrix entries
+     * @param startRow Initial row index
+     * @param endRow Final row index (inclusive)
+     * @param startColumn Initial column index
+     * @param endColumn Final column index (inclusive)
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @exception MatrixIndexException  if the indices are not valid
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     */
+    void walkInInternalOrder(RealMatrixChangingVisitor visitor,
+                             int startRow, int endRow, int startColumn, int endColumn)
+        throws MatrixIndexException, MatrixVisitorException;
+
+    /**
+     * Visit (but don't change) all matrix entries in row order.
+     * Visit (and possibly change) all matrix entries in row order.
+     * <p>The matrix internal order depends on the exact matrix class. It may be
+     * different from traditional row order, but is generally faster. If there is no need
+     * for an explicit walk order, this method should be preferred to the {@link
+     * #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)} one.</p>
+     * @param visitor visitor used to process all matrix entries
+     * @param startRow Initial row index
+     * @param endRow Final row index (inclusive)
+     * @param startColumn Initial column index
+     * @param endColumn Final column index (inclusive)
+     * @exception  MatrixVisitorException if the visitor cannot process an entry
+     * @exception MatrixIndexException  if the indices are not valid
+     * @see #walkInRowOrder(RealMatrixChangingVisitor)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor)
+     * @see #walkInRowOrder(RealMatrixChangingVisitor, int, int, int, int)
+     * @see #walkInRowOrder(RealMatrixPreservingVisitor, int, int, int, int)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor)
+     * @see #walkInInternalOrder(RealMatrixPreservingVisitor)
+     * @see #walkInInternalOrder(RealMatrixChangingVisitor, int, int, int, int)
+     */
+    void walkInInternalOrder(RealMatrixPreservingVisitor visitor,
+                             int startRow, int endRow, int startColumn, int endColumn)
+        throws MatrixIndexException, MatrixVisitorException;
+
+    /**
      * Returns the solution vector for a linear system with coefficient
      * matrix = this and constant vector = <code>b</code>.
      *

Added: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java?rev=729673&view=auto
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java (added)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java Sat Dec 27 12:55:12 2008
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.linear;
+
+import java.io.Serializable;
+
+/**
+ * Interface defining a visitor for matrix entries.
+ * 
+ * @version $Revision$ $Date$
+ * @since 2.0
+ */
+public interface RealMatrixChangingVisitor extends Serializable {
+
+    /**
+     * Visit one matrix entry.
+     * @param row row index of the entry
+     * @param column column index of the entry
+     * @param value current value of the entry
+     * @return the new value to be set for the entry
+     * @throws MatrixVisitorException if something wrong occurs
+     */
+    double visit(int row, int column, double value)
+        throws MatrixVisitorException;
+
+}

Propchange: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixChangingVisitor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixImpl.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixImpl.java?rev=729673&r1=729672&r2=729673&view=diff
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixImpl.java (original)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixImpl.java Sat Dec 27 12:55:12 2008
@@ -459,6 +459,60 @@
 
     }
 
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixChangingVisitor visitor)
+        throws MatrixVisitorException {
+        final int rows    = getRowDimension();
+        final int columns = getColumnDimension();
+        for (int i = 0; i < rows; ++i) {
+            final double[] rowI = data[i];
+            for (int j = 0; j < columns; ++j) {
+                rowI[j] = visitor.visit(i, j, rowI[j]);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixPreservingVisitor visitor)
+        throws MatrixVisitorException {
+        final int rows    = getRowDimension();
+        final int columns = getColumnDimension();
+        for (int i = 0; i < rows; ++i) {
+            final double[] rowI = data[i];
+            for (int j = 0; j < columns; ++j) {
+                visitor.visit(i, j, rowI[j]);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixChangingVisitor visitor,
+                               final int startRow, final int endRow,
+                               final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int i = startRow; i <= endRow; ++i) {
+            final double[] rowI = data[i];
+            for (int j = startColumn; j <= endColumn; ++j) {
+                rowI[j] = visitor.visit(i, j, rowI[j]);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void walkInRowOrder(final RealMatrixPreservingVisitor visitor,
+                               final int startRow, final int endRow,
+                               final int startColumn, final int endColumn)
+        throws MatrixIndexException, MatrixVisitorException {
+        checkSubMatrixIndex(startRow, endRow, startColumn, endColumn);
+        for (int i = startRow; i <= endRow; ++i) {
+            final double[] rowI = data[i];
+            for (int j = startColumn; j <= endColumn; ++j) {
+                visitor.visit(i, j, rowI[j]);
+            }
+        }
+    }
+
     /**
      * Returns a fresh copy of the underlying data array.
      *

Added: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java?rev=729673&view=auto
==============================================================================
--- commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java (added)
+++ commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java Sat Dec 27 12:55:12 2008
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.linear;
+
+import java.io.Serializable;
+
+/**
+ * Interface defining a visitor for matrix entries.
+ * 
+ * @version $Revision$ $Date$
+ * @since 2.0
+ */
+public interface RealMatrixPreservingVisitor extends Serializable {
+
+    /**
+     * Visit one matrix entry.
+     * @param row row index of the entry
+     * @param column column index of the entry
+     * @param value current value of the entry
+     * @throws MatrixVisitorException if something wrong occurs
+     */
+    void visit(int row, int column, double value)
+        throws MatrixVisitorException;
+
+}

Propchange: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/java/org/apache/commons/math/linear/RealMatrixPreservingVisitor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=729673&r1=729672&r2=729673&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Sat Dec 27 12:55:12 2008
@@ -39,6 +39,12 @@
   </properties>
   <body>
     <release version="2.0" date="TBD" description="TBD">
+      <action dev="luc" type="add" >
+        Added method to walk matrix entries with or without changing them in the
+        visitor design pattern sense. Two different orders can be used, row by row
+        of following internal storage. Internal order should be preferred when no
+        specific order is needed, because it will be more cache efficient.
+      </action>
       <action dev="luc" type="add" issue="MATH-215" due-to="Bernhard Grünewaldt">
         Added Fast Hadamard Transform.
       </action>

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=729673&r1=729672&r2=729673&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 Sat Dec 27 12:55:12 2008
@@ -1019,7 +1019,73 @@
         }
         
     }
+
+    public void testWalk() {
+        int rows    = 150;
+        int columns = 75;
+
+        RealMatrix m = new DenseRealMatrix(rows, columns);
+        m.walkInRowOrder(new SetVisitor());
+        GetVisitor getVisitor = new GetVisitor();
+        m.walkInInternalOrder(getVisitor);
+        assertEquals(rows * columns, getVisitor.getCount());
+
+        m = new DenseRealMatrix(rows, columns);
+        m.walkInRowOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
+        getVisitor = new GetVisitor();
+        m.walkInInternalOrder(getVisitor, 1, rows - 2, 1, columns - 2);
+        assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
+        for (int i = 0; i < rows; ++i) {
+            assertEquals(0.0, m.getEntry(i, 0), 0);                    
+            assertEquals(0.0, m.getEntry(i, columns - 1), 0);
+        }
+        for (int j = 0; j < columns; ++j) {
+            assertEquals(0.0, m.getEntry(0, j), 0);                    
+            assertEquals(0.0, m.getEntry(rows - 1, j), 0);
+        }
+
+
+        m = new DenseRealMatrix(rows, columns);
+        m.walkInInternalOrder(new SetVisitor());
+        getVisitor = new GetVisitor();
+        m.walkInRowOrder(getVisitor);
+        assertEquals(rows * columns, getVisitor.getCount());
+
+        m = new DenseRealMatrix(rows, columns);
+        m.walkInInternalOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
+        getVisitor = new GetVisitor();
+        m.walkInRowOrder(getVisitor, 1, rows - 2, 1, columns - 2);
+        assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
+        for (int i = 0; i < rows; ++i) {
+            assertEquals(0.0, m.getEntry(i, 0), 0);                    
+            assertEquals(0.0, m.getEntry(i, columns - 1), 0);
+        }
+        for (int j = 0; j < columns; ++j) {
+            assertEquals(0.0, m.getEntry(0, j), 0);                    
+            assertEquals(0.0, m.getEntry(rows - 1, j), 0);
+        }
+
+    }
     
+    private static class SetVisitor implements RealMatrixChangingVisitor {
+        private static final long serialVersionUID = -5724808764099124932L;
+        public double visit(int i, int j, double value) {
+            return i + j / 1024.0;
+        }
+    }
+
+    private static class GetVisitor implements RealMatrixPreservingVisitor {
+        private static final long serialVersionUID = 1299771253908695242L;
+        int count = 0;
+        public void visit(int i, int j, double value) {
+            ++count;
+            assertEquals(i + j / 1024.0, value, 0.0);
+        }
+        public int getCount() {
+            return count;
+        }
+    };
+
     //--------------- -----------------Protected methods
         
     /** verifies that two matrices are close (1-norm) */              

Modified: commons/proper/math/trunk/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java?rev=729673&r1=729672&r2=729673&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java (original)
+++ commons/proper/math/trunk/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java Sat Dec 27 12:55:12 2008
@@ -805,7 +805,73 @@
         }
         
     }
+
+    public void testWalk() {
+        int rows    = 150;
+        int columns = 75;
+
+        RealMatrix m = new RealMatrixImpl(rows, columns);
+        m.walkInRowOrder(new SetVisitor());
+        GetVisitor getVisitor = new GetVisitor();
+        m.walkInInternalOrder(getVisitor);
+        assertEquals(rows * columns, getVisitor.getCount());
+
+        m = new RealMatrixImpl(rows, columns);
+        m.walkInRowOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
+        getVisitor = new GetVisitor();
+        m.walkInInternalOrder(getVisitor, 1, rows - 2, 1, columns - 2);
+        assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
+        for (int i = 0; i < rows; ++i) {
+            assertEquals(0.0, m.getEntry(i, 0), 0);                    
+            assertEquals(0.0, m.getEntry(i, columns - 1), 0);
+        }
+        for (int j = 0; j < columns; ++j) {
+            assertEquals(0.0, m.getEntry(0, j), 0);                    
+            assertEquals(0.0, m.getEntry(rows - 1, j), 0);
+        }
+
+
+        m = new RealMatrixImpl(rows, columns);
+        m.walkInInternalOrder(new SetVisitor());
+        getVisitor = new GetVisitor();
+        m.walkInRowOrder(getVisitor);
+        assertEquals(rows * columns, getVisitor.getCount());
+
+        m = new RealMatrixImpl(rows, columns);
+        m.walkInInternalOrder(new SetVisitor(), 1, rows - 2, 1, columns - 2);
+        getVisitor = new GetVisitor();
+        m.walkInRowOrder(getVisitor, 1, rows - 2, 1, columns - 2);
+        assertEquals((rows - 2) * (columns - 2), getVisitor.getCount());
+        for (int i = 0; i < rows; ++i) {
+            assertEquals(0.0, m.getEntry(i, 0), 0);                    
+            assertEquals(0.0, m.getEntry(i, columns - 1), 0);
+        }
+        for (int j = 0; j < columns; ++j) {
+            assertEquals(0.0, m.getEntry(0, j), 0);                    
+            assertEquals(0.0, m.getEntry(rows - 1, j), 0);
+        }
+
+    }
     
+    private static class SetVisitor implements RealMatrixChangingVisitor {
+        private static final long serialVersionUID = -5724808764099124932L;
+        public double visit(int i, int j, double value) {
+            return i + j / 1024.0;
+        }
+    }
+
+    private static class GetVisitor implements RealMatrixPreservingVisitor {
+        private static final long serialVersionUID = 1299771253908695242L;
+        int count = 0;
+        public void visit(int i, int j, double value) {
+            ++count;
+            assertEquals(i + j / 1024.0, value, 0.0);
+        }
+        public int getCount() {
+            return count;
+        }
+    };
+
     //--------------- -----------------Protected methods
         
     /** verifies that two matrices are close (1-norm) */