import java.util.Random;

public class MathPowTest {

    final private static int RESULTS_SIZE = 1000;
    final private static double denominator = 1000;
    final private static double TO_MILLIS = 1000*1000;
    private static double x = 1;
    private static double y = 1;
    private static double[][] results;

    private static double[] computeRowStrict(double x, double y) {
        double[] result = new double[RESULTS_SIZE];
        for (int i = 0; i < RESULTS_SIZE; i++) {
            double newY;
            newY = y + i;
            result[i] = StrictMath.pow(x, newY);
        }
        return result;
    }

    private static double[] computeRow(double x, double y) {
        double[] result = new double[RESULTS_SIZE];
        for (int i = 0; i < RESULTS_SIZE; i++) {
            double newY;
            newY = y + i;
            result[i] = Math.pow(x, newY);
        }
        return result;
    }

    private static double[][] computeTable() {
        for (int i = 0; i < RESULTS_SIZE; i++) {
            double newX = (x+i)/denominator;
            results[i] = computeRow(newX,y);
        }
        return results;
    }

    private static double[][] computeTableStrict() {
        for (int i = 0; i < RESULTS_SIZE; i++) {
            double newX = (x+i)/denominator;
            results[i] = computeRowStrict(newX,y);
        }
        return results;
    }

    public static void main(String[] args) {
        results = new double[RESULTS_SIZE][RESULTS_SIZE];
        
        // warmup
        long end, start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();

        Random r = new Random();
        int i = r.nextInt(RESULTS_SIZE);
        int j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        long elapsedTime = end - start;
        System.out.println("      Warmup time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        elapsedTime = end - start;
        System.out.println("Strict warmup time: " + elapsedTime/TO_MILLIS + " millis");
        
        
        // first run
        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      1st run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 1st run time: " + elapsedTime/TO_MILLIS + " millis");

        // second run
        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      2nd run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 2nd run time: " + elapsedTime/TO_MILLIS + " millis");

        // third run
        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      3rd run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 3rd run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      4th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 4th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      5th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 5th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      6th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 6th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      7th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 7th run time: " + elapsedTime/TO_MILLIS + " millis");

        // third run
        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      8th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 8th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      9th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 9th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      10th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 10th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTable();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("      11th run time: " + elapsedTime/TO_MILLIS + " millis");

        start = System.nanoTime();
        results = computeTableStrict();
        end = System.nanoTime();
        elapsedTime = end - start;
        i = r.nextInt(RESULTS_SIZE);
        j = r.nextInt(RESULTS_SIZE);
        System.out.println("Value at [" + i + "][" + j + "] = " + results[i][j]);
        System.out.println("Strict 11th run time: " + elapsedTime/TO_MILLIS + " millis");
    }
}
