/*
 * 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.random;

import java.util.Arrays;

import org.apache.commons.math3.TestUtils;
import org.apache.commons.math3.stat.Frequency;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.commons.math3.util.FastMath;
import org.apache.commons.math3.exception.MathIllegalArgumentException;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Base class for RandomGenerator tests.
 *
 * Tests RandomGenerator methods directly and also executes RandomDataTest
 * test cases against a RandomDataImpl created using the provided generator.
 *
 * RandomGenerator test classes should extend this class, implementing
 * makeGenerator() to provide a concrete generator to test. The generator
 * returned by makeGenerator should be seeded with a fixed seed.
 *
 */

public abstract class RandomGeneratorAbstractTest extends RandomDataGeneratorTest {

    /** RandomGenerator under test */
    protected RandomGenerator generator;

    /**
     * Override this method in subclasses to provide a concrete generator to test.
     * Return a generator seeded with a fixed seed.
     */
    protected abstract RandomGenerator makeGenerator();

    /**
     * Initialize generator and randomData instance in superclass.
     */
    public RandomGeneratorAbstractTest() {
        generator = makeGenerator();
        randomData = new RandomDataGenerator(generator);
    }

    /**
     * Set a fixed seed for the tests
     */
    @Before
    public void setUp() {
        generator = makeGenerator();
    }

    // Omit secureXxx tests, since they do not use the provided generator
    @Override
    public void testNextSecureLongIAE() {}
    @Override
    public void testNextSecureLongNegativeToPositiveRange() {}
    @Override
    public void testNextSecureLongNegativeRange() {}
    @Override
    public void testNextSecureLongPositiveRange() {}
    @Override
    public void testNextSecureIntIAE() {}
    @Override
    public void testNextSecureIntNegativeToPositiveRange() {}
    @Override
    public void testNextSecureIntNegativeRange() {}
    @Override
    public void testNextSecureIntPositiveRange() {}
    @Override
    public void testNextSecureHex() {}

    @Test
    /**
     * Tests uniformity of nextInt(int) distribution by generating 1000
     * samples for each of 10 test values and for each sample performing
     * a chi-square test of homogeneity of the observed distribution with
     * the expected uniform distribution.  Tests are performed at the .01
     * level and an average failure rate higher than 2% (i.e. more than 20
     * null hypothesis rejections) causes the test case to fail.
     *
     * All random values are generated using the generator instance used by
     * other tests and the generator is not reseeded, so this is a fixed seed
     * test.
     */
    public void testNextIntDirect() {
        // Set up test values - end of the array filled randomly
        int[] testValues = new int[] {4, 10, 12, 32, 100, 10000, 0, 0, 0, 0};
        for (int i = 6; i < 10; i++) {
            final int val = generator.nextInt();
            testValues[i] = val < 0 ? -val : val + 1;
        }

        final int numTests = 1000;
        for (int i = 0; i < testValues.length; i++) {
            final int n = testValues[i];
            // Set up bins
            int[] binUpperBounds;
            if (n < 32) {
                binUpperBounds = new int[n];
                for (int k = 0; k < n; k++) {
                    binUpperBounds[k] = k;
                }
            } else {
                binUpperBounds = new int[10];
                final int step = n / 10;
                for (int k = 0; k < 9; k++) {
                    binUpperBounds[k] = (k + 1) * step;
                }
                binUpperBounds[9] = n - 1;
            }
            // Run the tests
            int numFailures = 0;
            final int binCount = binUpperBounds.length;
            final long[] observed = new long[binCount];
            final double[] expected = new double[binCount];
            expected[0] = binUpperBounds[0] == 0 ? (double) smallSampleSize / (double) n :
                (double) ((binUpperBounds[0] + 1) * smallSampleSize) / (double) n;
            for (int k = 1; k < binCount; k++) {
                expected[k] = (double) smallSampleSize *
                (double) (binUpperBounds[k] - binUpperBounds[k - 1]) / n;
            }
            for (int j = 0; j < numTests; j++) {
                Arrays.fill(observed, 0);
                for (int k = 0; k < smallSampleSize; k++) {
                    final int value = generator.nextInt(n);
                    Assert.assertTrue("nextInt range",(value >= 0) && (value < n));
                    for (int l = 0; l < binCount; l++) {
                        if (binUpperBounds[l] >= value) {
                            observed[l]++;
                            break;
                        }
                    }
                }
                if (testStatistic.chiSquareTest(expected, observed) < 0.01) {
                    numFailures++;
                }
            }
            if ((double) numFailures / (double) numTests > 0.02) {
                Assert.fail("Too many failures for n = " + n +
                " " + numFailures + " out of " + numTests + " tests failed.");
            }
        }
    }

