@Override
    public long invert(long element) {
        isInField(element);

        if (element == 1) {
            return 1;
        }

        if (element == 0) {
            throw new MathArithmeticException("Cannot find inverse for ZERO.");
        }

        //prepare for division
        long remainder = element;
        long numerator = reducingPolynomial;
        long denumerator = element;

        //prepare to find Bezout's identity
        long temp = 0;
        ArrayList<Long> resultList = new ArrayList<>();
        ArrayList<Long> bezoutIdentity = new ArrayList<>();


        //find greatest greatest common divisor, last positive remainder
        while (remainder != 0) {

            short numeratorBinarySize = countBinarySize(numerator);
            short denumeratorBinarySize = countBinarySize(denumerator);
            long tempNumerator = numerator;

            //division of binary polynomial
            long result = 0;
            while (numeratorBinarySize >= denumeratorBinarySize) {
                temp = 1;
                temp <<= (numeratorBinarySize - denumeratorBinarySize);
                result ^= temp;
                tempNumerator ^= (denumerator << (numeratorBinarySize - denumeratorBinarySize));

                numeratorBinarySize = countBinarySize(tempNumerator);
                denumeratorBinarySize = countBinarySize(denumerator);
            }
            remainder = tempNumerator;

            if (remainder == 0 && denumerator != 1) {
                throw new MathArithmeticException("Cannot compute inverse"
                        + " for this element.");
            }

            //resultList data neccessary to find Bezout's identity
            resultList.add(numerator);
            resultList.add(denumerator);
            resultList.add(result);

            numerator = denumerator;
            denumerator = remainder;
        }

        if (resultList.size() > 3) {
            //we don't need last 3 values
            resultList.remove(resultList.size() - 1);
            resultList.remove(resultList.size() - 1);
            resultList.remove(resultList.size() - 1);
        }

        bezoutIdentity.add(1l);
        bezoutIdentity.add(resultList.get(resultList.size() - 3));
        bezoutIdentity.add(resultList.get(resultList.size() - 2));
        bezoutIdentity.add(resultList.get(resultList.size() - 1));


        //find Bezout's identity from resultList data counted in Euclidean algorithm
        while (resultList.size() != 3) {
            resultList.remove(resultList.size() - 1);
            resultList.remove(resultList.size() - 1);
            resultList.remove(resultList.size() - 1);

            temp = bezoutIdentity.get(0);
            bezoutIdentity.set(0, bezoutIdentity.get(3));
            bezoutIdentity.set(1, resultList.get(resultList.size() - 3));
            bezoutIdentity.set(2, resultList.get(resultList.size() - 2));
            bezoutIdentity.set(3, add(temp, multiply(bezoutIdentity.get(3), resultList.get(resultList.size() - 1))));
        }

        //inverted element
        return bezoutIdentity.get(3);
    }