Author: luc
Date: Sun Jan  4 10:08:18 2009
New Revision: 731307

URL: http://svn.apache.org/viewvc?rev=731307&view=rev
Log:
fixed a dimension error with under-determined problems
removed IllegalStateException
create a DenseRealMatrix when solving A.X = B

Modified:
    
commons/proper/math/trunk/src/java/org/apache/commons/math/linear/QRDecompositionImpl.java

Modified: 
commons/proper/math/trunk/src/java/org/apache/commons/math/linear/QRDecompositionImpl.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/linear/QRDecompositionImpl.java?rev=731307&r1=731306&r2=731307&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/linear/QRDecompositionImpl.java
 (original)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/linear/QRDecompositionImpl.java
 Sun Jan  4 10:08:18 2009
@@ -17,6 +17,10 @@
 
 package org.apache.commons.math.linear;
 
+import java.util.Arrays;
+
+import org.apache.commons.math.MathRuntimeException;
+
 
 /**
  * Calculates the QR-decomposition of a matrix.
@@ -73,7 +77,7 @@
         final int m = matrix.getRowDimension();
         final int n = matrix.getColumnDimension();
         qrt = matrix.transpose().getData();
-        rDiag = new double[n];
+        rDiag = new double[Math.min(m, n)];
         cachedQ  = null;
         cachedQT = null;
         cachedR  = null;
@@ -170,8 +174,7 @@
     }
 
     /** {...@inheritdoc} */
