diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 689fa6868..6bd22ee6e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,6 +55,10 @@ This is a minor release: It combines bug fixes and new features. Changes to existing features were made in a backwards-compatible way such as to allow drop-in replacement of the v3.1[.1] JAR file. "> + + AbstractRealMatrix will now check for rectangular input arrays in + its copySubMatrix methods. + Increment iteration counter in optimization algorithms. diff --git a/src/main/java/org/apache/commons/math3/linear/AbstractRealMatrix.java b/src/main/java/org/apache/commons/math3/linear/AbstractRealMatrix.java index 432d9ede8..c3c9c2d2a 100644 --- a/src/main/java/org/apache/commons/math3/linear/AbstractRealMatrix.java +++ b/src/main/java/org/apache/commons/math3/linear/AbstractRealMatrix.java @@ -353,6 +353,13 @@ public abstract class AbstractRealMatrix rowsCount, columnsCount); } + for (int i = 1; i < rowsCount; i++) { + if (destination[i].length != columnsCount) { + throw new MatrixDimensionMismatchException(destination.length, destination[i].length, + rowsCount, columnsCount); + } + } + walkInOptimizedOrder(new DefaultRealMatrixPreservingVisitor() { /** Initial row index. */ @@ -385,14 +392,19 @@ public abstract class AbstractRealMatrix throws OutOfRangeException, NullArgumentException, NoDataException, MatrixDimensionMismatchException { MatrixUtils.checkSubMatrixIndex(this, selectedRows, selectedColumns); + final int nCols = selectedColumns.length; if ((destination.length < selectedRows.length) || - (destination[0].length < selectedColumns.length)) { + (destination[0].length < nCols)) { throw new MatrixDimensionMismatchException(destination.length, destination[0].length, selectedRows.length, selectedColumns.length); } for (int i = 0; i < selectedRows.length; i++) { final double[] destinationI = destination[i]; + if (destinationI.length != nCols) { + throw new MatrixDimensionMismatchException(destination.length, destinationI.length, + selectedRows.length, selectedColumns.length); + } for (int j = 0; j < selectedColumns.length; j++) { destinationI[j] = getEntry(selectedRows[i], selectedColumns[j]); } diff --git a/src/test/java/org/apache/commons/math3/linear/Array2DRowRealMatrixTest.java b/src/test/java/org/apache/commons/math3/linear/Array2DRowRealMatrixTest.java index 880fa3b2f..19cad4991 100644 --- a/src/test/java/org/apache/commons/math3/linear/Array2DRowRealMatrixTest.java +++ b/src/test/java/org/apache/commons/math3/linear/Array2DRowRealMatrixTest.java @@ -537,6 +537,11 @@ public final class Array2DRowRealMatrixTest { checkCopy(m, null, 1, 0, 2, 4, true); checkCopy(m, null, new int[] {}, new int[] { 0 }, true); checkCopy(m, null, new int[] { 0 }, new int[] { 4 }, true); + + // rectangular check + double[][] copy = new double[][] { { 0, 0, 0 }, { 0, 0 } }; + checkCopy(m, copy, 0, 1, 0, 2, true); + checkCopy(m, copy, new int[] { 0, 1 }, new int[] { 0, 2 }, true); } private void checkCopy(RealMatrix m, double[][] reference, @@ -544,8 +549,7 @@ public final class Array2DRowRealMatrixTest { boolean mustFail) { try { double[][] sub = (reference == null) ? - new double[1][1] : - new double[reference.length][reference[0].length]; + new double[1][1] : createIdenticalCopy(reference); m.copySubMatrix(startRow, endRow, startColumn, endColumn, sub); Assert.assertEquals(new Array2DRowRealMatrix(reference), new Array2DRowRealMatrix(sub)); if (mustFail) { @@ -563,6 +567,10 @@ public final class Array2DRowRealMatrixTest { if (!mustFail) { throw e; } + } catch (MatrixDimensionMismatchException e) { + if (!mustFail) { + throw e; + } } } @@ -571,8 +579,7 @@ public final class Array2DRowRealMatrixTest { boolean mustFail) { try { double[][] sub = (reference == null) ? - new double[1][1] : - new double[reference.length][reference[0].length]; + new double[1][1] : createIdenticalCopy(reference); m.copySubMatrix(selectedRows, selectedColumns, sub); Assert.assertEquals(new Array2DRowRealMatrix(reference), new Array2DRowRealMatrix(sub)); if (mustFail) { @@ -590,9 +597,21 @@ public final class Array2DRowRealMatrixTest { if (!mustFail) { throw e; } + } catch (MatrixDimensionMismatchException e) { + if (!mustFail) { + throw e; + } } } + private double[][] createIdenticalCopy(final double[][] matrix) { + final double[][] matrixCopy = new double[matrix.length][]; + for (int i = 0; i < matrixCopy.length; i++) { + matrixCopy[i] = new double[matrix[i].length]; + } + return matrixCopy; + } + @Test public void testGetRowMatrix() { RealMatrix m = new Array2DRowRealMatrix(subTestData);