You can use SymPy and this awesome answer to work on finite fields.
You are on the ring Z/nZ
with n = 2
so you want to use the GF
class from the linked answer :
>>> %time field = GF(2, 409)
CPU times: user 1min 47s, sys: 6.64 ms, total: 1min 47s
Wall time: 1min 47s
As you can see the initialization of GF(2, 409)
is quite long (~= 1-2 min)...
...but the computation of multiplication inverts is almost instant :
%%time
import numpy as np
# list of 410 coefficients regarding x^409 (left-most) up to x^0 (right-most)
coeffs = [0] * 410
for idx in [0, 1, 6, 15, 409]: # exponents present in your polynome
coeffs[409 - idx] = 1 # set to 1 to indicate existence
li = []
for i in range(4):
'''
To help SymPy make the polynome `x^409 + x^15 + x^6 + x + 1`,
provide the `GF.inv()` method with its coefficients using `ZZ.map()`
Actually, `inv()` will call `sympy.polys.galoistools.gf_gcdex()`
'''
coeffs = field.inv(ZZ.map(coeffs))
li.append(np.array(coeffs))
CPU times: user 37.3 ms, sys: 2 µs, total: 37.3 ms
Wall time: 36 ms
The result returned by GF.inv()
is the array of the invert's coefficients.
Note that reapplying inversion again reverts to original polynome :
>>> print(np.equal(li[0], li[2]).all() and np.equal(li[1], li[3]).all())
True
You can also verify that p(x) * p(x)^(-1) = 1
:
>>> field.mul(li[0], li[1])
[1] # Ok !
Below is the stripped code from cited answer with only what you need for inversion :
import itertools
from sympy.polys.domains import ZZ
from sympy.polys.galoistools import (gf_irreducible_p, gf_gcdex)
from sympy.ntheory.primetest import isprime
class GF():
def __init__(self, p, n=1):
p, n = int(p), int(n)
if not isprime(p):
raise ValueError("p must be a prime number, not %s" % p)
if n <= 0:
raise ValueError("n must be a positive integer, not %s" % n)
self.p = p
self.n = n
if n == 1:
self.reducing = [1, 0]
else:
for c in itertools.product(range(p), repeat=n):
poly = (1, *c)
if gf_irreducible_p(poly, p, ZZ):
self.reducing = poly
break
def inv(self, x):
s, t, h = gf_gcdex(x, self.reducing, self.p, ZZ)
return s
GF(2, 409).inv(ZZ.map(coeffs))