import math k = 31 F = GF(2) var = 'x' PR = PolynomialRing(F, var) p = PR.irreducible_element(k) gamma = PR.random_element(k) exp = 10 target = gamma^exp % p def polynomial_power_in_Z2(q, exp, p, var): if exp == 0: return 1 if q.degree() == p.degree(): q += p res = q for i in range(2, exp+1): res = multiply_polynomials_in_Z2(res, q, p, var) return res def polynomial_power_in_Z2_V2(q, exp, p, var): if exp == 0: return 1 if q.degree() == p.degree(): q += p log2deg = math.floor(math.log2(exp)) + 1 arr = [0]*log2deg arr[0] = q for i in range(1, log2deg): arr[i] = multiply_polynomials_in_Z2(arr[i-1], arr[i-1], p, var) res = PR(1) for i, b in enumerate(bin(exp)[:1:-1]): if b == '1': res = multiply_polynomials_in_Z2(res, arr[i], p, var) return res def multiply_polynomials_in_Z2(q1, q2, p, var): if q1.degree() > p.degree(): raise ValueError('Unsupported!') if q1.degree() == p.degree(): q1 += p arr = [0]*(q2.degree()+1) arr[0] = q1 for i in range(1, q2.degree()+1): arr[i] = arr[i-1]*PR(var) if arr[i].degree() == p.degree(): arr[i] += p return sum(arr[i] for i in q2.exponents()) print(target) res = polynomial_power_in_Z2(gamma, exp, p, var) print(res) res = polynomial_power_in_Z2_V2(gamma, exp, p, var) print(res)