def testExactDivision(self): fortyfive = misc.FactoredInteger(45) self.assertEqual(45, int(fortyfive)) fifteen = fortyfive.exact_division(3) self.assertEqual(15, int(fifteen)) five = fortyfive // 9 self.assertEqual(5, int(five)) five = fortyfive.exact_division(misc.FactoredInteger(9, {3: 2})) self.assertEqual(5, int(five))
def testSquarefreePart(self): fifteen = misc.FactoredInteger(15) self.assertEqual(15, fifteen.squarefree_part()) self.assertTrue( isinstance(fifteen.squarefree_part(True), misc.FactoredInteger)) self.assertEqual(15, fifteen.squarefree_part(True).integer) self.assertEqual({3: 1, 5: 1}, fifteen.squarefree_part(True).factors) factored45 = misc.FactoredInteger(45, {3: 2, 5: 1}) self.assertEqual({5: 1}, factored45.squarefree_part(True).factors)
def trorder(n, sossp, sogsp, nt, disc): """ Compute the order. n: int nt: element """ factor_n = misc.FactoredInteger(n) while True: c_s1 = ClassGroup(disc, 0, []) lstp_ls = sossp.retel() sogsptp = sogsp.retel() for p, e in factor_n: # initialize c_s1 base = nt**(int(factor_n) // p) for ttp_ls in lstp_ls: c_s1.insttree(base * ttp_ls) # search in c_s1 for tmp_ell in sogsptp: rete = c_s1.search(tmp_ell) if rete != False: factor_n //= p break else: continue break else: return int(factor_n)
def ordercv(n, sossp, sogsp, nt, disc, classnum, tmp_ss, tmp_gs): """ n: int """ factor_n = misc.FactoredInteger(n) while True: c_s1 = ClassGroup(disc, classnum, []) # a subset of G lstp_ls = sossp.retel() sogsptp = sogsp.retel() for p, e in factor_n: base = nt**(int(factor_n) // p) for ttp_ls in lstp_ls: tmp_c_s1 = base * ttp_ls tmp_c_s1.s_parent = ttp_ls c_s1.insttree(tmp_c_s1) for tmp_ell in sogsptp: rete = c_s1.search(tmp_ell) if rete != False: factor_n //= p tmp_ss = rete.s_parent tmp_gs = tmp_ell break else: continue break else: break return int(factor_n), tmp_ss, tmp_gs
def _primitive_polynomial(char, degree): """ Return a primitive polynomial of self.degree. REF: Lidl & Niederreiter, Introduction to finite fields and their applications. """ cardinality = char**degree basefield = FinitePrimeField.getInstance(char) const = basefield.primitive_element() if degree & 1: const = -const cand = uniutil.polynomial({0: const, degree: basefield.one}, basefield) maxorder = factor_misc.FactoredInteger((cardinality - 1) // (char - 1)) var = uniutil.polynomial({1: basefield.one}, basefield) while not (cand.isirreducible() and all( pow(var, int(maxorder) // p, cand).degree() > 0 for p in maxorder.prime_divisors())): # randomly modify the polynomial deg = bigrandom.randrange(1, degree) coeff = basefield.random_element(1, char) cand += uniutil.polynomial({deg: coeff}, basefield) _log.debug(cand.order.format(cand)) return cand
def testIsDivisibleBy(self): factored45 = misc.FactoredInteger(45, {3: 2, 5: 1}) self.assertFalse(factored45.is_divisible_by(2)) self.assertTrue(factored45.is_divisible_by(3)) self.assertTrue(factored45.is_divisible_by(5)) self.assertFalse(factored45.is_divisible_by(7)) self.assertTrue(factored45.is_divisible_by(9)) self.assertTrue(factored45.is_divisible_by(15))
def viafactor(n): """ Test whether n is squarefree or not. It is obvious that if one knows the prime factorization of the number, he/she can tell whether the number is squarefree or not. """ for p, e in factor_misc.FactoredInteger(n): if e >= 2: return False return True
def sigma(m, n): """ Return the sum of m-th powers of the factors of n. """ if n == 1: return 1 if prime.primeq(n): return 1 + n**m s = 1 for p, e in factor_misc.FactoredInteger(n): t = 1 for i in range(1, e + 1): t += (p**i)**m s *= t return s
def primitive_element(self): """ Return a primitive element of the field, i.e., a generator of the multiplicative group. """ fullorder = card(self) - 1 if self._orderfactor is None: self._orderfactor = factor_misc.FactoredInteger(fullorder) for i in bigrange.range(self.char, card(self)): g = self.createElement(i) for p in self._orderfactor.prime_divisors(): if g**(fullorder // p) == self.one: break else: return g
def order(self): """ Find and return the order of the element in the multiplicative group of F_p. """ if self.n == 0: raise ValueError("zero is not in the group.") if not hasattr(self, "orderfactor"): self.orderfactor = factor_misc.FactoredInteger(self.m - 1) o = 1 for p, e in self.orderfactor: b = self**(int(self.orderfactor) // (p**e)) while b.n != 1: o = o * p b = b**p return o
def order(self, elem): """ Find and return the order of the element in the multiplicative group of the field. """ if not elem: raise ValueError("zero is not in the multiplicative group.") if self._orderfactor is None: self._orderfactor = factor_misc.FactoredInteger(card(self) - 1) o = 1 for p, e in self._orderfactor: b = elem**(int(self._orderfactor) // (p**e)) while b != self.one: o = o * p b = b**p return o
def order(self): """ Compute order using grouporder factorization. """ clas = self.set.entity if hasattr(clas, "zero") and self.entity == clas.zero: return 1 ordfact = factor_misc.FactoredInteger(self.set.grouporder()) identity = self.set.identity() k = 1 for p, e in ordfact: b = self.ope2(int(ordfact) // (p**e)) while b != identity: k = k * p b = b.ope2(p) return k
def euler(n): """ Euler totient function. It returns the number of relatively prime numbers to n smaller than n. """ if n == 1: return 1 if prime.primeq(n): return n - 1 t = 1 for p, e in factor_misc.FactoredInteger(n): if e > 1: t *= pow(p, e - 1) * (p - 1) else: t *= p - 1 return t
def moebius(n): """ Moebius function. It returns: -1 if n has odd distinct prime factors, 1 if n has even distinct prime factors, or 0 if n has a squared prime factor. """ if n == 1: return 1 if prime.primeq(n): return -1 m = 1 for p, e in factor_misc.FactoredInteger(n): if e > 1: return 0 m = -m return m
def SilverPohligHellman(target, base, p): """ Silver-Pohlig-Hellman method of DLP for finite prime fields. x, the discrete log of target, can be determined for each prime power factor of p - 1 (passed through factored_order): x = \sum s_j p_i**j mod p_i**e (0 <= s_j < p_i) Lidl, Niederreiter, 'Intro. to finite fields and their appl.' (revised ed) pp.356 (1994) CUP. """ log_mod_factor = {} order = p - 1 factored_order = factor_misc.FactoredInteger(order) base_inverse = arith1.inverse(base, p) for p_i, e in factored_order: log_mod_factor[p_i] = 0 smallorder = order modtarget = target primitive_root_of_unity = pow(base, order // p_i, p) p_i_power = 1 for j in range(e): smallorder //= p_i targetpow = pow(modtarget, smallorder, p) if targetpow == 1: s_j = 0 else: root_of_unity = primitive_root_of_unity for k in range(1, p_i): if targetpow == root_of_unity: s_j = k break root_of_unity = root_of_unity * primitive_root_of_unity % p log_mod_factor[p_i] += s_j * p_i_power modtarget = modtarget * pow(base_inverse, s_j * p_i_power, p) % p p_i_power *= p_i if p_i < p_i_power: log_mod_factor[p_i_power] = log_mod_factor[p_i] del log_mod_factor[p_i] if len(log_mod_factor) == 1: return list(log_mod_factor.values())[0] return arith1.CRT([(r, p) for (p, r) in list(log_mod_factor.items())])
def _prepare_squarefactors(disc): """ Return a list of square factors of disc (=discriminant). PRECOND: d is integer """ squarefactors = [] if disc < 0: fund_disc, absd = -1, -disc else: fund_disc, absd = 1, disc v2, absd = arith1.vp(absd, 2) if squarefree.trivial_test_ternary(absd): fund_disc *= absd else: for p, e in factor_misc.FactoredInteger(absd): if e > 1: squareness, oddity = divmod(e, 2) squarefactors.append((p, squareness)) if oddity: fund_disc *= p else: fund_disc *= p if fund_disc & 3 == 1: if v2 & 1: squareness, oddity = divmod(v2, 2) squarefactors.append((2, squareness)) if oddity: fund_disc *= 2 else: squarefactors.append((2, v2 >> 1)) else: # fund_disc & 3 == 3 assert v2 >= 2 fund_disc *= 4 if v2 > 2: squarefactors.append((2, (v2 - 2) >> 1)) return squarefactors
def testDivisors(self): fifteen = misc.FactoredInteger(15) self.assertEqual([1, 3, 5, 15], fifteen.divisors())
def testEquality(self): fifteen = misc.FactoredInteger(15) self.assertEqual(15, fifteen) self.assertEqual(misc.FactoredInteger(15), fifteen) self.assertNotEqual(misc.FactoredInteger(16), fifteen)
def testPrimeDivisors(self): fifteen = misc.FactoredInteger(15) self.assertEqual([3, 5], fifteen.prime_divisors())
def testProperDivisors(self): fortyfive = misc.FactoredInteger(45) self.assertEqual([3, 5, 9, 15], fortyfive.proper_divisors())
def testInitFactored(self): factored45 = misc.FactoredInteger(45, {3: 2, 5: 1}) self.assertEqual(45, factored45.integer) self.assertEqual({3: 2, 5: 1}, factored45.factors)