/*
 * 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/publicdomain/zero/1.0/
 */

import java.util.*;
import java.util.concurrent.*;

public class RSL3 {
    static final long SR_SIZE  = 10_000_000_000L;
    static final long JUR_SIZE = 10_000_000_000L;
    static final int REPS = 5;
    public static void main(String[] args) throws Exception {
        System.out.println("par: " + ForkJoinPool.getCommonPoolParallelism());
        long lsum = 0L; int isum = 0; double dsum = 0.0;
        long size = 1000000L;
        lsum += t3(size);
        lsum += t6(size + 1);
        dsum += t3d(size + 2);
        dsum += t6d(size + 3);
        isum += t3i(size + 4);
        isum += t6i(size + 5);
        System.out.println();
        System.gc();
        for (int reps = 0; reps < 3; ++reps) 
            lsum += t6(JUR_SIZE);
        for (int reps = 0; reps < 3; ++reps) 
            lsum += t3(SR_SIZE);
        for (int reps = 0; reps < 3; ++reps) 
            dsum += t6d(JUR_SIZE);
        for (int reps = 0; reps < 3; ++reps) 
            dsum += t3d(SR_SIZE);
        for (int reps = 0; reps < 3; ++reps) 
            isum += t6i(JUR_SIZE);
        for (int reps = 0; reps < 3; ++reps) 
            isum += t3i(SR_SIZE);
        if (isum + lsum + dsum == 0) System.out.println(" ");
    }

    static long t1(long size) {
        SplittableRandom r = new SplittableRandom();
        long start = System.nanoTime();
        long sum = r.longs(size).parallel().sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("L SR  par n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static long t3(long size) {
        SplittableRandom r = new SplittableRandom();
        long start = System.nanoTime();
        long sum = r.longs(size).sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("L SR  seq n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static long t5(long size) {
        Random r = new Random();
        long start = System.nanoTime();
        long sum = r.longs().limit(size).parallel().sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("L JUR par n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static long t6(long size) {
        Random r = new Random();
        long start = System.nanoTime();
        long sum = r.longs().limit(size).sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("L JUR seq n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static double t1d(long size) {
        SplittableRandom r = new SplittableRandom();
        long start = System.nanoTime();
        double sum = r.doubles(size).parallel().sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("D SR  par n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static double t3d(long size) {
        SplittableRandom r = new SplittableRandom();
        long start = System.nanoTime();
        double sum = r.doubles(size).sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("D SR  seq n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static double t5d(long size) {
        Random r = new Random();
        long start = System.nanoTime();
        double sum = r.doubles().limit(size).parallel().sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("D JUR par n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static double t6d(long size) {
        Random r = new Random();
        long start = System.nanoTime();
        double sum = r.doubles().limit(size).sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("D JUR seq n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static int t1i(long size) {
        SplittableRandom r = new SplittableRandom();
        long start = System.nanoTime();
        int sum = r.ints(size).parallel().sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("I SR  par n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static int t3i(long size) {
        SplittableRandom r = new SplittableRandom();
        long start = System.nanoTime();
        int sum = r.ints(size).sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("I SR  seq n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static int t5i(long size) {
        Random r = new Random();
        long start = System.nanoTime();
        int sum = r.ints().limit(size).parallel().sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("I JUR par n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }

    static int t6i(long size) {
        Random r = new Random();
        long start = System.nanoTime();
        int sum = r.ints().limit(size).sum(); 
        long end = System.nanoTime();
        double ns = throughput(start, end, size);
        double es = elapsedTime(start, end);
        System.out.printf("I JUR seq n: %10d mops: %10.1f elapsed: %10.4f\n", size, ns, es);
        return sum;
    }
    


    static double opTime(long startTime, long endTime, long nops) {
        return (double)(endTime - startTime) / nops;
    }

    static double elapsedTime(long startTime, long endTime) {
        return (double)(endTime - startTime) / (1000L * 1000 * 1000);
    }

    static double throughput(long startTime, long endTime, long nops) {
        return (nops * 1000L) / (double)(endTime - startTime);
    }

}


