/*
 * 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 DPS {
    static final class DoublePair implements Comparable<DoublePair> {
        public double fst;
        public double snd;
        public final int compareTo(DoublePair p) {
            double y = p.fst, x = fst;
            return (x < y) ? -1 : (x > y) ? 1 : 0;
        }
    }

    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 ArraysSort n reps");
            return;
        }

        DoublePair[] a = new DoublePair[n];
        for (int i = 0; i < n; ++i)
            a[i] = new DoublePair();

        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(DoublePair[] a, int n, int reps) {
        System.out.printf("Sorting %d pairs, %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(DoublePair[] a, int n, int reps) throws Exception {
        System.out.printf("Sorting %d pairs, %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(DoublePair[] a) {
        for (int i = 0; i < a.length; ++i)
            a[i].fst = (double)hash(i);
    }
    
    static void checkSorted(DoublePair[] a) {
        int n = a.length;
        double x = a[0].fst, y;
        for (int i = 0; i < n - 1; i++) {
            if (x > (y = a[i+1].fst))
                throw new Error("Unsorted at " + i + ": " + x + " / " + y);
            x = y;
        }
    }
}

