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

package org.bouncycastle.pqc.crypto.falcon;

import org.bouncycastle.util.Pack;
import org.bouncycastle.crypto.digests.SHAKEDigest;

class FalconRNG
{
    byte[] bd;
    int ptr;
    byte[] sd;
    
    FalconRNG() {
        this.bd = new byte[512];
        this.ptr = 0;
        this.sd = new byte[256];
    }
    
    void prng_init(final SHAKEDigest shakeDigest) {
        shakeDigest.doOutput(this.sd, 0, 56);
        this.prng_refill();
    }
    
    void prng_refill() {
        final int[] array = { 1634760805, 857760878, 2036477234, 1797285236 };
        long littleEndianToLong = Pack.littleEndianToLong(this.sd, 48);
        final int[] array2 = new int[16];
        for (int i = 0; i < 8; ++i) {
            System.arraycopy(array, 0, array2, 0, array.length);
            Pack.littleEndianToInt(this.sd, 0, array2, 4, 12);
            final int[] array3 = array2;
            final int n = 14;
            array3[n] ^= (int)littleEndianToLong;
            final int[] array4 = array2;
            final int n2 = 15;
            array4[n2] ^= (int)(littleEndianToLong >>> 32);
            for (int j = 0; j < 10; ++j) {
                this.QROUND(0, 4, 8, 12, array2);
                this.QROUND(1, 5, 9, 13, array2);
                this.QROUND(2, 6, 10, 14, array2);
                this.QROUND(3, 7, 11, 15, array2);
                this.QROUND(0, 5, 10, 15, array2);
                this.QROUND(1, 6, 11, 12, array2);
                this.QROUND(2, 7, 8, 13, array2);
                this.QROUND(3, 4, 9, 14, array2);
            }
            for (int k = 0; k < 4; ++k) {
                final int[] array5 = array2;
                final int n3 = k;
                array5[n3] += array[k];
            }
            for (int l = 4; l < 14; ++l) {
                final int[] array6 = array2;
                final int n4 = l;
                array6[n4] += Pack.littleEndianToInt(this.sd, 4 * l - 16);
            }
            final int[] array7 = array2;
            final int n5 = 14;
            array7[n5] += (Pack.littleEndianToInt(this.sd, 40) ^ (int)littleEndianToLong);
            final int[] array8 = array2;
            final int n6 = 15;
            array8[n6] += (Pack.littleEndianToInt(this.sd, 44) ^ (int)(littleEndianToLong >>> 32));
            ++littleEndianToLong;
            for (int n7 = 0; n7 < 16; ++n7) {
                Pack.intToLittleEndian(array2[n7], this.bd, (i << 2) + (n7 << 5));
            }
        }
        Pack.longToLittleEndian(littleEndianToLong, this.sd, 48);
        this.ptr = 0;
    }
    
    private void QROUND(final int n, final int n2, final int n3, final int n4, final int[] array) {
        array[n] += array[n2];
        array[n4] ^= array[n];
        array[n4] = (array[n4] << 16 | array[n4] >>> 16);
        array[n3] += array[n4];
        array[n2] ^= array[n3];
        array[n2] = (array[n2] << 12 | array[n2] >>> 20);
        array[n] += array[n2];
        array[n4] ^= array[n];
        array[n4] = (array[n4] << 8 | array[n4] >>> 24);
        array[n3] += array[n4];
        array[n2] ^= array[n3];
        array[n2] = (array[n2] << 7 | array[n2] >>> 25);
    }
    
    long prng_get_u64() {
        int ptr = this.ptr;
        if (ptr >= this.bd.length - 9) {
            this.prng_refill();
            ptr = 0;
        }
        this.ptr = ptr + 8;
        return Pack.littleEndianToLong(this.bd, ptr);
    }
    
    byte prng_get_u8() {
        final byte b = this.bd[this.ptr++];
        if (this.ptr == this.bd.length) {
            this.prng_refill();
        }
        return b;
    }
}
