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