/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.math3.stat.descriptive.rank;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.commons.math3.distribution.LogNormalDistribution;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
import org.apache.commons.math3.exception.OutOfRangeException;
import org.apache.commons.math3.random.RandomGenerator;
import org.apache.commons.math3.random.Well19937c;
import org.apache.commons.math3.stat.descriptive.StorelessUnivariateStatistic;
import org.apache.commons.math3.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
import org.apache.commons.math3.stat.descriptive.UnivariateStatistic;
import org.apache.commons.math3.stat.descriptive.rank.PSquarePercentile.PSquareMarkers;
import org.apache.commons.math3.util.FastMath;
import org.junit.Assert;
import org.junit.Test;

/**
 * Test cases for the {@link PSquarePercentile} class which naturally extends
 * {@link StorelessUnivariateStatisticAbstractTest}.
 */
public class PSquarePercentileTest extends
        StorelessUnivariateStatisticAbstractTest {

    protected double percentile5 = 8.2299d;
    protected double percentile95 = 16.72195;// 20.82d; this is approximation
    protected double tolerance = 10E-12;

    private final RandomGenerator randomGenerator = new Well19937c(1000);

    @Override
    public double getTolerance() {
        return 1.0e-2;// tolerance limit changed as this is an approximation
        // algorithm and also gets accurate after few tens of
        // samples
    }

    /**
     * Verifies that copied statistics remain equal to originals when
     * incremented the same way by making the copy after a majority of elements
     * are incremented
     */
    @Test
    public void testCopyConsistencyWithInitialMostElements() {

        StorelessUnivariateStatistic master =
                (StorelessUnivariateStatistic) getUnivariateStatistic();

        StorelessUnivariateStatistic replica = null;

        // select a portion of testArray till 75 % of the length to load first
        long index = FastMath.round(0.75 * testArray.length);

        // Put first half in master and copy master to replica
        master.incrementAll(testArray, 0, (int) index);
        replica = master.copy();

        // Check same
        Assert.assertTrue(replica.equals(master));
        Assert.assertTrue(master.equals(replica));

        // Now add second part to both and check again
        master.incrementAll(testArray, (int) index,
                (int) (testArray.length - index));
        replica.incrementAll(testArray, (int) index,
                (int) (testArray.length - index));
        Assert.assertTrue(replica.equals(master));
        Assert.assertTrue(master.equals(replica));
    }

    /**
     * Verifies that copied statistics remain equal to originals when
     * incremented the same way by way of copying original after just a few
     * elements are incremented
     */
    @Test
    public void testCopyConsistencyWithInitialFirstFewElements() {

        StorelessUnivariateStatistic master =
                (StorelessUnivariateStatistic) getUnivariateStatistic();

        StorelessUnivariateStatistic replica = null;

        // select a portion of testArray which is 10% of the length to load
        // first
        long index = FastMath.round(0.1 * testArray.length);

        // Put first half in master and copy master to replica
        master.incrementAll(testArray, 0, (int) index);
        replica = master.copy();

        // Check same
        Assert.assertTrue(replica.equals(master));
        Assert.assertTrue(master.equals(replica));
        // Now add second part to both and check again
        master.incrementAll(testArray, (int) index,
                (int) (testArray.length - index));
        replica.incrementAll(testArray, (int) index,
                (int) (testArray.length - index));
        Assert.assertTrue(master.equals(master));
        Assert.assertTrue(replica.equals(replica));
        Assert.assertTrue(replica.equals(master));
        Assert.assertTrue(master.equals(replica));
    }

    @Test(expected = MathIllegalArgumentException.class)
    public void testNullListInMarkers() {
        // In case of null list Markers cannot be instantiated..is geting
        // verified
        // new Markers(null, 0, PSquarePercentile.newEstimator());
        PSquarePercentile.newMarkers(null, 0);

    }

    @Test
    public void testMiscellaniousFunctionsInMarkers() {
        double p = 0.5;
        PSquareMarkers markers =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91,
                                38.62 }), p);
        // Markers equality
        Assert.assertTrue(markers.equals(markers));
        Assert.assertFalse(markers.equals(null));
        Assert.assertFalse(markers.equals(new String()));
        // Check for null markers test during equality testing
        // Until 5 elements markers are not initialized
        PSquarePercentile p1 = new PSquarePercentile(), p2 =
                new PSquarePercentile();
        Assert.assertEquals(p1, p2);
        p1.evaluate(new double[] { 1.0, 2.0, 3.0 });
        p2.evaluate(new double[] { 1.0, 2.0, 3.0 });
        Assert.assertEquals(p1, p2);
        // Move p2 alone with more values just to make sure markers are not null
        // for p2
        p2.incrementAll(new double[] { 5.0, 7.0, 11.0 });
        Assert.assertFalse(p1.equals(p2));
        Assert.assertFalse(p2.equals(p1));
        // Next add different data to p1 to make number of elements match and
        // markers are not null however actual results will vary
        p1.incrementAll(new double[] { 20, 21, 22, 23 });
        Assert.assertFalse(p1.equals(p2));// though markers are non null, N
        // matches, results wont

    }

    @Test(expected = OutOfRangeException.class)
    public void testMarkersOORLow() {
        PSquarePercentile.newMarkers(
                Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91, 38.62 }),
                0.5).estimate(0);
    }

    @Test(expected = OutOfRangeException.class)
    public void testMarkersOORHigh() {
        PSquarePercentile.newMarkers(
                Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91, 38.62 }),
                0.5).estimate(5);
    }

    @Test
    public void testMarkers2() {
        double p = 0.5;
        PSquareMarkers markers =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91,
                                38.62 }), p);

        PSquareMarkers markersNew =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 0.02, 1.18, 9.15, 21.91,
                                38.62 }), p);

        Assert.assertTrue(markers.equals(markersNew));
        // If just one element of markers got changed then its still false.
        markersNew.processDataPoint(39);
        Assert.assertFalse(markers.equals(markersNew));

    }

    @Test
    public void testHashCodeInMarkers() {
        PSquarePercentile p = new PSquarePercentile(95);
        PSquarePercentile p2 = new PSquarePercentile(95);
        Set<PSquarePercentile> s = new HashSet<PSquarePercentile>();
        s.add(p);
        s.add(p2);
        Assert.assertEquals(1, s.size());
        Assert.assertEquals(p, s.iterator().next());
        double[] d =
                new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
                        95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
                        95.1682 };
        Assert.assertEquals(95.1981, p.evaluate(d), 1.0e-2); // change
        Assert.assertEquals(95.1981, p2.evaluate(d), 1.0e-2); // change
        s.clear();
        s.add(p);
        s.add(p2);
        Assert.assertEquals(1, s.size());
        Assert.assertEquals(p, s.iterator().next());

        PSquareMarkers m1 =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.0);
        PSquareMarkers m2 =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.0);
        Assert.assertTrue(m1.equals(m2));
        Set<PSquareMarkers> setMarkers = new LinkedHashSet<PSquareMarkers>();
        Assert.assertTrue(setMarkers.add(m1));
        Assert.assertFalse(setMarkers.add(m2));
        Assert.assertEquals(1, setMarkers.size());

        PSquareMarkers mThis =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 195.1772, 195.1567,
                                195.1937, 195.1959, 95.1442, 195.0610,
                                195.1591, 195.1195, 195.1772, 95.0925, 95.1990,
                                195.1682 }), 0.50);
        PSquareMarkers mThat =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
        Assert.assertTrue(mThis.equals(mThis));
        Assert.assertFalse(mThis.equals(mThat));
        String s1="";
        Assert.assertFalse(mThis.equals(s1));
        for (int i = 0; i < testArray.length; i++) {
            mThat.processDataPoint(testArray[i]);
        }
        setMarkers.add(mThat);
        setMarkers.add(mThis);
        Assert.assertTrue(mThat.equals(mThat));
        Assert.assertTrue(setMarkers.contains(mThat));
        Assert.assertTrue(setMarkers.contains(mThis));
        Assert.assertEquals(3, setMarkers.size());
        Iterator<PSquareMarkers> iterator=setMarkers.iterator();
        Assert.assertEquals(m1, iterator.next());
        Assert.assertEquals(mThat, iterator.next());
        Assert.assertEquals(mThis, iterator.next());
    }

    @Test(expected = OutOfRangeException.class)
    public void testMarkersWithLowerIndex() {
        PSquareMarkers mThat =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
        for (int i = 0; i < testArray.length; i++) {
            mThat.processDataPoint(testArray[i]);
        }
        mThat.estimate(0);
    }

    @Test(expected = OutOfRangeException.class)
    public void testMarkersWithHigherIndex() {
        PSquareMarkers mThat =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
        for (int i = 0; i < testArray.length; i++) {
            mThat.processDataPoint(testArray[i]);
        }
        mThat.estimate(6);
    }

    @Test(expected = OutOfRangeException.class)
    public void testMarkerHeightWithLowerIndex() {
        PSquareMarkers mThat =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
        mThat.height(0);
    }

    @Test(expected = OutOfRangeException.class)
    public void testMarkerHeightWithHigherIndex() {
        PSquareMarkers mThat =
                PSquarePercentile.newMarkers(
                        Arrays.asList(new Double[] { 95.1772, 95.1567, 95.1937,
                                95.1959, 95.1442, 95.0610, 95.1591, 95.1195,
                                95.1772, 95.0925, 95.1990, 95.1682 }), 0.50);
        mThat.height(6);
    }

    @Test
    public void testPSquaredEqualsAndMin() {
        PSquarePercentile ptile = new PSquarePercentile(0);
        Assert.assertEquals(ptile, ptile);
        Assert.assertFalse(ptile.equals(null));
        Assert.assertFalse(ptile.equals(new String()));
        // Just to check if there is no data get result for zeroth and 100th
        // ptile returns NAN
        Assert.assertTrue(Double.isNaN(ptile.getResult()));
        Assert.assertTrue(Double.isNaN(new PSquarePercentile(100).getResult()));

        double[] d = new double[] { 1, 3, 2, 4, 9, 10, 11 };
        ptile.evaluate(d);
        Assert.assertEquals(ptile, ptile);
        Assert.assertEquals(1d, ptile.getResult(), 1e-02);// this calls min
    }

    @Test
    public void testString() {
        PSquarePercentile ptile = new PSquarePercentile(95);
        Assert.assertNotNull(ptile.toString());
        ptile.increment(1);
        ptile.increment(2);
        ptile.increment(3);
        Assert.assertNotNull(ptile.toString());
        Assert.assertEquals(expectedValue(), ptile.evaluate(testArray),
                getTolerance());
        Assert.assertNotNull(ptile.toString());
    }

    @Override
    public UnivariateStatistic getUnivariateStatistic() {
        PSquarePercentile ptile = new PSquarePercentile(95);
        // Assert.assertNull(ptile.markers());
        return ptile;
    }

    @Override
    public double expectedValue() {
        return this.percentile95;
    }

    @Test
    public void testHighPercentile() {
        double[] d = new double[] { 1, 2, 3 };
        PSquarePercentile p = new PSquarePercentile(75.0);
        Assert.assertEquals(2, p.evaluate(d), 1.0e-5);
        PSquarePercentile p95 = new PSquarePercentile();
        Assert.assertEquals(2, p95.evaluate(d), 1.0e-5);
    }

    @Test
    public void testLowPercentile() {
        double[] d = new double[] { 0, 1 };
        PSquarePercentile p = new PSquarePercentile(25.0);
        Assert.assertEquals(0d, p.evaluate(d), Double.MIN_VALUE);
    }

    @Test
    public void testPercentile() {
        double[] d = new double[] { 1, 3, 2, 4 };
        PSquarePercentile p = new PSquarePercentile(30d);
        Assert.assertEquals(1.0, p.evaluate(d), 1.0e-5);
        p = new PSquarePercentile(25);
        Assert.assertEquals(1.0, p.evaluate(d), 1.0e-5);
        p = new PSquarePercentile(75);
        Assert.assertEquals(3.0, p.evaluate(d), 1.0e-5);
        p = new PSquarePercentile(50);
        Assert.assertEquals(2d, p.evaluate(d), 1.0e-5);

    }

    @Test(expected = MathIllegalArgumentException.class)
    public void testInitial() {
        PSquarePercentile.newMarkers(new ArrayList<Double>(), 0.5);
        Assert.fail();
    }

    @Test(expected = MathIllegalArgumentException.class)
    public void testNegativeInvalidValues() {
        double[] d =
                new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
                        95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
                        95.1682 };
        PSquarePercentile p = new PSquarePercentile(-1.0);
        p.evaluate(d, 0, d.length);
        Assert.fail("This method has had to throw exception..but it is not..");

    }

    @Test(expected = MathIllegalArgumentException.class)
    public void testPositiveInvalidValues() {
        double[] d =
                new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
                        95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
                        95.1682 };
        PSquarePercentile p = new PSquarePercentile(101.0);
        p.evaluate(d, 0, d.length);
        Assert.fail("This method has had to throw exception..but it is not..");

    }

    @Test
    public void testNISTExample() {
        double[] d =
                new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
                        95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
                        95.1682 };
        Assert.assertEquals(95.1981, new PSquarePercentile(90d).evaluate(d),
                1.0e-2); // changed the accuracy to 1.0e-2
        Assert.assertEquals(95.061, new PSquarePercentile(0d).evaluate(d), 0);
        Assert.assertEquals(95.1990,
                new PSquarePercentile(100d).evaluate(d, 0, d.length), 0);
    }

    @Test
    public void test5() {
        PSquarePercentile percentile = new PSquarePercentile(5d);
        Assert.assertEquals(this.percentile5, percentile.evaluate(testArray),
                1.0);// changed the accuracy to 1 instead of tolerance
    }

    @Test(expected = MathIllegalArgumentException.class)
    public void testNull() {
        PSquarePercentile percentile = new PSquarePercentile(50d);
        double[] nullArray = null;
        percentile.evaluate(nullArray);
    }

    @Test
    public void testEmpty() {
        PSquarePercentile percentile = new PSquarePercentile(50d);
        double[] emptyArray = new double[] {};
        Assert.assertTrue(Double.isNaN(percentile.evaluate(emptyArray)));
    }

    @Test
    public void testSingleton() {
        PSquarePercentile percentile = new PSquarePercentile(50d);
        double[] singletonArray = new double[] { 1d };
        Assert.assertEquals(1d, percentile.evaluate(singletonArray), 0);
        Assert.assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
        percentile = new PSquarePercentile(5);
        Assert.assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
        percentile = new PSquarePercentile(100);
        Assert.assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
        percentile = new PSquarePercentile(100);
        Assert.assertTrue(Double.isNaN(percentile
                .evaluate(singletonArray, 0, 0)));
    }

    @Test
    public void testSpecialValues() {
        PSquarePercentile percentile = new PSquarePercentile(50d);
        double[] specialValues =
                new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
        Assert.assertEquals(2d, percentile.evaluate(specialValues), 0);
        specialValues =
                new double[] { Double.NEGATIVE_INFINITY, 1d, 2d, 3d,
                        Double.NaN, Double.POSITIVE_INFINITY };
        Assert.assertEquals(2d, percentile.evaluate(specialValues), 0);
        specialValues =
                new double[] { 1d, 1d, Double.POSITIVE_INFINITY,
                        Double.POSITIVE_INFINITY };
        Assert.assertFalse(Double.isInfinite(percentile.evaluate(specialValues)));
        specialValues = new double[] { 1d, 1d, Double.NaN, Double.NaN };
        Assert.assertFalse(Double.isNaN(percentile.evaluate(specialValues)));
        specialValues =
                new double[] { 1d, 1d, Double.NEGATIVE_INFINITY,
                        Double.NEGATIVE_INFINITY };
        percentile = new PSquarePercentile(50d);
        // Interpolation results in NEGATIVE_INFINITY + POSITIVE_INFINITY
        // changed the result check to infinity instead of NaN
        Assert.assertTrue(Double.isInfinite(percentile.evaluate(specialValues)));
    }

    @Test
    public void testArrayExample() {
        Assert.assertEquals(expectedValue(),
                new PSquarePercentile(95d).evaluate(testArray), getTolerance());
    }

    @Test
    public void testSetQuantile() {
        PSquarePercentile percentile = new PSquarePercentile(10d);

        percentile = new PSquarePercentile(100); // OK
        Assert.assertEquals(1.0, percentile.quantile(), 0);
        try {
            percentile = new PSquarePercentile(0);
            // Assert.fail("Expecting MathIllegalArgumentException");
        } catch (MathIllegalArgumentException ex) {
            // expected
        }
        try {
            new PSquarePercentile(0d);
            // Assert.fail("Expecting MathIllegalArgumentException");
        } catch (MathIllegalArgumentException ex) {
            // expected
        }
    }

    private Double[] randomTestData(int factor, int values) {
        Double[] test = new Double[values];
        for (int i = 0; i < test.length; i++) {
            test[i] = Math.abs(randomGenerator.nextDouble() * factor);
        }
        return test;
    }

    @Test
    public void testAccept() {
        PSquarePercentile psquared = new PSquarePercentile(0.99);
        Assert.assertTrue(Double.isNaN(psquared.getResult()));
        Double[] test = randomTestData(100, 10000);

        for (Double value : test) {
            psquared.increment(value);
            Assert.assertTrue(psquared.getResult() >= 0);
        }
    }

    private void assertValues(Double a, Double b, double delta) {
        if (Double.isNaN(a)) {
            Assert.assertTrue("" + b + " is not NaN.", Double.isNaN(a));
        } else {
            double max = FastMath.max(a, b);
            double percentage = FastMath.abs(a - b) / max;
            double deviation = delta;
            Assert.assertTrue(String.format(
                    "Deviated = %f and is beyond %f as a=%f,  b=%f",
                    percentage, deviation, a, b), percentage < deviation);
        }
    }

    private void doCalculatePercentile(Double percentile, Number[] test) {
        doCalculatePercentile(percentile, test, Double.MAX_VALUE);
    }

    private void doCalculatePercentile(Double percentile, Number[] test,
            double delta) {
        PSquarePercentile psquared = new PSquarePercentile(percentile);
        for (Number value : test) {
            psquared.increment(value.doubleValue());
        }

        Percentile p2 = new Percentile(percentile * 100);

        double[] dall = new double[test.length];
        for (int i = 0; i < test.length; i++) {
            dall[i] = test[i].doubleValue();
        }

        Double referenceValue = p2.evaluate(dall);
        assertValues(psquared.getResult(), referenceValue, delta);
    }

    private void doCalculatePercentile(double percentile, double[] test,
            double delta) {
        PSquarePercentile psquared = new PSquarePercentile(percentile);
        for (double value : test) {
            psquared.increment(value);
        }

        Percentile p2 =
                new Percentile(percentile < 1 ? percentile * 100 : percentile);
        /*
         * double[] dall = new double[test.length]; for (int i = 0; i <
         * test.length; i++) dall[i] = test[i];
         */
        Double referenceValue = p2.evaluate(test);
        assertValues(psquared.getResult(), referenceValue, delta);
    }

    @Test
    public void testCannedDataSet() {
        // test.unoverride("dump");
        Integer[] seedInput =
                new Integer[] { 283, 285, 298, 304, 310, 31, 319, 32, 33, 339,
                        342, 348, 350, 354, 354, 357, 36, 36, 369, 37, 37, 375,
                        378, 383, 390, 396, 405, 408, 41, 414, 419, 416, 42,
                        420, 430, 430, 432, 444, 447, 447, 449, 45, 451, 456,
                        468, 470, 471, 474, 600, 695, 70, 83, 97, 109, 113, 128 };
        Integer[] input = new Integer[seedInput.length * 100];
        for (int i = 0; i < input.length; i++) {
            input[i] = seedInput[i % seedInput.length] + i;
        }
        // Arrays.sort(input);
        doCalculatePercentile(0.50d, input);
        doCalculatePercentile(0.95d, input);

    }

    @Test
    public void test99Percentile() {
        Double[] test = randomTestData(100, 10000);
        doCalculatePercentile(0.99d, test);
    }

    @Test
    public void test90Percentile() {
        Double[] test = randomTestData(100, 10000);
        doCalculatePercentile(0.90d, test);
    }

    @Test
    public void test20Percentile() {
        Double[] test = randomTestData(100, 100000);
        doCalculatePercentile(0.20d, test);
    }

    @Test
    public void test5Percentile() {
        Double[] test = randomTestData(50, 990000);
        doCalculatePercentile(0.50d, test);
    }

    @Test
    public void test99PercentileHighValues() {
        Double[] test = randomTestData(100000, 10000);
        doCalculatePercentile(0.99d, test);
    }

    @Test
    public void test90PercentileHighValues() {
        Double[] test = randomTestData(100000, 100000);
        doCalculatePercentile(0.90d, test);
    }

    @Test
    public void test20PercentileHighValues() {
        Double[] test = randomTestData(100000, 100000);
        doCalculatePercentile(0.20d, test);
    }

    @Test
    public void test5PercentileHighValues() {
        Double[] test = randomTestData(100000, 100000);
        doCalculatePercentile(0.05d, test);
    }

    @Test
    public void test0PercentileValuesWithFewerThan5Values() {
        double[] test = { 1d, 2d, 3d, 4d };
        PSquarePercentile p = new PSquarePercentile(0d);
        Assert.assertEquals(1d, p.evaluate(test), 0);
        Assert.assertNotNull(p.toString());
    }

    @Test
    public void testPSQuaredEvalFuncWithPapersExampleData() throws IOException {

        // This data as input is considered from
        // http://www.cs.wustl.edu/~jain/papers/ftp/psqr.pdf
        double[] data =
                { 0.02, 0.5, 0.74, 3.39, 0.83, 22.37, 10.15, 15.43, 38.62,
                        15.92, 34.6, 10.28, 1.47, 0.4, 0.05, 11.39, 0.27, 0.42,
                        0.09, 11.37,

                        11.39, 15.43, 15.92, 22.37, 34.6, 38.62, 18.9, 19.2,
                        27.6, 12.8, 13.7, 21.9

                };

        PSquarePercentile psquared = new PSquarePercentile(50);

        Double p2value = 0d;
        for (int i = 0; i < 20; i++) {
            psquared.increment(data[i]);
            p2value = psquared.getResult();
            // System.out.println(psquared.toString());//uncomment here to see
            // the papers example output
        }
        // System.out.println("p2value=" + p2value);
        Double expected = 4.44d;// 13d; // From The Paper
        // http://www.cs.wustl.edu/~jain/papers/ftp/psqr.pdf.
        // Pl refer Pg 1061 Look at the mid marker
        // height
        // expected = new Percentile(50).evaluate(data,0,20);
        // Well the values deviate in our calculation by 0.25 so its 4.25 vs
        // 4.44
        Assert.assertEquals(
                String.format("Expected=%f, Actual=%f", expected, p2value),
                expected, p2value, 0.25);

    }

    final int TINY = 10, SMALL = 50, NOMINAL = 100, MEDIUM = 500,
            STANDARD = 1000, BIG = 10000, VERY_BIG = 50000, LARGE = 1000000,
            VERY_LARGE = 10000000;

    private void doDistributionTest(RealDistribution distribution) {
        double data[];

        data = distribution.sample(VERY_LARGE);
        doCalculatePercentile(50, data, 0.0001);
        doCalculatePercentile(95, data, 0.0001);

        data = distribution.sample(LARGE);
        doCalculatePercentile(50, data, 0.001);
        doCalculatePercentile(95, data, 0.001);

        data = distribution.sample(VERY_BIG);
        doCalculatePercentile(50, data, 0.001);
        doCalculatePercentile(95, data, 0.001);

        data = distribution.sample(BIG);
        doCalculatePercentile(50, data, 0.001);
        doCalculatePercentile(95, data, 0.001);

        data = distribution.sample(STANDARD);
        doCalculatePercentile(50, data, 0.005);
        doCalculatePercentile(95, data, 0.005);

        data = distribution.sample(MEDIUM);
        doCalculatePercentile(50, data, 0.005);
        doCalculatePercentile(95, data, 0.005);

        data = distribution.sample(NOMINAL);
        doCalculatePercentile(50, data, 0.01);
        doCalculatePercentile(95, data, 0.01);

        data = distribution.sample(SMALL);
        doCalculatePercentile(50, data, 0.01);
        doCalculatePercentile(95, data, 0.01);

        data = distribution.sample(TINY);
        doCalculatePercentile(50, data, 0.05);
        doCalculatePercentile(95, data, 0.05);

    }

    /**
     * Test Various Dist
     */
    @Test
    public void testDistribution() {
        doDistributionTest(new NormalDistribution(randomGenerator, 4000, 50));
        doDistributionTest(new LogNormalDistribution(randomGenerator,4000, 50));
        // doDistributionTest((new ExponentialDistribution(4000));
        // doDistributionTest(new GammaDistribution(5d,1d),0.1);
    }
}
