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:
parent
2ef1c3b7d0
commit
dd1a6bf954
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue