/*
 * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
import java.util.ArrayList;
import java.util.List;

import java.util.random.*;

import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.DoubleSupplier;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

/**
 * @test
 * @summary test bit sequences produced by clases that implement interface RandomGenerator
 * @bug 8248862
 * @run main RandomTestMoments
 * @author Guy Steele
 * @key randomness
 */

public class RandomTestMoments {

    static String currentRNG = "";
    static int failCount = 0;

    static void exceptionOnFail() {
        if (failCount != 0) {
            throw new RuntimeException(failCount + " fails detected");
        }
    }

    static void setRNG(String rng) {
        currentRNG = rng;
    }

    static void fail(String format, Object... args) {
        if (currentRNG.length() != 0) {
            System.err.println(currentRNG);
            currentRNG = "";
        }

        System.err.format("  " + format, args);
        failCount++;
    }

    static final int SEQUENCE_SIZE = 50000;

    // Moment k of uniform distribution over [0.0,1.0) is 1.0/(1+k).

    static double[][] momentsUniform = {
       { 1.00000, 1.00000, 0.01000 },
       { 0.500000, 0.500000, 0.0266265 },
       { 0.333333, 0.333333, 0.0391128 },
       { 0.250000, 0.250000, 0.0477151 },
       { 0.200000, 0.200000, 0.0540496 },
       { 0.166667, 0.166667, 0.0589355 },
       { 0.142857, 0.142857, 0.0628462 },
       { 0.125000, 0.125000, 0.0660693 },
       { 0.111111, 0.111111, 0.0688036 },
       { 0.100000, 0.100000, 0.0712002 },
       { 0.0909091, 0.0909091, 0.0733755 },
       { 0.0833333, 0.0833333, 0.0754172 },
       { 0.0769231, 0.0769231, 0.0773868 },
       { 0.0714286, 0.0714286, 0.0793244 },
       { 0.0666667, 0.0666667, 0.0812526 },
       { 0.0625000, 0.0625000, 0.0831806 },
    };

    // Moment k of exponential distribution with mean 1 is k!.

    static double[][] momentsExponential = {
       { 1.00000, 1.00000, 0.01000 },
       { 1.00000, 1.00000, 0.0718997 },
       { 2.00000, 2.00000, 0.153241 },
       { 6.00000, 6.00000, 0.282813 },
       { 24.0000, 24.0000, 0.503707 },
    };


    // Absolute moment k of Gaussian distribution with mean 0 and stddev 1 is
    //    pow(2.0,k/2.0)*gamma((k+1)/2.0)/sqrt(PI)
    // https://arxiv.org/pdf/1209.4340.pdf, equation (18)

    static double[][] absoluteMomentsGaussian = {
       { 1.00000, 1.00000, 0.01 },
       { 0.797885, 0.797885, 0.1 },
       { 1.00000, 1.00000, 0.1 },
       { 1.59577, 1.59577, 0.2 },
       { 3.00000, 3.00000, 0.2 },
       { 6.38308, 6.38308, 0.2 },
       { 15.0000, 15.0000, 0.2 },
       { 38.2985, 38.2985, 0.2 },
       { 105.000, 105.000, 0.4 },
    };

    static void checkMoments(String test, double[] measurements, double[][] standard) {
       for (int j = 0; j < measurements.length; j++) {
           double actual = measurements[j];
           double expected = standard[j][0];
           double basis = standard[j][1];
           double tolerance = standard[j][2];
           if (!(Math.abs(actual - expected)/basis < tolerance)) {
               fail("%s fail: actual=%f, expected=%f, basis=%f, tolerance=%f\n",
                     test, actual, expected, basis, tolerance);
           }
       }
    }

    static void testMomentsGaussian(DoubleSupplier theSupplier) {
       int m = absoluteMomentsGaussian.length;
       double[] absoluteMoments = new double[m];
       for (int j = 0; j < SEQUENCE_SIZE; j++) {
           double v = theSupplier.getAsDouble();
           double z = 1.0;
           for (int k = 0; k < m; k++) {
               absoluteMoments[k] += Math.abs(z);
               z *= v;
           }
       }
       for (int k = 0; k < m; k++) {
           absoluteMoments[k] /= SEQUENCE_SIZE;
       }
       checkMoments("Gaussian", absoluteMoments, absoluteMomentsGaussian);
    }

    static void testMomentsExponential(DoubleSupplier theSupplier) {
       int m = momentsExponential.length;
       double[] moments = new double[m];
       for (int j = 0; j < SEQUENCE_SIZE; j++) {
           double v = theSupplier.getAsDouble();
           double z = 1.0;
           for (int k = 0; k < m; k++) {
               moments[k] += z;
               z *= v;
           }
       }
       for (int k = 0; k < m; k++) {
           moments[k] /= SEQUENCE_SIZE;
       }
       checkMoments("Exponential", moments, momentsExponential);
    }

    static void testMomentsUniform(DoubleSupplier theSupplier) {
       int m = momentsUniform.length;
       double[] moments = new double[m];
       for (int j = 0; j < SEQUENCE_SIZE; j++) {
           double v = theSupplier.getAsDouble();
           double z = 1.0;
           for (int k = 0; k < m; k++) {
               moments[k] += z;
               z *= v;
           }
       }
       for (int k = 0; k < m; k++) {
           moments[k] /= SEQUENCE_SIZE;
       }
       checkMoments("Uniform", moments, momentsUniform);
    }

    static void testOneRng(RandomGenerator rng) {
        testMomentsGaussian(rng::nextGaussian);
        testMomentsExponential(rng::nextExponential);
        testMomentsUniform(rng::nextDouble);
        testMomentsUniform(rng.doubles().iterator()::next);
    }

    public static void main(String[] args) {
        RandomGeneratorFactory.all()
                              .filter(f -> !f.name().equals("SecureRandom"))
                              .forEach(factory -> {
                setRNG(factory.name());
                testOneRng(factory.create(325) );
            });

        exceptionOnFail();
    }

}
