// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.pqc.crypto.hqc;

class FastFourierTransform
{
    static void fastFourierTransform(final int[] array, final int[] array2, final int n, final int n2) {
        final int n3 = 8;
        final int n4 = 128;
        final int n5 = 1 << n2;
        final int[] array3 = new int[n5];
        final int[] array4 = new int[n5];
        final int[] array5 = new int[n3 - 1];
        final int[] array6 = new int[n4];
        final int[] array7 = new int[n4];
        final int[] array8 = new int[n3 - 1];
        final int[] array9 = new int[n4];
        computeFFTBetas(array8, n3);
        computeSubsetSum(array9, array8, n3 - 1);
        computeRadix(array3, array4, array2, n2, n2);
        for (int i = 0; i < n3 - 1; ++i) {
            array5[i] = (GFCalculator.mult(array8[i], array8[i]) ^ array8[i]);
        }
        computeFFTRec(array6, array3, (n + 1) / 2, n3 - 1, n2 - 1, array5, n2, n3);
        computeFFTRec(array7, array4, n / 2, n3 - 1, n2 - 1, array5, n2, n3);
        final int n6 = 1 << n3 - 1;
        System.arraycopy(array7, 0, array, n6, n6);
        array[0] = array6[0];
        final int n7 = n6;
        array[n7] ^= array6[0];
        for (int j = 1; j < n6; ++j) {
            array[j] = (array6[j] ^ GFCalculator.mult(array9[j], array7[j]));
            final int n8 = n6 + j;
            array[n8] ^= array[j];
        }
    }
    
    static void computeFFTBetas(final int[] array, final int n) {
        for (int i = 0; i < n - 1; ++i) {
            array[i] = 1 << n - 1 - i;
        }
    }
    
