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

package org.bouncycastle.pqc.crypto.rainbow;

class ComputeInField
{
    public ComputeInField() {
    }
    
    public short[] solveEquation(final short[][] array, final short[] array2) {
        if (array.length != array2.length) {
            return null;
        }
        try {
            final short[][] array3 = new short[array.length][array.length + 1];
            final short[] array4 = new short[array.length];
            for (int i = 0; i < array.length; ++i) {
                System.arraycopy(array[i], 0, array3[i], 0, array[0].length);
                array3[i][array2.length] = GF2Field.addElem(array2[i], array3[i][array2.length]);
            }
            this.gaussElim(array3);
            for (int j = 0; j < array3.length; ++j) {
                array4[j] = array3[j][array2.length];
            }
            return array4;
        }
        catch (final RuntimeException ex) {
            return null;
        }
    }
    
    public short[][] inverse(final short[][] array) {
        if (array.length != array[0].length) {
            throw new RuntimeException("The matrix is not invertible. Please choose another one!");
        }
        try {
            final short[][] array2 = new short[array.length][2 * array.length];
            for (int i = 0; i < array.length; ++i) {
                System.arraycopy(array[i], 0, array2[i], 0, array.length);
                for (int j = array.length; j < 2 * array.length; ++j) {
                    array2[i][j] = 0;
                }
                array2[i][i + array2.length] = 1;
            }
            this.gaussElim(array2);
            final short[][] array3 = new short[array2.length][array2.length];
            for (int k = 0; k < array2.length; ++k) {
                for (int l = array2.length; l < 2 * array2.length; ++l) {
                    array3[k][l - array2.length] = array2[k][l];
                }
            }
            return array3;
        }
        catch (final RuntimeException ex) {
            return null;
        }
    }
    
    private void gaussElim(final short[][] array) {
        for (int i = 0; i < array.length; ++i) {
            for (int j = i + 1; j < array.length; ++j) {
                if (array[i][i] == 0) {
                    for (int k = i; k < array[0].length; ++k) {
                        array[i][k] = GF2Field.addElem(array[i][k], array[j][k]);
                    }
                }
            }
            final short invElem = GF2Field.invElem(array[i][i]);
            if (invElem == 0) {
                throw new RuntimeException("The matrix is not invertible");
            }
            array[i] = this.multVect(invElem, array[i]);
            for (int l = 0; l < array.length; ++l) {
                if (i != l) {
                    final short n = array[l][i];
                    for (int n2 = i; n2 < array[0].length; ++n2) {
                        array[l][n2] = GF2Field.addElem(array[l][n2], GF2Field.multElem(array[i][n2], n));
                    }
                }
            }
        }
    }
    
