def velu_walk(E, l, lam, k): q = E.base_field().order() lam = GF(l)(lam) r = lam.multiplicative_order() mu = GF(l)((lam ** (-1)) * q) r_mu = mu.multiplicative_order() if k < 0: return velu_walk(E.quadratic_twist(), l, -mu, -k) if r_mu == r: print("Invalid parameters") return if r_mu < r: return velu_walk(E.quadratic_twist(), l, -lam, k) t = E.trace_of_frobenius() order = rec_order(q, t, r) cur = extend_field(E, r) for i in range(k): cur = velu_step(cur, l, lam, order, q) cur = EllipticCurve_from_j(GF(q)(cur.j_invariant())) return cur
def walk_the_crater(E,l,lam): k = E.base_field() q = k.order() lam = GF(l)(lam) r = lam.multiplicative_order() t = E.trace_of_frobenius() order = rec_order(q, t, r) cur = extend_field(E, r) crater = [E.j_invariant()] cur = velu_step(cur, l, lam, order, q) while k(cur.j_invariant())!=E.j_invariant(): crater.append(k(cur.j_invariant())) cur = velu_step(cur, l, lam, order, q) return crater
def elkies_first_step(E, l, lam): q = E.base_field().order() lam = GF(l)(lam) Phi = ClassicalModularPolynomialDatabase()[l] x = PolynomialRing(E.base_field(), 'x').gen() f = Phi(x, E.j_invariant()) j_1, j_2 = f.roots()[0][0], f.roots()[1][0] E1 = elkies_mod_poly(E, j_1, l) try: I = EllipticCurveIsogeny(E, None, E1, l) except: I = l_isogeny(E, E1, l) r = lam.multiplicative_order() k = GF(q ** r) ext = extend_field(E, r) try: P = ext.lift_x(I.kernel_polynomial().any_root(k)) except: return j_2 if ext(P[0] ** q, P[1] ** q) == Integer(lam) * P: return j_1 else: return j_2