/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/licenses/publicdomain
 */
import java.util.*;
import java.util.concurrent.atomic.*;

public class RNGLoopsV4 {

    static volatile int total = 0;

    static void fpi(int iters, Random rng, String tag) {
        int under = 0;
        long startTime = System.nanoTime();
        for (int i = iters; i > 0; --i) {
            float x1 = rng.nextFloat();
            float y1 = rng.nextFloat();
            if (x1*x1 + y1*y1 <= 1.0)
                under++;
        }
        double time = System.nanoTime() - startTime;
        double est = 4.0 * under / iters;
        double tpr = time / iters;
        System.out.print(tag + " fTime : " + tpr);
        System.out.println(" \tpi est : " + est);
    }

    static void dpi(int iters, Random rng, String tag) {
        int under = 0;
        long startTime = System.nanoTime();
        for (int i = 0; i < iters; ++i) {
            double x1 = rng.nextDouble();
            double y1 = rng.nextDouble();
            if (x1*x1 + y1*y1 <= 1.0)
                under++;
        }
        double time = System.nanoTime() - startTime;
        double est = 4.0 * under / iters;
        double tpr = time / iters;
        System.out.print(tag + " dTime : " + tpr);
        System.out.println(" \tpi est : " + est);
    }

    static void oneRun(int iters) {
        dpi(iters, XorShiftRandomFactory.xorShift1(), "L");
        //        fpi(iters, XorShiftRandomFactory.xorShift1(), "L");
        //        fpi(iters, XorShiftRandomFactory.xorShift4(), "M");
        //        fpi(iters, XorShiftRandomFactory.xorShift8(), "H");
        //        dpi(iters, XorShiftRandomFactory.xorShift4(), "M");
        //        dpi(iters, XorShiftRandomFactory.xorShift8(), "H");

        //        pi(iters, new UnsynchedRandom(), "U");
        //        pi(iters, new Random(), "R");
    }

    public static void main(String[] args) {
        for (int k = 2; k < 32; k += 2) {
            int iters = 1 << k;
            System.out.println("Iterations : " + iters);
            oneRun(iters);
        }
    }

    static final class UnsynchedRandom extends java.util.Random {
        private final static long multiplier = 0x5DEECE66DL;
        private final static long addend = 0xBL;
        private final static long mask = (1L << 48) - 1;
        private long seed = System.nanoTime();

        UnsynchedRandom() { super(); }
        UnsynchedRandom(long seed) { super(seed); }
        public void setSeed(long seed) {
            super.setSeed(seed);
            this.seed = seed;
        }

        protected final int next(int bits) {  
            long nextseed = (seed * multiplier + addend) & mask;
            seed = nextseed;
            return (int)(nextseed >>> (48 - bits));
        }
    }


}