-    public RealMatrix getQ()
-        throws IllegalStateException {
+    public RealMatrix getQ() {
         if (cachedQ == null) {
             cachedQ = getQT().transpose();
         }
@@ -179,8 +182,7 @@
     }
 
     /** {...@inheritdoc} */
-    public RealMatrix getQT()
-        throws IllegalStateException {
+    public RealMatrix getQT() {
 
         if (cachedQT == null) {
 
@@ -224,8 +226,7 @@
     }
 
     /** {...@inheritdoc} */
-    public RealMatrix getH()
-        throws IllegalStateException {
+    public RealMatrix getH() {
 
         if (cachedH == null) {
 
@@ -278,8 +279,7 @@
         }
 
         /** {...@inheritdoc} */
-        public boolean isNonSingular()
-        throws IllegalStateException {
+        public boolean isNonSingular() {
 
             for (double diag : rDiag) {
                 if (diag == 0) {
@@ -292,12 +292,14 @@
 
         /** {...@inheritdoc} */
         public double[] solve(double[] b)
-        throws IllegalStateException, IllegalArgumentException, 
InvalidMatrixException {
+        throws IllegalArgumentException, InvalidMatrixException {
 
             final int n = qrt.length;
             final int m = qrt[0].length;
             if (b.length != m) {
-                throw new IllegalArgumentException("Incorrect row dimension");
+                throw MathRuntimeException.createIllegalArgumentException(
+                        "vector length mismatch: got {0} but expected {1}",
+                        new Object[] { b.length, m });
             }
             if (!isNonSingular()) {
                 throw new SingularMatrixException();
@@ -323,7 +325,7 @@
             }
 
             // solve triangular system R.x = y
-            for (int row = n - 1; row >= 0; --row) {
+            for (int row = rDiag.length - 1; row >= 0; --row) {
                 y[row] /= rDiag[row];
                 final double yRow   = y[row];
                 final double[] qrtRow = qrt[row];
@@ -339,7 +341,7 @@
 
         /** {...@inheritdoc} */
         public RealVector solve(RealVector b)
-        throws IllegalStateException, IllegalArgumentException, 
InvalidMatrixException {
+        throws IllegalArgumentException, InvalidMatrixException {
             try {
                 return solve((RealVectorImpl) b);
             } catch (ClassCastException cce) {
@@ -351,76 +353,103 @@
          * <p>The A matrix is implicit here. It is </p>
          * @param b right-hand side of the equation A &times; X = B
          * @return a vector X that minimizes the two norm of A &times; X - B
-         * @exception IllegalStateException if {...@link 
#decompose(RealMatrix) decompose}
-         * has not been called
          * @throws IllegalArgumentException if matrices dimensions don't match
          * @throws InvalidMatrixException if decomposed matrix is singular
          */
         public RealVectorImpl solve(RealVectorImpl b)
-        throws IllegalStateException, IllegalArgumentException, 
InvalidMatrixException {
+        throws IllegalArgumentException, InvalidMatrixException {
             return new RealVectorImpl(solve(b.getDataRef()), false);
         }
 
         /** {...@inheritdoc} */
         public RealMatrix solve(RealMatrix b)
-        throws IllegalStateException, IllegalArgumentException, 
InvalidMatrixException {
+        throws IllegalArgumentException, InvalidMatrixException {
 
             final int n = qrt.length;
             final int m = qrt[0].length;
             if (b.getRowDimension() != m) {
-                throw new IllegalArgumentException("Incorrect row dimension");
+                throw MathRuntimeException.createIllegalArgumentException(
+                        "dimensions mismatch: got {0}x{1} but expected 
{2}x{3}",
+                        new Object[] { b.getRowDimension(), 
b.getColumnDimension(), m, "n"});
             }
             if (!isNonSingular()) {
                 throw new SingularMatrixException();
             }
 
-            final int cols = b.getColumnDimension();
-            final double[][] xData = new double[n][cols];
-            final double[] y = new double[b.getRowDimension()];
-
-            for (int k = 0; k < cols; ++k) {
+            final int columns        = b.getColumnDimension();
+            final int blockSize      = DenseRealMatrix.BLOCK_SIZE;
+            final int cBlocks        = (columns + blockSize - 1) / blockSize;
+            final double[][] xBlocks = DenseRealMatrix.createBlocksLayout(n, 
columns);
+            final double[][] y       = new 
double[b.getRowDimension()][blockSize];
+            final double[]   alpha   = new double[blockSize];
+
+            for (int kBlock = 0; kBlock < cBlocks; ++kBlock) {
+                final int kStart = kBlock * blockSize;
+                final int kEnd   = Math.min(kStart + blockSize, columns);
+                final int kWidth = kEnd - kStart;
 
                 // get the right hand side vector
-                for (int j = 0; j < y.length; ++j) {
-                    y[j] = b.getEntry(j, k);
-                }
+                b.copySubMatrix(0, m - 1, kStart, kEnd - 1, y);
 
                 // apply Householder transforms to solve Q.y = b
                 for (int minor = 0; minor < Math.min(m, n); minor++) {
-
                     final double[] qrtMinor = qrt[minor];
-                    double dotProduct = 0;
-                    for (int row = minor; row < m; row++) {
-                        dotProduct += y[row] * qrtMinor[row];
+                    final double factor     = 1.0 / (rDiag[minor] * 
qrtMinor[minor]); 
+
+                    Arrays.fill(alpha, 0, kWidth, 0.0);
+                    for (int row = minor; row < m; ++row) {
+                        final double   d    = qrtMinor[row];
+                        final double[] yRow = y[row];
+                        for (int k = 0; k < kWidth; ++k) {
+                            alpha[k] += d * yRow[k];
+                        }
+                    }
+                    for (int k = 0; k < kWidth; ++k) {
+                        alpha[k] *= factor;
                     }
-                    dotProduct /= rDiag[minor] * qrtMinor[minor];
 
-                    for (int row = minor; row < m; row++) {
-                        y[row] += dotProduct * qrtMinor[row];
+                    for (int row = minor; row < m; ++row) {
+                        final double   d    = qrtMinor[row];
+                        final double[] yRow = y[row];
+                        for (int k = 0; k < kWidth; ++k) {
+                            yRow[k] += alpha[k] * d;
+                        }
                     }
 
                 }
 
                 // solve triangular system R.x = y
-                for (int row = n - 1; row >= 0; --row) {
-                    y[row] /= rDiag[row];
-                    final double yRow = y[row];
-                    final double[] qrtRow = qrt[row];
-                    xData[row][k] = yRow;
-                    for (int i = 0; i < row; i++) {
-                        y[i] -= yRow * qrtRow[i];
+                for (int j = rDiag.length - 1; j >= 0; --j) {
+                    final int      jBlock = j / blockSize;
+                    final int      jStart = jBlock * blockSize;
+                    final double   factor = 1.0 / rDiag[j];
+                    final double[] yJ     = y[j];
+                    final double[] xBlock = xBlocks[jBlock * cBlocks + kBlock];
+                    for (int k = 0, index = (j - jStart) * kWidth; k < kWidth; 
++k, ++index) {
+                        yJ[k]        *= factor;
+                        xBlock[index] = yJ[k];
                     }
+
+                    final double[] qrtJ = qrt[j];
+                    for (int i = 0; i < j; ++i) {
+                        final double rIJ  = qrtJ[i];
+                        final double[] yI = y[i];
+                        for (int k = 0; k < kWidth; ++k) {
+                            yI[k] -= yJ[k] * rIJ;
+                        }
+                    }
+
                 }
 
             }
 
-            return new RealMatrixImpl(xData, false);
+            return new DenseRealMatrix(n, columns, xBlocks, false);
 
         }
 
         /** {...@inheritdoc} */
         public RealMatrix getInverse()
-        throws IllegalStateException, InvalidMatrixException {
+        throws InvalidMatrixException {
             return solve(MatrixUtils.createRealIdentityMatrix(rDiag.length));
         }
 


Reply via email to