void init(int n) {
        bitrev = new int[n / 4];
        trig = new float[n + n / 4];

        log2n = (int) Math.rint(Math.log(n) / Math.log(2));
        this.n = n;

        int AE = 0;
        int AO = 1;
        int BE = AE + n / 2;
        int BO = BE + 1;
        int CE = BE + n / 2;
        int CO = CE + 1;
        // trig lookups...
        for (int i = 0; i < n / 4; i++) {
            trig[AE + i * 2] = (float) Math.cos((Math.PI / n) * (4 * i));
            trig[AO + i * 2] = (float) -Math.sin((Math.PI / n) * (4 * i));
            trig[BE + i * 2] = (float) Math.cos((Math.PI / (2 * n)) * (2 * i + 1));
            trig[BO + i * 2] = (float) Math.sin((Math.PI / (2 * n)) * (2 * i + 1));
        }
        for (int i = 0; i < n / 8; i++) {
            trig[CE + i * 2] = (float) Math.cos((Math.PI / n) * (4 * i + 2));
            trig[CO + i * 2] = (float) -Math.sin((Math.PI / n) * (4 * i + 2));
        }

        {
            int mask = (1 << (log2n - 1)) - 1;
            int msb = 1 << (log2n - 2);
            for (int i = 0; i < n / 8; i++) {
                int acc = 0;
                for (int j = 0; msb >>> j != 0; j++) {
                    if (((msb >>> j) & i) != 0) {
                        acc |= 1 << j;
                    }
                }
                bitrev[i * 2] = ((~acc) & mask);
                //	bitrev[i*2]=((~acc)&mask)-1;
                bitrev[i * 2 + 1] = acc;
            }
        }
        scale = 4.f / n;
    }