    public short[][] multiplyMatrix(final short[][] array, final short[][] array2) throws RuntimeException {
        if (array[0].length != array2.length) {
            throw new RuntimeException("Multiplication is not possible!");
        }
        final short[][] array3 = new short[array.length][array2[0].length];
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array2.length; ++j) {
                for (int k = 0; k < array2[0].length; ++k) {
                    array3[i][k] = GF2Field.addElem(array3[i][k], GF2Field.multElem(array[i][j], array2[j][k]));
                }
            }
        }
        return array3;
    }
    
    public short[] multiplyMatrix(final short[][] array, final short[] array2) throws RuntimeException {
        if (array[0].length != array2.length) {
            throw new RuntimeException("Multiplication is not possible!");
        }
        final short[] array3 = new short[array.length];
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array2.length; ++j) {
                array3[i] = GF2Field.addElem(array3[i], GF2Field.multElem(array[i][j], array2[j]));
            }
        }
        return array3;
    }
    
    public short multiplyMatrix_quad(final short[][] array, final short[] array2) throws RuntimeException {
        if (array.length != array[0].length || array[0].length != array2.length) {
            throw new RuntimeException("Multiplication is not possible!");
        }
        final short[] array3 = new short[array.length];
        short addElem = 0;
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array2.length; ++j) {
                array3[i] = GF2Field.addElem(array3[i], GF2Field.multElem(array[i][j], array2[j]));
            }
            addElem = GF2Field.addElem(addElem, GF2Field.multElem(array3[i], array2[i]));
        }
        return addElem;
    }
    
    public short[] addVect(final short[] array, final short[] array2) {
        if (array.length != array2.length) {
            throw new RuntimeException("Addition is not possible! vector1.length: " + array.length + " vector2.length: " + array2.length);
        }
        final short[] array3 = new short[array.length];
        for (int i = 0; i < array3.length; ++i) {
            array3[i] = GF2Field.addElem(array[i], array2[i]);
        }
        return array3;
    }
    
    public short[][] multVects(final short[] array, final short[] array2) {
        if (array.length != array2.length) {
            throw new RuntimeException("Multiplication is not possible!");
        }
        final short[][] array3 = new short[array.length][array2.length];
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array2.length; ++j) {
                array3[i][j] = GF2Field.multElem(array[i], array2[j]);
            }
        }
        return array3;
    }
    
    public short[] multVect(final short n, final short[] array) {
        final short[] array2 = new short[array.length];
        for (int i = 0; i < array2.length; ++i) {
            array2[i] = GF2Field.multElem(n, array[i]);
        }
        return array2;
    }
    
    public short[][] multMatrix(final short n, final short[][] array) {
        final short[][] array2 = new short[array.length][array[0].length];
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array[0].length; ++j) {
                array2[i][j] = GF2Field.multElem(n, array[i][j]);
            }
        }
        return array2;
    }
    
    public short[][] addMatrix(final short[][] array, final short[][] array2) {
        if (array.length != array2.length || array[0].length != array2[0].length) {
            throw new RuntimeException("Addition is not possible!");
        }
        final short[][] array3 = new short[array.length][array[0].length];
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array[0].length; ++j) {
                array3[i][j] = GF2Field.addElem(array[i][j], array2[i][j]);
            }
        }
        return array3;
    }
    
    public short[][] addMatrixTranspose(final short[][] array) {
        if (array.length != array[0].length) {
            throw new RuntimeException("Addition is not possible!");
        }
        return this.addMatrix(array, this.transpose(array));
    }
    
    public short[][] transpose(final short[][] array) {
        final short[][] array2 = new short[array[0].length][array.length];
        for (int i = 0; i < array.length; ++i) {
            for (int j = 0; j < array[0].length; ++j) {
                array2[j][i] = array[i][j];
            }
        }
        return array2;
    }
    
    public short[][] to_UT(final short[][] array) {
        if (array.length != array[0].length) {
            throw new RuntimeException("Computation to upper triangular matrix is not possible!");
        }
        final short[][] array2 = new short[array.length][array.length];
        for (int i = 0; i < array.length; ++i) {
            array2[i][i] = array[i][i];
            for (int j = i + 1; j < array[0].length; ++j) {
                array2[i][j] = GF2Field.addElem(array[i][j], array[j][i]);
            }
        }
        return array2;
    }
    
    public short[][][] obfuscate_l1_polys(final short[][] array, final short[][][] array2, final short[][][] array3) {
        if (array2[0].length != array3[0].length || array2[0][0].length != array3[0][0].length || array2.length != array[0].length || array3.length != array.length) {
            throw new RuntimeException("Multiplication not possible!");
        }
        final short[][][] array4 = new short[array3.length][array3[0].length][array3[0][0].length];
        for (int i = 0; i < array2[0].length; ++i) {
            for (int j = 0; j < array2[0][0].length; ++j) {
                for (int k = 0; k < array.length; ++k) {
                    for (int l = 0; l < array[0].length; ++l) {
                        array4[k][i][j] = GF2Field.addElem(array4[k][i][j], GF2Field.multElem(array[k][l], array2[l][i][j]));
                    }
                    array4[k][i][j] = GF2Field.addElem(array3[k][i][j], array4[k][i][j]);
                }
            }
        }
        return array4;
    }
}
