diff --git a/src/java/org/apache/commons/math/linear/SparseRealMatrix.java b/src/java/org/apache/commons/math/linear/SparseRealMatrix.java index ff8389549..2d9b53bf5 100644 --- a/src/java/org/apache/commons/math/linear/SparseRealMatrix.java +++ b/src/java/org/apache/commons/math/linear/SparseRealMatrix.java @@ -48,7 +48,7 @@ public class SparseRealMatrix extends AbstractRealMatrix { super(rowDimension, columnDimension); this.rowDimension = rowDimension; this.columnDimension = columnDimension; - this.entries = new OpenIntToDoubleHashMap(); + this.entries = new OpenIntToDoubleHashMap(0.0); } /** diff --git a/src/java/org/apache/commons/math/util/OpenIntToDoubleHashMap.java b/src/java/org/apache/commons/math/util/OpenIntToDoubleHashMap.java index 6c943e79b..3a6fd87fb 100644 --- a/src/java/org/apache/commons/math/util/OpenIntToDoubleHashMap.java +++ b/src/java/org/apache/commons/math/util/OpenIntToDoubleHashMap.java @@ -73,6 +73,9 @@ public class OpenIntToDoubleHashMap implements Serializable { /** States table. */ private byte[] states; + /** Return value for missing entries. */ + private final double missingEntries; + /** Current size of the map. */ private int size; @@ -83,21 +86,40 @@ public class OpenIntToDoubleHashMap implements Serializable { private transient int count; /** - * Build an empty map with default size. + * Build an empty map with default size and using NaN for missing entries. */ public OpenIntToDoubleHashMap() { - this(DEFAULT_EXPECTED_SIZE); + this(DEFAULT_EXPECTED_SIZE, Double.NaN); + } + + /** + * Build an empty map with default size + * @param missingEntries value to return when a missing entry is fetched + */ + public OpenIntToDoubleHashMap(final double missingEntries) { + this(DEFAULT_EXPECTED_SIZE, missingEntries); + } + + /** + * Build an empty map with specified size and using NaN for missing entries. + * @param expectedSize expected number of elements in the map + */ + public OpenIntToDoubleHashMap(final int expectedSize) { + this(expectedSize, Double.NaN); } /** * Build an empty map with specified size. * @param expectedSize expected number of elements in the map + * @param missingEntries value to return when a missing entry is fetched */ - public OpenIntToDoubleHashMap(final int expectedSize) { + public OpenIntToDoubleHashMap(final int expectedSize, + final double missingEntries) { final int capacity = computeCapacity(expectedSize); keys = new int[capacity]; values = new double[capacity]; states = new byte[capacity]; + this.missingEntries = missingEntries; mask = capacity - 1; } @@ -113,6 +135,7 @@ public class OpenIntToDoubleHashMap implements Serializable { System.arraycopy(source.values, 0, values, 0, length); states = new byte[length]; System.arraycopy(source.states, 0, states, 0, length); + missingEntries = source.missingEntries; size = source.size; mask = source.mask; count = source.count; @@ -158,7 +181,7 @@ public class OpenIntToDoubleHashMap implements Serializable { } if (states[index] == FREE) { - return 0.0; + return missingEntries; } for (int perturb = perturb(hash), j = index; states[index] != FREE; perturb >>= PERTURB_SHIFT) { @@ -169,7 +192,7 @@ public class OpenIntToDoubleHashMap implements Serializable { } } - return 0.0; + return missingEntries; } @@ -329,7 +352,7 @@ public class OpenIntToDoubleHashMap implements Serializable { } if (states[index] == FREE) { - return 0.0; + return missingEntries; } for (int perturb = perturb(hash), j = index; states[index] != FREE; perturb >>= PERTURB_SHIFT) { @@ -340,7 +363,7 @@ public class OpenIntToDoubleHashMap implements Serializable { } } - return 0.0; + return missingEntries; } @@ -364,7 +387,7 @@ public class OpenIntToDoubleHashMap implements Serializable { keys[index] = 0; states[index] = REMOVED; final double previous = values[index]; - values[index] = 0; + values[index] = missingEntries; --size; ++count; return previous; @@ -378,7 +401,7 @@ public class OpenIntToDoubleHashMap implements Serializable { */ public double put(final int key, final double value) { int index = findInsertionIndex(key); - double previous = 0.0; + double previous = missingEntries; boolean newMapping = true; if (index < 0) { index = changeIndexSign(index); diff --git a/src/test/org/apache/commons/math/util/OpenIntToDoubleHashMapTest.java b/src/test/org/apache/commons/math/util/OpenIntToDoubleHashMapTest.java index 09fb61e5c..e150ab99b 100644 --- a/src/test/org/apache/commons/math/util/OpenIntToDoubleHashMapTest.java +++ b/src/test/org/apache/commons/math/util/OpenIntToDoubleHashMapTest.java @@ -124,14 +124,14 @@ public class OpenIntToDoubleHashMapTest extends TestCase { OpenIntToDoubleHashMap map = createFromJavaMap(); for (Map.Entry mapEntry : generated.entrySet()) - assertEquals(0.0, map.get(mapEntry.getKey())); + assertTrue(Double.isNaN(map.get(mapEntry.getKey()))); } public void testGetFromEmpty() { OpenIntToDoubleHashMap map = new OpenIntToDoubleHashMap(); - assertEquals(0.0, map.get(5)); - assertEquals(0.0, map.get(0)); - assertEquals(0.0, map.get(50)); + assertTrue(Double.isNaN(map.get(5))); + assertTrue(Double.isNaN(map.get(0))); + assertTrue(Double.isNaN(map.get(50))); } public void testRemove() { @@ -141,7 +141,7 @@ public class OpenIntToDoubleHashMapTest extends TestCase { for (Map.Entry mapEntry : javaMap.entrySet()) { map.remove(mapEntry.getKey()); assertEquals(--mapSize, map.size()); - assertEquals(0.0, map.get(mapEntry.getKey())); + assertTrue(Double.isNaN(map.get(mapEntry.getKey()))); } /* Ensure that put and get still work correctly after removals */ @@ -158,7 +158,7 @@ public class OpenIntToDoubleHashMapTest extends TestCase { keysInMap.remove(mapEntry.getKey()); map.remove(mapEntry.getKey()); assertEquals(--mapSize, map.size()); - assertEquals(0.0, map.get(mapEntry.getKey())); + assertTrue(Double.isNaN(map.get(mapEntry.getKey()))); if (count++ > 5) break; } @@ -169,7 +169,7 @@ public class OpenIntToDoubleHashMapTest extends TestCase { public void testRemoveFromEmpty() { OpenIntToDoubleHashMap map = new OpenIntToDoubleHashMap(); - assertEquals(0.0, map.remove(50)); + assertTrue(Double.isNaN(map.remove(50))); } public void testRemoveAbsent() { @@ -181,7 +181,7 @@ public class OpenIntToDoubleHashMapTest extends TestCase { for (Map.Entry mapEntry : generated.entrySet()) { map.remove(mapEntry.getKey()); assertEquals(mapSize, map.size()); - assertEquals(0.0, map.get(mapEntry.getKey())); + assertTrue(Double.isNaN(map.get(mapEntry.getKey()))); } }