def random_mersenne_prime(): while True: p = random_prime(100, 200) m = 2^p - 1 if is_prime(m): return m #p = random_mersenne_prime() p = 8191 # -1 should not be a quadratic residue modulo p assert legendre_symbol(-1, p) == -1 assert p % 4 == 3 F = GF(p) R. = F[] K. = F.extension(x^2 + 1) def get_point(t): x = (1 - t^2)/(1 + t^2) y = 2*t / (1 + t^2) return (x, y) (p1_x, p1_y) = get_point(K(3)) assert p1_x^2 + p1_y^2 == 1 z = p1_x + i*p1_y (p2_x, p2_y) = get_point(K(7)) assert p2_x^2 + p2_y^2 == 1 w = p2_x + i*p2_y def abs(z): return z[0]^2 + z[1]^2 # z and w are now elements of F_p(i) which is a field assert abs(z) == 1 assert abs(w) == 1 assert abs(z * w) == 1 # We can also construct the inverse def conjugate(z): return z[0] - i*z[1] # Remember that (x + iy)(x - iy) = x^2 - i^2 y^2 = x^2 + y^2 assert z * conjugate(z) in F # Now we find the multiplicative inverse z_inv = conjugate(z) / (z * conjugate(z)) assert z * z_inv == 1 # Size of K is p^2 assert len(K) == p^2 # Because in sage we cannot construct a homomorphism to GF(p^2) directly # we instead construct the isomorphic field extension, and use that instead. Fp2. = GF(p^2) conway_fp2 = a.minimal_polynomial() L. = F.extension(conway_fp2(x=x)) y = L.multiplicative_generator() phi = K.hom([y^(y.multiplicative_order()/i.multiplicative_order())]) # K ≌ GF(p^2) assert phi.is_injective() and phi.is_surjective() assert a.multiplicative_order() == p^2 - 1 g_K = phi.inverse()(y) g1 = g_K^int((p^2 - 1)/(p + 1)) assert abs(g1) == 1 g2 = K.multiplicative_generator() g2 = g2^(p - 1) assert abs(g2) == 1 # bug in sage where .unit_group is missing # https://ask.sagemath.org/question/62822/make-morphism-from-gfp2s-multiplicative-group-to-gfps-multiplicative-group/ C = AbelianGroup([p + 1]) g, = C.gens() while True: print(f"Group of order = {g.order()}") for C2 in C.subgroups(): print(f" {C2}") print() if g.order() == 1: break # For some annoying reason, I cannot iterate on subgroups # C = C.subgroup([g^2]) # Trying to get the subgroup of this will give me some error. # Lets just construct it manually. C = AbelianGroup([(g^2).order()]) g, = C.gens()