diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 47e68ec73..3b6593e01 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces!
+
+ QR decomposition can compute pseudo-inverses for tall matrices.
+
Field vectors now implement the visitor pattern just like real vectors.
diff --git a/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java b/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java
index a3f3c6e12..9c3480afc 100644
--- a/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java
+++ b/src/main/java/org/apache/commons/math3/linear/QRDecomposition.java
@@ -463,7 +463,7 @@ public class QRDecomposition {
* @throws SingularMatrixException if the decomposed matrix is singular.
*/
public RealMatrix getInverse() {
- return solve(MatrixUtils.createRealIdentityMatrix(rDiag.length));
+ return solve(MatrixUtils.createRealIdentityMatrix(qrt[0].length));
}
}
}
diff --git a/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java b/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java
index a458e5274..1b780cc20 100644
--- a/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java
+++ b/src/test/java/org/apache/commons/math3/linear/QRDecompositionTest.java
@@ -248,6 +248,21 @@ public class QRDecompositionTest {
qr.getSolver().getInverse();
}
+ @Test
+ public void testInvertTallSkinny() {
+ RealMatrix a = MatrixUtils.createRealMatrix(testData4x3);
+ RealMatrix pinv = new QRDecomposition(a).getSolver().getInverse();
+ Assert.assertEquals(0, pinv.multiply(a).subtract(MatrixUtils.createRealIdentityMatrix(3)).getNorm(), 1.0e-6);
+ }
+
+ @Test
+ public void testInvertShortWide() {
+ RealMatrix a = MatrixUtils.createRealMatrix(testData3x4);
+ RealMatrix pinv = new QRDecomposition(a).getSolver().getInverse();
+ Assert.assertEquals(0, a.multiply(pinv).subtract(MatrixUtils.createRealIdentityMatrix(3)).getNorm(), 1.0e-6);
+ Assert.assertEquals(0, pinv.multiply(a).getSubMatrix(0, 2, 0, 2).subtract(MatrixUtils.createRealIdentityMatrix(3)).getNorm(), 1.0e-6);
+ }
+
private RealMatrix createTestMatrix(final Random r, final int rows, final int columns) {
RealMatrix m = MatrixUtils.createRealMatrix(rows, columns);
m.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor(){