    @Test
    public void testNextIntIAE2() {
        try {
            generator.nextInt(-1);
            Assert.fail("MathIllegalArgumentException expected");
        } catch (MathIllegalArgumentException ex) {
            // ignored
        }
        try {
            generator.nextInt(0);
        } catch (MathIllegalArgumentException ex) {
            // ignored
        }
    }

    @Test
    public void testNextLongDirect() {
        long q1 = Long.MAX_VALUE/4;
        long q2 = 2 *  q1;
        long q3 = 3 * q1;

        Frequency freq = new Frequency();
        long val = 0;
        int value = 0;
        for (int i=0; i<smallSampleSize; i++) {
            val = generator.nextLong();
            val = val < 0 ? -val : val;
            if (val < q1) {
                value = 0;
            } else if (val < q2) {
                value = 1;
            } else if (val < q3) {
                value = 2;
            } else {
                value = 3;
            }
            freq.addValue(value);
        }
        long[] observed = new long[4];
        for (int i=0; i<4; i++) {
            observed[i] = freq.getCount(i);
        }

        /* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
         * Change to 11.34 for alpha = .01
         */
        Assert.assertTrue("chi-square test -- will fail about 1 in 1000 times",
                testStatistic.chiSquare(expected,observed) < 16.27);
    }

    @Test
    public void testNextBooleanDirect() {
        long halfSampleSize = smallSampleSize / 2;
        double[] expected = {halfSampleSize, halfSampleSize};
        long[] observed = new long[2];
        for (int i=0; i<smallSampleSize; i++) {
            if (generator.nextBoolean()) {
                observed[0]++;
            } else {
                observed[1]++;
            }
        }
        /* Use ChiSquare dist with df = 2-1 = 1, alpha = .001
         * Change to 6.635 for alpha = .01
         */
        Assert.assertTrue("chi-square test -- will fail about 1 in 1000 times",
                testStatistic.chiSquare(expected,observed) < 10.828);
    }

    @Test
    public void testNextFloatDirect() {
        Frequency freq = new Frequency();
        float val = 0;
        int value = 0;
        for (int i=0; i<smallSampleSize; i++) {
            val = generator.nextFloat();
            if (val < 0.25) {
                value = 0;
            } else if (val < 0.5) {
                value = 1;
            } else if (val < 0.75) {
                value = 2;
            } else {
                value = 3;
            }
            freq.addValue(value);
        }
        long[] observed = new long[4];
        for (int i=0; i<4; i++) {
            observed[i] = freq.getCount(i);
        }

        /* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
         * Change to 11.34 for alpha = .01
         */
        Assert.assertTrue("chi-square test -- will fail about 1 in 1000 times",
                testStatistic.chiSquare(expected,observed) < 16.27);
    }

    @Test
    public void testDoubleDirect() {
        SummaryStatistics sample = new SummaryStatistics();
        final int N = 10000;
        for (int i = 0; i < N; ++i) {
            sample.addValue(generator.nextDouble());
        }
        Assert.assertEquals("Note: This test will fail randomly about 1 in 100 times.",
                0.5, sample.getMean(), FastMath.sqrt(N/12.0) * 2.576);
        Assert.assertEquals(1.0 / (2.0 * FastMath.sqrt(3.0)),
                     sample.getStandardDeviation(), 0.01);
    }

