Added the following methods to ResizableDoubleArray to support MATH-212

changes to stats classes:
copy constructor
static copy(-,-)
instance copy()
equals and hashcode

JIRA: MATH-212


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_0@719894 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2008-11-22 18:41:40 +00:00
parent 2ef1c3b7d0
commit dd1a6bf954
2 changed files with 215 additions and 15 deletions

View File

@ -17,6 +17,7 @@
package org.apache.commons.math.util;
import java.io.Serializable;
import java.util.Arrays;
import org.apache.commons.math.MathRuntimeException;
@ -243,6 +244,18 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
setExpansionMode(expansionMode);
internalArray = new double[initialCapacity];
}
/**
* Copy constructor. Creates a new ResizableDoubleArray that is a deep,
* fresh copy of the original. Needs to acquire synchronization lock
* on original. Original may not be null; otherwise a NullPointerException
* is thrown.
*
* @param original
*/
public ResizableDoubleArray(ResizableDoubleArray original) {
copy(original, this);
}
/**
* Adds an element to the end of this expandable array.
@ -294,27 +307,28 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
}
return discarded;
}
public synchronized double substituteMostRecentElement(double value) {
if (numElements < 1) {
throw MathRuntimeException.createArrayIndexOutOfBoundsException("cannot substitute an element from an empty array",
null);
throw MathRuntimeException.createArrayIndexOutOfBoundsException(
"cannot substitute an element from an empty array", null);
}
double discarded = internalArray[startIndex + (numElements - 1)];
internalArray[startIndex + (numElements - 1)] = value;
internalArray[startIndex + (numElements - 1)] = value;
return discarded;
return discarded;
}
/**
* Checks the expansion factor and the contraction criteria and throws an
* IllegalArgumentException if the contractionCriteria is less than the
* expansionCriteria
*
* @param expansionFactor factor to be checked
* @param contractionCritera critera to be checked
* @param contractionCritera criteria to be checked
* @throws IllegalArgumentException if the contractionCriteria is less than
* the expansionCriteria.
*/
@ -386,8 +400,8 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
*/
public synchronized void discardFrontElements(int i) {
discardExtremeElements(i,true);
discardExtremeElements(i,true);
}
/**
@ -402,10 +416,10 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
*/
public synchronized void discardMostRecentElements(int i) {
discardExtremeElements(i,false);
discardExtremeElements(i,false);
}
/**
* Discards the <code>i<code> first or last elements of the array,
* depending on the value of <code>front</code>.
@ -453,7 +467,7 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
*/
protected synchronized void expand() {
// notice the use of Math.ceil(), this gaurantees that we will always
// notice the use of Math.ceil(), this guarantees that we will always
// have an array of at least currentSize + 1. Assume that the
// current initial capacity is 1 and the expansion factor
// is 1.000000000000000001. The newly calculated size will be
@ -534,7 +548,7 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
}
/**
* The expansion factor controls the size of a new aray when an array
* The expansion factor controls the size of a new array when an array
* needs to be expanded. The <code>expansionMode</code>
* determines whether the size of the array is multiplied by the
* <code>expansionFactor</code> (MULTIPLICATIVE_MODE) or if
@ -704,7 +718,7 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
}
// Test the new num elements, check to see if the array needs to be
// expanded to accomodate this new number of elements
// expanded to accommodate this new number of elements
if ((startIndex + i) > internalArray.length) {
expandTo(startIndex + i);
}
@ -739,5 +753,94 @@ public class ResizableDoubleArray implements DoubleArray, Serializable {
public synchronized int start() {
return startIndex;
}
/**
* <p>Copies source to dest, copying the underlying data, so dest is
* a new, independent copy of source. Does not contract before
* the copy.</p>
*
* <p>Obtains synchronization locks on both source and dest
* (in that order) before performing the copy.</p>
*
* <p>Neither source nor dest may be null; otherwise a NullPointerException
* is thrown</p>
*
*/
public static void copy(ResizableDoubleArray source, ResizableDoubleArray dest) {
synchronized(source) {
synchronized(dest) {
dest.initialCapacity = source.initialCapacity;
dest.contractionCriteria = source.contractionCriteria;
dest.expansionFactor = source.expansionFactor;
dest.expansionMode = source.expansionMode;
dest.internalArray = new double[source.internalArray.length];
System.arraycopy(source.internalArray, 0, dest.internalArray,
0, dest.internalArray.length);
dest.numElements = source.numElements;
dest.startIndex = source.startIndex;
}
}
}
/**
* Returns a copy of the ResizableDoubleArray. Does not contract before
* the copy, so the returned object is an exact copy of this.
*
* @return a new ResizableDoubleArray with the same data and configuration
* properties as this
*/
public synchronized ResizableDoubleArray copy() {
ResizableDoubleArray result = new ResizableDoubleArray();
copy(this, result);
return result;
}
/**
* Returns true iff object is a ResizableDoubleArray with the same properties
* as this and an identical internal storage array.
*
* @param object object to be compared for equality with this
* @return true iff object is a ResizableDoubleArray with the same data and
* properties as this
*
*/
public boolean equals(Object object) {
if (object == this ) {
return true;
}
if (object instanceof ResizableDoubleArray == false) {
return false;
}
boolean result = true;
ResizableDoubleArray other = (ResizableDoubleArray) object;
result = result && (other.initialCapacity == initialCapacity);
result = result && (other.contractionCriteria == contractionCriteria);
result = result && (other.expansionFactor == expansionFactor);
result = result && (other.expansionMode == expansionMode);
result = result && (other.numElements == numElements);
result = result && (other.startIndex == startIndex);
if (!result) {
return false;
} else {
return Arrays.equals(internalArray, other.internalArray);
}
}
/**
* Returns a hash code consistent with equals.
*
* @return hash code representing this ResizableDoubleArray
*/
public int hashCode() {
int[] hashData = new int[7];
hashData[0] = Arrays.hashCode(internalArray);
hashData[1] = new Float(expansionFactor).hashCode();
hashData[2] = new Float(contractionCriteria).hashCode();
hashData[3] = initialCapacity;
hashData[4] = expansionMode;
hashData[5] = numElements;
hashData[6] = startIndex;
return Arrays.hashCode(hashData);
}
}

