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

package org.bouncycastle.pqc.crypto.hqc;

import org.bouncycastle.util.Arrays;

class GF2PolynomialCalculator
{
    private final int VEC_N_SIZE_64;
    private final int PARAM_N;
    private final long RED_MASK;
    
    GF2PolynomialCalculator(final int vec_N_SIZE_64, final int param_N, final long red_MASK) {
        this.VEC_N_SIZE_64 = vec_N_SIZE_64;
        this.PARAM_N = param_N;
        this.RED_MASK = red_MASK;
    }
    
    public void vectMul(final long[] array, final long[] array2, final long[] array3) {
        final long[] array4 = new long[this.VEC_N_SIZE_64 << 1];
        this.karatsuba(array4, 0, array2, 0, array3, 0, this.VEC_N_SIZE_64, new long[this.VEC_N_SIZE_64 << 4], 0);
        this.reduce(array, array4);
    }
    
    private void schoolbookMul(final long[] array, int n, final long[] array2, final int n2, final long[] array3, final int n3, final int n4) {
        Arrays.fill(array, n, n + (n4 << 1), 0L);
        for (int i = 0; i < n4; ++i, ++n) {
            final long n5 = array2[i + n2];
            for (int j = 0; j < 64; ++j) {
                final long n6 = -(n5 >> j & 0x1L);
                if (j == 0) {
                    for (int k = 0, n7 = n, n8 = n3; k < n4; ++k, ++n7, ++n8) {
                        final int n9 = n7;
                        array[n9] ^= (array3[n8] & n6);
                    }
                }
                else {
                    final int n10 = 64 - j;
                    int l = 0;
                    int n11 = n;
                    for (int n12 = n3; l < n4; ++l, ++n12) {
                        final int n13 = n11++;
                        array[n13] ^= (array3[n12] << j & n6);
                        final int n14 = n11;
                        array[n14] ^= (array3[n12] >>> n10 & n6);
                    }
                }
            }
        }
    }
    
    private void karatsuba(final long[] array, final int n, final long[] array2, final int n2, final long[] array3, final int n3, final int n4, final long[] array4, final int n5) {
        if (n4 <= 16) {
            this.schoolbookMul(array, n, array2, n2, array3, n3, n4);
            return;
        }
        final int n6 = n4 >> 1;
        final int n7 = n4 - n6;
        final int n8 = n4 << 1;
        final int n9 = n6 << 1;
        final int n10 = n7 << 1;
        final int n11 = n5 + n8;
        final int n12 = n11 + n8;
        final int n13 = n12 + n8;
        final int n14 = n13 + n4;
        final int n15 = n5 + (n4 << 3);
        this.karatsuba(array4, n5, array2, n2, array3, n3, n6, array4, n15);
        this.karatsuba(array4, n11, array2, n2 + n6, array3, n3 + n6, n7, array4, n15);
        for (int i = 0; i < n7; ++i) {
            final long n16 = (i < n6) ? array2[n2 + i] : 0L;
            final long n17 = (i < n6) ? array3[n3 + i] : 0L;
            array4[n13 + i] = (n16 ^ array2[n2 + n6 + i]);
            array4[n14 + i] = (n17 ^ array3[n3 + n6 + i]);
        }
        this.karatsuba(array4, n12, array4, n13, array4, n14, n7, array4, n15);
        System.arraycopy(array4, n5, array, n, n9);
        System.arraycopy(array4, n11, array, n + n9, n10);
        for (int j = 0; j < 2 * n7; ++j) {
            final long n18 = (j < n9) ? array4[n5 + j] : 0L;
            final long n19 = (j < n10) ? array4[n11 + j] : 0L;
            final int n20 = n + n6 + j;
            array[n20] ^= (array4[n12 + j] ^ n18 ^ n19);
        }
    }
    
    private void reduce(final long[] array, final long[] array2) {
        for (int i = 0; i < this.VEC_N_SIZE_64; ++i) {
            array[i] = (array2[i] ^ array2[i + this.VEC_N_SIZE_64 - 1] >>> (this.PARAM_N & 0x3F) ^ array2[i + this.VEC_N_SIZE_64] << (int)(64L - ((long)this.PARAM_N & 0x3FL)));
        }
        final int n = this.VEC_N_SIZE_64 - 1;
        array[n] &= this.RED_MASK;
    }
}