    static void computeSubsetSum(final int[] array, final int[] array2, final int n) {
        array[0] = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < 1 << i; ++j) {
                array[(1 << i) + j] = (array2[i] ^ array[j]);
            }
        }
    }
    
    static void computeRadix(final int[] array, final int[] array2, final int[] array3, final int n, final int n2) {
        switch (n) {
            case 4: {
                array[4] = (array3[8] ^ array3[12]);
                array[6] = (array3[12] ^ array3[14]);
                array[7] = (array3[14] ^ array3[15]);
                array2[5] = (array3[11] ^ array3[13]);
                array2[6] = (array3[13] ^ array3[14]);
                array2[7] = array3[15];
                array[5] = (array3[10] ^ array3[12] ^ array2[5]);
                array2[4] = (array3[9] ^ array3[13] ^ array[5]);
                array[0] = array3[0];
                array2[3] = (array3[7] ^ array3[11] ^ array3[15]);
                array[3] = (array3[6] ^ array3[10] ^ array3[14] ^ array2[3]);
                array[2] = (array3[4] ^ array[4] ^ array[3] ^ array2[3]);
                array2[1] = (array3[3] ^ array3[5] ^ array3[9] ^ array3[13] ^ array2[3]);
                array2[2] = (array3[3] ^ array2[1] ^ array[3]);
                array[1] = (array3[2] ^ array[2] ^ array2[1]);
                array2[0] = (array3[1] ^ array[1]);
                return;
            }
            case 3: {
                array[0] = array3[0];
                array[2] = (array3[4] ^ array3[6]);
                array[3] = (array3[6] ^ array3[7]);
                array2[1] = (array3[3] ^ array3[5] ^ array3[7]);
                array2[2] = (array3[5] ^ array3[6]);
                array2[3] = array3[7];
                array[1] = (array3[2] ^ array[2] ^ array2[1]);
                array2[0] = (array3[1] ^ array[1]);
                return;
            }
            case 2: {
                array[0] = array3[0];
                array[1] = (array3[2] ^ array3[3]);
                array2[0] = (array3[1] ^ array[1]);
                array2[1] = array3[3];
                return;
            }
            case 1: {
                array[0] = array3[0];
                array2[0] = array3[1];
                return;
            }
            default: {
                computeRadixBig(array, array2, array3, n, n2);
            }
        }
    }
    
    static void computeRadixBig(final int[] array, final int[] array2, final int[] array3, final int n, final int n2) {
        final int n3 = 1 << n - 2;
        final int n4 = 1 << n2 - 2;
        final int[] array4 = new int[2 * n4 + 1];
        final int[] array5 = new int[2 * n4 + 1];
        final int[] array6 = new int[n4];
        final int[] array7 = new int[n4];
        final int[] array8 = new int[n4];
        final int[] array9 = new int[n4];
        Utils.copyBytes(array3, 3 * n3, array4, 0, 2 * n3);
        Utils.copyBytes(array3, 3 * n3, array4, n3, 2 * n3);
        Utils.copyBytes(array3, 0, array5, 0, 4 * n3);
        for (int i = 0; i < n3; ++i) {
            final int[] array10 = array4;
            final int n5 = i;
            array10[n5] ^= array3[2 * n3 + i];
            final int[] array11 = array5;
            final int n6 = n3 + i;
            array11[n6] ^= array4[i];
        }
        computeRadix(array6, array7, array4, n - 1, n2);
        computeRadix(array8, array9, array5, n - 1, n2);
        Utils.copyBytes(array8, 0, array, 0, 2 * n3);
        Utils.copyBytes(array6, 0, array, n3, 2 * n3);
        Utils.copyBytes(array9, 0, array2, 0, 2 * n3);
        Utils.copyBytes(array7, 0, array2, n3, 2 * n3);
    }
    
    static void computeFFTRec(final int[] array, final int[] array2, final int n, final int n2, final int n3, final int[] array3, final int n4, final int n5) {
        final int n6 = 1 << n4 - 2;
        final int n7 = 1 << n5 - 2;
        final int[] array4 = new int[n6];
        final int[] array5 = new int[n6];
        final int[] array6 = new int[n5 - 2];
        final int[] array7 = new int[n5 - 2];
        final int[] array8 = new int[n7];
        final int[] array9 = new int[n7];
        final int[] array10 = new int[n7];
        final int[] array11 = new int[n5 - n4 + 1];
        if (n3 == 1) {
            for (int i = 0; i < n2; ++i) {
                array11[i] = GFCalculator.mult(array3[i], array2[1]);
            }
            array[0] = array2[0];
            int n8 = 1;
            for (int j = 0; j < n2; ++j) {
                for (int k = 0; k < n8; ++k) {
                    array[n8 + k] = (array[k] ^ array11[j]);
                }
                n8 <<= 1;
            }
            return;
        }
        if (array3[n2 - 1] != 1) {
            int mult = 1;
            for (int n9 = 1 << n3, l = 1; l < n9; ++l) {
                mult = GFCalculator.mult(mult, array3[n2 - 1]);
                array2[l] = GFCalculator.mult(mult, array2[l]);
            }
        }
        computeRadix(array4, array5, array2, n3, n4);
        for (int n10 = 0; n10 < n2 - 1; ++n10) {
            array6[n10] = GFCalculator.mult(array3[n10], GFCalculator.inverse(array3[n2 - 1]));
            array7[n10] = (GFCalculator.mult(array6[n10], array6[n10]) ^ array6[n10]);
        }
        computeSubsetSum(array8, array6, n2 - 1);
        computeFFTRec(array9, array4, (n + 1) / 2, n2 - 1, n3 - 1, array7, n4, n5);
        final int n11 = 1 << (n2 - 1 & 0xF);
        if (n <= 3) {
            array[0] = array9[0];
            array[n11] = (array9[0] ^ array5[0]);
            for (int n12 = 1; n12 < n11; ++n12) {
                array[n12] = (array9[n12] ^ GFCalculator.mult(array8[n12], array5[0]));
                array[n11 + n12] = (array[n12] ^ array5[0]);
            }
        }
        else {
            computeFFTRec(array10, array5, n / 2, n2 - 1, n3 - 1, array7, n4, n5);
            System.arraycopy(array10, 0, array, n11, n11);
            array[0] = array9[0];
            final int n13 = n11;
            array[n13] ^= array9[0];
            for (int n14 = 1; n14 < n11; ++n14) {
                array[n14] = (array9[n14] ^ GFCalculator.mult(array8[n14], array10[n14]));
                final int n15 = n11 + n14;
                array[n15] ^= array[n14];
            }
        }
    }
    
    static void fastFourierTransformGetError(final byte[] array, final int[] array2, final int n, final int[] array3) {
        final int n2 = 8;
        final int n3 = 255;
        final int[] array4 = new int[n2 - 1];
        final int[] array5 = new int[n];
        computeFFTBetas(array4, n2);
        computeSubsetSum(array5, array4, n2 - 1);
        final int n4 = 0;
        array[n4] ^= (byte)(0x1 ^ Utils.toUnsigned16Bits(-array2[0] >> 15));
        final int n5 = 0;
        array[n5] ^= (byte)(0x1 ^ Utils.toUnsigned16Bits(-array2[n] >> 15));
        for (int i = 1; i < n; ++i) {
            final int n6 = n3 - array3[array5[i]];
            array[n6] ^= (byte)(0x1 ^ Math.abs(-array2[i] >> 15));
            final int n7 = n3 - array3[array5[i] ^ 0x1];
            array[n7] ^= (byte)(0x1 ^ Math.abs(-array2[n + i] >> 15));
        }
    }
}
