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

package org.bouncycastle.pqc.crypto.ntru;

import org.bouncycastle.pqc.math.ntru.HRSSPolynomial;
import org.bouncycastle.pqc.math.ntru.HPSPolynomial;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUHPSParameterSet;
import org.bouncycastle.pqc.math.ntru.Polynomial;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUHRSSParameterSet;
import org.bouncycastle.pqc.math.ntru.parameters.NTRUParameterSet;

class NTRUSampling
{
    private final NTRUParameterSet params;
    
    public NTRUSampling(final NTRUParameterSet params) {
        this.params = params;
    }
    
    public PolynomialPair sampleFg(final byte[] array) {
        if (this.params instanceof NTRUHRSSParameterSet) {
            return new PolynomialPair(this.sampleIidPlus(Arrays.copyOfRange(array, 0, this.params.sampleIidBytes())), this.sampleIidPlus(Arrays.copyOfRange(array, this.params.sampleIidBytes(), array.length)));
        }
        if (this.params instanceof NTRUHPSParameterSet) {
            return new PolynomialPair(this.sampleIid(Arrays.copyOfRange(array, 0, this.params.sampleIidBytes())), this.sampleFixedType(Arrays.copyOfRange(array, this.params.sampleIidBytes(), array.length)));
        }
        throw new IllegalArgumentException("Invalid polynomial type");
    }
    
    public PolynomialPair sampleRm(final byte[] array) {
        if (this.params instanceof NTRUHRSSParameterSet) {
            return new PolynomialPair(this.sampleIid(Arrays.copyOfRange(array, 0, this.params.sampleIidBytes())), this.sampleIid(Arrays.copyOfRange(array, this.params.sampleIidBytes(), array.length)));
        }
        if (this.params instanceof NTRUHPSParameterSet) {
            return new PolynomialPair(this.sampleIid(Arrays.copyOfRange(array, 0, this.params.sampleIidBytes())), this.sampleFixedType(Arrays.copyOfRange(array, this.params.sampleIidBytes(), array.length)));
        }
        throw new IllegalArgumentException("Invalid polynomial type");
    }
    
    public Polynomial sampleIid(final byte[] array) {
        final Polynomial polynomial = this.params.createPolynomial();
        for (int i = 0; i < this.params.n() - 1; ++i) {
            polynomial.coeffs[i] = (short)mod3(array[i] & 0xFF);
        }
        polynomial.coeffs[this.params.n() - 1] = 0;
        return polynomial;
    }
    
    public HPSPolynomial sampleFixedType(final byte[] array) {
        final int n = this.params.n();
        final int weight = ((NTRUHPSParameterSet)this.params).weight();
        final HPSPolynomial hpsPolynomial = new HPSPolynomial((NTRUHPSParameterSet)this.params);
        final int[] a = new int[n - 1];
        for (int i = 0; i < (n - 1) / 4; ++i) {
            a[4 * i + 0] = ((array[15 * i + 0] & 0xFF) << 2) + ((array[15 * i + 1] & 0xFF) << 10) + ((array[15 * i + 2] & 0xFF) << 18) + ((array[15 * i + 3] & 0xFF) << 26);
            a[4 * i + 1] = ((array[15 + i * 3] & 0xFF & 0xC0) >> 4) + ((array[15 * i + 4] & 0xFF) << 4) + ((array[15 * i + 5] & 0xFF) << 12) + ((array[15 * i + 6] & 0xFF) << 20) + ((array[15 * i + 7] & 0xFF) << 28);
            a[4 * i + 2] = ((array[15 + i * 7] & 0xFF & 0xF0) >> 2) + ((array[15 * i + 8] & 0xFF) << 6) + ((array[15 * i + 9] & 0xFF) << 14) + ((array[15 * i + 10] & 0xFF) << 22) + ((array[15 * i + 11] & 0xFF) << 30);
            a[4 * i + 3] = (array[15 * i + 11] & 0xFF & 0xFC) + ((array[15 * i + 12] & 0xFF) << 8) + ((array[15 * i + 13] & 0xFF) << 16) + ((array[15 * i + 14] & 0xFF) << 24);
        }
        if (n - 1 > (n - 1) / 4 * 4) {
            final int n2 = (n - 1) / 4;
            a[4 * n2 + 0] = ((array[15 * n2 + 0] & 0xFF) << 2) + ((array[15 * n2 + 1] & 0xFF) << 10) + ((array[15 * n2 + 2] & 0xFF) << 18) + ((array[15 * n2 + 3] & 0xFF) << 26);
            a[4 * n2 + 1] = ((array[15 + n2 * 3] & 0xFF & 0xC0) >> 4) + ((array[15 * n2 + 4] & 0xFF) << 4) + ((array[15 * n2 + 5] & 0xFF) << 12) + ((array[15 * n2 + 6] & 0xFF) << 20) + ((array[15 * n2 + 7] & 0xFF) << 28);
        }
        for (int j = 0; j < weight / 2; ++j) {
            final int[] array2 = a;
            final int n3 = j;
            array2[n3] |= 0x1;
        }
        for (int k = weight / 2; k < weight; ++k) {
            final int[] array3 = a;
            final int n4 = k;
            array3[n4] |= 0x2;
        }
        java.util.Arrays.sort(a);
        for (int l = 0; l < n - 1; ++l) {
            hpsPolynomial.coeffs[l] = (short)(a[l] & 0x3);
        }
        hpsPolynomial.coeffs[n - 1] = 0;
        return hpsPolynomial;
    }
    
    public HRSSPolynomial sampleIidPlus(final byte[] array) {
        final int n = this.params.n();
        short n2 = 0;
        final HRSSPolynomial hrssPolynomial = (HRSSPolynomial)this.sampleIid(array);
        for (int i = 0; i < n - 1; ++i) {
            hrssPolynomial.coeffs[i] |= (short)(-(hrssPolynomial.coeffs[i] >>> 1));
        }
        for (int j = 0; j < n - 1; ++j) {
            n2 += (short)(hrssPolynomial.coeffs[j + 1] * hrssPolynomial.coeffs[j]);
        }
        final short n3 = (short)(0x1 | -((n2 & 0xFFFF) >>> 15));
        for (int k = 0; k < n - 1; k += 2) {
            hrssPolynomial.coeffs[k] *= n3;
        }
        for (int l = 0; l < n - 1; ++l) {
            hrssPolynomial.coeffs[l] = (short)(0x3 & ((hrssPolynomial.coeffs[l] & 0xFFFF) ^ (hrssPolynomial.coeffs[l] & 0xFFFF) >>> 15));
        }
        return hrssPolynomial;
    }
    
    private static int mod3(final int n) {
        return n % 3;
    }
}
