@Override
    public Matrix gauss(Matrix matrix) {

        isValid(matrix);

        //prepare result
        Matrix result = new Matrix(matrix);

        for (int diagPos = 1; diagPos < Math.min(matrix.getRows(), matrix.getColumns()) + 1; diagPos++) {

            long value;

            //find column with pivot, swap lines if necessary
            int colPos = diagPos - 1;
            while (colPos < matrix.getColumns() && result.getElement(diagPos - 1, colPos) == 0) {
                result = findPivot(result, colPos, diagPos - 1);
                if (result.getElement(diagPos - 1, colPos) == 0) {
                    colPos++;
                }
            }
            if (colPos == matrix.getColumns()) {
                colPos = diagPos - 1;
            }

            for (int rowsUnderDiagPos = diagPos; rowsUnderDiagPos < matrix.getRows(); rowsUnderDiagPos++) {

                try {
                    //set value, it will be used to set column at diagPos to zero
                    value = galoisField.divide(result.getElement(rowsUnderDiagPos, colPos), result.getElement(diagPos - 1, colPos));

                    //subtract from line, pivot will be set to zero and other values will be edited
                    for (int colsUnderDiagPos = diagPos - 1; colsUnderDiagPos < matrix.getColumns(); colsUnderDiagPos++) {
                        result.setElement(rowsUnderDiagPos, colsUnderDiagPos,
                                galoisField.subtract(galoisField.multiply(result.getElement(diagPos - 1, colsUnderDiagPos), value),
                                result.getElement(rowsUnderDiagPos, colsUnderDiagPos)));
                    }
                } catch (MathArithmeticException ex) {
                    //catched division by zero, OK, thrown by columns full of zeroes
                }
            }
        }

        //Result matrix is in row echelon form
        return result;
    }