diff --git a/src/java/org/apache/commons/math/ContractableDoubleArray.java b/src/java/org/apache/commons/math/ContractableDoubleArray.java index 9832ec12a..5fa82babb 100644 --- a/src/java/org/apache/commons/math/ContractableDoubleArray.java +++ b/src/java/org/apache/commons/math/ContractableDoubleArray.java @@ -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; } /** diff --git a/src/java/org/apache/commons/math/DoubleArray.java b/src/java/org/apache/commons/math/DoubleArray.java new file mode 100644 index 000000000..a593789c8 --- /dev/null +++ b/src/java/org/apache/commons/math/DoubleArray.java @@ -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 + * . + */ +package org.apache.commons.math; + +import java.util.NoSuchElementException; + +/** + * Provides an interface to implemntations which function as an array + * of double primitives. + * + * @author Tim O'Brien + */ +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); +} \ No newline at end of file diff --git a/src/java/org/apache/commons/math/ExpandableDoubleArray.java b/src/java/org/apache/commons/math/ExpandableDoubleArray.java index f82dbb102..89847c8db 100644 --- a/src/java/org/apache/commons/math/ExpandableDoubleArray.java +++ b/src/java/org/apache/commons/math/ExpandableDoubleArray.java @@ -61,7 +61,7 @@ import java.util.NoSuchElementException; * * @author Tim O'Brien */ -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; + } + } diff --git a/src/test/org/apache/commons/math/ContractableDoubleArrayTest.java b/src/test/org/apache/commons/math/ContractableDoubleArrayTest.java index 5eff9cd0a..5f59e490d 100644 --- a/src/test/org/apache/commons/math/ContractableDoubleArrayTest.java +++ b/src/test/org/apache/commons/math/ContractableDoubleArrayTest.java @@ -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) ); } diff --git a/src/test/org/apache/commons/math/DoubleArrayAbstractTest.java b/src/test/org/apache/commons/math/DoubleArrayAbstractTest.java index 3e3c7c1d8..11f34f5f9 100644 --- a/src/test/org/apache/commons/math/DoubleArrayAbstractTest.java +++ b/src/test/org/apache/commons/math/DoubleArrayAbstractTest.java @@ -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); } diff --git a/src/test/org/apache/commons/math/ExpandableDoubleArrayTest.java b/src/test/org/apache/commons/math/ExpandableDoubleArrayTest.java index 7fe2bac4a..e5ef19433 100644 --- a/src/test/org/apache/commons/math/ExpandableDoubleArrayTest.java +++ b/src/test/org/apache/commons/math/ExpandableDoubleArrayTest.java @@ -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 */