View Javadoc
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.math4.legacy.stat.descriptive.rank;
18  
19  import java.io.IOException;
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.LinkedHashSet;
25  import java.util.Set;
26  import org.apache.commons.statistics.distribution.LogNormalDistribution;
27  import org.apache.commons.statistics.distribution.NormalDistribution;
28  import org.apache.commons.statistics.distribution.ContinuousDistribution;
29  import org.apache.commons.math4.legacy.distribution.AbstractRealDistribution;
30  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
31  import org.apache.commons.math4.legacy.exception.NullArgumentException;
32  import org.apache.commons.math4.legacy.exception.OutOfRangeException;
33  import org.apache.commons.rng.UniformRandomProvider;
34  import org.apache.commons.rng.simple.RandomSource;
35  import org.apache.commons.math4.legacy.stat.descriptive.StorelessUnivariateStatistic;
36  import org.apache.commons.math4.legacy.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
37  import org.apache.commons.math4.legacy.stat.descriptive.UnivariateStatistic;
38  import org.apache.commons.math4.legacy.stat.descriptive.rank.PSquarePercentile.PSquareMarkers;
39  import org.apache.commons.math4.core.jdkmath.JdkMath;
40  import org.junit.Assert;
41  import org.junit.Test;
42  
43  /**
44   * Test cases for the {@link PSquarePercentile} class which naturally extends
45   * {@link StorelessUnivariateStatisticAbstractTest}.
46   */
47  public class PSquarePercentileTest extends
48          StorelessUnivariateStatisticAbstractTest {
49  
50      protected double percentile5 = 8.2299d;
51      protected double percentile95 = 16.72195;// 20.82d; this is approximation
52      protected double tolerance = 10E-12;
53  
54      private final UniformRandomProvider randomGenerator = RandomSource.WELL_19937_C.create(1000);
55  
56      @Override
57      public double getTolerance() {
58          return 1.0e-2;// tolerance limit changed as this is an approximation
59          // algorithm and also gets accurate after few tens of
60          // samples
61      }
62  
63      /**
64       * Verifies that copied statistics remain equal to originals when
65       * incremented the same way by making the copy after a majority of elements
66       * are incremented
67       */
68      @Test
69      public void testCopyConsistencyWithInitialMostElements() {
70  
71          StorelessUnivariateStatistic master =
72                  (StorelessUnivariateStatistic) getUnivariateStatistic();
73  
74          StorelessUnivariateStatistic replica = null;
75  
76          // select a portion of testArray till 75 % of the length to load first
77          long index = JdkMath.round(0.75 * testArray.length);
78  
79          // Put first half in master and copy master to replica
80          master.incrementAll(testArray, 0, (int) index);
81          replica = master.copy();
82  
83          // Check same
84          Assert.assertEquals(replica, master);
85          Assert.assertEquals(master, replica);
86  
87          // Now add second part to both and check again
88          master.incrementAll(testArray, (int) index,
89                  (int) (testArray.length - index));
90          replica.incrementAll(testArray, (int) index,
91                  (int) (testArray.length - index));
92          Assert.assertEquals(replica, master);
93          Assert.assertEquals(master, replica);
94      }
95  
96      /**
97       * Verifies that copied statistics remain equal to originals when
98       * incremented the same way by way of copying original after just a few
99       * elements are incremented
100      */
101     @Test
102     public void testCopyConsistencyWithInitialFirstFewElements() {
103 
104         StorelessUnivariateStatistic master =
105                 (StorelessUnivariateStatistic) getUnivariateStatistic();
106 
107         StorelessUnivariateStatistic replica = null;
108 
109         // select a portion of testArray which is 10% of the length to load
110         // first
111         long index = JdkMath.round(0.1 * testArray.length);
112 
113         // Put first half in master and copy master to replica
114         master.incrementAll(testArray, 0, (int) index);
115         replica = master.copy();
116 
117         // Check same
118         Assert.assertEquals(replica, master);
119         Assert.assertEquals(master, replica);
120         // Now add second part to both and check again
121         master.incrementAll(testArray, (int) index,
122                 (int) (testArray.length - index));
123         replica.incrementAll(testArray, (int) index,
124                 (int) (testArray.length - index));
125         // Check same
126         // Explicit test of the equals method
127         Assert.assertTrue(master.equals(master));
128         Assert.assertTrue(replica.equals(replica));
129         Assert.assertEquals(replica, master);
130         Assert.assertEquals(master, replica);
131     }
132 
133     @Test(expected = MathIllegalArgumentException.class)
134     public void testNullListInMarkers() {
135         // In case of null list Markers cannot be instantiated..is getting
136         // verified
137         // new Markers(null, 0, PSquarePercentile.newEstimator());
138         PSquarePercentile.newMarkers(null, 0);
139     }
140 
141     @Test
142     public void testEqualsInMarkers() {
143         double p = 0.5;
144         PSquareMarkers markers =
145                 PSquarePercentile.newMarkers(
146                         Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91,
147                                 38.62 }), p);
148         // Markers equality
149         Assert.assertEquals(markers, markers);
150         Assert.assertNotEquals(markers, null);
151         Assert.assertNotEquals(markers, "");
152         // Check for null markers test during equality testing
153         // Until 5 elements markers are not initialized
154         PSquarePercentile p1 = new PSquarePercentile();
155         PSquarePercentile p2 = new PSquarePercentile();
156         Assert.assertEquals(p1, p2);
157         p1.evaluate(new double[] { 1.0, 2.0, 3.0 });
158         p2.evaluate(new double[] { 1.0, 2.0, 3.0 });
159         Assert.assertEquals(p1, p2);
160         // Move p2 alone with more values just to make sure markers are not null
161         // for p2
162         p2.incrementAll(new double[] { 5.0, 7.0, 11.0 });
163         Assert.assertNotEquals(p1, p2);
164         Assert.assertNotEquals(p2, p1);
165         // Next add different data to p1 to make number of elements match and
166         // markers are not null however actual results will vary
167         p1.incrementAll(new double[] { 20, 21, 22, 23 });
168         Assert.assertNotEquals(p1, p2);// though markers are non null, N
169         // matches, results wont
170     }
171 
172     @Test(expected = OutOfRangeException.class)
173     public void testMarkersOORLow() {
174         PSquarePercentile.newMarkers(
175                 Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91, 38.62 }),
176                 0.5).estimate(0);
177     }
178 
179     @Test(expected = OutOfRangeException.class)
180     public void testMarkersOORHigh() {
181         PSquarePercentile.newMarkers(
182                 Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91, 38.62 }),
183                 0.5).estimate(5);
184     }
185 
186     @Test
187     public void testMarkers2() {
188         double p = 0.5;
189         PSquareMarkers markers =
190                 PSquarePercentile.newMarkers(
191                         Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91,
192                                 38.62 }), p);
193 
194         PSquareMarkers markersNew =
195                 PSquarePercentile.newMarkers(
196                         Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91,
197                                 38.62 }), p);
198 
199         Assert.assertEquals(markers, markersNew);
200         // If just one element of markers got changed then its still false.
201         markersNew.processDataPoint(39);
202         Assert.assertNotEquals(markers, markersNew);
203     }
204 
205     @Test
206     public void testHashCodeInMarkers() {
207         PSquarePercentile p = new PSquarePercentile(95);
208         PSquarePercentile p2 = new PSquarePercentile(95);
209         Set<PSquarePercentile> s = new HashSet<>();
210         s.add(p);
211         s.add(p2);
212         Assert.assertEquals(1, s.size());
213         Assert.assertEquals(p, s.iterator().next());
214         double[] d =
215                 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
216                         95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
217                         95.1682 };
218         Assert.assertEquals(95.1981, p.evaluate(d), 1.0e-2); // change
219         Assert.assertEquals(95.1981, p2.evaluate(d), 1.0e-2); // change
220         s.clear();
221         s.add(p);
222         s.add(p2);
223         Assert.assertEquals(1, s.size());
224         Assert.assertEquals(p, s.iterator().next());
225 
226         PSquareMarkers m1 =
227                 PSquarePercentile.newMarkers(
228                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
229                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
230                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.0);
231         PSquareMarkers m2 =
232                 PSquarePercentile.newMarkers(
233                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
234                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
235                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.0);
236         Assert.assertEquals(m1, m2);
237         Set<PSquareMarkers> setMarkers = new LinkedHashSet<>();
238         Assert.assertTrue(setMarkers.add(m1));
239         Assert.assertFalse(setMarkers.add(m2));
240         Assert.assertEquals(1, setMarkers.size());
241 
242         PSquareMarkers mThis =
243                 PSquarePercentile.newMarkers(
244                         Arrays.asList(new Double[] { 195.1772, 195.1567,
245                                 195.1937, 195.1959, 95.1442, 195.0610,
246                                 195.1591, 195.1195, 195.1772, 95.0925, 95.1990,
247                                 195.1682 }), 0.50);
248         PSquareMarkers mThat =
249                 PSquarePercentile.newMarkers(
250                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
251                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
252                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
253         Assert.assertEquals(mThis, mThis);
254         Assert.assertNotEquals(mThis, mThat);
255         String s1="";
256         Assert.assertNotEquals(mThis, s1);
257         for (int i = 0; i < testArray.length; i++) {
258             mThat.processDataPoint(testArray[i]);
259         }
260         setMarkers.add(mThat);
261         setMarkers.add(mThis);
262         Assert.assertEquals(mThat, mThat);
263         Assert.assertTrue(setMarkers.contains(mThat));
264         Assert.assertTrue(setMarkers.contains(mThis));
265         Assert.assertEquals(3, setMarkers.size());
266         Iterator<PSquareMarkers> iterator=setMarkers.iterator();
267         Assert.assertEquals(m1, iterator.next());
268         Assert.assertEquals(mThat, iterator.next());
269         Assert.assertEquals(mThis, iterator.next());
270     }
271 
272     @Test(expected = OutOfRangeException.class)
273     public void testMarkersWithLowerIndex() {
274         PSquareMarkers mThat =
275                 PSquarePercentile.newMarkers(
276                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
277                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
278                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
279         for (int i = 0; i < testArray.length; i++) {
280             mThat.processDataPoint(testArray[i]);
281         }
282         mThat.estimate(0);
283     }
284 
285     @Test(expected = OutOfRangeException.class)
286     public void testMarkersWithHigherIndex() {
287         PSquareMarkers mThat =
288                 PSquarePercentile.newMarkers(
289                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
290                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
291                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
292         for (int i = 0; i < testArray.length; i++) {
293             mThat.processDataPoint(testArray[i]);
294         }
295         mThat.estimate(6);
296     }
297 
298     @Test(expected = OutOfRangeException.class)
299     public void testMarkerHeightWithLowerIndex() {
300         PSquareMarkers mThat =
301                 PSquarePercentile.newMarkers(
302                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
303                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
304                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
305         mThat.height(0);
306     }
307 
308     @Test(expected = OutOfRangeException.class)
309     public void testMarkerHeightWithHigherIndex() {
310         PSquareMarkers mThat =
311                 PSquarePercentile.newMarkers(
312                         Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
313                                 95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
314                                 95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
315         mThat.height(6);
316     }
317 
318     @Test
319     public void testPSquaredEqualsAndMin() {
320         PSquarePercentile ptile = new PSquarePercentile(0);
321         Assert.assertEquals(ptile, ptile);
322         Assert.assertNotEquals(ptile, null);
323         Assert.assertNotEquals(ptile, "");
324         // Just to check if there is no data get result for zeroth and 100th
325         // ptile returns NAN
326         Assert.assertTrue(Double.isNaN(ptile.getResult()));
327         Assert.assertTrue(Double.isNaN(new PSquarePercentile(100).getResult()));
328 
329         double[] d = new double[] { 1, 3, 2, 4, 9, 10, 11 };
330         ptile.incrementAll(d);
331         Assert.assertEquals(ptile, ptile);
332         Assert.assertEquals(1d, ptile.getResult(), 1e-02);// this calls min
333     }
334 
335     @Test
336     public void testString() {
337         PSquarePercentile ptile = new PSquarePercentile(95);
338         Assert.assertNotNull(ptile.toString());
339         ptile.increment(1);
340         ptile.increment(2);
341         ptile.increment(3);
342         Assert.assertNotNull(ptile.toString());
343         Assert.assertEquals(expectedValue(), ptile.evaluate(testArray), getTolerance());
344         Assert.assertNotNull(ptile.toString());
345     }
346 
347     @Override
348     public UnivariateStatistic getUnivariateStatistic() {
349         PSquarePercentile ptile = new PSquarePercentile(95);
350         // Assert.assertNull(ptile.markers());
351         return ptile;
352     }
353 
354     @Override
355     public double expectedValue() {
356         return this.percentile95;
357     }
358 
359     @Test
360     public void testHighPercentile() {
361         double[] d = new double[] { 1, 2, 3 };
362         PSquarePercentile p = new PSquarePercentile(75.0);
363         Assert.assertEquals(2, p.evaluate(d), 1.0e-5);
364         PSquarePercentile p95 = new PSquarePercentile();
365         Assert.assertEquals(2, p95.evaluate(d), 1.0e-5);
366     }
367 
368     @Test
369     public void testLowPercentile() {
370         double[] d = new double[] { 0, 1 };
371         PSquarePercentile p = new PSquarePercentile(25.0);
372         Assert.assertEquals(0d, p.evaluate(d), Double.MIN_VALUE);
373     }
374 
375     @Test
376     public void testPercentile() {
377         double[] d = new double[] { 1, 3, 2, 4 };
378         PSquarePercentile p = new PSquarePercentile(30d);
379         Assert.assertEquals(1.0, p.evaluate(d), 1.0e-5);
380         p = new PSquarePercentile(25);
381         Assert.assertEquals(1.0, p.evaluate(d), 1.0e-5);
382         p = new PSquarePercentile(75);
383         Assert.assertEquals(3.0, p.evaluate(d), 1.0e-5);
384         p = new PSquarePercentile(50);
385         Assert.assertEquals(2d, p.evaluate(d), 1.0e-5);
386     }
387 
388     @Test(expected = MathIllegalArgumentException.class)
389     public void testInitial() {
390         PSquarePercentile.newMarkers(new ArrayList<>(), 0.5);
391         Assert.fail();
392     }
393 
394     @Test(expected = MathIllegalArgumentException.class)
395     public void testNegativeInvalidValues() {
396         double[] d =
397                 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
398                         95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
399                         95.1682 };
400         PSquarePercentile p = new PSquarePercentile(-1.0);
401         p.evaluate(d, 0, d.length);
402         Assert.fail("This method has had to throw exception..but it is not..");
403     }
404 
405     @Test(expected = MathIllegalArgumentException.class)
406     public void testPositiveInvalidValues() {
407         double[] d =
408                 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
409                         95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
410                         95.1682 };
411         PSquarePercentile p = new PSquarePercentile(101.0);
412         p.evaluate(d, 0, d.length);
413         Assert.fail("This method has had to throw exception..but it is not..");
414     }
415 
416     @Test
417     public void testNISTExample() {
418         double[] d =
419                 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
420                         95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
421                         95.1682 };
422         Assert.assertEquals(95.1981, new PSquarePercentile(90d).evaluate(d),
423                 1.0e-2); // changed the accuracy to 1.0e-2
424         Assert.assertEquals(95.061, new PSquarePercentile(0d).evaluate(d), 0);
425         Assert.assertEquals(95.1990,
426                 new PSquarePercentile(100d).evaluate(d, 0, d.length), 0);
427     }
428 
429     @Test
430     public void test5() {
431         PSquarePercentile percentile = new PSquarePercentile(5d);
432         Assert.assertEquals(this.percentile5, percentile.evaluate(testArray),
433                 1.0);// changed the accuracy to 1 instead of tolerance
434     }
435 
436     @Test(expected = NullArgumentException.class)
437     public void testNull() {
438         PSquarePercentile percentile = new PSquarePercentile(50d);
439         double[] nullArray = null;
440         percentile.evaluate(nullArray);
441     }
442 
443     @Test
444     public void testEmpty() {
445         PSquarePercentile percentile = new PSquarePercentile(50d);
446         double[] emptyArray = new double[] {};
447         Assert.assertTrue(Double.isNaN(percentile.evaluate(emptyArray)));
448     }
449 
450     @Test
451     public void testSingleton() {
452         PSquarePercentile percentile = new PSquarePercentile(50d);
453         double[] singletonArray = new double[] { 1d };
454         Assert.assertEquals(1d, percentile.evaluate(singletonArray), 0);
455         Assert.assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
456         percentile = new PSquarePercentile(5);
457         Assert.assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
458         percentile = new PSquarePercentile(100);
459         Assert.assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
460         percentile = new PSquarePercentile(100);
461         Assert.assertTrue(Double.isNaN(percentile
462                 .evaluate(singletonArray, 0, 0)));
463     }
464 
465     @Test
466     public void testSpecialValues() {
467         PSquarePercentile percentile = new PSquarePercentile(50d);
468         double[] specialValues =
469                 new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
470         Assert.assertEquals(2d, percentile.evaluate(specialValues), 0);
471         specialValues =
472                 new double[] { Double.NEGATIVE_INFINITY, 1d, 2d, 3d,
473                         Double.NaN, Double.POSITIVE_INFINITY };
474         Assert.assertEquals(2d, percentile.evaluate(specialValues), 0);
475         specialValues =
476                 new double[] { 1d, 1d, Double.POSITIVE_INFINITY,
477                         Double.POSITIVE_INFINITY };
478         Assert.assertFalse(Double.isInfinite(percentile.evaluate(specialValues)));
479         specialValues = new double[] { 1d, 1d, Double.NaN, Double.NaN };
480         Assert.assertFalse(Double.isNaN(percentile.evaluate(specialValues)));
481         specialValues =
482                 new double[] { 1d, 1d, Double.NEGATIVE_INFINITY,
483                         Double.NEGATIVE_INFINITY };
484         percentile = new PSquarePercentile(50d);
485         // Interpolation results in NEGATIVE_INFINITY + POSITIVE_INFINITY
486         // changed the result check to infinity instead of NaN
487         Assert.assertTrue(Double.isInfinite(percentile.evaluate(specialValues)));
488     }
489 
490     @Test
491     public void testArrayExample() {
492         Assert.assertEquals(expectedValue(),
493                 new PSquarePercentile(95d).evaluate(testArray), getTolerance());
494     }
495 
496     @Test
497     public void testSetQuantile() {
498         PSquarePercentile percentile = new PSquarePercentile(10d);
499 
500         percentile = new PSquarePercentile(100); // OK
501         Assert.assertEquals(1.0, percentile.quantile(), 0);
502         try {
503             percentile = new PSquarePercentile(0);
504             // Assert.fail("Expecting MathIllegalArgumentException");
505         } catch (MathIllegalArgumentException ex) {
506             // expected
507         }
508         try {
509             new PSquarePercentile(0d);
510             // Assert.fail("Expecting MathIllegalArgumentException");
511         } catch (MathIllegalArgumentException ex) {
512             // expected
513         }
514     }
515 
516     private Double[] randomTestData(int factor, int values) {
517         Double[] test = new Double[values];
518         for (int i = 0; i < test.length; i++) {
519             test[i] = Math.abs(randomGenerator.nextDouble() * factor);
520         }
521         return test;
522     }
523 
524     @Test
525     public void testAccept() {
526         PSquarePercentile psquared = new PSquarePercentile(0.99);
527         Assert.assertTrue(Double.isNaN(psquared.getResult()));
528         Double[] test = randomTestData(100, 10000);
529 
530         for (Double value : test) {
531             psquared.increment(value);
532             Assert.assertTrue(psquared.getResult() >= 0);
533         }
534     }
535 
536     private void assertValues(Double a, Double b, double delta) {
537         if (Double.isNaN(a)) {
538             Assert.assertTrue("" + b + " is not NaN.", Double.isNaN(a));
539         } else {
540             double max = JdkMath.max(a, b);
541             double percentage = JdkMath.abs(a - b) / max;
542             double deviation = delta;
543             Assert.assertTrue(String.format(
544                     "Deviated = %f and is beyond %f as a=%f,  b=%f",
545                     percentage, deviation, a, b), percentage < deviation);
546         }
547     }
548 
549     private void doCalculatePercentile(Double percentile, Number[] test) {
550         doCalculatePercentile(percentile, test, Double.MAX_VALUE);
551     }
552 
553     private void doCalculatePercentile(Double percentile, Number[] test,
554             double delta) {
555         PSquarePercentile psquared = new PSquarePercentile(percentile);
556         for (Number value : test) {
557             psquared.increment(value.doubleValue());
558         }
559 
560         Percentile p2 = new Percentile(percentile * 100);
561 
562         double[] dall = new double[test.length];
563         for (int i = 0; i < test.length; i++) {
564             dall[i] = test[i].doubleValue();
565         }
566 
567         Double referenceValue = p2.evaluate(dall);
568         assertValues(psquared.getResult(), referenceValue, delta);
569     }
570 
571     private void doCalculatePercentile(double percentile, double[] test,
572             double delta) {
573         PSquarePercentile psquared = new PSquarePercentile(percentile);
574         for (double value : test) {
575             psquared.increment(value);
576         }
577 
578         Percentile p2 =
579                 new Percentile(percentile < 1 ? percentile * 100 : percentile);
580         /*
581          * double[] dall = new double[test.length]; for (int i = 0; i <
582          * test.length; i++) dall[i] = test[i];
583          */
584         Double referenceValue = p2.evaluate(test);
585         assertValues(psquared.getResult(), referenceValue, delta);
586     }
587 
588     @Test
589     public void testCannedDataSet() {
590         // test.unoverride("dump");
591         Integer[] seedInput =
592                 new Integer[] { 283, 285, 298, 304, 310, 31, 319, 32, 33, 339,
593                         342, 348, 350, 354, 354, 357, 36, 36, 369, 37, 37, 375,
594                         378, 383, 390, 396, 405, 408, 41, 414, 419, 416, 42,
595                         420, 430, 430, 432, 444, 447, 447, 449, 45, 451, 456,
596                         468, 470, 471, 474, 600, 695, 70, 83, 97, 109, 113, 128 };
597         Integer[] input = new Integer[seedInput.length * 100];
598         for (int i = 0; i < input.length; i++) {
599             input[i] = seedInput[i % seedInput.length] + i;
600         }
601         // Arrays.sort(input);
602         doCalculatePercentile(0.50d, input);
603         doCalculatePercentile(0.95d, input);
604     }
605 
606     @Test
607     public void test99Percentile() {
608         Double[] test = randomTestData(100, 10000);
609         doCalculatePercentile(0.99d, test);
610     }
611 
612     @Test
613     public void test90Percentile() {
614         Double[] test = randomTestData(100, 10000);
615         doCalculatePercentile(0.90d, test);
616     }
617 
618     @Test
619     public void test20Percentile() {
620         Double[] test = randomTestData(100, 100000);
621         doCalculatePercentile(0.20d, test);
622     }
623 
624     @Test
625     public void test5Percentile() {
626         Double[] test = randomTestData(50, 990000);
627         doCalculatePercentile(0.50d, test);
628     }
629 
630     @Test
631     public void test99PercentileHighValues() {
632         Double[] test = randomTestData(100000, 10000);
633         doCalculatePercentile(0.99d, test);
634     }
635 
636     @Test
637     public void test90PercentileHighValues() {
638         Double[] test = randomTestData(100000, 100000);
639         doCalculatePercentile(0.90d, test);
640     }
641 
642     @Test
643     public void test20PercentileHighValues() {
644         Double[] test = randomTestData(100000, 100000);
645         doCalculatePercentile(0.20d, test);
646     }
647 
648     @Test
649     public void test5PercentileHighValues() {
650         Double[] test = randomTestData(100000, 100000);
651         doCalculatePercentile(0.05d, test);
652     }
653 
654     @Test
655     public void test0PercentileValuesWithFewerThan5Values() {
656         double[] test = { 1d, 2d, 3d, 4d };
657         PSquarePercentile p = new PSquarePercentile(0d);
658         Assert.assertEquals(1d, p.evaluate(test), 0);
659         Assert.assertNotNull(p.toString());
660     }
661 
662     @Test
663     public void testPSQuaredEvalFuncWithPapersExampleData() throws IOException {
664 
665         // This data as input is considered from
666         // http://www.cs.wustl.edu/~jain/papers/ftp/psqr.pdf
667         double[] data =
668                 { 0.02, 0.5, 0.74, 3.39, 0.83, 22.37, 10.15, 15.43, 38.62,
669                         15.92, 34.6, 10.28, 1.47, 0.4, 0.05, 11.39, 0.27, 0.42,
670                         0.09, 11.37,
671 
672                         11.39, 15.43, 15.92, 22.37, 34.6, 38.62, 18.9, 19.2,
673                         27.6, 12.8, 13.7, 21.9
674                 };
675 
676         PSquarePercentile psquared = new PSquarePercentile(50);
677 
678         Double p2value = 0d;
679         for (int i = 0; i < 20; i++) {
680             psquared.increment(data[i]);
681             p2value = psquared.getResult();
682             // System.out.println(psquared.toString());//uncomment here to see
683             // the papers example output
684         }
685         // System.out.println("p2value=" + p2value);
686         Double expected = 4.44d;// 13d; // From The Paper
687         // http://www.cs.wustl.edu/~jain/papers/ftp/psqr.pdf.
688         // Pl refer Pg 1061 Look at the mid marker
689         // height
690         // expected = new Percentile(50).evaluate(data,0,20);
691         // Well the values deviate in our calculation by 0.25 so its 4.25 vs
692         // 4.44
693         Assert.assertEquals(
694                 String.format("Expected=%f, Actual=%f", expected, p2value),
695                 expected, p2value, 0.25);
696     }
697 
698     private final int TINY = 10;
699     private final int SMALL = 50;
700     private final int NOMINAL = 100;
701     private final int MEDIUM = 500;
702     private final int STANDARD = 1000;
703     private final int BIG = 10000;
704     private final int VERY_BIG = 50000;
705     private final int LARGE = 1000000;
706     private final int VERY_LARGE = 10000000;
707 
708     private void doDistributionTest(ContinuousDistribution distribution) {
709         final ContinuousDistribution.Sampler sampler =
710             distribution.createSampler(RandomSource.WELL_19937_C.create(1000));
711         double data[];
712 
713         data = AbstractRealDistribution.sample(VERY_LARGE, sampler);
714         doCalculatePercentile(50, data, 0.0001);
715         doCalculatePercentile(95, data, 0.0001);
716 
717         data = AbstractRealDistribution.sample(LARGE, sampler);
718         doCalculatePercentile(50, data, 0.001);
719         doCalculatePercentile(95, data, 0.001);
720 
721         data = AbstractRealDistribution.sample(VERY_BIG, sampler);
722         doCalculatePercentile(50, data, 0.001);
723         doCalculatePercentile(95, data, 0.001);
724 
725         data = AbstractRealDistribution.sample(BIG, sampler);
726         doCalculatePercentile(50, data, 0.001);
727         doCalculatePercentile(95, data, 0.001);
728 
729         data = AbstractRealDistribution.sample(STANDARD, sampler);
730         doCalculatePercentile(50, data, 0.005);
731         doCalculatePercentile(95, data, 0.005);
732 
733         data = AbstractRealDistribution.sample(MEDIUM, sampler);
734         doCalculatePercentile(50, data, 0.005);
735         doCalculatePercentile(95, data, 0.005);
736 
737         data = AbstractRealDistribution.sample(NOMINAL, sampler);
738         doCalculatePercentile(50, data, 0.01);
739         doCalculatePercentile(95, data, 0.01);
740 
741         data = AbstractRealDistribution.sample(SMALL, sampler);
742         doCalculatePercentile(50, data, 0.01);
743         doCalculatePercentile(95, data, 0.01);
744 
745         data = AbstractRealDistribution.sample(TINY, sampler);
746         doCalculatePercentile(50, data, 0.05);
747         doCalculatePercentile(95, data, 0.05);
748     }
749 
750     /**
751      * Test Various Dist
752      */
753     @Test
754     public void testDistribution() {
755         doDistributionTest(NormalDistribution.of(4000, 50));
756         doDistributionTest(LogNormalDistribution.of(4000, 50));
757         // doDistributionTest((ExponentialDistribution.of(4000));
758         // doDistributionTest(GammaDistribution.of(5d,1d),0.1);
759     }
760 }