* DoubleArray is now an interface which is implemented by

ExpandableDoubleArray.  The interface provides a public interface
which does not hint at any of the storage parameters of
Expandable or Contractable.

* DoubleArrayTest now operates on the DoubleArray interface, casting
to Expandable when we need to call the package scopes getInternalLength
method.

* While we should not provide access to the internal storage array, it
should be possible to obtain a double[] of elements stored in this
DoubleArray - double[] getElements() was added to the DoubleArray interface,
it will return the element array.


git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@140834 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim O'Brien 2003-05-16 04:23:06 +00:00
parent 7651a6b14d
commit 0700b0f482
6 changed files with 197 additions and 56 deletions

View File

@ -145,12 +145,13 @@ public class ContractableDoubleArray extends ExpandableDoubleArray implements Se
*
* @return value to be added to end of array
*/
public synchronized void addElementRolling(double value) {
super.addElementRolling(value);
public synchronized double addElementRolling(double value) {
double discarded = super.addElementRolling(value);
// Check the contraction criteria
if( shouldContract() ) {
contract();
}
return discarded;
}
/**

View File

@ -0,0 +1,123 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.math;
import java.util.NoSuchElementException;
/**
* Provides an interface to implemntations which function as an array
* of double primitives.
*
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
*/
public interface DoubleArray {
/**
* Returns the number of elements currently in the array. Please note
* that this is different from the length of the internal storage array.
* @return number of elements
*/
public abstract int getNumElements();
/**
* Returns the element at the specified index
*
* @param index index to fetch a value from
* @return value stored at the specified index
*/
public abstract double getElement(int index) throws NoSuchElementException;
/**
* Sets the element at the specified index. This method will expand the internal storage array to
* accomodate the insertion of a value at an index beyond the current capacity.
* @param index index to store a value in
* @param value value to store at the specified index
*/
public abstract void setElement(int index, double value);
/**
* Adds an element to the end of this expandable array
*
* @return value to be added to end of array
*/
public abstract void addElement(double value);
/**
* Adds an element and moves the window of elements up one. This
* has the effect of a FIFO. when you "roll" the array an element is removed
* from the array. The return value of this function is the discarded double.
*
* @return the value which has been discarded or "pushed" out of the array
* by this rolling insert.
*/
public abstract double addElementRolling(double value);
/**
* Returns a double[] of elements
*/
public abstract double[] getElements();
/**
* Clear the double array
*/
public abstract void clear();
/**
* Discards values from the front of the list. This function removes n elements from
* the front of the array.
*
* @param i number of elements to discard from the front of the array.
*/
public abstract void discardFrontElements(int i);
}

View File

@ -61,7 +61,7 @@ import java.util.NoSuchElementException;
*
* @author <a href="mailto:tobrien@apache.org">Tim O'Brien</a>
*/
public class ExpandableDoubleArray implements Serializable {
public class ExpandableDoubleArray implements Serializable, DoubleArray {
// This is the internal storage array.
protected double[] internalArray;
@ -290,9 +290,15 @@ public class ExpandableDoubleArray implements Serializable {
/**
* Adds an element and moves the window of elements up one. This
* has the effect of a FIFO
* has the effect of a FIFO. when you "roll" the array an element is removed
* from the array. The return value of this function is the discarded double.
*
* @return the value which has been discarded or "pushed" out of the array
* by this rolling insert.
*/
public synchronized void addElementRolling(double value) {
public synchronized double addElementRolling(double value) {
double discarded = internalArray[startIndex];
if ( (startIndex + (numElements+1) ) > internalArray.length) {
expand();
}
@ -301,6 +307,8 @@ public class ExpandableDoubleArray implements Serializable {
// Add the new value
internalArray[startIndex + (numElements -1)] = value;
return discarded;
}
@ -342,4 +350,13 @@ public class ExpandableDoubleArray implements Serializable {
}
}
/* (non-Javadoc)
* @see org.apache.commons.math.DoubleArray#getElements()
*/
public double[] getElements() {
double[] elementArray = new double[numElements];
System.arraycopy(internalArray, startIndex, elementArray, 0, numElements);
return elementArray;
}
}

View File

@ -69,7 +69,7 @@ public class ContractableDoubleArrayTest extends DoubleArrayAbstractTest {
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
eDA = new ContractableDoubleArray();
da = new ContractableDoubleArray();
}
/** Test normal operations and then test internal storage */
@ -77,18 +77,18 @@ public class ContractableDoubleArrayTest extends DoubleArrayAbstractTest {
super.testAdd1000();
assertEquals("Internal Storage length should be 1024 if we started out with initial capacity of " +
"16 and an expansion factor of 2.0",
1024, eDA.getInternalLength());
1024, ((ExpandableDoubleArray) da).getInternalLength());
}
public void testSetElementArbitraryExpansion() {
super.testSetElementArbitraryExpansion();
assertEquals( "The length of the internal array should now be 1001, it isn't", eDA.getInternalLength(), 1001);
assertEquals( "The length of the internal array should now be 1001, it isn't", ((ExpandableDoubleArray) da).getInternalLength(), 1001);
}
public void testAddElementRolling() {
super.testAddElementRolling();
assertTrue( "Even though there are only 6 element, internal storage should be less than 2.5 times the number of elements",
eDA.getInternalLength() < ((int) 6 * 2.5) );
((ExpandableDoubleArray) da).getInternalLength() < ((int) 6 * 2.5) );
}

View File

@ -62,7 +62,7 @@ import junit.framework.TestCase;
*/
public abstract class DoubleArrayAbstractTest extends TestCase {
protected ExpandableDoubleArray eDA = null;
protected DoubleArray da = null;
public DoubleArrayAbstractTest(String name) {
super( name );
@ -75,15 +75,15 @@ public abstract class DoubleArrayAbstractTest extends TestCase {
public void testAdd1000() {
for( int i = 0; i < 1000; i++) {
eDA.addElement( i );
da.addElement( i );
}
assertEquals("Number of elements should be equal to 1000 after adding 1000 values",
1000, eDA.getNumElements() );
1000, da.getNumElements() );
assertEquals("The element at the 56th index should be 56",
56.0, eDA.getElement(56), Double.MIN_VALUE );
56.0, da.getElement(56), Double.MIN_VALUE );
}
@ -91,12 +91,12 @@ public abstract class DoubleArrayAbstractTest extends TestCase {
public void testGetValues() {
double[] controlArray = {2.0, 4.0, 6.0};
eDA.addElement(2.0);
eDA.addElement(4.0);
eDA.addElement(6.0);
double[] testArray = eDA.getValues();
da.addElement(2.0);
da.addElement(4.0);
da.addElement(6.0);
double[] testArray = da.getElements();
for( int i = 0; i < eDA.getNumElements(); i++) {
for( int i = 0; i < da.getNumElements(); i++) {
assertEquals( "The testArray values should equal the controlArray values, index i: " + i +
" does not match", testArray[i], controlArray[i], Double.MIN_VALUE);
}
@ -106,65 +106,65 @@ public abstract class DoubleArrayAbstractTest extends TestCase {
public void testSetElementArbitraryExpansion() {
double[] controlArray = {2.0, 4.0, 6.0};
eDA.addElement(2.0);
eDA.addElement(4.0);
eDA.addElement(6.0);
eDA.setElement(1, 3.0);
da.addElement(2.0);
da.addElement(4.0);
da.addElement(6.0);
da.setElement(1, 3.0);
// Expand the array arbitrarily to 1000 items
eDA.setElement(1000, 3.4);
da.setElement(1000, 3.4);
assertEquals( "The number of elements should now be 1001, it isn't", eDA.getNumElements(), 1001);
assertEquals( "The number of elements should now be 1001, it isn't", da.getNumElements(), 1001);
assertEquals( "Uninitialized Elements are default value of 0.0, index 766 wasn't", 0.0,
eDA.getElement( 760 ), Double.MIN_VALUE );
da.getElement( 760 ), Double.MIN_VALUE );
assertEquals( "The 1000th index should be 3.4, it isn't", 3.4, eDA.getElement(1000), Double.MIN_VALUE );
assertEquals( "The 0th index should be 2.0, it isn't", 2.0, eDA.getElement(0), Double.MIN_VALUE);
assertEquals( "The 1000th index should be 3.4, it isn't", 3.4, da.getElement(1000), Double.MIN_VALUE );
assertEquals( "The 0th index should be 2.0, it isn't", 2.0, da.getElement(0), Double.MIN_VALUE);
}
public void testSetNumberOfElements() {
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
assertEquals( "Number of elements should equal 6", eDA.getNumElements(), 6);
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
assertEquals( "Number of elements should equal 6", da.getNumElements(), 6);
eDA.setNumElements( 3 );
assertEquals( "Number of elements should equal 3", eDA.getNumElements(), 3);
((ExpandableDoubleArray) da).setNumElements( 3 );
assertEquals( "Number of elements should equal 3", da.getNumElements(), 3);
try {
eDA.setNumElements( -3 );
((ExpandableDoubleArray) da).setNumElements( -3 );
fail( "Setting number of elements to negative should've thrown an exception");
} catch( IllegalArgumentException iae ) {
}
eDA.setNumElements(1024);
assertEquals( "Number of elements should now be 1024", eDA.getNumElements(), 1024);
assertEquals( "Element 453 should be a default double", eDA.getElement( 453 ), 0.0, Double.MIN_VALUE);
((ExpandableDoubleArray) da).setNumElements(1024);
assertEquals( "Number of elements should now be 1024", da.getNumElements(), 1024);
assertEquals( "Element 453 should be a default double", da.getElement( 453 ), 0.0, Double.MIN_VALUE);
}
public void testAddElementRolling() {
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElement( 1.0 );
eDA.addElementRolling( 2.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElement( 1.0 );
da.addElementRolling( 2.0 );
assertEquals( "There should be 6 elements in the eda", eDA.getNumElements(), 6);
assertEquals( "The last element should be 2.0", eDA.getElement( eDA.getNumElements() -1 ), 2.0, Double.MIN_VALUE);
assertEquals( "There should be 6 elements in the eda", da.getNumElements(), 6);
assertEquals( "The last element should be 2.0", da.getElement( da.getNumElements() -1 ), 2.0, Double.MIN_VALUE);
for( int i = 0; i < 1024; i++ ) {
eDA.addElementRolling( i );
da.addElementRolling( i );
}
assertEquals( "We just inserted 1024 rolling elements, num elements should still be 6", eDA.getNumElements(), 6);
assertEquals( "We just inserted 1024 rolling elements, num elements should still be 6", da.getNumElements(), 6);
}

View File

@ -69,14 +69,14 @@ public class ExpandableDoubleArrayTest extends DoubleArrayAbstractTest {
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
eDA = new ExpandableDoubleArray();
da = new ExpandableDoubleArray();
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
eDA = null;
da = null;
}
@ -87,17 +87,17 @@ public class ExpandableDoubleArrayTest extends DoubleArrayAbstractTest {
super.testAdd1000();
assertEquals("Internal Storage length should be 1024 if we started out with initial capacity of " +
"16 and an expansion factor of 2.0",
1024, eDA.getInternalLength());
1024, ((ExpandableDoubleArray) da).getInternalLength());
}
public void testSetElementArbitraryExpansion() {
super.testSetElementArbitraryExpansion();
assertEquals( "The length of the internal array should now be 1001, it isn't", eDA.getInternalLength(), 1001);
assertEquals( "The length of the internal array should now be 1001, it isn't", ((ExpandableDoubleArray) da).getInternalLength(), 1001);
}
public void testAddElementRolling() {
super.testAddElementRolling();
assertEquals( "Even though there are only 6 element, internal storage should be 2048", eDA.getInternalLength(), 2048);
assertEquals( "Even though there are only 6 element, internal storage should be 2048", ((ExpandableDoubleArray) da).getInternalLength(), 2048);
}
/** TESTS WHICH FOCUS ON ExpandableSpecific internal storage */