commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l..@apache.org
Subject svn commit: r730837 - /commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.java
Date Fri, 02 Jan 2009 20:13:10 GMT
Author: luc
Date: Fri Jan  2 12:13:10 2009
New Revision: 730837

URL: http://svn.apache.org/viewvc?rev=730837&view=rev
Log:
added a way to build dense matrices from data already in block layout

Modified:
    commons/proper/math/trunk/src/java/org/apache/commons/math/linear/DenseRealMatrix.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=730837&r1=730836&r2=730837&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
Fri Jan  2 12:13:10 2009
@@ -103,57 +103,153 @@
         blockRows    = (rows    + BLOCK_SIZE - 1) / BLOCK_SIZE;
         blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;
 
-        // number of lines in smaller blocks at the bottom side of the matrix
-        final int lastLines = rows - (blockRows - 1) * BLOCK_SIZE;
-
-        // number of columns in smaller blocks at the right side of the matrix
-        final int lastColumns = columns - (blockColumns - 1) * BLOCK_SIZE;
-
         // allocate storage blocks, taking care of smaller ones at right and bottom
-        blocks       = new double[blockRows * blockColumns][];
+        blocks = new double[blockRows * blockColumns][];
         int blockIndex = 0;
-        for (int iBlock = 0; iBlock < (blockRows - 1); ++iBlock) {
-            for (int jBlock = 0; jBlock < (blockColumns - 1); ++jBlock) {
-                blocks[blockIndex++] = new double[BLOCK_SIZE * BLOCK_SIZE];
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            for (int jBlock = 0; jBlock < blockColumns; ++jBlock) {
+                blocks[blockIndex++] = new double[iHeight * blockWidth(jBlock)];
             }
-            blocks[blockIndex++] = new double[BLOCK_SIZE * lastColumns];
         }
-        for (int jBlock = 0; jBlock < (blockColumns - 1); ++jBlock) {
-            blocks[blockIndex++] = new double[lastLines * BLOCK_SIZE];
-        }
-        blocks[blockIndex++] = new double[lastLines * lastColumns];
 
     }
 
     /**
-     * Create a new RealMatrix using the input array as the underlying
-     * data array.
-     * <p>The input array is copied (and data rearranged), it is not referenced.</p>
+     * Create a new dense matrix copying entries from raw layout data.
+     * <p>The input array <em>must</em> already be in raw layout.</p>
+     * <p>Calling this constructor is equivalent to call:
+     * <pre>matrix = new DenseRealMatrix(rawData.length, rawData[0].length,
+     *                                   toBlocksLayout(rawData), false);</pre>
+     * </p>
+     * @param rawData data for new matrix, in raw layout
      *
-     * @param d data for new matrix
-     * @throws IllegalArgumentException if <code>d</code> is not rectangular
+     * @exception IllegalArgumentException if <code>blockData</code> shape is
+     * inconsistent with block layout
+     * @see #DenseRealMatrix(int, int, double[][], boolean)
+     */
+    public DenseRealMatrix(final double[][] rawData)
+        throws IllegalArgumentException {
+        this(rawData.length, rawData[0].length, toBlocksLayout(rawData), false);
+    }
+
+    /**
+     * Create a new dense matrix copying entries from block layout data.
+     * <p>The input array <em>must</em> already be in blocks layout.</p>
+     * @param rows  the number of rows in the new matrix
+     * @param columns  the number of columns in the new matrix
+     * @param blockData data for new matrix
+     * @param copyArray if true, the input array will be copied, otherwise
+     * it will be referenced
+     *
+     * @exception IllegalArgumentException if <code>blockData</code> shape is
+     * inconsistent with block layout
+     * @see #toBlocksLayout(double[][])
+     * @see #DenseRealMatrix(double[][])
+     */
+    public DenseRealMatrix(final int rows, final int columns,
+                           final double[][] blockData, final boolean copyArray)
+        throws IllegalArgumentException {
+
+        super(rows, columns);
+        this.rows    = rows;
+        this.columns = columns;
+
+        // number of blocks
+        blockRows    = (rows    + BLOCK_SIZE - 1) / BLOCK_SIZE;
+        blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;
+
+        if (copyArray) {
+            // allocate storage blocks, taking care of smaller ones at right and bottom
+            blocks = new double[blockRows * blockColumns][];
+        } else {
+            // reference existing array
+            blocks = blockData;
+        }
+
+        int index = 0;
+        for (int iBlock = 0; iBlock < blockRows; ++iBlock) {
+            final int iHeight = blockHeight(iBlock);
+            for (int jBlock = 0; jBlock < blockColumns; ++jBlock, ++index) {
+                if (blockData[index].length != iHeight * blockWidth(jBlock)) {
+                    throw MathRuntimeException.createIllegalArgumentException("wrong array
shape (block length = {0}, expected {1})",
+                                                                              new Object[]
{
+                                                                                  blockData[index].length,
+                                                                                  iHeight
* blockWidth(jBlock)
+                                                                              });
+                }
+                if (copyArray) {
+                    blocks[index] = blockData[index].clone();
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Convert a data array from raw layout to blocks layout.
+     * <p>
+     * Raw layout is the straightforward layout where element at row i and
+     * column j is in array element <code>rawData[i][j]</code>. Blocks layout
+     * is the layout used in {@link DenseRealMatrix} instances, where the matrix
+     * is split in square blocks (except at right and bottom side where blocks may
+     * be rectangular to fit matrix size) and each block is stored in a flattened
+     * one-dimensional array.
+     * </p>
+     * <p>
+     * This method creates an array in blocks layout from an input array in raw layout.
+     * It can be used to provide the array argument of the {@link
+     * DenseRealMatrix#DenseRealMatrix(int, int, double[][], boolean)} constructor.
+     * </p>
+     * @param rawData data array in raw layout
+     * @return a new data array containing the same entries but in blocks layout
+     * @exception IllegalArgumentException if <code>rawData</code> is not rectangular
      *  (not all rows have the same length)
+     * @see #DenseRealMatrix(int, int, double[][], boolean)
      */
-    public DenseRealMatrix(final double[][] d)
+    public static double[][] toBlocksLayout(final double[][] rawData)
         throws IllegalArgumentException {
 
-        // build empty instance
-        this(d.length, d[0].length);
+        final int rows         = rawData.length;
+        final int columns      = rawData[0].length;
+        final int blockRows    = (rows    + BLOCK_SIZE - 1) / BLOCK_SIZE;
+        final int blockColumns = (columns + BLOCK_SIZE - 1) / BLOCK_SIZE;
 
-        // fill in instance
-        for (int i = 0; i < d.length; ++i) {
-            final double[] rowI = d[i];
-            if (rowI.length != columns) {
-                throw MathRuntimeException.createIllegalArgumentException("some rows have
length {0} while others have length {1}",
-                                                                          new Object[] {
-                                                                              columns, rowI.length
-                                                                          }); 
+        // safety checks
+        for (int i = 0; i < rawData.length; ++i) {
+            final int length = rawData[i].length;
+            if (length != columns) {
+                throw MathRuntimeException.createIllegalArgumentException(
+                        "some rows have length {0} while others have length {1}",
+                        new Object[] { columns, length }); 
             }
-            for (int j = 0; j < rowI.length; ++j) {
-                setEntry(i, j, rowI[j]);
+        }
+
+        // convert array
+        final double[][] blocks = new double[blockRows * blockColumns][];
+        for (int iBlock = 0, blockIndex = 0; iBlock < blockRows; ++iBlock) {
+            final int pStart  = iBlock * BLOCK_SIZE;
+            final int pEnd    = Math.min(pStart + BLOCK_SIZE, rows);
+            final int iHeight = pEnd - pStart;
+            for (int jBlock = 0; jBlock < blockColumns; ++jBlock, ++blockIndex) {
+                final int qStart = jBlock * BLOCK_SIZE;
+                final int qEnd   = Math.min(qStart + BLOCK_SIZE, columns);
+                final int jWidth = qEnd - qStart;
+
+                // allocate new block
+                final double[] block = new double[iHeight * jWidth];
+                blocks[blockIndex] = block;
+
+                // copy data
+                for (int p = pStart, index = 0; p < pEnd; ++p, index += jWidth) {
+                    System.arraycopy(rawData[p], qStart, block, index, jWidth);
+                }
+
             }
         }
 
+        return blocks;
+
     }
 
     /** {@inheritDoc} */



Mime
View raw message