diff --git a/src/java/org/apache/commons/math/linear/RealMatrixImpl.java b/src/java/org/apache/commons/math/linear/RealMatrixImpl.java index 57b375019..42d3ac311 100644 --- a/src/java/org/apache/commons/math/linear/RealMatrixImpl.java +++ b/src/java/org/apache/commons/math/linear/RealMatrixImpl.java @@ -15,7 +15,10 @@ */ package org.apache.commons.math.linear; + import java.io.Serializable; +import org.apache.commons.math.util.MathUtils; + /** * Implementation for RealMatrix using a double[][] array to store entries @@ -43,10 +46,10 @@ import java.io.Serializable; * is 0-based -- e.g., getEntry(0, 0) * returns the element in the first row, first column of the matrix. * - * @version $Revision: 1.30 $ $Date: 2004/10/09 22:39:22 $ + * @version $Revision: 1.31 $ $Date: 2004/10/10 05:23:16 $ */ public class RealMatrixImpl implements RealMatrix, Serializable { - + /** Serializable version identifier */ static final long serialVersionUID = 4237564493130426188L; @@ -91,8 +94,27 @@ public class RealMatrixImpl implements RealMatrix, Serializable { * The input array is copied, not referenced. * * @param d data for new matrix + * @throws IllegalArgumentException if data is not rectangular (not all + * rows have the same length) or data is empty + * @throws NullPointerException if data is null */ public RealMatrixImpl(double[][] d) { + int nRows = d.length; + if (nRows == 0) { + throw new IllegalArgumentException( + "Matrix must have at least one row."); + } + int nCols = d[0].length; + if (nCols == 0) { + throw new IllegalArgumentException( + "Matrix must have at least one column."); + } + for (int row = 1; row < nRows; row++) { + if (d[row].length != nCols) { + throw new IllegalArgumentException( + "All input rows must have the same length."); + } + } this.copyIn(d); lu = null; } @@ -841,6 +863,57 @@ public class RealMatrixImpl implements RealMatrix, Serializable { res.append("}"); return res.toString(); } //toString + + /** + * Returns true iff object is a + * RealMatrixImpl instance with the same dimensions as this + * and all corresponding matrix entries are equal. + * + * @param object the object to test equality against. + * @return true if object equals this + */ + public boolean equals(Object object) { + if (object == this ) { + return true; + } + if (object instanceof RealMatrixImpl == false) { + return false; + } + RealMatrix m = (RealMatrix) object; + int nRows = getRowDimension(); + int nCols = getColumnDimension(); + if (m.getColumnDimension() != nCols || m.getRowDimension() != nRows) { + return false; + } + for (int row = 0; row < nRows; row++) { + for (int col = 0; col < nCols; col++) { + if (data[row][col] != m.getEntry(row, col)) { + return false; + } + } + } + return true; + } + + /** + * Computes a hashcode for the matrix. + * + * @return hashcode for matrix + */ + public int hashCode() { + int ret = 7; + int nRows = getRowDimension(); + int nCols = getColumnDimension(); + ret = ret * 31 + nRows; + ret = ret * 31 + nCols; + for (int row = 0; row < nRows; row++) { + for (int col = 0; col < nCols; col++) { + ret = ret * 31 + (11 * row + 17 * col) * + MathUtils.hash(data[row][col]); + } + } + return ret; + } //------------------------ Protected methods diff --git a/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java b/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java index f034be132..c86be455f 100644 --- a/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java +++ b/src/test/org/apache/commons/math/linear/RealMatrixImplTest.java @@ -22,7 +22,7 @@ import junit.framework.TestSuite; /** * Test cases for the {@link RealMatrixImpl} class. * - * @version $Revision: 1.17 $ $Date: 2004/10/09 22:39:22 $ + * @version $Revision: 1.18 $ $Date: 2004/10/10 05:23:16 $ */ public final class RealMatrixImplTest extends TestCase { @@ -508,22 +508,25 @@ public final class RealMatrixImplTest extends TestCase { RealMatrix mRows03Cols123 = new RealMatrixImpl(subRows03Cols123); RealMatrix mRows20Cols123 = new RealMatrixImpl(subRows20Cols123); RealMatrix mRows31Cols31 = new RealMatrixImpl(subRows31Cols31); - assertClose("Rows23Cols00", mRows23Cols00, - m.getSubMatrix(2 , 3 , 0, 0), normTolerance ); - assertClose("Rows00Cols33", mRows00Cols33, - m.getSubMatrix(0 , 0 , 3, 3), normTolerance ); - assertClose("Rows01Cols23", mRows01Cols23, - m.getSubMatrix(0 , 1 , 2, 3), normTolerance ); - assertClose("Rows02Cols13", mRows02Cols13, - m.getSubMatrix(new int[] {0,2}, new int[] {1,3}), normTolerance); - assertClose("Rows03Cols12", mRows03Cols12, - m.getSubMatrix(new int[] {0,3}, new int[] {1,2}), normTolerance); - assertClose("Rows03Cols123", mRows03Cols123, - m.getSubMatrix(new int[] {0,3}, new int[] {1,2,3}), normTolerance); - assertClose("Rows20Cols123", mRows20Cols123, - m.getSubMatrix(new int[] {2,0}, new int[] {1,2,3}), normTolerance); - assertClose("Rows31Cols31", mRows31Cols31, - m.getSubMatrix(new int[] {3,1}, new int[] {3,1}), normTolerance); + assertEquals("Rows23Cols00", mRows23Cols00, + m.getSubMatrix(2 , 3 , 0, 0)); + assertEquals("Rows00Cols33", mRows00Cols33, + m.getSubMatrix(0 , 0 , 3, 3)); + assertEquals("Rows01Cols23", mRows01Cols23, + m.getSubMatrix(0 , 1 , 2, 3)); + assertEquals("Rows02Cols13", mRows02Cols13, + m.getSubMatrix(new int[] {0,2}, new int[] {1,3})); + assertEquals("Rows03Cols12", mRows03Cols12, + m.getSubMatrix(new int[] {0,3}, new int[] {1,2})); + assertEquals("Rows03Cols123", mRows03Cols123, + m.getSubMatrix(new int[] {0,3}, new int[] {1,2,3})); + assertEquals("Rows20Cols123", mRows20Cols123, + m.getSubMatrix(new int[] {2,0}, new int[] {1,2,3})); + assertEquals("Rows31Cols31", mRows31Cols31, + m.getSubMatrix(new int[] {3,1}, new int[] {3,1})); + assertEquals("Rows31Cols31", mRows31Cols31, + m.getSubMatrix(new int[] {3,1}, new int[] {3,1})); + try { m.getSubMatrix(1,0,2,4); fail("Expecting MatrixIndexException"); @@ -566,10 +569,10 @@ public final class RealMatrixImplTest extends TestCase { RealMatrix m = new RealMatrixImpl(subTestData); RealMatrix mRow0 = new RealMatrixImpl(subRow0); RealMatrix mRow3 = new RealMatrixImpl(subRow3); - assertClose("Row0", mRow0, - m.getRowMatrix(0), normTolerance ); - assertClose("Row3", mRow3, - m.getRowMatrix(3), normTolerance ); + assertEquals("Row0", mRow0, + m.getRowMatrix(0)); + assertEquals("Row3", mRow3, + m.getRowMatrix(3)); try { m.getRowMatrix(-1); fail("Expecting MatrixIndexException"); @@ -588,10 +591,10 @@ public final class RealMatrixImplTest extends TestCase { RealMatrix m = new RealMatrixImpl(subTestData); RealMatrix mColumn1 = new RealMatrixImpl(subColumn1); RealMatrix mColumn3 = new RealMatrixImpl(subColumn3); - assertClose("Column1", mColumn1, - m.getColumnMatrix(1), normTolerance ); - assertClose("Column3", mColumn3, - m.getColumnMatrix(3), normTolerance ); + assertEquals("Column1", mColumn1, + m.getColumnMatrix(1)); + assertEquals("Column3", mColumn3, + m.getColumnMatrix(3)); try { m.getColumnMatrix(-1); fail("Expecting MatrixIndexException"); @@ -606,6 +609,18 @@ public final class RealMatrixImplTest extends TestCase { } } + public void testEqualsAndHashCode() { + RealMatrixImpl m = new RealMatrixImpl(testData); + RealMatrixImpl m1 = (RealMatrixImpl) m.copy(); + RealMatrixImpl mt = (RealMatrixImpl) m.transpose(); + assertTrue(m.hashCode() != mt.hashCode()); + assertEquals(m.hashCode(), m1.hashCode()); + assertEquals(m, m); + assertEquals(m, m1); + assertFalse(m.equals(null)); + assertFalse(m.equals(mt)); + } + //--------------- -----------------Protected methods /** verifies that two matrices are close (1-norm) */