package math;


public abstract class Mat {

    public static void main(String args[]) {
        float f[][] = new float[3][3];
        for (int i = 0; i < f.length; i++)
            for (int j = 0; j < f[0].length; j++)
                f[i][j] = 1;
        Mat.normalize(f);
        //Mat.printKernel(f,"mean3");
    }

    public static void print(double a[][]) {
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++)
                System.out.print(a[i][j] + " ");
            System.out.println();
        }
    }

    public static void printStats(String title, float a[][]) {
        System.out.println(title);
        printStats(a);
    }

    public static void printStats(float a[][]) {
        float min = Float.MAX_VALUE;
        float max = Float.MIN_VALUE;
        float aBar = 0;


        double N = a.length * a[0].length;
        for (int x = 0; x < a.length; x++)
            for (int y = 0; y < a[0].length; y++) {
                aBar += a[x][y];

                min = Math.min(a[x][y], min);
                max = Math.max(a[x][y], max);
            }


        aBar /= N;

        System.out.println(
                " aBar=" + aBar +
                " a min=" + min +
                " a max=" + max +
                " a.length=" + a.length +
                " a[0].length=" + a[0].length);

    }

    public static void print(float a[][]) {
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++)
                System.out.print(a[i][j] + " ");
            System.out.println();
        }
    }

    public static double sum(double a[][]) {
        double s = 0.0;
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < a[i].length; j++)
                s += a[i][j];
        return s;
    }

    public static double sum(float a[][]) {
        double s = 0.0;
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < a[0].length; j++)
                s += a[i][j];
        return s;
    }

    public static double sum(short a[][]) {
        double s = 0.0;
        if (a == null) return 0;
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < a[0].length; j++)
                s += a[i][j];
        return s;
    }

    public static short clip(short i) {
        if (i < 0)
            return 0;

        if (i > 255)
            return 255;

        return i;
    }

    public static short[][] clip(short i[][]) {
        short i2[][] = new short[i.length][i[0].length];
        for (int x = 0; x < i2.length; x++)
            for (int y = 0; y < i2[0].length; y++)
                i2[x][y] = clip(i[x][y]);
        return i2;
    }

    public static void normalize(double a[][]) {
        scale(a, 1.0 / sum(a));
    }

    public static float[][] normalize(short a[][]) {
        return scale(a, (float) (1.0f / sum(a)));
    }

    public static void normalize(float a[][]) {
        scale(a, 1.0 / sum(a));
    }

    public static double average(double a[][]) {
        int n = a.length * a[0].length;
        return sum(a) / n;
    }

    public static double average(float a[][]) {
        int n = a.length * a[0].length;
        return sum(a) / n;
    }

    public static double average(short a[][]) {
        int n = a.length * a[0].length;
        return sum(a) / n;
    }

    public static void threshold(short a[][], short thresh) {
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < a[0].length; j++)
                if (a[i][j] < thresh)
                    a[i][j] = 0;
                else
                    a[i][j] = 255;
    }

    public static void threshold(short a[][]) {
        threshold(a, (short) average(a));
    }

    public static void printKernel(float k[][], String name) {
        float g;
        System.out.println(
                "\npublic void " + name + "(){\n"
                + "\tfloat k[][] = {");
        int w = k.length;
        int h = k[0].length;

        for (int y = 0; y < h; y++) {
            System.out.print("\t{");
            for (int x = 0; x < w - 1; x++) {
                g = k[x][y];
                if (g < 10)
                    System.out.print("  ");
                else if (g < 100) System.out.print(" ");
                System.out.print(g + "f, ");
            }
            String s = k[w - 1][y] + "f}";
            if (y < h - 1)
                s = s + ",";
            else
                s = s + "};";
            System.out.println(s);
        }

        //String s="\n\tconvolve(k);\n}";
        //s = "//sum="+sum(k)+s;

        //System.out.println(s);

    }

    public static void printArray(double k[][], String name) {
        double g;
        int w = k.length;
        int h = k[0].length;
        System.out.println("w=" + w + " h=" + h);
        System.out.println(
                name + "(){\n"
                + "\tfloat k[][] = {");

        for (int x = 0; x < w; x++) {
            System.out.print("{");
            for (int y = 0; y < h; y++) {
                g = k[x][y];
                if (g < 10)
                    System.out.print("  ");
                else if (g < 100) System.out.print(" ");
                System.out.print(g);
            }
            System.out.println("}");
        }

    }

    public static void printKernel(double k[][], String name) {
        double g;
        int w = k.length;
        int h = k[0].length;
        System.out.println("w=" + w + " h=" + h);
        System.out.println(
                "\npublic void " + name + "(){\n"
                + "\tfloat k[][] = {");

        for (int y = 0; y < h; y++) {
            System.out.print("\t{");
            for (int x = 0; x < w - 1; x++) {
                g = k[x][y];
                if (g < 10)
                    System.out.print("  ");
                else if (g < 100) System.out.print(" ");
                System.out.print(g + "f, ");
            }
            String s = " " + k[w - 1][y] + "f }";
            if (y < h - 1)
                s = s + ",";
            else
                s = s + "};";
            System.out.println(s);
        }

        String s = "\n\tconvolve(k);\n}";
        s = "//sum=" + sum(k) + s;

        System.out.println(s);

    }

    public static void printKernel(short k[][], String name) {
        int g;
        System.out.println(
                "\npublic void " + name + "(){\n"
                + "\tfloat s =(float)" + Mat.sum(k) + ";\n"
                + "\tfloat k[][] = {");
        int w = k.length;
        int h = k[0].length;

        for (int y = 0; y < h; y++) {
            System.out.print("\t{");
            for (int x = 0; x < w - 1; x++) {
                g = k[x][y];
                System.out.print(g + "/s,");
            }
            String s = k[w - 1][y] + "/s}";
            if (y < h - 1)
                s = s + ",";
            else
                s = s + "};";
            System.out.println(s);
        }

        String s = "\n\tconvolve(k);\n}";
        System.out.println(s);

    }

    public static float[][] scale(short a[][], float k) {
        if (a == null) return null;
        float f[][] = new float[a.length][a[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++)
                f[i][j] = k * a[i][j];
        }
        return f;

    }

    public static void scale(double a[][], double k) {
        System.out.println("scale(double a[][], double k)");
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++)
                a[i][j] *= k;
        }

    }

    public static void scale(float a[][], float k) {
//System.out.println("scale(float a[][], float k)");
//System.out.println("k="+k);
        if (a == null) return;
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++)
                a[i][j] = a[i][j] * k;
        }

    }

    public static void scale(float a[][], double k) {
//System.out.println("scale(float a[][], double k)");
//  System.out.println("k="+k);
        scale(a, (float) k);
    }

    public static float[][] shortToFloat(short a[][]) {
        int w = a.length;
        int h = a[0].length;
        float c[][] = new float[w][h];
        for (int i = 0; i < w; i++)
            for (int j = 0; j < h; j++)
                c[i][j] = a[i][j];
        return c;
    }

    public static short[][] copyArray(short a[][]) {
        int w = a.length;
        int h = a[0].length;
        short c[][] = new short[w][h];
        for (int i = 0; i < w; i++)
            for (int j = 0; j < h; j++)
                c[i][j] = a[i][j];
        return c;
    }

    public static double variance(int a[]) {
        double xBar = mean(a);
        double sum = 0;
        double dx = 0;
        for (int i = 0; i < a.length; i++) {
            dx = a[i] - xBar;
            sum += dx * dx;
        }
        return sum / a.length;
    }

    public static double mean(int a[]) {
        double sum = 0;
        for (int i = 0; i < a.length; i++)
            sum += a[i];
        return sum / a.length;
    }

    public static double coefficientOfVariation(int a[]) {
        double aBar = mean(a);
        double aBar2 = aBar * aBar;
        return Math.sqrt(variance(a) / aBar2);
    }

    public static void testVariance() {
        int a[] = {1, 2, 3, 5, 4, 3, 2, 5, 6, 7};
        System.out.println("The variance =" + variance(a));
    }

    public static void testCoefficientOfVariation() {
        int a[] = {0, 85, 87, 90, 100};
        System.out.println(
                "coefficientOfVariation({0,85,87,90,100}) ="
                + coefficientOfVariation(a));
        int b[] = {95, 85, 87, 90, 100};
        System.out.println(
                "The coefficientOfVariation({95,85,87,90,100}) ="
                + coefficientOfVariation(b));
    }

    public static boolean outlierHere(int a[]) {
        return (coefficientOfVariation(a) > .1);
    }

    public static void testOutlier() {
        int a[] = {0, 85, 87, 90, 100};
        int b[] = {95, 85, 87, 90, 100};
        System.out.println(
                "dog ate my homework ={0,85,87,90,100}"
                + outlierHere(a));
        System.out.println(
                "dog ate my homework ={95,85,87,90,100}"
                + outlierHere(b));
    }

    public static void quickSort(int a[], int lo0, int hi0) {
        // Based on the QuickSort method by
        // James Gosling from Sun's SortDemo applet

        int lo = lo0;
        int hi = hi0;
        int mid, t;

        if (hi0 > lo0) {
            mid = a[(lo0 + hi0) / 2];
            while (lo <= hi) {
                while ((lo < hi0) && (a[lo] < mid))
                    ++lo;
                while ((hi > lo0) && (a[hi] > mid))
                    --hi;
                if (lo <= hi) {
                    t = a[lo];
                    a[lo] = a[hi];
                    a[hi] = t;
                    ++lo;
                    --hi;
                }
            }
            if (lo0 < hi)
                quickSort(a, lo0, hi);
            if (lo < hi0)
                quickSort(a, lo, hi0);

        }
    }

    public static void swap(int x[], int a, int b) {
        int t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

    public static void quickSort(int a[]) {
        quickSort(a, 0, a.length - 1);
    }

    public static double mean(short a[][]) {
        double sum = 0;
        for (int x = 0; x < a.length; x++)
            for (int y = 0; y < a[0].length; y++) {
                sum += a[x][y];
            }
        return sum / (a.length * a[0].length);
    }

    public static double variance(short a[][]) {
        double xBar = mean(a);
        double sum = 0;
        double dx = 0;
        for (int x = 0; x < a.length; x++)
            for (int y = 0; y < a[0].length; y++) {
                dx = a[x][y] - xBar;
                sum += dx * dx;
            }
        return sum / (a.length * a[0].length);
    }

    public static double[] getAverage(
            double a[], double b[], double c[]) {
        double avg[] = new double[a.length];

        for (int i = 0; i < a.length; i++) {
            avg[i] = (a[i] + b[i] + c[i]) / 3.0;
        }
        return avg;
    }

}