def optimized_poly_rounded_div(self, a: Sequence[IntOrFQ], b: Sequence[IntOrFQ]) -> Sequence[IntOrFQ]: dega = deg(a) degb = deg(b) temp = [x for x in a] o = [0 for x in a] for i in range(dega - degb, -1, -1): o[i] = int(o[i] + temp[degb + i] * prime_field_inv(int(b[degb]), self.field_modulus)) for c in range(degb + 1): temp[c + i] = (temp[c + i] - o[c]) return [x % self.field_modulus for x in o[:deg(o) + 1]]
def inv(self: T_FQP) -> T_FQP: lm, hm = ( [1] + [0] * self.degree, [0] * (self.degree + 1), ) low, high = ( # Ignore mypy yelling about the inner types for the tuples being incompatible cast(List[IntOrFQ], list(self.coeffs + (0,))), cast(List[IntOrFQ], list(self.modulus_coeffs + (1,))), ) while deg(low): r = cast(List[IntOrFQ], list(poly_rounded_div(high, low))) r += [0] * (self.degree + 1 - len(r)) nm = [x for x in hm] new = [x for x in high] if len(lm) != self.degree + 1: raise Exception("Length of lm is not {}".format(self.degree + 1)) elif len(hm) != self.degree + 1: raise Exception("Length of hm is not {}".format(self.degree + 1)) elif len(nm) != self.degree + 1: raise Exception("Length of nm is not {}".format(self.degree + 1)) elif len(low) != self.degree + 1: raise Exception("Length of low is not {}".format(self.degree + 1)) elif len(high) != self.degree + 1: raise Exception("Length of high is not {}".format(self.degree + 1)) elif len(new) != self.degree + 1: raise Exception("Length of new is not {}".format(self.degree + 1)) for i in range(self.degree + 1): for j in range(self.degree + 1 - i): nm[i + j] -= lm[i] * int(r[j]) new[i + j] -= low[i] * int(r[j]) lm, low, hm, high = nm, new, lm, low return type(self)(lm[:self.degree]) / low[0]
def inv(self: T_FQP) -> T_FQP: lm, hm = [1] + [0] * self.degree, [0] * (self.degree + 1) low, high = ( cast(List[IntOrFQ], list(self.coeffs + (0, ))), cast(List[IntOrFQ], list(self.modulus_coeffs + (1, ))), ) while deg(low): r = cast(List[IntOrFQ], list(self.optimized_poly_rounded_div(high, low))) r += [0] * (self.degree + 1 - len(r)) nm = [x for x in hm] new = [x for x in high] # assert len(lm) == len(hm) == len(low) == len(high) == len(nm) == len(new) == self.degree + 1 # noqa: E501 for i in range(self.degree + 1): for j in range(self.degree + 1 - i): nm[i + j] -= lm[i] * int(r[j]) new[i + j] -= low[i] * r[j] nm = [x % self.field_modulus for x in nm] new = [int(x) % self.field_modulus for x in new] lm, low, hm, high = nm, new, lm, low return type(self)(lm[:self.degree]) / low[0]