def _factor_minpoly_modp(minpoly_coeff, p): """ Factor theminpoly modulo p, and return two values in a tuple. We call gcd(square factors mod p, difference of minpoly and its modp) Z. 1) degree of Z 2) (minpoly mod p) / Z """ Fp = finitefield.FinitePrimeField.getInstance(p) theminpoly_p = uniutil.polynomial([(d, Fp.createElement(c)) for (d, c) in enumerate(minpoly_coeff)], Fp) modpfactors = theminpoly_p.factor() mini_p = arith1.product([t for (t, e) in modpfactors]) quot_p = theminpoly_p.exact_division(mini_p) mini = _min_abs_poly(mini_p) quot = _min_abs_poly(quot_p) minpoly = uniutil.polynomial(enumerate(minpoly_coeff), Z) f_p = _mod_p((mini * quot - minpoly).scalar_exact_division(p), p) gcd = f_p.getRing().gcd common_p = gcd(gcd(mini_p, quot_p), f_p) # called Z uniq_p = theminpoly_p // common_p uniq = _min_abs_poly(uniq_p) return common_p.degree(), uniq
def isIdeal(self): """ Check whether given lattice is a ideal lattice. """ n = self.basis.column Compo = [] for i in range(n): for j in range(n): if i == j + 1: Compo.append(1) else: Compo.append(0) M = Matrix(n, n, Compo) d = self.basis.determinant() B = self.basis.hermiteNormalForm() z = B.compo[n-1][n-1] A = B.adjugateMatrix() z = B.compo[n-1][n-1] P = A*M*B for i in range(n): for j in range(n): P.compo[i][j] = P.compo[i][j]%d sum = 0 for i in range(n): for j in range(n-1): sum = sum + P.compo[i][j] if sum == 0: c_compo = [] for i in range(n): c_compo.append(P.compo[i][n-1]) else: return False c_sum = 0 for i in range(n): c_sum = c_sum + c_compo[i] if c_sum == 0: c_compo = [] for i in range(n): c_compo.append(d) c = Vector(c_compo) if z == 1: qstar = c poly = B*qstar elif gcd(z, d//z) != 1: qstar = c poly = B*qstar else: sum0 = 0 for i in range(n): sum0 = sum0 + c.compo[i]%z if sum0 == 0: qstar_compo = [] for j in range(n): qstar_compo.append(CRT([(c.compo[j]//z, d//z), (0, z)])) qstar = Vector(qstar_compo) poly = B*qstar else: return False sum1 = 0 for i in range(n): sum1 = sum1 + poly.compo[i]%(d//z) if sum1 == 0: q_compo = [] for j in range(n): q_compo.append(poly.compo[j]//d) q = Vector(q_compo) return True, q else: return False
def isIdeal(self): """ Check whether given lattice is a ideal lattice. """ n = self.basis.column Compo = [] for i in range(n): for j in range(n): if i == j + 1: Compo.append(1) else: Compo.append(0) M = Matrix(n, n, Compo) d = self.basis.determinant() B = self.basis.hermiteNormalForm() z = B.compo[n - 1][n - 1] A = B.adjugateMatrix() z = B.compo[n - 1][n - 1] P = A * M * B for i in range(n): for j in range(n): P.compo[i][j] = P.compo[i][j] % d sum = 0 for i in range(n): for j in range(n - 1): sum = sum + P.compo[i][j] if sum == 0: c_compo = [] for i in range(n): c_compo.append(P.compo[i][n - 1]) else: return False c_sum = 0 for i in range(n): c_sum = c_sum + c_compo[i] if c_sum == 0: c_compo = [] for i in range(n): c_compo.append(d) c = Vector(c_compo) if z == 1: qstar = c poly = B * qstar elif gcd(z, d // z) != 1: qstar = c poly = B * qstar else: sum0 = 0 for i in range(n): sum0 = sum0 + c.compo[i] % z if sum0 == 0: qstar_compo = [] for j in range(n): qstar_compo.append(CRT([(c.compo[j] // z, d // z), (0, z)])) qstar = Vector(qstar_compo) poly = B * qstar else: return False sum1 = 0 for i in range(n): sum1 = sum1 + poly.compo[i] % (d // z) if sum1 == 0: q_compo = [] for j in range(n): q_compo.append(poly.compo[j] // d) q = Vector(q_compo) return True, q else: return False