circle-stark.sage 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. def random_mersenne_prime():
  2. while True:
  3. p = random_prime(100, 200)
  4. m = 2^p - 1
  5. if is_prime(m):
  6. return m
  7. #p = random_mersenne_prime()
  8. p = 8191
  9. # -1 should not be a quadratic residue modulo p
  10. assert legendre_symbol(-1, p) == -1
  11. assert p % 4 == 3
  12. F = GF(p)
  13. R.<x> = F[]
  14. K.<i> = F.extension(x^2 + 1)
  15. def get_point(t):
  16. x = (1 - t^2)/(1 + t^2)
  17. y = 2*t / (1 + t^2)
  18. return (x, y)
  19. (p1_x, p1_y) = get_point(K(3))
  20. assert p1_x^2 + p1_y^2 == 1
  21. z = p1_x + i*p1_y
  22. (p2_x, p2_y) = get_point(K(7))
  23. assert p2_x^2 + p2_y^2 == 1
  24. w = p2_x + i*p2_y
  25. def abs(z):
  26. return z[0]^2 + z[1]^2
  27. # z and w are now elements of F_p(i) which is a field
  28. assert abs(z) == 1
  29. assert abs(w) == 1
  30. assert abs(z * w) == 1
  31. # We can also construct the inverse
  32. def conjugate(z):
  33. return z[0] - i*z[1]
  34. # Remember that (x + iy)(x - iy) = x^2 - i^2 y^2 = x^2 + y^2
  35. assert z * conjugate(z) in F
  36. # Now we find the multiplicative inverse
  37. z_inv = conjugate(z) / (z * conjugate(z))
  38. assert z * z_inv == 1
  39. # Size of K is p^2
  40. assert len(K) == p^2
  41. # Because in sage we cannot construct a homomorphism to GF(p^2) directly
  42. # we instead construct the isomorphic field extension, and use that instead.
  43. Fp2.<a> = GF(p^2)
  44. conway_fp2 = a.minimal_polynomial()
  45. L.<j> = F.extension(conway_fp2(x=x))
  46. y = L.multiplicative_generator()
  47. phi = K.hom([y^(y.multiplicative_order()/i.multiplicative_order())])
  48. # K ≌ GF(p^2)
  49. assert phi.is_injective() and phi.is_surjective()
  50. assert a.multiplicative_order() == p^2 - 1
  51. g_K = phi.inverse()(y)
  52. g1 = g_K^int((p^2 - 1)/(p + 1))
  53. assert abs(g1) == 1
  54. g2 = K.multiplicative_generator()
  55. g2 = g2^(p - 1)
  56. assert abs(g2) == 1
  57. # bug in sage where .unit_group is missing
  58. # https://ask.sagemath.org/question/62822/make-morphism-from-gfp2s-multiplicative-group-to-gfps-multiplicative-group/
  59. C = AbelianGroup([p + 1])
  60. g, = C.gens()
  61. while True:
  62. print(f"Group of order = {g.order()}")
  63. for C2 in C.subgroups():
  64. print(f" {C2}")
  65. print()
  66. if g.order() == 1:
  67. break
  68. # For some annoying reason, I cannot iterate on subgroups
  69. # C = C.subgroup([g^2])
  70. # Trying to get the subgroup of this will give me some error.
  71. # Lets just construct it manually.
  72. C = AbelianGroup([(g^2).order()])
  73. g, = C.gens()