1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math.util;
18  import org.apache.commons.math.random.RandomDataImpl;
19  import org.apache.commons.math.random.RandomData;
20  
21  
22  /**
23   * This class contains test cases for the ResizableDoubleArray.
24   * 
25   * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
26   */
27  public class ResizableDoubleArrayTest extends DoubleArrayAbstractTest {
28      
29      public ResizableDoubleArrayTest(String name) {
30          super( name );
31      }
32  
33      @Override
34      protected void tearDown() throws Exception {
35          da = null;
36          ra = null;
37      }
38         
39      @Override
40      protected void setUp() throws Exception {
41          da = new ResizableDoubleArray();
42          ra = new ResizableDoubleArray();
43      }
44      
45      public void testConstructors() {
46          float defaultExpansionFactor = 2.0f;
47          float defaultContractionCriteria = 2.5f;
48          int defaultMode = ResizableDoubleArray.MULTIPLICATIVE_MODE;
49          
50          ResizableDoubleArray testDa = new ResizableDoubleArray(2);
51          assertEquals(0, testDa.getNumElements());
52          assertEquals(2, testDa.getInternalLength());
53          assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
54          assertEquals(defaultContractionCriteria, testDa.getContractionCriteria(), 0);
55          assertEquals(defaultMode, testDa.getExpansionMode());
56          try {
57              da = new ResizableDoubleArray(-1);
58              fail("Expecting IllegalArgumentException");
59          } catch (IllegalArgumentException ex) {
60              // expected
61          }
62          
63          testDa = new ResizableDoubleArray(2, 2.0f);
64          assertEquals(0, testDa.getNumElements());
65          assertEquals(2, testDa.getInternalLength());
66          assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
67          assertEquals(defaultContractionCriteria, testDa.getContractionCriteria(), 0);
68          assertEquals(defaultMode, testDa.getExpansionMode());
69          
70          try {
71              da = new ResizableDoubleArray(2, 0.5f);
72              fail("Expecting IllegalArgumentException");
73          } catch (IllegalArgumentException ex) {
74              // expected
75          }
76          
77          testDa = new ResizableDoubleArray(2, 3.0f);
78          assertEquals(3.0f, testDa.getExpansionFactor(), 0);
79          assertEquals(3.5f, testDa.getContractionCriteria(), 0);
80          
81          testDa = new ResizableDoubleArray(2, 2.0f, 3.0f);
82          assertEquals(0, testDa.getNumElements());
83          assertEquals(2, testDa.getInternalLength());
84          assertEquals(defaultExpansionFactor, testDa.getExpansionFactor(), 0);
85          assertEquals(3.0f, testDa.getContractionCriteria(), 0);
86          assertEquals(defaultMode, testDa.getExpansionMode());
87          
88          try {
89              da = new ResizableDoubleArray(2, 2.0f, 1.5f);
90              fail("Expecting IllegalArgumentException");
91          } catch (IllegalArgumentException ex) {
92              // expected
93          }
94          
95          testDa = new ResizableDoubleArray(2, 2.0f, 3.0f, 
96                  ResizableDoubleArray.ADDITIVE_MODE);
97          assertEquals(0, testDa.getNumElements());
98          assertEquals(2, testDa.getInternalLength());
99          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 }