def invert(self, a):
    " Ths method returns the inverse of a in the field\n            The inverse is computed by determining the Bezout coefficient using the\n            extended Euclide's algorithm or by specialized algorithms depending\n            on the degree of the extension (2 or 3)\n        "
    assert (a.F == self)
    k = (self.deg - 1)
    if ((k == 2) and (self.F.rep == 'A')):
        A = a.poly.coef
        (a1, a0) = (A[0].val, A[1].val)
        p = self.char
        norm = ((a0 * a0) + (a1 * a1))
        invnorm = gmpy.invert(norm, p)
        c0 = ((a0 * invnorm) % p)
        c1 = (((- a1) * invnorm) % p)
        c0e = FieldElem(c0, self.F)
        c1e = FieldElem(c1, self.F)
        invap = polynom(self.F, [c1e, c0e])
        inva = ExtensionFieldElem(self, invap)
        return inva
    elif (k == 2):
        A = a.poly.coef
        (a1, a0) = (A[0], A[1])
        mod = self.irpoly.coef[(- 1)]
        a12 = self.F.square(a1)
        mid = self.F.pmul(a12, mod)
        norm = (self.F.square(a0) + mid)
        invnorm = self.F.invert(norm)
        c = self.F.pmul(a0, invnorm)
        d = (- self.F.pmul(a1, invnorm))
        invap = polynom(self.F, [d, c])
        inva = ExtensionFieldElem(self, invap)
        return inva
    elif (k == 3):
        A = a.poly.coef
        (a2, a1, a0) = (A[0], A[1], A[2])
        mod = (- self.irpoly.coef[(- 1)])
        z0 = self.F.zero()
        z1 = self.F.one()
        if (a0 == z0):
            if (a1 == z0):
                (c0, c1, c2) = (z0, self.F.invert(self.F.pmul(a2, mod)), z0)
            elif (a2 == z0):
                (c0, c1, c2) = (z0, z0, self.F.invert(self.F.pmul(a1, mod)))
            else:
                a22 = self.F.square(a2)
                a12 = self.F.square(a1)
                c2 = self.F.pmul(a12, self.F.invert((self.F.pmul(self.F.pmul(a22, a2), mod) + self.F.pmul(self.F.pmul(a12, a1), mod))))
                c1 = self.F.pmul((z1 - self.F.pmul(self.F.pmul(a1, c2), mod)), self.F.invert(self.F.pmul(a2, mod)))
                c0 = self.F.pmul((- self.F.pmul(self.F.pmul(a2, mod), c2)), self.F.invert(a1))
        elif ((a1 == z0) and (a2 == z0)):
            (c0, c1, c2) = (self.F.invert(a0), z0, z0)
        else:
            a12 = self.F.pmul(a1, a2)
            a12m = self.F.pmul(a12, mod)
            a00 = self.F.square(a0)
            abis = (a00 - a12m)
            if (abis == z0):
                a11 = self.F.square(a1)
                a22 = self.F.square(a2)
                a02 = self.F.pmul(a0, a2)
                a01 = self.F.pmul(a0, a1)
                c2 = self.F.pmul((- a), self.F.invert(self.F.pmul((a02 - a11), mod)))
                c1 = self.F.pmul((- a2), self.F.invert((a01 - self.F.pmul(a22, mod))))
                a1c2 = self.F.pmul(a1, c2)
                a2c1 = self.F.pmul(a2, c1)
                c0 = self.F.pmul((z1 - self.F.pmul((a1c2 + a2c1), mod)), self.F.invert(a0))
            elif (a1 == z0):
                inva0 = self.F.invert(a0)
                a02 = self.F.pmul(a0, a2)
                a000 = self.F.pmul(a00, a0)
                a22 = self.F.square(a2)
                a222 = self.F.pmul(a22, a2)
                mm = self.F.square(mod)
                a222mm = self.F.pmul(a222, mm)
                c2 = self.F.pmul((- a02), self.F.invert((a000 + a222mm)))
                a02m = self.F.pmul(a02, mod)
                a02mc2 = self.F.pmul(a02m, c2)
                inva00 = self.F.square(inva0)
                c1 = self.F.pmul((- a02mc2), inva00)
                a2m = self.F.pmul(a2, mod)
                a2mc1 = self.F.pmul(a2m, c1)
                c0 = self.F.pmul((z1 - a2mc1), inva0)
            elif (a2 == z0):
                a11 = self.F.square(a1)
                a111 = self.F.pmul(a11, a1)
                a000 = self.F.pmul(a00, a0)
                a111m = self.F.pmul(a111, mod)
                inva0 = self.F.invert(a0)
                c2 = self.F.pmul(a11, self.F.invert((a111m + a000)))
                a11m = self.F.pmul(a11, mod)
                a11mc2 = self.F.pmul(a11m, c2)
                inva00 = self.F.square(inva0)
                c1 = self.F.pmul((a11mc2 - a1), inva00)
                a1m = self.F.pmul(a1, mod)
                a1mc2 = self.F.pmul(a1m, c2)
                c0 = self.F.pmul((z1 - a1mc2), inva0)
            else:
                a01 = self.F.pmul(a0, a1)
                a22 = self.F.square(a2)
                a22m = self.F.pmul(a22, mod)
                a02 = self.F.pmul(a0, a2)
                a11 = self.F.square(a1)
                abus = (a01 - a22m)
                abos = self.F.pmul((a02 - a11), mod)
                invabis = self.F.invert(abis)
                abb = self.F.pmul(abus, invabis)
                abb1 = self.F.pmul(abb, a1)
                abbbos = self.F.pmul(abb, abos)
                c2 = self.F.pmul((abb1 - a2), self.F.invert((abis - abbbos)))
                abosc2 = self.F.pmul(abos, c2)
                c1 = self.F.pmul(((- a1) - abosc2), invabis)
                a1c2 = self.F.pmul(a1, c2)
                a2c1 = self.F.pmul(a2, c1)
                c0 = self.F.pmul((z1 - self.F.pmul((a1c2 + a2c1), mod)), self.F.invert(a0))
        invap = polynom(self.F, [c2, c1, c0])
        inva = ExtensionFieldElem(self, invap)
        return inva
    else:
        P = ExtensionFieldElem(self, self.irpoly)
        (r, u, v) = self.extendedeuclide(P, a)
        (n, d) = r.poly.truedeg()
        assert (n == (self.deg - 2))
        c = r.poly.coef[(len(r.poly.coef) - 1)].invert()
        cp = polynom(self.F, [c])
        ce = ExtensionFieldElem(self, cp)
        return (ce * v)
