/// <summary>
        /// Calculates the multiplicative inverse of <c>this</c> and returns the result in a new GF2nPolynomialElement
        /// </summary>
        /// 
        /// <returns>Returns <c>this</c>^(-1)</returns>
        public GF2nPolynomialElement InvertEEA()
        {
            if (IsZero())
                throw new ArithmeticException();

            GF2Polynomial b = new GF2Polynomial(mDegree + 32, "ONE");
            b.ReduceN();
            GF2Polynomial c = new GF2Polynomial(mDegree + 32);
            c.ReduceN();
            GF2Polynomial u = GetGF2Polynomial();
            GF2Polynomial v = mField.FieldPolynomial;
            GF2Polynomial h;
            int j;
            u.ReduceN();

            while (!u.IsOne())
            {
                u.ReduceN();
                v.ReduceN();
                j = u.Length - v.Length;
                if (j < 0)
                {
                    h = u;
                    u = v;
                    v = h;
                    h = b;
                    b = c;
                    c = h;
                    j = -j;
                    c.ReduceN(); // this increases the performance
                }

                u.ShiftLeftAddThis(v, j);
                b.ShiftLeftAddThis(c, j);
            }
            b.ReduceN();

            return new GF2nPolynomialElement((GF2nPolynomialField)mField, b);
        }
        /// <summary>
        /// Does the recursion for Karatzuba multiplication
        /// </summary>
        /// 
        /// <param name="B">A GF2Polynomial</param>
        /// 
        /// <returns><c>this * B</c></returns>
        private GF2Polynomial KaraMult(GF2Polynomial B)
        {
            GF2Polynomial result = new GF2Polynomial(_length << 1);
            if (_length <= 32)
            {
                result._value = Mult32(_value[0], B._value[0]);
                return result;
            }
            if (_length <= 64)
            {
                result._value = Mult64(_value, B._value);
                return result;
            }
            if (_length <= 128)
            {
                result._value = Mult128(_value, B._value);
                return result;
            }
            if (_length <= 256)
            {
                result._value = Mult256(_value, B._value);
                return result;
            }
            if (_length <= 512)
            {
                result._value = Mult512(_value, B._value);
                return result;
            }

            int n = BigMath.FloorLog(_length - 1);
            n = _bitMask[n];

            GF2Polynomial a0 = Lower(((n - 1) >> 5) + 1);
            GF2Polynomial a1 = Upper(((n - 1) >> 5) + 1);
            GF2Polynomial b0 = B.Lower(((n - 1) >> 5) + 1);
            GF2Polynomial b1 = B.Upper(((n - 1) >> 5) + 1);
            GF2Polynomial c = a1.KaraMult(b1); // c = a1*b1
            GF2Polynomial e = a0.KaraMult(b0); // e = a0*b0
            a0.AddToThis(a1); // a0 = a0 + a1
            b0.AddToThis(b1); // b0 = b0 + b1

            GF2Polynomial d = a0.KaraMult(b0); // d = (a0+a1)*(b0+b1)
            result.ShiftLeftAddThis(c, n << 1);
            result.ShiftLeftAddThis(c, n);
            result.ShiftLeftAddThis(d, n);
            result.ShiftLeftAddThis(e, n);
            result.AddToThis(e);

            return result;
        }