def gen_params_from_r(r, k): """ Description: Finds a fundamental discriminant D to use as input to the Cocks-Pinch method Input: r - prime such that r % k == 1 k - embedding degree Output: r - prime such that r % k == 1 k - embedding degree D - (negative) fundamental discriminant where D is a square mod r """ D = -Integer(Mod(int(random() * (1000)), r)) i = 0 while not kronecker( D, r) == 1: # expected number of iterations of the while loop is 2 D = -Integer(Mod(int(random() * (1000)), r)) i += 1 D = fundamental_discriminant(D) if not (kronecker(D, r) == 1): return r, k, 0 return r, k, D
def small_A_twist(E): """ Description: Finds a curve isogenous to E that has small A in the curve equation y^2 = x^3 + A*x + B Input: E - elliptic curve Output: E' - elliptic curve isogenous to E that has small A in the curve equation y^2 = x^3 + A*x + B """ a = E.ainvs()[3] q = E.base_field().order() a = power_mod(Integer(a), -1, q) if kronecker(a, q) == -1: b = 2 while kronecker(b, q) == 1: b += 1 a = a * b assert kronecker(a, q) == 1 d = Mod(a, q).sqrt() ainvs = [i for i in E.ainvs()] ainvs[3] *= d**2 ainvs[4] *= d**3 return EllipticCurve(E.base_field(), ainvs)
def small_B_twist(E): """ Description: Finds a curve isogenous to E that has small B in the curve equation y^2 = x^3 + A*x + B Input: E - elliptic curve Output: E' - elliptic curve isogenous to E that has small B in the curve equation y^2 = x^3 + A*x + B """ b = E.ainvs()[4] q = E.base_field().order() b = power_mod(Integer(b), -1, q) d = 0 s = Mod(1, q) bool = True while bool: try: d = (s * b) d = d.nth_root(3) d = Integer(d) bool = False except ValueError as e: s += 1 pass ainvs = [i for i in E.ainvs()] ainvs[3] *= d**2 ainvs[4] *= d**3 return EllipticCurve(E.base_field(), ainvs)
def method(r, k, D, max_trials=10000, g=0): """ Description: Run the Cocks-Pinch method to find an elliptic curve Input: r - prime k - embedding degree, r % k == 1 D - (negative) fundamental discriminant where D is a square mod r max_trials - the number of integers q to test for primality in the CP method g - an element of order k in Z_r^* Output: (q,t) - tuple where q is a prime and t is chosen such that there exists an elliptic curve E over F_q with trace t, and r | q+1-t; if the algorithm fails to find (q,t), it will return (0,0) """ assert test_promise(r, k, D), 'Invalid inputs' if g != 0: assert power_mod(g, k, r) == 1, 'Invalid inputs' else: g = find_element_of_order(k, r) D = Integer(D) t = Integer(g) + 1 root_d = Integer(Mod(D, r).sqrt()) u = Integer(Mod((t - 2) * root_d.inverse_mod(r), r)) q = 1 j = Integer(0) i = Integer(0) count = 0 while (count < max_trials): q = Integer((t + i * r)**2 - D * (u + j * r)**2) if q % 4 == 0: q = q // 4 if utils.is_suitable_q(q): return (q, t + i * r) q = 1 if random() < 0.5: j += 1 else: i += 1 count += 1 return (0, 0) # no prime found, so end
def order(h, k, p): bool = True g = h for i in range(1, k): bool = bool and g != 1 g = Mod(g * h, p) bool = bool and g == 1 return bool
def test_conrey(nranges=[(20, 100), (200, 1000), (500, 500000)]): for n, r in nranges: for i in range(n): q = randint(1, r) print("n, r, i, q = {}, {}, {}, {}".format(n, r, i, q)) G = DirichletGroup_conrey(q) inv = G.invariants() cinv = tuple([Mod(g, q).multiplicative_order() for g in G.gens()]) try: assert prod(inv) == G.order() assert q <= 2 or G.zeta_order() == inv[0] assert cinv == inv except: print('group error') return q, inv, G if q > 2: m = 0 while gcd(m, q) != 1: m = randint(1, q) chi = G[m] n = randint(1, q) try: assert chi.multiplicative_order() == Mod( m, q).multiplicative_order() if gcd(n, q) != 1: try: assert chi.logvalue(n) == -1 except: print('non unit value error') return chi, n, r elif q < 10 ^ 6: try: ref = chi.sage_character()(n).n().real() new = N(chi(n).real) assert abs(ref - new) < 1e-5 except: print('unit value error') return chi, n except: print('char error') return chi, n, r
def parity(self): number = self.number par = 0 for p, e in self.modfactor(): if p == 2: if number % 4 == 3: par = 1 - par else: phi2 = (p - 1) / Integer(2) * p**(e - 1) if Mod(number, p**e)**phi2 != 1: par = 1 - par return par
def IsSquareInQp(x, p): if x == 0: return true # Check parity of valuation v = valuation(x, p) if v % 2: return false # Renormalise to get a unit x //= p**v # Reduce mod p and conclude if p == 2: return Mod(x, 8) == 1 else: return kronecker_symbol(x, p) == 1
def _method_pt1(num_bits, k, D, y): a = Integer(-D * y**2) R = PolynomialRing(ZZ, 'x') f = R.cyclotomic_polynomial(k)(x - 1).polynomial(base_ring=R) g = (a + (x - 2)**2).polynomial(base_ring=R) r = Integer(f.resultant(g)) if (Mod(r, k) == 1) and r > 2**(num_bits - 1) and utils.is_suitable_r( r): # found a valid r, so use it F = GF(r) f = f.change_ring(F) g = g.change_ring(F) t = Integer(f.gcd(g).any_root()) return t, r else: return 0, 0
def conductor(self): cond = Integer(1) number = self.number for p, e in self.modfactor(): mp = Mod(number, p**e) if mp == 1: continue if p == 2: cond = 4 if number % 4 == 3: mp = -mp else: cond *= p mp = mp**(p - 1) while mp != 1: cond *= p mp = mp**p return cond
def dirichlet_character_conrey_galois_orbit_embeddings(N, xi): r""" Returns a dictionary that maps the Conrey numbers of the Dirichlet characters in the Galois orbit of x to the powers of $\zeta_{\phi(N)}$ so that the corresponding embeddings map the labels. Let $\zeta_{\phi(N)}$ be the generator of the cyclotomic field of $N$-th roots of unity which is the base field for the coefficients of a modular form contained in the database. Considering the space $S_k(N,\chi)$, where $\chi = \chi_N(m, \cdot)$, if embeddings()[m] = n, then $\zeta_{\phi(N)}$ is mapped to $\zeta_{\phi(N)}^n = \mathrm{exp}(2\pi i n /\phi(N))$. """ embeddings = {} base_number = 0 base_number = xi embeddings[base_number] = 1 for n in range(2, N): if gcd(n, N) == 1: embeddings[Mod(base_number, N)**n] = n return embeddings
def multiplicative_order(self): return Mod(self.number, self.modulus).multiplicative_order()
def NChars(N): return ZZ( sum([ 1 / euler_phi(Mod(i, N).multiplicative_order()) for i in range(N) if gcd(i, N) == 1 ]))