Ths method returns the inverse of a in the field
The inverse is computed by determining the Bezout coefficient using the
extended Euclide's algorithm or by specialized algorithms depending
on the degree of the extension (2 or 3)
def invert(self, a):
    " Ths method returns the inverse of a in the field\n            The inverse is computed by determining the Bezout coefficient using the\n            extended Euclide's algorithm or by specialized algorithms depending\n            on the degree of the extension (2 or 3)\n        "
    assert (a.F == self)
    k = (self.deg - 1)
    if ((k == 2) and (self.F.rep == 'A')):
        A = a.poly.coef
        (a1, a0) = (A[0].val, A[1].val)
        p = self.char
        norm = ((a0 * a0) + (a1 * a1))
        invnorm = gmpy.invert(norm, p)
        c0 = ((a0 * invnorm) % p)
        c1 = (((- a1) * invnorm) % p)
        c0e = FieldElem(c0, self.F)
        c1e = FieldElem(c1, self.F)
        invap = polynom(self.F, [c1e, c0e])
        inva = ExtensionFieldElem(self, invap)
        return inva
    elif (k == 2):
        A = a.poly.coef
        (a1, a0) = (A[0], A[1])
        mod = self.irpoly.coef[(- 1)]
        a12 = self.F.square(a1)
        mid = self.F.pmul(a12, mod)
        norm = (self.F.square(a0) + mid)
        invnorm = self.F.invert(norm)
        c = self.F.pmul(a0, invnorm)
        d = (- self.F.pmul(a1, invnorm))
        invap = polynom(self.F, [d, c])
        inva = ExtensionFieldElem(self, invap)
        return inva
    elif (k == 3):
        A = a.poly.coef
        (a2, a1, a0) = (A[0], A[1], A[2])
        mod = (- self.irpoly.coef[(- 1)])
        z0 = self.F.zero()
        z1 = self.F.one()
        if (a0 == z0):
            if (a1 == z0):
                (c0, c1, c2) = (z0, self.F.invert(self.F.pmul(a2, mod)), z0)
            elif (a2 == z0):
                (c0, c1, c2) = (z0, z0, self.F.invert(self.F.pmul(a1, mod)))
            else:
                a22 = self.F.square(a2)
                a12 = self.F.square(a1)
                c2 = self.F.pmul(a12, self.F.invert((self.F.pmul(self.F.pmul(a22, a2), mod) + self.F.pmul(self.F.pmul(a12, a1), mod))))
                c1 = self.F.pmul((z1 - self.F.pmul(self.F.pmul(a1, c2), mod)), self.F.invert(self.F.pmul(a2, mod)))
                c0 = self.F.pmul((- self.F.pmul(self.F.pmul(a2, mod), c2)), self.F.invert(a1))
        elif ((a1 == z0) and (a2 == z0)):
            (c0, c1, c2) = (self.F.invert(a0), z0, z0)
        else:
            a12 = self.F.pmul(a1, a2)
            a12m = self.F.pmul(a12, mod)
            a00 = self.F.square(a0)
            abis = (a00 - a12m)
            if (abis == z0):
                a11 = self.F.square(a1)
                a22 = self.F.square(a2)
                a02 = self.F.pmul(a0, a2)
                a01 = self.F.pmul(a0, a1)
                c2 = self.F.pmul((- a), self.F.invert(self.F.pmul((a02 - a11), mod)))
                c1 = self.F.pmul((- a2), self.F.invert((a01 - self.F.pmul(a22, mod))))
                a1c2 = self.F.pmul(a1, c2)
                a2c1 = self.F.pmul(a2, c1)
                c0 = self.F.pmul((z1 - self.F.pmul((a1c2 + a2c1), mod)), self.F.invert(a0))
            elif (a1 == z0):
                inva0 = self.F.invert(a0)
                a02 = self.F.pmul(a0, a2)
                a000 = self.F.pmul(a00, a0)
                a22 = self.F.square(a2)
                a222 = self.F.pmul(a22, a2)
                mm = self.F.square(mod)
                a222mm = self.F.pmul(a222, mm)
                c2 = self.F.pmul((- a02), self.F.invert((a000 + a222mm)))
                a02m = self.F.pmul(a02, mod)
                a02mc2 = self.F.pmul(a02m, c2)
                inva00 = self.F.square(inva0)
                c1 = self.F.pmul((- a02mc2), inva00)
                a2m = self.F.pmul(a2, mod)
                a2mc1 = self.F.pmul(a2m, c1)
                c0 = self.F.pmul((z1 - a2mc1), inva0)
            elif (a2 == z0):
                a11 = self.F.square(a1)
                a111 = self.F.pmul(a11, a1)
                a000 = self.F.pmul(a00, a0)
                a111m = self.F.pmul(a111, mod)
                inva0 = self.F.invert(a0)
                c2 = self.F.pmul(a11, self.F.invert((a111m + a000)))
                a11m = self.F.pmul(a11, mod)
                a11mc2 = self.F.pmul(a11m, c2)
                inva00 = self.F.square(inva0)
                c1 = self.F.pmul((a11mc2 - a1), inva00)
                a1m = self.F.pmul(a1, mod)
                a1mc2 = self.F.pmul(a1m, c2)
                c0 = self.F.pmul((z1 - a1mc2), inva0)
            else:
                a01 = self.F.pmul(a0, a1)
                a22 = self.F.square(a2)
                a22m = self.F.pmul(a22, mod)
                a02 = self.F.pmul(a0, a2)
                a11 = self.F.square(a1)
                abus = (a01 - a22m)
                abos = self.F.pmul((a02 - a11), mod)
                invabis = self.F.invert(abis)
                abb = self.F.pmul(abus, invabis)
                abb1 = self.F.pmul(abb, a1)
                abbbos = self.F.pmul(abb, abos)
                c2 = self.F.pmul((abb1 - a2), self.F.invert((abis - abbbos)))
                abosc2 = self.F.pmul(abos, c2)
                c1 = self.F.pmul(((- a1) - abosc2), invabis)
                a1c2 = self.F.pmul(a1, c2)
                a2c1 = self.F.pmul(a2, c1)
                c0 = self.F.pmul((z1 - self.F.pmul((a1c2 + a2c1), mod)), self.F.invert(a0))
        invap = polynom(self.F, [c2, c1, c0])
        inva = ExtensionFieldElem(self, invap)
        return inva
    else:
        P = ExtensionFieldElem(self, self.irpoly)
        (r, u, v) = self.extendedeuclide(P, a)
        (n, d) = r.poly.truedeg()
        assert (n == (self.deg - 2))
        c = r.poly.coef[(len(r.poly.coef) - 1)].invert()
        cp = polynom(self.F, [c])
        ce = ExtensionFieldElem(self, cp)
        return (ce * v)