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,2837 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Elliptic curves over a general field
4
+
5
+ This module defines the class :class:`EllipticCurve_field`, based on
6
+ :class:`EllipticCurve_generic`, for elliptic curves over general fields.
7
+ """
8
+ # *****************************************************************************
9
+ # Copyright (C) 2006 William Stein <wstein@gmail.com>
10
+ #
11
+ # Distributed under the terms of the GNU General Public License (GPL)
12
+ #
13
+ # https://www.gnu.org/licenses/
14
+ # *****************************************************************************
15
+
16
+ import sage.rings.abc
17
+ from sage.categories.number_fields import NumberFields
18
+ from sage.categories.finite_fields import FiniteFields
19
+ from sage.rings.integer import Integer
20
+ from sage.rings.integer_ring import ZZ
21
+ from sage.rings.polynomial.polynomial_ring import polygen
22
+ from sage.rings.rational_field import QQ
23
+ from sage.misc.misc_c import prod
24
+ from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field
25
+ from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field
26
+
27
+ from .constructor import EllipticCurve
28
+ from .ell_curve_isogeny import EllipticCurveIsogeny, isogeny_codomain_from_kernel
29
+ from . import ell_generic
30
+
31
+
32
+ class EllipticCurve_field(ell_generic.EllipticCurve_generic, ProjectivePlaneCurve_field):
33
+
34
+ def __init__(self, R, data, category=None) -> None:
35
+ r"""
36
+ Constructor for elliptic curves over fields.
37
+
38
+ Identical to the constructor for elliptic curves over
39
+ general rings, except for setting the default category
40
+ to :class:`AbelianVarieties`.
41
+
42
+ EXAMPLES::
43
+
44
+ sage: E = EllipticCurve(QQ, [1,1])
45
+ sage: E.category()
46
+ Category of abelian varieties over Rational Field
47
+ sage: E = EllipticCurve(GF(101), [1,1])
48
+ sage: E.category()
49
+ Category of abelian varieties over Finite Field of size 101
50
+ """
51
+ from sage.categories.schemes import AbelianVarieties
52
+ if category is None:
53
+ category = AbelianVarieties(R)
54
+ super().__init__(R, data, category=category)
55
+
56
+ base_field = ell_generic.EllipticCurve_generic.base_ring
57
+
58
+ _point = EllipticCurvePoint_field
59
+
60
+ # Twists: rewritten by John Cremona as follows:
61
+ #
62
+ # Quadratic twist allowed except when char=2, j=0
63
+ # Quartic twist allowed only if j=1728!=0 (so char!=2,3)
64
+ # Sextic twist allowed only if j=0!=1728 (so char!=2,3)
65
+ #
66
+ # More complicated twists exist in theory for char=2,3 and
67
+ # j=0=1728, but I have never worked them out or seen them used!
68
+ #
69
+
70
+ def genus(self) -> Integer:
71
+ """
72
+ Return 1 for elliptic curves.
73
+
74
+ EXAMPLES::
75
+
76
+ sage: E = EllipticCurve(GF(3), [0, -1, 0, -346, 2652])
77
+ sage: E.genus()
78
+ 1
79
+
80
+ sage: R = FractionField(QQ['z'])
81
+ sage: E = EllipticCurve(R, [0, -1, 0, -346, 2652])
82
+ sage: E.genus()
83
+ 1
84
+ """
85
+ return ZZ.one()
86
+
87
+ r"""
88
+ Twists: rewritten by John Cremona as follows:
89
+
90
+ The following twists are implemented:
91
+
92
+ - Quadratic twist: except when char=2 and `j=0`.
93
+ - Quartic twist: only if `j=1728\not=0` (so not if char=2,3).
94
+ - Sextic twist: only if `j=0\not=1728` (so not if char=2,3).
95
+
96
+ More complicated twists exist in theory for char=2,3 and j=0=1728,
97
+ but are not implemented.
98
+ """
99
+
100
+ def quadratic_twist(self, D=None):
101
+ r"""
102
+ Return the quadratic twist of this curve by ``D``.
103
+
104
+ INPUT:
105
+
106
+ - ``D`` -- (default: ``None``) the twisting parameter (see below)
107
+
108
+ In characteristics other than 2, `D` must be nonzero, and the
109
+ twist is isomorphic to ``self`` after adjoining `\sqrt(D)` to the
110
+ base.
111
+
112
+ In characteristic 2, `D` is arbitrary, and the twist is
113
+ isomorphic to ``self`` after adjoining a root of `x^2+x+D` to the
114
+ base.
115
+
116
+ In characteristic 2 when `j=0`, this is not implemented.
117
+
118
+ If the base field `F` is finite, `D` need not be specified,
119
+ and the curve returned is the unique curve (up to isomorphism)
120
+ defined over `F` isomorphic to the original curve over the
121
+ quadratic extension of `F` but not over `F` itself. Over
122
+ infinite fields, an error is raised if `D` is not given.
123
+
124
+ EXAMPLES::
125
+
126
+ sage: # needs sage.rings.finite_rings
127
+ sage: E = EllipticCurve([GF(1103)(1), 0, 0, 107, 340]); E
128
+ Elliptic Curve defined by y^2 + x*y = x^3 + 107*x + 340
129
+ over Finite Field of size 1103
130
+ sage: F = E.quadratic_twist(-1); F
131
+ Elliptic Curve defined by y^2 = x^3 + 1102*x^2 + 609*x + 300
132
+ over Finite Field of size 1103
133
+ sage: E.is_isomorphic(F)
134
+ False
135
+ sage: E.is_isomorphic(F, GF(1103^2,'a'))
136
+ True
137
+
138
+ A characteristic 2 example::
139
+
140
+ sage: E = EllipticCurve(GF(2), [1,0,1,1,1])
141
+ sage: E1 = E.quadratic_twist(1)
142
+ sage: E.is_isomorphic(E1)
143
+ False
144
+ sage: E.is_isomorphic(E1, GF(4,'a'))
145
+ True
146
+
147
+ Over finite fields, the twisting parameter may be omitted::
148
+
149
+ sage: # needs sage.rings.finite_rings
150
+ sage: k.<a> = GF(2^10)
151
+ sage: E = EllipticCurve(k, [a^2,a,1,a+1,1])
152
+ sage: Et = E.quadratic_twist()
153
+ sage: Et # random (only determined up to isomorphism)
154
+ Elliptic Curve defined
155
+ by y^2 + x*y = x^3 + (a^7+a^4+a^3+a^2+a+1)*x^2 + (a^8+a^6+a^4+1)
156
+ over Finite Field in a of size 2^10
157
+ sage: E.is_isomorphic(Et)
158
+ False
159
+ sage: E.j_invariant() == Et.j_invariant()
160
+ True
161
+
162
+ sage: # needs sage.rings.finite_rings
163
+ sage: p = next_prime(10^10)
164
+ sage: k = GF(p)
165
+ sage: E = EllipticCurve(k, [1,2,3,4,5])
166
+ sage: Et = E.quadratic_twist()
167
+ sage: Et # random (only determined up to isomorphism)
168
+ Elliptic Curve defined
169
+ by y^2 = x^3 + 7860088097*x^2 + 9495240877*x + 3048660957
170
+ over Finite Field of size 10000000019
171
+ sage: E.is_isomorphic(Et)
172
+ False
173
+ sage: k2 = GF(p^2,'a')
174
+ sage: E.change_ring(k2).is_isomorphic(Et.change_ring(k2))
175
+ True
176
+ """
177
+ K = self.base_ring()
178
+ char = K.characteristic()
179
+
180
+ if D is None:
181
+ if K.is_finite():
182
+ x = polygen(K)
183
+ if char == 2:
184
+ # We find D such that x^2+x+D is irreducible. If the
185
+ # degree is odd we can take D=1; otherwise it suffices to
186
+ # consider odd powers of a generator.
187
+ D = K(1)
188
+ if K.degree() % 2 == 0:
189
+ D = K.gen()
190
+ a = D**2
191
+ while (x**2 + x + D).roots():
192
+ D *= a
193
+ else:
194
+ # We could take a multiplicative generator but
195
+ # that might be expensive to compute; otherwise
196
+ # half the elements will do, and testing squares
197
+ # is very fast.
198
+ D = K.random_element()
199
+ while D.is_square():
200
+ D = K.random_element()
201
+ else:
202
+ raise ValueError("twisting parameter D must be specified over infinite fields.")
203
+ else:
204
+ try:
205
+ D = K(D)
206
+ except ValueError:
207
+ raise ValueError("twisting parameter D must be in the base field.")
208
+
209
+ if char != 2 and D.is_zero():
210
+ raise ValueError("twisting parameter D must be nonzero when characteristic is not 2")
211
+
212
+ if char != 2:
213
+ b2, b4, b6, b8 = self.b_invariants()
214
+ # E is isomorphic to [0,b2,0,8*b4,16*b6]
215
+ return EllipticCurve(K, [0, b2*D, 0, 8*b4*D**2, 16*b6*D**3])
216
+
217
+ # now char==2
218
+ if self.j_invariant() != 0: # iff a1!=0
219
+ a1, a2, a3, a4, a6 = self.ainvs()
220
+ E0 = self.change_weierstrass_model(a1, a3/a1, 0, (a1**2*a4+a3**2)/a1**3)
221
+ # which has the form = [1,A2,0,0,A6]
222
+ assert E0.a1() == K(1)
223
+ assert E0.a3() == K(0)
224
+ assert E0.a4() == K(0)
225
+ return EllipticCurve(K, [1, E0.a2() + D, 0, 0, E0.a6()])
226
+ else:
227
+ raise ValueError("Quadratic twist not implemented in char 2 when j=0")
228
+
229
+ def two_torsion_rank(self):
230
+ r"""
231
+ Return the dimension of the 2-torsion subgroup of
232
+ `E(K)`.
233
+
234
+ This will be 0, 1 or 2.
235
+
236
+ EXAMPLES::
237
+
238
+ sage: # needs database_cremona_mini_ellcurve
239
+ sage: E = EllipticCurve('11a1')
240
+ sage: E.two_torsion_rank()
241
+ 0
242
+ sage: K.<alpha> = QQ.extension(E.division_polynomial(2).monic()) # needs sage.rings.number_field
243
+ sage: E.base_extend(K).two_torsion_rank() # needs sage.rings.number_field
244
+ 1
245
+ sage: E.reduction(53).two_torsion_rank()
246
+ 2
247
+
248
+ ::
249
+
250
+ sage: # needs database_cremona_mini_ellcurve
251
+ sage: E = EllipticCurve('14a1')
252
+ sage: E.two_torsion_rank()
253
+ 1
254
+ sage: f = E.division_polynomial(2).monic().factor()[1][0]
255
+ sage: K.<alpha> = QQ.extension(f) # needs sage.rings.number_field
256
+ sage: E.base_extend(K).two_torsion_rank() # needs sage.rings.number_field
257
+ 2
258
+
259
+ ::
260
+
261
+ sage: EllipticCurve('15a1').two_torsion_rank() # needs database_cremona_mini_ellcurve
262
+ 2
263
+ """
264
+ f = self.division_polynomial(Integer(2))
265
+ n = len(f.roots()) + 1
266
+ return Integer(n).ord(Integer(2))
267
+
268
+ def quartic_twist(self, D):
269
+ r"""
270
+ Return the quartic twist of this curve by `D`.
271
+
272
+ INPUT:
273
+
274
+ - ``D`` -- (must be nonzero) the twisting parameter
275
+
276
+ .. NOTE::
277
+
278
+ The characteristic must not be 2 or 3, and the `j`-invariant must be 1728.
279
+
280
+ EXAMPLES::
281
+
282
+ sage: # needs sage.rings.finite_rings
283
+ sage: E = EllipticCurve_from_j(GF(13)(1728)); E
284
+ Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 13
285
+ sage: E1 = E.quartic_twist(2); E1
286
+ Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 13
287
+ sage: E.is_isomorphic(E1)
288
+ False
289
+ sage: E.is_isomorphic(E1, GF(13^2,'a'))
290
+ False
291
+ sage: E.is_isomorphic(E1, GF(13^4,'a'))
292
+ True
293
+ """
294
+ K = self.base_ring()
295
+ char = K.characteristic()
296
+ D = K(D)
297
+
298
+ if char == 2 or char == 3:
299
+ raise ValueError("Quartic twist not defined in chars 2,3")
300
+
301
+ if self.j_invariant() != K(1728):
302
+ raise ValueError("Quartic twist not defined when j!=1728")
303
+
304
+ if D.is_zero():
305
+ raise ValueError("quartic twist requires a nonzero argument")
306
+
307
+ c4, c6 = self.c_invariants()
308
+ # E is isomorphic to [0,0,0,-27*c4,0]
309
+ assert c6 == 0
310
+ return EllipticCurve(K, [0, 0, 0, -27 * c4 * D, 0])
311
+
312
+ def sextic_twist(self, D):
313
+ r"""
314
+ Return the sextic twist of this curve by `D`.
315
+
316
+ INPUT:
317
+
318
+ - ``D`` -- (must be nonzero) the twisting parameter
319
+
320
+ .. NOTE::
321
+
322
+ The characteristic must not be 2 or 3, and the `j`-invariant must be 0.
323
+
324
+ EXAMPLES::
325
+
326
+ sage: # needs sage.rings.finite_rings
327
+ sage: E = EllipticCurve_from_j(GF(13)(0)); E
328
+ Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 13
329
+ sage: E1 = E.sextic_twist(2); E1
330
+ Elliptic Curve defined by y^2 = x^3 + 11 over Finite Field of size 13
331
+ sage: E.is_isomorphic(E1)
332
+ False
333
+ sage: E.is_isomorphic(E1, GF(13^2,'a'))
334
+ False
335
+ sage: E.is_isomorphic(E1, GF(13^4,'a'))
336
+ False
337
+ sage: E.is_isomorphic(E1, GF(13^6,'a'))
338
+ True
339
+ """
340
+ K = self.base_ring()
341
+ char = K.characteristic()
342
+ D = K(D)
343
+
344
+ if char == 2 or char == 3:
345
+ raise ValueError("Sextic twist not defined in chars 2,3")
346
+
347
+ if self.j_invariant() != K(0):
348
+ raise ValueError("Sextic twist not defined when j!=0")
349
+
350
+ if D.is_zero():
351
+ raise ValueError("Sextic twist requires a nonzero argument")
352
+
353
+ c4, c6 = self.c_invariants()
354
+ # E is isomorphic to [0,0,0,0,-54*c6]
355
+ assert c4 == 0
356
+ return EllipticCurve(K, [0, 0, 0, 0, -54 * c6 * D])
357
+
358
+ def is_quadratic_twist(self, other):
359
+ r"""
360
+ Determine whether this curve is a quadratic twist of another.
361
+
362
+ INPUT:
363
+
364
+ - ``other`` -- an elliptic curve with the same base field as ``self``
365
+
366
+ OUTPUT:
367
+
368
+ Either 0, if the curves are not quadratic twists, or `D` if
369
+ ``other`` is ``self.quadratic_twist(D)`` (up to isomorphism).
370
+ If ``self`` and ``other`` are isomorphic, returns 1.
371
+
372
+ If the curves are defined over `\QQ`, the output `D` is
373
+ a squarefree integer.
374
+
375
+ .. NOTE::
376
+
377
+ Not fully implemented in characteristic 2, or in
378
+ characteristic 3 when both `j`-invariants are 0.
379
+
380
+ EXAMPLES::
381
+
382
+ sage: # needs database_cremona_mini_ellcurve
383
+ sage: E = EllipticCurve('11a1')
384
+ sage: Et = E.quadratic_twist(-24)
385
+ sage: E.is_quadratic_twist(Et)
386
+ -6
387
+
388
+ sage: E1 = EllipticCurve([0,0,1,0,0])
389
+ sage: E1.j_invariant()
390
+ 0
391
+ sage: E2 = EllipticCurve([0,0,0,0,2])
392
+ sage: E1.is_quadratic_twist(E2)
393
+ 2
394
+ sage: E1.is_quadratic_twist(E1)
395
+ 1
396
+ sage: type(E1.is_quadratic_twist(E1)) == type(E1.is_quadratic_twist(E2)) # Issue #6574
397
+ True
398
+
399
+ ::
400
+
401
+ sage: E1 = EllipticCurve([0,0,0,1,0])
402
+ sage: E1.j_invariant()
403
+ 1728
404
+ sage: E2 = EllipticCurve([0,0,0,2,0])
405
+ sage: E1.is_quadratic_twist(E2)
406
+ 0
407
+ sage: E2 = EllipticCurve([0,0,0,25,0])
408
+ sage: E1.is_quadratic_twist(E2)
409
+ 5
410
+
411
+ ::
412
+
413
+ sage: # needs sage.rings.finite_rings
414
+ sage: F = GF(101)
415
+ sage: E1 = EllipticCurve(F, [4,7])
416
+ sage: E2 = E1.quadratic_twist()
417
+ sage: D = E1.is_quadratic_twist(E2); D != 0
418
+ True
419
+ sage: F = GF(101)
420
+ sage: E1 = EllipticCurve(F, [4,7])
421
+ sage: E2 = E1.quadratic_twist()
422
+ sage: D = E1.is_quadratic_twist(E2)
423
+ sage: E1.quadratic_twist(D).is_isomorphic(E2)
424
+ True
425
+ sage: E1.is_isomorphic(E2)
426
+ False
427
+ sage: F2 = GF(101^2,'a')
428
+ sage: E1.change_ring(F2).is_isomorphic(E2.change_ring(F2))
429
+ True
430
+
431
+ A characteristic 3 example::
432
+
433
+ sage: # needs sage.rings.finite_rings
434
+ sage: F = GF(3^5,'a')
435
+ sage: E1 = EllipticCurve_from_j(F(1))
436
+ sage: E2 = E1.quadratic_twist(-1)
437
+ sage: D = E1.is_quadratic_twist(E2); D != 0
438
+ True
439
+ sage: E1.quadratic_twist(D).is_isomorphic(E2)
440
+ True
441
+
442
+ ::
443
+
444
+ sage: # needs sage.rings.finite_rings
445
+ sage: E1 = EllipticCurve_from_j(F(0))
446
+ sage: E2 = E1.quadratic_twist()
447
+ sage: D = E1.is_quadratic_twist(E2); D
448
+ 1
449
+ sage: E1.is_isomorphic(E2)
450
+ True
451
+ """
452
+ from sage.schemes.elliptic_curves.ell_generic import EllipticCurve_generic
453
+ E = self
454
+ F = other
455
+ if not isinstance(E, EllipticCurve_generic) or not isinstance(F, EllipticCurve_generic):
456
+ raise ValueError("arguments are not elliptic curves")
457
+ K = E.base_ring()
458
+ zero = K.zero()
459
+ if not K == F.base_ring():
460
+ return zero
461
+ j = E.j_invariant()
462
+ if j != F.j_invariant():
463
+ return zero
464
+
465
+ if E.is_isomorphic(F):
466
+ if K is QQ:
467
+ return ZZ(1)
468
+ return K.one()
469
+
470
+ char = K.characteristic()
471
+
472
+ if char == 2:
473
+ raise NotImplementedError("not implemented in characteristic 2")
474
+ elif char == 3:
475
+ if j == 0:
476
+ raise NotImplementedError("not implemented in characteristic 3 for curves of j-invariant 0")
477
+ D = E.b2() / F.b2()
478
+
479
+ else:
480
+ # now char!=2,3:
481
+ c4E, c6E = E.c_invariants()
482
+ c4F, c6F = F.c_invariants()
483
+
484
+ if j == 0:
485
+ um = c6E/c6F
486
+ x = polygen(K)
487
+ ulist = (x**3-um).roots(multiplicities=False)
488
+ if not ulist:
489
+ D = zero
490
+ else:
491
+ D = ulist[0]
492
+ elif j == 1728:
493
+ um = c4E/c4F
494
+ x = polygen(K)
495
+ ulist = (x**2-um).roots(multiplicities=False)
496
+ if not ulist:
497
+ D = zero
498
+ else:
499
+ D = ulist[0]
500
+ else:
501
+ D = (c6E*c4F)/(c6F*c4E)
502
+
503
+ # Normalization of output:
504
+
505
+ if D.is_zero():
506
+ return D
507
+
508
+ if K is QQ:
509
+ D = D.squarefree_part()
510
+
511
+ assert E.quadratic_twist(D).is_isomorphic(F)
512
+
513
+ return D
514
+
515
+ def is_quartic_twist(self, other):
516
+ r"""
517
+ Determine whether this curve is a quartic twist of another.
518
+
519
+ INPUT:
520
+
521
+ - ``other`` -- an elliptic curves with the same base field as ``self``
522
+
523
+ OUTPUT:
524
+
525
+ Either 0, if the curves are not quartic twists, or `D` if
526
+ ``other`` is ``self.quartic_twist(D)`` (up to isomorphism).
527
+ If ``self`` and ``other`` are isomorphic, returns 1.
528
+
529
+ .. NOTE::
530
+
531
+ Not fully implemented in characteristics 2 or 3.
532
+
533
+ EXAMPLES::
534
+
535
+ sage: E = EllipticCurve_from_j(GF(13)(1728))
536
+ sage: E1 = E.quartic_twist(2)
537
+ sage: D = E.is_quartic_twist(E1); D!=0
538
+ True
539
+ sage: E.quartic_twist(D).is_isomorphic(E1)
540
+ True
541
+
542
+ ::
543
+
544
+ sage: E = EllipticCurve_from_j(1728)
545
+ sage: E1 = E.quartic_twist(12345)
546
+ sage: D = E.is_quartic_twist(E1); D
547
+ 15999120
548
+ sage: (D/12345).is_perfect_power(4)
549
+ True
550
+ """
551
+ from sage.schemes.elliptic_curves.ell_generic import EllipticCurve_generic
552
+ E = self
553
+ F = other
554
+ if not isinstance(E, EllipticCurve_generic) or not isinstance(F, EllipticCurve_generic):
555
+ raise ValueError("arguments are not elliptic curves")
556
+ K = E.base_ring()
557
+ zero = K.zero()
558
+ if not K == F.base_ring():
559
+ return zero
560
+ j = E.j_invariant()
561
+ if j != F.j_invariant() or j != K(1728):
562
+ return zero
563
+
564
+ if E.is_isomorphic(F):
565
+ return K.one()
566
+
567
+ char = K.characteristic()
568
+
569
+ if char == 2:
570
+ raise NotImplementedError("not implemented in characteristic 2")
571
+ elif char == 3:
572
+ raise NotImplementedError("not implemented in characteristic 3")
573
+ else:
574
+ # now char!=2,3:
575
+ D = F.c4() / E.c4()
576
+
577
+ if D.is_zero():
578
+ return D
579
+
580
+ assert E.quartic_twist(D).is_isomorphic(F)
581
+
582
+ return D
583
+
584
+ def is_sextic_twist(self, other):
585
+ r"""
586
+ Determine whether this curve is a sextic twist of another.
587
+
588
+ INPUT:
589
+
590
+ - ``other`` -- an elliptic curves with the same base field as ``self``
591
+
592
+ OUTPUT:
593
+
594
+ Either 0, if the curves are not sextic twists, or `D` if
595
+ ``other`` is ``self.sextic_twist(D)`` (up to isomorphism).
596
+ If ``self`` and ``other`` are isomorphic, returns 1.
597
+
598
+ .. NOTE::
599
+
600
+ Not fully implemented in characteristics 2 or 3.
601
+
602
+ EXAMPLES::
603
+
604
+ sage: E = EllipticCurve_from_j(GF(13)(0))
605
+ sage: E1 = E.sextic_twist(2)
606
+ sage: D = E.is_sextic_twist(E1); D != 0
607
+ True
608
+ sage: E.sextic_twist(D).is_isomorphic(E1)
609
+ True
610
+
611
+ ::
612
+
613
+ sage: E = EllipticCurve_from_j(0)
614
+ sage: E1 = E.sextic_twist(12345)
615
+ sage: D = E.is_sextic_twist(E1); D
616
+ 575968320
617
+ sage: (D/12345).is_perfect_power(6)
618
+ True
619
+ """
620
+ from sage.schemes.elliptic_curves.ell_generic import EllipticCurve_generic
621
+ E = self
622
+ F = other
623
+ if not isinstance(E, EllipticCurve_generic) or not isinstance(F, EllipticCurve_generic):
624
+ raise ValueError("arguments are not elliptic curves")
625
+ K = E.base_ring()
626
+ zero = K.zero()
627
+ if not K == F.base_ring():
628
+ return zero
629
+ j = E.j_invariant()
630
+ if j != F.j_invariant() or not j.is_zero():
631
+ return zero
632
+
633
+ if E.is_isomorphic(F):
634
+ return K.one()
635
+
636
+ char = K.characteristic()
637
+
638
+ if char == 2:
639
+ raise NotImplementedError("not implemented in characteristic 2")
640
+ elif char == 3:
641
+ raise NotImplementedError("not implemented in characteristic 3")
642
+ else:
643
+ # now char!=2,3:
644
+ D = F.c6() / E.c6()
645
+
646
+ if D.is_zero():
647
+ return D
648
+
649
+ assert E.sextic_twist(D).is_isomorphic(F)
650
+
651
+ return D
652
+
653
+ def descend_to(self, K, f=None) -> list:
654
+ r"""
655
+ Given an elliptic curve ``self`` defined over a field `L` and a
656
+ subfield `K` of `L`, return all elliptic curves over `K` which
657
+ are isomorphic over `L` to ``self``.
658
+
659
+ INPUT:
660
+
661
+ - ``K`` -- a field which embeds into the base field `L` of ``self``
662
+
663
+ - ``f`` -- (optional) an embedding of `K` into `L`; ignored if
664
+ `K` is `\QQ`
665
+
666
+ OUTPUT:
667
+
668
+ A list (possibly empty) of elliptic curves defined over `K`
669
+ which are isomorphic to ``self`` over `L`, up to isomorphism over `K`.
670
+
671
+ .. NOTE::
672
+
673
+ Currently only implemented over number fields. To extend
674
+ to other fields of characteristic not 2 or 3, what is
675
+ needed is a method giving the preimages in `K^*/(K^*)^m` of
676
+ an element of the base field, for `m=2,4,6`.
677
+
678
+ EXAMPLES::
679
+
680
+ sage: E = EllipticCurve([1,2,3,4,5])
681
+ sage: E.descend_to(ZZ)
682
+ Traceback (most recent call last):
683
+ ...
684
+ TypeError: Input must be a field.
685
+
686
+ ::
687
+
688
+ sage: # needs sage.rings.number_field
689
+ sage: F.<b> = QuadraticField(23)
690
+ sage: x = polygen(ZZ, 'x')
691
+ sage: G.<a> = F.extension(x^3 + 5)
692
+ sage: E = EllipticCurve(j=1728*b).change_ring(G)
693
+ sage: EF = E.descend_to(F); EF
694
+ [Elliptic Curve defined by y^2 = x^3 + (27*b-621)*x + (-1296*b+2484)
695
+ over Number Field in b with defining polynomial x^2 - 23
696
+ with b = 4.795831523312720?]
697
+ sage: all(Ei.change_ring(G).is_isomorphic(E) for Ei in EF)
698
+ True
699
+
700
+ ::
701
+
702
+ sage: # needs sage.rings.number_field
703
+ sage: L.<a> = NumberField(x^4 - 7)
704
+ sage: K.<b> = NumberField(x^2 - 7, embedding=a^2)
705
+ sage: E = EllipticCurve([a^6, 0])
706
+ sage: EK = E.descend_to(K); EK
707
+ [Elliptic Curve defined by y^2 = x^3 + b*x over Number Field in b
708
+ with defining polynomial x^2 - 7 with b = a^2,
709
+ Elliptic Curve defined by y^2 = x^3 + 7*b*x over Number Field in b
710
+ with defining polynomial x^2 - 7 with b = a^2]
711
+ sage: all(Ei.change_ring(L).is_isomorphic(E) for Ei in EK)
712
+ True
713
+
714
+ ::
715
+
716
+ sage: K.<a> = QuadraticField(17) # needs sage.rings.number_field
717
+ sage: E = EllipticCurve(j=2*a) # needs sage.rings.number_field
718
+ sage: E.descend_to(QQ) # needs sage.rings.number_field
719
+ []
720
+
721
+ TESTS:
722
+
723
+ Check that :issue:`16456` is fixed::
724
+
725
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
726
+ sage: K.<a> = NumberField(x^3 - 2)
727
+ sage: E = EllipticCurve('11a1').quadratic_twist(2)
728
+ sage: EK = E.change_ring(K)
729
+ sage: EK2 = EK.change_weierstrass_model((a,a,a,a+1))
730
+ sage: EK2.descend_to(QQ)
731
+ [Elliptic Curve defined by y^2 = x^3 + x^2 - 41*x - 199 over Rational Field]
732
+
733
+ sage: k.<i> = QuadraticField(-1) # needs sage.rings.number_field
734
+ sage: E = EllipticCurve(k,[0,0,0,1,0]) # needs sage.rings.number_field
735
+ sage: E.descend_to(QQ) # needs sage.rings.number_field
736
+ [Elliptic Curve defined by y^2 = x^3 + x over Rational Field,
737
+ Elliptic Curve defined by y^2 = x^3 - 4*x over Rational Field]
738
+ """
739
+ if not K.is_field():
740
+ raise TypeError("Input must be a field.")
741
+ L = self.base_field()
742
+ if L is K:
743
+ return self
744
+ elif L == K: # number fields can be equal but not identical
745
+ return self.base_extend(K)
746
+
747
+ # Construct an embedding f of K in L, and check that the
748
+ # j-invariant is in the image, otherwise return an empty list:
749
+
750
+ j = self.j_invariant()
751
+ if K == QQ:
752
+ try:
753
+ jK = QQ(j)
754
+ except (ValueError, TypeError):
755
+ return []
756
+ elif f is None:
757
+ embeddings = K.embeddings(L)
758
+ if not embeddings:
759
+ raise TypeError("Input must be a subfield of the base field of the curve.")
760
+ for g in embeddings:
761
+ try:
762
+ jK = g.preimage(j)
763
+ f = g
764
+ break
765
+ except Exception:
766
+ pass
767
+ if f is None:
768
+ return []
769
+ else:
770
+ try:
771
+ if f.domain() != K:
772
+ raise ValueError("embedding has wrong domain")
773
+ if f.codomain() != L:
774
+ raise ValueError("embedding has wrong codomain")
775
+ except AttributeError:
776
+ raise ValueError("invalid embedding: {}".format(f))
777
+ try:
778
+ jK = f.preimage(j)
779
+ except Exception:
780
+ return []
781
+
782
+ # Now we have the j-invariant in K and must find all twists
783
+ # which work, separating the cases of j=0 and j=1728.
784
+
785
+ if L.characteristic():
786
+ raise NotImplementedError("Not implemented in positive characteristic")
787
+
788
+ if jK == 0:
789
+ t = -54 * self.c6()
790
+ try:
791
+ dlist = t.descend_mod_power(K, 6)
792
+ # list of d in K such that t/d is in L*^6
793
+ except AttributeError:
794
+ raise NotImplementedError("Not implemented over %s" % L)
795
+ Elist = [EllipticCurve([0, 0, 0, 0, d]) for d in dlist]
796
+ elif jK == 1728:
797
+ t = -27 * self.c4()
798
+ try:
799
+ dlist = t.descend_mod_power(K, 4)
800
+ # list of d in K such that t/d is in L*^4
801
+ except AttributeError:
802
+ raise NotImplementedError("Not implemented over %s" % L)
803
+ Elist = [EllipticCurve([0, 0, 0, d, 0]) for d in dlist]
804
+ else:
805
+ c4, c6 = self.c_invariants()
806
+ t = c6 / c4
807
+ try:
808
+ dlist = t.descend_mod_power(K, 2)
809
+ # list of d in K such that t/d is in L*^2
810
+ except AttributeError:
811
+ raise NotImplementedError("Not implemented over %s" % L)
812
+ c = -27*jK/(jK-1728) # =-27c4^3/c6^2
813
+ a4list = [c*d**2 for d in dlist]
814
+ a6list = [2*a4*d for a4, d in zip(a4list, dlist)]
815
+ Elist = [EllipticCurve([0, 0, 0, a4, a6]) for a4, a6 in zip(a4list, a6list)]
816
+
817
+ if K is QQ:
818
+ Elist = [E.minimal_model() for E in Elist]
819
+ return Elist
820
+
821
+ def division_field(self, n, names='t', map=False, **kwds):
822
+ r"""
823
+ Given an elliptic curve over a number field or finite field `F` and
824
+ a positive integer `n`, construct the `n`-division field `F(E[n])`.
825
+
826
+ The `n`-division field is the smallest extension of `F` over which
827
+ all `n`-torsion points of `E` are defined.
828
+
829
+ INPUT:
830
+
831
+ - ``n`` -- positive integer
832
+ - ``names`` -- (default: ``'t'``) a variable name for the division field
833
+ - ``map`` -- boolean (default: ``False``); also return an embedding of the
834
+ :meth:`base_field` into the resulting field
835
+ - ``kwds`` -- additional keyword arguments passed to
836
+ :func:`~sage.rings.polynomial.polynomial_element.Polynomial.splitting_field`
837
+
838
+ OUTPUT:
839
+
840
+ If ``map`` is ``False``, the division field `K` as an absolute
841
+ number field or a finite field.
842
+ If ``map`` is ``True``, a tuple `(K, \phi)` where `\phi` is an
843
+ embedding of the base field in the division field `K`.
844
+
845
+ .. WARNING::
846
+
847
+ This can take a very long time when the degree of the division
848
+ field is large (e.g. when `n` is large or when the Galois
849
+ representation is surjective). The ``simplify`` flag also
850
+ has a big influence on the running time over number fields:
851
+ sometimes ``simplify=False`` is faster, sometimes the default
852
+ ``simplify=True`` is faster.
853
+
854
+ EXAMPLES:
855
+
856
+ The 2-division field is the same as the splitting field of
857
+ the 2-division polynomial (therefore, it has degree 1, 2, 3 or 6)::
858
+
859
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
860
+ sage: E = EllipticCurve('15a1')
861
+ sage: K.<b> = E.division_field(2); K
862
+ Number Field in b with defining polynomial x
863
+ sage: E = EllipticCurve('14a1')
864
+ sage: K.<b> = E.division_field(2); K
865
+ Number Field in b with defining polynomial x^2 + 5*x + 92
866
+ sage: E = EllipticCurve('196b1')
867
+ sage: K.<b> = E.division_field(2); K
868
+ Number Field in b with defining polynomial x^3 + x^2 - 114*x - 127
869
+ sage: E = EllipticCurve('19a1')
870
+ sage: K.<b> = E.division_field(2); K
871
+ Number Field in b with defining polynomial
872
+ x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292
873
+
874
+ For odd primes `n`, the division field is either the splitting
875
+ field of the `n`-division polynomial, or a quadratic extension
876
+ of it. ::
877
+
878
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
879
+ sage: E = EllipticCurve('50a1')
880
+ sage: F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
881
+ Number Field in a
882
+ with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
883
+ sage: K.<b> = E.division_field(3, simplify_all=True); K
884
+ Number Field in b
885
+ with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
886
+
887
+ If we take any quadratic twist, the splitting field of the
888
+ 3-division polynomial remains the same, but the 3-division field
889
+ becomes a quadratic extension::
890
+
891
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
892
+ sage: E = E.quadratic_twist(5) # 50b3
893
+ sage: F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
894
+ Number Field in a
895
+ with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
896
+ sage: K.<b> = E.division_field(3, simplify_all=True); K
897
+ Number Field in b with defining polynomial x^12 - 3*x^11 + 8*x^10 - 15*x^9
898
+ + 30*x^8 - 63*x^7 + 109*x^6 - 144*x^5 + 150*x^4 - 120*x^3 + 68*x^2 - 24*x + 4
899
+
900
+ Try another quadratic twist, this time over a subfield of `F`::
901
+
902
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
903
+ sage: G.<c>,_,_ = F.subfields(3)[0]
904
+ sage: E = E.base_extend(G).quadratic_twist(c); E
905
+ Elliptic Curve defined
906
+ by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000)
907
+ over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9
908
+ sage: K.<b> = E.division_field(3, simplify_all=True); K
909
+ Number Field in b with defining polynomial x^12 + 5*x^10 + 40*x^8 + 315*x^6 + 750*x^4 + 675*x^2 + 2025
910
+
911
+ Some higher-degree examples::
912
+
913
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
914
+ sage: E = EllipticCurve('11a1')
915
+ sage: K.<b> = E.division_field(2); K
916
+ Number Field in b with defining polynomial
917
+ x^6 + 2*x^5 - 48*x^4 - 436*x^3 + 1668*x^2 + 28792*x + 73844
918
+ sage: K.<b> = E.division_field(3); K # long time
919
+ Number Field in b with defining polynomial x^48 ...
920
+ sage: K.<b> = E.division_field(5); K
921
+ Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
922
+ sage: E.division_field(5, 'b', simplify=False)
923
+ Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101
924
+ sage: E.base_extend(K).torsion_subgroup() # long time
925
+ Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve
926
+ defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20)
927
+ over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
928
+
929
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
930
+ sage: E = EllipticCurve('27a1')
931
+ sage: K.<b> = E.division_field(3); K
932
+ Number Field in b with defining polynomial x^2 + 3*x + 9
933
+ sage: K.<b> = E.division_field(2); K
934
+ Number Field in b with defining polynomial
935
+ x^6 + 6*x^5 + 24*x^4 - 52*x^3 - 228*x^2 + 744*x + 3844
936
+ sage: K.<b> = E.division_field(2, simplify_all=True); K
937
+ Number Field in b with defining polynomial x^6 - 3*x^5 + 5*x^3 - 3*x + 1
938
+ sage: K.<b> = E.division_field(5); K # long time
939
+ Number Field in b with defining polynomial x^48 ...
940
+ sage: K.<b> = E.division_field(7); K # long time
941
+ Number Field in b with defining polynomial x^72 ...
942
+
943
+ Over a number field::
944
+
945
+ sage: # needs sage.rings.number_field
946
+ sage: R.<x> = PolynomialRing(QQ)
947
+ sage: K.<i> = NumberField(x^2 + 1)
948
+ sage: E = EllipticCurve([0,0,0,0,i])
949
+ sage: L.<b> = E.division_field(2); L
950
+ Number Field in b with defining polynomial x^4 - x^2 + 1
951
+ sage: L.<b>, phi = E.division_field(2, map=True); phi
952
+ Ring morphism:
953
+ From: Number Field in i with defining polynomial x^2 + 1
954
+ To: Number Field in b with defining polynomial x^4 - x^2 + 1
955
+ Defn: i |--> -b^3
956
+ sage: L.<b>, phi = E.division_field(3, map=True)
957
+ sage: L
958
+ Number Field in b with defining polynomial x^24 - 6*x^22 - 12*x^21
959
+ - 21*x^20 + 216*x^19 + 48*x^18 + 804*x^17 + 1194*x^16 - 13488*x^15
960
+ + 21222*x^14 + 44196*x^13 - 47977*x^12 - 102888*x^11 + 173424*x^10
961
+ - 172308*x^9 + 302046*x^8 + 252864*x^7 - 931182*x^6 + 180300*x^5
962
+ + 879567*x^4 - 415896*x^3 + 1941012*x^2 + 650220*x + 443089
963
+ sage: phi
964
+ Ring morphism:
965
+ From: Number Field in i with defining polynomial x^2 + 1
966
+ To: Number Field in b with defining polynomial x^24 ...
967
+ Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ...
968
+
969
+ Over a finite field::
970
+
971
+ sage: E = EllipticCurve(GF(431^2), [1,0]) # needs sage.rings.finite_rings
972
+ sage: E.division_field(5, map=True) # needs sage.rings.finite_rings
973
+ (Finite Field in t of size 431^4,
974
+ Ring morphism:
975
+ From: Finite Field in z2 of size 431^2
976
+ To: Finite Field in t of size 431^4
977
+ Defn: z2 |--> 52*t^3 + 222*t^2 + 78*t + 105)
978
+
979
+ ::
980
+
981
+ sage: E = EllipticCurve(GF(433^2), [1,0]) # needs sage.rings.finite_rings
982
+ sage: K.<v> = E.division_field(7); K # needs sage.rings.finite_rings
983
+ Finite Field in v of size 433^16
984
+
985
+ It also works for composite orders::
986
+
987
+ sage: E = EllipticCurve(GF(11), [5,5])
988
+ sage: E.change_ring(E.division_field(8)).abelian_group().torsion_subgroup(8).invariants()
989
+ (8, 8)
990
+ sage: E.change_ring(E.division_field(9)).abelian_group().torsion_subgroup(9).invariants()
991
+ (9, 9)
992
+ sage: E.change_ring(E.division_field(10)).abelian_group().torsion_subgroup(10).invariants()
993
+ (10, 10)
994
+ sage: E.change_ring(E.division_field(36)).abelian_group().torsion_subgroup(36).invariants()
995
+ (36, 36)
996
+ sage: E.change_ring(E.division_field(11)).abelian_group().torsion_subgroup(11).invariants()
997
+ (11,)
998
+ sage: E.change_ring(E.division_field(66)).abelian_group().torsion_subgroup(66).invariants()
999
+ (6, 66)
1000
+
1001
+ ...also over number fields::
1002
+
1003
+ sage: R.<x> = PolynomialRing(QQ)
1004
+ sage: K.<i> = NumberField(x^2 + 1)
1005
+ sage: E = EllipticCurve([0,0,0,0,i])
1006
+ sage: L,emb = E.division_field(6, names='b', map=True); L
1007
+ Number Field in b with defining polynomial x^24 + 12*x^23 + ...
1008
+ sage: E.change_ring(emb).torsion_subgroup().invariants()
1009
+ (6, 6)
1010
+
1011
+ .. SEEALSO::
1012
+
1013
+ To compute a basis of the `n`-torsion once the base field
1014
+ has been extended, you may use
1015
+ :meth:`sage.schemes.elliptic_curves.ell_number_field.EllipticCurve_number_field.torsion_subgroup`
1016
+ or
1017
+ :meth:`sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field.torsion_basis`.
1018
+
1019
+ TESTS:
1020
+
1021
+ Some random for prime orders::
1022
+
1023
+ sage: # needs sage.rings.finite_rings
1024
+ sage: def check(E, l, K):
1025
+ ....: EE = E.change_ring(K)
1026
+ ....: cof = EE.order().prime_to_m_part(l)
1027
+ ....: pts = (cof * EE.random_point() for _ in iter(int, 1))
1028
+ ....: mul = lambda P: P if not l*P else mul(l*P)
1029
+ ....: pts = map(mul, filter(bool, pts))
1030
+ ....: if l == EE.base_field().characteristic():
1031
+ ....: if EE.is_supersingular():
1032
+ ....: Ps = ()
1033
+ ....: else:
1034
+ ....: assert l.divides(EE.order())
1035
+ ....: Ps = (next(pts),)
1036
+ ....: else:
1037
+ ....: assert l.divides(EE.order())
1038
+ ....: for _ in range(9999):
1039
+ ....: P,Q = next(pts), next(pts)
1040
+ ....: if P.weil_pairing(Q,l) != 1:
1041
+ ....: Ps = (P,Q)
1042
+ ....: break
1043
+ ....: else:
1044
+ ....: assert False
1045
+ ....: deg = lcm(el.minpoly().degree() for el in sum(map(list,Ps),[]))
1046
+ ....: assert max(deg, E.base_field().degree()) == K.degree()
1047
+ sage: q = next_prime_power(randrange(1, 10^9))
1048
+ sage: F.<a> = GF(q)
1049
+ sage: while True:
1050
+ ....: try:
1051
+ ....: E = EllipticCurve([F.random_element() for _ in range(5)])
1052
+ ....: except ArithmeticError:
1053
+ ....: continue
1054
+ ....: break
1055
+ sage: l = random_prime(8)
1056
+ sage: K = E.division_field(l)
1057
+ sage: n = E.cardinality(extension_degree=K.degree()//F.degree())
1058
+ sage: (l^2 if q%l else 0 + E.is_ordinary()).divides(n)
1059
+ True
1060
+ sage: check(E, l, K) # long time
1061
+
1062
+ AUTHORS:
1063
+
1064
+ - Jeroen Demeyer (2014-01-06): :issue:`11905`, use
1065
+ ``splitting_field`` method, moved from ``gal_reps.py``, make
1066
+ it work over number fields.
1067
+ - Lorenz Panny (2022): extend to finite fields
1068
+ - Lorenz Panny (2023): extend to composite `n`.
1069
+ """
1070
+ from sage.misc.verbose import verbose
1071
+
1072
+ n = Integer(n)
1073
+ if n <= 0:
1074
+ raise ValueError("n must be a positive integer")
1075
+
1076
+ verbose("Adjoining X-coordinates of %s-torsion points" % n)
1077
+
1078
+ F = self.base_ring()
1079
+ f = self.division_polynomial(n).radical()
1080
+
1081
+ if n == 2 or f.is_constant():
1082
+ # For n = 2, the division field is the splitting field of
1083
+ # the division polynomial.
1084
+ # If f is a nonzero constant, the n-torsion is trivial:
1085
+ # This means the curve must be supersingular and n == p.
1086
+ return f.splitting_field(names, map=map, **kwds)
1087
+
1088
+ # We divide out the part defining points of non-maximal order.
1089
+ # Clearly all points of non-maximal order are multiples of points
1090
+ # of maximal order, so they cannot be defined over a larger field.
1091
+ if not n.is_prime():
1092
+ for d in n.prime_divisors():
1093
+ g = self.division_polynomial(n // d)
1094
+ f //= f.gcd(g)
1095
+
1096
+ # Compute splitting field of X-coordinates.
1097
+ # The Galois group of the division field is a subgroup of GL(2,n).
1098
+ # The Galois group of the X-coordinates is a subgroup of GL(2,n)/{-1,+1}.
1099
+ if F in NumberFields():
1100
+ from sage.misc.misc_c import prod
1101
+ deg_mult = F.degree() * prod(l * (l+1) * (l-1)**2 * l**(4*(e-1))
1102
+ for l, e in n.factor()) // 2
1103
+ K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds)
1104
+ elif F in FiniteFields():
1105
+ K, F_to_K = f.splitting_field('u', map=True, **kwds)
1106
+ else:
1107
+ raise NotImplementedError('only number fields and finite fields are currently supported')
1108
+
1109
+ verbose("Adjoining Y-coordinates of %s-torsion points" % n)
1110
+
1111
+ # THEOREM
1112
+ # (Cremona, https://github.com/sagemath/sage/issues/11905#comment:21)
1113
+ # (Later generalized to composite n by Lorenz Panny)
1114
+ #
1115
+ # Let K be a field, E an elliptic curve over K and n a positive
1116
+ # integer. Assume that K contains all roots of the n-division
1117
+ # polynomial of E, and that at least one point P of full order n
1118
+ # is defined over K. Then K contains all n-torsion points on E.
1119
+ #
1120
+ # PROOF. Let G be the absolute Galois group of K (every element
1121
+ # in it fixes all elements of K). For any n-torsion point Q
1122
+ # over the algebraic closure and any sigma in G, we must have
1123
+ # either sigma(Q) = Q or sigma(Q) = -Q (since K contains the
1124
+ # X-coordinate of Q). Similarly, sigma(P+Q) must equal either
1125
+ # P+Q or -(P+Q). However, since sigma is a group homomorphism,
1126
+ # we have sigma(P+Q) = sigma(P) + sigma(Q) = P + sigma(Q),
1127
+ # so either P + sigma(Q) = P+Q, which implies sigma(Q) = Q,
1128
+ # or P + sigma(Q) = -(P+Q), which implies sigma(Q) = -2P-Q.
1129
+ # The latter is impossible except for the easier case n = 2.
1130
+ # Hence, sigma(Q) = Q in all cases.
1131
+ #
1132
+ # This implies that it suffices to adjoin the Y-coordinate
1133
+ # of just one full-order point.
1134
+
1135
+ x = f.change_ring(F_to_K).any_root(assume_squarefree=True)
1136
+ h = self.defining_polynomial().change_ring(F_to_K)(x, polygen(K), 1)
1137
+ L = h.splitting_field(names, map=map, **kwds)
1138
+
1139
+ if map:
1140
+ L, K_to_L = L
1141
+ L = L, F_to_K.post_compose(K_to_L)
1142
+ return L
1143
+
1144
+ def _Hom_(self, other, category=None):
1145
+ r"""
1146
+ Hook to make :class:`~sage.categories.homset.Hom`
1147
+ set the correct parent
1148
+ :class:`~sage.schemes.elliptic_curves.homset.EllipticCurveHomset`
1149
+ for
1150
+ :class:`~sage.schemes.elliptic_curves.hom.EllipticCurveHom`
1151
+ objects.
1152
+
1153
+ EXAMPLES::
1154
+
1155
+ sage: E = EllipticCurve(GF(19), [1,0])
1156
+ sage: type(E._Hom_(E))
1157
+ <class 'sage.schemes.elliptic_curves.homset.EllipticCurveHomset_with_category'>
1158
+ """
1159
+ if isinstance(other, ell_generic.EllipticCurve_generic) and self.base_ring() == other.base_ring():
1160
+ from . import homset
1161
+ return homset.EllipticCurveHomset(self, other, category=category)
1162
+ from sage.schemes.generic.homset import SchemeHomset_generic
1163
+ return SchemeHomset_generic(self, other, category=category)
1164
+
1165
+ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, algorithm=None, velu_sqrt_bound=None):
1166
+ r"""
1167
+ Return an elliptic-curve isogeny from this elliptic curve.
1168
+
1169
+ The isogeny can be specified in two ways, by passing either a
1170
+ polynomial or a set of torsion points. The methods used are:
1171
+
1172
+ - Factored Isogenies (see
1173
+ :mod:`~sage.schemes.elliptic_curves.hom_composite`):
1174
+ Given a point, or a list of points which generate a
1175
+ composite-order subgroup, decomposes the isogeny into
1176
+ prime-degree steps. This can be used to construct isogenies
1177
+ of extremely large, smooth degree. When applicable, this
1178
+ algorithm is selected as default (see below). After factoring
1179
+ the degree single isogenies are computed using the other
1180
+ methods.
1181
+ This algorithm is selected using ``algorithm="factored"``.
1182
+
1183
+ - Vélu's Formulas: Vélu's original formulas for computing
1184
+ isogenies. This algorithm is selected by giving as the
1185
+ ``kernel`` parameter a single point generating a finite
1186
+ subgroup.
1187
+
1188
+ - Kohel's Formulas: Kohel's original formulas for computing
1189
+ isogenies. This algorithm is selected by giving as the
1190
+ ``kernel`` parameter a monic polynomial (or a coefficient list
1191
+ in little endian) which will define the kernel of the isogeny.
1192
+ Kohel's algorithm is currently only implemented for cyclic
1193
+ isogenies, with the exception of `[2]`.
1194
+
1195
+ - Îlu Algorithm (see
1196
+ :mod:`~sage.schemes.elliptic_curves.hom_velusqrt`):
1197
+ A variant of Vélu's formulas with essentially square-root
1198
+ instead of linear complexity (in the degree). Currently only
1199
+ available over finite fields. The input must be a single
1200
+ kernel point of odd order `\geq 5`.
1201
+ This algorithm is selected using ``algorithm="velusqrt"``.
1202
+
1203
+ INPUT:
1204
+
1205
+ - ``kernel`` -- a kernel; either a point on this curve, a list of
1206
+ points on this curve, a monic kernel polynomial, or ``None``.
1207
+ If initializing from a codomain, this must be ``None``.
1208
+
1209
+ - ``codomain`` -- an elliptic curve (default: ``None``).
1210
+
1211
+ - If ``kernel`` is ``None``, then ``degree`` must be given as well
1212
+ and the given ``codomain`` must be the codomain of a cyclic,
1213
+ separable, normalized isogeny of the given degree.
1214
+
1215
+ - If ``kernel`` is not ``None``, then this must be isomorphic to
1216
+ the codomain of the separable isogeny defined by ``kernel``; in
1217
+ this case, the isogeny is post-composed with an isomorphism so
1218
+ that the codomain equals the given curve.
1219
+
1220
+ - ``degree`` -- integer (default: ``None``).
1221
+
1222
+ - If ``kernel`` is ``None``, then this is the degree of the isogeny
1223
+ from this curve to ``codomain``.
1224
+
1225
+ - If ``kernel`` is not ``None``, then this is used to determine
1226
+ whether or not to skip a `\gcd` of the given kernel polynomial
1227
+ with the two-torsion polynomial of this curve.
1228
+
1229
+ - ``model`` -- string (default: ``None``); supported values
1230
+ (cf. :func:`~sage.schemes.elliptic_curves.ell_field.compute_model`):
1231
+
1232
+ - ``'minimal'``: if ``self`` is a curve over the rationals or
1233
+ over a number field, then the codomain is a global minimal
1234
+ model where this exists.
1235
+
1236
+ - ``'short_weierstrass'``: the codomain is a short Weierstrass curve,
1237
+ assuming one exists.
1238
+
1239
+ - ``'montgomery'``: the codomain is an (untwisted) Montgomery
1240
+ curve, assuming one exists over this field.
1241
+
1242
+ - ``check`` -- boolean (default: ``True``); check whether the input is valid.
1243
+ Setting this to ``False`` can lead to significant speedups.
1244
+
1245
+ - ``algorithm`` -- string (optional); the possible choices are:
1246
+
1247
+ - ``'velusqrt'``: Use
1248
+ :class:`~sage.schemes.elliptic_curves.hom_velusqrt.EllipticCurveHom_velusqrt`.
1249
+
1250
+ - ``'factored'``: Use
1251
+ :class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite`
1252
+ to decompose the isogeny into prime-degree steps.
1253
+
1254
+ - ``'traditional'``: Use
1255
+ :class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny`.
1256
+
1257
+ When ``algorithm`` is not specified, and ``kernel`` is not ``None``, an
1258
+ algorithm is selected using the following criteria:
1259
+
1260
+ - if ``kernel`` is a list of multiple points, ``'factored'`` is selected.
1261
+
1262
+ - If ``kernel`` is a single point, or a list containing a single point:
1263
+
1264
+ - if the order of the point is unknown, ``'traditional'`` is selected.
1265
+
1266
+ - If the order is known and composite, ``'factored'`` is selected.
1267
+
1268
+ - If the order is known and prime, a choice between ``'velusqrt'`` and
1269
+ ``'traditional'`` is done according to the ``velu_sqrt_bound``
1270
+ parameter (see below).
1271
+
1272
+ If none of the previous apply, ``'traditional'`` is selected.
1273
+
1274
+ - ``velu_sqrt_bound`` -- integer (default: ``None``); establish the highest
1275
+ (prime) degree for which the ``'traditional'`` algorithm should be selected
1276
+ instead of ``'velusqrt'``. If ``None``, the default value from
1277
+ :class:`~sage.schemes.elliptic_curves.hom_velusqrt._VeluBoundObj` is used.
1278
+ This value is initially set to 1000, but can be modified by the user.
1279
+ If an integer is supplied and the isogeny computation goes through the
1280
+ ``'factored'`` algorithm, the same integer is supplied to each factor.
1281
+
1282
+ The ``degree`` parameter is not supported when an ``algorithm`` is
1283
+ specified.
1284
+
1285
+ OUTPUT:
1286
+
1287
+ An isogeny between elliptic curves. This is a morphism of curves.
1288
+ (In all cases, the returned object will be an instance of
1289
+ :class:`~sage.schemes.elliptic_curves.hom.EllipticCurveHom`.)
1290
+
1291
+ EXAMPLES::
1292
+
1293
+ sage: # needs sage.rings.finite_rings
1294
+ sage: F = GF(2^5, 'alpha'); alpha = F.gen()
1295
+ sage: E = EllipticCurve(F, [1,0,1,1,1])
1296
+ sage: R.<x> = F[]
1297
+ sage: phi = E.isogeny(x + 1)
1298
+ sage: phi.rational_maps()
1299
+ ((x^2 + x + 1)/(x + 1), (x^2*y + x)/(x^2 + 1))
1300
+
1301
+ ::
1302
+
1303
+ sage: # needs database_cremona_mini_ellcurve
1304
+ sage: E = EllipticCurve('11a1')
1305
+ sage: P = E.torsion_points()[1]
1306
+ sage: E.isogeny(P)
1307
+ Isogeny of degree 5
1308
+ from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20
1309
+ over Rational Field
1310
+ to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580
1311
+ over Rational Field
1312
+
1313
+ ::
1314
+
1315
+ sage: E = EllipticCurve(GF(19),[1,1])
1316
+ sage: P = E(15,3); Q = E(2,12)
1317
+ sage: (P.order(), Q.order())
1318
+ (7, 3)
1319
+ sage: phi = E.isogeny([P,Q]); phi
1320
+ Composite morphism of degree 21 = 7*3:
1321
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
1322
+ To: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
1323
+ sage: phi(E.random_point()) # all points defined over GF(19) are in the kernel
1324
+ (0 : 1 : 0)
1325
+
1326
+ ::
1327
+
1328
+ sage: E = EllipticCurve(GF(2^32 - 5), [170246996, 2036646110]) # needs sage.rings.finite_rings
1329
+ sage: P = E.lift_x(2) # needs sage.rings.finite_rings
1330
+ sage: E.isogeny(P, algorithm='factored') # needs sage.rings.finite_rings
1331
+ Composite morphism of degree 1073721825 = 3^4*5^2*11*19*43*59:
1332
+ From: Elliptic Curve defined by y^2 = x^3 + 170246996*x + 2036646110
1333
+ over Finite Field of size 4294967291
1334
+ To: Elliptic Curve defined by y^2 = x^3 + 272790262*x + 1903695400
1335
+ over Finite Field of size 4294967291
1336
+
1337
+ Not all polynomials define a finite subgroup (:issue:`6384`)::
1338
+
1339
+ sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
1340
+ sage: phi = E.isogeny([14,27,4,1])
1341
+ Traceback (most recent call last):
1342
+ ...
1343
+ ValueError: the polynomial x^3 + 4*x^2 + 27*x + 14 does not define a finite
1344
+ subgroup of Elliptic Curve defined by y^2 + x*y = x^3 + x + 2
1345
+ over Finite Field of size 31
1346
+
1347
+ Order of the point known and composite::
1348
+
1349
+ sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
1350
+ sage: P = E(26, 4)
1351
+ sage: assert P.order() == 12
1352
+ sage: print(P._order)
1353
+ 12
1354
+ sage: E.isogeny(P)
1355
+ Composite morphism of degree 12 = 2^2*3:
1356
+ From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
1357
+ To: Elliptic Curve defined by y^2 + x*y = x^3 + 26*x + 8 over Finite Field of size 31
1358
+
1359
+ ``kernel`` is a list of points::
1360
+
1361
+ sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
1362
+ sage: P = E(21,2)
1363
+ sage: Q = E(7, 12)
1364
+ sage: print(P.order())
1365
+ 6
1366
+ sage: print(Q.order())
1367
+ 2
1368
+ sage: E.isogeny([P, Q])
1369
+ Composite morphism of degree 12 = 2*3*2:
1370
+ From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
1371
+ To: Elliptic Curve defined by y^2 + x*y = x^3 + 2*x + 26 over Finite Field of size 31
1372
+
1373
+ Multiple ways to set the ``velu_sqrt_bound``::
1374
+
1375
+ sage: E = EllipticCurve_from_j(GF(97)(42))
1376
+ sage: P = E.gens()[0]*4
1377
+ sage: print(P.order())
1378
+ 23
1379
+ sage: E.isogeny(P)
1380
+ Isogeny of degree 23 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 72*x + 29 over Finite Field of size 97
1381
+ sage: E.isogeny(P, velu_sqrt_bound=10)
1382
+ Elliptic-curve isogeny (using square-root Vélu) of degree 23:
1383
+ From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
1384
+ To: Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
1385
+ sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1386
+ sage: _velu_sqrt_bound.set(10)
1387
+ sage: E.isogeny(P)
1388
+ Elliptic-curve isogeny (using square-root Vélu) of degree 23:
1389
+ From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
1390
+ To: Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
1391
+ sage: _velu_sqrt_bound.set(1000) # Reset bound
1392
+
1393
+ If the order of the point is unknown, fall back to ``'traditional'``::
1394
+
1395
+ sage: E = EllipticCurve_from_j(GF(97)(42))
1396
+ sage: P = E(2, 39)
1397
+ sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1398
+ sage: _velu_sqrt_bound.set(1)
1399
+ sage: E.isogeny(P)
1400
+ Isogeny of degree 46 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 87*x + 47 over Finite Field of size 97
1401
+ sage: _velu_sqrt_bound.set(1000) # Reset bound
1402
+
1403
+ .. SEEALSO::
1404
+
1405
+ - :class:`~sage.schemes.elliptic_curves.hom.EllipticCurveHom`
1406
+ - :class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny`
1407
+ - :class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite`
1408
+
1409
+ TESTS:
1410
+
1411
+ Until the checking of kernel polynomials was implemented in
1412
+ :issue:`23222`, the following raised no error but returned an
1413
+ invalid morphism. See also :issue:`11578`::
1414
+
1415
+ sage: # needs sage.rings.number_field
1416
+ sage: R.<x> = QQ[]
1417
+ sage: K.<a> = NumberField(x^2 - x - 1)
1418
+ sage: E = EllipticCurve(K, [-13392, -1080432])
1419
+ sage: R.<x> = K[]
1420
+ sage: phi = E.isogeny( (x-564)*(x - 396/5*a + 348/5) )
1421
+ Traceback (most recent call last):
1422
+ ...
1423
+ ValueError: the polynomial x^2 + (-396/5*a - 2472/5)*x + 223344/5*a - 196272/5 does not
1424
+ define a finite subgroup of Elliptic Curve defined by y^2 = x^3 + (-13392)*x + (-1080432)
1425
+ over Number Field in a with defining polynomial x^2 - x - 1
1426
+
1427
+ We check that the cached order is correctly copied over::
1428
+
1429
+ sage: # needs sage.rings.finite_rings
1430
+ sage: E = EllipticCurve(GF(2^127 - 1), [1,2,3,4,5])
1431
+ sage: E.set_order(170141183460469231746191640949390434666)
1432
+ sage: phi = E.isogeny(E.lift_x(77347718128277853096420969229987528666))
1433
+ sage: phi.codomain()._order
1434
+ 170141183460469231746191640949390434666
1435
+
1436
+ Check that ``factored`` recursively apply ``velu_sqrt_bound``::
1437
+
1438
+ sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1439
+ sage: _velu_sqrt_bound.get()
1440
+ 1000
1441
+ sage: _velu_sqrt_bound.set(50)
1442
+ sage: _velu_sqrt_bound.get()
1443
+ 50
1444
+ sage: from sage.schemes.elliptic_curves import hom_composite
1445
+ sage: p = 3217
1446
+ sage: E = EllipticCurve_from_j(GF(p)(42))
1447
+ sage: P = E.gens()[0]
1448
+ sage: phis = hom_composite._compute_factored_isogeny_single_generator(P, velu_sqrt_bound=50)
1449
+ sage: for phi in phis:
1450
+ ....: print(phi)
1451
+ ....:
1452
+ Isogeny of degree 31 from Elliptic Curve defined by y^2 = x^3 + 114*x + 544 over Finite Field of size 3217 to Elliptic Curve defined by y^2 = x^3 + 277*x + 1710 over Finite Field of size 3217
1453
+ Elliptic-curve isogeny (using square-root Vélu) of degree 103:
1454
+ From: Elliptic Curve defined by y^2 = x^3 + 277*x + 1710 over Finite Field of size 3217
1455
+ To: Elliptic Curve defined by y^2 = x^3 + 2979*x + 1951 over Finite Field of size 3217
1456
+ """
1457
+ if algorithm is not None and degree is not None:
1458
+ raise TypeError('cannot pass "degree" and "algorithm" parameters simultaneously')
1459
+ if algorithm == "velusqrt":
1460
+ from sage.schemes.elliptic_curves.hom_velusqrt import EllipticCurveHom_velusqrt
1461
+ return EllipticCurveHom_velusqrt(self, kernel, codomain=codomain, model=model)
1462
+ if algorithm == "factored":
1463
+ from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
1464
+ return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model, velu_sqrt_bound=velu_sqrt_bound)
1465
+ if algorithm == "traditional":
1466
+ return EllipticCurveIsogeny(self, kernel, codomain, degree, model, check=check)
1467
+
1468
+ if kernel is not None:
1469
+ # Check for multiple points or point of known order
1470
+ kernel_is_list = isinstance(kernel, (list, tuple))
1471
+ if kernel_is_list and kernel[0] in self and len(kernel) > 1:
1472
+ from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
1473
+ return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model, velu_sqrt_bound=velu_sqrt_bound)
1474
+
1475
+ if not kernel_is_list or (len(kernel) == 1 and kernel[0] in self):
1476
+ # Single point on the curve; unpack the list for compatibility with velusqrt
1477
+ if kernel_is_list:
1478
+ kernel = kernel[0]
1479
+
1480
+ known_order = hasattr(kernel, "_order")
1481
+
1482
+ if known_order and kernel._order.is_pseudoprime():
1483
+ if not velu_sqrt_bound:
1484
+ from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1485
+ velu_sqrt_bound = _velu_sqrt_bound.get()
1486
+
1487
+ if kernel._order > velu_sqrt_bound:
1488
+ from sage.schemes.elliptic_curves.hom_velusqrt import EllipticCurveHom_velusqrt
1489
+ return EllipticCurveHom_velusqrt(self, kernel, codomain=codomain, model=model)
1490
+ # Otherwise fall back to the standard case
1491
+ elif known_order:
1492
+ from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
1493
+ return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model, velu_sqrt_bound=velu_sqrt_bound)
1494
+ try:
1495
+ return EllipticCurveIsogeny(self, kernel, codomain, degree, model, check=check)
1496
+ except AttributeError as e:
1497
+ raise RuntimeError("Unable to construct isogeny: %s" % e)
1498
+
1499
+ def isogeny_codomain(self, kernel):
1500
+ r"""
1501
+ Return the codomain of the isogeny from ``self`` with given kernel.
1502
+
1503
+ INPUT:
1504
+
1505
+ - ``kernel`` -- either a list of points in the kernel of the isogeny,
1506
+ or a kernel polynomial (specified as either a univariate polynomial
1507
+ or a coefficient list)
1508
+
1509
+ OUTPUT:
1510
+
1511
+ An elliptic curve, the codomain of the separable normalized
1512
+ isogeny defined by this kernel.
1513
+
1514
+ EXAMPLES::
1515
+
1516
+ sage: # needs database_cremona_mini_ellcurve
1517
+ sage: E = EllipticCurve('17a1')
1518
+ sage: R.<x> = QQ[]
1519
+ sage: E2 = E.isogeny_codomain(x - 11/4); E2
1520
+ Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 1461/16*x - 19681/64
1521
+ over Rational Field
1522
+
1523
+ TESTS:
1524
+
1525
+ We check that the cached order is correctly copied over::
1526
+
1527
+ sage: # needs sage.rings.finite_rings
1528
+ sage: E = EllipticCurve(GF(2^127 - 1), [1,2,3,4,5])
1529
+ sage: E.set_order(170141183460469231746191640949390434666)
1530
+ sage: E2 = E.isogeny_codomain(E.lift_x(77347718128277853096420969229987528666))
1531
+ sage: E2._order
1532
+ 170141183460469231746191640949390434666
1533
+ """
1534
+ E = isogeny_codomain_from_kernel(self, kernel)
1535
+ if self.base_field().is_finite():
1536
+ E._fetch_cached_order(self)
1537
+ return E
1538
+
1539
+ def period_lattice(self):
1540
+ r"""
1541
+ Return the period lattice of the elliptic curve for the given
1542
+ embedding of its base field with respect to the differential
1543
+ `dx/(2y + a_1x + a_3)`.
1544
+
1545
+ Only supported for some base rings.
1546
+
1547
+ EXAMPLES::
1548
+
1549
+ sage: EllipticCurve(RR, [1, 6]).period_lattice()
1550
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 6.00000000000000 over Real Field with 53 bits of precision
1551
+
1552
+ TESTS::
1553
+
1554
+ sage: EllipticCurve(QQ, [1, 6]).period_lattice()
1555
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x + 6 over Rational Field
1556
+ sage: EllipticCurve(RR, [1, 6]).period_lattice()
1557
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 6.00000000000000 over Real Field with 53 bits of precision
1558
+ sage: EllipticCurve(RDF, [1, 6]).period_lattice()
1559
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.0*x + 6.0 over Real Double Field
1560
+ sage: EllipticCurve(RealField(100), [1, 6]).period_lattice()
1561
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.0000000000000000000000000000*x + 6.0000000000000000000000000000 over Real Field with 100 bits of precision
1562
+ sage: EllipticCurve(CC, [1, 6]).period_lattice()
1563
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 6.00000000000000 over Complex Field with 53 bits of precision
1564
+ sage: EllipticCurve(CDF, [1, 6]).period_lattice()
1565
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.0*x + 6.0 over Complex Double Field
1566
+ sage: EllipticCurve(ComplexField(100), [1, 6]).period_lattice()
1567
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + 1.0000000000000000000000000000*x + 6.0000000000000000000000000000 over Complex Field with 100 bits of precision
1568
+ sage: EllipticCurve(AA, [1, 6]).period_lattice()
1569
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x + 6 over Algebraic Real Field
1570
+ sage: EllipticCurve(QQbar, [1, 6]).period_lattice()
1571
+ Period lattice associated to Elliptic Curve defined by y^2 = x^3 + x + 6 over Algebraic Field
1572
+
1573
+ Unsupported cases (the exact error being raised may change in the future)::
1574
+
1575
+ sage: EllipticCurve(ZZ, [1, 6]).period_lattice()
1576
+ Traceback (most recent call last):
1577
+ ...
1578
+ AttributeError: 'EllipticCurve_generic_with_category' object has no attribute 'period_lattice'
1579
+ sage: QQt.<t> = QQ[]
1580
+ sage: EllipticCurve(QQt.fraction_field(), [1, 6]).period_lattice()
1581
+ Traceback (most recent call last):
1582
+ ...
1583
+ AttributeError: 'FractionField_1poly_field_with_category' object has no attribute ...
1584
+ sage: EllipticCurve(GF(7), [1, 6]).period_lattice()
1585
+ Traceback (most recent call last):
1586
+ ...
1587
+ IndexError: list index out of range
1588
+ """
1589
+ from sage.schemes.elliptic_curves.period_lattice import PeriodLattice_ell
1590
+ return PeriodLattice_ell(self)
1591
+
1592
+ def kernel_polynomial_from_point(self, P, *, algorithm=None):
1593
+ r"""
1594
+ Given a point `P` on this curve which generates a rational subgroup,
1595
+ return the kernel polynomial of that subgroup as a polynomial over
1596
+ the base field of the curve.
1597
+
1598
+ The point `P` itself may be defined over an extension.
1599
+
1600
+ EXAMPLES::
1601
+
1602
+ sage: E = EllipticCurve(GF(101), [1,1])
1603
+ sage: F = GF(101^3)
1604
+ sage: EE = E.change_ring(F)
1605
+ sage: xK = F([77, 28, 8]); xK
1606
+ 8*z3^2 + 28*z3 + 77
1607
+ sage: K = EE.lift_x(xK); K.order()
1608
+ 43
1609
+ sage: E.kernel_polynomial_from_point(K)
1610
+ x^21 + 7*x^20 + 22*x^19 + 4*x^18 + 7*x^17 + 81*x^16 + 41*x^15 + 68*x^14 + 18*x^13 + 58*x^12 + 31*x^11 + 26*x^10 + 62*x^9 + 20*x^8 + 73*x^7 + 23*x^6 + 66*x^5 + 79*x^4 + 12*x^3 + 40*x^2 + 50*x + 93
1611
+
1612
+ The ``'minpoly'`` algorithm is often much faster than the
1613
+ ``'basic'`` algorithm::
1614
+
1615
+ sage: from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field, point_of_order
1616
+ sage: p = 2^127 - 1
1617
+ sage: E = EllipticCurve(GF(p), [1,0])
1618
+ sage: P = point_of_order(E, 31) # long time (8.5s)
1619
+ sage: %timeit E.kernel_polynomial_from_point(P, algorithm='basic') # not tested
1620
+ 4.38 ms ± 13.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1621
+ sage: %timeit E.kernel_polynomial_from_point(P, algorithm='minpoly') # not tested
1622
+ 854 µs ± 1.56 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
1623
+
1624
+ Example of finding all the rational isogenies using this method::
1625
+
1626
+ sage: E = EllipticCurve(GF(71), [1,2,3,4,5])
1627
+ sage: F = E.division_field(11)
1628
+ sage: EE = E.change_ring(F)
1629
+ sage: fs = set()
1630
+ sage: for K in EE(0).division_points(11):
1631
+ ....: if not K:
1632
+ ....: continue
1633
+ ....: Kp = EE.frobenius_isogeny()(K)
1634
+ ....: if Kp.weil_pairing(K, 11) == 1:
1635
+ ....: fs.add(E.kernel_polynomial_from_point(K))
1636
+ sage: fs = sorted(fs); fs
1637
+ [x^5 + 10*x^4 + 18*x^3 + 10*x^2 + 43*x + 46,
1638
+ x^5 + 65*x^4 + 39*x^2 + 20*x + 63]
1639
+ sage: from sage.schemes.elliptic_curves.isogeny_small_degree import is_kernel_polynomial
1640
+ sage: {is_kernel_polynomial(E, 11, f) for f in fs}
1641
+ {True}
1642
+ sage: isogs = [E.isogeny(f) for f in fs]
1643
+ sage: isogs[0]
1644
+ Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 71 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 34*x + 42 over Finite Field of size 71
1645
+ sage: isogs[1]
1646
+ Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 71 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 12*x + 40 over Finite Field of size 71
1647
+ sage: set(isogs) == set(E.isogenies_prime_degree(11))
1648
+ True
1649
+
1650
+ ALGORITHM:
1651
+
1652
+ - The ``'basic'`` algorithm is to multiply together all the linear
1653
+ factors `(X - x([i]P))` of the kernel polynomial using a product
1654
+ tree, then converting the result to the base field of the curve.
1655
+ Its complexity is `\widetilde O(\ell k)` where `k` is the
1656
+ extension degree.
1657
+
1658
+ - The ``'minpoly'`` algorithm is
1659
+ [EPSV2023]_, Algorithm 4 (``KernelPolynomialFromIrrationalX``).
1660
+ Over finite fields, its complexity is `O(\ell k) + \widetilde O(\ell)`
1661
+ where `k` is the extension degree.
1662
+ """
1663
+ R = self.base_ring()
1664
+
1665
+ if not P:
1666
+ return R['x'].one()
1667
+
1668
+ S = P.base_ring()
1669
+ if not S.has_coerce_map_from(R):
1670
+ raise TypeError(f'{R} does not coerce into {S}')
1671
+
1672
+ EE = self.change_ring(S)
1673
+ if P.curve() is not EE:
1674
+ raise TypeError(f'{P} is not a point on {EE}')
1675
+
1676
+ l = P.order()
1677
+
1678
+ if algorithm is None:
1679
+ if R in FiniteFields():
1680
+ # In this case the minpoly approach is likely to be faster.
1681
+ if l & 1 and l.is_prime_power():
1682
+ algorithm = 'minpoly'
1683
+ if algorithm is None:
1684
+ algorithm = 'basic'
1685
+
1686
+ if algorithm == 'basic':
1687
+ from sage.groups.generic import multiples
1688
+ Qs = multiples(P, l//2, P)
1689
+ x = polygen(S)
1690
+ f = prod(x - Q.xy()[0] for Q in Qs)
1691
+ return f.change_ring(R)
1692
+
1693
+ if algorithm == 'minpoly':
1694
+ if not l & 1 or not l.is_prime_power():
1695
+ raise ValueError('algorithm "minpoly" only supports odd prime-power degrees')
1696
+
1697
+ xx = P.xy()[0]
1698
+ ext = xx.parent().over(self.base_ring())
1699
+ mu = ext(xx).minpoly()
1700
+ assert mu.base_ring() == self.base_ring()
1701
+
1702
+ return self.kernel_polynomial_from_divisor(mu, P.order(), check=False)
1703
+
1704
+ raise ValueError('unknown algorithm')
1705
+
1706
+ def kernel_polynomial_from_divisor(self, f, l, *, check=True):
1707
+ r"""
1708
+ Given an irreducible divisor `f` of the `l`-division polynomial
1709
+ on this curve, return the kernel polynomial defining the subgroup
1710
+ defined by `f`.
1711
+
1712
+ If the given polynomial does not define a rational subgroup, a
1713
+ :exc:`ValueError` is raised.
1714
+
1715
+ This method is currently only implemented for prime `l`.
1716
+
1717
+ EXAMPLES::
1718
+
1719
+ sage: E = EllipticCurve(GF(101^2), [0,1])
1720
+ sage: f,_ = E.division_polynomial(5).factor()[0]
1721
+ sage: ker = E.kernel_polynomial_from_divisor(f, 5); ker
1722
+ x^2 + (49*z2 + 10)*x + 30*z2 + 80
1723
+ sage: E.isogeny(ker)
1724
+ Isogeny of degree 5
1725
+ from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 101^2
1726
+ to Elliptic Curve defined by y^2 = x^3 + (6*z2+16)*x + 18 over Finite Field in z2 of size 101^2
1727
+
1728
+ The method detects invalid inputs::
1729
+
1730
+ sage: E = EllipticCurve(GF(101), [0,1])
1731
+ sage: f,_ = E.division_polynomial(5).factor()[-1]
1732
+ sage: E.kernel_polynomial_from_divisor(f, 5)
1733
+ Traceback (most recent call last):
1734
+ ...
1735
+ ValueError: given polynomial does not define a rational 5-isogeny
1736
+
1737
+ ::
1738
+
1739
+ sage: E = EllipticCurve(GF(101), [1,1])
1740
+ sage: f,_ = E.division_polynomial(7).factor()[-1]
1741
+ sage: E.kernel_polynomial_from_divisor(f, 7)
1742
+ Traceback (most recent call last):
1743
+ ...
1744
+ ValueError: given polynomial does not define a rational 7-isogeny
1745
+
1746
+ ::
1747
+
1748
+ sage: x = polygen(QQ)
1749
+ sage: K.<t> = NumberField(x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13)
1750
+ sage: E = EllipticCurve(K, [1,0])
1751
+ sage: ker = E.kernel_polynomial_from_divisor(x - t, 13); ker
1752
+ x^6 + (-169/64*t^10 + 169/32*t^8 - 247/32*t^6 - 377/8*t^4 - 2977/64*t^2 - 105/32)*x^4 + (-169/32*t^10 + 169/16*t^8 - 247/16*t^6 - 377/4*t^4 - 2977/32*t^2 - 89/16)*x^2 - 13/64*t^10 + 13/32*t^8 - 19/32*t^6 - 29/8*t^4 - 229/64*t^2 - 13/32
1753
+ sage: phi = E.isogeny(ker, check=True); phi
1754
+ Isogeny of degree 13
1755
+ from Elliptic Curve defined by y^2 = x^3 + x
1756
+ over Number Field in t with defining polynomial x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13
1757
+ to Elliptic Curve defined by y^2 = x^3 + (-2535/16*t^10+2535/8*t^8-3705/8*t^6-5655/2*t^4-44655/16*t^2-2047/8)*x
1758
+ over Number Field in t with defining polynomial x^12 - 2*x^10 + 3*x^8 + 228/13*x^6 + 235/13*x^4 + 22/13*x^2 + 1/13
1759
+
1760
+ ALGORITHM: [EPSV2023]_, Algorithm 3 (``KernelPolynomialFromDivisor``).
1761
+ """
1762
+ l = ZZ(l)
1763
+ if check:
1764
+ if not l.is_prime():
1765
+ raise NotImplementedError('currently, kernel_polynomial_from_divisor() only supports prime orders')
1766
+ if not f.is_irreducible():
1767
+ raise NotImplementedError('currently, kernel_polynomial_from_divisor() only supports irreducible polynomials')
1768
+ if f.parent().base_ring() != self.base_ring():
1769
+ raise TypeError('given polynomial is not defined over the base ring of the curve')
1770
+ if self.division_polynomial(l, x=f.parent().quotient_ring(f).gen()):
1771
+ raise ValueError(f'given polynomial does not divide the {l}-division polynomial')
1772
+
1773
+ if l == 2:
1774
+ return f
1775
+
1776
+ if not f.degree().divides(l//2):
1777
+ raise ValueError(f'given polynomial does not define a rational {l}-isogeny')
1778
+
1779
+ from sage.schemes.elliptic_curves.isogeny_small_degree import _least_semi_primitive
1780
+ a = _least_semi_primitive(l)
1781
+
1782
+ def mul_a(x):
1783
+ return self._multiple_x_numerator(a, x=x) / self._multiple_x_denominator(a, x=x)
1784
+
1785
+ def x_mod(g):
1786
+ return g.parent().quotient(g).gen()
1787
+
1788
+ fs = [f]
1789
+ m = l//2//f.degree()
1790
+
1791
+ for i in range(1, m):
1792
+ fs.append(mul_a(x_mod(fs[-1])).minpoly())
1793
+
1794
+ if fs[0](mul_a(x_mod(fs[-1]))):
1795
+ raise ValueError(f'given polynomial does not define a rational {l}-isogeny')
1796
+
1797
+ return prod(fs)
1798
+
1799
+ def isogenies_prime_degree(self, l=None, max_l=31) -> list:
1800
+ """
1801
+ Return a list of all separable isogenies (up to post-composition with
1802
+ isomorphisms) of given prime degree(s) with domain equal to ``self``,
1803
+ which are defined over the base field of ``self``.
1804
+
1805
+ INPUT:
1806
+
1807
+ - ``l`` -- a prime or a list of primes
1808
+
1809
+ - ``max_l`` -- (default: 31) a bound on the primes to be tested.
1810
+ This is only used if ``l`` is ``None``.
1811
+
1812
+ OUTPUT:
1813
+
1814
+ (list) All separable `l`-isogenies for the given `l` with domain ``self``.
1815
+
1816
+ ALGORITHM:
1817
+
1818
+ Calls the generic function :func:`isogenies_prime_degree()`.
1819
+ This is generic code, valid for all fields. It requires that
1820
+ certain operations have been implemented over the base field,
1821
+ such as root-finding for univariate polynomials.
1822
+
1823
+ EXAMPLES:
1824
+
1825
+ Examples over finite fields::
1826
+
1827
+ sage: # needs sage.libs.pari
1828
+ sage: E = EllipticCurve(GF(next_prime(1000000)), [7,8])
1829
+ sage: E.isogenies_prime_degree(2)
1830
+ [Isogeny of degree 2
1831
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1832
+ to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
1833
+ Isogeny of degree 2
1834
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1835
+ to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
1836
+ Isogeny of degree 2
1837
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1838
+ to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003]
1839
+ sage: E.isogenies_prime_degree(3)
1840
+ []
1841
+ sage: E.isogenies_prime_degree(5)
1842
+ []
1843
+ sage: E.isogenies_prime_degree(7)
1844
+ []
1845
+ sage: E.isogenies_prime_degree(11)
1846
+ []
1847
+ sage: E.isogenies_prime_degree(13)
1848
+ [Isogeny of degree 13
1849
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1850
+ to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
1851
+ Isogeny of degree 13
1852
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1853
+ to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
1854
+ sage: E.isogenies_prime_degree(max_l=13)
1855
+ [Isogeny of degree 2
1856
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1857
+ to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
1858
+ Isogeny of degree 2
1859
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1860
+ to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
1861
+ Isogeny of degree 2
1862
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1863
+ to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
1864
+ Isogeny of degree 13
1865
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1866
+ to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
1867
+ Isogeny of degree 13
1868
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1869
+ to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
1870
+ sage: E.isogenies_prime_degree() # Default limit of 31
1871
+ [Isogeny of degree 2
1872
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1873
+ to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
1874
+ Isogeny of degree 2
1875
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1876
+ to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
1877
+ Isogeny of degree 2
1878
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1879
+ to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
1880
+ Isogeny of degree 13
1881
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1882
+ to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
1883
+ Isogeny of degree 13
1884
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1885
+ to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003,
1886
+ Isogeny of degree 17
1887
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1888
+ to Elliptic Curve defined by y^2 = x^3 + 347438*x + 594729 over Finite Field of size 1000003,
1889
+ Isogeny of degree 17
1890
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1891
+ to Elliptic Curve defined by y^2 = x^3 + 674846*x + 7392 over Finite Field of size 1000003,
1892
+ Isogeny of degree 23
1893
+ from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
1894
+ to Elliptic Curve defined by y^2 = x^3 + 390065*x + 605596 over Finite Field of size 1000003]
1895
+
1896
+ sage: E = EllipticCurve(GF(17), [2,0])
1897
+ sage: E.isogenies_prime_degree(3)
1898
+ []
1899
+ sage: E.isogenies_prime_degree(2)
1900
+ [Isogeny of degree 2
1901
+ from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
1902
+ to Elliptic Curve defined by y^2 = x^3 + 9*x over Finite Field of size 17,
1903
+ Isogeny of degree 2
1904
+ from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
1905
+ to Elliptic Curve defined by y^2 = x^3 + 5*x + 9 over Finite Field of size 17,
1906
+ Isogeny of degree 2
1907
+ from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
1908
+ to Elliptic Curve defined by y^2 = x^3 + 5*x + 8 over Finite Field of size 17]
1909
+
1910
+ The base field matters, over a field extension we find more
1911
+ isogenies::
1912
+
1913
+ sage: E = EllipticCurve(GF(13), [2,8])
1914
+ sage: E.isogenies_prime_degree(max_l=3)
1915
+ [Isogeny of degree 2
1916
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
1917
+ to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field of size 13,
1918
+ Isogeny of degree 3
1919
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
1920
+ to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field of size 13]
1921
+
1922
+ sage: # needs sage.rings.finite_rings
1923
+ sage: E = EllipticCurve(GF(13^6), [2,8])
1924
+ sage: E.isogenies_prime_degree(max_l=3)
1925
+ [Isogeny of degree 2
1926
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1927
+ to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field in z6 of size 13^6,
1928
+ Isogeny of degree 2
1929
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1930
+ to Elliptic Curve defined by y^2 = x^3 + (2*z6^5+6*z6^4+9*z6^3+8*z6+7)*x + (3*z6^5+9*z6^4+7*z6^3+12*z6+7) over Finite Field in z6 of size 13^6,
1931
+ Isogeny of degree 2
1932
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1933
+ to Elliptic Curve defined by y^2 = x^3 + (11*z6^5+7*z6^4+4*z6^3+5*z6+9)*x + (10*z6^5+4*z6^4+6*z6^3+z6+10) over Finite Field in z6 of size 13^6,
1934
+ Isogeny of degree 3
1935
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1936
+ to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field in z6 of size 13^6,
1937
+ Isogeny of degree 3
1938
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1939
+ to Elliptic Curve defined by y^2 = x^3 + (3*z6^5+5*z6^4+8*z6^3+11*z6^2+5*z6+12)*x + (12*z6^5+6*z6^4+8*z6^3+4*z6^2+7*z6+6) over Finite Field in z6 of size 13^6,
1940
+ Isogeny of degree 3
1941
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1942
+ to Elliptic Curve defined by y^2 = x^3 + (7*z6^4+12*z6^3+7*z6^2+4)*x + (6*z6^5+10*z6^3+12*z6^2+10*z6+8) over Finite Field in z6 of size 13^6,
1943
+ Isogeny of degree 3
1944
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
1945
+ to Elliptic Curve defined by y^2 = x^3 + (10*z6^5+z6^4+6*z6^3+8*z6^2+8*z6)*x + (8*z6^5+7*z6^4+8*z6^3+10*z6^2+9*z6+7) over Finite Field in z6 of size 13^6]
1946
+
1947
+ If the degree equals the characteristic, we find only separable
1948
+ isogenies::
1949
+
1950
+ sage: E = EllipticCurve(GF(13), [2,8])
1951
+ sage: E.isogenies_prime_degree(13)
1952
+ [Isogeny of degree 13
1953
+ from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
1954
+ to Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field of size 13]
1955
+ sage: E = EllipticCurve(GF(5), [1,1])
1956
+ sage: E.isogenies_prime_degree(5)
1957
+ [Isogeny of degree 5
1958
+ from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
1959
+ to Elliptic Curve defined by y^2 = x^3 + x + 4 over Finite Field of size 5]
1960
+
1961
+ sage: # needs sage.rings.finite_rings
1962
+ sage: k.<a> = GF(3^4)
1963
+ sage: E = EllipticCurve(k, [0,1,0,0,a])
1964
+ sage: E.isogenies_prime_degree(3)
1965
+ [Isogeny of degree 3
1966
+ from Elliptic Curve defined by y^2 = x^3 + x^2 + a
1967
+ over Finite Field in a of size 3^4
1968
+ to Elliptic Curve defined by y^2 = x^3 + x^2 + (2*a^3+a^2+2)*x + (a^2+2)
1969
+ over Finite Field in a of size 3^4]
1970
+
1971
+ In the supersingular case, there are no separable isogenies of
1972
+ degree equal to the characteristic::
1973
+
1974
+ sage: E = EllipticCurve(GF(5), [0,1])
1975
+ sage: E.isogenies_prime_degree(5)
1976
+ []
1977
+
1978
+ An example over a rational function field::
1979
+
1980
+ sage: R.<t> = GF(5)[]
1981
+ sage: K = R.fraction_field()
1982
+ sage: E = EllipticCurve(K, [1, t^5])
1983
+ sage: E.isogenies_prime_degree(5)
1984
+ [Isogeny of degree 5
1985
+ from Elliptic Curve defined by y^2 = x^3 + x + t^5 over Fraction Field
1986
+ of Univariate Polynomial Ring in t over Finite Field of size 5
1987
+ to Elliptic Curve defined by y^2 = x^3 + x + 4*t over Fraction Field
1988
+ of Univariate Polynomial Ring in t over Finite Field of size 5]
1989
+
1990
+ Examples over number fields (other than QQ)::
1991
+
1992
+ sage: # needs sage.rings.number_field
1993
+ sage: x = polygen(ZZ, 'x')
1994
+ sage: QQroot2.<e> = NumberField(x^2 - 2)
1995
+ sage: E = EllipticCurve(QQroot2, j=8000)
1996
+ sage: E.isogenies_prime_degree()
1997
+ [Isogeny of degree 2
1998
+ from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
1999
+ over Number Field in e with defining polynomial x^2 - 2
2000
+ to Elliptic Curve defined by y^2 = x^3 + (-36750)*x + 2401000
2001
+ over Number Field in e with defining polynomial x^2 - 2,
2002
+ Isogeny of degree 2
2003
+ from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
2004
+ over Number Field in e with defining polynomial x^2 - 2
2005
+ to Elliptic Curve defined by y^2 = x^3 + (220500*e-257250)*x + (54022500*e-88837000)
2006
+ over Number Field in e with defining polynomial x^2 - 2,
2007
+ Isogeny of degree 2
2008
+ from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
2009
+ over Number Field in e with defining polynomial x^2 - 2
2010
+ to Elliptic Curve defined by y^2 = x^3 + (-220500*e-257250)*x + (-54022500*e-88837000)
2011
+ over Number Field in e with defining polynomial x^2 - 2]
2012
+ sage: E = EllipticCurve(QQroot2, [1,0,1,4, -6]); E
2013
+ Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
2014
+ over Number Field in e with defining polynomial x^2 - 2
2015
+ sage: E.isogenies_prime_degree(2)
2016
+ [Isogeny of degree 2
2017
+ from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
2018
+ over Number Field in e with defining polynomial x^2 - 2
2019
+ to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-36)*x + (-70)
2020
+ over Number Field in e with defining polynomial x^2 - 2]
2021
+ sage: E.isogenies_prime_degree(3)
2022
+ [Isogeny of degree 3
2023
+ from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
2024
+ over Number Field in e with defining polynomial x^2 - 2
2025
+ to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-1)*x
2026
+ over Number Field in e with defining polynomial x^2 - 2,
2027
+ Isogeny of degree 3
2028
+ from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
2029
+ over Number Field in e with defining polynomial x^2 - 2
2030
+ to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-171)*x + (-874)
2031
+ over Number Field in e with defining polynomial x^2 - 2]
2032
+
2033
+ These are not implemented yet::
2034
+
2035
+ sage: E = EllipticCurve(QQbar, [1,18]); E # needs sage.rings.number_field
2036
+ Elliptic Curve defined by y^2 = x^3 + x + 18 over Algebraic Field
2037
+ sage: E.isogenies_prime_degree() # needs sage.rings.number_field
2038
+ Traceback (most recent call last):
2039
+ ...
2040
+ NotImplementedError: This code could be implemented for QQbar, but has not been yet.
2041
+
2042
+ sage: E = EllipticCurve(CC, [1,18]); E
2043
+ Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
2044
+ over Complex Field with 53 bits of precision
2045
+ sage: E.isogenies_prime_degree(11)
2046
+ Traceback (most recent call last):
2047
+ ...
2048
+ NotImplementedError: This code could be implemented for general complex fields,
2049
+ but has not been yet.
2050
+
2051
+ TESTS::
2052
+
2053
+ sage: E = EllipticCurve(QQ, [1,1])
2054
+ sage: E.isogenies_prime_degree([2, 4])
2055
+ Traceback (most recent call last):
2056
+ ...
2057
+ ValueError: 4 is not prime.
2058
+ sage: E.isogenies_prime_degree(4)
2059
+ Traceback (most recent call last):
2060
+ ...
2061
+ ValueError: 4 is not prime.
2062
+ """
2063
+ F = self.base_ring()
2064
+ if isinstance(F, sage.rings.abc.RealField):
2065
+ raise NotImplementedError("This code could be implemented for general real fields, but has not been yet.")
2066
+ if isinstance(F, sage.rings.abc.ComplexField):
2067
+ raise NotImplementedError("This code could be implemented for general complex fields, but has not been yet.")
2068
+ if isinstance(F, sage.rings.abc.AlgebraicField):
2069
+ raise NotImplementedError("This code could be implemented for QQbar, but has not been yet.")
2070
+
2071
+ if l is None:
2072
+ from sage.rings.fast_arith import prime_range
2073
+ L = prime_range(max_l + 1)
2074
+ else:
2075
+ try:
2076
+ l = list(l)
2077
+ except TypeError:
2078
+ L = [ZZ(l)]
2079
+ else:
2080
+ L = [ZZ(d) for d in l]
2081
+
2082
+ from .isogeny_small_degree import isogenies_prime_degree
2083
+ return sum([isogenies_prime_degree(self, d) for d in L], [])
2084
+
2085
+ def isogenies_degree(self, n, *, _intermediate=False):
2086
+ r"""
2087
+ Return an iterator of all separable isogenies of given degree (up to
2088
+ post-composition with isomorphisms) with domain equal to ``self``,
2089
+ which are defined over the base field of ``self``.
2090
+
2091
+ ALGORITHM:
2092
+
2093
+ The prime factors `p` of `n` are processed one by one in decreasing
2094
+ order, each time "branching" out by taking isogenies of degree `p`.
2095
+
2096
+ INPUT:
2097
+
2098
+ - ``n`` -- integer, or its
2099
+ :class:`~sage.structure.factorization.Factorization`.
2100
+
2101
+ - ``_intermediate`` -- (bool, default: False): If set, the isogenies
2102
+ from this curve to the curves traversed within the depth-first search
2103
+ are returned. This is for internal use only.
2104
+
2105
+ EXAMPLES::
2106
+
2107
+ sage: E = EllipticCurve(GF(11), [1, 1])
2108
+ sage: list(E.isogenies_degree(23 * 19))
2109
+ [Composite morphism of degree 437 = 23*19:
2110
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 11
2111
+ To: Elliptic Curve defined by y^2 = x^3 + 8*x + 7 over Finite Field of size 11,
2112
+ Composite morphism of degree 437 = 23*19:
2113
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 11
2114
+ To: Elliptic Curve defined by y^2 = x^3 + 6*x + 2 over Finite Field of size 11,
2115
+ Composite morphism of degree 437 = 23*19:
2116
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 11
2117
+ To: Elliptic Curve defined by y^2 = x^3 + 2*x + 6 over Finite Field of size 11,
2118
+ Composite morphism of degree 437 = 23*19:
2119
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 11
2120
+ To: Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 11]
2121
+
2122
+ ::
2123
+
2124
+ sage: # needs sage.symbolic
2125
+ sage: E = EllipticCurve(GF(next_prime(2^32)), j=1728)
2126
+ sage: sorted([phi.codomain().j_invariant() for phi in E.isogenies_degree(11 * 17 * 19^2)]) # long time (:issue:`39569`)
2127
+ [1348157279, 1348157279, 1713365879, 1713365879, 3153894341, 3153894341,
2128
+ 3225140514, 3225140514, 3673460198, 3673460198, 3994312564, 3994312564]
2129
+ sage: it = E.isogenies_degree(2^2); it
2130
+ <generator object EllipticCurve_field.isogenies_degree at 0x...>
2131
+ sage: all(phi.degree() == 2^2 for phi in it)
2132
+ True
2133
+
2134
+ We verify that the isogenies outputted are distinct. Note that we do
2135
+ not use a ``set`` or any hash-based data structure, as hashing
2136
+ isogenies is slow::
2137
+
2138
+ sage: # needs sage.symbolic
2139
+ sage: import itertools
2140
+ sage: all_distinct = lambda arr: all(x != y for x, y in itertools.combinations(arr, 2))
2141
+ sage: K.<z> = GF((19, 2))
2142
+ sage: E = EllipticCurve(K, [11*z+5, 14*z+3])
2143
+ sage: S = list(E.isogenies_degree(5^2)); len(S), all_distinct(S)
2144
+ (3, True)
2145
+ sage: S = list(E.isogenies_degree(5^2*11)); len(S), all_distinct(S)
2146
+ (6, True)
2147
+ sage: S = list(E.isogenies_degree(5^2*11^4)); len(S), all_distinct(S) # long time (2s)
2148
+ (15, True)
2149
+
2150
+ For curves over number fields, the number of distinct isogenies will usually be small::
2151
+
2152
+ sage: E = EllipticCurve(QQ, [0, 1, 0, -2, 0])
2153
+ sage: len(list(E.isogenies_degree(2**1)))
2154
+ 3
2155
+ sage: len(list(E.isogenies_degree(2**5)))
2156
+ 3
2157
+ sage: len(list(E.isogenies_degree(2**8))) # long time (8s)
2158
+ 1
2159
+
2160
+ ::
2161
+
2162
+ sage: pol = PolynomialRing(QQ, 'x')([529, 782, 1])
2163
+ sage: L.<a> = NumberField(pol)
2164
+ sage: E = EllipticCurve(j=-7072/1127*a + 2016)
2165
+ sage: len(list(E.isogenies_degree(2)))
2166
+ 3
2167
+ sage: len(list(E.isogenies_degree(2**5)))
2168
+ 3
2169
+
2170
+ ::
2171
+
2172
+ sage: pol = PolynomialRing(QQ, 'x')([1, -3, 5, -5, 5, -3, 1])
2173
+ sage: L.<a> = NumberField(pol)
2174
+ sage: js = hilbert_class_polynomial(-23).roots(L, multiplicities=False)
2175
+ sage: E = EllipticCurve(j=choice(js))
2176
+ sage: len(list(E.isogenies_degree(2^3))) # long time (9s)
2177
+ 10
2178
+
2179
+ TESTS::
2180
+
2181
+ sage: E = EllipticCurve(GF(next_prime(2^32)), j=1728)
2182
+ sage: list(E.isogenies_degree(2^2, _intermediate=True))
2183
+ [Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 4294967311
2184
+ Via: (u,r,s,t) = (1, 0, 0, 0),
2185
+ Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 4294967311
2186
+ to Elliptic Curve defined by y^2 = x^3 + 4294967307*x over Finite Field of size 4294967311,
2187
+ Composite morphism of degree 4 = 2^2:
2188
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 4294967311
2189
+ To: Elliptic Curve defined by y^2 = x^3 + 16*x over Finite Field of size 4294967311,
2190
+ Composite morphism of degree 4 = 2^2:
2191
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 4294967311
2192
+ To: Elliptic Curve defined by y^2 = x^3 + 4294967267*x + 4294967199 over Finite Field of size 4294967311,
2193
+ Composite morphism of degree 4 = 2^2:
2194
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 4294967311
2195
+ To: Elliptic Curve defined by y^2 = x^3 + 4294967267*x + 112 over Finite Field of size 4294967311]
2196
+ sage: all(isog.domain() is E for isog in _)
2197
+ True
2198
+ sage: all(isog.domain() is E for isog in E.isogenies_degree(2^5, _intermediate=True)) # long time (:issue:`39569`), needs sage.symbolic
2199
+ True
2200
+
2201
+ The following curve has no degree-`53` isogenies, so the code is quick::
2202
+
2203
+ sage: E = EllipticCurve(GF(103), [3, 5])
2204
+ sage: E.isogenies_prime_degree(53)
2205
+ []
2206
+ sage: list(E.isogenies_degree(product(prime_range(3, 53)) * 53))
2207
+ []
2208
+ """
2209
+ def compute_key(phi):
2210
+ """
2211
+ Data used in ``hash(phi)`` excluding the expensive ``.kernel_polynomial``.
2212
+ """
2213
+ return (phi.domain(), phi.codomain(), phi.degree(), phi.scaling_factor())
2214
+
2215
+ from sage.schemes.elliptic_curves.weierstrass_morphism import identity_morphism
2216
+ from sage.structure.factorization import Factorization
2217
+
2218
+ if not isinstance(n, Factorization):
2219
+ n = Integer(n).factor()
2220
+
2221
+ if n.value() == 1:
2222
+ yield identity_morphism(self)
2223
+ return
2224
+
2225
+ p = n[-1][0]
2226
+ seen = {}
2227
+
2228
+ def insert_seen(phi) -> bool:
2229
+ key = compute_key(phi)
2230
+ if key not in seen:
2231
+ seen[key] = [phi]
2232
+ return True
2233
+ for psi in seen[key]:
2234
+ if psi == phi:
2235
+ return False
2236
+ seen[key].append(phi)
2237
+ return True
2238
+
2239
+ if _intermediate:
2240
+ yield identity_morphism(self)
2241
+
2242
+ # isog: self -> E1
2243
+ for isog in self.isogenies_prime_degree(p):
2244
+ if _intermediate:
2245
+ if insert_seen(isog):
2246
+ # self -> E1
2247
+ yield isog
2248
+
2249
+ Eiso = isog.codomain()
2250
+ # next_isog : E1 -> E2
2251
+ for next_isog in Eiso.isogenies_degree(n / p, _intermediate=_intermediate):
2252
+ # psi: self -> E2
2253
+ psi = next_isog * isog
2254
+ if insert_seen(psi):
2255
+ # self -> E2
2256
+ yield psi
2257
+
2258
+ def is_isogenous(self, other, field=None) -> bool:
2259
+ """
2260
+ Return whether or not ``self`` is isogenous to ``other``.
2261
+
2262
+ INPUT:
2263
+
2264
+ - ``other`` -- another elliptic curve
2265
+
2266
+ - ``field`` -- (default: ``None``) currently not implemented. A
2267
+ field containing the base fields of the two elliptic curves
2268
+ onto which the two curves may be extended to test if they
2269
+ are isogenous over this field. By default ``is_isogenous`` will
2270
+ not try to find this field unless one of the curves can be
2271
+ be extended into the base field of the ``other``, in which case
2272
+ it will test over the larger base field.
2273
+
2274
+ OUTPUT: boolean; ``True`` if there is an isogeny from curve ``self`` to
2275
+ curve ``other`` defined over ``field``
2276
+
2277
+ METHOD:
2278
+
2279
+ Over general fields this is only implemented in trivial cases.
2280
+
2281
+ EXAMPLES::
2282
+
2283
+ sage: E1 = EllipticCurve(CC, [1,18]); E1
2284
+ Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
2285
+ over Complex Field with 53 bits of precision
2286
+ sage: E2 = EllipticCurve(CC, [2,7]); E2
2287
+ Elliptic Curve defined by y^2 = x^3 + 2.00000000000000*x + 7.00000000000000
2288
+ over Complex Field with 53 bits of precision
2289
+ sage: E1.is_isogenous(E2)
2290
+ Traceback (most recent call last):
2291
+ ...
2292
+ NotImplementedError: Only implemented for isomorphic curves over general fields.
2293
+
2294
+ sage: E1 = EllipticCurve(Frac(PolynomialRing(ZZ,'t')), [2,19]); E1
2295
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 19
2296
+ over Fraction Field of Univariate Polynomial Ring in t over Integer Ring
2297
+ sage: E2 = EllipticCurve(CC, [23,4]); E2
2298
+ Elliptic Curve defined by y^2 = x^3 + 23.0000000000000*x + 4.00000000000000
2299
+ over Complex Field with 53 bits of precision
2300
+ sage: E1.is_isogenous(E2)
2301
+ Traceback (most recent call last):
2302
+ ...
2303
+ NotImplementedError: Only implemented for isomorphic curves over general fields.
2304
+ """
2305
+ from .ell_generic import EllipticCurve_generic
2306
+ if not isinstance(other, EllipticCurve_generic):
2307
+ raise ValueError("Second argument is not an Elliptic Curve.")
2308
+ if self.is_isomorphic(other):
2309
+ return True
2310
+ else:
2311
+ raise NotImplementedError("Only implemented for isomorphic curves over general fields.")
2312
+
2313
+ def weierstrass_p(self, prec=20, algorithm=None):
2314
+ r"""
2315
+ Compute the Weierstrass `\wp`-function of this elliptic curve.
2316
+
2317
+ ALGORITHM: :func:`sage.schemes.elliptic_curves.ell_wp.weierstrass_p`
2318
+
2319
+ INPUT:
2320
+
2321
+ - ``prec`` -- precision
2322
+
2323
+ - ``algorithm`` -- string or ``None`` (default: ``None``);
2324
+ a choice of algorithm among ``'pari'``, ``'fast'``, ``'quadratic'``
2325
+ or ``None`` to let this function determine the best algorithm to use
2326
+
2327
+ OUTPUT:
2328
+
2329
+ A Laurent series in one variable `z` with coefficients in the
2330
+ base field `k` of `E`.
2331
+
2332
+ EXAMPLES::
2333
+
2334
+ sage: # needs database_cremona_mini_ellcurve
2335
+ sage: E = EllipticCurve('11a1')
2336
+ sage: E.weierstrass_p(prec=10)
2337
+ z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8 + O(z^10)
2338
+ sage: E.weierstrass_p(prec=8)
2339
+ z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
2340
+ sage: Esh = E.short_weierstrass_model()
2341
+ sage: Esh.weierstrass_p(prec=8)
2342
+ z^-2 + 13392/5*z^2 + 1080432/7*z^4 + 59781888/25*z^6 + O(z^8)
2343
+ sage: E.weierstrass_p(prec=20, algorithm='fast')
2344
+ z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
2345
+ + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
2346
+ + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
2347
+ sage: E.weierstrass_p(prec=20, algorithm='pari')
2348
+ z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
2349
+ + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
2350
+ + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
2351
+ sage: E.weierstrass_p(prec=20, algorithm='quadratic')
2352
+ z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
2353
+ + 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
2354
+ + 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
2355
+ """
2356
+ from .ell_wp import weierstrass_p
2357
+ return weierstrass_p(self, prec=prec, algorithm=algorithm)
2358
+
2359
+ def hasse_invariant(self):
2360
+ r"""
2361
+ Return the Hasse invariant of this elliptic curve.
2362
+
2363
+ OUTPUT:
2364
+
2365
+ The Hasse invariant of this elliptic curve, as an element of
2366
+ the base field. This is only defined over fields of positive
2367
+ characteristic, and is an element of the field which is zero
2368
+ if and only if the curve is supersingular. Over a field of
2369
+ characteristic zero, where the Hasse invariant is undefined,
2370
+ a :exc:`ValueError` is raised.
2371
+
2372
+ EXAMPLES::
2373
+
2374
+ sage: E = EllipticCurve([Mod(1,2), Mod(1,2), 0, 0, Mod(1,2)])
2375
+ sage: E.hasse_invariant()
2376
+ 1
2377
+ sage: E = EllipticCurve([0, 0, Mod(1,3), Mod(1,3), Mod(1,3)])
2378
+ sage: E.hasse_invariant()
2379
+ 0
2380
+ sage: E = EllipticCurve([0, 0, Mod(1,5), 0, Mod(2,5)])
2381
+ sage: E.hasse_invariant()
2382
+ 0
2383
+ sage: E = EllipticCurve([0, 0, Mod(1,5), Mod(1,5), Mod(2,5)])
2384
+ sage: E.hasse_invariant()
2385
+ 2
2386
+
2387
+ Some examples over larger fields::
2388
+
2389
+ sage: # needs sage.rings.finite_rings
2390
+ sage: EllipticCurve(GF(101), [0,0,0,0,1]).hasse_invariant()
2391
+ 0
2392
+ sage: EllipticCurve(GF(101), [0,0,0,1,1]).hasse_invariant()
2393
+ 98
2394
+ sage: EllipticCurve(GF(103), [0,0,0,0,1]).hasse_invariant()
2395
+ 20
2396
+ sage: EllipticCurve(GF(103), [0,0,0,1,1]).hasse_invariant()
2397
+ 17
2398
+ sage: F.<a> = GF(107^2)
2399
+ sage: EllipticCurve(F, [0,0,0,a,1]).hasse_invariant()
2400
+ 62*a + 75
2401
+ sage: EllipticCurve(F, [0,0,0,0,a]).hasse_invariant()
2402
+ 0
2403
+
2404
+ Over fields of characteristic zero, the Hasse invariant is
2405
+ undefined::
2406
+
2407
+ sage: E = EllipticCurve([0,0,0,0,1])
2408
+ sage: E.hasse_invariant()
2409
+ Traceback (most recent call last):
2410
+ ...
2411
+ ValueError: Hasse invariant only defined in positive characteristic
2412
+ """
2413
+ k = self.base_field()
2414
+ p = k.characteristic()
2415
+ if p == 0:
2416
+ raise ValueError('Hasse invariant only defined in positive characteristic')
2417
+ elif p == 2:
2418
+ return self.a1()
2419
+ elif p == 3:
2420
+ return self.b2()
2421
+ elif p == 5:
2422
+ return self.c4()
2423
+ elif p == 7:
2424
+ return -self.c6()
2425
+ else:
2426
+ R = k['x']
2427
+ x = R.gen()
2428
+ E = self.short_weierstrass_model()
2429
+ f = (x**3+E.a4()*x+E.a6())**((p-1)//2)
2430
+ return f.coefficients(sparse=False)[p-1]
2431
+
2432
+ def isogeny_ell_graph(self, l, directed=True, label_by_j=False):
2433
+ """
2434
+ Return a graph representing the ``l``-degree ``K``-isogenies between
2435
+ ``K``-isomorphism classes of elliptic curves for ``K =
2436
+ self.base_field()``.
2437
+
2438
+ INPUT:
2439
+
2440
+ - ``l`` -- prime degree of isogenies
2441
+
2442
+ - ``directed`` -- boolean (default: ``True``); whether to return a
2443
+ directed or undirected graph. In the undirected case, the in-degrees
2444
+ and out-degrees of the vertices must be balanced and therefore the
2445
+ number of out-edges from the vertices corresponding to j-invariants 0
2446
+ and 1728 (if they are part of the graph) are reduced to match the
2447
+ number of in-edges.
2448
+
2449
+ - ``label_by_j`` -- boolean (default: ``False``); whether to label
2450
+ graph vertices by the j-invariant corresponding to the isomorphism
2451
+ class of curves. If the j-invariant is not unique in the isogeny
2452
+ class, append ``*`` to it to indicate a twist. Otherwise, if
2453
+ ``False`` label vertices by the equation of a representative curve.
2454
+
2455
+ OUTPUT: a :class:`Graph` or :class:`DiGraph`
2456
+
2457
+ EXAMPLES:
2458
+
2459
+ Ordinary curve over finite extension field of degree 2::
2460
+
2461
+ sage: # needs sage.graphs sage.rings.finite_rings
2462
+ sage: x = polygen(ZZ, 'x')
2463
+ sage: E = EllipticCurve(GF(59^2, "i", x^2 + 1), j=5)
2464
+ sage: G = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G
2465
+ Graph on 20 vertices
2466
+ sage: G.vertices(sort=True)
2467
+ ['1',
2468
+ '12',
2469
+ ...
2470
+ 'i + 55']
2471
+ sage: G.edges(sort=True)
2472
+ [('1', '28*i + 11', None),
2473
+ ('1', '31*i + 11', None),
2474
+ ...
2475
+ ('8', 'i + 1', None)]
2476
+
2477
+ Supersingular curve over prime field::
2478
+
2479
+ sage: # needs sage.graphs sage.rings.finite_rings
2480
+ sage: E = EllipticCurve(GF(419), j=1728)
2481
+ sage: G3 = E.isogeny_ell_graph(3, directed=False, label_by_j=True); G3
2482
+ Graph on 27 vertices
2483
+ sage: G3.vertices(sort=True)
2484
+ ['0',
2485
+ '0*',
2486
+ ...
2487
+ '98*']
2488
+ sage: G3.edges(sort=True)
2489
+ [('0', '0*', None),
2490
+ ('0', '13', None),
2491
+ ...
2492
+ ('48*', '98*', None)]
2493
+ sage: G5 = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G5
2494
+ Graph on 9 vertices
2495
+ sage: G5.vertices(sort=True)
2496
+ ['13', '13*', '407', '407*', '52', '62', '62*', '98', '98*']
2497
+ sage: G5.edges(sort=True)
2498
+ [('13', '52', None),
2499
+ ('13', '98', None),
2500
+ ...
2501
+ ('62*', '98*', None)]
2502
+
2503
+ Supersingular curve over finite extension field of degree 2::
2504
+
2505
+ sage: # needs sage.graphs sage.rings.finite_rings
2506
+ sage: K = GF(431^2, "i", x^2 + 1)
2507
+ sage: E = EllipticCurve(K, j=0)
2508
+ sage: E.is_supersingular()
2509
+ True
2510
+ sage: G = E.isogeny_ell_graph(2, directed=True, label_by_j=True); G
2511
+ Looped multi-digraph on 37 vertices
2512
+ sage: G.vertices(sort=True)
2513
+ ['0',
2514
+ '102',
2515
+ ...
2516
+ '87*i + 190']
2517
+ sage: G.edges(sort=True)
2518
+ [('0', '125', None),
2519
+ ('0', '125', None),
2520
+ ...
2521
+ '81*i + 65', None)]
2522
+ sage: H = E.isogeny_ell_graph(2, directed=False, label_by_j=True); H
2523
+ Looped multi-graph on 37 vertices
2524
+ sage: H.vertices(sort=True)
2525
+ ['0',
2526
+ '102',
2527
+ ...
2528
+ '87*i + 190']
2529
+ sage: H.edges(sort=True)
2530
+ [('0', '125', None),
2531
+ ('102', '125', None),
2532
+ ...
2533
+ ('81*i + 65', '87*i + 190', None)]
2534
+
2535
+ Curve over a quadratic number field::
2536
+
2537
+ sage: # needs sage.graphs sage.rings.finite_rings sage.rings.number_field
2538
+ sage: K.<e> = NumberField(x^2 - 2)
2539
+ sage: E = EllipticCurve(K, [1, 0, 1, 4, -6])
2540
+ sage: G2 = E.isogeny_ell_graph(2, directed=False)
2541
+ sage: G2.vertices(sort=True)
2542
+ ['y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
2543
+ 'y^2 + x*y + y = x^3 + (-36)*x + (-70)',
2544
+ 'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)',
2545
+ 'y^2 + x*y + y = x^3 + 4*x + (-6)']
2546
+ sage: G2.edges(sort=True)
2547
+ [('y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
2548
+ 'y^2 + x*y + y = x^3 + (-36)*x + (-70)', None),
2549
+ ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
2550
+ 'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)', None),
2551
+ ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
2552
+ 'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]
2553
+ sage: G3 = E.isogeny_ell_graph(3, directed=False)
2554
+ sage: G3.vertices(sort=True)
2555
+ ['y^2 + x*y + y = x^3 + (-1)*x',
2556
+ 'y^2 + x*y + y = x^3 + (-171)*x + (-874)',
2557
+ 'y^2 + x*y + y = x^3 + 4*x + (-6)']
2558
+ sage: G3.edges(sort=True)
2559
+ [('y^2 + x*y + y = x^3 + (-1)*x',
2560
+ 'y^2 + x*y + y = x^3 + 4*x + (-6)', None),
2561
+ ('y^2 + x*y + y = x^3 + (-171)*x + (-874)',
2562
+ 'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]
2563
+
2564
+ TESTS::
2565
+
2566
+ sage: # needs sage.graphs
2567
+ sage: E = EllipticCurve(GF(11), j=0)
2568
+ sage: G0 = E.isogeny_ell_graph(2, directed=False)
2569
+ sage: G0.is_directed()
2570
+ False
2571
+ sage: G1 = E.isogeny_ell_graph(2, directed=True)
2572
+ sage: G1.is_directed()
2573
+ True
2574
+ sage: G2 = E.isogeny_ell_graph(2, label_by_j=False)
2575
+ sage: G2.vertices(sort=True)
2576
+ ['y^2 = x^3 + 1',
2577
+ 'y^2 = x^3 + 2',
2578
+ 'y^2 = x^3 + 5*x',
2579
+ 'y^2 = x^3 + 7*x']
2580
+ sage: G3 = E.isogeny_ell_graph(2, label_by_j=True)
2581
+ sage: G3.vertices(sort=True)
2582
+ ['0', '0*', '1', '1*']
2583
+ """
2584
+ from warnings import warn
2585
+ from sage.matrix.constructor import Matrix
2586
+
2587
+ # warn users if things are getting big
2588
+ if l == 2:
2589
+ curve_max = 1000
2590
+ if l == 3:
2591
+ curve_max = 700
2592
+ elif l < 20:
2593
+ curve_max = 200
2594
+ else:
2595
+ curve_max = 50
2596
+
2597
+ Es = [self] # list of curves in graph
2598
+ A = [] # adjacency matrix
2599
+ labels = [] # list of vertex labels
2600
+ for i, E in enumerate(Es):
2601
+ if 0 < curve_max < len(Es):
2602
+ warn('Isogeny graph contains more than '
2603
+ + str(curve_max) + ' curves.')
2604
+ curve_max = 0
2605
+
2606
+ r = [0] * len(Es) # adjacency matrix row
2607
+ for I in E.isogenies_prime_degree(l):
2608
+ C = I.codomain()
2609
+ j = next((k for k, F in enumerate(Es) if C.is_isomorphic(F)),
2610
+ -1) # index of curve isomorphic to codomain of isogeny
2611
+ if j >= 0:
2612
+ r[j] += 1
2613
+ else:
2614
+ Es.append(C)
2615
+ r.append(1)
2616
+
2617
+ # If the graph is undirected, non-symmetric values in the adjacency
2618
+ # matrix will result in Sage outputting different graphs depending
2619
+ # on the vertex ordering. Therefore, scale down the non-loop
2620
+ # out-edges of vertices corresponding to j-invariants 0 and 1728 so
2621
+ # that the same isogeny graphs output are isomorphic as graphs
2622
+ # regardless of the starting vertex.
2623
+ if not directed and E.j_invariant() in [0, 1728]:
2624
+ m = len(E.automorphisms()) / 2 # multiplicity of out-edges
2625
+ r = [v if k == i else v / m for k, v in enumerate(r)]
2626
+
2627
+ A.append(r)
2628
+ if label_by_j:
2629
+ s = str(E.j_invariant())
2630
+ while s in labels:
2631
+ s += "*"
2632
+ labels.append(s)
2633
+ else:
2634
+ labels.append(E._equation_string())
2635
+
2636
+ A = Matrix([r + [0] * (len(A) - len(r)) for r in A])
2637
+ if directed:
2638
+ from sage.graphs.digraph import DiGraph as GraphType
2639
+ else:
2640
+ from sage.graphs.graph import Graph as GraphType
2641
+
2642
+ G = GraphType(A, format='adjacency_matrix',
2643
+ data_structure='static_sparse')
2644
+ # inplace relabelling is necessary for static_sparse graphs
2645
+ GL = G.relabel(labels, inplace=False)
2646
+ return GL
2647
+
2648
+ def endomorphism_ring_is_commutative(self) -> bool:
2649
+ r"""
2650
+ Check whether the endomorphism ring of this elliptic curve
2651
+ *over its base field* is commutative.
2652
+
2653
+ ALGORITHM: The endomorphism ring is always commutative in
2654
+ characteristic zero. Over finite fields, it is commutative
2655
+ if and only if the Frobenius endomorphism is not in `\ZZ`.
2656
+ All elliptic curves with non-commutative endomorphism ring
2657
+ are supersingular. (The converse holds over the algebraic
2658
+ closure, but here we consider endomorphisms *over the field
2659
+ of definition*.)
2660
+
2661
+ EXAMPLES::
2662
+
2663
+ sage: EllipticCurve(QQ, [1,1]).endomorphism_ring_is_commutative()
2664
+ True
2665
+ sage: EllipticCurve(QQ, [1,0]).endomorphism_ring_is_commutative()
2666
+ True
2667
+ sage: EllipticCurve(GF(19), [1,1]).endomorphism_ring_is_commutative()
2668
+ True
2669
+ sage: EllipticCurve(GF(19^2), [1,1]).endomorphism_ring_is_commutative()
2670
+ True
2671
+ sage: EllipticCurve(GF(19), [1,0]).endomorphism_ring_is_commutative()
2672
+ True
2673
+ sage: EllipticCurve(GF(19^2), [1,0]).endomorphism_ring_is_commutative()
2674
+ False
2675
+ sage: EllipticCurve(GF(19^3), [1,0]).endomorphism_ring_is_commutative()
2676
+ True
2677
+ """
2678
+ k = self.base()
2679
+ if k.characteristic() == 0 or self.is_ordinary():
2680
+ return True
2681
+
2682
+ if not k.is_finite():
2683
+ raise NotImplementedError
2684
+
2685
+ return self.frobenius() not in ZZ
2686
+
2687
+
2688
+ def compute_model(E, name):
2689
+ r"""
2690
+ Return a model of an elliptic curve ``E`` of the type specified
2691
+ in the ``name`` parameter.
2692
+
2693
+ Used as a helper function in
2694
+ :class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny`.
2695
+
2696
+ INPUT:
2697
+
2698
+ - ``E`` -- elliptic curve
2699
+
2700
+ - ``name`` -- string; current options:
2701
+
2702
+ - ``'minimal'``: Return a global minimal model of ``E`` if it
2703
+ exists, and a semi-global minimal model otherwise.
2704
+ For this choice, ``E`` must be defined over a number field.
2705
+ See :meth:`~sage.schemes.elliptic_curves.ell_number_field.EllipticCurve_number_field.global_minimal_model`.
2706
+
2707
+ - ``'short_weierstrass'``: Return a short Weierstrass model of ``E``
2708
+ assuming one exists.
2709
+ See :meth:`~sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic.short_weierstrass_model`.
2710
+
2711
+ - ``'montgomery'``: Return an (untwisted) Montgomery model of ``E``
2712
+ assuming one exists over this field.
2713
+ See :meth:`~sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic.montgomery_model`.
2714
+
2715
+ OUTPUT: an elliptic curve of the specified type isomorphic to `E`
2716
+
2717
+ EXAMPLES::
2718
+
2719
+ sage: from sage.schemes.elliptic_curves.ell_field import compute_model
2720
+ sage: E = EllipticCurve([12/7, 405/49, 0, -81/8, 135/64])
2721
+ sage: compute_model(E, 'minimal')
2722
+ Elliptic Curve defined by y^2 = x^3 - x^2 - 7*x + 10 over Rational Field
2723
+ sage: compute_model(E, 'short_weierstrass')
2724
+ Elliptic Curve defined by y^2 = x^3 - 48114*x + 4035015 over Rational Field
2725
+ sage: compute_model(E, 'montgomery')
2726
+ Elliptic Curve defined by y^2 = x^3 + 5*x^2 + x over Rational Field
2727
+ """
2728
+ if not isinstance(E, ell_generic.EllipticCurve_generic):
2729
+ raise TypeError('not an elliptic curve')
2730
+
2731
+ if name == 'minimal':
2732
+ from sage.rings.number_field.number_field_base import NumberField
2733
+ if not isinstance(E.base_field(), NumberField):
2734
+ raise ValueError('can only compute minimal model for curves over number fields')
2735
+ return E.global_minimal_model(semi_global=True)
2736
+
2737
+ if name == 'short_weierstrass':
2738
+ return E.short_weierstrass_model()
2739
+
2740
+ if name == 'montgomery':
2741
+ return E.montgomery_model()
2742
+
2743
+ raise NotImplementedError(f'cannot compute {name} model')
2744
+
2745
+
2746
+ def point_of_order(E, n):
2747
+ r"""
2748
+ Given an elliptic curve `E` over a finite field or a number field
2749
+ and an integer `n \geq 1`, construct a point of order `n` on `E`,
2750
+ possibly defined over an extension of the base field of `E`.
2751
+
2752
+ Currently only prime powers `n` are supported.
2753
+
2754
+ EXAMPLES::
2755
+
2756
+ sage: from sage.schemes.elliptic_curves.ell_field import point_of_order
2757
+ sage: E = EllipticCurve(GF(101), [1,2,3,4,5])
2758
+ sage: P = point_of_order(E, 5); P # random
2759
+ (50*Y^5 + 48*Y^4 + 26*Y^3 + 37*Y^2 + 48*Y + 15 : 25*Y^5 + 31*Y^4 + 79*Y^3 + 39*Y^2 + 3*Y + 20 : 1)
2760
+ sage: P.base_ring()
2761
+ Finite Field in Y of size 101^6
2762
+ sage: P.order()
2763
+ 5
2764
+ sage: P.curve().a_invariants()
2765
+ (1, 2, 3, 4, 5)
2766
+
2767
+ ::
2768
+
2769
+ sage: Q = point_of_order(E, 8); Q # random
2770
+ (69*x^5 + 24*x^4 + 100*x^3 + 65*x^2 + 88*x + 97 : 65*x^5 + 28*x^4 + 5*x^3 + 45*x^2 + 42*x + 18 : 1)
2771
+ sage: 8*Q == 0 and 4*Q != 0
2772
+ True
2773
+
2774
+ ::
2775
+
2776
+ sage: from sage.schemes.elliptic_curves.ell_field import point_of_order
2777
+ sage: E = EllipticCurve(QQ, [7,7])
2778
+ sage: P = point_of_order(E, 3); P # random
2779
+ (x : -Y : 1)
2780
+ sage: P.base_ring()
2781
+ Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
2782
+ sage: P.base_ring().base_field()
2783
+ Number Field in x with defining polynomial x^4 + 14*x^2 + 28*x - 49/3
2784
+ sage: P.order()
2785
+ 3
2786
+ sage: P.curve().a_invariants()
2787
+ (0, 0, 0, 7, 7)
2788
+
2789
+ ::
2790
+
2791
+ sage: Q = point_of_order(E, 4); Q # random
2792
+ (x : Y : 1)
2793
+ sage: Q.base_ring()
2794
+ Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
2795
+ sage: Q.base_ring().base_field()
2796
+ Number Field in x with defining polynomial x^6 + 35*x^4 + 140*x^3 - 245*x^2 - 196*x - 735
2797
+ sage: Q.order()
2798
+ 4
2799
+ """
2800
+ # Construct the field extension defined by the given polynomial,
2801
+ # in such a way that the result is recognized by Sage as a field.
2802
+ def ffext(poly):
2803
+ rng = poly.parent()
2804
+ fld = rng.base_ring()
2805
+ if fld in FiniteFields():
2806
+ # Workaround: .extension() would return a PolynomialQuotientRing
2807
+ # rather than another FiniteField.
2808
+ return poly.splitting_field(rng.variable_name())
2809
+ return fld.extension(poly, rng.variable_name())
2810
+
2811
+ n = ZZ(n)
2812
+ if n == 1:
2813
+ return E(0)
2814
+
2815
+ l, m = n.is_prime_power(get_data=True)
2816
+ if not m:
2817
+ raise NotImplementedError('only prime-power orders are currently supported')
2818
+
2819
+ xpoly = E.division_polynomial(n).radical()
2820
+ xpoly //= E.division_polynomial(n // l).radical()
2821
+ if xpoly.degree() < 1: # supersingular and l == p
2822
+ raise ValueError('curve does not have any points of the specified order')
2823
+
2824
+ mu = xpoly.factor()[0][0]
2825
+ FF = ffext(mu)
2826
+ xx = mu.any_root(ring=FF, assume_squarefree=True)
2827
+
2828
+ Y = polygen(FF, 'Y')
2829
+ ypoly = E.defining_polynomial()(xx, Y, 1)
2830
+ if ypoly.is_irreducible():
2831
+ FF = ffext(ypoly)
2832
+ xx = FF(xx)
2833
+
2834
+ EE = E.change_ring(FF)
2835
+ pt = EE.lift_x(xx)
2836
+ pt.set_order(n, check=False)
2837
+ return pt