passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +721 -0
  40. sage/modular/abvar/homspace.py +989 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2020 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1070 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +817 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +991 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,3249 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ """
3
+ Elliptic curves over finite fields
4
+
5
+ AUTHORS:
6
+
7
+ - William Stein (2005): Initial version
8
+
9
+ - Robert Bradshaw et al....
10
+
11
+ - John Cremona (2008-02): Point counting and group structure for
12
+ non-prime fields, Frobenius endomorphism and order, elliptic logs
13
+
14
+ - Mariah Lenox (2011-03): Added ``set_order`` method
15
+
16
+ - Lorenz Panny, John Cremona (2023-02): ``.twists()``
17
+
18
+ - Lorenz Panny (2023): ``special_supersingular_curve()``
19
+
20
+ - Martin Grenouilloux, Gareth Ma (2024-09): ``EllipticCurve_with_prime_order()``
21
+ """
22
+
23
+ # ****************************************************************************
24
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
25
+ #
26
+ # This program is free software: you can redistribute it and/or modify
27
+ # it under the terms of the GNU General Public License as published by
28
+ # the Free Software Foundation, either version 2 of the License, or
29
+ # (at your option) any later version.
30
+ # https://www.gnu.org/licenses/
31
+ # ****************************************************************************
32
+
33
+ import sage.groups.generic as generic
34
+
35
+ from sage.arith.functions import lcm
36
+ from sage.arith.misc import binomial, GCD as gcd
37
+ from sage.groups.additive_abelian.additive_abelian_wrapper import AdditiveAbelianGroupWrapper
38
+ from sage.misc.cachefunc import cached_method
39
+ from sage.rings.finite_rings.finite_field_base import FiniteField
40
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
41
+ from sage.rings.integer import Integer
42
+ from sage.rings.integer_ring import ZZ
43
+ from sage.rings.polynomial.polynomial_ring import polygen
44
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
45
+ from sage.schemes.curves.projective_curve import Hasse_bounds, ProjectivePlaneCurve_finite_field
46
+ from sage.structure.element import Element
47
+
48
+ from . import ell_point
49
+ from .constructor import EllipticCurve
50
+ from .ell_field import EllipticCurve_field
51
+
52
+
53
+ class EllipticCurve_finite_field(EllipticCurve_field, ProjectivePlaneCurve_finite_field):
54
+ r"""
55
+ Elliptic curve over a finite field.
56
+
57
+ EXAMPLES::
58
+
59
+ sage: EllipticCurve(GF(101),[2,3])
60
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field of size 101
61
+
62
+ sage: # needs sage.rings.finite_rings
63
+ sage: F = GF(101^2, 'a')
64
+ sage: EllipticCurve([F(2),F(3)])
65
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Finite Field in a of size 101^2
66
+
67
+ Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
68
+ "elliptic curve over a finite field"::
69
+
70
+ sage: F = Zmod(101)
71
+ sage: EllipticCurve(F, [2, 3])
72
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
73
+ sage: E = EllipticCurve([F(2), F(3)])
74
+ sage: type(E)
75
+ <class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
76
+ sage: E.category()
77
+ Category of abelian varieties over Ring of integers modulo 101
78
+
79
+ Elliptic curves over `\ZZ/N\ZZ` with `N` composite are of type
80
+ "generic elliptic curve"::
81
+
82
+ sage: F = Zmod(95)
83
+ sage: EllipticCurve(F, [2, 3])
84
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
85
+ sage: E = EllipticCurve([F(2), F(3)])
86
+ sage: type(E)
87
+ <class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>
88
+ sage: E.category()
89
+ Category of schemes over Ring of integers modulo 95
90
+ sage: TestSuite(E).run(skip=["_test_elements"])
91
+ """
92
+
93
+ _point = ell_point.EllipticCurvePoint_finite_field
94
+
95
+ def plot(self, *args, **kwds):
96
+ """
97
+ Draw a graph of this elliptic curve over a prime finite field.
98
+
99
+ INPUT:
100
+
101
+ - ``*args``, ``**kwds`` -- all other options are passed
102
+ to the circle graphing primitive
103
+
104
+ EXAMPLES::
105
+
106
+ sage: E = EllipticCurve(FiniteField(17), [0,1])
107
+ sage: P = plot(E, rgbcolor=(0,0,1)) # needs sage.plot
108
+ """
109
+ R = self.base_ring()
110
+ if not R.is_prime_field():
111
+ raise NotImplementedError
112
+
113
+ from sage.plot.point import points
114
+
115
+ return points([P[0:2] for P in self.points() if not P.is_zero()], *args, **kwds)
116
+
117
+ def _points_via_group_structure(self):
118
+ r"""
119
+ Return a list of all the points on the curve using the group structure.
120
+
121
+ For cyclic groups with generator `G` of order `n`, the set of points
122
+ is computed from `[x]G` for `x \in [0, n - 1]` requiring `n - 2`
123
+ additions on the curve.
124
+
125
+ For non-cyclic groups, first two cyclic subgroups `H_i` are computed as
126
+ above from `[x]G_i` for `x \in [0, n_i]` requiring `n_1 + n_2 - 4`
127
+ additions. The set of all points is returned as the cartesian product
128
+ of these two cyclic groups.
129
+
130
+ When the group is trivial, only the point at infinity is returned.
131
+
132
+ EXAMPLES::
133
+
134
+ sage: S = EllipticCurve(GF(97),[2,3])._points_via_group_structure()
135
+ sage: len(S)
136
+ 100
137
+
138
+ See :issue:`4687`, where the following example did not work::
139
+
140
+ sage: E = EllipticCurve(GF(2),[0, 0, 1, 1, 1])
141
+ sage: E.points()
142
+ [(0 : 1 : 0)]
143
+
144
+ ::
145
+
146
+ sage: E = EllipticCurve(GF(2),[0, 0, 1, 0, 1])
147
+ sage: E.points()
148
+ [(0 : 1 : 0), (1 : 0 : 1), (1 : 1 : 1)]
149
+
150
+ ::
151
+
152
+ sage: # needs sage.rings.finite_rings
153
+ sage: E = EllipticCurve(GF(4,'a'),[0, 0, 1, 0, 1])
154
+ sage: E.points()
155
+ [(0 : 1 : 0), (0 : a : 1), (0 : a + 1 : 1), (1 : 0 : 1), (1 : 1 : 1), (a : 0 : 1), (a : 1 : 1), (a + 1 : 0 : 1), (a + 1 : 1 : 1)]
156
+ """
157
+ # TODO, eliminate when polynomial calling is fast
158
+ # 11-03-2024 - G. Pope : it is not clear to me what the above TODO references
159
+
160
+ # Compute the generators of the abelian group of the curve
161
+ G = self.abelian_group()
162
+ gens = [x.element() for x in G.gens()]
163
+
164
+ # Zero element of the group
165
+ zero = self(0)
166
+
167
+ # Trivial group, return the identity element only
168
+ if len(gens) == 0:
169
+ return [zero]
170
+
171
+ def __multiples(G):
172
+ """
173
+ Compute the list of points [i]G for i in [0, G.order())
174
+ """
175
+ H = [zero, G]
176
+ P = G
177
+ for _ in range(2, G.order()):
178
+ P += G
179
+ H.append(P)
180
+ return H
181
+
182
+ # Collect all multiples of the generator
183
+ H1 = __multiples(gens[0])
184
+
185
+ # Cyclic case, we now have all points
186
+ if len(gens) == 1:
187
+ return H1
188
+
189
+ # Non-cyclic case we generate the second set of points and compute
190
+ # the entire set of points from the Cartesian product
191
+ H2 = __multiples(gens[1])
192
+ return [P + Q for P in H1 for Q in H2]
193
+
194
+ def points(self):
195
+ r"""
196
+ Return all rational points on this elliptic curve. The list of points is cached
197
+ so subsequent calls are free.
198
+
199
+ EXAMPLES::
200
+
201
+ sage: p = 5
202
+ sage: F = GF(p)
203
+ sage: E = EllipticCurve(F, [1, 3])
204
+ sage: len(E.points())
205
+ 4
206
+ sage: E.order()
207
+ 4
208
+ sage: E.points()
209
+ [(0 : 1 : 0), (1 : 0 : 1), (4 : 1 : 1), (4 : 4 : 1)]
210
+
211
+ ::
212
+
213
+ sage: K = GF((p, 2), 'a')
214
+ sage: E = E.change_ring(K)
215
+ sage: len(E.points())
216
+ 32
217
+ sage: E.order()
218
+ 32
219
+ sage: w = E.points(); w
220
+ [(0 : 1 : 0), (0 : 2*a + 4 : 1), (0 : 3*a + 1 : 1), (1 : 0 : 1), (2 : 2*a + 4 : 1), (2 : 3*a + 1 : 1), (3 : 2*a + 4 : 1), (3 : 3*a + 1 : 1), (4 : 1 : 1), (4 : 4 : 1), (a : 1 : 1), (a : 4 : 1), (a + 2 : a + 1 : 1), (a + 2 : 4*a + 4 : 1), (a + 3 : a : 1), (a + 3 : 4*a : 1), (a + 4 : 0 : 1), (2*a : 2*a : 1), (2*a : 3*a : 1), (2*a + 4 : a + 1 : 1), (2*a + 4 : 4*a + 4 : 1), (3*a + 1 : a + 3 : 1), (3*a + 1 : 4*a + 2 : 1), (3*a + 2 : 2*a + 3 : 1), (3*a + 2 : 3*a + 2 : 1), (4*a : 0 : 1), (4*a + 1 : 1 : 1), (4*a + 1 : 4 : 1), (4*a + 3 : a + 3 : 1), (4*a + 3 : 4*a + 2 : 1), (4*a + 4 : a + 4 : 1), (4*a + 4 : 4*a + 1 : 1)]
221
+
222
+ Note that the returned list is an immutable sorted Sequence::
223
+
224
+ sage: w[0] = 9
225
+ Traceback (most recent call last):
226
+ ...
227
+ ValueError: object is immutable; please change a copy instead.
228
+ """
229
+ if hasattr(self, "__points"):
230
+ return self.__points
231
+
232
+ from sage.structure.sequence import Sequence
233
+ v = self._points_via_group_structure()
234
+ v.sort()
235
+ self.__points = Sequence(v, immutable=True)
236
+ return self.__points
237
+
238
+ rational_points = points
239
+
240
+ def count_points(self, n=1):
241
+ """
242
+ Return the cardinality of this elliptic curve over the base field or extensions.
243
+
244
+ INPUT:
245
+
246
+ - ``n`` -- positive integer
247
+
248
+ OUTPUT: if `n=1`, returns the cardinality of the curve over its base field
249
+
250
+ If `n>1`, returns a list `[c_1, c_2, ..., c_n]` where `c_d` is
251
+ the cardinality of the curve over the extension of degree `d`
252
+ of its base field.
253
+
254
+ EXAMPLES::
255
+
256
+ sage: p = 101
257
+ sage: F = GF(p)
258
+ sage: E = EllipticCurve(F, [2,3])
259
+ sage: E.count_points(1)
260
+ 96
261
+ sage: E.count_points(5)
262
+ [96, 10368, 1031904, 104053248, 10509895776]
263
+
264
+ ::
265
+
266
+ sage: # needs sage.rings.finite_rings
267
+ sage: F.<a> = GF(p^2)
268
+ sage: E = EllipticCurve(F, [a,a])
269
+ sage: E.cardinality()
270
+ 10295
271
+ sage: E.count_points()
272
+ 10295
273
+ sage: E.count_points(1)
274
+ 10295
275
+ sage: E.count_points(5)
276
+ [10295, 104072155, 1061518108880, 10828567126268595, 110462212555439192375]
277
+ """
278
+ try:
279
+ n = Integer(n)
280
+ except TypeError:
281
+ raise TypeError("n must be a positive integer")
282
+
283
+ if n < 1:
284
+ raise ValueError("n must be a positive integer")
285
+
286
+ if n == 1:
287
+ return self.cardinality()
288
+
289
+ return [self.cardinality(extension_degree=i) for i in range(1, n + 1)]
290
+
291
+ def trace_of_frobenius(self):
292
+ r"""
293
+ Return the trace of Frobenius acting on this elliptic curve.
294
+
295
+ .. NOTE::
296
+
297
+ This computes the curve cardinality, which may be
298
+ time-consuming.
299
+
300
+ EXAMPLES::
301
+
302
+ sage: E = EllipticCurve(GF(101),[2,3])
303
+ sage: E.trace_of_frobenius()
304
+ 6
305
+ sage: E = EllipticCurve(GF(11^5,'a'),[2,5]) # needs sage.rings.finite_rings
306
+ sage: E.trace_of_frobenius() # needs sage.rings.finite_rings
307
+ 802
308
+
309
+ The following shows that the issue from :issue:`2849` is fixed::
310
+
311
+ sage: E = EllipticCurve(GF(3^5,'a'),[-1,-1]) # needs sage.rings.finite_rings
312
+ sage: E.trace_of_frobenius() # needs sage.rings.finite_rings
313
+ -27
314
+ """
315
+ return 1 + self.base_field().order() - self.cardinality()
316
+
317
+ def cardinality(self, algorithm=None, extension_degree=1):
318
+ r"""
319
+ Return the number of points on this elliptic curve.
320
+
321
+ INPUT:
322
+
323
+ - ``algorithm`` -- (optional) string:
324
+
325
+ - ``'pari'`` -- use the PARI C-library function ``ellcard``
326
+
327
+ - ``'bsgs'`` -- use the baby-step giant-step method as
328
+ implemented in Sage, with the Cremona-Sutherland version
329
+ of Mestre's trick
330
+
331
+ - ``'exhaustive'`` -- naive point counting
332
+
333
+ - ``'subfield'`` -- reduce to a smaller field, provided that
334
+ the j-invariant lies in a subfield
335
+
336
+ - ``'all'`` -- compute cardinality with both ``'pari'`` and
337
+ ``'bsgs'``; return result if they agree or raise a
338
+ :exc:`AssertionError` if they do not
339
+
340
+ - ``extension_degree`` -- integer `d` (default: 1); if the
341
+ base field is `\GF{q}`, return the cardinality of ``self``
342
+ over the extension `\GF{q^d}` of degree `d`
343
+
344
+ OUTPUT:
345
+
346
+ The order of the group of rational points of ``self`` over its
347
+ base field, or over an extension field of degree `d` as above.
348
+ The result is cached.
349
+
350
+ EXAMPLES::
351
+
352
+ sage: # needs sage.rings.finite_rings
353
+ sage: EllipticCurve(GF(4, 'a'), [1,2,3,4,5]).cardinality()
354
+ 8
355
+ sage: k.<a> = GF(3^3)
356
+ sage: l = [a^2 + 1, 2*a^2 + 2*a + 1, a^2 + a + 1, 2, 2*a]
357
+ sage: EllipticCurve(k,l).cardinality()
358
+ 29
359
+
360
+ ::
361
+
362
+ sage: # needs sage.rings.finite_rings
363
+ sage: l = [1, 1, 0, 2, 0]
364
+ sage: EllipticCurve(k, l).cardinality()
365
+ 38
366
+
367
+ An even bigger extension (which we check against Magma)::
368
+
369
+ sage: # needs sage.rings.finite_rings
370
+ sage: EllipticCurve(GF(3^100, 'a'), [1,2,3,4,5]).cardinality()
371
+ 515377520732011331036459693969645888996929981504
372
+ sage: magma.eval("Order(EllipticCurve([GF(3^100)|1,2,3,4,5]))") # optional - magma
373
+ '515377520732011331036459693969645888996929981504'
374
+
375
+ ::
376
+
377
+ sage: EllipticCurve(GF(10007), [1,2,3,4,5]).cardinality()
378
+ 10076
379
+ sage: EllipticCurve(GF(10007), [1,2,3,4,5]).cardinality(algorithm='pari')
380
+ 10076
381
+ sage: EllipticCurve(GF(next_prime(10**20)), [1,2,3,4,5]).cardinality()
382
+ 100000000011093199520
383
+
384
+ The cardinality is cached::
385
+
386
+ sage: # needs sage.rings.finite_rings
387
+ sage: E = EllipticCurve(GF(3^100, 'a'), [1,2,3,4,5])
388
+ sage: E.cardinality() is E.cardinality()
389
+ True
390
+
391
+ The following is very fast since the curve is actually defined
392
+ over the prime field::
393
+
394
+ sage: # needs sage.rings.finite_rings
395
+ sage: k.<a> = GF(11^100)
396
+ sage: E1 = EllipticCurve(k, [3,3])
397
+ sage: N1 = E1.cardinality(algorithm='subfield'); N1
398
+ 137806123398222701841183371720896367762643312000384671846835266941791510341065565176497846502742959856128
399
+ sage: E1.cardinality_pari() == N1
400
+ True
401
+ sage: E2 = E1.quadratic_twist()
402
+ sage: N2 = E2.cardinality(algorithm='subfield'); N2
403
+ 137806123398222701841183371720896367762643312000384656816094284101308193849980588362304472492174093035876
404
+ sage: E2.cardinality_pari() == N2
405
+ True
406
+ sage: N1 + N2 == 2*(k.cardinality() + 1)
407
+ True
408
+
409
+ We can count points over curves defined as a reduction::
410
+
411
+ sage: # needs sage.rings.number_field
412
+ sage: x = polygen(QQ)
413
+ sage: K.<w> = NumberField(x^2 + x + 1)
414
+ sage: EK = EllipticCurve(K, [0, 0, w, 2, 1])
415
+ sage: E = EK.base_extend(K.residue_field(2))
416
+ sage: E
417
+ Elliptic Curve defined by y^2 + wbar*y = x^3 + 1
418
+ over Residue field in wbar of Fractional ideal (2)
419
+ sage: E.cardinality()
420
+ 7
421
+ sage: E = EK.base_extend(K.residue_field(w - 1))
422
+ sage: E.abelian_group()
423
+ Trivial group embedded in Abelian group of points on Elliptic Curve defined
424
+ by y^2 + y = x^3 + 2*x + 1 over Residue field of Fractional ideal (w - 1)
425
+
426
+ ::
427
+
428
+ sage: R.<x> = GF(17)[]
429
+ sage: pol = R.irreducible_element(5)
430
+ sage: k.<a> = R.residue_field(pol)
431
+ sage: E = EllipticCurve(R, [1, x]).base_extend(k)
432
+ sage: E
433
+ Elliptic Curve defined by y^2 = x^3 + x + a
434
+ over Residue field in a of Principal ideal (x^5 + x + 14)
435
+ of Univariate Polynomial Ring in x over Finite Field of size 17
436
+ sage: E.cardinality()
437
+ 1421004
438
+
439
+ TESTS::
440
+
441
+ sage: EllipticCurve(GF(10009), [1,2,3,4,5]).cardinality(algorithm='foobar')
442
+ Traceback (most recent call last):
443
+ ...
444
+ ValueError: algorithm 'foobar' is not known
445
+
446
+ If the cardinality has already been computed, then the ``algorithm``
447
+ keyword is ignored::
448
+
449
+ sage: E = EllipticCurve(GF(10007), [1,2,3,4,5])
450
+ sage: E.cardinality(algorithm='pari')
451
+ 10076
452
+ sage: E.cardinality(algorithm='foobar')
453
+ 10076
454
+
455
+ Check that a bug noted at :issue:`15667` is fixed::
456
+
457
+ sage: # needs sage.rings.finite_rings
458
+ sage: F.<a> = GF(3^6)
459
+ sage: EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1]).cardinality()
460
+ 784
461
+ """
462
+ if extension_degree > 1:
463
+ # A recursive call to cardinality() with
464
+ # extension_degree=1, which will cache the cardinality, is
465
+ # made by the call to frobenius_order() here:
466
+ frob = self.frobenius() ** extension_degree - 1
467
+ R = self.frobenius_order()
468
+ if R.degree() == 1:
469
+ return frob * frob
470
+ else:
471
+ return frob.norm()
472
+
473
+ # We need manual caching (not @cached_method) since various
474
+ # other methods refer to this _order attribute, in particular
475
+ # self.set_order().
476
+ try:
477
+ return self._order
478
+ except AttributeError:
479
+ pass
480
+
481
+ jpol = None
482
+ if algorithm is None:
483
+ # Check for j in subfield
484
+ jpol = self.j_invariant().minimal_polynomial()
485
+ if jpol.degree() < self.base_field().degree():
486
+ algorithm = "subfield"
487
+ else:
488
+ algorithm = "pari"
489
+
490
+ if algorithm == "pari":
491
+ N = self.cardinality_pari()
492
+ elif algorithm == "subfield":
493
+ if jpol is None:
494
+ jpol = self.j_invariant().minimal_polynomial()
495
+ N = self._cardinality_subfield(jpol)
496
+ elif algorithm == "bsgs":
497
+ N = self.cardinality_bsgs()
498
+ elif algorithm == "exhaustive":
499
+ N = self.cardinality_exhaustive()
500
+ elif algorithm == "all":
501
+ N = self.cardinality_pari()
502
+ N2 = self.cardinality_bsgs()
503
+ if N != N2:
504
+ raise AssertionError("cardinality with pari=%s but with bsgs=%s" % (N, N2))
505
+ else:
506
+ raise ValueError("algorithm {!r} is not known".format(algorithm))
507
+
508
+ self._order = N
509
+ return N
510
+
511
+ from .cardinality import (cardinality_bsgs,
512
+ cardinality_exhaustive, _cardinality_subfield)
513
+
514
+ order = cardinality # alias
515
+
516
+ @cached_method
517
+ def multiplication_by_p_isogeny(self):
518
+ r"""
519
+ Return the multiplication-by-`p` isogeny.
520
+
521
+ EXAMPLES::
522
+
523
+ sage: p = 23
524
+ sage: K.<a> = GF(p^3)
525
+ sage: E = EllipticCurve(j=K.random_element())
526
+ sage: phi = E.multiplication_by_p_isogeny()
527
+ sage: assert phi.degree() == p**2
528
+ sage: P = E.random_element()
529
+ sage: assert phi(P) == P * p
530
+ """
531
+ frob = self.frobenius_isogeny()
532
+ return frob.dual() * frob
533
+
534
+ def frobenius_polynomial(self):
535
+ r"""
536
+ Return the characteristic polynomial of Frobenius.
537
+
538
+ The Frobenius endomorphism of the elliptic curve has quadratic
539
+ characteristic polynomial. In most cases this is irreducible and
540
+ defines an imaginary quadratic order; for some supersingular
541
+ curves, Frobenius is an integer a and the polynomial is
542
+ `(x-a)^2`.
543
+
544
+ .. NOTE::
545
+
546
+ This computes the curve cardinality, which may be
547
+ time-consuming.
548
+
549
+ EXAMPLES::
550
+
551
+ sage: E = EllipticCurve(GF(11),[3,3])
552
+ sage: E.frobenius_polynomial()
553
+ x^2 - 4*x + 11
554
+
555
+ For some supersingular curves, Frobenius is in Z and the polynomial
556
+ is a square::
557
+
558
+ sage: # needs sage.rings.finite_rings
559
+ sage: E = EllipticCurve(GF(25,'a'),[0,0,0,0,1])
560
+ sage: E.frobenius_polynomial().factor()
561
+ (x + 5)^2
562
+ """
563
+ x = polygen(ZZ)
564
+ return x**2-self.trace_of_frobenius()*x+self.base_field().cardinality()
565
+
566
+ def frobenius_order(self):
567
+ r"""
568
+ Return the quadratic order Z[phi] where phi is the Frobenius
569
+ endomorphism of the elliptic curve.
570
+
571
+ .. NOTE::
572
+
573
+ This computes the curve cardinality, which may be
574
+ time-consuming.
575
+
576
+ .. SEEALSO::
577
+
578
+ :meth:`endomorphism_order`
579
+
580
+ EXAMPLES::
581
+
582
+ sage: E = EllipticCurve(GF(11),[3,3])
583
+ sage: E.frobenius_order()
584
+ Order of conductor 2 generated by pi
585
+ in Number Field in pi with defining polynomial x^2 - 4*x + 11
586
+
587
+ For some supersingular curves, Frobenius is in `\ZZ` and the Frobenius
588
+ order is `\ZZ`::
589
+
590
+ sage: # needs sage.rings.finite_rings
591
+ sage: E = EllipticCurve(GF(25,'a'),[0,0,0,0,1])
592
+ sage: R = E.frobenius_order()
593
+ sage: R
594
+ Order generated by []
595
+ in Number Field in pi with defining polynomial x + 5
596
+ sage: R.degree()
597
+ 1
598
+ """
599
+ f = self.frobenius_polynomial().factor()[0][0]
600
+ return ZZ.extension(f, names='pi')
601
+
602
+ def frobenius(self):
603
+ r"""
604
+ Return the frobenius of ``self`` as an element of a quadratic order.
605
+
606
+ .. NOTE::
607
+
608
+ This computes the curve cardinality, which may be
609
+ time-consuming.
610
+
611
+ Frobenius is only determined up to conjugacy.
612
+
613
+ EXAMPLES::
614
+
615
+ sage: E = EllipticCurve(GF(11),[3,3])
616
+ sage: E.frobenius()
617
+ pi
618
+ sage: E.frobenius().minpoly()
619
+ x^2 - 4*x + 11
620
+
621
+ For some supersingular curves, Frobenius is in Z::
622
+
623
+ sage: # needs sage.rings.finite_rings
624
+ sage: E = EllipticCurve(GF(25,'a'),[0,0,0,0,1])
625
+ sage: E.frobenius()
626
+ -5
627
+ """
628
+ R = self.frobenius_order()
629
+ if R.degree() == 1:
630
+ return self.frobenius_polynomial().roots(multiplicities=False)[0]
631
+ else:
632
+ return R.gen(1)
633
+
634
+ def frobenius_endomorphism(self):
635
+ r"""
636
+ Return the `q`-power Frobenius endomorphism of this elliptic
637
+ curve, where `q` is the cardinality of the (finite) base field.
638
+
639
+ EXAMPLES::
640
+
641
+ sage: # needs sage.rings.finite_rings
642
+ sage: F.<t> = GF(11^4)
643
+ sage: E = EllipticCurve([t,t])
644
+ sage: E.frobenius_endomorphism()
645
+ Frobenius endomorphism of degree 14641 = 11^4:
646
+ From: Elliptic Curve defined by y^2 = x^3 + t*x + t over Finite Field in t of size 11^4
647
+ To: Elliptic Curve defined by y^2 = x^3 + t*x + t over Finite Field in t of size 11^4
648
+ sage: E.frobenius_endomorphism() == E.frobenius_isogeny(4)
649
+ True
650
+
651
+ .. SEEALSO::
652
+
653
+ :meth:`~sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic.frobenius_isogeny`
654
+ """
655
+ return self.frobenius_isogeny(self.base_field().degree())
656
+
657
+ def frobenius_discriminant(self):
658
+ r"""
659
+ Return the discriminant of the ring `\ZZ[\pi_E]` where `\pi_E` is the Frobenius endomorphism.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: # needs sage.rings.finite_rings
664
+ sage: F.<t> = GF(11^4)
665
+ sage: E = EllipticCurve([t,t])
666
+ sage: E.frobenius_discriminant()
667
+ -57339
668
+ """
669
+ return self.frobenius_polynomial().discriminant()
670
+
671
+ def cardinality_pari(self):
672
+ r"""
673
+ Return the cardinality of ``self`` using PARI.
674
+
675
+ This uses :pari:`ellcard`.
676
+
677
+ EXAMPLES::
678
+
679
+ sage: p = next_prime(10^3)
680
+ sage: E = EllipticCurve(GF(p),[3,4])
681
+ sage: E.cardinality_pari()
682
+ 1020
683
+ sage: K = GF(next_prime(10^6))
684
+ sage: E = EllipticCurve(K,[1,0,0,1,1])
685
+ sage: E.cardinality_pari()
686
+ 999945
687
+
688
+ Since :issue:`16931`, this now works over finite fields which
689
+ are not prime fields::
690
+
691
+ sage: # needs sage.rings.finite_rings
692
+ sage: k.<a> = GF(7^3)
693
+ sage: E = EllipticCurve_from_j(a)
694
+ sage: E.cardinality_pari()
695
+ 318
696
+ sage: K.<a> = GF(3^20)
697
+ sage: E = EllipticCurve(K,[1,0,0,1,a])
698
+ sage: E.cardinality_pari()
699
+ 3486794310
700
+
701
+ TESTS::
702
+
703
+ sage: E.cardinality_pari().parent() # needs sage.rings.finite_rings
704
+ Integer Ring
705
+ """
706
+ return Integer(self.__pari__().ellcard())
707
+
708
+ @cached_method
709
+ def gens(self) -> tuple:
710
+ r"""
711
+ Return points which generate the abelian group of points on
712
+ this elliptic curve.
713
+
714
+ The algorithm involves factoring the group order of ``self``,
715
+ but is otherwise (randomized) polynomial-time.
716
+
717
+ (The points returned by this function are not guaranteed to be
718
+ the same each time, although they should remain fixed within a
719
+ single run of Sage unless :meth:`abelian_group` is called.)
720
+
721
+ OUTPUT: a tuple of points on the curve
722
+
723
+ - if the group is trivial: an empty tuple.
724
+
725
+ - if the group is cyclic: a tuple with 1 point, a generator.
726
+
727
+ - if the group is not cyclic: a tuple with 2 points, where the
728
+ order of the first point equals the exponent of the group.
729
+
730
+ .. WARNING::
731
+
732
+ In the case of 2 generators `P` and `Q`, it is not
733
+ guaranteed that the group is the cartesian product of the 2
734
+ cyclic groups `\langle P \rangle` and `\langle Q \rangle`.
735
+ In other words, the order of `Q` is not as small as possible.
736
+ If you really need a basis (rather than just a generating set)
737
+ of the group, use :meth:`abelian_group`.
738
+
739
+ EXAMPLES::
740
+
741
+ sage: E = EllipticCurve(GF(11),[2,5])
742
+ sage: P = E.gens()[0]; P # random
743
+ (0 : 7 : 1)
744
+ sage: E.cardinality(), P.order()
745
+ (10, 10)
746
+ sage: E = EllipticCurve(GF(41),[2,5])
747
+ sage: E.gens() # random
748
+ ((20 : 38 : 1), (25 : 31 : 1))
749
+ sage: E.cardinality()
750
+ 44
751
+
752
+ If the abelian group has been computed, return those generators
753
+ instead::
754
+
755
+ sage: E.abelian_group()
756
+ Additive abelian group isomorphic to Z/22 + Z/2
757
+ embedded in Abelian group of points on Elliptic Curve
758
+ defined by y^2 = x^3 + 2*x + 5 over Finite Field of size 41
759
+ sage: ab_gens = E.abelian_group().gens()
760
+ sage: ab_gens == E.gens()
761
+ True
762
+ sage: E.gens()[0].order()
763
+ 22
764
+ sage: E.gens()[1].order()
765
+ 2
766
+
767
+ Examples with 1 and 0 generators::
768
+
769
+ sage: # needs sage.rings.finite_rings
770
+ sage: F.<a> = GF(3^6)
771
+ sage: E = EllipticCurve([a, a+1])
772
+ sage: pts = E.gens()
773
+ sage: len(pts)
774
+ 1
775
+ sage: pts[0].order() == E.cardinality()
776
+ True
777
+
778
+ sage: E = EllipticCurve(GF(2), [0,0,1,1,1])
779
+ sage: E.gens()
780
+ ()
781
+
782
+ This works over larger finite fields where :meth:`abelian_group`
783
+ may be too expensive::
784
+
785
+ sage: # needs sage.rings.finite_rings
786
+ sage: k.<a> = GF(5^60)
787
+ sage: E = EllipticCurve([a, a])
788
+ sage: len(E.gens())
789
+ 2
790
+ sage: E.cardinality()
791
+ 867361737988403547206134229616487867594472
792
+ sage: a = E.gens()[0].order(); a # random
793
+ 433680868994201773603067114808243933797236
794
+ sage: b = E.gens()[1].order(); b # random
795
+ 30977204928157269543076222486303138128374
796
+ sage: lcm(a,b)
797
+ 433680868994201773603067114808243933797236
798
+ """
799
+ card, ords, pts = self.__pari__().ellgroup(flag=1)
800
+ if not hasattr(self, '_order'):
801
+ self._order = ZZ(card)
802
+ pts = tuple(self.point(list(P)) for P in pts)
803
+ if len(pts) >= 1:
804
+ pts[0]._order = ZZ(ords[0]) # PARI documentation: "P is of order d_1"
805
+ return pts
806
+
807
+ def __iter__(self):
808
+ """
809
+ Return an iterator through the points of this elliptic curve.
810
+
811
+ EXAMPLES::
812
+
813
+ sage: E = EllipticCurve(GF(11), [1,2])
814
+ sage: for P in E: print("{} {}".format(P, P.order()))
815
+ (0 : 1 : 0) 1
816
+ (1 : 2 : 1) 4
817
+ (1 : 9 : 1) 4
818
+ (2 : 1 : 1) 8
819
+ ...
820
+ (10 : 0 : 1) 2
821
+ """
822
+ yield from self.points()
823
+
824
+ def __getitem__(self, n):
825
+ """
826
+ Return the n-th point in ``self``'s ``__points`` list.
827
+
828
+ This enables users to iterate over the curve's point set.
829
+
830
+ EXAMPLES::
831
+
832
+ sage: E = EllipticCurve(GF(97),[2,3])
833
+ sage: S = E.points()
834
+ sage: E[10]
835
+ (10 : 76 : 1)
836
+ sage: E[15]
837
+ (17 : 10 : 1)
838
+ sage: for P in E: print(P.order())
839
+ 1
840
+ 50
841
+ 50
842
+ 50
843
+ 50
844
+ 5
845
+ 5
846
+ 50
847
+ ...
848
+ """
849
+ return self.points()[n]
850
+
851
+ @cached_method
852
+ def abelian_group(self):
853
+ r"""
854
+ Return the abelian group structure of the group of points on this
855
+ elliptic curve.
856
+
857
+ .. SEEALSO::
858
+
859
+ If you do not need the complete abelian group structure but
860
+ only generators of the group, use :meth:`gens` which can
861
+ be much faster in some cases.
862
+
863
+ This method relies on :meth:`gens`, which uses random points on the
864
+ curve and hence the generators are likely to differ from one run to
865
+ another. However, the group is cached, so the generators will not
866
+ change in any one run of Sage.
867
+
868
+ OUTPUT:
869
+
870
+ - an :class:`AdditiveAbelianGroupWrapper` object encapsulating the
871
+ abelian group of rational points on this elliptic curve
872
+
873
+ ALGORITHM:
874
+
875
+ We first call :meth:`gens` to obtain a generating set `(P,Q)`.
876
+ Letting `P` denote the point of larger order `n_1`, we extend `P`
877
+ to a basis `(P,Q')` by computing a scalar `x` such that `Q'=Q-[x]P`
878
+ has order `n_2=\#E/n_1`. Finding `x` involves a (typically easy)
879
+ discrete-logarithm computation.
880
+
881
+ The complexity of the algorithm is the cost of factoring the group
882
+ order, plus `\Theta(\sqrt{\ell})` for each prime `\ell` such that
883
+ the rational `\ell^\infty`-torsion of ``self`` is isomorphic to
884
+ `\ZZ/\ell^r\times\ZZ/\ell^s` with `r>s>0`, times a polynomial in
885
+ the logarithm of the base-field size.
886
+
887
+ AUTHORS:
888
+
889
+ - John Cremona: original implementation
890
+ - Lorenz Panny (2021): current implementation
891
+
892
+ .. SEEALSO::
893
+
894
+ :meth:`AdditiveAbelianGroupWrapper.from_generators()<sage.groups.additive_abelian.additive_abelian_wrapper.AdditiveAbelianGroupWrapper.from_generators>`
895
+
896
+ EXAMPLES::
897
+
898
+ sage: E = EllipticCurve(GF(11),[2,5])
899
+ sage: E.abelian_group()
900
+ Additive abelian group isomorphic to Z/10 embedded in
901
+ Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 2*x + 5
902
+ over Finite Field of size 11
903
+
904
+ ::
905
+
906
+ sage: E = EllipticCurve(GF(41),[2,5])
907
+ sage: E.abelian_group()
908
+ Additive abelian group isomorphic to Z/22 + Z/2 ...
909
+
910
+ ::
911
+
912
+ sage: # needs sage.rings.finite_rings
913
+ sage: F.<a> = GF(3^6,'a')
914
+ sage: E = EllipticCurve([a^4 + a^3 + 2*a^2 + 2*a, 2*a^5 + 2*a^3 + 2*a^2 + 1])
915
+ sage: E.abelian_group()
916
+ Additive abelian group isomorphic to Z/26 + Z/26 ...
917
+
918
+ ::
919
+
920
+ sage: # needs sage.rings.finite_rings
921
+ sage: F.<a> = GF(101^3,'a')
922
+ sage: E = EllipticCurve([2*a^2 + 48*a + 27, 89*a^2 + 76*a + 24])
923
+ sage: E.abelian_group()
924
+ Additive abelian group isomorphic to Z/1031352 ...
925
+
926
+ The group can be trivial::
927
+
928
+ sage: E = EllipticCurve(GF(2), [0,0,1,1,1])
929
+ sage: E.abelian_group()
930
+ Trivial group embedded in Abelian group of points on
931
+ Elliptic Curve defined by y^2 + y = x^3 + x + 1 over Finite Field of size 2
932
+
933
+ Of course, there are plenty of points if we extend the field::
934
+
935
+ sage: E.cardinality(extension_degree=100)
936
+ 1267650600228231653296516890625
937
+
938
+ This tests the patch for :issue:`3111`, using 10 primes randomly
939
+ selected::
940
+
941
+ sage: # needs database_cremona_mini_ellcurve
942
+ sage: E = EllipticCurve('389a')
943
+ sage: for p in [5927, 2297, 1571, 1709, 3851, 127, 3253, 5783, 3499, 4817]:
944
+ ....: G = E.change_ring(GF(p)).abelian_group()
945
+ sage: for p in prime_range(10000): # long time (19s on sage.math, 2011)
946
+ ....: if p != 389:
947
+ ....: G = E.change_ring(GF(p)).abelian_group()
948
+
949
+ This tests that the bug reported in :issue:`3926` has been fixed::
950
+
951
+ sage: # needs sage.rings.number_field
952
+ sage: K.<i> = QuadraticField(-1)
953
+ sage: OK = K.ring_of_integers()
954
+ sage: P = K.factor(10007)[0][0]
955
+ sage: OKmodP = OK.residue_field(P)
956
+ sage: E = EllipticCurve([0, 0, 0, i, i + 3])
957
+ sage: Emod = E.change_ring(OKmodP); Emod
958
+ Elliptic Curve defined by y^2 = x^3 + ibar*x + (ibar+3)
959
+ over Residue field in ibar of Fractional ideal (10007)
960
+ sage: Emod.abelian_group() #random generators
961
+ (Multiplicative Abelian group isomorphic to C50067594 x C2,
962
+ ((3152*ibar + 7679 : 7330*ibar + 7913 : 1), (8466*ibar + 1770 : 0 : 1)))
963
+ """
964
+
965
+ gens = self.gens()
966
+ assert len(gens) <= 2
967
+
968
+ if len(gens) == 2:
969
+
970
+ P, Q = gens
971
+ n = self.cardinality() # cached
972
+ n1 = P.order() # cached
973
+ n2 = n//n1
974
+ assert not n1 * Q # PARI should guarantee this
975
+
976
+ k = n1.prime_to_m_part(n2)
977
+ Q *= k # don't need; kill that part
978
+ nQ = n2 * generic.order_from_multiple(n2*Q, n1//k//n2)
979
+
980
+ S = n//nQ * P
981
+ T = n2 * Q
982
+ S.set_order(nQ//n2, check=False) # for .log()
983
+ x = T.log(S)
984
+ Q -= x * n1//nQ * P
985
+
986
+ assert not n2 * Q # by construction
987
+ Q.set_order(n2, check=False)
988
+
989
+ gens = P, Q
990
+
991
+ orders = [T.order() for T in gens] # cached
992
+
993
+ self.gens.set_cache(gens)
994
+ return AdditiveAbelianGroupWrapper(self.point_homset(), gens, orders)
995
+
996
+ def torsion_basis(self, n):
997
+ r"""
998
+ Return a basis of the `n`-torsion subgroup of this elliptic curve,
999
+ assuming it is fully rational.
1000
+
1001
+ EXAMPLES::
1002
+
1003
+ sage: # needs sage.rings.finite_rings
1004
+ sage: E = EllipticCurve(GF(62207^2), [1,0])
1005
+ sage: E.abelian_group()
1006
+ Additive abelian group isomorphic to Z/62208 + Z/62208 embedded in
1007
+ Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x
1008
+ over Finite Field in z2 of size 62207^2
1009
+ sage: PA,QA = E.torsion_basis(2^8)
1010
+ sage: PA.weil_pairing(QA, 2^8).multiplicative_order()
1011
+ 256
1012
+ sage: PB,QB = E.torsion_basis(3^5)
1013
+ sage: PB.weil_pairing(QB, 3^5).multiplicative_order()
1014
+ 243
1015
+
1016
+ ::
1017
+
1018
+ sage: E = EllipticCurve(GF(101), [4,4])
1019
+ sage: E.torsion_basis(23)
1020
+ Traceback (most recent call last):
1021
+ ...
1022
+ ValueError: curve does not have full rational 23-torsion
1023
+ sage: F = E.division_field(23); F
1024
+ Finite Field in t of size 101^11
1025
+ sage: EE = E.change_ring(F)
1026
+ sage: P, Q = EE.torsion_basis(23)
1027
+ sage: P # random
1028
+ (89*z11^10 + 51*z11^9 + 96*z11^8 + 8*z11^7 + 67*z11^6
1029
+ + 31*z11^5 + 55*z11^4 + 59*z11^3 + 28*z11^2 + 8*z11 + 88
1030
+ : 40*z11^10 + 33*z11^9 + 80*z11^8 + 87*z11^7 + 97*z11^6
1031
+ + 69*z11^5 + 56*z11^4 + 17*z11^3 + 26*z11^2 + 69*z11 + 11
1032
+ : 1)
1033
+ sage: Q # random
1034
+ (25*z11^10 + 61*z11^9 + 49*z11^8 + 17*z11^7 + 80*z11^6
1035
+ + 20*z11^5 + 49*z11^4 + 52*z11^3 + 61*z11^2 + 27*z11 + 61
1036
+ : 60*z11^10 + 91*z11^9 + 89*z11^8 + 7*z11^7 + 63*z11^6
1037
+ + 55*z11^5 + 23*z11^4 + 17*z11^3 + 90*z11^2 + 91*z11 + 68
1038
+ : 1)
1039
+
1040
+ .. SEEALSO::
1041
+
1042
+ Use :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.division_field`
1043
+ to determine a field extension containing the full `\ell`-torsion subgroup.
1044
+
1045
+ ALGORITHM:
1046
+
1047
+ This method currently uses :meth:`abelian_group` and
1048
+ :meth:`AdditiveAbelianGroupWrapper.torsion_subgroup`.
1049
+ """
1050
+ # TODO: In many cases this is not the fastest algorithm.
1051
+ # Alternatives include factoring division polynomials and
1052
+ # random sampling (like PARI's ellgroup, but with a milder
1053
+ # termination condition). We should implement these too
1054
+ # and figure out when to use which.
1055
+ T = self.abelian_group().torsion_subgroup(n)
1056
+ if T.invariants() != (n, n):
1057
+ raise ValueError(f'curve does not have full rational {n}-torsion')
1058
+ return tuple(P.element() for P in T.gens())
1059
+
1060
+ def is_isogenous(self, other, field=None, proof=True):
1061
+ """
1062
+ Return whether or not ``self`` is isogenous to ``other``.
1063
+
1064
+ INPUT:
1065
+
1066
+ - ``other`` -- another elliptic curve
1067
+
1068
+ - ``field`` -- (default: ``None``) a field containing the base
1069
+ fields of the two elliptic curves into which the two curves
1070
+ may be extended to test if they are isogenous over this
1071
+ field. By default is_isogenous will not try to find this
1072
+ field unless one of the curves can be extended into the base
1073
+ field of the ``other``, in which case it will test over the
1074
+ larger base field.
1075
+
1076
+ - ``proof`` -- boolean (default: ``True``); this parameter is here only
1077
+ to be consistent with versions for other types of elliptic curves
1078
+
1079
+ OUTPUT:
1080
+
1081
+ boolean; ``True`` if there is an isogeny from curve ``self`` to
1082
+ curve ``other`` defined over ``field``
1083
+
1084
+ EXAMPLES::
1085
+
1086
+ sage: # needs sage.rings.finite_rings
1087
+ sage: E1 = EllipticCurve(GF(11^2,'a'),[2,7]); E1
1088
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 7 over Finite Field in a of size 11^2
1089
+ sage: E1.is_isogenous(5)
1090
+ Traceback (most recent call last):
1091
+ ...
1092
+ ValueError: Second argument is not an Elliptic Curve.
1093
+ sage: E1.is_isogenous(E1)
1094
+ True
1095
+
1096
+ sage: # needs sage.rings.finite_rings
1097
+ sage: E2 = EllipticCurve(GF(7^3,'b'),[3,1]); E2
1098
+ Elliptic Curve defined by y^2 = x^3 + 3*x + 1 over Finite Field in b of size 7^3
1099
+ sage: E1.is_isogenous(E2)
1100
+ Traceback (most recent call last):
1101
+ ...
1102
+ ValueError: The base fields must have the same characteristic.
1103
+
1104
+ sage: # needs sage.rings.finite_rings
1105
+ sage: E3 = EllipticCurve(GF(11^2,'c'),[4,3]); E3
1106
+ Elliptic Curve defined by y^2 = x^3 + 4*x + 3 over Finite Field in c of size 11^2
1107
+ sage: E1.is_isogenous(E3)
1108
+ False
1109
+
1110
+ sage: # needs sage.rings.finite_rings
1111
+ sage: E4 = EllipticCurve(GF(11^6,'d'),[6,5]); E4
1112
+ Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field in d of size 11^6
1113
+ sage: E1.is_isogenous(E4)
1114
+ True
1115
+
1116
+ sage: # needs sage.rings.finite_rings
1117
+ sage: E5 = EllipticCurve(GF(11^7,'e'),[4,2]); E5
1118
+ Elliptic Curve defined by y^2 = x^3 + 4*x + 2 over Finite Field in e of size 11^7
1119
+ sage: E1.is_isogenous(E5)
1120
+ Traceback (most recent call last):
1121
+ ...
1122
+ ValueError: Curves have different base fields: use the field parameter.
1123
+
1124
+ When the field is given::
1125
+
1126
+ sage: # needs sage.rings.finite_rings
1127
+ sage: E1 = EllipticCurve(GF(13^2,'a'),[2,7]); E1
1128
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 7 over Finite Field in a of size 13^2
1129
+ sage: E1.is_isogenous(5,GF(13^6,'f'))
1130
+ Traceback (most recent call last):
1131
+ ...
1132
+ ValueError: Second argument is not an Elliptic Curve.
1133
+ sage: E6 = EllipticCurve(GF(11^3,'g'),[9,3]); E6
1134
+ Elliptic Curve defined by y^2 = x^3 + 9*x + 3 over Finite Field in g of size 11^3
1135
+ sage: E1.is_isogenous(E6,QQ)
1136
+ Traceback (most recent call last):
1137
+ ...
1138
+ ValueError: The base fields must have the same characteristic.
1139
+ sage: E7 = EllipticCurve(GF(13^5,'h'),[2,9]); E7
1140
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 9 over Finite Field in h of size 13^5
1141
+ sage: E1.is_isogenous(E7,GF(13^4,'i'))
1142
+ Traceback (most recent call last):
1143
+ ...
1144
+ ValueError: Field must be an extension of the base fields of both curves
1145
+ sage: E1.is_isogenous(E7,GF(13^10,'j'))
1146
+ False
1147
+ sage: E1.is_isogenous(E7,GF(13^30,'j'))
1148
+ False
1149
+ """
1150
+ from .ell_generic import EllipticCurve_generic
1151
+ if not isinstance(other, EllipticCurve_generic):
1152
+ raise ValueError("Second argument is not an Elliptic Curve.")
1153
+ if self.is_isomorphic(other):
1154
+ return True
1155
+ if self.base_field().characteristic() != other.base_field().characteristic():
1156
+ raise ValueError("The base fields must have the same characteristic.")
1157
+ if field is None:
1158
+ if self.base_field().degree() == other.base_field().degree():
1159
+ return self.cardinality() == other.cardinality()
1160
+
1161
+ elif self.base_field().degree() == gcd(self.base_field().degree(),
1162
+ other.base_field().degree()):
1163
+ return self.cardinality(extension_degree=other.base_field().degree()//self.base_field().degree()) == other.cardinality()
1164
+
1165
+ elif other.base_field().degree() == gcd(self.base_field().degree(),
1166
+ other.base_field().degree()):
1167
+ return other.cardinality(extension_degree=self.base_field().degree()//other.base_field().degree()) == self.cardinality()
1168
+
1169
+ else:
1170
+ raise ValueError("Curves have different base fields: use the field parameter.")
1171
+ else:
1172
+ f_deg = field.degree()
1173
+ s_deg = self.base_field().degree()
1174
+ o_deg = other.base_field().degree()
1175
+ if not lcm(s_deg, o_deg).divides(f_deg):
1176
+ raise ValueError("Field must be an extension of the base fields of both curves")
1177
+ else:
1178
+ sc = self.cardinality(extension_degree=f_deg // s_deg)
1179
+ oc = other.cardinality(extension_degree=f_deg // o_deg)
1180
+ return sc == oc
1181
+
1182
+ def is_supersingular(self, proof=True):
1183
+ r"""
1184
+ Return ``True`` if this elliptic curve is supersingular, else ``False``.
1185
+
1186
+ INPUT:
1187
+
1188
+ - ``proof``-- boolean (default: ``True``); if ``True``, returns a
1189
+ proved result. If ``False``, then a return value of ``False`` is
1190
+ certain but a return value of ``True`` may be based on a
1191
+ probabilistic test. See the documentation of the function
1192
+ :meth:`is_j_supersingular` for more details.
1193
+
1194
+ EXAMPLES::
1195
+
1196
+ sage: F = GF(101)
1197
+ sage: EllipticCurve(j=F(0)).is_supersingular()
1198
+ True
1199
+ sage: EllipticCurve(j=F(1728)).is_supersingular()
1200
+ False
1201
+ sage: EllipticCurve(j=F(66)).is_supersingular()
1202
+ True
1203
+ sage: EllipticCurve(j=F(99)).is_supersingular()
1204
+ False
1205
+
1206
+ TESTS::
1207
+
1208
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import supersingular_j_polynomial, is_j_supersingular
1209
+ sage: F = GF(103)
1210
+ sage: ssjlist = [F(1728)] + supersingular_j_polynomial(103).roots(multiplicities=False)
1211
+ sage: Set([j for j in F if is_j_supersingular(j)]) == Set(ssjlist)
1212
+ True
1213
+ """
1214
+ return is_j_supersingular(self.j_invariant(), proof=proof)
1215
+
1216
+ def is_ordinary(self, proof=True):
1217
+ r"""
1218
+ Return ``True`` if this elliptic curve is ordinary, else ``False``.
1219
+
1220
+ INPUT:
1221
+
1222
+ - ``proof``-- boolean (default: ``True``); if ``True``, returns a
1223
+ proved result. If ``False``, then a return value of ``True`` is
1224
+ certain but a return value of ``False`` may be based on a
1225
+ probabilistic test. See the documentation of the function
1226
+ :meth:`is_j_supersingular` for more details.
1227
+
1228
+ EXAMPLES::
1229
+
1230
+ sage: F = GF(101)
1231
+ sage: EllipticCurve(j=F(0)).is_ordinary()
1232
+ False
1233
+ sage: EllipticCurve(j=F(1728)).is_ordinary()
1234
+ True
1235
+ sage: EllipticCurve(j=F(66)).is_ordinary()
1236
+ False
1237
+ sage: EllipticCurve(j=F(99)).is_ordinary()
1238
+ True
1239
+ """
1240
+ return not is_j_supersingular(self.j_invariant(), proof=proof)
1241
+
1242
+ def has_order(self, value, num_checks=8) -> bool:
1243
+ r"""
1244
+ Return ``True`` if the curve has order ``value``.
1245
+
1246
+ INPUT:
1247
+
1248
+ - ``value`` -- integer in the Hasse-Weil range for this curve
1249
+
1250
+ - ``num_checks``-- integer (default: `8`); the number of times to check
1251
+ whether ``value`` times a random point on this curve equals the
1252
+ identity. If ``value`` is a prime and the curve is over a field of
1253
+ order at least `5`, it is sufficient to pass in ``num_checks=1`` -
1254
+ see the examples below.
1255
+
1256
+ .. NOTE::
1257
+
1258
+ Since the method is probabilistic, there is a possibility for the
1259
+ method to yield false positives (i.e. returning ``True`` even when
1260
+ the result is ``False``). Even worse, it is possible for this to
1261
+ happen even when ``num_checks`` is increased arbitrarily. See below
1262
+ for an example and :issue:`38617` for an open discussion.
1263
+
1264
+ EXAMPLES:
1265
+
1266
+ For curves over small finite fields, the order is computed and compared
1267
+ directly::
1268
+
1269
+ sage: E = EllipticCurve(GF(7), [0, 1])
1270
+ sage: E.order()
1271
+ 12
1272
+ sage: E.has_order(12, num_checks=0)
1273
+ True
1274
+ sage: E.has_order(11, num_checks=0)
1275
+ False
1276
+ sage: E.has_order(13, num_checks=0)
1277
+ False
1278
+
1279
+ This tests the method on a random curve::
1280
+
1281
+ sage: # long time (10s)
1282
+ sage: p = random_prime(2**128, lbound=2**127)
1283
+ sage: K = GF((p, 2), name="a")
1284
+ sage: E = EllipticCurve(K, [K.random_element() for _ in range(2)])
1285
+ sage: N = E.order()
1286
+ sage: E.has_order(N, num_checks=20)
1287
+ True
1288
+ sage: E.has_order(N + 1)
1289
+ False
1290
+
1291
+ This demonstrates the bug mentioned in the NOTE above. The last return
1292
+ value should be ``False`` after :issue:`38617` is fixed::
1293
+
1294
+ sage: E = EllipticCurve(GF(5443568676570036275321323), [0, 13])
1295
+ sage: N = 2333145661241
1296
+ sage: E.order() == N^2
1297
+ True
1298
+ sage: E.has_order(N^2)
1299
+ True
1300
+ sage: del E._order
1301
+ sage: E.has_order(N^2 + N)
1302
+ True
1303
+
1304
+ Due to the nature of the algorithm (testing multiple of points) and the Hasse-Weil bound, we see that for testing prime orders, ``num_checks=1`` is sufficient::
1305
+
1306
+ sage: p = random_prime(1000)
1307
+ sage: E = EllipticCurve(GF(p), j=randrange(p))
1308
+ sage: q = random_prime(p + 20, lbound=p - 20)
1309
+ sage: E.has_order(q, num_checks=20) == E.has_order(q, num_checks=1)
1310
+ True
1311
+
1312
+ AUTHORS:
1313
+
1314
+ - Mariah Lenox (2011-02-16): Initial implementation
1315
+
1316
+ - Gareth Ma (2024-01-21): Fix bug for small curves
1317
+ """
1318
+ q = self.base_field().order()
1319
+ a, b = Hasse_bounds(q, 1)
1320
+ if not a <= value <= b:
1321
+ return False
1322
+
1323
+ # For really small values, the random tests are too weak to detect wrong
1324
+ # orders So we go with computing directly instead.
1325
+ # In #38341, the bound has been increased to a large value (2^64), but
1326
+ # it should be decreased (to ~100) after bug #38617 is fixed.
1327
+ if q <= 2**64 or hasattr(self, "_order"):
1328
+ return self.order() == value
1329
+
1330
+ # This might be slow
1331
+ # if value.is_prime():
1332
+ # num_checks = 1
1333
+
1334
+ # Is value * random == identity?
1335
+ for _ in range(num_checks):
1336
+ while True:
1337
+ G = self.random_point()
1338
+ if not G.is_zero():
1339
+ break
1340
+
1341
+ if not (value * G).is_zero():
1342
+ return False
1343
+
1344
+ # TODO: uncomment this and remove the line in `set_order` after 38617 is fixed.
1345
+ # self._order = value
1346
+
1347
+ return True
1348
+
1349
+ def set_order(self, value, *, check=True, num_checks=8):
1350
+ r"""
1351
+ Set the value of ``self._order`` to ``value``.
1352
+
1353
+ Use this when you know a priori the order of the curve to
1354
+ avoid a potentially expensive order calculation.
1355
+
1356
+ INPUT:
1357
+
1358
+ - ``value`` -- integer in the Hasse-Weil range for this curve
1359
+
1360
+ - ``check``-- boolean (default: ``True``); whether or
1361
+ not to run sanity checks on the input
1362
+
1363
+ - ``num_checks``-- integer (default: `8`); if ``check`` is
1364
+ ``True``, the number of times to check whether ``value``
1365
+ times a random point on this curve equals the identity
1366
+
1367
+ OUTPUT: none
1368
+
1369
+ EXAMPLES:
1370
+
1371
+ This example illustrates basic usage::
1372
+
1373
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1374
+ sage: E.set_order(12)
1375
+ sage: E.order()
1376
+ 12
1377
+ sage: E.order() * E.random_point()
1378
+ (0 : 1 : 0)
1379
+
1380
+ We now give a more interesting case, the NIST-P521 curve. Its
1381
+ order is too big to calculate with Sage, and takes a long time
1382
+ using other packages, so it is very useful here::
1383
+
1384
+ sage: p = 2^521 - 1
1385
+ sage: prev_proof_state = proof.arithmetic()
1386
+ sage: proof.arithmetic(False) # turn off primality checking
1387
+ sage: F = GF(p)
1388
+ sage: A = p - 3
1389
+ sage: B = 1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984
1390
+ sage: q = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449
1391
+ sage: E = EllipticCurve([F(A), F(B)])
1392
+ sage: E.set_order(q)
1393
+ sage: G = E.random_point()
1394
+ sage: G.order() * G # This takes practically no time.
1395
+ (0 : 1 : 0)
1396
+ sage: proof.arithmetic(prev_proof_state) # restore state
1397
+
1398
+ It is an error to pass a value which is not an integer in the
1399
+ Hasse-Weil range::
1400
+
1401
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1402
+ sage: E.set_order("hi")
1403
+ Traceback (most recent call last):
1404
+ ...
1405
+ TypeError: unable to convert 'hi' to an integer
1406
+ sage: E.set_order(0)
1407
+ Traceback (most recent call last):
1408
+ ...
1409
+ ValueError: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7 does not have order 0
1410
+ sage: E.set_order(1000)
1411
+ Traceback (most recent call last):
1412
+ ...
1413
+ ValueError: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7 does not have order 1000
1414
+
1415
+ It is also very likely an error to pass a value which is not the actual
1416
+ order of this curve. How unlikely is determined by ``num_checks``, the
1417
+ factorization of the actual order, and the actual group structure::
1418
+
1419
+ sage: E = EllipticCurve(GF(1009), [0, 1]) # This curve has order 948
1420
+ sage: E.set_order(947)
1421
+ Traceback (most recent call last):
1422
+ ...
1423
+ ValueError: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 1009 does not have order 947
1424
+
1425
+ For curves over small finite fields, the order is cheap to compute, so
1426
+ it is computed directly and compared::
1427
+
1428
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1429
+ sage: E.set_order(11)
1430
+ Traceback (most recent call last):
1431
+ ...
1432
+ ValueError: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7 does not have order 11
1433
+
1434
+ TESTS:
1435
+
1436
+ The previous version's random tests are not strong enough. In particular,
1437
+ the following used to work::
1438
+
1439
+ sage: E = EllipticCurve(GF(2), [0, 0, 1, 1, 1]) # This curve has order 1
1440
+ sage: E.set_order(3)
1441
+ Traceback (most recent call last):
1442
+ ...
1443
+ ValueError: Elliptic Curve defined by y^2 + y = x^3 + x + 1 over Finite Field of size 2 does not have order 3
1444
+
1445
+ ::
1446
+
1447
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1448
+ sage: E.set_order(4, num_checks=0)
1449
+ Traceback (most recent call last):
1450
+ ...
1451
+ ValueError: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7 does not have order 4
1452
+ sage: E.order()
1453
+ 12
1454
+
1455
+ .. TODO:: Add provable correctness check by computing the abelian group
1456
+ structure and comparing.
1457
+
1458
+ AUTHORS:
1459
+
1460
+ - Mariah Lenox (2011-02-16): Initial implementation
1461
+
1462
+ - Gareth Ma (2024-01-21): Fix bug for small curves
1463
+ """
1464
+ value = Integer(value)
1465
+
1466
+ if check and not self.has_order(value, num_checks=num_checks):
1467
+ raise ValueError(f"{self} does not have order {value}")
1468
+
1469
+ # TODO: It might help some of PARI's algorithms if we
1470
+ # could copy this over to the .pari_curve() as well.
1471
+ # At the time of writing, this appears to be tricky to
1472
+ # do in a non-hacky way because cypari2 doesn't expose
1473
+ # "member functions" of PARI objects.
1474
+
1475
+ self._order = value
1476
+
1477
+ def _fetch_cached_order(self, other):
1478
+ r"""
1479
+ This method copies the ``_order`` member from ``other`` to
1480
+ ``self``. Both curves must have the same finite base field.
1481
+
1482
+ This is used in
1483
+ :class:`~sage.schemes.elliptic_curves.hom.EllipticCurveHom`
1484
+ to keep track of an already computed curve order: According
1485
+ to Tate's theorem [Tate1966b]_, isogenous elliptic curves
1486
+ over a finite field have the same number of rational points.
1487
+
1488
+ EXAMPLES::
1489
+
1490
+ sage: E1 = EllipticCurve(GF(2^127-1), [1,2,3,4,5])
1491
+ sage: E1.set_order(170141183460469231746191640949390434666)
1492
+ sage: E2 = EllipticCurve(GF(2^127-1), [115649500210559831225094148253060920818, 36348294106991415644658737184600079491])
1493
+ sage: E2._fetch_cached_order(E1)
1494
+ sage: E2._order
1495
+ 170141183460469231746191640949390434666
1496
+
1497
+ TESTS::
1498
+
1499
+ sage: E3 = EllipticCurve(GF(17), [1,2,3,4,5])
1500
+ sage: hasattr(E3, '_order')
1501
+ False
1502
+ sage: E3._fetch_cached_order(E1)
1503
+ Traceback (most recent call last):
1504
+ ...
1505
+ ValueError: curves have distinct base fields
1506
+ """
1507
+ if hasattr(self, '_order') or not hasattr(other, '_order'):
1508
+ return
1509
+ F = self.base_field()
1510
+ if F != other.base_field():
1511
+ raise ValueError('curves have distinct base fields')
1512
+ n = getattr(other, '_order', None)
1513
+ if n is not None:
1514
+ self._order = n
1515
+
1516
+ def height_above_floor(self, ell, e):
1517
+ r"""
1518
+ Return the height of the `j`-invariant of this elliptic curve on its `\ell`-volcano.
1519
+
1520
+ The curve must have a rational endomorphism ring of rank 2: This includes all
1521
+ ordinary elliptic curves over finite fields as well as those supersingular
1522
+ elliptic curves with Frobenius not in `\ZZ`.
1523
+
1524
+ INPUT:
1525
+
1526
+ - ``ell`` -- a prime number
1527
+ - ``e`` -- nonnegative integer, the `\ell`-adic valuation of
1528
+ the conductor the Frobenius order
1529
+
1530
+
1531
+ .. NOTE::
1532
+
1533
+ For a suitable `E/\GF{q}`, and a prime `\ell`, the height
1534
+ `e` of the `\ell`-volcano containing `E` is the `\ell`-adic
1535
+ valuation of the conductor of the order generated by the
1536
+ `\GF{q}`-Frobenius `\pi_E`; the height of `E` on its
1537
+ ell-volcano is the `\ell`-adic valuation of the conductor
1538
+ of the order `\text{End}_{\GF{q}}(E)`.
1539
+
1540
+ ALGORITHM:
1541
+
1542
+ See [RouSuthZur2022]_.
1543
+
1544
+ EXAMPLES::
1545
+
1546
+ sage: F = GF(312401)
1547
+ sage: E = EllipticCurve(F,(0, 0, 0, 309381, 93465))
1548
+ sage: D = E.frobenius_discriminant(); D
1549
+ -687104
1550
+ sage: D.factor()
1551
+ -1 * 2^10 * 11 * 61
1552
+ sage: E.height_above_floor(2,8)
1553
+ 5
1554
+ """
1555
+ pi = self.frobenius()
1556
+ if pi in ZZ:
1557
+ raise ValueError("{} has a (rational) endomorphism ring of rank 4".format(self))
1558
+
1559
+ e = ZZ(e)
1560
+ if not e:
1561
+ return ZZ.zero()
1562
+
1563
+ if self.is_supersingular():
1564
+ if ell == self.base_field().characteristic():
1565
+ # In this (exceptional) case, the Frobenius can always be divided
1566
+ # by the maximal possible power of the characteristic. The reason
1567
+ # is that Frobenius must be of the form phi o [p^k] where phi is
1568
+ # a purely inseparable isogeny of degree 1 or p, hence this [p^k]
1569
+ # can always be divided out while retaining an endomorphism.
1570
+ assert self.base_field().cardinality().valuation(ell) >= 2*e
1571
+ return e
1572
+
1573
+ # In the supersingular case, the j-invariant alone does not determine
1574
+ # the level in the volcano. (The underlying reason is that there can
1575
+ # be multiple non-F_q-isomorphic curves with a given j-invariant in
1576
+ # the isogeny graph.)
1577
+ # Example: y^2 = x^3 ± x over F_p with p congruent to 3 modulo 4 have
1578
+ # distinct (rational) endomorphism rings.
1579
+ # Thus we run the "probing the depths" algorithm with F_q-isomorphism
1580
+ # classes of curves instead.
1581
+ E0 = [self] * 3
1582
+ E1 = [phi.codomain() for phi in self.isogenies_prime_degree(ell)]
1583
+ assert E1
1584
+ if len(E1) == 1:
1585
+ return ZZ.zero()
1586
+ assert len(E1) == ell + 1
1587
+ h = ZZ.one()
1588
+ while True:
1589
+ for i in range(3):
1590
+ isogs = E1[i].isogenies_prime_degree(ell)
1591
+ try:
1592
+ step = next(phi for phi in isogs if not phi.codomain().is_isomorphic(E0[i]))
1593
+ except StopIteration:
1594
+ return h
1595
+ E0[i], E1[i] = step.domain(), step.codomain()
1596
+ h += 1
1597
+ assert h <= e
1598
+ raise AssertionError('unreachable code -- this is a bug')
1599
+
1600
+ j = self.j_invariant()
1601
+ if j in [0, 1728]:
1602
+ return e
1603
+ F = j.parent()
1604
+ x = polygen(F)
1605
+ from sage.rings.polynomial.polynomial_ring import polygens
1606
+ from sage.schemes.elliptic_curves.mod_poly import classical_modular_polynomial
1607
+ X, Y = polygens(F, 'X,Y')
1608
+ phi = classical_modular_polynomial(ell)(X, Y)
1609
+ j1 = phi([x,j]).roots(multiplicities=False)
1610
+ nj1 = len(j1)
1611
+ on_floor = self.two_torsion_rank() < 2 if ell == 2 else nj1 <= ell
1612
+ if on_floor:
1613
+ return ZZ.zero()
1614
+ if e == 1 or nj1 != ell+1: # double roots can only happen at the surface
1615
+ return e
1616
+ if nj1 < 3:
1617
+ return ZZ.zero()
1618
+ j0 = [j,j,j]
1619
+ h = ZZ.one()
1620
+ while True:
1621
+ for i in range(3):
1622
+ r = (phi([x,j1[i]])//(x-j0[i])).roots(multiplicities=False)
1623
+ if not r:
1624
+ return h
1625
+ j0[i] = j1[i]
1626
+ j1[i] = r[0]
1627
+ h += 1
1628
+
1629
+ def endomorphism_discriminant_from_class_number(self, h):
1630
+ r"""
1631
+ Return the endomorphism order discriminant of this ordinary elliptic curve, given its class number ``h``.
1632
+
1633
+ INPUT:
1634
+
1635
+ - ``h`` -- positive integer
1636
+
1637
+ OUTPUT:
1638
+
1639
+ integer; the discriminant of the endomorphism ring `\text{End}(E)`, if
1640
+ this has class number ``h``. If `\text{End}(E)` does not have class
1641
+ number ``h``, a :exc:`ValueError` is raised.
1642
+
1643
+ ALGORITHM:
1644
+
1645
+ Compute the trace of Frobenius and hence the discriminant
1646
+ `D_0` and class number `h_0` of the maximal order containing
1647
+ the endomorphism order. From the given value of `h`, which
1648
+ must be a multiple of `h_0`, compute the possible conductors,
1649
+ using :meth:`height_above_floor` for each prime `\ell`
1650
+ dividing the quotient `h/h_0`. If exactly one conductor `f`
1651
+ remains, return `f^2D_0`, otherwise raise a :exc:`ValueError`;
1652
+ this can onlyhappen when the input value of `h` was incorrect.
1653
+
1654
+ .. NOTE::
1655
+
1656
+ Adapted from [RouSuthZur2022]_. The application for which
1657
+ one knows the class number in advance is in the
1658
+ recognition of Hilbert Class Polynomials: see
1659
+ :func:`sage.schemes.elliptic_curves.cm.is_HCP`.
1660
+
1661
+ EXAMPLES::
1662
+
1663
+ sage: F = GF(312401)
1664
+ sage: E = EllipticCurve(F,(0, 0, 0, 309381, 93465))
1665
+ sage: E.endomorphism_discriminant_from_class_number(30)
1666
+ -671
1667
+
1668
+ We check that this is the correct discriminant, and the input value of `h` was correct::
1669
+
1670
+ sage: H = hilbert_class_polynomial(-671)
1671
+ sage: H(E.j_invariant()) == 0 and H.degree()==30
1672
+ True
1673
+ """
1674
+ F = self.base_field()
1675
+ if not F.is_finite():
1676
+ raise ValueError("Base field {} must be finite".format(F))
1677
+ if self.is_supersingular():
1678
+ raise ValueError("Elliptic curve ({}) must be ordinary".format(self))
1679
+ D1 = self.frobenius_discriminant()
1680
+ D0 = D1.squarefree_part()
1681
+ if D0 % 4 != 1:
1682
+ D0 *= 4
1683
+ v = ZZ(D1//D0).isqrt()
1684
+ h0 = D0.class_number()
1685
+ if h % h0:
1686
+ raise ValueError("Incorrect class number {}".format(h))
1687
+ from sage.schemes.elliptic_curves.cm import OrderClassNumber
1688
+ cs = [v//f for f in v.divisors() if OrderClassNumber(D0,h0,f) == h] # cofactors c=v/f compatible with h(f**2D0)=h
1689
+ if not cs:
1690
+ raise ValueError("Incorrect class number {}".format(h))
1691
+ if len(cs) == 1:
1692
+ return (v//cs[0])**2 * D0
1693
+
1694
+ L = sorted(set(sum([c.prime_factors() for c in cs], [])))
1695
+ for ell in L:
1696
+ e = self.height_above_floor(ell,v.valuation(ell))
1697
+ cs = [c for c in cs if c.valuation(ell) == e]
1698
+ if not cs:
1699
+ raise ValueError("Incorrect class number {}".format(h))
1700
+ if len(cs) == 1:
1701
+ return (v//cs[0])**2 * D0
1702
+ raise ValueError("Incorrect class number {}".format(h))
1703
+
1704
+ def endomorphism_order(self):
1705
+ r"""
1706
+ Return a quadratic order isomorphic to the endomorphism ring
1707
+ of this elliptic curve, assuming the order has rank two.
1708
+
1709
+ .. NOTE::
1710
+
1711
+ In the future, this method will hopefully be extended to return a
1712
+ :class:`~sage.algebras.quatalg.quaternion_algebra.QuaternionOrder`
1713
+ object in the rank-4 case, but this has not been implemented yet.
1714
+
1715
+ .. SEEALSO::
1716
+
1717
+ :meth:`frobenius_order`
1718
+
1719
+ EXAMPLES::
1720
+
1721
+ sage: E = EllipticCurve(GF(11), [3,3])
1722
+ sage: E.endomorphism_order()
1723
+ Maximal Order generated by 1/2*pi + 1/2 in Number Field in pi with defining polynomial x^2 - 4*x + 11
1724
+
1725
+ It also works for supersingular elliptic curves provided that Frobenius
1726
+ is not in `\ZZ`::
1727
+
1728
+ sage: E = EllipticCurve(GF(11), [1,0])
1729
+ sage: E.is_supersingular()
1730
+ True
1731
+ sage: E.endomorphism_order()
1732
+ Order of conductor 2 generated by pi in Number Field in pi with defining polynomial x^2 + 11
1733
+
1734
+ ::
1735
+
1736
+ sage: E = EllipticCurve(GF(11), [-1,0])
1737
+ sage: E.is_supersingular()
1738
+ True
1739
+ sage: E.endomorphism_order()
1740
+ Maximal Order generated by 1/2*pi + 1/2 in Number Field in pi with defining polynomial x^2 + 11
1741
+
1742
+ There are some exceptional cases where Frobenius itself is divisible
1743
+ by the characteristic::
1744
+
1745
+ sage: EllipticCurve([GF(7^2).gen(), 0]).endomorphism_order()
1746
+ Gaussian Integers generated by 1/7*pi in Number Field in pi with defining polynomial x^2 + 49
1747
+ sage: EllipticCurve(GF(3^5), [1, 0]).endomorphism_order()
1748
+ Order of conductor 2 generated by 1/9*pi in Number Field in pi with defining polynomial x^2 + 243
1749
+ sage: EllipticCurve(GF(7^3), [-1, 0]).endomorphism_order()
1750
+ Maximal Order generated by 1/14*pi + 1/2 in Number Field in pi with defining polynomial x^2 + 343
1751
+ """
1752
+ pi = self.frobenius()
1753
+ if pi in ZZ:
1754
+ raise NotImplementedError('the rank-4 case is not supported yet')
1755
+
1756
+ O = self.frobenius_order()
1757
+ f0 = O.conductor()
1758
+
1759
+ f = 1
1760
+ for l,e in f0.factor():
1761
+ h = self.height_above_floor(l, e)
1762
+ f *= l**(e-h)
1763
+
1764
+ K = O.number_field()
1765
+ return K.order_of_conductor(f)
1766
+
1767
+ def twists(self):
1768
+ r"""
1769
+ Return a list of `k`-isomorphism representatives of all
1770
+ twists of this elliptic curve, where `k` is the base field.
1771
+
1772
+ The input curve appears as the first entry of the result.
1773
+
1774
+ .. NOTE::
1775
+
1776
+ A *twist* of `E/k` is an elliptic curve `E'` defined over
1777
+ `k` that is isomorphic to `E` over the algebraic closure
1778
+ `\bar k`.
1779
+
1780
+ Most elliptic curves over a finite field only admit a
1781
+ single nontrivial twist (the quadratic twist); the only
1782
+ exceptions are curves with `j`-invariant `0` or `1728`.
1783
+
1784
+ In all cases the sum over all the twists `E'` of `1/|Aut(E')|` is 1.
1785
+
1786
+ .. SEEALSO::
1787
+
1788
+ - :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.quadratic_twist`
1789
+ - :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.quartic_twist`
1790
+ - :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.sextic_twist`
1791
+
1792
+ EXAMPLES::
1793
+
1794
+ sage: E = EllipticCurve(GF(97), [1,1])
1795
+ sage: E.j_invariant()
1796
+ 54
1797
+ sage: E.twists()
1798
+ [Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 97,
1799
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97]
1800
+
1801
+ ::
1802
+
1803
+ sage: E = EllipticCurve(GF(97), [1,0])
1804
+ sage: E.j_invariant()
1805
+ 79
1806
+ sage: E.twists()
1807
+ [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 97,
1808
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97,
1809
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97,
1810
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97]
1811
+
1812
+ ::
1813
+
1814
+ sage: E = EllipticCurve(GF(97), [0,1])
1815
+ sage: E.j_invariant()
1816
+ 0
1817
+ sage: E.twists()
1818
+ [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 97,
1819
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97,
1820
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97,
1821
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97,
1822
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97,
1823
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97]
1824
+
1825
+ This can be useful to quickly compute a list of all elliptic curves
1826
+ over a finite field `k` up to `k`-isomorphism::
1827
+
1828
+ sage: Es = [E for j in GF(13) for E in EllipticCurve(j=j).twists()]
1829
+ sage: len(Es)
1830
+ 32
1831
+ sage: Es
1832
+ [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 13,
1833
+ ...
1834
+ Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 13]
1835
+
1836
+ In characteristic 3, the number of twists is 2 except for
1837
+ `j=0=1728`, when there are either 4 or 6 depending on whether the
1838
+ field has odd or even degree over `\GF{3}`::
1839
+
1840
+ sage: # needs sage.rings.finite_rings
1841
+ sage: K = GF(3**5)
1842
+ sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()]
1843
+ [(0, 1, 0, 0, 2), (0, z5, 0, 0, 2*z5^3)]
1844
+
1845
+ sage: # needs sage.rings.finite_rings
1846
+ sage: K = GF(3**5)
1847
+ sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] # random
1848
+ [(0, 0, 0, 1, 0),
1849
+ (0, 0, 0, 2, 0),
1850
+ (0, 0, 0, 2, z5^4 + z5^3 + z5^2),
1851
+ (0, 0, 0, 2, 2*z5^4 + 2*z5^3 + 2*z5^2)]
1852
+
1853
+ sage: # needs sage.rings.finite_rings
1854
+ sage: K = GF(3**4)
1855
+ sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()]
1856
+ [(0, 1, 0, 0, 2), (0, z4, 0, 0, 2*z4^3)]
1857
+
1858
+ sage: # needs sage.rings.finite_rings
1859
+ sage: K = GF(3**4)
1860
+ sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] # random
1861
+ [(0, 0, 0, 1, 0),
1862
+ (0, 0, 0, 2, 2*z4^3 + 2*z4^2 + 2*z4 + 2),
1863
+ (0, 0, 0, 1, 0),
1864
+ (0, 0, 0, 1, 2*z4^3 + 2*z4^2 + 2*z4 + 2),
1865
+ (0, 0, 0, z4, 0),
1866
+ (0, 0, 0, z4^3, 0)]
1867
+
1868
+ In characteristic 2, the number of twists is 2 except for
1869
+ `j=0=1728`, when there are either 3 or 7 depending on whether the
1870
+ field has odd or even degree over `\GF{2}`::
1871
+
1872
+ sage: # needs sage.rings.finite_rings
1873
+ sage: K = GF(2**7)
1874
+ sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()]
1875
+ [(1, 0, 0, 0, 1), (1, 1, 0, 0, 1)]
1876
+
1877
+ sage: # needs sage.rings.finite_rings
1878
+ sage: K = GF(2**7)
1879
+ sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()]
1880
+ [(0, 0, 1, 0, 0), (0, 0, 1, 1, 0), (0, 0, 1, 1, 1)]
1881
+
1882
+ sage: # needs sage.rings.finite_rings
1883
+ sage: K = GF(2**8)
1884
+ sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()] # random
1885
+ [(1, 0, 0, 0, 1), (1, z8^7 + z8^6 + z8^5 + z8^4 + z8^2 + z8, 0, 0, 1)]
1886
+
1887
+ sage: # needs sage.rings.finite_rings
1888
+ sage: K = GF(2**8)
1889
+ sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] # random
1890
+ [(0, 0, 1, 0, 0),
1891
+ (0, 0, 1, 0, z8^5 + z8^4 + z8^3),
1892
+ (0, 0, 1, z8^6 + z8^5 + z8^2 + 1, 0),
1893
+ (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, 0),
1894
+ (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, z8^3 + z8^2 + 1),
1895
+ (0, 0, z8^6 + z8^3 + z8^2, 0, 0),
1896
+ (0, 0, z8^6 + z8^3 + z8^2, 0, z8^3 + z8^2)]
1897
+
1898
+ TESTS:
1899
+
1900
+ Randomized check that we find all twists and there are no duplicates::
1901
+
1902
+ sage: # needs sage.rings.finite_rings
1903
+ sage: p = next_prime(randrange(2,100))
1904
+ sage: e = randrange(1,10)
1905
+ sage: F.<t> = GF((p,e))
1906
+ sage: E = EllipticCurve(j=F.random_element())
1907
+ sage: twists1 = E.twists()
1908
+ sage: {sum(E1.is_isomorphic(E2) for E2 in twists1) == 1 for E1 in twists1}
1909
+ {True}
1910
+ sage: j = E.j_invariant()
1911
+ sage: A,B = polygens(F, 'A,B')
1912
+ sage: eq = 1728*4*A**3 - j * (4*A**3 + 27*B**2)
1913
+ sage: twists2 = []
1914
+ sage: for _ in range(10):
1915
+ ....: I = Ideal([eq, A + B - F.random_element()])
1916
+ ....: try:
1917
+ ....: V = I.variety()
1918
+ ....: except ValueError:
1919
+ ....: if I.dimension() == 0:
1920
+ ....: raise
1921
+ ....: if not V:
1922
+ ....: continue
1923
+ ....: sol = choice(V)
1924
+ ....: a, b = sol[A], sol[B]
1925
+ ....: try:
1926
+ ....: twists2.append(EllipticCurve([a, b]))
1927
+ ....: except ArithmeticError:
1928
+ ....: pass
1929
+ sage: all(any(E2.is_isomorphic(E1) for E1 in twists1) for E2 in twists2)
1930
+ True
1931
+ """
1932
+ K = self.base_field()
1933
+ j = self.j_invariant()
1934
+ twists = None
1935
+ if not j:
1936
+ twists = curves_with_j_0(K)
1937
+ elif j == 1728:
1938
+ twists = curves_with_j_1728(K)
1939
+
1940
+ if twists: # i.e. if j=0 or 1728
1941
+ # replace the one isomorphic to self with self and move to front
1942
+ for i, t in enumerate(twists):
1943
+ if self.is_isomorphic(t):
1944
+ twists[i] = twists[0]
1945
+ twists[0] = self
1946
+ break
1947
+ return twists
1948
+
1949
+ # Now j is not 0 or 1728, and we only have a quadratic twist
1950
+
1951
+ if K.characteristic() == 2:
1952
+ # find D with trace 1 for the additive twist
1953
+ D = K.one()
1954
+ while not D or D.trace() == 0:
1955
+ D = K.random_element()
1956
+ else:
1957
+ # find a nonsquare D.
1958
+ D = K.gen()
1959
+ q2 = (K.cardinality() - 1) // 2
1960
+ while not D or D**q2 == 1:
1961
+ D = K.random_element()
1962
+ # assert D and D**q2 != 1
1963
+ # assert not D.is_square()
1964
+
1965
+ return [self, self.quadratic_twist(D)]
1966
+
1967
+
1968
+ def curves_with_j_0(K):
1969
+ r"""
1970
+ Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 0 over the finite field `K`.
1971
+
1972
+ .. NOTE::
1973
+
1974
+ In characteristics 2 and 3 this function simply calls ``curves_with_j_0_char2`` or
1975
+ ``curves_with_j_0_char3``. Otherwise there are either 2 or 6 curves, parametrised by
1976
+ `K^*/(K^*)^6`.
1977
+
1978
+ Examples:
1979
+
1980
+ For `K=\GF{q}` where `q\equiv1\mod{6}` there are six curves, the sextic twists of `y^2=x^3+1`::
1981
+
1982
+ sage: # needs sage.rings.finite_rings
1983
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0
1984
+ sage: sorted(curves_with_j_0(GF(7)), key = lambda E: E.a_invariants())
1985
+ [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7,
1986
+ Elliptic Curve defined by y^2 = x^3 + 2 over Finite Field of size 7,
1987
+ Elliptic Curve defined by y^2 = x^3 + 3 over Finite Field of size 7,
1988
+ Elliptic Curve defined by y^2 = x^3 + 4 over Finite Field of size 7,
1989
+ Elliptic Curve defined by y^2 = x^3 + 5 over Finite Field of size 7,
1990
+ Elliptic Curve defined by y^2 = x^3 + 6 over Finite Field of size 7]
1991
+ sage: curves = curves_with_j_0(GF(25)); len(curves)
1992
+ 6
1993
+ sage: all(not curves[i].is_isomorphic(curves[j]) for i in range(6) for j in range(i + 1, 6))
1994
+ True
1995
+ sage: set(E.j_invariant() for E in curves)
1996
+ {0}
1997
+
1998
+ For `K=\GF{q}` where `q\equiv5\mod{6}` there are two curves,
1999
+ quadratic twists of each other by `-3`: `y^2=x^3+1` and
2000
+ `y^2=x^3-27`::
2001
+
2002
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0
2003
+ sage: curves_with_j_0(GF(5))
2004
+ [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 5,
2005
+ Elliptic Curve defined by y^2 = x^3 + 3 over Finite Field of size 5]
2006
+ sage: curves_with_j_0(GF(11))
2007
+ [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 11,
2008
+ Elliptic Curve defined by y^2 = x^3 + 6 over Finite Field of size 11]
2009
+ """
2010
+ if not K.is_finite():
2011
+ raise ValueError("field must be finite")
2012
+ p = K.characteristic()
2013
+ if p == 2:
2014
+ return curves_with_j_0_char2(K)
2015
+ if p == 3:
2016
+ return curves_with_j_0_char3(K)
2017
+ q = K.cardinality()
2018
+ if q % 3 == 2:
2019
+ # Then we only have two quadratic twists (and -3 is non-square)
2020
+ return [EllipticCurve(K, [0, a]) for a in [1, -27]]
2021
+ # Now we have genuine sextic twists, find D generating K* mod 6th powers
2022
+ q2 = (q - 1) // 2
2023
+ q3 = (q - 1) // 3
2024
+ D = K.gen()
2025
+ while not D or D**q2 == 1 or D**q3 == 1:
2026
+ D = K.random_element()
2027
+
2028
+ curves = [EllipticCurve(K, [0, D**i]) for i in range(6)]
2029
+ # TODO: issue 37110, Precompute orders of sextic twists + docs
2030
+ # The idea should be to evaluate the character (D / q) or something
2031
+ # Probably reference [RS2010]_ and [Connell1999]_
2032
+ # Also a necessary change is `curves_with_j_0` should take in an optional "starting curve"
2033
+ # (passed from the original .twists call), because if you start twisting from that curve,
2034
+ # then you can also compute the orders!
2035
+ return curves
2036
+
2037
+
2038
+ def curves_with_j_1728(K):
2039
+ r"""
2040
+ Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 1728 over the finite field `K`.
2041
+
2042
+ .. NOTE::
2043
+
2044
+ In characteristics 2 and 3 (so 0=1728) this function simply calls ``curves_with_j_0_char2`` or
2045
+ ``curves_with_j_0_char3``. Otherwise there are either 2 or 4 curves, parametrised by
2046
+ `K^*/(K^*)^4`.
2047
+
2048
+ EXAMPLES:
2049
+
2050
+ For `K=\GF{q}` where `q\equiv1\mod{4}`, there are four curves, the quartic twists of `y^2=x^3+x`::
2051
+
2052
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_1728
2053
+ sage: sorted(curves_with_j_1728(GF(5)), key = lambda E: E.a_invariants())
2054
+ [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 5,
2055
+ Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 5,
2056
+ Elliptic Curve defined by y^2 = x^3 + 3*x over Finite Field of size 5,
2057
+ Elliptic Curve defined by y^2 = x^3 + 4*x over Finite Field of size 5]
2058
+ sage: curves_with_j_1728(GF(49)) # random # needs sage.rings.finite_rings
2059
+ [Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 7^2,
2060
+ Elliptic Curve defined by y^2 = x^3 + z2*x over Finite Field in z2 of size 7^2,
2061
+ Elliptic Curve defined by y^2 = x^3 + (z2+4)*x over Finite Field in z2 of size 7^2,
2062
+ Elliptic Curve defined by y^2 = x^3 + (5*z2+4)*x over Finite Field in z2 of size 7^2]
2063
+
2064
+ For `K=\GF{q}` where `q\equiv3\mod{4}`, there are two curves,
2065
+ quadratic twists of each other by `-1`: `y^2=x^3+x` and
2066
+ `y^2=x^3-x`::
2067
+
2068
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_1728
2069
+ sage: curves_with_j_1728(GF(7))
2070
+ [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7,
2071
+ Elliptic Curve defined by y^2 = x^3 + 6*x over Finite Field of size 7]
2072
+ sage: curves_with_j_1728(GF(11))
2073
+ [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 11,
2074
+ Elliptic Curve defined by y^2 = x^3 + 10*x over Finite Field of size 11]
2075
+ """
2076
+ if not K.is_finite():
2077
+ raise ValueError("field must be finite")
2078
+ p = K.characteristic()
2079
+ if p == 2:
2080
+ return curves_with_j_0_char2(K)
2081
+ if p == 3:
2082
+ return curves_with_j_0_char3(K)
2083
+ q = K.cardinality()
2084
+ if q % 4 == 3:
2085
+ return [EllipticCurve(K, [a,0]) for a in [1,-1]]
2086
+ # Now we have genuine quartic twists, find D generating K* mod 4th powers
2087
+ q2 = (q - 1) // 2
2088
+ D = K.gen()
2089
+ while not D or D**q2 == 1:
2090
+ D = K.random_element()
2091
+ curves = [EllipticCurve(K, [D**i, 0]) for i in range(4)]
2092
+ return curves
2093
+
2094
+
2095
+ def curves_with_j_0_char2(K):
2096
+ r"""
2097
+ Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 0 over the finite field `K` of characteristic 2.
2098
+
2099
+ .. NOTE::
2100
+
2101
+ The number of twists is either 3 or 7 depending on whether
2102
+ the field has odd or even degree over `\GF{2}`. See
2103
+ [Connell1999]_, pages 429-431.
2104
+
2105
+ Examples:
2106
+
2107
+ In odd degree, there are three isomorphism classes all with representatives defined over `\GF{2}`::
2108
+
2109
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char2
2110
+ sage: # needs sage.rings.finite_rings
2111
+ sage: K = GF(2**7)
2112
+ sage: curves = curves_with_j_0_char2(K)
2113
+ sage: len(curves)
2114
+ 3
2115
+ sage: [E.ainvs() for E in curves]
2116
+ [(0, 0, 1, 0, 0), (0, 0, 1, 1, 0), (0, 0, 1, 1, 1)]
2117
+
2118
+ Check that the curves are mutually non-isomorphic::
2119
+
2120
+ sage: all((e1 == e2 or not e1.is_isomorphic(e2)) # needs sage.rings.finite_rings
2121
+ ....: for e1 in curves for e2 in curves)
2122
+ True
2123
+
2124
+ Check that the weight formula holds::
2125
+
2126
+ sage: sum(1/len(E.automorphisms()) for E in curves) == 1 # needs sage.rings.finite_rings
2127
+ True
2128
+
2129
+ In even degree there are seven isomorphism classes::
2130
+
2131
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char2
2132
+ sage: # needs sage.rings.finite_rings
2133
+ sage: K = GF(2**8)
2134
+ sage: curves = EllipticCurve(j=K(0)).twists()
2135
+ sage: len(curves)
2136
+ 7
2137
+ sage: [E.ainvs() for E in curves] # random
2138
+ [(0, 0, 1, 0, 0),
2139
+ (0, 0, 1, 0, z8^5 + z8^4 + z8^3),
2140
+ (0, 0, 1, z8^6 + z8^5 + z8^2 + 1, 0),
2141
+ (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, 0),
2142
+ (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, z8^3 + z8^2 + 1),
2143
+ (0, 0, z8^6 + z8^3 + z8^2, 0, 0),
2144
+ (0, 0, z8^6 + z8^3 + z8^2, 0, z8^3 + z8^2)]
2145
+
2146
+ Check that the twists are mutually non-isomorphic::
2147
+
2148
+ sage: all((e1 == e2 or not e1.is_isomorphic(e2)) # needs sage.rings.finite_rings
2149
+ ....: for e1 in curves for e2 in curves)
2150
+ True
2151
+
2152
+ Check that the weight formula holds::
2153
+
2154
+ sage: sum(1/len(E.automorphisms()) for E in curves) == 1 # needs sage.rings.finite_rings
2155
+ True
2156
+ """
2157
+ if not K.is_finite() or K.characteristic() != 2:
2158
+ raise ValueError("field must be finite of characteristic 2")
2159
+ if K.degree() % 2:
2160
+ return [EllipticCurve(K, [0, 0, 1, 0, 0]),
2161
+ EllipticCurve(K, [0, 0, 1, 1, 0]),
2162
+ EllipticCurve(K, [0, 0, 1, 1, 1])]
2163
+ # find a,b,c,d,e such that
2164
+ # a is not a cube, i.e. a**((q-1)//3)!=1
2165
+ # Tr(b)=1
2166
+ # X^4+X+c irreducible
2167
+ # X^2+a*X+d irreducible
2168
+ # X^2+a^2*X+e irreducible
2169
+ a = b = c = d = e = None
2170
+ x = polygen(K)
2171
+ q3 = (K.cardinality()-1)//3
2172
+ while not a or a**q3 == 1:
2173
+ a = K.random_element()
2174
+ asq = a*a
2175
+ while not b or not b.trace():
2176
+ b = K.random_element()
2177
+ c = K.one() # OK if degree is 2 mod 4
2178
+ if K.degree() % 4 == 0:
2179
+ while (x**4+x+c).roots():
2180
+ c = K.random_element()
2181
+ while not d or (x**2+a*x+d).roots():
2182
+ d = K.random_element()
2183
+ while not e or (x**2+asq*x+e).roots():
2184
+ e = K.random_element()
2185
+ return [EllipticCurve(K, ai) for ai in
2186
+ [[0,0,1,0,0], [0,0,1,0,b], [0,0,1,c,0], [0,0,a,0,0], [0,0,a,0,d], [0,0,asq,0,0], [0,0,asq,0,e]]]
2187
+
2188
+
2189
+ def curves_with_j_0_char3(K):
2190
+ r"""
2191
+ Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 0 over the finite field `K` of characteristic 3.
2192
+
2193
+ .. NOTE::
2194
+
2195
+ The number of twists is either 4 or 6 depending on whether
2196
+ the field has odd or even degree over `\GF{3}`. See
2197
+ [Connell1999]_, pages 429-431.
2198
+
2199
+ Examples:
2200
+
2201
+ In odd degree, there are four isomorphism classes::
2202
+
2203
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char3
2204
+ sage: # needs sage.rings.finite_rings
2205
+ sage: K = GF(3**5)
2206
+ sage: curves = curves_with_j_0_char3(K)
2207
+ sage: len(curves)
2208
+ 4
2209
+ sage: [E.ainvs() for E in curves] # random
2210
+ [(0, 0, 0, 1, 0),
2211
+ (0, 0, 0, 2, 0),
2212
+ (0, 0, 0, 2, z5^4 + z5^3 + z5^2),
2213
+ (0, 0, 0, 2, 2*z5^4 + 2*z5^3 + 2*z5^2)]
2214
+
2215
+ Check that the twists are mutually non-isomorphic::
2216
+
2217
+ sage: all((e1 == e2 or not e1.is_isomorphic(e2)) # needs sage.rings.finite_rings
2218
+ ....: for e1 in curves for e2 in curves)
2219
+ True
2220
+
2221
+ Check that the weight formula holds::
2222
+
2223
+ sage: sum(1/len(E.automorphisms()) for E in curves) == 1 # needs sage.rings.finite_rings
2224
+ True
2225
+
2226
+ In even degree, there are six isomorphism classes::
2227
+
2228
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char3
2229
+ sage: # needs sage.rings.finite_rings
2230
+ sage: K = GF(3**4)
2231
+ sage: curves = EllipticCurve(j=K(0)).twists()
2232
+ sage: len(curves)
2233
+ 6
2234
+ sage: [E.ainvs() for E in curves] # random
2235
+ [(0, 0, 0, 1, 0),
2236
+ (0, 0, 0, 2, 2*z4^3 + 2*z4^2 + 2*z4 + 2),
2237
+ (0, 0, 0, 1, 0),
2238
+ (0, 0, 0, 1, 2*z4^3 + 2*z4^2 + 2*z4 + 2),
2239
+ (0, 0, 0, z4, 0),
2240
+ (0, 0, 0, z4^3, 0)]
2241
+
2242
+ Check that the twists are mutually non-isomorphic::
2243
+
2244
+ sage: all((e1 == e2 or not e1.is_isomorphic(e2)) # needs sage.rings.finite_rings
2245
+ ....: for e1 in curves for e2 in curves)
2246
+ True
2247
+
2248
+ Check that the weight formula holds::
2249
+
2250
+ sage: sum(1/len(E.automorphisms()) for E in curves) == 1 # needs sage.rings.finite_rings
2251
+ True
2252
+ """
2253
+ if not K.is_finite() or K.characteristic() != 3:
2254
+ raise ValueError("field must be finite of characteristic 3")
2255
+ # find b with nonzero trace
2256
+ b = None
2257
+ while not b or not b.trace():
2258
+ b = K.random_element()
2259
+
2260
+ if K.degree() % 2:
2261
+ return [EllipticCurve(K, a4a6) for a4a6 in
2262
+ [[1,0], [-1,0], [-1,b], [-1,-b]]]
2263
+
2264
+ # find a, i, c where:
2265
+ # a generates K* mod 4th powers, i.e. non-square,
2266
+ # i^2=-1
2267
+ # c with x^3+a^2*x+c irreducible
2268
+ a = K.gen()
2269
+ q2 = (K.cardinality()-1)//2
2270
+ while not a or a**q2 == 1:
2271
+ a = K.random_element()
2272
+ x = polygen(K)
2273
+ i = (x**2+1).roots()[0][0]
2274
+ c = None
2275
+ while not c or (x**3 + a**2*x + c).roots():
2276
+ c = K.random_element()
2277
+ return [EllipticCurve(K, a4a6) for a4a6 in
2278
+ [[1,0], [1,i*b], [a,0], [a**2,0], [a**2,c], [a**3,0]]]
2279
+
2280
+ # dict to hold precomputed coefficient vectors of supersingular j values (excluding 0, 1728):
2281
+
2282
+
2283
+ supersingular_j_polynomials = {}
2284
+
2285
+
2286
+ def fill_ss_j_dict():
2287
+ r"""
2288
+ Fill the global cache of supersingular j-_polynomials.
2289
+
2290
+ This function does nothing except the first time it is called,
2291
+ when it fills ``supersingular_j_polynomials`` with precomputed
2292
+ values for `p<300`. Setting the values this way avoids start-up
2293
+ costs.
2294
+ """
2295
+ global supersingular_j_polynomials
2296
+ if not supersingular_j_polynomials:
2297
+ supersingular_j_polynomials[13] = [8, 1]
2298
+ supersingular_j_polynomials[17] = [9, 1]
2299
+ supersingular_j_polynomials[19] = [12, 1]
2300
+ supersingular_j_polynomials[23] = [4, 1]
2301
+ supersingular_j_polynomials[29] = [21, 2, 1]
2302
+ supersingular_j_polynomials[31] = [8, 25, 1]
2303
+ supersingular_j_polynomials[37] = [11, 5, 23, 1]
2304
+ supersingular_j_polynomials[41] = [18, 10, 19, 1]
2305
+ supersingular_j_polynomials[43] = [32, 11, 21, 1]
2306
+ supersingular_j_polynomials[47] = [35, 33, 31, 1]
2307
+ supersingular_j_polynomials[53] = [24, 9, 30, 7, 1]
2308
+ supersingular_j_polynomials[59] = [39, 31, 35, 39, 1]
2309
+ supersingular_j_polynomials[61] = [60, 21, 27, 8, 60, 1]
2310
+ supersingular_j_polynomials[67] = [8, 36, 47, 4, 53, 1]
2311
+ supersingular_j_polynomials[71] = [18, 54, 28, 33, 1, 1]
2312
+ supersingular_j_polynomials[73] = [7, 39, 38, 9, 68, 60, 1]
2313
+ supersingular_j_polynomials[79] = [10, 25, 1, 63, 57, 55, 1]
2314
+ supersingular_j_polynomials[83] = [43, 72, 81, 81, 62, 11, 1]
2315
+ supersingular_j_polynomials[89] = [42, 79, 23, 22, 37, 86, 60, 1]
2316
+ supersingular_j_polynomials[97] = [19, 28, 3, 72, 2, 96, 10, 60, 1]
2317
+ supersingular_j_polynomials[101] = [9, 76, 45, 79, 1, 68, 87, 60, 1]
2318
+ supersingular_j_polynomials[103] = [64, 15, 24, 58, 70, 83, 84, 100, 1]
2319
+ supersingular_j_polynomials[107] = [6, 18, 72, 59, 43, 19, 17, 68, 1]
2320
+ supersingular_j_polynomials[109] = [107, 22, 39, 83, 30, 34, 108, 104, 60, 1]
2321
+ supersingular_j_polynomials[113] = [86, 71, 75, 6, 47, 97, 100, 4, 60, 1]
2322
+ supersingular_j_polynomials[127] = [32, 31, 5, 50, 115, 122, 114, 67, 38, 35, 1]
2323
+ supersingular_j_polynomials[131] = [65, 64, 10, 34, 129, 35, 94, 127, 7, 7, 1]
2324
+ supersingular_j_polynomials[137] = [104, 83, 3, 82, 112, 23, 77, 135, 18, 50, 60, 1]
2325
+ supersingular_j_polynomials[139] = [87, 79, 109, 21, 138, 9, 104, 130, 61, 118, 90, 1]
2326
+ supersingular_j_polynomials[149] = [135, 55, 80, 86, 87, 74, 32, 60, 130, 80, 146, 60, 1]
2327
+ supersingular_j_polynomials[151] = [94, 125, 8, 6, 93, 21, 114, 80, 107, 58, 42, 18, 1]
2328
+ supersingular_j_polynomials[157] = [14, 95, 22, 58, 110, 23, 71, 51, 47, 5, 147, 59, 60, 1]
2329
+ supersingular_j_polynomials[163] = [102, 26, 74, 95, 112, 151, 98, 107, 27, 37, 25, 111, 109, 1]
2330
+ supersingular_j_polynomials[167] = [14, 9, 27, 109, 97, 55, 51, 74, 145, 125, 36, 113, 89, 1]
2331
+ supersingular_j_polynomials[173] = [152, 73, 56, 12, 18, 96, 98, 49, 30, 43, 52, 79, 163, 60, 1]
2332
+ supersingular_j_polynomials[179] = [110, 51, 3, 94, 123, 90, 156, 90, 88, 119, 158, 27, 71, 29, 1]
2333
+ supersingular_j_polynomials[181] = [7, 65, 77, 29, 139, 34, 65, 84, 164, 73, 51, 136, 7, 141, 60, 1]
2334
+ supersingular_j_polynomials[191] = [173, 140, 144, 3, 135, 80, 182, 84, 93, 75, 83, 17, 22, 42, 160, 1]
2335
+ supersingular_j_polynomials[193] = [23, 48, 26, 15, 108, 141, 124, 44, 132, 49, 72, 173, 126, 101, 22, 60, 1]
2336
+ supersingular_j_polynomials[197] = [14, 111, 64, 170, 193, 32, 124, 91, 112, 163, 14, 112, 167, 191, 183, 60, 1]
2337
+ supersingular_j_polynomials[199] = [125, 72, 65, 30, 63, 45, 10, 177, 91, 102, 28, 27, 5, 150, 51, 128, 1]
2338
+ supersingular_j_polynomials[211] = [27, 137, 128, 90, 102, 141, 5, 77, 131, 144, 83, 108, 23, 105, 98, 13, 80, 1]
2339
+ supersingular_j_polynomials[223] = [56, 183, 46, 133, 191, 94, 20, 8, 92, 100, 57, 200, 166, 67, 59, 218, 28, 32, 1]
2340
+ supersingular_j_polynomials[227] = [79, 192, 142, 66, 11, 114, 100, 208, 57, 147, 32, 5, 144, 93, 185, 147, 92, 16, 1]
2341
+ supersingular_j_polynomials[229] = [22, 55, 182, 130, 228, 172, 63, 25, 108, 99, 100, 101, 220, 111, 205, 199, 91, 163, 60, 1]
2342
+ supersingular_j_polynomials[233] = [101, 148, 85, 113, 226, 68, 71, 103, 61, 44, 173, 175, 5, 225, 227, 99, 146, 170, 60, 1]
2343
+ supersingular_j_polynomials[239] = [225, 81, 47, 26, 133, 182, 238, 2, 144, 154, 234, 178, 165, 130, 35, 61, 144, 112, 207, 1]
2344
+ supersingular_j_polynomials[241] = [224, 51, 227, 139, 134, 186, 187, 152, 161, 175, 213, 59, 105, 88, 87, 124, 202, 40, 15, 60, 1]
2345
+ supersingular_j_polynomials[251] = [30, 183, 80, 127, 40, 56, 230, 168, 192, 48, 226, 61, 214, 54, 165, 147, 105, 88, 38, 171, 1]
2346
+ supersingular_j_polynomials[257] = [148, 201, 140, 146, 169, 147, 220, 4, 205, 224, 35, 42, 198, 97, 127, 7, 110, 229, 118, 202, 60, 1]
2347
+ supersingular_j_polynomials[263] = [245, 126, 72, 213, 14, 64, 152, 83, 169, 114, 9, 128, 138, 231, 103, 85, 114, 211, 173, 249, 135, 1]
2348
+ supersingular_j_polynomials[269] = [159, 32, 69, 95, 201, 266, 190, 176, 76, 151, 212, 21, 106, 49, 263, 105, 136, 194, 215, 181, 237, 60, 1]
2349
+ supersingular_j_polynomials[271] = [169, 87, 179, 109, 133, 101, 31, 167, 208, 99, 127, 120, 83, 62, 36, 23, 61, 50, 69, 263, 265, 111, 1]
2350
+ supersingular_j_polynomials[277] = [251, 254, 171, 72, 190, 237, 12, 231, 123, 217, 263, 151, 270, 183, 29, 228, 85, 4, 67, 101, 29, 169, 60, 1]
2351
+ supersingular_j_polynomials[281] = [230, 15, 146, 69, 41, 23, 142, 232, 18, 80, 58, 134, 270, 62, 272, 70, 247, 189, 118, 255, 274, 159, 60, 1]
2352
+ supersingular_j_polynomials[283] = [212, 4, 42, 155, 38, 1, 270, 175, 172, 256, 264, 232, 50, 82, 244, 127, 148, 46, 249, 72, 59, 124, 75, 1]
2353
+ supersingular_j_polynomials[293] = [264, 66, 165, 144, 243, 25, 163, 210, 18, 107, 160, 153, 70, 255, 91, 211, 22, 7, 256, 50, 150, 94, 225, 60, 1]
2354
+
2355
+
2356
+ def supersingular_j_polynomial(p, use_cache=True):
2357
+ r"""
2358
+ Return a polynomial whose roots are the supersingular
2359
+ `j`-invariants in characteristic `p`, other than 0, 1728.
2360
+
2361
+ INPUT:
2362
+
2363
+ - ``p`` -- integer; a prime number
2364
+
2365
+ - ``use_cache`` -- boolean (default: ``True``); use cached coefficients if they exist
2366
+
2367
+ ALGORITHM:
2368
+
2369
+ First compute H(X) whose roots are the Legendre
2370
+ `\lambda`-invariants of supersingular curves (Silverman V.4.1(b))
2371
+ in characteristic `p`. Then, using a resultant computation with
2372
+ the polynomial relating `\lambda` and `j` (Silverman III.1.7(b)),
2373
+ we recover the polynomial (in variable ``j``) whose roots are the
2374
+ `j`-invariants. Factors of `j` and `j-1728` are removed if
2375
+ present.
2376
+
2377
+ .. NOTE::
2378
+
2379
+ The only point of the use_cache parameter is to allow checking
2380
+ the precomputed coefficients.
2381
+
2382
+ EXAMPLES::
2383
+
2384
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import supersingular_j_polynomial
2385
+ sage: f = supersingular_j_polynomial(67); f
2386
+ j^5 + 53*j^4 + 4*j^3 + 47*j^2 + 36*j + 8
2387
+ sage: f.factor()
2388
+ (j + 1) * (j^2 + 8*j + 45) * (j^2 + 44*j + 24)
2389
+
2390
+ ::
2391
+
2392
+ sage: [supersingular_j_polynomial(p) for p in prime_range(30)]
2393
+ [1, 1, 1, 1, 1, j + 8, j + 9, j + 12, j + 4, j^2 + 2*j + 21]
2394
+
2395
+ TESTS::
2396
+
2397
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import supersingular_j_polynomial
2398
+ sage: supersingular_j_polynomial(6)
2399
+ Traceback (most recent call last):
2400
+ ...
2401
+ ValueError: p (=6) should be a prime number
2402
+
2403
+ Check the cached values are correct::
2404
+
2405
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import supersingular_j_polynomial as ssjpol
2406
+ sage: assert all(ssjpol(p,True) == ssjpol(p,False) for p in primes(300))
2407
+ """
2408
+ try:
2409
+ p = ZZ(p)
2410
+ except TypeError:
2411
+ raise ValueError("p (=%s) should be a prime number" % p)
2412
+ if not p.is_prime():
2413
+ raise ValueError("p (=%s) should be a prime number" % p)
2414
+
2415
+ J = polygen(GF(p),'j')
2416
+ if p < 13:
2417
+ return J.parent().one()
2418
+ if use_cache:
2419
+ fill_ss_j_dict()
2420
+ if p in supersingular_j_polynomials:
2421
+ return J.parent()(supersingular_j_polynomials[p])
2422
+
2423
+ from sage.misc.misc_c import prod
2424
+ m = (p-1)//2
2425
+ X,T = PolynomialRing(GF(p),2,names=['X','T']).gens()
2426
+ H = sum(binomial(m, i) ** 2 * T ** i for i in range(m + 1))
2427
+ F = T**2 * (T-1)**2 * X - 256*(T**2-T+1)**3
2428
+ R = F.resultant(H, T)
2429
+ R = prod([fi for fi, e in R([J, 0]).factor()])
2430
+ if R(0) == 0:
2431
+ R = R // J
2432
+ if R(1728) == 0:
2433
+ R = R // (J - 1728)
2434
+ supersingular_j_polynomials[p] = R.coefficients(sparse=False)
2435
+ return R
2436
+
2437
+
2438
+ def is_j_supersingular(j, proof=True):
2439
+ r"""
2440
+ Return ``True`` if `j` is a supersingular `j`-invariant.
2441
+
2442
+ INPUT:
2443
+
2444
+ - ``j`` -- finite field element
2445
+
2446
+ - ``proof``-- boolean (default: ``True``); if ``True``, returns a proved
2447
+ result. If ``False``, then a return value of ``False`` is certain but a
2448
+ return value of ``True`` may be based on a probabilistic test. See
2449
+ the ALGORITHM section below for more details.
2450
+
2451
+ OUTPUT: boolean; ``True`` if `j` is supersingular, else ``False``
2452
+
2453
+ ALGORITHM:
2454
+
2455
+ For small characteristics `p` we check whether the `j`-invariant
2456
+ is in a precomputed list of supersingular values. Otherwise we
2457
+ next check the `j`-invariant. If `j=0`, the curve is
2458
+ supersingular if and only if `p=2` or `p\equiv3\pmod{4}`; if
2459
+ `j=1728`, the curve is supersingular if and only if `p=3` or
2460
+ `p\equiv2\pmod{3}`. Next, if the base field is the prime field
2461
+ `{\rm GF}(p)`, we check that `(p+1)P=0` for several random points
2462
+ `P`, returning ``False`` if any fail: supersingular curves over `{\rm
2463
+ GF}(p)` have cardinality `p+1`. If Proof is false we now return
2464
+ ``True``. Otherwise we compute the cardinality and return ``True`` if and
2465
+ only if it is divisible by `p`.
2466
+
2467
+ EXAMPLES::
2468
+
2469
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import is_j_supersingular, supersingular_j_polynomials
2470
+ sage: [(p,[j for j in GF(p) if is_j_supersingular(j)]) for p in prime_range(30)]
2471
+ [(2, [0]), (3, [0]), (5, [0]), (7, [6]), (11, [0, 1]), (13, [5]),
2472
+ (17, [0, 8]), (19, [7, 18]), (23, [0, 3, 19]), (29, [0, 2, 25])]
2473
+
2474
+ sage: [j for j in GF(109) if is_j_supersingular(j)]
2475
+ [17, 41, 43]
2476
+ sage: PolynomialRing(GF(109),'j')(supersingular_j_polynomials[109]).roots()
2477
+ [(43, 1), (41, 1), (17, 1)]
2478
+
2479
+ sage: [p for p in prime_range(100) if is_j_supersingular(GF(p)(0))]
2480
+ [2, 3, 5, 11, 17, 23, 29, 41, 47, 53, 59, 71, 83, 89]
2481
+ sage: [p for p in prime_range(100) if is_j_supersingular(GF(p)(1728))]
2482
+ [2, 3, 7, 11, 19, 23, 31, 43, 47, 59, 67, 71, 79, 83]
2483
+ sage: [p for p in prime_range(100) if is_j_supersingular(GF(p)(123456))]
2484
+ [2, 3, 59, 89]
2485
+ """
2486
+ if not (isinstance(j, Element) and isinstance(j.parent(), FiniteField)):
2487
+ raise ValueError("%s must be an element of a finite field" % j)
2488
+
2489
+ F = j.parent()
2490
+ p = F.characteristic()
2491
+ d = F.degree()
2492
+
2493
+ if j.is_zero():
2494
+ return p == 3 or p % 3 == 2
2495
+
2496
+ if (j - 1728).is_zero():
2497
+ return p == 2 or p % 4 == 3
2498
+
2499
+ # From now on we know that j != 0, 1728
2500
+
2501
+ if p in (2, 3, 5, 7, 11):
2502
+ return False # since j=0, 1728 are the only s.s. invariants
2503
+
2504
+ # supersingular j-invariants have degree at most 2:
2505
+
2506
+ jpol = j.minimal_polynomial()
2507
+ degj = jpol.degree()
2508
+ if degj > 2:
2509
+ return False
2510
+
2511
+ # if p occurs in the precomputed list, use that:
2512
+
2513
+ fill_ss_j_dict()
2514
+ if p in supersingular_j_polynomials:
2515
+ return supersingular_j_polynomial(p)(j).is_zero()
2516
+
2517
+ # Over GF(p), supersingular elliptic curves have cardinality
2518
+ # exactly p+1, so we check some random points in order to detect
2519
+ # non-supersingularity. Over GF(p^2) (for p at least 5) the
2520
+ # cardinality is either (p-1)^2 or (p+1)^2, and the group has
2521
+ # exponent p+1 or p-1, so we can do a similar random check: unless
2522
+ # (p+1)*P=0 for all the random points, or (p-1)*P=0 for all of
2523
+ # them, we can certainly return False.
2524
+
2525
+ # First we replace j by an element of GF(p) or GF(p^2) (since F
2526
+ # might be a proper extension of these):
2527
+
2528
+ if degj == 1:
2529
+ j = -jpol(0) # = j, but in GF(p)
2530
+ elif d > 2:
2531
+ F = GF((p, 2), 'a')
2532
+ j = jpol.roots(F, multiplicities=False)[0] # j, but in GF(p^2)
2533
+
2534
+ E = EllipticCurve(j=j)
2535
+ if degj == 1:
2536
+ for i in range(10):
2537
+ P = E.random_element()
2538
+ if not ((p + 1) * P).is_zero():
2539
+ return False
2540
+ else:
2541
+ n = None # will hold either p+1 or p-1 later
2542
+ for i in range(10):
2543
+ P = E.random_element()
2544
+ # avoid 2-torsion; we know that a1=a3=0 and #E>4!
2545
+ while P[2].is_zero() or P[1].is_zero():
2546
+ P = E.random_element()
2547
+
2548
+ if n is None: # not yet decided between p+1 and p-1
2549
+ pP = p*P
2550
+ if pP[0] != P[0]: # i.e. pP is neither P nor -P
2551
+ return False
2552
+ if pP[1] == P[1]: # then p*P == P != -P
2553
+ n = p - 1
2554
+ else: # then p*P == -P != P
2555
+ n = p + 1
2556
+ else:
2557
+ if not (n*P).is_zero():
2558
+ return False
2559
+
2560
+ # when proof is False we return True for any curve which passes
2561
+ # the probabilistic test:
2562
+
2563
+ if not proof:
2564
+ return True
2565
+
2566
+ # otherwise we check the trace of Frobenius (which could be
2567
+ # expensive since it involves counting the number of points on E):
2568
+
2569
+ return E.trace_of_frobenius() % p == 0
2570
+
2571
+
2572
+ def special_supersingular_curve(F, q=None, *, endomorphism=False):
2573
+ r"""
2574
+ Given a finite field ``F`` of characteristic `p`, and optionally
2575
+ a positive integer `q` such that the Hilbert conductor of `-q`
2576
+ and `-p` equals `p`, construct a "special" supersingular elliptic
2577
+ curve `E` defined over ``F``.
2578
+
2579
+ Such a curve
2580
+
2581
+ - has coefficients in `\mathbb F_p`;
2582
+
2583
+ - has group structure `E(\mathbb F_p) \cong \ZZ/(p+1)` and
2584
+ `E(\mathbb F_{p^2}) \cong \ZZ/(p+1) \times \ZZ/(p+1)`;
2585
+
2586
+ - has an endomorphism `\vartheta` of degree `q` that
2587
+ anticommutes with the `\mathbb F_p`-Frobenius on `E`.
2588
+
2589
+ (The significance of `\vartheta` is that any such endomorphism,
2590
+ together with the `\mathbb F_p`-Frobenius, generates the endomorphism
2591
+ algebra `\mathrm{End}(E) \otimes \QQ`.)
2592
+
2593
+ The complexity grows exponentially in `\log(q)`. Automatically
2594
+ chosen values of `q` lie in `O((\log p)^2)` assuming GRH.
2595
+
2596
+ INPUT:
2597
+
2598
+ - ``F`` -- finite field `\mathbb F_{p^r}`
2599
+
2600
+ - ``q`` -- positive integer (optional, default ``None``)
2601
+
2602
+ - ``endomorphism`` -- boolean (default: ``False``); when set to ``True``,
2603
+ it is required that `2 \mid r`, and the function then additionally
2604
+ returns `\vartheta`
2605
+
2606
+ .. WARNING::
2607
+
2608
+ Due to :issue:`38481`, calling this function with a value of `q`
2609
+ larger than approximately `p/4` may currently fail. This failure
2610
+ will not occur for automatically chosen values of `q`.
2611
+
2612
+ EXAMPLES::
2613
+
2614
+ sage: special_supersingular_curve(GF(1013^2), endomorphism=True)
2615
+ (Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1013^2,
2616
+ Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1013^2 to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1013^2)
2617
+
2618
+ sage: special_supersingular_curve(GF(1019^2), endomorphism=True)
2619
+ (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1019^2,
2620
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1019^2
2621
+ Via: (u,r,s,t) = (389*z2 + 241, 0, 0, 0))
2622
+
2623
+ sage: special_supersingular_curve(GF(1021^2), endomorphism=True)
2624
+ (Elliptic Curve defined by y^2 = x^3 + 791*x + 230 over Finite Field in z2 of size 1021^2,
2625
+ Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 791*x + 230 over Finite Field in z2 of size 1021^2 to Elliptic Curve defined by y^2 = x^3 + 791*x + 230 over Finite Field in z2 of size 1021^2)
2626
+
2627
+ sage: special_supersingular_curve(GF(1031^2), endomorphism=True)
2628
+ (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1031^2,
2629
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1031^2
2630
+ Via: (u,r,s,t) = (747*z2 + 284, 0, 0, 0))
2631
+
2632
+ sage: special_supersingular_curve(GF(1033^2), endomorphism=True)
2633
+ (Elliptic Curve defined by y^2 = x^3 + 53*x + 980 over Finite Field in z2 of size 1033^2,
2634
+ Isogeny of degree 11 from Elliptic Curve defined by y^2 = x^3 + 53*x + 980 over Finite Field in z2 of size 1033^2 to Elliptic Curve defined by y^2 = x^3 + 53*x + 980 over Finite Field in z2 of size 1033^2)
2635
+
2636
+ sage: special_supersingular_curve(GF(1039^2), endomorphism=True)
2637
+ (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1039^2,
2638
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1039^2
2639
+ Via: (u,r,s,t) = (626*z2 + 200, 0, 0, 0))
2640
+
2641
+ sage: special_supersingular_curve(GF(1049^2), endomorphism=True)
2642
+ (Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1049^2,
2643
+ Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1049^2 to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 1049^2)
2644
+
2645
+ sage: special_supersingular_curve(GF(1051^2), endomorphism=True)
2646
+ (Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1051^2,
2647
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 1051^2
2648
+ Via: (u,r,s,t) = (922*z2 + 129, 0, 0, 0))
2649
+
2650
+ We can also supply a suitable value of `q` ourselves::
2651
+
2652
+ sage: special_supersingular_curve(GF(1019), q=99)
2653
+ Elliptic Curve defined by y^2 = x^3 + 211*x + 808 over Finite Field of size 1019
2654
+
2655
+ sage: special_supersingular_curve(GF(1019^2), q=99, endomorphism=True)
2656
+ (Elliptic Curve defined by y^2 = x^3 + 211*x + 808 over Finite Field in z2 of size 1019^2,
2657
+ Isogeny of degree 99 from Elliptic Curve defined by y^2 = x^3 + 211*x + 808 over Finite Field in z2 of size 1019^2 to Elliptic Curve defined by y^2 = x^3 + 211*x + 808 over Finite Field in z2 of size 1019^2)
2658
+
2659
+ sage: special_supersingular_curve(GF(1013), q=99)
2660
+ Traceback (most recent call last):
2661
+ ...
2662
+ ValueError: invalid choice of q
2663
+
2664
+ TESTS::
2665
+
2666
+ sage: p = random_prime(1000)
2667
+ sage: E = special_supersingular_curve(GF(p))
2668
+ sage: E.is_supersingular()
2669
+ True
2670
+ sage: E.order() == p + 1
2671
+ True
2672
+ sage: F.<t> = GF((p,2))
2673
+ sage: E, endo = special_supersingular_curve(F, endomorphism=True)
2674
+ sage: E.is_supersingular()
2675
+ True
2676
+ sage: E.j_invariant() in GF(p)
2677
+ True
2678
+ sage: E.abelian_group().invariants() == (p+1, p+1)
2679
+ True
2680
+ sage: endo.domain() is endo.codomain() is E
2681
+ True
2682
+ sage: endo.trace()
2683
+ 0
2684
+ sage: pi = E.frobenius_isogeny()
2685
+ sage: pi.codomain() is pi.domain() is E
2686
+ True
2687
+ sage: pi * endo == -endo * pi # needs sage.symbolic
2688
+ True
2689
+
2690
+ Also try it for larger-degree fields::
2691
+
2692
+ sage: k = ZZ(randrange(3, 10, 2))
2693
+ sage: E = special_supersingular_curve(GF((p, k)))
2694
+ sage: E.is_supersingular()
2695
+ True
2696
+ sage: F.<t> = GF((p, 2*k))
2697
+ sage: E, endo = special_supersingular_curve(F, endomorphism=True)
2698
+ sage: E.is_supersingular()
2699
+ True
2700
+ sage: E.j_invariant() in GF(p)
2701
+ True
2702
+ sage: endo.domain() is endo.codomain() is E
2703
+ True
2704
+ sage: endo.trace()
2705
+ 0
2706
+ sage: pi = E.frobenius_isogeny()
2707
+ sage: pi.codomain() is pi.domain() is E
2708
+ True
2709
+ sage: pi * endo == -endo * pi # needs sage.symbolic
2710
+ True
2711
+
2712
+ Also try it when `q` is given:
2713
+
2714
+ sage: p = random_prime(300, lbound=10)
2715
+ sage: k = ZZ(randrange(1, 5))
2716
+ sage: while True:
2717
+ ....: q = randrange(1, p//4) # upper bound p//4 is a workaround for #38481
2718
+ ....: if QuaternionAlgebra(-q, -p).discriminant() == p:
2719
+ ....: break
2720
+ sage: E = special_supersingular_curve(GF((p, k)), q)
2721
+ sage: E.is_supersingular()
2722
+ True
2723
+ sage: F.<t> = GF((p, 2*k))
2724
+ sage: E, endo = special_supersingular_curve(F, q, endomorphism=True)
2725
+ sage: E.is_supersingular()
2726
+ True
2727
+ sage: E.j_invariant() in GF(p)
2728
+ True
2729
+ sage: endo.domain() is endo.codomain() is E
2730
+ True
2731
+ sage: endo.degree() == q
2732
+ True
2733
+ sage: endo.trace()
2734
+ 0
2735
+ sage: pi = E.frobenius_isogeny()
2736
+ sage: pi.codomain() is pi.domain() is E
2737
+ True
2738
+ sage: pi * endo == -endo * pi # needs sage.symbolic
2739
+ True
2740
+
2741
+ .. NOTE::
2742
+
2743
+ This function makes no guarantees about the distribution of
2744
+ the output. The current implementation is deterministic in
2745
+ many cases.
2746
+
2747
+ ALGORITHM: [Bro2009]_, Algorithm 2.4
2748
+ """
2749
+ if not isinstance(F, FiniteField):
2750
+ raise TypeError('input must be a finite field')
2751
+ p = F.characteristic()
2752
+ deg = F.degree()
2753
+
2754
+ if endomorphism and deg % 2:
2755
+ raise ValueError('endomorphism was requested but is not defined over given field')
2756
+
2757
+ if q is not None:
2758
+ from sage.arith.misc import hilbert_conductor
2759
+ if p.divides(q) or hilbert_conductor(-q, -p) != p:
2760
+ raise ValueError('invalid choice of q')
2761
+
2762
+ # first find the degree q of our special endomorphism
2763
+ if q is None:
2764
+ if p == 2:
2765
+ q = 3
2766
+ elif p % 4 == 3:
2767
+ q = 1
2768
+ elif p % 3 == 2:
2769
+ q = 3
2770
+ elif p % 8 == 5:
2771
+ q = 2
2772
+ else:
2773
+ from sage.arith.misc import legendre_symbol
2774
+ for q in map(ZZ, range(3,p,4)):
2775
+ if not q.is_prime():
2776
+ continue
2777
+ if legendre_symbol(-q, p) == -1:
2778
+ break
2779
+ else: # should never happen
2780
+ assert False, 'bug in special_supersingular_curve()'
2781
+ q = ZZ(q)
2782
+
2783
+ from sage.arith.misc import fundamental_discriminant
2784
+ from sage.schemes.elliptic_curves.cm import hilbert_class_polynomial
2785
+ H = hilbert_class_polynomial(fundamental_discriminant(-q))
2786
+ j = H.change_ring(GF(p)).any_root()
2787
+ if j.is_zero():
2788
+ if p == 2:
2789
+ ainvs = [0,0,1,0,0]
2790
+ elif p == 3:
2791
+ ainvs = [1,0]
2792
+ else:
2793
+ ainvs = [0,1]
2794
+ elif j == 1728:
2795
+ ainvs = [1,0]
2796
+ else:
2797
+ a = 27 * j / (4 * (1728-j))
2798
+ ainvs = [a,-a]
2799
+ E = EllipticCurve(F, ainvs)
2800
+
2801
+ if ZZ(2).divides(deg):
2802
+ k = deg//2
2803
+ E.set_order((p**k - (-1)**k)**2)
2804
+ else:
2805
+ E.set_order(p**deg - (-1)**deg)
2806
+
2807
+ if not endomorphism:
2808
+ return E
2809
+
2810
+ if q.is_one():
2811
+ endo = next(auto for auto in E.automorphisms() if auto.trace().is_zero())
2812
+ else:
2813
+ iso = E.isomorphism(F(-q).sqrt(), is_codomain=True)
2814
+ try:
2815
+ endo = iso * E.isogeny(None, iso.domain(), degree=q)
2816
+ except (NotImplementedError, ValueError): #FIXME catching ValueError here is a workaround for #38481
2817
+ endos = (iso*phi for phi in E.isogenies_degree(q)
2818
+ for iso in phi.codomain().isomorphisms(E))
2819
+ endo = next(endo for endo in endos if endo.trace().is_zero())
2820
+
2821
+ endo._degree = ZZ(q)
2822
+ endo.trace.set_cache(ZZ.zero())
2823
+ return E, endo
2824
+
2825
+
2826
+ def EllipticCurve_with_order(m, *, D=None):
2827
+ r"""
2828
+ Return an iterator for elliptic curves over finite fields with the given order. The curves are
2829
+ computed using the Complex Multiplication (CM) method.
2830
+
2831
+ A :class:`~sage.structure.factorization.Factorization` can be passed for ``m``, in which case
2832
+ the algorithm is more efficient.
2833
+
2834
+ If ``D`` is specified, it is used as the discriminant.
2835
+
2836
+ EXAMPLES::
2837
+
2838
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import EllipticCurve_with_order
2839
+ sage: E = next(EllipticCurve_with_order(1234)); E # random
2840
+ Elliptic Curve defined by y^2 = x^3 + 1142*x + 1209 over Finite Field of size 1237
2841
+ sage: E.order() == 1234
2842
+ True
2843
+
2844
+ When ``iter`` is set, the function returns an iterator of all elliptic curves with the given
2845
+ order::
2846
+
2847
+ sage: from sage.schemes.elliptic_curves.ell_finite_field import EllipticCurve_with_order
2848
+ sage: it = EllipticCurve_with_order(21); it
2849
+ <generator object EllipticCurve_with_order at 0x...>
2850
+ sage: E = next(it); E # random
2851
+ Elliptic Curve defined by y^2 = x^3 + 6*x + 14 over Finite Field of size 23
2852
+ sage: E.order() == 21
2853
+ True
2854
+ sage: Es = [E] + list(it); Es # random
2855
+ [Elliptic Curve defined by y^2 = x^3 + 6*x + 14 over Finite Field of size 23,
2856
+ Elliptic Curve defined by y^2 = x^3 + 12*x + 4 over Finite Field of size 23,
2857
+ Elliptic Curve defined by y^2 = x^3 + 5*x + 2 over Finite Field of size 23,
2858
+ Elliptic Curve defined by y^2 = x^3 + (z2+3) over Finite Field in z2 of size 5^2,
2859
+ Elliptic Curve defined by y^2 = x^3 + (2*z2+2) over Finite Field in z2 of size 5^2,
2860
+ Elliptic Curve defined by y^2 = x^3 + 7*x + 1 over Finite Field of size 19,
2861
+ Elliptic Curve defined by y^2 = x^3 + 17*x + 10 over Finite Field of size 19,
2862
+ Elliptic Curve defined by y^2 = x^3 + 5*x + 12 over Finite Field of size 17,
2863
+ Elliptic Curve defined by y^2 = x^3 + 9*x + 1 over Finite Field of size 17,
2864
+ Elliptic Curve defined by y^2 = x^3 + 7*x + 6 over Finite Field of size 17,
2865
+ Elliptic Curve defined by y^2 = x^3 + z3^2*x^2 + (2*z3^2+z3) over Finite Field in z3 of size 3^3,
2866
+ Elliptic Curve defined by y^2 = x^3 + (z3^2+2*z3+1)*x^2 + (2*z3^2+2*z3) over Finite Field in z3 of size 3^3,
2867
+ Elliptic Curve defined by y^2 = x^3 + (z3^2+z3+1)*x^2 + (2*z3^2+1) over Finite Field in z3 of size 3^3,
2868
+ Elliptic Curve defined by y^2 + (z4^2+z4+1)*y = x^3 over Finite Field in z4 of size 2^4,
2869
+ Elliptic Curve defined by y^2 + (z4^2+z4)*y = x^3 over Finite Field in z4 of size 2^4,
2870
+ Elliptic Curve defined by y^2 = x^3 + 18*x + 26 over Finite Field of size 29,
2871
+ Elliptic Curve defined by y^2 = x^3 + 11*x + 19 over Finite Field of size 29,
2872
+ Elliptic Curve defined by y^2 = x^3 + 4 over Finite Field of size 19,
2873
+ Elliptic Curve defined by y^2 = x^3 + 19 over Finite Field of size 31,
2874
+ Elliptic Curve defined by y^2 = x^3 + 4 over Finite Field of size 13]
2875
+ sage: all(E.order() == 21 for E in Es)
2876
+ True
2877
+
2878
+ Indeed, we can verify that this is correct. Hasse's bounds tell us that
2879
+ `p \leq 50` (approximately), and the rest can be checked via bruteforce::
2880
+
2881
+ sage: for p in prime_range(50):
2882
+ ....: for j in range(p):
2883
+ ....: E0 = EllipticCurve(GF(p), j=j)
2884
+ ....: for Et in E0.twists():
2885
+ ....: if Et.order() == 21:
2886
+ ....: assert any(Et.is_isomorphic(E) for E in Es)
2887
+
2888
+ .. NOTE::
2889
+
2890
+ The output curves are not deterministic, as :func:`EllipticCurve_finite_field.twists` is not
2891
+ deterministic. However, the order of the j-invariants and base fields is fixed.
2892
+
2893
+ AUTHORS:
2894
+
2895
+ - Gareth Ma and Giacomo Pope (Sage Days 123): initial version
2896
+ """
2897
+ from sage.arith.misc import is_prime_power, factor
2898
+ from sage.quadratic_forms.binary_qf import BinaryQF
2899
+ from sage.structure.factorization import Factorization
2900
+ from sage.schemes.elliptic_curves.cm import hilbert_class_polynomial
2901
+
2902
+ def find_q(m, m4_fac, D):
2903
+ for t, _ in BinaryQF(1, 0, -D).solve_integer(m4_fac, _flag=3):
2904
+ yield m + 1 - t
2905
+ yield m + 1 + t
2906
+
2907
+ if isinstance(m, Factorization):
2908
+ m4_fac = m * factor(4)
2909
+ m_val = m.value()
2910
+ else:
2911
+ m4_fac = factor(m * 4)
2912
+ m_val = m
2913
+
2914
+ if D is None:
2915
+ Ds = (D for D in range(-1, -4 * m_val - 1, -1) if D % 4 in [0, 1])
2916
+ else:
2917
+ assert D < 0 and D % 4 in [0, 1]
2918
+ Ds = [D]
2919
+
2920
+ seen = set()
2921
+ for D in Ds:
2922
+ for q in find_q(m_val, m4_fac, D):
2923
+ if not is_prime_power(q):
2924
+ continue
2925
+
2926
+ H = hilbert_class_polynomial(D)
2927
+ for j0 in H.roots(ring=GF(q), multiplicities=False):
2928
+ E = EllipticCurve(j=j0)
2929
+ for Et in E.twists():
2930
+ if any(Et.is_isomorphic(E) for E in seen):
2931
+ continue
2932
+ # This tests whether the curve has given order
2933
+ if Et.has_order(m_val):
2934
+ # TODO: remove after 38617
2935
+ Et.set_order(m_val, check=False)
2936
+ seen.add(Et)
2937
+ yield Et
2938
+
2939
+
2940
+ def EllipticCurve_with_prime_order(N):
2941
+ r"""
2942
+ Given a prime number ``N``, find another prime number `p` and construct an
2943
+ elliptic curve `E` defined over `\mathbb F_p` such that
2944
+ `\#E(\mathbb F_p) = N`.
2945
+
2946
+ INPUT:
2947
+
2948
+ - ``N`` -- integer; the order for which we seek an elliptic curve. Must be a
2949
+ prime number.
2950
+
2951
+ OUTPUT: an iterator of (some) elliptic curves `E/\mathbb F_p` of order ``N``
2952
+
2953
+ ALGORITHM:
2954
+
2955
+ Our algorithm is based on [BS2007]_, Algorithm 2.2, but we deviate for
2956
+ several key steps. Firstly, the authors in the paper perform the search for
2957
+ a suitable `D` *incrementally*, by enlarging the table `S` by `log(N)`-size
2958
+ interval of primes `p` and testing all products of distinct primes `p` (or
2959
+ rather `p^*`). We find this difficult to implement without testing
2960
+ duplicate `D`\s, so we instead enlarge the table one prime at a time
2961
+ (effectively replacing `[r\log(N), (r + 1)\log(N)]` in the paper by `[r,
2962
+ r]`). To compensate for the speed loss, we begin the algorithm by
2963
+ prefilling `S` with the primes below `1000` (satisfying quadratic
2964
+ reciprocity properties). The constant `1000` is determined experimentally
2965
+ to be fast for many purposes, and for most `N` we tested we are able to
2966
+ find a suitable small `D` without increasing the size of `S`.
2967
+
2968
+ The paper also doesn't specify how to enumerate such `D`\s, which recall
2969
+ should be product of distinct values in the table `S`. We implement this
2970
+ with a priority queue (min heap), which also allows us to search for the
2971
+ suitable `D`\s in increasing (absolute value) order. This is suitable for
2972
+ the algorithm because smaller `D` means the Hilbert class polynomial is
2973
+ computed quicker.
2974
+
2975
+ Finally, to avoid repeatedly testing the same `D`\s, we require the latest
2976
+ prime to be added to the table to be included as a factor of `D` (see code
2977
+ for more explanation). As we need to find integers `x, y` such that `x^2 +
2978
+ (-D)y^2 = 4N` with `D < 0` and `N` prime, we actually need `|D| \leq 4N`,
2979
+ so we terminate the algorithm when the primes in the table are larger than
2980
+ that bound. This makes the iterator return all curves it can find in finite
2981
+ time.
2982
+
2983
+ ALGORITHM: Based on [BS2007]_, Algorithm 2.2
2984
+
2985
+ EXAMPLES::
2986
+
2987
+ sage: N = 8314040072427107567
2988
+ sage: E = next(EllipticCurve_with_prime_order(N))
2989
+ sage: E
2990
+ Elliptic Curve defined by y^2 = x^3 + 4757897140353078952*x + 1841350074072114366
2991
+ over Finite Field of size 8314040074357871443
2992
+ sage: E.has_order(N)
2993
+ True
2994
+
2995
+ The returned curves are sometimes random because
2996
+ :meth:`~sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field.twists`
2997
+ is not deterministic. However, it's always isomorphic::
2998
+
2999
+ sage: E = next(EllipticCurve_with_prime_order(23)); E # random
3000
+ Elliptic Curve defined by y^2 = x^3 + 12*x + 6 over Finite Field of size 17
3001
+ sage: E.is_isomorphic(EllipticCurve(GF(17), [3, 5]))
3002
+ True
3003
+
3004
+ You can directly iterate over the iterator; here only on the first 10
3005
+ curves::
3006
+
3007
+ sage: N = 54675917
3008
+ sage: for _, E in zip(range(10), EllipticCurve_with_prime_order(N)):
3009
+ ....: assert E.has_order(N)
3010
+
3011
+ It works for large primes::
3012
+
3013
+ sage: N = 2666207849820848272386538889527600954292544013630953455833
3014
+ sage: E = next(EllipticCurve_with_prime_order(N)); E
3015
+ Elliptic Curve defined by y^2 = x^3 + 2666207849820848272386538889427721639173508298483739490459*x
3016
+ + 77986137112576 over Finite Field of size 2666207849820848272386538889427721639173508298487130585243
3017
+ sage: E.has_order(N)
3018
+ True
3019
+
3020
+ Another example for large primes::
3021
+
3022
+ sage: N = next_prime(2^256)
3023
+ sage: E = next(EllipticCurve_with_prime_order(N)); E # random
3024
+ Elliptic Curve defined by y^2 = x^3 + 6056521267553273205988520276135607487700943205131813669424576873701361709521*x
3025
+ + 86942739955486781674010637133214195706465136689012129911736706024465988573567 over Finite Field of size
3026
+ 115792089237316195423570985008687907853847329310253429036565151476471048389761
3027
+ sage: E.j_invariant()
3028
+ 111836223967433630316209796253554285080540088646141285337487360944738698436350
3029
+ sage: E.has_order(N)
3030
+ True
3031
+
3032
+ Note that the iterator does *not* return all curves with the given order::
3033
+
3034
+ sage: any(E.base_ring() is GF(7) for E in EllipticCurve_with_prime_order(7))
3035
+ False
3036
+ sage: EllipticCurve(GF(7), [0, 5]).order()
3037
+ 7
3038
+
3039
+ However, experimentally it returns many of them. Here it returns all of
3040
+ them::
3041
+
3042
+ sage: N = 23
3043
+ sage: set_random_seed(1337) # as the function returns random twists of curves
3044
+ sage: curves = list(EllipticCurve_with_prime_order(N)); curves # random
3045
+ [Elliptic Curve defined by y^2 = x^3 + 3*x + 5 over Finite Field of size 17,
3046
+ Elliptic Curve defined by y^2 = x^3 + 19*x + 14 over Finite Field of size 31,
3047
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 9 over Finite Field of size 19,
3048
+ Elliptic Curve defined by y^2 = x^3 + 7*x + 18 over Finite Field of size 29,
3049
+ Elliptic Curve defined by y^2 = x^3 + 20*x + 20 over Finite Field of size 23,
3050
+ Elliptic Curve defined by y^2 = x^3 + 10*x + 16 over Finite Field of size 23]
3051
+ sage: import itertools
3052
+ sage: # These are the only primes, by the Hasse-Weil bound
3053
+ sage: for q in prime_range(17, 35):
3054
+ ....: K = GF(q)
3055
+ ....: for u in itertools.product(range(q), repeat=2):
3056
+ ....: try: E = EllipticCurve(GF(q), u)
3057
+ ....: except ArithmeticError: continue
3058
+ ....: if E.has_order(N):
3059
+ ....: assert any(E.is_isomorphic(E_) for E_ in curves)
3060
+
3061
+ The algorithm is efficient for small ``N`` due to the low number of suitable
3062
+ discriminants (see the ``abs_products_under`` internal function of the code
3063
+ for details)::
3064
+
3065
+ sage: len(list(EllipticCurve_with_prime_order(next_prime(5000))))
3066
+ 534
3067
+ sage: len(list(EllipticCurve_with_prime_order(next_prime(50000)))) # long time (6s)
3068
+ 3841
3069
+
3070
+ There is different verbose data for level `2` to `4`, though level `3`
3071
+ rarely logs anything (it logs when a new prime `p` is added to the
3072
+ smoothness bound)::
3073
+
3074
+ sage: from sage.misc.verbose import set_verbose
3075
+ sage: set_random_seed(1337) # as the function returns random twists of curves
3076
+ sage: for _, E in zip(range(3), EllipticCurve_with_prime_order(10^9 + 7)):
3077
+ ....: print(E)
3078
+ Elliptic Curve defined by y^2 = x^3 + 265977778*x + 120868502 over Finite Field of size 1000041437
3079
+ Elliptic Curve defined by y^2 = x^3 + 689795416*x + 188156157 over Finite Field of size 999969307
3080
+ Elliptic Curve defined by y^2 = x^3 + 999178436*x + 900579394 over Finite Field of size 999969307
3081
+ sage: set_verbose(2)
3082
+ sage: set_random_seed(1337)
3083
+ sage: for _, E in zip(range(3), EllipticCurve_with_prime_order(10^9 + 7)):
3084
+ ....: print(E)
3085
+ verbose 2 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Computing the Hilbert class polynomial H_-163
3086
+ Elliptic Curve defined by y^2 = x^3 + 265977778*x + 120868502 over Finite Field of size 1000041437
3087
+ verbose 2 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Computing the Hilbert class polynomial H_-667
3088
+ Elliptic Curve defined by y^2 = x^3 + 689795416*x + 188156157 over Finite Field of size 999969307
3089
+ Elliptic Curve defined by y^2 = x^3 + 999178436*x + 900579394 over Finite Field of size 999969307
3090
+ sage: set_verbose(4)
3091
+ sage: set_random_seed(1337)
3092
+ sage: for _, E in zip(range(3), EllipticCurve_with_prime_order(10^9 + 7)):
3093
+ ....: print(E)
3094
+ verbose 4 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Testing D=-19
3095
+ ...
3096
+ verbose 4 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Testing D=-163
3097
+ verbose 2 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Computing the Hilbert class polynomial H_-163
3098
+ Elliptic Curve defined by y^2 = x^3 + 265977778*x + 120868502 over Finite Field of size 1000041437
3099
+ verbose 4 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Testing D=-179
3100
+ ...
3101
+ verbose 4 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Testing D=-667
3102
+ verbose 2 (...: ell_finite_field.py, EllipticCurve_with_prime_order) Computing the Hilbert class polynomial H_-667
3103
+ Elliptic Curve defined by y^2 = x^3 + 689795416*x + 188156157 over Finite Field of size 999969307
3104
+ Elliptic Curve defined by y^2 = x^3 + 999178436*x + 900579394 over Finite Field of size 999969307
3105
+
3106
+ TESTS::
3107
+
3108
+ sage: list(EllipticCurve_with_prime_order(2))
3109
+ [Elliptic Curve defined by y^2 + x*y + y = x^3 + 1 over Finite Field of size 2,
3110
+ Elliptic Curve defined by y^2 = x^3 + 2*x^2 + 2 over Finite Field of size 3,
3111
+ Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 5]
3112
+
3113
+ sage: set_verbose(0)
3114
+ sage: for N in prime_range(3, 100):
3115
+ ....: E = next(EllipticCurve_with_prime_order(N))
3116
+ ....: assert E.has_order(N)
3117
+
3118
+ sage: N = 113
3119
+ sage: for _, E in zip(range(30), EllipticCurve_with_prime_order(N)):
3120
+ ....: assert E.has_order(N)
3121
+
3122
+ sage: N = 15175980689839334471
3123
+ sage: E = next(EllipticCurve_with_prime_order(N))
3124
+ sage: E.has_order(N)
3125
+ True
3126
+
3127
+ sage: N = next_prime(123456789)
3128
+ sage: E = next(EllipticCurve_with_prime_order(N))
3129
+ sage: E.has_order(N)
3130
+ True
3131
+
3132
+ sage: N = 123456789
3133
+ sage: E = next(EllipticCurve_with_prime_order(N))
3134
+ Traceback (most recent call last):
3135
+ ...
3136
+ ValueError: input order is not a prime
3137
+
3138
+ sage: E = next(EllipticCurve_with_prime_order(0))
3139
+ Traceback (most recent call last):
3140
+ ...
3141
+ ValueError: input order is not a prime
3142
+
3143
+ sage: E = next(EllipticCurve_with_prime_order(-7))
3144
+ Traceback (most recent call last):
3145
+ ...
3146
+ ValueError: input order is not a prime
3147
+
3148
+ AUTHORS:
3149
+
3150
+ - Martin Grenouilloux, Gareth Ma (2024-09): initial implementation
3151
+ """
3152
+ import itertools
3153
+ from sage.arith.misc import is_prime, legendre_symbol
3154
+ from sage.misc.verbose import verbose
3155
+ from sage.quadratic_forms.binary_qf import BinaryQF
3156
+ from sage.rings.fast_arith import prime_range
3157
+ from sage.schemes.elliptic_curves.cm import hilbert_class_polynomial
3158
+ from sage.sets.primes import Primes
3159
+
3160
+ if not is_prime(N):
3161
+ raise ValueError("input order is not a prime")
3162
+
3163
+ if N == 2:
3164
+ yield from [
3165
+ EllipticCurve(GF(2), [1, 0, 1, 0, 1]),
3166
+ EllipticCurve(GF(3), [0, 2, 0, 0, 2]),
3167
+ EllipticCurve(GF(5), [2, 0])
3168
+ ]
3169
+ return
3170
+
3171
+ # We start with small primes directly to accelerate the search. Note that
3172
+ # 1000 is a magic constant, it's just fast enough to compute without
3173
+ # sacrificing much speed.
3174
+ # The if-then-else term is (-1)^((p - 1) / 2) * p in [BS2007]_ page 5.
3175
+ S = [(-p if p % 4 == 3 else p) for p in prime_range(3, min(1000, 4 * N))
3176
+ if legendre_symbol(N, p) == 1]
3177
+
3178
+ def abs_products_under(bound):
3179
+ """
3180
+ This function returns an iterator of all numbers with absolute
3181
+ value not exceeding ``bound`` expressible as product of
3182
+ distinct elements in ``S`` in ascending order.
3183
+ """
3184
+ import heapq
3185
+ hq = [(1, 1, -1)]
3186
+ while hq:
3187
+ abs_n, n, idx = heapq.heappop(hq)
3188
+ yield n
3189
+ for nxt in range(idx + 1, len(S)):
3190
+ if abs_n * abs(S[nxt]) <= bound:
3191
+ heapq.heappush(hq, (abs_n * abs(S[nxt]), n * S[nxt], nxt))
3192
+ else:
3193
+ break
3194
+
3195
+ # We add p = 1 to process the small primes.
3196
+ for p in itertools.chain([1], Primes()):
3197
+ if p != 1:
3198
+ if p < abs(S[-1]):
3199
+ continue
3200
+
3201
+ if legendre_symbol(N, p) != 1:
3202
+ continue
3203
+
3204
+ # Later we need x^2 + (-D)y^2 = 4N, and since y = 0 has no
3205
+ # solution, we need p = |p_star| <= |-D| <= 4N. This is a stopping
3206
+ # condition for the algorithm.
3207
+ if p > 4 * N:
3208
+ break
3209
+
3210
+ verbose(f"Considering {len(S) + 1}th valid prime {p}", level=3)
3211
+
3212
+ p_star = -p if p % 4 == 3 else p
3213
+
3214
+ for e in abs_products_under(4 * N // p):
3215
+ # According to the paper, the expected minimum D to work is
3216
+ # O(log(N)^2)
3217
+ D = p_star * e
3218
+ assert abs(D) <= 4 * N
3219
+
3220
+ if D % 8 != 5 or D >= 0:
3221
+ continue
3222
+
3223
+ verbose(f"Testing {D=}", level=4)
3224
+
3225
+ Q = BinaryQF([1, 0, -D])
3226
+ sol = Q.solve_integer(4 * N, algorithm='cornacchia')
3227
+ if sol is None:
3228
+ continue
3229
+
3230
+ x, _ = sol
3231
+ for p_i in [N + 1 - x, N + 1 + x]:
3232
+ if is_prime(p_i):
3233
+ verbose(f"Computing the Hilbert class polynomial H_{D}",
3234
+ level=2)
3235
+ H = hilbert_class_polynomial(D)
3236
+ K = GF(p_i)
3237
+ for j0 in H.roots(ring=K, multiplicities=False):
3238
+ E = EllipticCurve(K, j=j0)
3239
+ # `E.twists()` also contains E.
3240
+ for Et in E.twists():
3241
+ # `num_checks=1` is sufficient for prime order
3242
+ if Et.has_order(N, num_checks=1):
3243
+ # TODO: remove after 38617
3244
+ Et.set_order(N, check=False)
3245
+ yield Et
3246
+
3247
+ if p != 1:
3248
+ # Extending our prime list and continuing onto the next round.
3249
+ S.append(p_star)