/*
 * 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.concurrent.*;
import java.util.*;

class DSAS {
    static final long NPS = (1000L * 1000 * 1000);

    public static void main(String[] args) throws Exception {
        int n = 100000000;
        int reps = 30;
        int sreps = 2;
        try {
            if (args.length > 0)
                n = Integer.parseInt(args[0]);
            if (args.length > 1)
                reps = Integer.parseInt(args[1]);
        }
        catch (Exception e) {
            System.out.println("Usage: java ScalarArraysSort n reps");
            return;
        }

       
        double[] a = new double[n];
        ForkJoinPool pool = ForkJoinPool.commonPool();
        seqTest(a, n, 1);
        System.out.println(pool);
        parTest(a, n, reps);
        System.out.println(pool);
        seqTest(a, n, 2);
        System.out.println(pool);
    }

    static void seqTest(double[] a, int n, int reps) {
        System.out.printf("Sorting %d doubles, %d replications\n", n, reps);
        long start = System.nanoTime();
        for (int i = 0; i < reps; ++i) {
            fill(a);
            long last = System.nanoTime();
            java.util.Arrays.sort(a);
            long now = System.nanoTime();
            double total = (double)(now - start) / NPS;
            double elapsed = (double)(now - last) / NPS;
            System.out.printf("Arrays.sort   time:  %7.3f total %9.3f\n",
                              elapsed, total);
        }
        checkSorted(a);
    }

    static void parTest(double[] a, int n, int reps) throws Exception {
        System.out.printf("Sorting %d doubles, %d replications\n", n, reps);
        long start = System.nanoTime();
        for (int i = 0; i < reps; ++i) {
            fill(a);
            long last = System.nanoTime();
            java.util.Arrays.parallelSort(a);
            long now = System.nanoTime();
            double total = (double)(now - start) / NPS;
            double elapsed = (double)(now - last) / NPS;
            System.out.printf("Parallel sort time:  %7.3f total %9.3f\n",
                              elapsed, total);
        }
        checkSorted(a);
    }

    // generates a int hash from an int value 
    static int hash(int i) {
        long v = (long)i * 3935559000370003845L + 2691343689449507681L;
        v = v ^ (v >>> 21);
        v = v ^ (v << 37);
        v = v ^ (v >>> 4);
        v = v * 4768777513237032717L;
        v = v ^ (v << 20);
        v = v ^ (v >>> 41);
        v = v ^ (v <<  5);
        return (int) (v & ((1L << 31) - 1L));
    }
    
    static void fill(double[] a) {
        for (int i = 0; i < a.length; ++i)
            a[i] = (double)hash(i);
    }
    
    static void checkSorted(double[] a) {
        int n = a.length;
        double x = a[0], y;
        for (int i = 0; i < n - 1; i++) {
            if (x > (y = a[i+1]))
                throw new Error("Unsorted at " + i + ": " + x + " / " + y);
            x = y;
        }
    }
    

}