    @Test
    public void testFloatDirect() {
        SummaryStatistics sample = new SummaryStatistics();
        final int N = 1000;
        for (int i = 0; i < N; ++i) {
            sample.addValue(generator.nextFloat());
        }
        Assert.assertEquals("Note: This test will fail randomly about 1 in 100 times.",
                0.5, sample.getMean(), FastMath.sqrt(N/12.0) * 2.576);
        Assert.assertEquals(1.0 / (2.0 * FastMath.sqrt(3.0)),
                     sample.getStandardDeviation(), 0.01);
    }

    @Test(expected=MathIllegalArgumentException.class)
    public void testNextIntNeg() {
        generator.nextInt(-1);
    }

    @Test
    public void testNextInt2() {
        int walk = 0;
        final int N = 10000;
        for (int k = 0; k < N; ++k) {
           if (generator.nextInt() >= 0) {
               ++walk;
           } else {
               --walk;
           }
        }
        Assert.assertTrue("Walked too far astray: " + walk + "\nNote: This " +
                "test will fail randomly about 1 in 100 times.",
                FastMath.abs(walk) < FastMath.sqrt(N) * 2.576);
    }

    @Test
    public void testNextLong2() {
        int walk = 0;
        final int N = 1000;
        for (int k = 0; k < N; ++k) {
           if (generator.nextLong() >= 0) {
               ++walk;
           } else {
               --walk;
           }
        }
        Assert.assertTrue("Walked too far astray: " + walk + "\nNote: This " +
                "test will fail randomly about 1 in 100 times.",
                FastMath.abs(walk) < FastMath.sqrt(N) * 2.576);
    }

    @Test
    public void testNexBoolean2() {
        int walk = 0;
        final int N = 10000;
        for (int k = 0; k < N; ++k) {
           if (generator.nextBoolean()) {
               ++walk;
           } else {
               --walk;
           }
        }
        Assert.assertTrue("Walked too far astray: " + walk + "\nNote: This " +
                "test will fail randomly about 1 in 100 times.",
                FastMath.abs(walk) < FastMath.sqrt(N) * 2.576);
    }

    @Test
    public void testNexBytes() {
        long[] count = new long[256];
        byte[] bytes = new byte[10];
        double[] expected = new double[256];
        final int sampleSize = 100000;

        for (int i = 0; i < 256; i++) {
            expected[i] = (double) sampleSize / 265f;
        }

        for (int k = 0; k < sampleSize; ++k) {
           generator.nextBytes(bytes);
           for (byte b : bytes) {
               ++count[b + 128];
           }
        }

        TestUtils.assertChiSquareAccept(expected, count, 0.001);

    }

    @Test
    public void testSeeding() {
        // makeGenerator initializes with fixed seed
        RandomGenerator gen = makeGenerator();
        RandomGenerator gen1 = makeGenerator();
        checkSameSequence(gen, gen1);
        // reseed, but recreate the second one
        // verifies MATH-723
        gen.setSeed(100);
        gen1 = makeGenerator();
        gen1.setSeed(100);
        checkSameSequence(gen, gen1);
    }

    private void checkSameSequence(RandomGenerator gen1, RandomGenerator gen2) {
        final int len = 11;  // Needs to be an odd number to check MATH-723
        final double[][] values = new double[2][len];
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextDouble();
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextDouble();
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextFloat();
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextFloat();
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextInt();
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextInt();
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextLong();
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextLong();
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextInt(len);
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextInt(len);
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextBoolean() ? 1 : 0;
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextBoolean() ? 1 : 0;
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
        for (int i = 0; i < len; i++) {
            values[0][i] = gen1.nextGaussian();
        }
        for (int i = 0; i < len; i++) {
            values[1][i] = gen2.nextGaussian();
        }
        Assert.assertTrue(Arrays.equals(values[0], values[1]));
    }

}