View File

@ -106,6 +106,14 @@ public class ResizableDoubleArrayTest extends DoubleArrayAbstractTest {
// expected
}
// Copy constructor
testDa = new ResizableDoubleArray(2, 2.0f, 3.0f,
ResizableDoubleArray.ADDITIVE_MODE);
testDa.addElement(2.0);
testDa.addElement(3.2);
ResizableDoubleArray copyDa = new ResizableDoubleArray(testDa);
assertEquals(copyDa, testDa);
assertEquals(testDa, copyDa);
}
@ -402,4 +410,93 @@ public class ResizableDoubleArrayTest extends DoubleArrayAbstractTest {
// expected
}
}
public void testEqualsAndHashCode() throws Exception {
// Wrong type
ResizableDoubleArray first = new ResizableDoubleArray();
Double other = new Double(2);
assertFalse(first.equals(other));
// Null
other = null;
assertFalse(first.equals(other));
// Reflexive
assertTrue(first.equals(first));
// Argumentless constructor
ResizableDoubleArray second = new ResizableDoubleArray();
verifyEquality(first, second);
// Equals iff same data, same properties
ResizableDoubleArray third = new ResizableDoubleArray(3, 2.0f, 2.0f);
verifyInequality(third, first);
ResizableDoubleArray fourth = new ResizableDoubleArray(3, 2.0f, 2.0f);
ResizableDoubleArray fifth = new ResizableDoubleArray(2, 2.0f, 2.0f);
verifyEquality(third, fourth);
verifyInequality(third, fifth);
third.addElement(4.1);
third.addElement(4.2);
third.addElement(4.3);
fourth.addElement(4.1);
fourth.addElement(4.2);
fourth.addElement(4.3);
verifyEquality(third, fourth);
// expand
fourth.addElement(4.4);
verifyInequality(third, fourth);
third.addElement(4.4);
verifyEquality(third, fourth);
fourth.addElement(4.4);
verifyInequality(third, fourth);
third.addElement(4.4);
verifyEquality(third, fourth);
fourth.addElementRolling(4.5);
third.addElementRolling(4.5);
verifyEquality(third, fourth);
// discard
third.discardFrontElements(1);
verifyInequality(third, fourth);
fourth.discardFrontElements(1);
verifyEquality(third, fourth);
// discard recent
third.discardMostRecentElements(2);
fourth.discardMostRecentElements(2);
verifyEquality(third, fourth);
// wrong order
third.addElement(18);
fourth.addElement(17);
third.addElement(17);
fourth.addElement(18);
verifyInequality(third, fourth);
// copy
ResizableDoubleArray.copy(fourth, fifth);
verifyEquality(fourth, fifth);
// Copy constructor
verifyEquality(fourth, new ResizableDoubleArray(fourth));
// Instance copy
verifyEquality(fourth, fourth.copy());
}
private void verifyEquality(ResizableDoubleArray a, ResizableDoubleArray b) {
assertTrue(b.equals(a));
assertTrue(a.equals(b));
assertEquals(a.hashCode(), b.hashCode());
}
private void verifyInequality(ResizableDoubleArray a, ResizableDoubleArray b) {
assertFalse(b.equals(a));
assertFalse(a.equals(b));
assertFalse(a.hashCode() == b.hashCode());
}
}