001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.util;
018    import org.apache.commons.math.random.RandomDataImpl;
019    import org.apache.commons.math.random.RandomData;
020    
021    
022    /**
023     * This class contains test cases for the ResizableDoubleArray.
024     * 
025     * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
026     */
027    public class ResizableDoubleArrayTest extends DoubleArrayAbstractTest {
028        
029        public ResizableDoubleArrayTest(String name) {
030            super( name );
031        }
032    
033        @Override
034        protected void tearDown() throws Exception {
035            da = null;
036            ra = null;
037        }
038           
039        @Override
040        protected void setUp() throws Exception {
041            da = new ResizableDoubleArray();
042            ra = new ResizableDoubleArray();
043        }
044        
045        public void testConstructors() {
046            float defaultExpansionFactor = 2.0f;
047            float defaultContractionCriteria = 2.5f;
048            int defaultMode = ResizableDoubleArray.MULTIPLICATIVE_MODE;
049            
050            ResizableDoubleArray testDa = new ResizableDoubleArray(2);
051            assertEquals(0, testDa.getNumElements());
052            assertEquals(2, testDa.getInternalLength());
053            assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
054            assertEquals(defaultContractionCriteria, testDa.getContractionCriteria(), 0);
055            assertEquals(defaultMode, testDa.getExpansionMode());
056            try {
057                da = new ResizableDoubleArray(-1);
058                fail("Expecting IllegalArgumentException");
059            } catch (IllegalArgumentException ex) {
060                // expected
061            }
062            
063            testDa = new ResizableDoubleArray(2, 2.0f);
064            assertEquals(0, testDa.getNumElements());
065            assertEquals(2, testDa.getInternalLength());
066            assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
067            assertEquals(defaultContractionCriteria, testDa.getContractionCriteria(), 0);
068            assertEquals(defaultMode, testDa.getExpansionMode());
069            
070            try {
071                da = new ResizableDoubleArray(2, 0.5f);
072                fail("Expecting IllegalArgumentException");
073            } catch (IllegalArgumentException ex) {
074                // expected
075            }
076            
077            testDa = new ResizableDoubleArray(2, 3.0f);
078            assertEquals(3.0f, testDa.getExpansionFactor(), 0);
079            assertEquals(3.5f, testDa.getContractionCriteria(), 0);
080            
081            testDa = new ResizableDoubleArray(2, 2.0f, 3.0f);
082            assertEquals(0, testDa.getNumElements());
083            assertEquals(2, testDa.getInternalLength());
084            assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
085            assertEquals(3.0f, testDa.getContractionCriteria(), 0);
086            assertEquals(defaultMode, testDa.getExpansionMode());
087            
088            try {
089                da = new ResizableDoubleArray(2, 2.0f, 1.5f);
090                fail("Expecting IllegalArgumentException");
091            } catch (IllegalArgumentException ex) {
092                // expected
093            }
094            
095            testDa = new ResizableDoubleArray(2, 2.0f, 3.0f, 
096                    ResizableDoubleArray.ADDITIVE_MODE);
097            assertEquals(0, testDa.getNumElements());
098            assertEquals(2, testDa.getInternalLength());
099            assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
100            assertEquals(3.0f, testDa.getContractionCriteria(), 0);
101            assertEquals(ResizableDoubleArray.ADDITIVE_MODE, 
102                    testDa.getExpansionMode());
103            
104            try {
105                da = new ResizableDoubleArray(2, 2.0f, 2.5f, -1);
106                fail("Expecting IllegalArgumentException");
107            } catch (IllegalArgumentException ex) {
108                // expected
109            }
110            
111            // Copy constructor
112            testDa = new ResizableDoubleArray(2, 2.0f, 3.0f, 
113                    ResizableDoubleArray.ADDITIVE_MODE);
114            testDa.addElement(2.0);
115            testDa.addElement(3.2);
116            ResizableDoubleArray copyDa = new ResizableDoubleArray(testDa);
117            assertEquals(copyDa, testDa);
118            assertEquals(testDa, copyDa);   
119        }
120        
121        
122        public void testSetElementArbitraryExpansion() {
123            
124            // MULTIPLICATIVE_MODE 
125            da.addElement(2.0);
126            da.addElement(4.0);
127            da.addElement(6.0);
128            da.setElement(1, 3.0);
129            
130            // Expand the array arbitrarily to 1000 items
131            da.setElement(1000, 3.4);
132            
133            assertEquals( "The number of elements should now be 1001, it isn't", 
134                    da.getNumElements(), 1001);
135            
136            assertEquals( "Uninitialized Elements are default value of 0.0, index 766 wasn't", 0.0,
137                    da.getElement( 760 ), Double.MIN_VALUE );
138            
139            assertEquals( "The 1000th index should be 3.4, it isn't", 3.4, da.getElement(1000), 
140                    Double.MIN_VALUE );
141            assertEquals( "The 0th index should be 2.0, it isn't", 2.0, da.getElement(0), 
142                    Double.MIN_VALUE); 
143            
144            // Make sure numElements and expansion work correctly for expansion boundary cases
145            da.clear();
146            da.addElement(2.0);
147            da.addElement(4.0);
148            da.addElement(6.0);
149            assertEquals(4, ((ResizableDoubleArray) da).getInternalLength());
150            assertEquals(3, da.getNumElements());
151            da.setElement(3, 7.0);
152            assertEquals(4, ((ResizableDoubleArray) da).getInternalLength());
153            assertEquals(4, da.getNumElements());
154            da.setElement(10, 10.0);
155            assertEquals(11, ((ResizableDoubleArray) da).getInternalLength());
156            assertEquals(11, da.getNumElements());
157            da.setElement(9, 10.0);
158            assertEquals(11, ((ResizableDoubleArray) da).getInternalLength());
159            assertEquals(11, da.getNumElements());
160            
161            try {
162                da.setElement(-2, 3);
163                fail("Expecting ArrayIndexOutOfBoundsException for negative index");
164            } catch (ArrayIndexOutOfBoundsException ex) {
165                // expected
166            }
167            
168            // ADDITIVE_MODE
169            
170            ResizableDoubleArray testDa = new ResizableDoubleArray(2, 2.0f, 3.0f, 
171                    ResizableDoubleArray.ADDITIVE_MODE);
172            assertEquals(2, testDa.getInternalLength());
173            testDa.addElement(1d);
174            testDa.addElement(1d);
175            assertEquals(2, testDa.getInternalLength());
176            testDa.addElement(1d);
177            assertEquals(4, testDa.getInternalLength());         
178        }
179    
180        @Override
181        public void testAdd1000() {
182            super.testAdd1000();
183            assertEquals("Internal Storage length should be 1024 if we started out with initial capacity of " +
184                    "16 and an expansion factor of 2.0",
185                    1024, ((ResizableDoubleArray) da).getInternalLength());
186        }
187    
188        @Override
189        public void testAddElementRolling() {
190            super.testAddElementRolling();
191            
192            // MULTIPLICATIVE_MODE
193            da.clear();
194            da.addElement(1);
195            da.addElement(2);
196            da.addElementRolling(3);
197            assertEquals(3, da.getElement(1), 0);
198            da.addElementRolling(4);
199            assertEquals(3, da.getElement(0), 0);
200            assertEquals(4, da.getElement(1), 0);
201            da.addElement(5);
202            assertEquals(5, da.getElement(2), 0);
203            da.addElementRolling(6);
204            assertEquals(4, da.getElement(0), 0);
205            assertEquals(5, da.getElement(1), 0);
206            assertEquals(6, da.getElement(2), 0);   
207            
208            // ADDITIVE_MODE  (x's are occupied storage locations, 0's are open)
209            ResizableDoubleArray testDa = new ResizableDoubleArray(2, 2.0f, 2.5f, 
210                    ResizableDoubleArray.ADDITIVE_MODE);
211            assertEquals(2, testDa.getInternalLength());
212            testDa.addElement(1d); // x,0
213            testDa.addElement(2d); // x,x
214            testDa.addElement(3d); // x,x,x,0 -- expanded
215            assertEquals(1d, testDa.getElement(0), 0);
216            assertEquals(2d, testDa.getElement(1), 0);
217            assertEquals(3d, testDa.getElement(2), 0);   
218            assertEquals(4, testDa.getInternalLength());  // x,x,x,0 
219            assertEquals(3, testDa.getNumElements());
220            testDa.addElementRolling(4d);
221            assertEquals(2d, testDa.getElement(0), 0);
222            assertEquals(3d, testDa.getElement(1), 0);
223            assertEquals(4d, testDa.getElement(2), 0);   
224            assertEquals(4, testDa.getInternalLength());  // 0,x,x,x
225            assertEquals(3, testDa.getNumElements());
226            testDa.addElementRolling(5d);   // 0,0,x,x,x,0 -- time to contract
227            assertEquals(3d, testDa.getElement(0), 0);
228            assertEquals(4d, testDa.getElement(1), 0);
229            assertEquals(5d, testDa.getElement(2), 0);   
230            assertEquals(4, testDa.getInternalLength());  // contracted -- x,x,x,0     
231            assertEquals(3, testDa.getNumElements());
232            try {
233                testDa.getElement(4);
234                fail("Expecting ArrayIndexOutOfBoundsException");
235            } catch (ArrayIndexOutOfBoundsException ex) {
236                // expected
237            }  
238            try {
239                testDa.getElement(-1);
240                fail("Expecting ArrayIndexOutOfBoundsException");
241            } catch (ArrayIndexOutOfBoundsException ex) {
242                // expected
243            }
244        }
245        
246        public void testSetNumberOfElements() {
247            da.addElement( 1.0 );
248            da.addElement( 1.0 );
249            da.addElement( 1.0 );
250            da.addElement( 1.0 );
251            da.addElement( 1.0 );
252            da.addElement( 1.0 );
253            assertEquals( "Number of elements should equal 6", da.getNumElements(), 6);
254            
255            ((ResizableDoubleArray) da).setNumElements( 3 );
256            assertEquals( "Number of elements should equal 3", da.getNumElements(), 3);
257            
258            try {
259                ((ResizableDoubleArray) da).setNumElements( -3 );
260                fail( "Setting number of elements to negative should've thrown an exception");
261            } catch( IllegalArgumentException iae ) {
262            }
263            
264            ((ResizableDoubleArray) da).setNumElements(1024);
265            assertEquals( "Number of elements should now be 1024", da.getNumElements(), 1024);
266            assertEquals( "Element 453 should be a default double", da.getElement( 453 ), 0.0, Double.MIN_VALUE);
267            
268        }
269        
270        public void testWithInitialCapacity() {
271            
272            ResizableDoubleArray eDA2 = new ResizableDoubleArray(2);
273            assertEquals("Initial number of elements should be 0", 0, eDA2.getNumElements());
274            
275            RandomData randomData = new RandomDataImpl();
276            int iterations = randomData.nextInt(100, 1000);
277            
278            for( int i = 0; i < iterations; i++) {
279                eDA2.addElement( i );
280            }
281            
282            assertEquals("Number of elements should be equal to " + iterations, iterations, eDA2.getNumElements());
283            
284            eDA2.addElement( 2.0 );
285            
286            assertEquals("Number of elements should be equals to " + (iterations +1),
287                    iterations + 1 , eDA2.getNumElements() );
288        }
289        
290        public void testWithInitialCapacityAndExpansionFactor() {
291            
292            ResizableDoubleArray eDA3 = new ResizableDoubleArray(3, 3.0f, 3.5f);
293            assertEquals("Initial number of elements should be 0", 0, eDA3.getNumElements() );
294            
295            RandomData randomData = new RandomDataImpl();
296            int iterations = randomData.nextInt(100, 3000);
297            
298            for( int i = 0; i < iterations; i++) {
299                eDA3.addElement( i );
300            }
301            
302            assertEquals("Number of elements should be equal to " + iterations, iterations,eDA3.getNumElements());
303            
304            eDA3.addElement( 2.0 );
305            
306            assertEquals("Number of elements should be equals to " + (iterations +1),
307                    iterations +1, eDA3.getNumElements() );
308            
309            assertEquals("Expansion factor should equal 3.0", 3.0f, eDA3.getExpansionFactor(), Double.MIN_VALUE);
310        }
311        
312        public void testDiscard() {
313            da.addElement(2.0);
314            da.addElement(2.0);
315            da.addElement(2.0);
316            da.addElement(2.0);
317            da.addElement(2.0);
318            da.addElement(2.0);
319            da.addElement(2.0);
320            da.addElement(2.0);
321            da.addElement(2.0);
322            da.addElement(2.0);
323            da.addElement(2.0);
324            assertEquals( "Number of elements should be 11", 11, da.getNumElements());
325            
326            ((ResizableDoubleArray)da).discardFrontElements(5);
327            assertEquals( "Number of elements should be 6", 6, da.getNumElements());
328    
329            da.addElement(2.0);
330            da.addElement(2.0);
331            da.addElement(2.0);
332            da.addElement(2.0);
333            assertEquals( "Number of elements should be 10", 10, da.getNumElements());
334    
335            ((ResizableDoubleArray)da).discardMostRecentElements(2);
336            assertEquals( "Number of elements should be 8", 8, da.getNumElements());
337            
338            try {
339                ((ResizableDoubleArray)da).discardFrontElements(-1);
340                fail( "Trying to discard a negative number of element is not allowed");
341            } catch( Exception e ){
342            }
343    
344            try {
345                ((ResizableDoubleArray)da).discardMostRecentElements(-1);
346                fail( "Trying to discard a negative number of element is not allowed");
347            } catch( Exception e ){
348            }
349    
350            try {
351                ((ResizableDoubleArray)da).discardFrontElements( 10000 );
352                fail( "You can't discard more elements than the array contains");
353            } catch( Exception e ){
354            }
355    
356            try {
357                ((ResizableDoubleArray)da).discardMostRecentElements( 10000 );
358                fail( "You can't discard more elements than the array contains");
359            } catch( Exception e ){
360            }
361    
362        }
363    
364        public void testSubstitute() {
365        
366            da.addElement(2.0);
367            da.addElement(2.0);
368            da.addElement(2.0);
369            da.addElement(2.0);
370            da.addElement(2.0);
371            da.addElement(2.0);
372            da.addElement(2.0);
373            da.addElement(2.0);
374            da.addElement(2.0);
375            da.addElement(2.0);
376            da.addElement(2.0);
377            assertEquals( "Number of elements should be 11", 11, da.getNumElements());
378            
379            ((ResizableDoubleArray)da).substituteMostRecentElement(24);
380    
381            assertEquals( "Number of elements should be 11", 11, da.getNumElements());
382    
383            try {
384                ((ResizableDoubleArray)da).discardMostRecentElements(10);
385            } catch( Exception e ){
386                fail( "Trying to discard a negative number of element is not allowed");
387            }
388    
389            ((ResizableDoubleArray)da).substituteMostRecentElement(24);
390    
391            assertEquals( "Number of elements should be 1", 1, da.getNumElements());
392    
393        }
394        
395        public void testMutators() {
396            ((ResizableDoubleArray)da).setContractionCriteria(10f);
397            assertEquals(10f, ((ResizableDoubleArray)da).getContractionCriteria(), 0);
398            ((ResizableDoubleArray)da).setExpansionFactor(8f);  
399            assertEquals(8f, ((ResizableDoubleArray)da).getExpansionFactor(), 0);
400            try {
401                ((ResizableDoubleArray)da).setExpansionFactor(11f);  // greater than contractionCriteria
402                fail("Expecting IllegalArgumentException");
403            } catch (IllegalArgumentException ex) {
404                // expected
405            }
406            ((ResizableDoubleArray)da).setExpansionMode(
407                    ResizableDoubleArray.ADDITIVE_MODE);
408            assertEquals(ResizableDoubleArray.ADDITIVE_MODE, 
409                    ((ResizableDoubleArray)da).getExpansionMode());
410            try {
411                ((ResizableDoubleArray)da).setExpansionMode(-1);
412                fail ("Expecting IllegalArgumentException");
413            } catch (IllegalArgumentException ex) {
414                // expected
415            }
416        }
417        
418        public void testEqualsAndHashCode() throws Exception {
419            
420            // Wrong type
421            ResizableDoubleArray first = new ResizableDoubleArray();
422            Double other = new Double(2);
423            assertFalse(first.equals(other));
424            
425            // Null
426            other = null;
427            assertFalse(first.equals(other));
428            
429            // Reflexive
430            assertTrue(first.equals(first));
431            
432            // Argumentless constructor
433            ResizableDoubleArray second = new ResizableDoubleArray();
434            verifyEquality(first, second);
435            
436            // Equals iff same data, same properties
437            ResizableDoubleArray third = new ResizableDoubleArray(3, 2.0f, 2.0f);
438            verifyInequality(third, first);
439            ResizableDoubleArray fourth = new ResizableDoubleArray(3, 2.0f, 2.0f);
440            ResizableDoubleArray fifth = new ResizableDoubleArray(2, 2.0f, 2.0f);
441            verifyEquality(third, fourth);
442            verifyInequality(third, fifth);
443            third.addElement(4.1);
444            third.addElement(4.2);
445            third.addElement(4.3);
446            fourth.addElement(4.1);
447            fourth.addElement(4.2);
448            fourth.addElement(4.3);
449            verifyEquality(third, fourth);
450            
451            // expand
452            fourth.addElement(4.4);
453            verifyInequality(third, fourth);
454            third.addElement(4.4);
455            verifyEquality(third, fourth);
456            fourth.addElement(4.4);
457            verifyInequality(third, fourth);
458            third.addElement(4.4);
459            verifyEquality(third, fourth);
460            fourth.addElementRolling(4.5);
461            third.addElementRolling(4.5);
462            verifyEquality(third, fourth);
463            
464            // discard
465            third.discardFrontElements(1);
466            verifyInequality(third, fourth);
467            fourth.discardFrontElements(1);
468            verifyEquality(third, fourth);
469            
470            // discard recent
471            third.discardMostRecentElements(2);
472            fourth.discardMostRecentElements(2);
473            verifyEquality(third, fourth);
474            
475            // wrong order
476            third.addElement(18);
477            fourth.addElement(17);
478            third.addElement(17);
479            fourth.addElement(18);
480            verifyInequality(third, fourth);
481            
482            // copy
483            ResizableDoubleArray.copy(fourth, fifth);
484            verifyEquality(fourth, fifth);
485            
486            // Copy constructor
487            verifyEquality(fourth, new ResizableDoubleArray(fourth));
488            
489            // Instance copy
490            verifyEquality(fourth, fourth.copy());   
491                 
492        }
493        
494        private void verifyEquality(ResizableDoubleArray a, ResizableDoubleArray b) {
495            assertTrue(b.equals(a));
496            assertTrue(a.equals(b));
497            assertEquals(a.hashCode(), b.hashCode());    
498        }
499        
500        private void verifyInequality(ResizableDoubleArray a, ResizableDoubleArray b) {
501            assertFalse(b.equals(a));
502            assertFalse(a.equals(b));
503            assertFalse(a.hashCode() == b.hashCode());
504        }
505        
506    }