passagemath-schemes 10.6.47__cp312-cp312-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 (311) 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.6.47.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
  9. passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.47.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 +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-312-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-312-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -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 +720 -0
  40. sage/modular/abvar/homspace.py +998 -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 +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-312-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-312-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-312-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -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 +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -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 +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-312-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 +2017 -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 +1071 -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 +815 -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 +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -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 +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-312-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-312-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list_nf.py +1241 -0
  154. sage/modular/modsym/relation_matrix.py +591 -0
  155. sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
  156. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  157. sage/modular/modsym/space.py +2468 -0
  158. sage/modular/modsym/subspace.py +455 -0
  159. sage/modular/modsym/tests.py +375 -0
  160. sage/modular/multiple_zeta.py +2632 -0
  161. sage/modular/multiple_zeta_F_algebra.py +786 -0
  162. sage/modular/overconvergent/all.py +6 -0
  163. sage/modular/overconvergent/genus0.py +1878 -0
  164. sage/modular/overconvergent/hecke_series.py +1187 -0
  165. sage/modular/overconvergent/weightspace.py +778 -0
  166. sage/modular/pollack_stevens/all.py +4 -0
  167. sage/modular/pollack_stevens/distributions.py +874 -0
  168. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  169. sage/modular/pollack_stevens/manin_map.py +859 -0
  170. sage/modular/pollack_stevens/modsym.py +1593 -0
  171. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  172. sage/modular/pollack_stevens/sigma0.py +534 -0
  173. sage/modular/pollack_stevens/space.py +1076 -0
  174. sage/modular/quasimodform/all.py +3 -0
  175. sage/modular/quasimodform/element.py +845 -0
  176. sage/modular/quasimodform/ring.py +828 -0
  177. sage/modular/quatalg/all.py +3 -0
  178. sage/modular/quatalg/brandt.py +1642 -0
  179. sage/modular/ssmod/all.py +8 -0
  180. sage/modular/ssmod/ssmod.py +827 -0
  181. sage/rings/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  183. sage/rings/polynomial/binary_form_reduce.py +585 -0
  184. sage/schemes/all.py +41 -0
  185. sage/schemes/berkovich/all.py +6 -0
  186. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  187. sage/schemes/berkovich/berkovich_space.py +748 -0
  188. sage/schemes/curves/affine_curve.py +2928 -0
  189. sage/schemes/curves/all.py +33 -0
  190. sage/schemes/curves/closed_point.py +434 -0
  191. sage/schemes/curves/constructor.py +381 -0
  192. sage/schemes/curves/curve.py +542 -0
  193. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  194. sage/schemes/curves/point.py +463 -0
  195. sage/schemes/curves/projective_curve.py +3026 -0
  196. sage/schemes/curves/zariski_vankampen.py +1932 -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 +1036 -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 +1102 -0
  208. sage/schemes/elliptic_curves/constructor.py +1552 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -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 +4787 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -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 +1669 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7335 -0
  229. sage/schemes/elliptic_curves/height.py +2109 -0
  230. sage/schemes/elliptic_curves/hom.py +1406 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  232. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  233. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  234. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  235. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  236. sage/schemes/elliptic_curves/homset.py +271 -0
  237. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  238. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  239. sage/schemes/elliptic_curves/jacobian.py +237 -0
  240. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  241. sage/schemes/elliptic_curves/kraus.py +1014 -0
  242. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  243. sage/schemes/elliptic_curves/mod5family.py +105 -0
  244. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  245. sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  247. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  248. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  249. sage/schemes/elliptic_curves/padics.py +1816 -0
  250. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  251. sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  253. sage/schemes/elliptic_curves/saturation.py +715 -0
  254. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  255. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  256. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  257. sage/schemes/hyperelliptic_curves/all.py +6 -0
  258. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  259. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  264. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  265. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  270. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  271. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  272. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  273. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  274. sage/schemes/jacobians/all.py +2 -0
  275. sage/schemes/overview.py +161 -0
  276. sage/schemes/plane_conics/all.py +22 -0
  277. sage/schemes/plane_conics/con_field.py +1296 -0
  278. sage/schemes/plane_conics/con_finite_field.py +158 -0
  279. sage/schemes/plane_conics/con_number_field.py +456 -0
  280. sage/schemes/plane_conics/con_rational_field.py +406 -0
  281. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  282. sage/schemes/plane_conics/constructor.py +249 -0
  283. sage/schemes/plane_quartics/all.py +2 -0
  284. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  285. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  286. sage/schemes/riemann_surfaces/all.py +1 -0
  287. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  288. sage_wheels/share/cremona/cremona_mini.db +0 -0
  289. sage_wheels/share/ellcurves/rank0 +30427 -0
  290. sage_wheels/share/ellcurves/rank1 +31871 -0
  291. sage_wheels/share/ellcurves/rank10 +6 -0
  292. sage_wheels/share/ellcurves/rank11 +6 -0
  293. sage_wheels/share/ellcurves/rank12 +1 -0
  294. sage_wheels/share/ellcurves/rank14 +1 -0
  295. sage_wheels/share/ellcurves/rank15 +1 -0
  296. sage_wheels/share/ellcurves/rank17 +1 -0
  297. sage_wheels/share/ellcurves/rank19 +1 -0
  298. sage_wheels/share/ellcurves/rank2 +2388 -0
  299. sage_wheels/share/ellcurves/rank20 +1 -0
  300. sage_wheels/share/ellcurves/rank21 +1 -0
  301. sage_wheels/share/ellcurves/rank22 +1 -0
  302. sage_wheels/share/ellcurves/rank23 +1 -0
  303. sage_wheels/share/ellcurves/rank24 +1 -0
  304. sage_wheels/share/ellcurves/rank28 +1 -0
  305. sage_wheels/share/ellcurves/rank3 +836 -0
  306. sage_wheels/share/ellcurves/rank4 +10 -0
  307. sage_wheels/share/ellcurves/rank5 +5 -0
  308. sage_wheels/share/ellcurves/rank6 +5 -0
  309. sage_wheels/share/ellcurves/rank7 +5 -0
  310. sage_wheels/share/ellcurves/rank8 +6 -0
  311. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,3760 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Elliptic curves over a general ring
4
+
5
+ Sage defines an elliptic curve over a ring `R` as a *Weierstrass Model* with
6
+ five coefficients `[a_1,a_2,a_3,a_4,a_6]` in `R` given by
7
+
8
+ .. MATH::
9
+
10
+ y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.
11
+
12
+ Note that the (usual) scheme-theoretic definition of an elliptic curve over `R`
13
+ would require the discriminant to be a unit in `R`; Sage only imposes that the
14
+ discriminant is nonzero. Also note that in Magma, "Weierstrass Model" refers
15
+ to a model with `a_1=a_2=a_3=0`, which is called *Short Weierstrass Model* in
16
+ Sage; these do not always exist in characteristics 2 and 3.
17
+
18
+ EXAMPLES:
19
+
20
+ We construct an elliptic curve over an elaborate base ring::
21
+
22
+ sage: p, a, b = 97, 1, 3
23
+ sage: R.<u> = GF(p)[]
24
+ sage: S.<v> = R[]
25
+ sage: T = S.fraction_field()
26
+ sage: E = EllipticCurve(T, [a, b]); E
27
+ Elliptic Curve defined by y^2 = x^3 + x + 3 over Fraction Field of Univariate
28
+ Polynomial Ring in v over Univariate Polynomial Ring in u over Finite Field of size 97
29
+ sage: latex(E)
30
+ y^2 = x^{3} + x + 3
31
+
32
+ AUTHORS:
33
+
34
+ - William Stein (2005): Initial version
35
+
36
+ - Robert Bradshaw et al....
37
+
38
+ - John Cremona (2008-01): isomorphisms, automorphisms and twists in all characteristics
39
+
40
+ - Julian Rueth (2014-04-11): improved caching
41
+
42
+ - Lorenz Panny (2022-04-14): added ``.montgomery_model()``
43
+ """
44
+
45
+ # ****************************************************************************
46
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
47
+ # Copyright (C) 2014 Julian Rueth <julian.rueth@fsfe.org>
48
+ #
49
+ # This program is free software: you can redistribute it and/or modify
50
+ # it under the terms of the GNU General Public License as published by
51
+ # the Free Software Foundation, either version 2 of the License, or
52
+ # (at your option) any later version.
53
+ # https://www.gnu.org/licenses/
54
+ # ****************************************************************************
55
+
56
+ import math
57
+ from sage.arith.misc import valuation
58
+
59
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
60
+ from sage.rings.polynomial.polynomial_ring import polygen, polygens
61
+ from sage.rings.polynomial.polynomial_element import polynomial_is_variable
62
+ from sage.rings.polynomial.polynomial_quotient_ring_element import PolynomialQuotientRingElement
63
+ from sage.rings.finite_rings.finite_field_base import FiniteField
64
+ import sage.groups.additive_abelian.additive_abelian_group as groups
65
+ import sage.groups.generic as generic
66
+
67
+ from sage.arith.functions import lcm
68
+ from sage.rings.integer import Integer
69
+ from sage.rings.rational import Rational
70
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
71
+ from sage.rings.rational_field import RationalField
72
+ from sage.rings.real_mpfr import RealField
73
+ from sage.misc.cachefunc import cached_method
74
+ from sage.misc.fast_methods import WithEqualityById
75
+
76
+ # Schemes
77
+ import sage.schemes.projective.projective_space as projective_space
78
+ from sage.schemes.projective.projective_homset import SchemeHomset_points_abelian_variety_field
79
+ import sage.schemes.curves.projective_curve as plane_curve
80
+
81
+ from . import ell_point
82
+ from . import ell_torsion
83
+ from . import constructor
84
+ from . import formal_group
85
+ from . import weierstrass_morphism as wm
86
+
87
+ sqrt = math.sqrt
88
+ exp = math.exp
89
+
90
+
91
+ def is_EllipticCurve(x):
92
+ r"""
93
+ Utility function to test if ``x`` is an instance of an Elliptic Curve class.
94
+
95
+ EXAMPLES::
96
+
97
+ sage: from sage.schemes.elliptic_curves.ell_generic import is_EllipticCurve
98
+ sage: E = EllipticCurve([1,2,3/4,7,19])
99
+ sage: is_EllipticCurve(E)
100
+ doctest:warning...
101
+ DeprecationWarning: The function is_EllipticCurve is deprecated; use 'isinstance(..., EllipticCurve_generic)' instead.
102
+ See https://github.com/sagemath/sage/issues/38022 for details.
103
+ True
104
+ sage: is_EllipticCurve(0)
105
+ False
106
+ """
107
+ from sage.misc.superseded import deprecation
108
+ deprecation(38022, "The function is_EllipticCurve is deprecated; use 'isinstance(..., EllipticCurve_generic)' instead.")
109
+ return isinstance(x, EllipticCurve_generic)
110
+
111
+
112
+ class EllipticCurve_generic(WithEqualityById, plane_curve.ProjectivePlaneCurve):
113
+ r"""
114
+ Elliptic curve over a generic base ring.
115
+
116
+ EXAMPLES::
117
+
118
+ sage: E = EllipticCurve([1,2,3/4,7,19]); E
119
+ Elliptic Curve defined by y^2 + x*y + 3/4*y = x^3 + 2*x^2 + 7*x + 19 over Rational Field
120
+ sage: loads(E.dumps()) == E
121
+ True
122
+ sage: E = EllipticCurve([1,3])
123
+ sage: P = E([-1,1,1])
124
+ sage: -5*P
125
+ (179051/80089 : -91814227/22665187 : 1)
126
+ """
127
+ def __init__(self, K, ainvs, category=None):
128
+ r"""
129
+ Construct an elliptic curve from Weierstrass `a`-coefficients.
130
+
131
+ INPUT:
132
+
133
+ - ``K`` -- a ring
134
+
135
+ - ``ainvs`` -- list or tuple `[a_1, a_2, a_3, a_4, a_6]` of
136
+ Weierstrass coefficients
137
+
138
+ .. NOTE::
139
+
140
+ This class should not be called directly; use
141
+ :class:`sage.constructor.EllipticCurve` to construct
142
+ elliptic curves.
143
+
144
+ EXAMPLES::
145
+
146
+ sage: E = EllipticCurve([1,2,3,4,5]); E
147
+ Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5
148
+ over Rational Field
149
+ sage: E = EllipticCurve(GF(7), [1,2,3,4,5]); E
150
+ Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5
151
+ over Finite Field of size 7
152
+
153
+ Constructor from `[a_4,a_6]` sets `a_1=a_2=a_3=0`::
154
+
155
+ sage: EllipticCurve([4,5]).ainvs()
156
+ (0, 0, 0, 4, 5)
157
+
158
+ The base ring need not be a field::
159
+
160
+ sage: EllipticCurve(IntegerModRing(91), [1,2,3,4,5])
161
+ Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5
162
+ over Ring of integers modulo 91
163
+ """
164
+ self.__base_ring = K
165
+ self.__ainvs = tuple(K(a) for a in ainvs)
166
+ if self.discriminant() == 0:
167
+ raise ArithmeticError(self._equation_string() + " defines a singular curve")
168
+ PP = projective_space.ProjectiveSpace(2, K, names='xyz')
169
+ x, y, z = PP.coordinate_ring().gens()
170
+ a1, a2, a3, a4, a6 = ainvs
171
+ f = y**2*z + (a1*x + a3*z)*y*z \
172
+ - (x**3 + a2*x**2*z + a4*x*z**2 + a6*z**3)
173
+ plane_curve.ProjectivePlaneCurve.__init__(self, PP, f, category=category)
174
+
175
+ self.__divpolys = ({}, {}, {})
176
+
177
+ _point = ell_point.EllipticCurvePoint
178
+
179
+ def assume_base_ring_is_field(self, flag=True):
180
+ r"""
181
+ Set a flag to pretend that this elliptic curve is defined over a
182
+ field while doing arithmetic, which is useful in some algorithms.
183
+
184
+
185
+ .. WARNING::
186
+
187
+ The flag affects all points created while the flag is set. Note
188
+ that elliptic curves are unique parents, hence setting this flag
189
+ may break seemingly unrelated parts of Sage.
190
+
191
+ .. NOTE::
192
+
193
+ This method is a **hack** provided for educational purposes.
194
+
195
+ EXAMPLES::
196
+
197
+ sage: E = EllipticCurve(Zmod(35), [1,1])
198
+ sage: P = E(-5, 9)
199
+ sage: 4*P
200
+ (23 : 26 : 1)
201
+ sage: 9*P
202
+ (10 : 11 : 5)
203
+ sage: E.assume_base_ring_is_field()
204
+ sage: P = E(-5, 9)
205
+ sage: 4*P
206
+ (23 : 26 : 1)
207
+ sage: 9*P
208
+ Traceback (most recent call last):
209
+ ...
210
+ ZeroDivisionError: Inverse of 5 does not exist (characteristic = 35 = 5*7)
211
+ """
212
+ if flag:
213
+ if self.__base_ring.is_finite():
214
+ self._point = ell_point.EllipticCurvePoint_finite_field
215
+ else:
216
+ self._point = ell_point.EllipticCurvePoint_field
217
+ else:
218
+ self._point = ell_point.EllipticCurvePoint
219
+
220
+ def _defining_params_(self):
221
+ r"""
222
+ Internal function. Return a tuple of the base ring of this
223
+ elliptic curve and its `a`-invariants, from which it can be
224
+ reconstructed.
225
+
226
+ EXAMPLES::
227
+
228
+ sage: E = EllipticCurve(QQ,[1,1])
229
+ sage: E._defining_params_()
230
+ (Rational Field, [0, 0, 0, 1, 1])
231
+ sage: EllipticCurve(*E._defining_params_()) == E
232
+ True
233
+ """
234
+ return (self.__base_ring, list(self.__ainvs))
235
+
236
+ def _equation_string(self):
237
+ """
238
+ String representation of the equation of elliptic curve.
239
+
240
+ EXAMPLES::
241
+
242
+ sage: E = EllipticCurve([1,2,3,4,5]); E._equation_string()
243
+ 'y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5'
244
+ """
245
+ b = self.ainvs()
246
+ a = [z._coeff_repr() for z in b]
247
+ s = "y^2"
248
+ if a[0] == "-1":
249
+ s += " - x*y"
250
+ elif a[0] == '1':
251
+ s += " + x*y"
252
+ elif b[0]:
253
+ s += " + %s*x*y" % a[0]
254
+ if a[2] == "-1":
255
+ s += " - y"
256
+ elif a[2] == '1':
257
+ s += " + y"
258
+ elif b[2]:
259
+ s += " + %s*y" % a[2]
260
+ s += " = x^3"
261
+ if a[1] == "-1":
262
+ s += " - x^2"
263
+ elif a[1] == '1':
264
+ s += " + x^2"
265
+ elif b[1]:
266
+ s += " + %s*x^2" % a[1]
267
+ if a[3] == "-1":
268
+ s += " - x"
269
+ elif a[3] == '1':
270
+ s += " + x"
271
+ elif b[3]:
272
+ s += " + %s*x" % a[3]
273
+ if a[4] == '-1':
274
+ s += " - 1"
275
+ elif a[4] == '1':
276
+ s += " + 1"
277
+ elif b[4]:
278
+ s += " + %s" % a[4]
279
+ return s.replace("+ -","- ")
280
+
281
+ def _repr_(self):
282
+ """
283
+ String representation of elliptic curve.
284
+
285
+ EXAMPLES::
286
+
287
+ sage: E = EllipticCurve([1,2,3,4,5]); E._repr_()
288
+ 'Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field'
289
+
290
+ ::
291
+
292
+ sage: R.<x> = QQ['x']
293
+ sage: K.<a> = NumberField(x^3 - 17) # needs sage.rings.number_field
294
+ sage: EllipticCurve([a^2 - 3, -2/3*a + 3]) # needs sage.rings.number_field
295
+ Elliptic Curve defined by y^2 = x^3 + (a^2-3)*x + (-2/3*a+3)
296
+ over Number Field in a
297
+ with defining polynomial x^3 - 17
298
+ """
299
+ s = "Elliptic Curve defined by "
300
+ s += self._equation_string()
301
+ s += " over %s" % self.base_ring()
302
+ return s
303
+
304
+ def _latex_(self):
305
+ """
306
+ Internal function. Return a latex string for this elliptic curve.
307
+
308
+ Users will normally use :func:`latex` instead.
309
+
310
+ EXAMPLES::
311
+
312
+ sage: E = EllipticCurve(QQ, [1,1])
313
+ sage: E._latex_()
314
+ 'y^2 = x^{3} + x + 1 '
315
+
316
+ sage: E = EllipticCurve(QQ, [1,2,3,4,5])
317
+ sage: E._latex_()
318
+ 'y^2 + x y + 3 y = x^{3} + 2 x^{2} + 4 x + 5 '
319
+
320
+ Check that :issue:`12524` is solved::
321
+
322
+ sage: x = polygen(ZZ, 'x')
323
+ sage: K.<phi> = NumberField(x^2 - x - 1) # needs sage.rings.number_field
324
+ sage: E = EllipticCurve([0, 0, phi, 27*phi - 43, -80*phi + 128]) # needs sage.rings.number_field
325
+ sage: E._latex_() # needs sage.rings.number_field
326
+ 'y^2 + \\phi y = x^{3} + \\left(27 \\phi - 43\\right) x - 80 \\phi + 128 '
327
+ """
328
+ from sage.rings.polynomial.polynomial_ring import polygen
329
+ a = self.ainvs()
330
+ x, y = polygen(self.base_ring(), 'x, y')
331
+ s = "y^2"
332
+ if a[0] or a[2]:
333
+ s += " + " + (a[0]*x*y + a[2]*y)._latex_()
334
+ s += " = "
335
+ s += (x**3 + a[1]*x**2 + a[3]*x + a[4])._latex_()
336
+ s += " "
337
+ s = s.replace("+ -","- ")
338
+ return s
339
+
340
+ def _pari_init_(self):
341
+ """
342
+ Internal function. Return a string to initialize this elliptic
343
+ curve in the PARI system.
344
+
345
+ EXAMPLES::
346
+
347
+ sage: E = EllipticCurve(QQ,[1,1])
348
+ sage: E._pari_init_()
349
+ 'ellinit([0/1,0/1,0/1,1/1,1/1])'
350
+ """
351
+ return 'ellinit([%s])' % (','.join(x._pari_init_()
352
+ for x in self.ainvs()))
353
+
354
+ def _magma_init_(self, magma):
355
+ """
356
+ Internal function. Return a string to initialize this elliptic
357
+ curve in the Magma subsystem.
358
+
359
+ EXAMPLES::
360
+
361
+ sage: # optional - magma
362
+ sage: E = EllipticCurve(QQ, [1,1])
363
+ sage: E._magma_init_(magma)
364
+ 'EllipticCurve([_sage_ref...|0/1,0/1,0/1,1/1,1/1])'
365
+ sage: E = EllipticCurve(GF(41), [2,5])
366
+ sage: E._magma_init_(magma)
367
+ 'EllipticCurve([_sage_ref...|GF(41)!0,GF(41)!0,GF(41)!0,GF(41)!2,GF(41)!5])'
368
+ sage: E = EllipticCurve(GF(25,'a'), [0,0,1,4,0]) # needs sage.rings.finite_rings
369
+ sage: magma(E) # needs sage.rings.finite_rings
370
+ Elliptic Curve defined by y^2 + y = x^3 + 4*x over GF(5^2)
371
+ sage: magma(EllipticCurve([1/2,2/3,-4/5,6/7,8/9]))
372
+ Elliptic Curve defined by y^2 + 1/2*x*y - 4/5*y = x^3 + 2/3*x^2 + 6/7*x + 8/9 over Rational Field
373
+ sage: R.<x> = Frac(QQ['x'])
374
+ sage: magma(EllipticCurve([x, 1 + x]))
375
+ Elliptic Curve defined by y^2 = x^3 + x*x + (x + 1)
376
+ over Univariate rational function field over Rational Field
377
+ """
378
+ kmn = magma(self.base_ring())._ref()
379
+ return 'EllipticCurve([%s|%s])' % (kmn,','.join(x._magma_init_(magma)
380
+ for x in self.ainvs()))
381
+
382
+ def _symbolic_(self, SR):
383
+ r"""
384
+ Many elliptic curves can be converted into a symbolic expression
385
+ using the ``symbolic_expression`` command.
386
+
387
+ EXAMPLES: We find a torsion point on 11a.
388
+
389
+ ::
390
+
391
+ sage: E = EllipticCurve('11a')
392
+ sage: E._symbolic_(SR) # needs sage.symbolic
393
+ y^2 + y == x^3 - x^2 - 10*x - 20
394
+ sage: E.torsion_subgroup().gens() # needs sage.symbolic
395
+ ((5 : 5 : 1),)
396
+
397
+ We find the corresponding symbolic equality::
398
+
399
+ sage: eqn = symbolic_expression(E); eqn # needs sage.symbolic
400
+ y^2 + y == x^3 - x^2 - 10*x - 20
401
+
402
+ We verify that the given point is on the curve::
403
+
404
+ sage: eqn(x=5, y=5) # needs sage.symbolic
405
+ 30 == 30
406
+ sage: bool(eqn(x=5, y=5)) # needs sage.symbolic
407
+ True
408
+
409
+ We create a single expression::
410
+
411
+ sage: F = eqn.lhs() - eqn.rhs(); F # needs sage.symbolic
412
+ -x^3 + x^2 + y^2 + 10*x + y + 20
413
+ sage: y = var('y') # needs sage.symbolic
414
+ sage: F.solve(y) # needs sage.symbolic
415
+ [y == -1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2,
416
+ y == 1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2]
417
+
418
+ You can also solve for x in terms of y, but the result is
419
+ horrendous. Continuing with the above example, we can explicitly
420
+ find points over random fields by substituting in values for x::
421
+
422
+ sage: # needs sage.symbolic
423
+ sage: v = F.solve(y)[0].rhs(); v
424
+ -1/2*sqrt(4*x^3 - 4*x^2 - 40*x - 79) - 1/2
425
+ sage: v = v.function(x)
426
+ sage: v(3)
427
+ -1/2*sqrt(-127) - 1/2
428
+ sage: v(7)
429
+ -1/2*sqrt(817) - 1/2
430
+ sage: v(-7)
431
+ -1/2*sqrt(-1367) - 1/2
432
+ sage: v(sqrt(2))
433
+ -1/2*sqrt(-32*sqrt(2) - 87) - 1/2
434
+
435
+ We can even do arithmetic with them, as follows::
436
+
437
+ sage: # needs sage.symbolic
438
+ sage: E2 = E.change_ring(SR); E2
439
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20)
440
+ over Symbolic Ring
441
+ sage: P = E2.point((3, v(3), 1), check=False) # the check=False option doesn't verify that y^2 = f(x)
442
+ sage: P
443
+ (3 : -1/2*sqrt(-127) - 1/2 : 1)
444
+ sage: P + P
445
+ (-756/127 : 41143/32258*sqrt(-127) - 1/2 : 1)
446
+
447
+ We can even throw in a transcendental::
448
+
449
+ sage: w = E2.point((pi,v(pi),1), check=False); w # needs sage.symbolic
450
+ (pi : -1/2*sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1/2 : 1)
451
+ sage: x, y, z = w; ((y^2 + y) - (x^3 - x^2 - 10*x - 20)).expand() # needs sage.symbolic
452
+ 0
453
+
454
+ sage: 2*w # needs sage.symbolic
455
+ (-2*pi - (2*pi - 3*pi^2 + 10)^2/(40*pi - 4*pi^3 + 4*pi^2 + 79) + 1 : (3*pi + (2*pi - 3*pi^2 + 10)^2/(40*pi - 4*pi^3 + 4*pi^2 + 79) - 1)*(2*pi - 3*pi^2 + 10)/sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) + 1/2*sqrt(-40*pi + 4*pi^3 - 4*pi^2 - 79) - 1/2 : 1)
456
+
457
+ sage: x, y, z = 2*w; temp = ((y^2 + y) - (x^3 - x^2 - 10*x - 20)) # needs sage.symbolic
458
+
459
+ This is a point on the curve::
460
+
461
+ sage: bool(temp == 0) # needs sage.symbolic
462
+ True
463
+ """
464
+ a = [SR(x) for x in self.a_invariants()]
465
+ x, y = SR.var('x, y')
466
+ return y**2 + a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]
467
+
468
+ def __contains__(self, P):
469
+ """
470
+ Return ``True`` if and only if P is a point on the elliptic curve.
471
+
472
+ P just has to be something that can be coerced to a point.
473
+
474
+ EXAMPLES::
475
+
476
+ sage: E = EllipticCurve([0, 0, 1, -1, 0])
477
+ sage: (0,0) in E
478
+ True
479
+ sage: (1,3) in E
480
+ False
481
+ sage: E = EllipticCurve([GF(7)(0), 1])
482
+ sage: [0,0] in E
483
+ False
484
+ sage: [0,8] in E
485
+ True
486
+ sage: P = E(0,8)
487
+ sage: P
488
+ (0 : 1 : 1)
489
+ sage: P in E
490
+ True
491
+ """
492
+ if not isinstance(P, ell_point.EllipticCurvePoint):
493
+ try:
494
+ P = self(P)
495
+ except TypeError:
496
+ return False
497
+ return P.curve() == self
498
+
499
+ def __call__(self, *args, **kwds):
500
+ r"""
501
+ EXAMPLES::
502
+
503
+ sage: E = EllipticCurve([0, 0, 1, -1, 0])
504
+
505
+ The point at infinity, which is the 0 element of the group::
506
+
507
+ sage: E(0)
508
+ (0 : 1 : 0)
509
+
510
+ The origin is a point on our curve::
511
+
512
+ sage: P = E([0,0])
513
+ sage: P
514
+ (0 : 0 : 1)
515
+
516
+ The curve associated to a point::
517
+
518
+ sage: P.curve()
519
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
520
+
521
+ Points can be specified by given a 2-tuple or 3-tuple::
522
+
523
+ sage: E([0,0])
524
+ (0 : 0 : 1)
525
+ sage: E([0,1,0])
526
+ (0 : 1 : 0)
527
+
528
+ Over a field, points are normalized so the 3rd entry (if nonzero)
529
+ is 1::
530
+
531
+ sage: E(105, -69, 125)
532
+ (21/25 : -69/125 : 1)
533
+
534
+ We create points on an elliptic curve over a prime finite field::
535
+
536
+ sage: E = EllipticCurve([GF(7)(0), 1])
537
+ sage: E([2,3])
538
+ (2 : 3 : 1)
539
+ sage: E([0,0])
540
+ Traceback (most recent call last):
541
+ ...
542
+ TypeError: Coordinates [0, 0, 1] do not define a point
543
+ on Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
544
+
545
+ We create a point on an elliptic curve over a number field::
546
+
547
+ sage: # needs sage.rings.number_field
548
+ sage: x = polygen(RationalField())
549
+ sage: K = NumberField(x**3 + x + 1, 'a'); a = K.gen()
550
+ sage: E = EllipticCurve([a, a])
551
+ sage: E
552
+ Elliptic Curve defined by y^2 = x^3 + a*x + a
553
+ over Number Field in a with defining polynomial x^3 + x + 1
554
+ sage: E = EllipticCurve([K(1), 1])
555
+ sage: E
556
+ Elliptic Curve defined by y^2 = x^3 + x + 1
557
+ over Number Field in a with defining polynomial x^3 + x + 1
558
+ sage: P = E([a,0,1])
559
+ sage: P
560
+ (a : 0 : 1)
561
+ sage: P + P
562
+ (0 : 1 : 0)
563
+
564
+ Another example involving `p`-adics::
565
+
566
+ sage: E = EllipticCurve('37a1')
567
+ sage: P = E([0,0]); P
568
+ (0 : 0 : 1)
569
+ sage: R = pAdicField(3, 20) # needs sage.rings.padics
570
+ sage: Ep = E.base_extend(R); Ep # needs sage.rings.padics
571
+ Elliptic Curve defined by
572
+ y^2 + (1+O(3^20))*y = x^3 + (2+2*3+2*3^2+2*3^3+2*3^4+2*3^5+2*3^6+2*3^7+2*3^8+2*3^9+2*3^10+2*3^11+2*3^12+2*3^13+2*3^14+2*3^15+2*3^16+2*3^17+2*3^18+2*3^19+O(3^20))*x
573
+ over 3-adic Field with capped relative precision 20
574
+ sage: Ep(P) # needs sage.rings.padics
575
+ (0 : 0 : 1 + O(3^20))
576
+
577
+ Constructing points from the torsion subgroup (which is an abstract
578
+ abelian group)::
579
+
580
+ sage: E = EllipticCurve('14a1')
581
+ sage: T = E.torsion_subgroup()
582
+ sage: [E(t) for t in T]
583
+ [(0 : 1 : 0),
584
+ (9 : 23 : 1),
585
+ (2 : 2 : 1),
586
+ (1 : -1 : 1),
587
+ (2 : -5 : 1),
588
+ (9 : -33 : 1)]
589
+
590
+ ::
591
+
592
+ sage: E = EllipticCurve([0,0,0,-49,0])
593
+ sage: T = E.torsion_subgroup()
594
+ sage: [E(t) for t in T]
595
+ [(0 : 1 : 0), (0 : 0 : 1), (-7 : 0 : 1), (7 : 0 : 1)]
596
+
597
+ ::
598
+
599
+ sage: E = EllipticCurve('37a1')
600
+ sage: T = E.torsion_subgroup()
601
+ sage: [E(t) for t in T]
602
+ [(0 : 1 : 0)]
603
+ """
604
+ if len(args) == 1 and args[0] == 0:
605
+ R = self.base_ring()
606
+ return self.point([R(0),R(1),R(0)], check=False)
607
+ P = args[0]
608
+ if isinstance(P, groups.AdditiveAbelianGroupElement) and isinstance(P.parent(),ell_torsion.EllipticCurveTorsionSubgroup):
609
+ return self(P.element())
610
+ if isinstance(args[0], ell_point.EllipticCurvePoint):
611
+ if P.curve() is self:
612
+ return P
613
+ # check if denominator of the point contains a factor of the
614
+ # characteristic of the base ring. if so, coerce the point to
615
+ # infinity.
616
+ characteristic = self.base_ring().characteristic()
617
+ if characteristic != 0 and isinstance(args[0][0], Rational) and isinstance(args[0][1], Rational):
618
+ if characteristic.divides(args[0][0].denominator()) or characteristic.divides(args[0][1].denominator()):
619
+ return self._reduce_point(args[0], characteristic)
620
+ args = tuple(args[0])
621
+
622
+ return plane_curve.ProjectivePlaneCurve.__call__(self, *args, **kwds)
623
+
624
+ def _reduce_point(self, R, p):
625
+ r"""
626
+ Reduces a point R on an elliptic curve to the corresponding point on
627
+ the elliptic curve reduced modulo p.
628
+
629
+ Used to coerce points between
630
+ curves when p is a factor of the denominator of one of the
631
+ coordinates.
632
+
633
+ This functionality is used internally in the ``call`` method for
634
+ elliptic curves.
635
+
636
+ INPUT:
637
+
638
+ - ``R`` -- a point on an elliptic curve
639
+ - ``p`` -- a prime
640
+
641
+ OUTPUT: S; the corresponding point of the elliptic curve containing
642
+ R, but reduced modulo p
643
+
644
+ EXAMPLES:
645
+
646
+ Suppose we have a point with large height on a rational elliptic curve
647
+ whose denominator contains a factor of 11::
648
+
649
+ sage: E = EllipticCurve([1,-1,0,94,9])
650
+ sage: R = E([0,3]) + 5*E([8,31])
651
+ sage: factor(R.x().denominator())
652
+ 2^2 * 11^2 * 1457253032371^2
653
+
654
+ Since 11 is a factor of the denominator, this point corresponds to the
655
+ point at infinity on the same curve but reduced modulo 11. The reduce
656
+ function tells us this::
657
+
658
+ sage: E11 = E.change_ring(GF(11))
659
+ sage: S = E11._reduce_point(R, 11)
660
+ sage: E11(S)
661
+ (0 : 1 : 0)
662
+
663
+ The 0 point reduces as expected::
664
+
665
+ sage: E11._reduce_point(E(0), 11)
666
+ (0 : 1 : 0)
667
+
668
+ Note that one need not explicitly call
669
+ \code{EllipticCurve._reduce_point}
670
+ """
671
+ if R.is_zero():
672
+ return R.curve().change_ring(GF(p))(0)
673
+ x, y = R.xy()
674
+ d = lcm(x.denominator(), y.denominator())
675
+ return R.curve().change_ring(GF(p))([x*d, y*d, d])
676
+
677
+ def is_x_coord(self, x):
678
+ r"""
679
+ Return ``True`` if ``x`` is the `x`-coordinate of a point on this curve.
680
+
681
+ .. NOTE::
682
+
683
+ See also :meth:`lift_x` to find the point(s) with a given
684
+ `x`-coordinate. This function may be useful in cases where
685
+ testing an element of the base field for being a square is
686
+ faster than finding its square root.
687
+
688
+ EXAMPLES::
689
+
690
+ sage: E = EllipticCurve('37a'); E
691
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
692
+ sage: E.is_x_coord(1)
693
+ True
694
+ sage: E.is_x_coord(2)
695
+ True
696
+
697
+ There are no rational points with x-coordinate 3::
698
+
699
+ sage: E.is_x_coord(3)
700
+ False
701
+
702
+ However, there are such points in `E(\RR)`::
703
+
704
+ sage: E.change_ring(RR).is_x_coord(3)
705
+ True
706
+
707
+ And of course it always works in `E(\CC)`::
708
+
709
+ sage: E.change_ring(RR).is_x_coord(-3)
710
+ False
711
+ sage: E.change_ring(CC).is_x_coord(-3)
712
+ True
713
+
714
+ AUTHORS:
715
+
716
+ - John Cremona (2008-08-07): adapted from :meth:`lift_x`
717
+
718
+ TESTS::
719
+
720
+ sage: E = EllipticCurve('5077a1')
721
+ sage: [x for x in srange(-10,10) if E.is_x_coord (x)]
722
+ [-3, -2, -1, 0, 1, 2, 3, 4, 8]
723
+
724
+ ::
725
+
726
+ sage: F = GF(32,'a') # needs sage.rings.finite_rings
727
+ sage: E = EllipticCurve(F,[1,0,0,0,1]) # needs sage.rings.finite_rings
728
+ sage: set(P[0] for P in E.points() if P!=E(0)) == set(x for x in F if E.is_x_coord(x)) # needs sage.rings.finite_rings
729
+ True
730
+ """
731
+ K = self.base_ring()
732
+ try:
733
+ x = K(x)
734
+ except TypeError:
735
+ raise TypeError('x must be coercible into the base ring of the curve')
736
+ a1, a2, a3, a4, a6 = self.ainvs()
737
+ fx = ((x + a2) * x + a4) * x + a6
738
+ if a1.is_zero() and a3.is_zero():
739
+ return fx.is_square()
740
+ b = (a1*x + a3)
741
+ if K.characteristic() == 2:
742
+ R = PolynomialRing(K, 'y')
743
+ F = R([-fx,b,1])
744
+ return bool(F.roots())
745
+ D = b*b + 4*fx
746
+ return D.is_square()
747
+
748
+ def lift_x(self, x, all=False, extend=False):
749
+ r"""
750
+ Return one or all points with given `x`-coordinate.
751
+
752
+ This method is deterministic: It returns the same data each
753
+ time when called again with the same `x`.
754
+
755
+ INPUT:
756
+
757
+ - ``x`` -- an element of the base ring of the curve, or of an extension
758
+
759
+ - ``all`` -- boolean (default: ``False``); if ``True``, return a
760
+ (possibly empty) list of all points; if ``False``, return just one
761
+ point, or raise a :exc:`ValueError` if there are none.
762
+
763
+ - ``extend`` -- boolean (default: ``False``);
764
+
765
+ - if ``False``, extend the base if necessary and possible to
766
+ include `x`, and only return point(s) defined over this
767
+ ring, or raise an error when there are none with this
768
+ `x`-coordinate;
769
+
770
+ - If ``True``, the base ring will be extended if necessary
771
+ to contain the `y`-coordinates of the point(s) with this
772
+ `x`-coordinate, in addition to a possible base change to
773
+ include `x`.
774
+
775
+ OUTPUT:
776
+
777
+ A point or list of up to 2 points on this curve, or a
778
+ base-change of this curve to a larger ring.
779
+
780
+ .. SEEALSO::
781
+
782
+ :meth:`is_x_coord`
783
+
784
+ EXAMPLES::
785
+
786
+ sage: E = EllipticCurve('37a'); E
787
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
788
+ sage: E.lift_x(1)
789
+ (1 : -1 : 1)
790
+ sage: E.lift_x(2)
791
+ (2 : -3 : 1)
792
+ sage: E.lift_x(1/4, all=True)
793
+ [(1/4 : -5/8 : 1), (1/4 : -3/8 : 1)]
794
+
795
+ There are no rational points with `x`-coordinate 3::
796
+
797
+ sage: E.lift_x(3)
798
+ Traceback (most recent call last):
799
+ ...
800
+ ValueError: No point with x-coordinate 3
801
+ on Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
802
+
803
+ We can use the ``extend`` parameter to make the necessary
804
+ quadratic extension. Note that in such cases the returned
805
+ point is a point on a new curve object, the result of changing
806
+ the base ring to the parent of `x`::
807
+
808
+ sage: P = E.lift_x(3, extend=True); P # needs sage.rings.number_field
809
+ (3 : -y - 1 : 1)
810
+ sage: P.curve() # needs sage.rings.number_field
811
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x
812
+ over Number Field in y with defining polynomial y^2 + y - 24
813
+
814
+ Or we can extend scalars. There are two such points in `E(\RR)`::
815
+
816
+ sage: E.change_ring(RR).lift_x(3, all=True)
817
+ [(3.00000000000000 : -5.42442890089805 : 1.00000000000000),
818
+ (3.00000000000000 : 4.42442890089805 : 1.00000000000000)]
819
+
820
+ And of course it always works in `E(\CC)`::
821
+
822
+ sage: E.change_ring(RR).lift_x(.5, all=True)
823
+ []
824
+ sage: E.change_ring(CC).lift_x(.5)
825
+ (0.500000000000000 : -0.500000000000000 - 0.353553390593274*I : 1.00000000000000)
826
+
827
+ In this example we start with a curve defined over `\QQ`
828
+ which has no rational points with `x=0`, but using
829
+ ``extend = True`` we can construct such a point over a quadratic
830
+ field::
831
+
832
+ sage: E = EllipticCurve([0,0,0,0,2]); E
833
+ Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field
834
+ sage: P = E.lift_x(0, extend=True); P # needs sage.rings.number_field
835
+ (0 : -y : 1)
836
+ sage: P.curve() # needs sage.rings.number_field
837
+ Elliptic Curve defined by y^2 = x^3 + 2
838
+ over Number Field in y with defining polynomial y^2 - 2
839
+
840
+ We can perform these operations over finite fields too::
841
+
842
+ sage: E = EllipticCurve('37a').change_ring(GF(17)); E
843
+ Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
844
+ sage: E.lift_x(7)
845
+ (7 : 5 : 1)
846
+ sage: E.lift_x(3)
847
+ Traceback (most recent call last):
848
+ ...
849
+ ValueError: No point with x-coordinate 3 on
850
+ Elliptic Curve defined by y^2 + y = x^3 + 16*x over Finite Field of size 17
851
+
852
+ Note that there is only one lift with `x`-coordinate 10 in
853
+ `E(\GF{17})`::
854
+
855
+ sage: E.lift_x(10, all=True)
856
+ [(10 : 8 : 1)]
857
+
858
+ We can lift over more exotic rings too. If the supplied x
859
+ value is in an extension of the base, note that the point
860
+ returned is on the base-extended curve::
861
+
862
+ sage: E = EllipticCurve('37a')
863
+ sage: P = E.lift_x(pAdicField(17, 5)(6)); P # needs sage.rings.padics
864
+ (6 + O(17^5) : 14 + O(17^5) : 1 + O(17^5))
865
+ sage: P.curve() # needs sage.rings.padics
866
+ Elliptic Curve defined by
867
+ y^2 + (1+O(17^5))*y = x^3 + (16+16*17+16*17^2+16*17^3+16*17^4+O(17^5))*x
868
+ over 17-adic Field with capped relative precision 5
869
+ sage: K.<t> = PowerSeriesRing(QQ, 't', 5)
870
+ sage: P = E.lift_x(1 + t); P
871
+ (1 + t : -1 - 2*t + t^2 - 5*t^3 + 21*t^4 + O(t^5) : 1)
872
+ sage: K.<a> = GF(16) # needs sage.rings.finite_rings
873
+ sage: P = E.change_ring(K).lift_x(a^3); P # needs sage.rings.finite_rings
874
+ (a^3 : a^3 + a : 1)
875
+ sage: P.curve() # needs sage.rings.finite_rings
876
+ Elliptic Curve defined by y^2 + y = x^3 + x over Finite Field in a of size 2^4
877
+
878
+ We can extend the base field to include the associated `y` value(s)::
879
+
880
+ sage: E = EllipticCurve([0,0,0,0,2]); E
881
+ Elliptic Curve defined by y^2 = x^3 + 2 over Rational Field
882
+ sage: x = polygen(QQ)
883
+ sage: P = E.lift_x(x, extend=True); P
884
+ (x : -y : 1)
885
+
886
+ This point is a generic point on E::
887
+
888
+ sage: P.curve()
889
+ Elliptic Curve defined by y^2 = x^3 + 2
890
+ over Univariate Quotient Polynomial Ring in y
891
+ over Fraction Field of Univariate Polynomial Ring in x over Rational Field
892
+ with modulus y^2 - x^3 - 2
893
+ sage: -P
894
+ (x : y : 1)
895
+ sage: 2*P
896
+ ((1/4*x^4 - 4*x)/(x^3 + 2) : ((-1/8*x^6 - 5*x^3 + 4)/(x^6 + 4*x^3 + 4))*y : 1)
897
+
898
+ Check that :issue:`30297` is fixed::
899
+
900
+ sage: K = Qp(5) # needs sage.rings.padics
901
+ sage: E = EllipticCurve([K(0), K(1)]) # needs sage.rings.padics
902
+ sage: E.lift_x(1, extend=True) # needs sage.rings.padics
903
+ (1 + O(5^20) : y + O(5^20) : 1 + O(5^20))
904
+
905
+ AUTHORS:
906
+
907
+ - Robert Bradshaw (2007-04-24)
908
+ - John Cremona (2017-11-10)
909
+
910
+ TESTS::
911
+
912
+ sage: E = EllipticCurve('37a').short_weierstrass_model().change_ring(GF(17))
913
+ sage: E.lift_x(3, all=True)
914
+ []
915
+ sage: E.lift_x(7, all=True)
916
+ [(7 : 3 : 1), (7 : 14 : 1)]
917
+
918
+ Check determinism::
919
+
920
+ sage: F.<t> = GF((101,3))
921
+ sage: {(t+1).sqrt() for _ in range(1000)} # both square roots can occur
922
+ {29*t^2 + 56*t + 26, 72*t^2 + 45*t + 75}
923
+ sage: E = EllipticCurve(F, [1,1])
924
+ sage: {E.lift_x(t+1) for _ in range(1000)} # but .lift_x() uses a fixed one
925
+ {(t + 1 : 39*t^2 + 14*t + 12 : 1)}
926
+ """
927
+ K = self.base_ring()
928
+ L = x.parent()
929
+ E = self
930
+
931
+ # Check that the x-coordinate is in K and extend otherwise if possible:
932
+ phi = K.coerce_map_from(L)
933
+ if phi:
934
+ x = phi(x)
935
+ L = K # new parent of x
936
+ else:
937
+ if L.coerce_map_from(K):
938
+ E = E.change_ring(L)
939
+ L = E.base_ring()
940
+ x = L(x)
941
+ else:
942
+ raise TypeError("Unable to construct a point with x in {} over {}".format(L,K))
943
+
944
+ # Now E is defined over L, possibly an extension of K, and x is in L
945
+
946
+ a1, a2, a3, a4, a6 = E.ainvs()
947
+ b = (a1*x + a3)
948
+ f = ((x + a2) * x + a4) * x + a6
949
+
950
+ # If possible find the associated y coordinates in L:
951
+
952
+ if K.characteristic() == 2:
953
+ R = PolynomialRing(L, 'y')
954
+ F = R([-f,b,1])
955
+ ys = F.roots(L, multiplicities=False)
956
+ else:
957
+ D = b*b+4*f
958
+ ys = []
959
+ if D.is_square(): # avoid automatic creation of sqrts
960
+ ys = [(-b+d)/2 for d in D.sqrt(all=True)]
961
+
962
+ ys.sort() # ensure deterministic behavior
963
+
964
+ # Return the point(s) if any:
965
+
966
+ if ys:
967
+ one = L.one()
968
+ if all:
969
+ return [E.point([x, y, one], check=False) for y in ys]
970
+ else:
971
+ return E.point([x, ys[0], one], check=False)
972
+
973
+ # otherwise if the additional extension was not requested return the empty list or raise an error:
974
+
975
+ if not extend:
976
+ if all:
977
+ return []
978
+ else:
979
+ raise ValueError("No point with x-coordinate {} on {}".format(x, self))
980
+
981
+ # Now make the extension needed to contain the y-coordinates:
982
+
983
+ if K.characteristic() != 2: # else we already defined F
984
+ R = PolynomialRing(L, 'y')
985
+ F = R([-f,b,1])
986
+ M = L.fraction_field().extension(F, names='y')
987
+ EM = E.change_ring(M)
988
+ y1 = M.gen()
989
+ y2 = -b-y1
990
+ if y2 == y1:
991
+ ys = [y1]
992
+ else:
993
+ ys = [y1, y2]
994
+ ys.sort() # ensure deterministic behavior
995
+ x = M(x)
996
+ one = M.one()
997
+ if all:
998
+ return [EM.point([x, y, one], check=False) for y in ys]
999
+ else:
1000
+ return EM.point([x, ys[0], one], check=False)
1001
+
1002
+ def _point_homset(self, *args, **kwds):
1003
+ r"""
1004
+ Internal function. Return the (abstract) group of points on this
1005
+ elliptic curve over a ring.
1006
+
1007
+ EXAMPLES::
1008
+
1009
+ sage: E = EllipticCurve(GF(5),[1,1])
1010
+ sage: E._point_homset(Spec(GF(5^10,'a'), GF(5)), E) # needs sage.rings.finite_rings
1011
+ Abelian group of points on Elliptic Curve defined
1012
+ by y^2 = x^3 + x + 1 over Finite Field in a of size 5^10
1013
+
1014
+ Point sets of elliptic curves are unique (see :issue:`17008`)::
1015
+
1016
+ sage: E = EllipticCurve([2, 3])
1017
+ sage: E.point_homset() is E.point_homset(QQ)
1018
+ True
1019
+
1020
+ sage: @fork
1021
+ ....: def compute_E():
1022
+ ....: E = EllipticCurve([2, 3])
1023
+ ....: p = E(3, 6, 1)
1024
+ ....: return p
1025
+ sage: p = compute_E()
1026
+ sage: 2*p
1027
+ (-23/144 : 2827/1728 : 1)
1028
+ """
1029
+ return SchemeHomset_points_abelian_variety_field(*args, **kwds)
1030
+
1031
+ def __getitem__(self, n):
1032
+ r"""
1033
+ Placeholder for standard indexing function.
1034
+
1035
+ EXAMPLES::
1036
+
1037
+ sage: E = EllipticCurve(QQ,[1,1])
1038
+ sage: E[2]
1039
+ Traceback (most recent call last):
1040
+ ...
1041
+ NotImplementedError: not implemented.
1042
+ """
1043
+ raise NotImplementedError("not implemented.")
1044
+
1045
+ def __is_over_RationalField(self):
1046
+ r"""
1047
+ Internal function. Return true iff the base ring of this elliptic
1048
+ curve is the field of rational numbers.
1049
+
1050
+ EXAMPLES::
1051
+
1052
+ sage: E = EllipticCurve(QQ,[1,1])
1053
+ sage: E._EllipticCurve_generic__is_over_RationalField()
1054
+ True
1055
+ sage: E = EllipticCurve(GF(5),[1,1])
1056
+ sage: E._EllipticCurve_generic__is_over_RationalField()
1057
+ False
1058
+ """
1059
+ return isinstance(self.base_ring(), RationalField)
1060
+
1061
+ def is_on_curve(self, x, y):
1062
+ r"""
1063
+ Return ``True`` if `(x,y)` is an affine point on this curve.
1064
+
1065
+ INPUT:
1066
+
1067
+ - ``x``, ``y`` -- elements of the base ring of the curve
1068
+
1069
+ EXAMPLES::
1070
+
1071
+ sage: E = EllipticCurve(QQ,[1,1])
1072
+ sage: E.is_on_curve(0,1)
1073
+ True
1074
+ sage: E.is_on_curve(1,1)
1075
+ False
1076
+ """
1077
+ a = self.ainvs()
1078
+ return y**2 + a[0]*x*y + a[2]*y == x**3 + a[1]*x**2 + a[3]*x + a[4]
1079
+
1080
+ def is_exact(self):
1081
+ """
1082
+ Test whether elements of this elliptic curve are represented exactly.
1083
+
1084
+ EXAMPLES::
1085
+
1086
+ sage: EllipticCurve(QQ, [1, 2]).is_exact()
1087
+ True
1088
+ sage: EllipticCurve(RR, [1, 2]).is_exact()
1089
+ False
1090
+ """
1091
+ return self.__base_ring.is_exact()
1092
+
1093
+ def a_invariants(self):
1094
+ r"""
1095
+ The `a`-invariants of this elliptic curve, as a tuple.
1096
+
1097
+ OUTPUT:
1098
+
1099
+ (tuple) - a 5-tuple of the `a`-invariants of this elliptic curve.
1100
+
1101
+ EXAMPLES::
1102
+
1103
+ sage: E = EllipticCurve([1,2,3,4,5])
1104
+ sage: E.a_invariants()
1105
+ (1, 2, 3, 4, 5)
1106
+
1107
+ sage: E = EllipticCurve([0,1]); E
1108
+ Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
1109
+ sage: E.a_invariants()
1110
+ (0, 0, 0, 0, 1)
1111
+
1112
+ sage: E = EllipticCurve([GF(7)(3),5])
1113
+ sage: E.a_invariants()
1114
+ (0, 0, 0, 3, 5)
1115
+
1116
+ TESTS::
1117
+
1118
+ sage: E = EllipticCurve([1,0,0,0,1])
1119
+ sage: E.a_invariants()[0] = 100000000
1120
+ Traceback (most recent call last):
1121
+ ...
1122
+ TypeError: 'tuple' object does not support item assignment
1123
+ """
1124
+ return self.__ainvs
1125
+
1126
+ ainvs = a_invariants
1127
+
1128
+ def a1(self):
1129
+ r"""
1130
+ Return the `a_1` invariant of this elliptic curve.
1131
+
1132
+ EXAMPLES::
1133
+
1134
+ sage: E = EllipticCurve([1,2,3,4,6])
1135
+ sage: E.a1()
1136
+ 1
1137
+ """
1138
+ return self.__ainvs[0]
1139
+
1140
+ def a2(self):
1141
+ r"""
1142
+ Return the `a_2` invariant of this elliptic curve.
1143
+
1144
+ EXAMPLES::
1145
+
1146
+ sage: E = EllipticCurve([1,2,3,4,6])
1147
+ sage: E.a2()
1148
+ 2
1149
+ """
1150
+ return self.__ainvs[1]
1151
+
1152
+ def a3(self):
1153
+ r"""
1154
+ Return the `a_3` invariant of this elliptic curve.
1155
+
1156
+ EXAMPLES::
1157
+
1158
+ sage: E = EllipticCurve([1,2,3,4,6])
1159
+ sage: E.a3()
1160
+ 3
1161
+ """
1162
+ return self.__ainvs[2]
1163
+
1164
+ def a4(self):
1165
+ r"""
1166
+ Return the `a_4` invariant of this elliptic curve.
1167
+
1168
+ EXAMPLES::
1169
+
1170
+ sage: E = EllipticCurve([1,2,3,4,6])
1171
+ sage: E.a4()
1172
+ 4
1173
+ """
1174
+ return self.__ainvs[3]
1175
+
1176
+ def a6(self):
1177
+ r"""
1178
+ Return the `a_6` invariant of this elliptic curve.
1179
+
1180
+ EXAMPLES::
1181
+
1182
+ sage: E = EllipticCurve([1,2,3,4,6])
1183
+ sage: E.a6()
1184
+ 6
1185
+ """
1186
+ return self.__ainvs[4]
1187
+
1188
+ @cached_method
1189
+ def b_invariants(self):
1190
+ r"""
1191
+ Return the `b`-invariants of this elliptic curve, as a tuple.
1192
+
1193
+ OUTPUT:
1194
+
1195
+ (tuple) - a 4-tuple of the `b`-invariants of this elliptic curve.
1196
+
1197
+ This method is cached.
1198
+
1199
+ EXAMPLES::
1200
+
1201
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
1202
+ sage: E.b_invariants()
1203
+ (-4, -20, -79, -21)
1204
+
1205
+ sage: E = EllipticCurve([-4,0])
1206
+ sage: E.b_invariants()
1207
+ (0, -8, 0, -16)
1208
+
1209
+ sage: E = EllipticCurve([1,2,3,4,5])
1210
+ sage: E.b_invariants()
1211
+ (9, 11, 29, 35)
1212
+ sage: E.b2()
1213
+ 9
1214
+ sage: E.b4()
1215
+ 11
1216
+ sage: E.b6()
1217
+ 29
1218
+ sage: E.b8()
1219
+ 35
1220
+
1221
+ ALGORITHM:
1222
+
1223
+ These are simple functions of the `a`-invariants.
1224
+
1225
+ AUTHORS:
1226
+
1227
+ - William Stein (2005-04-25)
1228
+ """
1229
+ a1, a2, a3, a4, a6 = self.ainvs()
1230
+ return (a1*a1 + 4*a2,
1231
+ a1*a3 + 2*a4,
1232
+ a3**2 + 4*a6,
1233
+ a1**2 * a6 + 4*a2*a6 - a1*a3*a4 + a2*a3**2 - a4**2)
1234
+
1235
+ def b2(self):
1236
+ r"""
1237
+ Return the `b_2` invariant of this elliptic curve.
1238
+
1239
+ EXAMPLES::
1240
+
1241
+ sage: E = EllipticCurve([1,2,3,4,5])
1242
+ sage: E.b2()
1243
+ 9
1244
+ """
1245
+ return self.b_invariants()[0]
1246
+
1247
+ def b4(self):
1248
+ r"""
1249
+ Return the `b_4` invariant of this elliptic curve.
1250
+
1251
+ EXAMPLES::
1252
+
1253
+ sage: E = EllipticCurve([1,2,3,4,5])
1254
+ sage: E.b4()
1255
+ 11
1256
+ """
1257
+ return self.b_invariants()[1]
1258
+
1259
+ def b6(self):
1260
+ r"""
1261
+ Return the `b_6` invariant of this elliptic curve.
1262
+
1263
+ EXAMPLES::
1264
+
1265
+ sage: E = EllipticCurve([1,2,3,4,5])
1266
+ sage: E.b6()
1267
+ 29
1268
+ """
1269
+ return self.b_invariants()[2]
1270
+
1271
+ def b8(self):
1272
+ r"""
1273
+ Return the `b_8` invariant of this elliptic curve.
1274
+
1275
+ EXAMPLES::
1276
+
1277
+ sage: E = EllipticCurve([1,2,3,4,5])
1278
+ sage: E.b8()
1279
+ 35
1280
+ """
1281
+ return self.b_invariants()[3]
1282
+
1283
+ @cached_method
1284
+ def c_invariants(self):
1285
+ r"""
1286
+ Return the `c`-invariants of this elliptic curve, as a tuple.
1287
+
1288
+ This method is cached.
1289
+
1290
+ OUTPUT:
1291
+
1292
+ (tuple) - a 2-tuple of the `c`-invariants of the elliptic curve.
1293
+
1294
+ EXAMPLES::
1295
+
1296
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
1297
+ sage: E.c_invariants()
1298
+ (496, 20008)
1299
+
1300
+ sage: E = EllipticCurve([-4,0])
1301
+ sage: E.c_invariants()
1302
+ (192, 0)
1303
+
1304
+ ALGORITHM:
1305
+
1306
+ These are simple functions of the `a`-invariants.
1307
+
1308
+ AUTHORS:
1309
+
1310
+ - William Stein (2005-04-25)
1311
+ """
1312
+ b2, b4, b6, b8 = self.b_invariants()
1313
+ # note: c6 is wrong in Silverman, but right in Cremona
1314
+ return (b2**2 - 24*b4,
1315
+ -b2**3 + 36*b2*b4 - 216*b6)
1316
+
1317
+ def c4(self):
1318
+ r"""
1319
+ Return the `c_4` invariant of this elliptic curve.
1320
+
1321
+ EXAMPLES::
1322
+
1323
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
1324
+ sage: E.c4()
1325
+ 496
1326
+ """
1327
+ return self.c_invariants()[0]
1328
+
1329
+ def c6(self):
1330
+ r"""
1331
+ Return the `c_6` invariant of this elliptic curve.
1332
+
1333
+ EXAMPLES::
1334
+
1335
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
1336
+ sage: E.c6()
1337
+ 20008
1338
+ """
1339
+ return self.c_invariants()[1]
1340
+
1341
+ @cached_method
1342
+ def discriminant(self):
1343
+ r"""
1344
+ Return the discriminant of this elliptic curve.
1345
+
1346
+ This method is cached.
1347
+
1348
+ EXAMPLES::
1349
+
1350
+ sage: E = EllipticCurve([0,0,1,-1,0])
1351
+ sage: E.discriminant()
1352
+ 37
1353
+
1354
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
1355
+ sage: E.discriminant()
1356
+ -161051
1357
+
1358
+ sage: E = EllipticCurve([GF(7)(2),1])
1359
+ sage: E.discriminant()
1360
+ 1
1361
+ """
1362
+ b2, b4, b6, b8 = self.b_invariants()
1363
+ return -b2**2*b8 - 8*b4**3 - 27*b6**2 + 9*b2*b4*b6
1364
+
1365
+ @cached_method
1366
+ def j_invariant(self):
1367
+ r"""
1368
+ Return the `j`-invariant of this elliptic curve.
1369
+
1370
+ This method is cached.
1371
+
1372
+ EXAMPLES::
1373
+
1374
+ sage: E = EllipticCurve([0,0,1,-1,0])
1375
+ sage: E.j_invariant()
1376
+ 110592/37
1377
+
1378
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
1379
+ sage: E.j_invariant()
1380
+ -122023936/161051
1381
+
1382
+ sage: E = EllipticCurve([-4,0])
1383
+ sage: E.j_invariant()
1384
+ 1728
1385
+
1386
+ sage: E = EllipticCurve([GF(7)(2),1])
1387
+ sage: E.j_invariant()
1388
+ 1
1389
+ """
1390
+ c4, _ = self.c_invariants()
1391
+ return c4**3 / self.discriminant()
1392
+
1393
+ def base_extend(self, R):
1394
+ r"""
1395
+ Return the base extension of ``self`` to `R`.
1396
+
1397
+ INPUT:
1398
+
1399
+ - ``R`` -- either a ring into which the `a`-invariants of
1400
+ ``self`` may be converted, or a morphism which may be
1401
+ applied to them.
1402
+
1403
+ OUTPUT:
1404
+
1405
+ An elliptic curve over the new ring whose `a`-invariants are
1406
+ the images of the `a`-invariants of ``self``.
1407
+
1408
+ EXAMPLES::
1409
+
1410
+ sage: E = EllipticCurve(GF(5), [1,1]); E
1411
+ Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
1412
+ sage: E1 = E.base_extend(GF(125,'a')); E1 # needs sage.rings.finite_rings
1413
+ Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 5^3
1414
+
1415
+ TESTS:
1416
+
1417
+ Check that we are correctly keeping track of known
1418
+ cardinalities when extending the base field::
1419
+
1420
+ sage: # needs sage.rings.finite_rings
1421
+ sage: E = EllipticCurve(j=GF(7)(5))
1422
+ sage: E.cardinality()
1423
+ 10
1424
+ sage: EE = E.base_extend(GF(7^2))
1425
+ sage: EE._order
1426
+ 60
1427
+
1428
+ Changing to a smaller field should not cache orders::
1429
+
1430
+ sage: EE = EllipticCurve(j=GF(7^3)(6)) # needs sage.rings.finite_rings
1431
+ sage: hasattr(EE.change_ring(GF(7)), '_order') # needs sage.rings.finite_rings
1432
+ False
1433
+
1434
+ Changing to a field of different characteristic should
1435
+ not cache orders::
1436
+
1437
+ sage: Elift = E.change_ring(QQ) # needs sage.rings.finite_rings
1438
+ sage: hasattr(Elift, '_order') # needs sage.rings.finite_rings
1439
+ False
1440
+ """
1441
+ E = constructor.EllipticCurve([R(a) for a in self.a_invariants()])
1442
+
1443
+ if isinstance(R, FiniteField) and hasattr(self, '_order') and self.__base_ring.is_subring(R):
1444
+ # The cardinality over an extension field follows easily
1445
+ # from the cardinality over the smaller field.
1446
+ n = R.cardinality().log(self.__base_ring.cardinality())
1447
+ E._order = self.cardinality(extension_degree=n)
1448
+
1449
+ return E
1450
+
1451
+ def change_ring(self, R):
1452
+ """
1453
+ Return the base change of ``self`` to `R`.
1454
+
1455
+ This has the same effect as ``self.base_extend(R)``.
1456
+
1457
+ EXAMPLES::
1458
+
1459
+ sage: # needs sage.rings.finite_rings
1460
+ sage: F2 = GF(5^2,'a'); a = F2.gen()
1461
+ sage: F4 = GF(5^4,'b'); b = F4.gen()
1462
+ sage: roots = a.charpoly().roots(ring=F4, multiplicities=False)
1463
+ sage: h = F2.hom([roots[0]], F4)
1464
+ sage: E = EllipticCurve(F2, [1,a]); E
1465
+ Elliptic Curve defined by y^2 = x^3 + x + a
1466
+ over Finite Field in a of size 5^2
1467
+ sage: E.change_ring(h)
1468
+ Elliptic Curve defined by y^2 = x^3 + x + (4*b^3+4*b^2+4*b+3)
1469
+ over Finite Field in b of size 5^4
1470
+ """
1471
+ return self.base_extend(R)
1472
+
1473
+ def base_ring(self):
1474
+ r"""
1475
+ Return the base ring of the elliptic curve.
1476
+
1477
+ EXAMPLES::
1478
+
1479
+ sage: E = EllipticCurve(GF(49, 'a'), [3,5]) # needs sage.rings.finite_rings
1480
+ sage: E.base_ring() # needs sage.rings.finite_rings
1481
+ Finite Field in a of size 7^2
1482
+
1483
+ ::
1484
+
1485
+ sage: E = EllipticCurve([1,1])
1486
+ sage: E.base_ring()
1487
+ Rational Field
1488
+
1489
+ ::
1490
+
1491
+ sage: E = EllipticCurve(ZZ, [3,5])
1492
+ sage: E.base_ring()
1493
+ Integer Ring
1494
+ """
1495
+ return self.__base_ring
1496
+
1497
+ def gens(self):
1498
+ r"""
1499
+ Placeholder function to return generators of an elliptic curve.
1500
+
1501
+ .. NOTE::
1502
+
1503
+ This functionality is implemented in certain derived
1504
+ classes, such as EllipticCurve_rational_field.
1505
+
1506
+ EXAMPLES::
1507
+
1508
+ sage: R.<a1,a2,a3,a4,a6> = QQ[]
1509
+ sage: E = EllipticCurve([a1,a2,a3,a4,a6])
1510
+ sage: E.gens()
1511
+ Traceback (most recent call last):
1512
+ ...
1513
+ NotImplementedError: not implemented.
1514
+ sage: E = EllipticCurve(QQ, [1,1])
1515
+ sage: E.gens() # needs eclib
1516
+ [(0 : 1 : 1)]
1517
+ """
1518
+ raise NotImplementedError("not implemented.")
1519
+
1520
+ def gen(self, i):
1521
+ r"""
1522
+ Function returning the i'th generator of this elliptic curve.
1523
+
1524
+ .. NOTE::
1525
+
1526
+ Relies on gens() being implemented.
1527
+
1528
+ EXAMPLES::
1529
+
1530
+ sage: R.<a1,a2,a3,a4,a6> = QQ[]
1531
+ sage: E = EllipticCurve([a1,a2,a3,a4,a6])
1532
+ sage: E.gen(0)
1533
+ Traceback (most recent call last):
1534
+ ...
1535
+ NotImplementedError: not implemented.
1536
+ """
1537
+ return self.gens()[i]
1538
+
1539
+ def rst_transform(self, r, s, t):
1540
+ r"""
1541
+ Return the transform of the curve by `(r,s,t)` (with `u=1`).
1542
+
1543
+ INPUT:
1544
+
1545
+ - ``r``, ``s``, ``t`` -- three elements of the base ring
1546
+
1547
+ OUTPUT:
1548
+
1549
+ The elliptic curve obtained from ``self`` by the standard
1550
+ Weierstrass transformation `(u,r,s,t)` with `u=1`.
1551
+
1552
+ .. NOTE::
1553
+
1554
+ This is just a special case of
1555
+ :meth:`change_weierstrass_model`, with `u=1`.
1556
+
1557
+ EXAMPLES::
1558
+
1559
+ sage: R.<r,s,t> = QQ[]
1560
+ sage: E = EllipticCurve([1,2,3,4,5])
1561
+ sage: E.rst_transform(r, s, t)
1562
+ Elliptic Curve defined by y^2 + (2*s+1)*x*y + (r+2*t+3)*y
1563
+ = x^3 + (-s^2+3*r-s+2)*x^2 + (3*r^2-r*s-2*s*t+4*r-3*s-t+4)*x
1564
+ + (r^3+2*r^2-r*t-t^2+4*r-3*t+5)
1565
+ over Multivariate Polynomial Ring in r, s, t over Rational Field
1566
+ """
1567
+ return self.change_weierstrass_model(1, r, s, t)
1568
+
1569
+ def scale_curve(self, u):
1570
+ r"""
1571
+ Return the transform of the curve by scale factor `u`.
1572
+
1573
+ INPUT:
1574
+
1575
+ - ``u`` -- an invertible element of the base ring
1576
+
1577
+ OUTPUT:
1578
+
1579
+ The elliptic curve obtained from ``self`` by the standard
1580
+ Weierstrass transformation `(u,r,s,t)` with `r=s=t=0`.
1581
+
1582
+ .. NOTE::
1583
+
1584
+ This is just a special case of
1585
+ :meth:`change_weierstrass_model`, with `r=s=t=0`.
1586
+
1587
+ EXAMPLES::
1588
+
1589
+ sage: K = Frac(PolynomialRing(QQ, 'u'))
1590
+ sage: u = K.gen()
1591
+ sage: E = EllipticCurve([1,2,3,4,5])
1592
+ sage: E.scale_curve(u)
1593
+ Elliptic Curve defined by
1594
+ y^2 + u*x*y + 3*u^3*y = x^3 + 2*u^2*x^2 + 4*u^4*x + 5*u^6
1595
+ over Fraction Field of Univariate Polynomial Ring in u over Rational Field
1596
+ """
1597
+ if isinstance(u, int):
1598
+ u = self.base_ring()(u) # because otherwise 1/u would round!
1599
+ return self.change_weierstrass_model(1/u, 0, 0, 0)
1600
+
1601
+ def isomorphism(self, u, r=0, s=0, t=0, *, is_codomain=False):
1602
+ r"""
1603
+ Given four values `u,r,s,t` in the base ring of this curve, return
1604
+ the :class:`WeierstrassIsomorphism` defined by `u,r,s,t` with this
1605
+ curve as its codomain.
1606
+ (The value `u` must be a unit; the values `r,s,t` default to zero.)
1607
+
1608
+ Optionally, if the keyword argument ``is_codomain`` is set to ``True``,
1609
+ return the isomorphism defined by `u,r,s,t` with this curve as its
1610
+ **co**\domain.
1611
+
1612
+ EXAMPLES::
1613
+
1614
+ sage: E = EllipticCurve([1, 2, 3, 4, 5])
1615
+ sage: iso = E.isomorphism(6); iso
1616
+ Elliptic-curve morphism:
1617
+ From: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
1618
+ To: Elliptic Curve defined by y^2 + 1/6*x*y + 1/72*y = x^3 + 1/18*x^2 + 1/324*x + 5/46656 over Rational Field
1619
+ Via: (u,r,s,t) = (6, 0, 0, 0)
1620
+ sage: iso.domain() == E
1621
+ True
1622
+ sage: iso.codomain() == E.scale_curve(1 / 6)
1623
+ True
1624
+
1625
+ sage: iso = E.isomorphism(1, 7, 8, 9); iso
1626
+ Elliptic-curve morphism:
1627
+ From: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
1628
+ To: Elliptic Curve defined by y^2 + 17*x*y + 28*y = x^3 - 49*x^2 - 54*x + 303 over Rational Field
1629
+ Via: (u,r,s,t) = (1, 7, 8, 9)
1630
+ sage: iso.domain() == E
1631
+ True
1632
+ sage: iso.codomain() == E.rst_transform(7, 8, 9)
1633
+ True
1634
+
1635
+ sage: iso = E.isomorphism(6, 7, 8, 9); iso
1636
+ Elliptic-curve morphism:
1637
+ From: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
1638
+ To: Elliptic Curve defined by y^2 + 17/6*x*y + 7/54*y = x^3 - 49/36*x^2 - 1/24*x + 101/15552 over Rational Field
1639
+ Via: (u,r,s,t) = (6, 7, 8, 9)
1640
+ sage: iso.domain() == E
1641
+ True
1642
+ sage: iso.codomain() == E.rst_transform(7, 8, 9).scale_curve(1 / 6)
1643
+ True
1644
+
1645
+ The ``is_codomain`` argument reverses the role of domain and codomain::
1646
+
1647
+ sage: E = EllipticCurve([1, 2, 3, 4, 5])
1648
+ sage: iso = E.isomorphism(6, is_codomain=True); iso
1649
+ Elliptic-curve morphism:
1650
+ From: Elliptic Curve defined by y^2 + 6*x*y + 648*y = x^3 + 72*x^2 + 5184*x + 233280 over Rational Field
1651
+ To: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
1652
+ Via: (u,r,s,t) = (6, 0, 0, 0)
1653
+ sage: iso.domain() == E.scale_curve(6)
1654
+ True
1655
+ sage: iso.codomain() == E
1656
+ True
1657
+
1658
+ sage: iso = E.isomorphism(1, 7, 8, 9, is_codomain=True); iso
1659
+ Elliptic-curve morphism:
1660
+ From: Elliptic Curve defined by y^2 - 15*x*y + 90*y = x^3 - 75*x^2 + 796*x - 2289 over Rational Field
1661
+ To: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
1662
+ Via: (u,r,s,t) = (1, 7, 8, 9)
1663
+ sage: iso.domain().rst_transform(7, 8, 9) == E
1664
+ True
1665
+ sage: iso.codomain() == E
1666
+ True
1667
+
1668
+ sage: iso = E.isomorphism(6, 7, 8, 9, is_codomain=True); iso
1669
+ Elliptic-curve morphism:
1670
+ From: Elliptic Curve defined by y^2 - 10*x*y + 700*y = x^3 + 35*x^2 + 9641*x + 169486 over Rational Field
1671
+ To: Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
1672
+ Via: (u,r,s,t) = (6, 7, 8, 9)
1673
+ sage: iso.domain().rst_transform(7, 8, 9) == E.scale_curve(6)
1674
+ True
1675
+ sage: iso.codomain() == E
1676
+ True
1677
+
1678
+ .. SEEALSO::
1679
+
1680
+ - :class:`~sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism`
1681
+ - :meth:`rst_transform`
1682
+ - :meth:`scale_curve`
1683
+ """
1684
+ from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
1685
+ if is_codomain:
1686
+ return WeierstrassIsomorphism(None, (u,r,s,t), self)
1687
+ return WeierstrassIsomorphism(self, (u,r,s,t))
1688
+
1689
+ # ###########################################################
1690
+ #
1691
+ # Explanation of the division (also known as torsion) polynomial
1692
+ # functions in Sage.
1693
+ #
1694
+ # The main user function division_polynomial() (also aliased as
1695
+ # torsion_polynomial()) is used to compute polynomials whose roots
1696
+ # determine the m-torsion points on the curve. Three options are
1697
+ # available, which effect the result when m is even and also the
1698
+ # parent ring of the returned value. The function can return either a
1699
+ # polynomial or the evaluation of that polynomial at a point,
1700
+ # depending on the input. Values are cached.
1701
+ #
1702
+ # The options are controlled by the value of the parameter
1703
+ # two_torsion_multiplicity, which may be 0, 1 or 2. If it is 0 or 2,
1704
+ # then a univariate polynomial will be returned (or evaluated at the
1705
+ # parameter x if x is not None). This is the polynomial whose roots
1706
+ # are the values of x(P) at the nonzero points P where m*P=0
1707
+ # (when two_torsion_multiplicity==2), or the points where m*P=0 but
1708
+ # 2*P\not=0 (when two_torsion_multiplicity==0).
1709
+ #
1710
+ # If two_torsion_multiplicity==1, then a bivariate polynomial is
1711
+ # returned, which (as a function on the curve) has a simple zero at
1712
+ # each nonzero point P such that m*P=0. When m is odd this is a
1713
+ # polynomial in x alone, but is still returned as an element of a
1714
+ # polynomial ring in two variables; when m is even it has a factor
1715
+ # 2y+a_1x+a_3. In this case if the parameter x is not None then it
1716
+ # should be a tuple of length 2, or a point P on the curve, and the
1717
+ # returned value is the value of the bivariate polynomial at this
1718
+ # point.
1719
+ #
1720
+ # Comparison with Magma: Magma's function DivisionPolynomial(E,m)
1721
+ # returns a triple of univariate polynomials f,g,h where f is
1722
+ # \code{E.division_polynomial(m,two_torsion_multiplicity=2)}, g is
1723
+ # \code{E.division_polynomial(m,two_torsion_multiplicity=0)} and h
1724
+ # is the quotient, so that h=1 when m is odd.
1725
+
1726
+ # ###########################################################
1727
+
1728
+ def division_polynomial_0(self, n, x=None):
1729
+ r"""
1730
+ Return the `n`-th torsion (division) polynomial, without
1731
+ the 2-torsion factor if `n` is even, as a polynomial in `x`.
1732
+
1733
+ These are the polynomials `g_n` defined in [MT1991]_, but with
1734
+ the sign flipped for even `n`, so that the leading coefficient is
1735
+ always positive.
1736
+
1737
+ .. NOTE::
1738
+
1739
+ This function is intended for internal use; users should use
1740
+ :meth:`division_polynomial`.
1741
+
1742
+ .. SEEALSO::
1743
+
1744
+ - :meth:`division_polynomial`
1745
+ - :meth:`_multiple_x_numerator`
1746
+ - :meth:`_multiple_x_denominator`
1747
+
1748
+ INPUT:
1749
+
1750
+ - ``n`` -- positive integer, or the special values ``-1`` and ``-2``
1751
+ which mean `B_6 = (2y + a_1 x + a_3)^2` and `B_6^2` respectively (in
1752
+ the notation of [MT1991]_), or a list of integers
1753
+
1754
+ - ``x`` -- a ring element to use as the "x" variable or ``None``
1755
+ (default: ``None``); if ``None``, then a new polynomial ring will
1756
+ be constructed over the base ring of the elliptic curve, and its
1757
+ generator will be used as ``x``. Note that ``x`` does not need to
1758
+ be a generator of a polynomial ring; any ring element is ok. This
1759
+ permits fast calculation of the torsion polynomial *evaluated* on
1760
+ any element of a ring.
1761
+
1762
+ ALGORITHM:
1763
+
1764
+ Recursion described in [MT1991]_. The recursive
1765
+ formulae are evaluated `O(\log^2 n)` times.
1766
+
1767
+ AUTHORS:
1768
+
1769
+ - David Harvey (2006-09-24): initial version
1770
+
1771
+ - John Cremona (2008-08-26): unified division polynomial code
1772
+
1773
+ EXAMPLES::
1774
+
1775
+ sage: E = EllipticCurve("37a")
1776
+ sage: E.division_polynomial_0(1)
1777
+ 1
1778
+ sage: E.division_polynomial_0(2)
1779
+ 1
1780
+ sage: E.division_polynomial_0(3)
1781
+ 3*x^4 - 6*x^2 + 3*x - 1
1782
+ sage: E.division_polynomial_0(4)
1783
+ 2*x^6 - 10*x^4 + 10*x^3 - 10*x^2 + 2*x + 1
1784
+ sage: E.division_polynomial_0(5)
1785
+ 5*x^12 - 62*x^10 + 95*x^9 - 105*x^8 - 60*x^7 + 285*x^6 - 174*x^5 - 5*x^4 - 5*x^3 + 35*x^2 - 15*x + 2
1786
+ sage: E.division_polynomial_0(6)
1787
+ 3*x^16 - 72*x^14 + 168*x^13 - 364*x^12 + 1120*x^10 - 1144*x^9 + 300*x^8 - 540*x^7 + 1120*x^6 - 588*x^5 - 133*x^4 + 252*x^3 - 114*x^2 + 22*x - 1
1788
+ sage: E.division_polynomial_0(7)
1789
+ 7*x^24 - 308*x^22 + 986*x^21 - 2954*x^20 + 28*x^19 + 17171*x^18 - 23142*x^17 + 511*x^16 - 5012*x^15 + 43804*x^14 - 7140*x^13 - 96950*x^12 + 111356*x^11 - 19516*x^10 - 49707*x^9 + 40054*x^8 - 124*x^7 - 18382*x^6 + 13342*x^5 - 4816*x^4 + 1099*x^3 - 210*x^2 + 35*x - 3
1790
+ sage: E.division_polynomial_0(8)
1791
+ 4*x^30 - 292*x^28 + 1252*x^27 - 5436*x^26 + 2340*x^25 + 39834*x^24 - 79560*x^23 + 51432*x^22 - 142896*x^21 + 451596*x^20 - 212040*x^19 - 1005316*x^18 + 1726416*x^17 - 671160*x^16 - 954924*x^15 + 1119552*x^14 + 313308*x^13 - 1502818*x^12 + 1189908*x^11 - 160152*x^10 - 399176*x^9 + 386142*x^8 - 220128*x^7 + 99558*x^6 - 33528*x^5 + 6042*x^4 + 310*x^3 - 406*x^2 + 78*x - 5
1792
+
1793
+ ::
1794
+
1795
+ sage: E.division_polynomial_0(18) % E.division_polynomial_0(6) == 0
1796
+ True
1797
+
1798
+ An example to illustrate the relationship with torsion points::
1799
+
1800
+ sage: F = GF(11)
1801
+ sage: E = EllipticCurve(F, [0, 2]); E
1802
+ Elliptic Curve defined by y^2 = x^3 + 2 over Finite Field of size 11
1803
+ sage: f = E.division_polynomial_0(5); f
1804
+ 5*x^12 + x^9 + 8*x^6 + 4*x^3 + 7
1805
+ sage: f.factor()
1806
+ (5) * (x^2 + 5) * (x^2 + 2*x + 5) * (x^2 + 5*x + 7)
1807
+ * (x^2 + 7*x + 7) * (x^2 + 9*x + 5) * (x^2 + 10*x + 7)
1808
+
1809
+ This indicates that the `x`-coordinates of all the 5-torsion points of
1810
+ `E` are in `\GF{11^2}`, and therefore the `y`-coordinates are in
1811
+ `\GF{11^4}`::
1812
+
1813
+ sage: # needs sage.rings.finite_rings
1814
+ sage: K = GF(11^4, 'a')
1815
+ sage: X = E.change_ring(K)
1816
+ sage: f = X.division_polynomial_0(5)
1817
+ sage: x_coords = f.roots(multiplicities=False); x_coords
1818
+ [10*a^3 + 4*a^2 + 5*a + 6,
1819
+ 9*a^3 + 8*a^2 + 10*a + 8,
1820
+ 8*a^3 + a^2 + 4*a + 10,
1821
+ 8*a^3 + a^2 + 4*a + 8,
1822
+ 8*a^3 + a^2 + 4*a + 4,
1823
+ 6*a^3 + 9*a^2 + 3*a + 4,
1824
+ 5*a^3 + 2*a^2 + 8*a + 7,
1825
+ 3*a^3 + 10*a^2 + 7*a + 8,
1826
+ 3*a^3 + 10*a^2 + 7*a + 3,
1827
+ 3*a^3 + 10*a^2 + 7*a + 1,
1828
+ 2*a^3 + 3*a^2 + a + 7,
1829
+ a^3 + 7*a^2 + 6*a]
1830
+
1831
+ Now we check that these are exactly the `x`-coordinates of the
1832
+ 5-torsion points of `E`::
1833
+
1834
+ sage: for x in x_coords: # needs sage.rings.finite_rings
1835
+ ....: assert X.lift_x(x).order() == 5
1836
+
1837
+ The roots of the polynomial are the `x`-coordinates of the points `P`
1838
+ such that `mP=0` but `2P\not=0`::
1839
+
1840
+ sage: E = EllipticCurve('14a1')
1841
+ sage: T = E.torsion_subgroup()
1842
+ sage: [n*T.0 for n in range(6)]
1843
+ [(0 : 1 : 0),
1844
+ (9 : 23 : 1),
1845
+ (2 : 2 : 1),
1846
+ (1 : -1 : 1),
1847
+ (2 : -5 : 1),
1848
+ (9 : -33 : 1)]
1849
+ sage: pol = E.division_polynomial_0(6)
1850
+ sage: xlist = pol.roots(multiplicities=False); xlist
1851
+ [9, 2, -1/3, -5]
1852
+ sage: [E.lift_x(x, all=True) for x in xlist]
1853
+ [[(9 : -33 : 1), (9 : 23 : 1)], [(2 : -5 : 1), (2 : 2 : 1)], [], []]
1854
+
1855
+ .. NOTE::
1856
+
1857
+ The point of order 2 and the identity do not appear.
1858
+ The points with `x=-1/3` and `x=-5` are not rational.
1859
+ """
1860
+ if x is None:
1861
+ # The generic division polynomials should be cached "forever".
1862
+ cache = self.__divpolys[0]
1863
+ x = polygen(self.base_ring())
1864
+ else:
1865
+ # For other inputs, we use a temporary cache.
1866
+ cache = {}
1867
+
1868
+ b2, b4, b6, b8 = self.b_invariants()
1869
+
1870
+ def poly(n):
1871
+ try:
1872
+ return cache[n]
1873
+ except KeyError:
1874
+ pass
1875
+ if n == -2:
1876
+ ret = poly(-1)**2
1877
+ elif n == -1:
1878
+ ret = 4*x**3 + b2*x**2 + 2*b4*x + b6
1879
+ elif n <= 0:
1880
+ raise ValueError("n must be a positive integer (or -1 or -2)")
1881
+ elif n == 1 or n == 2:
1882
+ ret = x.parent().one()
1883
+ elif n == 3:
1884
+ ret = 3*x**4 + b2*x**3 + 3*b4*x**2 + 3*b6*x + b8
1885
+ elif n == 4:
1886
+ ret = -poly(-2) + (6*x**2 + b2*x + b4) * poly(3)
1887
+ elif n % 2 == 0:
1888
+ m = (n-2) // 2
1889
+ ret = poly(m+1) * (poly(m+3) * poly(m)**2 - poly(m-1) * poly(m+2)**2)
1890
+ else:
1891
+ m = (n-1) // 2
1892
+ if m % 2 == 0:
1893
+ ret = poly(-2) * poly(m+2) * poly(m)**3 - poly(m-1) * poly(m+1)**3
1894
+ else:
1895
+ ret = poly(m+2) * poly(m)**3 - poly(-2) * poly(m-1) * poly(m+1)**3
1896
+ cache[n] = ret
1897
+ return ret
1898
+
1899
+ if not isinstance(n, (list, tuple)):
1900
+ return poly(int(n))
1901
+ else:
1902
+ return [poly(int(k)) for k in n]
1903
+
1904
+ def two_division_polynomial(self, x=None):
1905
+ r"""
1906
+ Return the 2-division polynomial of this elliptic curve evaluated
1907
+ at ``x``.
1908
+
1909
+ INPUT:
1910
+
1911
+ - ``x`` -- (optional) ring element to use as the `x` variable.
1912
+ If ``x`` is ``None``, then a new polynomial ring will be
1913
+ constructed over the base ring of the elliptic curve, and
1914
+ its generator will be used as ``x``. Note that ``x`` does
1915
+ not need to be a generator of a polynomial ring; any ring
1916
+ element is acceptable. This permits fast calculation of the
1917
+ torsion polynomial *evaluated* on any element of a ring.
1918
+
1919
+ EXAMPLES::
1920
+
1921
+ sage: E = EllipticCurve('5077a1')
1922
+ sage: E.two_division_polynomial()
1923
+ 4*x^3 - 28*x + 25
1924
+ sage: E = EllipticCurve(GF(3^2,'a'), [1,1,1,1,1]) # needs sage.rings.finite_rings
1925
+ sage: E.two_division_polynomial() # needs sage.rings.finite_rings
1926
+ x^3 + 2*x^2 + 2
1927
+ sage: E.two_division_polynomial().roots() # needs sage.rings.finite_rings
1928
+ [(2, 1), (2*a, 1), (a + 2, 1)]
1929
+ """
1930
+ return self.division_polynomial_0(-1,x)
1931
+
1932
+ def division_polynomial(self, m, x=None, two_torsion_multiplicity=2, force_evaluate=None):
1933
+ r"""
1934
+ Return the `m`-th division polynomial of this elliptic
1935
+ curve evaluated at `x`.
1936
+
1937
+ The division polynomial is cached if `x` is ``None``.
1938
+
1939
+ INPUT:
1940
+
1941
+ - ``m`` -- positive integer
1942
+
1943
+ - ``x`` -- (optional) ring element to use as the `x` variable.
1944
+ If `x` is ``None`` (omitted), then a new polynomial ring will be
1945
+ constructed over the base ring of the elliptic curve, and its
1946
+ generator will be used as `x`. Note that `x` does not need to
1947
+ be a generator of a polynomial ring; any ring element works. This
1948
+ permits fast calculation of the torsion polynomial *evaluated* on
1949
+ any element of a ring.
1950
+
1951
+ - ``two_torsion_multiplicity`` -- 0, 1, or 2
1952
+
1953
+ If 0: For even `m` when `x` is ``None``, a univariate polynomial
1954
+ over the base ring of the curve is returned, which omits factors
1955
+ whose roots are the `x`-coordinates of the `2`-torsion points.
1956
+ When `x` is not ``None``, the evaluation of such a polynomial at
1957
+ `x` is returned.
1958
+
1959
+ If 2: For even `m` when `x` is ``None``, a univariate polynomial
1960
+ over the base ring of the curve is returned, which includes a
1961
+ factor of degree 3 whose roots are the `x`-coordinates of the
1962
+ `2`-torsion points.
1963
+ Similarly, when `x` is not ``None``, the evaluation of such a
1964
+ polynomial at `x` is returned.
1965
+
1966
+ If 1: For even `m` when `x` is ``None``, a bivariate polynomial
1967
+ over the base ring of the curve is returned, which includes a
1968
+ factor `2y+a_1x+a_3` having simple zeros at the `2`-torsion points.
1969
+ When `x` is not ``None``, it should be a tuple of length 2, and
1970
+ the evaluation of such a polynomial at `x` is returned.
1971
+
1972
+ - ``force_evaluate`` -- (optional) 0, 1, or 2
1973
+
1974
+ By default, this method makes use of previously cached generic
1975
+ division polynomials to compute the value of the polynomial at
1976
+ a given element `x` whenever it appears beneficial to do so.
1977
+ Explicitly setting this flag overrides the default behavior.
1978
+
1979
+ Note that the complexity of evaluating a generic division
1980
+ polynomial scales much worse than that of computing the value
1981
+ at a point directly (using the recursive formulas), hence
1982
+ setting this flag can be detrimental to performance.
1983
+
1984
+ If 0: Do not use cached generic division polynomials.
1985
+
1986
+ If 1: If the generic division polynomial for this `m` has been
1987
+ cached before, evaluate it at `x` to compute the result.
1988
+
1989
+ If 2: Compute the value at `x` by evaluating the generic
1990
+ division polynomial. If the generic `m`-division polynomial
1991
+ has not yet been cached, compute and cache it first.
1992
+
1993
+ EXAMPLES::
1994
+
1995
+ sage: E = EllipticCurve([0,0,1,-1,0])
1996
+ sage: E.division_polynomial(1)
1997
+ 1
1998
+ sage: E.division_polynomial(2, two_torsion_multiplicity=0)
1999
+ 1
2000
+ sage: E.division_polynomial(2, two_torsion_multiplicity=1)
2001
+ 2*y + 1
2002
+ sage: E.division_polynomial(2, two_torsion_multiplicity=2)
2003
+ 4*x^3 - 4*x + 1
2004
+ sage: E.division_polynomial(2)
2005
+ 4*x^3 - 4*x + 1
2006
+ sage: [E.division_polynomial(3, two_torsion_multiplicity=i) for i in range(3)]
2007
+ [3*x^4 - 6*x^2 + 3*x - 1, 3*x^4 - 6*x^2 + 3*x - 1, 3*x^4 - 6*x^2 + 3*x - 1]
2008
+ sage: [type(E.division_polynomial(3, two_torsion_multiplicity=i)) for i in range(3)]
2009
+ [<... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>,
2010
+ <... 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>,
2011
+ <... 'sage.rings.polynomial.polynomial_rational_flint.Polynomial_rational_flint'>]
2012
+
2013
+ ::
2014
+
2015
+ sage: E = EllipticCurve([0, -1, 1, -10, -20])
2016
+ sage: R.<z> = PolynomialRing(QQ)
2017
+ sage: E.division_polynomial(4, z, 0)
2018
+ 2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821
2019
+ sage: E.division_polynomial(4, z)
2020
+ 8*z^9 - 24*z^8 - 464*z^7 - 2758*z^6 + 6636*z^5 + 34356*z^4
2021
+ + 53510*z^3 + 99714*z^2 + 351024*z + 459859
2022
+
2023
+ This does not work, since when two_torsion_multiplicity is 1, we
2024
+ compute a bivariate polynomial, and must evaluate at a tuple of
2025
+ length 2::
2026
+
2027
+ sage: E.division_polynomial(4,z,1)
2028
+ Traceback (most recent call last):
2029
+ ...
2030
+ ValueError: x should be a tuple of length 2 (or None)
2031
+ when two_torsion_multiplicity is 1
2032
+ sage: R.<z,w> = PolynomialRing(QQ, 2)
2033
+ sage: E.division_polynomial(4, (z,w), 1).factor()
2034
+ (2*w + 1) * (2*z^6 - 4*z^5 - 100*z^4 - 790*z^3 - 210*z^2 - 1496*z - 5821)
2035
+
2036
+ We can also evaluate this bivariate polynomial at a point::
2037
+
2038
+ sage: P = E(5,5)
2039
+ sage: E.division_polynomial(4,P,two_torsion_multiplicity=1)
2040
+ -1771561
2041
+
2042
+ TESTS:
2043
+
2044
+ Check that :issue:`33164` is fixed::
2045
+
2046
+ sage: E = EllipticCurve('11a3')
2047
+ sage: R.<X> = QQ[]
2048
+ sage: S.<Y> = R.quotient(X^2)
2049
+ sage: E.division_polynomial(5, x=Y)
2050
+ -5*Y
2051
+ sage: E.division_polynomial(5, x=X)
2052
+ 5*X^12 - 20*X^11 + 16*X^10 + 95*X^9 - 285*X^8 + 360*X^7 - 255*X^6 + 94*X^5 + 15*X^4 - 45*X^3 + 25*X^2 - 5*X
2053
+
2054
+ Tests for the ``force_evaluate`` argument::
2055
+
2056
+ sage: E.division_polynomial(5, x=Y, force_evaluate=0)
2057
+ -5*Y
2058
+ sage: E.division_polynomial(5, x=Y, force_evaluate=1)
2059
+ -5*Y
2060
+ sage: E.division_polynomial(5, x=Y, force_evaluate=2)
2061
+ -5*Y
2062
+ sage: E._EllipticCurve_generic__divpolys[2]
2063
+ {5: 5*x^12 - 20*x^11 + 16*x^10 + 95*x^9 - 285*x^8 + 360*x^7 - 255*x^6 + 94*x^5 + 15*x^4 - 45*x^3 + 25*x^2 - 5*x}
2064
+ sage: E._EllipticCurve_generic__divpolys[2][5] += 1 # poison cache
2065
+ sage: E.division_polynomial(5, x=Y, force_evaluate=0)
2066
+ -5*Y
2067
+ sage: E.division_polynomial(5, x=Y, force_evaluate=1)
2068
+ -5*Y + 1
2069
+ sage: E.division_polynomial(5, x=Y, force_evaluate=2)
2070
+ -5*Y + 1
2071
+ """
2072
+ if two_torsion_multiplicity not in (0, 1, 2):
2073
+ raise ValueError("two_torsion_multiplicity must be 0, 1, or 2")
2074
+
2075
+ if x is not None and two_torsion_multiplicity == 1:
2076
+ if isinstance(x, ell_point.EllipticCurvePoint_field):
2077
+ x = x.xy()
2078
+ if not (isinstance(x, tuple) and len(x) == 2):
2079
+ raise ValueError("x should be a tuple of length 2 (or None) when two_torsion_multiplicity is 1")
2080
+
2081
+ m = Integer(m)
2082
+
2083
+ if x is None:
2084
+ try:
2085
+ return self.__divpolys[two_torsion_multiplicity][m]
2086
+ except KeyError:
2087
+ pass
2088
+
2089
+ evaluate = False
2090
+ if force_evaluate is not None:
2091
+ evaluate = force_evaluate
2092
+ elif x is not None:
2093
+ # Univariate polynomials are much faster---this signals that the
2094
+ # result should first be computed as an univariate polynomial and
2095
+ # only then converted, even if it is not yet cached.
2096
+ if polynomial_is_variable(x) and x.base_ring() is self.base_ring():
2097
+ evaluate = 2
2098
+
2099
+ # Evaluating a precomputed polynomial is linear in the degree,
2100
+ # while the recursive definition is only logarithmic. For small
2101
+ # inputs, evaluation can be better nevertheless.
2102
+ # The following cutoffs were estimated based on experiments in
2103
+ # January 2022 (using Sage version 9.5.rc0).
2104
+ elif x in self.base_ring():
2105
+ evaluate = m < 100
2106
+ elif isinstance(x, PolynomialQuotientRingElement) and x.lift().is_gen() \
2107
+ and x.lift().base_ring() is self.base_ring():
2108
+ d = x.parent().modulus().degree()
2109
+ evaluate = m < 220 or \
2110
+ (d < 10 and m < 420) or (d < 15 and m < 340) or \
2111
+ (d < 30 and m < 280) or (d < 100 and m < 250) or \
2112
+ m <= min(250, d)
2113
+
2114
+ # Check if we should (attempt to) compute the result by simply
2115
+ # evaluating a cached polynomial at the given input.
2116
+ if evaluate:
2117
+ try:
2118
+ return self.__divpolys[two_torsion_multiplicity][m](x)
2119
+ except KeyError:
2120
+ if evaluate == 2:
2121
+ return self.division_polynomial(m, two_torsion_multiplicity=two_torsion_multiplicity)(x)
2122
+
2123
+ # If not, .division_polynomial_0() will do the real work for us.
2124
+ if two_torsion_multiplicity == 0:
2125
+ return self.division_polynomial_0(m, x)
2126
+
2127
+ should_cache = x is None
2128
+
2129
+ if two_torsion_multiplicity == 1:
2130
+ x,y = x if x is not None else (None,None)
2131
+
2132
+ if evaluate and m in self.__divpolys[0]:
2133
+ f = self.__divpolys[0][m](x)
2134
+ else:
2135
+ f = self.division_polynomial_0(m, x)
2136
+
2137
+ if two_torsion_multiplicity == 2:
2138
+ if m % 2 == 0:
2139
+ f *= self.division_polynomial_0(-1, x)
2140
+ elif two_torsion_multiplicity == 1:
2141
+ if x is y is None:
2142
+ x,y = polygens(self.base_ring(), 'x,y')
2143
+ f = f(x)
2144
+ if m % 2 == 0:
2145
+ f *= 2*y + self.a1()*x + self.a3()
2146
+
2147
+ if should_cache:
2148
+ self.__divpolys[two_torsion_multiplicity][m] = f
2149
+ return f
2150
+
2151
+ torsion_polynomial = division_polynomial
2152
+
2153
+ def _multiple_x_numerator(self, n, x=None):
2154
+ r"""
2155
+ Return the numerator of the `x`-coordinate of the `n\th` multiple of a
2156
+ point, using torsion polynomials (division polynomials).
2157
+
2158
+ INPUT:
2159
+
2160
+ - ``n``, ``x`` -- as described in :meth:`division_polynomial_0`
2161
+
2162
+ If ``x`` is ``None``, the result is cached. This is so that on calling
2163
+ ``P.division_points(n)`` for the same `n` and different points `P` (on
2164
+ the same curve), we do not have to recompute the polynomials.
2165
+
2166
+ .. WARNING::
2167
+
2168
+ There may of course be cancellation between the numerator and the
2169
+ denominator (:meth:`_multiple_x_denominator`). Be careful. E.g. if
2170
+ a point on an elliptic curve with coefficients in `\ZZ` reduces to
2171
+ a singular point modulo a prime, then there will be cancellation,
2172
+ otherwise not, see [Wu2004]_.
2173
+
2174
+ .. SEEALSO::
2175
+
2176
+ :meth:`_multiple_x_denominator`
2177
+
2178
+ AUTHORS:
2179
+
2180
+ - David Harvey (2006-09-24)
2181
+
2182
+ EXAMPLES::
2183
+
2184
+ sage: E = EllipticCurve([1,2])
2185
+ sage: E._multiple_x_numerator(3)
2186
+ x^9 - 12*x^7 - 192*x^6 + 30*x^5 - 48*x^4 + 228*x^3 + 96*x^2 + 393*x + 528
2187
+ sage: E._multiple_x_numerator(-3)
2188
+ x^9 - 12*x^7 - 192*x^6 + 30*x^5 - 48*x^4 + 228*x^3 + 96*x^2 + 393*x + 528
2189
+
2190
+ ::
2191
+
2192
+ sage: E = EllipticCurve("37a")
2193
+ sage: P = E.gens()[0] # needs eclib
2194
+ sage: x = P[0] # needs eclib
2195
+
2196
+ ::
2197
+
2198
+ sage: # needs eclib
2199
+ sage: (35*P)[0]
2200
+ -804287518035141565236193151/1063198259901027900600665796
2201
+ sage: E._multiple_x_numerator(35, x)
2202
+ -804287518035141565236193151
2203
+ sage: E._multiple_x_denominator(35, x)
2204
+ 1063198259901027900600665796
2205
+
2206
+ ::
2207
+
2208
+ sage: # needs eclib
2209
+ sage: (36*P)[0]
2210
+ 54202648602164057575419038802/15402543997324146892198790401
2211
+ sage: E._multiple_x_numerator(36, x)
2212
+ 54202648602164057575419038802
2213
+ sage: E._multiple_x_denominator(36, x)
2214
+ 15402543997324146892198790401
2215
+
2216
+ An example where cancellation occurs::
2217
+
2218
+ sage: E = EllipticCurve("88a1")
2219
+ sage: P = E([2,2]) # fixed choice of generator
2220
+ sage: n = E._multiple_x_numerator(11, P[0]); n
2221
+ 442446784738847563128068650529343492278651453440
2222
+ sage: d = E._multiple_x_denominator(11, P[0]); d
2223
+ 1427247692705959881058285969449495136382746624
2224
+ sage: n/d
2225
+ 310
2226
+ sage: 11*P
2227
+ (310 : -5458 : 1)
2228
+
2229
+ TESTS:
2230
+
2231
+ Check that the results are cached::
2232
+
2233
+ sage: E = EllipticCurve("88a1")
2234
+ sage: E._multiple_x_numerator(11) is E._multiple_x_numerator(11)
2235
+ True
2236
+
2237
+ Check for :issue:`33156`::
2238
+
2239
+ sage: # needs sage.rings.finite_rings
2240
+ sage: E = EllipticCurve(GF(65537), [5,5])
2241
+ sage: R.<x> = E.base_field()[]
2242
+ sage: E._multiple_x_numerator(5, x=R.quotient(x^2).gen())
2243
+ 10220*xbar + 42539
2244
+ sage: E._multiple_x_numerator(5)
2245
+ x^25 + 65037*x^23 + 55137*x^22 + ... + 813*x^2 + 10220*x + 42539
2246
+ """
2247
+ n = Integer(n).abs()
2248
+ if not n:
2249
+ raise ValueError("n must be nonzero")
2250
+
2251
+ if x is None:
2252
+ try:
2253
+ cache = self.__mulxnums
2254
+ except AttributeError:
2255
+ cache = self.__mulxnums = {}
2256
+ try:
2257
+ return cache[n]
2258
+ except KeyError:
2259
+ pass
2260
+ xx = polygen(self.base_ring())
2261
+ else:
2262
+ cache = None
2263
+ xx = x
2264
+
2265
+ if n == 1:
2266
+ return xx
2267
+
2268
+ polys = self.division_polynomial_0([-2,-1,n-1,n,n+1], x)
2269
+
2270
+ if n % 2 == 0:
2271
+ ret = xx * polys[1] * polys[3]**2 - polys[2] * polys[4]
2272
+ else:
2273
+ ret = xx * polys[3]**2 - polys[1] * polys[2] * polys[4]
2274
+
2275
+ if cache is not None:
2276
+ cache[n] = ret
2277
+ return ret
2278
+
2279
+ def _multiple_x_denominator(self, n, x=None):
2280
+ r"""
2281
+ Return the denominator of the `x`-coordinate of the `n\th` multiple of
2282
+ a point, using torsion polynomials (division polynomials).
2283
+
2284
+ INPUT:
2285
+
2286
+ - ``n``, ``x`` -- as described in :meth:`division_polynomial_0`
2287
+
2288
+ If ``x`` is ``None``, the result is cached. This is so that on calling
2289
+ ``P.division_points(n)`` for the same `n` and different points `P` (on
2290
+ the same curve), we do not have to recompute the polynomials.
2291
+
2292
+ AUTHORS:
2293
+
2294
+ - David Harvey (2006-09-24)
2295
+
2296
+ .. SEEALSO::
2297
+
2298
+ :meth:`multiple_x_numerator`
2299
+
2300
+ .. TODO::
2301
+
2302
+ The numerator and denominator versions share a calculation, namely
2303
+ squaring `\psi_n`. Maybe would be good to offer a combined version
2304
+ to make this more efficient.
2305
+
2306
+ EXAMPLES::
2307
+
2308
+ sage: E = EllipticCurve([1,2])
2309
+ sage: E._multiple_x_denominator(3)
2310
+ 9*x^8 + 36*x^6 + 144*x^5 + 30*x^4 + 288*x^3 + 564*x^2 - 48*x + 1
2311
+ sage: E._multiple_x_denominator(-3)
2312
+ 9*x^8 + 36*x^6 + 144*x^5 + 30*x^4 + 288*x^3 + 564*x^2 - 48*x + 1
2313
+
2314
+ ::
2315
+
2316
+ sage: # needs eclib
2317
+ sage: E = EllipticCurve("43a")
2318
+ sage: P = E.gens()[0]
2319
+ sage: x = P[0]
2320
+ sage: (31*P)[0]
2321
+ -33058398375463796474831580/154693637754223970056975321
2322
+ sage: E._multiple_x_numerator(31, x)
2323
+ -33058398375463796474831580
2324
+ sage: E._multiple_x_denominator(31, x)
2325
+ 154693637754223970056975321
2326
+
2327
+ TESTS:
2328
+
2329
+ Check that the results are cached::
2330
+
2331
+ sage: E = EllipticCurve("88a1")
2332
+ sage: E._multiple_x_denominator(11) is E._multiple_x_denominator(11)
2333
+ True
2334
+
2335
+ Check for :issue:`33156`::
2336
+
2337
+ sage: # needs sage.rings.finite_rings
2338
+ sage: E = EllipticCurve(GF(65537), [5,5])
2339
+ sage: R.<x> = E.base_field()[]
2340
+ sage: E._multiple_x_denominator(5, x=R.quotient(x^2).gen())
2341
+ 52039*xbar + 56726
2342
+ sage: E._multiple_x_denominator(5)
2343
+ 25*x^24 + 3100*x^22 + 19000*x^21 + ... + 24111*x^2 + 52039*x + 56726
2344
+ """
2345
+ n = Integer(n).abs()
2346
+ if not n:
2347
+ raise ValueError("n must be nonzero")
2348
+
2349
+ if x is None:
2350
+ try:
2351
+ cache = self.__mulxdens
2352
+ except AttributeError:
2353
+ cache = self.__mulxdens = {}
2354
+ try:
2355
+ return cache[n]
2356
+ except KeyError:
2357
+ pass
2358
+ else:
2359
+ cache = None
2360
+
2361
+ ret = self.division_polynomial_0(n, x)**2
2362
+ if n % 2 == 0:
2363
+ ret *= self.division_polynomial_0(-1, x)
2364
+
2365
+ if cache is not None:
2366
+ cache[n] = ret
2367
+ return ret
2368
+
2369
+ def multiplication_by_m(self, m, x_only=False):
2370
+ r"""
2371
+ Return the multiplication-by-`m` map from ``self`` to ``self``.
2372
+
2373
+ The result is a pair of rational functions in two variables
2374
+ `x`, `y` (or a rational function in one variable `x` if
2375
+ ``x_only`` is ``True``).
2376
+
2377
+ INPUT:
2378
+
2379
+ - ``m`` -- nonzero integer
2380
+
2381
+ - ``x_only`` -- boolean (default: ``False``); if ``True``, return only
2382
+ the `x`-coordinate of the map (as a rational function in one variable)
2383
+
2384
+ OUTPUT:
2385
+
2386
+ - a pair `(f(x), g(x,y))`, where `f` and `g` are rational
2387
+ functions with the degree of `y` in `g(x,y)` exactly 1,
2388
+
2389
+ - or just `f(x)` if ``x_only`` is ``True``
2390
+
2391
+ .. NOTE::
2392
+
2393
+ - The result is not cached.
2394
+
2395
+ - ``m`` is allowed to be negative (but not 0).
2396
+
2397
+ EXAMPLES::
2398
+
2399
+ sage: E = EllipticCurve([-1,3])
2400
+
2401
+ We verify that multiplication by 1 is just the identity::
2402
+
2403
+ sage: E.multiplication_by_m(1)
2404
+ (x, y)
2405
+
2406
+ Multiplication by 2 is more complicated::
2407
+
2408
+ sage: f = E.multiplication_by_m(2)
2409
+ sage: f
2410
+ ((x^4 + 2*x^2 - 24*x + 1)/(4*x^3 - 4*x + 12),
2411
+ (8*x^6*y - 40*x^4*y + 480*x^3*y - 40*x^2*y + 96*x*y - 568*y)/(64*x^6 - 128*x^4 + 384*x^3 + 64*x^2 - 384*x + 576))
2412
+
2413
+ Grab only the x-coordinate (less work)::
2414
+
2415
+ sage: mx = E.multiplication_by_m(2, x_only=True); mx
2416
+ (1/4*x^4 + 1/2*x^2 - 6*x + 1/4)/(x^3 - x + 3)
2417
+ sage: mx.parent()
2418
+ Fraction Field of Univariate Polynomial Ring in x over Rational Field
2419
+
2420
+ We check that it works on a point::
2421
+
2422
+ sage: P = E([2,3])
2423
+ sage: eval = lambda f,P: [fi(P[0],P[1]) for fi in f]
2424
+ sage: assert E(eval(f,P)) == 2*P
2425
+
2426
+ We do the same but with multiplication by 3::
2427
+
2428
+ sage: f = E.multiplication_by_m(3)
2429
+ sage: assert E(eval(f,P)) == 3*P
2430
+
2431
+ And the same with multiplication by 4::
2432
+
2433
+ sage: f = E.multiplication_by_m(4)
2434
+ sage: assert E(eval(f,P)) == 4*P
2435
+
2436
+ And the same with multiplication by -1,-2,-3,-4::
2437
+
2438
+ sage: for m in [-1,-2,-3,-4]:
2439
+ ....: f = E.multiplication_by_m(m)
2440
+ ....: assert E(eval(f,P)) == m*P
2441
+
2442
+ TESTS:
2443
+
2444
+ Verify for this fairly random looking curve and point that
2445
+ multiplication by m returns the right result for the first 10
2446
+ integers::
2447
+
2448
+ sage: E = EllipticCurve([23,-105])
2449
+ sage: P = E([129/4, 1479/8])
2450
+ sage: for n in [1..10]:
2451
+ ....: f = E.multiplication_by_m(n)
2452
+ ....: Q = n*P
2453
+ ....: assert Q == E(eval(f,P))
2454
+ ....: f = E.multiplication_by_m(-n)
2455
+ ....: Q = -n*P
2456
+ ....: assert Q == E(eval(f,P))
2457
+
2458
+ The following test shows that :issue:`4364` is indeed fixed::
2459
+
2460
+ sage: # needs sage.rings.finite_rings
2461
+ sage: p = next_prime(2^30 - 41)
2462
+ sage: a = GF(p)(1)
2463
+ sage: b = GF(p)(1)
2464
+ sage: E = EllipticCurve([a, b])
2465
+ sage: P = E.random_point()
2466
+ sage: my_eval = lambda f,P: [fi(P[0],P[1]) for fi in f]
2467
+ sage: f = E.multiplication_by_m(2)
2468
+ sage: assert(E(eval(f,P)) == 2*P)
2469
+
2470
+ The following test shows that :issue:`6413` is fixed for elliptic curves over finite fields::
2471
+ sage: p = 7
2472
+ sage: K.<a> = GF(p^2)
2473
+ sage: E = EllipticCurve(K, [a + 3, 5 - a])
2474
+ sage: k = p^2 * 3
2475
+ sage: f, g = E.multiplication_by_m(k)
2476
+ sage: for _ in range(100):
2477
+ ....: P = E.random_point()
2478
+ ....: if P * k == 0:
2479
+ ....: continue
2480
+ ....: Qx = f.subs(x=P[0])
2481
+ ....: Qy = g.subs(x=P[0], y=P[1])
2482
+ ....: assert (P * k).xy() == (Qx, Qy)
2483
+
2484
+ However, it still fails for elliptic curves over positive-characteristic fields::
2485
+
2486
+ sage: F.<a> = FunctionField(GF(7))
2487
+ sage: E = EllipticCurve(F, [a, 1 / a])
2488
+ sage: E.multiplication_by_m(7)
2489
+ Traceback (most recent call last):
2490
+ ...
2491
+ NotImplementedError: multiplication by integer not coprime to p is only implemented for curves over finite fields
2492
+
2493
+ ::
2494
+
2495
+ sage: p = 7
2496
+ sage: K.<a> = GF(p^2)
2497
+ sage: E = EllipticCurve(j=K.random_element())
2498
+ sage: E.multiplication_by_m(p * 2)[0] == E.multiplication_by_m(p * 2, x_only=True)
2499
+ True
2500
+ """
2501
+ # Coerce the input m to be an integer
2502
+ m = Integer(m)
2503
+ p = self.base_ring().characteristic()
2504
+
2505
+ if m == 0:
2506
+ raise ValueError("m must be a nonzero integer")
2507
+
2508
+ if x_only:
2509
+ x = polygen(self.base_ring(), 'x')
2510
+ else:
2511
+ from sage.rings.finite_rings.finite_field_base import FiniteField as FiniteField_generic
2512
+ if p != 0 and m % p == 0 and not isinstance(self.base_ring(), FiniteField_generic):
2513
+ # TODO: Implement the correct formula?
2514
+ raise NotImplementedError("multiplication by integer not coprime to p "
2515
+ "is only implemented for curves over finite fields")
2516
+ x, y = polygens(self.base_ring(), 'x,y')
2517
+
2518
+ # Special case of multiplication by 1 is easy.
2519
+ if m == 1:
2520
+ if not x_only:
2521
+ return (x, y)
2522
+ else:
2523
+ return x
2524
+
2525
+ # Grab curve invariants
2526
+ a1, _, a3, _, _ = self.a_invariants()
2527
+
2528
+ if m == -1:
2529
+ if not x_only:
2530
+ return (x, -y-a1*x-a3)
2531
+ else:
2532
+ return x
2533
+
2534
+ # If we only require the x coordinate, it is faster to use the recursive formula
2535
+ # since substituting polynomials is quite slow.
2536
+ v_p = 0 if p == 0 else valuation(m, p)
2537
+ if not x_only:
2538
+ m //= p**v_p
2539
+
2540
+ # the x-coordinate does not depend on the sign of m. The work
2541
+ # here is done by functions defined earlier:
2542
+
2543
+ mx = (x.parent()(self._multiple_x_numerator(m.abs(), x))
2544
+ / x.parent()(self._multiple_x_denominator(m.abs(), x)))
2545
+
2546
+ if x_only:
2547
+ return mx
2548
+
2549
+ # Consideration of the invariant differential
2550
+ # w=dx/(2*y+a1*x+a3) shows that m*w = d(mx)/(2*my+a1*mx+a3)
2551
+ # and hence 2*my+a1*mx+a3 = (1/m)*(2*y+a1*x+a3)*d(mx)/dx
2552
+ my = ((2*y+a1*x+a3)*mx.derivative(x)/m - a1*mx-a3)/2
2553
+
2554
+ if v_p > 0:
2555
+ isog = self.multiplication_by_p_isogeny()**v_p
2556
+ fx, fy = isog.rational_maps()
2557
+ # slow...
2558
+ mx = mx.subs(x=fx)
2559
+ my = my.subs(x=fx, y=fy)
2560
+
2561
+ return mx, my
2562
+
2563
+ def scalar_multiplication(self, m):
2564
+ r"""
2565
+ Return the scalar-multiplication map `[m]` on this elliptic
2566
+ curve as a
2567
+ :class:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar`
2568
+ object.
2569
+
2570
+ EXAMPLES::
2571
+
2572
+ sage: E = EllipticCurve('77a1')
2573
+ sage: m = E.scalar_multiplication(-7); m
2574
+ Scalar-multiplication endomorphism [-7]
2575
+ of Elliptic Curve defined by y^2 + y = x^3 + 2*x over Rational Field
2576
+ sage: m.degree()
2577
+ 49
2578
+ sage: P = E(2,3)
2579
+ sage: m(P)
2580
+ (-26/225 : -2132/3375 : 1)
2581
+ sage: m.rational_maps() == E.multiplication_by_m(-7)
2582
+ True
2583
+
2584
+ ::
2585
+
2586
+ sage: E = EllipticCurve('11a1')
2587
+ sage: E.scalar_multiplication(7)
2588
+ Scalar-multiplication endomorphism [7]
2589
+ of Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
2590
+
2591
+ TESTS:
2592
+
2593
+ Tests for :issue:`32490`::
2594
+
2595
+ sage: E = EllipticCurve(QQbar, [1,0]) # needs sage.rings.number_field
2596
+ sage: E.scalar_multiplication(1).rational_maps() # needs sage.rings.number_field
2597
+ (x, y)
2598
+
2599
+ ::
2600
+
2601
+ sage: E = EllipticCurve_from_j(GF(31337).random_element()) # needs sage.rings.finite_rings
2602
+ sage: P = E.random_point() # needs sage.rings.finite_rings
2603
+ sage: [E.scalar_multiplication(m)(P) == m*P for m in (1,2,3,5,7,9)] # needs sage.rings.finite_rings
2604
+ [True, True, True, True, True, True]
2605
+
2606
+ ::
2607
+
2608
+ sage: E = EllipticCurve('99.a1')
2609
+ sage: E.scalar_multiplication(5)
2610
+ Scalar-multiplication endomorphism [5]
2611
+ of Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 17*x + 30 over Rational Field
2612
+ sage: E.scalar_multiplication(2).rational_maps()
2613
+ ((x^4 + 33*x^2 - 242*x + 363)/(4*x^3 - 3*x^2 - 66*x + 121),
2614
+ (-4*x^7 + 8*x^6*y - 28*x^6 - 12*x^5*y - 420*x^5 - 660*x^4*y + 5020*x^4 + 4840*x^3*y - 7568*x^3 - 14520*x^2*y - 42108*x^2 + 20328*x*y + 143264*x - 10648*y - 122452)/(64*x^6 - 96*x^5 - 2076*x^4 + 5456*x^3 + 14520*x^2 - 63888*x + 58564))
2615
+ """
2616
+ from sage.schemes.elliptic_curves.hom_scalar import EllipticCurveHom_scalar
2617
+ return EllipticCurveHom_scalar(self, m)
2618
+
2619
+ def frobenius_isogeny(self, n=1):
2620
+ r"""
2621
+ Return the `n`-power Frobenius isogeny from this curve to
2622
+ its Galois conjugate.
2623
+
2624
+ The Frobenius *endo*\morphism is the special case where `n`
2625
+ is divisible by the degree of the base ring of the curve.
2626
+
2627
+ .. SEEALSO::
2628
+
2629
+ :meth:`~sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field.frobenius_endomorphism`
2630
+
2631
+ EXAMPLES::
2632
+
2633
+ sage: # needs sage.rings.finite_rings
2634
+ sage: z3, = GF(13^3).gens()
2635
+ sage: E = EllipticCurve([z3, z3^2])
2636
+ sage: E.frobenius_isogeny()
2637
+ Frobenius isogeny of degree 13:
2638
+ From: Elliptic Curve defined by y^2 = x^3 + z3*x + z3^2
2639
+ over Finite Field in z3 of size 13^3
2640
+ To: Elliptic Curve defined by y^2 = x^3 + (5*z3^2+7*z3+11)*x + (5*z3^2+12*z3+1)
2641
+ over Finite Field in z3 of size 13^3
2642
+ sage: E.frobenius_isogeny(3)
2643
+ Frobenius endomorphism of degree 2197 = 13^3:
2644
+ From: Elliptic Curve defined by y^2 = x^3 + z3*x + z3^2
2645
+ over Finite Field in z3 of size 13^3
2646
+ To: Elliptic Curve defined by y^2 = x^3 + z3*x + z3^2
2647
+ over Finite Field in z3 of size 13^3
2648
+ """
2649
+ p = self.base_ring().characteristic()
2650
+ if not p:
2651
+ raise ValueError('Frobenius isogeny only exists in positive characteristic')
2652
+ from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius
2653
+ return EllipticCurveHom_frobenius(self, n)
2654
+
2655
+ def identity_morphism(self):
2656
+ r"""
2657
+ Return the identity endomorphism of this elliptic curve
2658
+ as an :class:`EllipticCurveHom` object.
2659
+
2660
+ EXAMPLES::
2661
+
2662
+ sage: E = EllipticCurve(j=42)
2663
+ sage: E.identity_morphism()
2664
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + 5901*x + 1105454 over Rational Field
2665
+ Via: (u,r,s,t) = (1, 0, 0, 0)
2666
+ sage: E.identity_morphism() == E.scalar_multiplication(1)
2667
+ True
2668
+ """
2669
+ from sage.schemes.elliptic_curves.weierstrass_morphism import identity_morphism
2670
+ return identity_morphism(self)
2671
+
2672
+ def isomorphism_to(self, other):
2673
+ """
2674
+ Given another weierstrass model ``other`` of ``self``, return an
2675
+ isomorphism from ``self`` to ``other``.
2676
+
2677
+ INPUT:
2678
+
2679
+ - ``other`` -- an elliptic curve isomorphic to ``self``
2680
+
2681
+ OUTPUT:
2682
+
2683
+ (Weierstrassmorphism) An isomorphism from ``self`` to ``other``.
2684
+
2685
+ .. NOTE::
2686
+
2687
+ If the curves in question are not isomorphic, a :exc:`ValueError`
2688
+ is raised.
2689
+
2690
+ EXAMPLES::
2691
+
2692
+ sage: E = EllipticCurve('37a')
2693
+ sage: F = E.short_weierstrass_model()
2694
+ sage: w = E.isomorphism_to(F); w
2695
+ Elliptic-curve morphism:
2696
+ From: Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2697
+ To: Elliptic Curve defined by y^2 = x^3 - 16*x + 16 over Rational Field
2698
+ Via: (u,r,s,t) = (1/2, 0, 0, -1/2)
2699
+ sage: P = E(0,-1,1)
2700
+ sage: w(P)
2701
+ (0 : -4 : 1)
2702
+ sage: w(5*P)
2703
+ (1 : 1 : 1)
2704
+ sage: 5*w(P)
2705
+ (1 : 1 : 1)
2706
+ sage: 120*w(P) == w(120*P)
2707
+ True
2708
+
2709
+ We can also handle injections to different base rings::
2710
+
2711
+ sage: x = polygen(ZZ, 'x')
2712
+ sage: K.<a> = NumberField(x^3 - 7) # needs sage.rings.number_field
2713
+ sage: E.isomorphism_to(E.change_ring(K)) # needs sage.rings.number_field
2714
+ Elliptic-curve morphism:
2715
+ From: Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2716
+ To: Elliptic Curve defined by y^2 + y = x^3 + (-1)*x
2717
+ over Number Field in a with defining polynomial x^3 - 7
2718
+ Via: (u,r,s,t) = (1, 0, 0, 0)
2719
+ """
2720
+ return wm.WeierstrassIsomorphism(self, None, other)
2721
+
2722
+ def automorphisms(self, field=None):
2723
+ """
2724
+ Return the set of isomorphisms from ``self`` to itself (as a list).
2725
+
2726
+ The identity and negation morphisms are guaranteed to appear
2727
+ as the first and second entry of the returned list.
2728
+
2729
+ INPUT:
2730
+
2731
+ - ``field`` -- (default: ``None``) a field into which the
2732
+ coefficients of the curve may be coerced (by default, uses
2733
+ the base field of the curve)
2734
+
2735
+ OUTPUT:
2736
+
2737
+ A list of :class:`~wm.WeierstrassIsomorphism` objects
2738
+ consisting of all the isomorphisms from the curve ``self`` to
2739
+ itself defined over ``field``.
2740
+
2741
+ EXAMPLES::
2742
+
2743
+ sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
2744
+ sage: E.automorphisms()
2745
+ [Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2746
+ over Rational Field
2747
+ Via: (u,r,s,t) = (1, 0, 0, 0),
2748
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2749
+ over Rational Field
2750
+ Via: (u,r,s,t) = (-1, 0, 0, -1)]
2751
+
2752
+ We can also find automorphisms defined over extension fields::
2753
+
2754
+ sage: x = polygen(ZZ, 'x')
2755
+ sage: K.<a> = NumberField(x^2 + 3) # adjoin roots of unity # needs sage.rings.number_field
2756
+ sage: E.automorphisms(K) # needs sage.rings.number_field
2757
+ [Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2758
+ over Number Field in a with defining polynomial x^2 + 3
2759
+ Via: (u,r,s,t) = (1, 0, 0, 0),
2760
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2761
+ over Number Field in a with defining polynomial x^2 + 3
2762
+ Via: (u,r,s,t) = (-1, 0, 0, -1),
2763
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2764
+ over Number Field in a with defining polynomial x^2 + 3
2765
+ Via: (u,r,s,t) = (-1/2*a - 1/2, 0, 0, 0),
2766
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2767
+ over Number Field in a with defining polynomial x^2 + 3
2768
+ Via: (u,r,s,t) = (1/2*a + 1/2, 0, 0, -1),
2769
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2770
+ over Number Field in a with defining polynomial x^2 + 3
2771
+ Via: (u,r,s,t) = (1/2*a - 1/2, 0, 0, 0),
2772
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2773
+ over Number Field in a with defining polynomial x^2 + 3
2774
+ Via: (u,r,s,t) = (-1/2*a + 1/2, 0, 0, -1)]
2775
+
2776
+ ::
2777
+
2778
+ sage: [len(EllipticCurve_from_j(GF(q,'a')(0)).automorphisms()) # needs sage.rings.finite_rings
2779
+ ....: for q in [2,4,3,9,5,25,7,49]]
2780
+ [2, 24, 2, 12, 2, 6, 6, 6]
2781
+
2782
+ TESTS:
2783
+
2784
+ Random testing::
2785
+
2786
+ sage: # needs sage.rings.finite_rings
2787
+ sage: p = random_prime(100)
2788
+ sage: k = randrange(1,30)
2789
+ sage: F.<t> = GF((p,k))
2790
+ sage: while True:
2791
+ ....: try:
2792
+ ....: E = EllipticCurve(list((F^5).random_element()))
2793
+ ....: except ArithmeticError:
2794
+ ....: continue
2795
+ ....: break
2796
+ sage: Aut = E.automorphisms()
2797
+ sage: Aut[0] == E.scalar_multiplication(1)
2798
+ True
2799
+ sage: Aut[1] == E.scalar_multiplication(-1)
2800
+ True
2801
+ sage: sorted(Aut) == Aut
2802
+ True
2803
+ """
2804
+ if field is not None:
2805
+ self = self.change_ring(field)
2806
+ return self.isomorphisms(self)
2807
+
2808
+ def isomorphisms(self, other, field=None):
2809
+ """
2810
+ Return the set of isomorphisms from ``self`` to ``other`` (as a list).
2811
+
2812
+ INPUT:
2813
+
2814
+ - ``other`` -- another elliptic curve
2815
+
2816
+ - ``field`` -- (default: ``None``) a field into which the
2817
+ coefficients of the curves may be coerced (by default, uses
2818
+ the base field of the curves)
2819
+
2820
+ OUTPUT:
2821
+
2822
+ A list of :class:`~wm.WeierstrassIsomorphism` objects consisting of all
2823
+ the isomorphisms from the curve ``self`` to the curve
2824
+ ``other`` defined over ``field``.
2825
+
2826
+ EXAMPLES::
2827
+
2828
+ sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
2829
+ sage: F = EllipticCurve('27a3') # should be the same one
2830
+ sage: E.isomorphisms(F)
2831
+ [Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2832
+ over Rational Field
2833
+ Via: (u,r,s,t) = (1, 0, 0, 0),
2834
+ Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3
2835
+ over Rational Field
2836
+ Via: (u,r,s,t) = (-1, 0, 0, -1)]
2837
+
2838
+ We can also find isomorphisms defined over extension fields::
2839
+
2840
+ sage: # needs sage.rings.finite_rings
2841
+ sage: E = EllipticCurve(GF(7), [0,0,0,1,1])
2842
+ sage: F = EllipticCurve(GF(7), [0,0,0,1,-1])
2843
+ sage: E.isomorphisms(F)
2844
+ []
2845
+ sage: E.isomorphisms(F, GF(49,'a'))
2846
+ [Elliptic-curve morphism:
2847
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1
2848
+ over Finite Field in a of size 7^2
2849
+ To: Elliptic Curve defined by y^2 = x^3 + x + 6
2850
+ over Finite Field in a of size 7^2
2851
+ Via: (u,r,s,t) = (a + 3, 0, 0, 0),
2852
+ Elliptic-curve morphism:
2853
+ From: Elliptic Curve defined by y^2 = x^3 + x + 1
2854
+ over Finite Field in a of size 7^2
2855
+ To: Elliptic Curve defined by y^2 = x^3 + x + 6
2856
+ over Finite Field in a of size 7^2
2857
+ Via: (u,r,s,t) = (6*a + 4, 0, 0, 0)]
2858
+ """
2859
+ if field is not None:
2860
+ self = self.change_ring(field)
2861
+ other = other.change_ring(field)
2862
+ return sorted(wm.WeierstrassIsomorphism(self, urst, other)
2863
+ for urst in wm._isomorphisms(self, other))
2864
+
2865
+ def is_isomorphic(self, other, field=None):
2866
+ """
2867
+ Return whether or not ``self`` is isomorphic to ``other``.
2868
+
2869
+ INPUT:
2870
+
2871
+ - ``other`` -- another elliptic curve
2872
+
2873
+ - ``field`` -- (default: ``None``) a field into which the
2874
+ coefficients of the curves may be coerced (by default, uses
2875
+ the base field of the curves).
2876
+
2877
+ OUTPUT:
2878
+
2879
+ boolean; ``True`` if there is an isomorphism from curve ``self`` to
2880
+ curve ``other`` defined over ``field``.
2881
+
2882
+ EXAMPLES::
2883
+
2884
+ sage: E = EllipticCurve('389a')
2885
+ sage: F = E.change_weierstrass_model([2,3,4,5]); F
2886
+ Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 3/2*x^2 - 13/16*x
2887
+ over Rational Field
2888
+ sage: E.is_isomorphic(F)
2889
+ True
2890
+ sage: E.is_isomorphic(F.change_ring(CC))
2891
+ False
2892
+ """
2893
+ if not isinstance(other, EllipticCurve_generic):
2894
+ return False
2895
+ if field is None:
2896
+ if self.base_ring() != other.base_ring():
2897
+ return False
2898
+ else:
2899
+ self = self.base_extend(field)
2900
+ other = other.base_extend(field)
2901
+ if self.j_invariant() != other.j_invariant(): # easy check
2902
+ return False
2903
+ try:
2904
+ next(wm._isomorphisms(self, other))
2905
+ except StopIteration:
2906
+ return False
2907
+ return True
2908
+
2909
+ def change_weierstrass_model(self, *urst):
2910
+ r"""
2911
+ Return a new Weierstrass model of ``self`` under the standard
2912
+ transformation `(u,r,s,t)`.
2913
+
2914
+ .. MATH::
2915
+
2916
+ (x,y) \mapsto (x',y') = (u^2x + r , u^3y + su^2x + t).
2917
+
2918
+ EXAMPLES::
2919
+
2920
+ sage: E = EllipticCurve('15a')
2921
+ sage: F1 = E.change_weierstrass_model([1/2,0,0,0]); F1
2922
+ Elliptic Curve defined by y^2 + 2*x*y + 8*y = x^3 + 4*x^2 - 160*x - 640
2923
+ over Rational Field
2924
+ sage: F2 = E.change_weierstrass_model([7,2,1/3,5]); F2
2925
+ Elliptic Curve defined by
2926
+ y^2 + 5/21*x*y + 13/343*y = x^3 + 59/441*x^2 - 10/7203*x - 58/117649
2927
+ over Rational Field
2928
+ sage: F1.is_isomorphic(F2)
2929
+ True
2930
+ """
2931
+ if isinstance(urst[0], (tuple, list)):
2932
+ urst = urst[0]
2933
+ return constructor.EllipticCurve((wm.baseWI(*urst))(self.ainvs()))
2934
+
2935
+ def short_weierstrass_model(self, complete_cube=True):
2936
+ """
2937
+ Return a short Weierstrass model for ``self``.
2938
+
2939
+ INPUT:
2940
+
2941
+ - ``complete_cube`` -- boolean (default: ``True``); for
2942
+ meaning, see below
2943
+
2944
+ OUTPUT: an elliptic curve
2945
+
2946
+ If ``complete_cube=True``: Return a model of the form
2947
+ `y^2 = x^3 + a*x + b` for this curve. The characteristic
2948
+ must not be 2; in characteristic 3, it is only possible if `b_2=0`.
2949
+
2950
+ If ``complete_cube=False``: Return a model of the form
2951
+ `y^2 = x^3 + ax^2 + bx + c` for this curve. The
2952
+ characteristic must not be 2.
2953
+
2954
+ EXAMPLES::
2955
+
2956
+ sage: E = EllipticCurve([1,2,3,4,5])
2957
+ sage: E
2958
+ Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
2959
+ sage: F = E.short_weierstrass_model()
2960
+ sage: F
2961
+ Elliptic Curve defined by y^2 = x^3 + 4941*x + 185166 over Rational Field
2962
+ sage: E.is_isomorphic(F)
2963
+ True
2964
+ sage: F = E.short_weierstrass_model(complete_cube=False)
2965
+ sage: F
2966
+ Elliptic Curve defined by y^2 = x^3 + 9*x^2 + 88*x + 464 over Rational Field
2967
+ sage: E.is_isomorphic(F)
2968
+ True
2969
+
2970
+ ::
2971
+
2972
+ sage: E = EllipticCurve(GF(3), [1,2,3,4,5])
2973
+ sage: E.short_weierstrass_model(complete_cube=False)
2974
+ Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3
2975
+
2976
+ This used to be different see :issue:`3973`::
2977
+
2978
+ sage: E.short_weierstrass_model()
2979
+ Elliptic Curve defined by y^2 = x^3 + x + 2 over Finite Field of size 3
2980
+
2981
+ More tests in characteristic 3::
2982
+
2983
+ sage: E = EllipticCurve(GF(3), [0,2,1,2,1])
2984
+ sage: E.short_weierstrass_model()
2985
+ Traceback (most recent call last):
2986
+ ...
2987
+ ValueError: short_weierstrass_model(): no short model for Elliptic Curve
2988
+ defined by y^2 + y = x^3 + 2*x^2 + 2*x + 1 over Finite Field of size 3
2989
+ (characteristic is 3)
2990
+ sage: E.short_weierstrass_model(complete_cube=False)
2991
+ Elliptic Curve defined by y^2 = x^3 + 2*x^2 + 2*x + 2
2992
+ over Finite Field of size 3
2993
+ sage: E.short_weierstrass_model(complete_cube=False).is_isomorphic(E)
2994
+ True
2995
+ """
2996
+ from . import constructor
2997
+ K = self.base_ring()
2998
+
2999
+ # any curve of the form y^2 = x^3 +.. is singular in characteristic 2
3000
+ if K.characteristic() == 2:
3001
+ raise ValueError("short_weierstrass_model(): no short model for %s (characteristic is %s)" % (self, K.characteristic()))
3002
+
3003
+ # in characteristic 3 we can complete the square but we can only complete the cube if b2 is 0
3004
+ if K.characteristic() == 3:
3005
+ b2, b4, b6,_ = self.b_invariants()
3006
+ if complete_cube and b2 != 0:
3007
+ raise ValueError("short_weierstrass_model(): no short model for %s (characteristic is %s)" % (self,K.characteristic()))
3008
+ else:
3009
+ return constructor.EllipticCurve([0,b2,0,8*b4,16*b6])
3010
+
3011
+ a1,a2,a3,_,_ = self.a_invariants()
3012
+ if complete_cube:
3013
+ if a1 == 0 and a2 == 0 and a3 == 0:
3014
+ return self
3015
+ else:
3016
+ b2, b4, b6, _ = self.b_invariants()
3017
+ if b2 == 0:
3018
+ return constructor.EllipticCurve([0,0,0,8*b4,16*b6])
3019
+ else:
3020
+ c4, c6 = self.c_invariants()
3021
+ return constructor.EllipticCurve([0,0,0,-27*c4, -54*c6])
3022
+ else:
3023
+ if a1 == 0 and a3 == 0:
3024
+ return self
3025
+ else:
3026
+ b2, b4, b6, _ = self.b_invariants()
3027
+ return constructor.EllipticCurve([0,b2,0,8*b4,16*b6])
3028
+
3029
+ def montgomery_model(self, twisted=False, morphism=False):
3030
+ r"""
3031
+ Return a (twisted or untwisted) Montgomery model for this
3032
+ elliptic curve, if possible.
3033
+
3034
+ A Montgomery curve is a smooth projective curve of the form
3035
+
3036
+ .. MATH::
3037
+
3038
+ BY^2 = X^3 + AX^2 + X.
3039
+
3040
+ The Montgomery curve is called *untwisted* if `B=1`.
3041
+
3042
+ INPUT:
3043
+
3044
+ - ``twisted`` -- boolean (default: ``False``); allow `B \neq 1`
3045
+
3046
+ - ``morphism`` -- boolean (default: ``False``); also return an
3047
+ isomorphism from this curve to the computed Montgomery model
3048
+
3049
+ OUTPUT:
3050
+
3051
+ If ``twisted`` is ``False`` (the default), an
3052
+ :class:`EllipticCurve_generic` object encapsulating an untwisted
3053
+ Montgomery curve. Otherwise, a
3054
+ :class:`~sage.schemes.curves.projective_curve.ProjectivePlaneCurve`
3055
+ object encapsulating a (potentially twisted) Montgomery curve.
3056
+
3057
+ If ``morphism`` is ``True``, this method returns a tuple consisting of
3058
+ such a curve together with an isomorphism of suitable type (either
3059
+ :class:`~sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism`
3060
+ or
3061
+ :class:`~sage.schemes.elliptic_curves.weierstrass_transform.WeierstrassTransformationWithInverse`)
3062
+ from this curve to the Montgomery model.
3063
+
3064
+ EXAMPLES::
3065
+
3066
+ sage: E = EllipticCurve(QQbar, '11a1') # needs sage.rings.number_field
3067
+ sage: E.montgomery_model() # needs sage.rings.number_field
3068
+ Elliptic Curve defined by y^2 = x^3 + (-1.953522420987248?)*x^2 + x
3069
+ over Algebraic Field
3070
+
3071
+ ::
3072
+
3073
+ sage: E = EllipticCurve(GF(431^2), [7,7]) # needs sage.rings.finite_rings
3074
+ sage: E.montgomery_model() # needs sage.rings.finite_rings
3075
+ Elliptic Curve defined by y^2 = x^3 + (51*z2+190)*x^2 + x
3076
+ over Finite Field in z2 of size 431^2
3077
+
3078
+ An isomorphism between the Montgomery and Weierstrass form can
3079
+ be obtained using the ``morphism`` parameter::
3080
+
3081
+ sage: E.montgomery_model(morphism=True) # needs sage.rings.finite_rings
3082
+ (Elliptic Curve defined by y^2 = x^3 + (51*z2+190)*x^2 + x
3083
+ over Finite Field in z2 of size 431^2,
3084
+ Elliptic-curve morphism:
3085
+ From: Elliptic Curve defined by y^2 = x^3 + 7*x + 7
3086
+ over Finite Field in z2 of size 431^2
3087
+ To: Elliptic Curve defined by y^2 = x^3 + (51*z2+190)*x^2 + x
3088
+ over Finite Field in z2 of size 431^2
3089
+ Via: (u,r,s,t) = (64*z2 + 407, 159, 0, 0))
3090
+
3091
+ Not all elliptic curves have a Montgomery model over their field
3092
+ of definition::
3093
+
3094
+ sage: E = EllipticCurve(GF(257), [1,1])
3095
+ sage: E.montgomery_model()
3096
+ Traceback (most recent call last):
3097
+ ...
3098
+ ValueError: Elliptic Curve defined by y^2 = x^3 + x + 1
3099
+ over Finite Field of size 257 has no Montgomery model
3100
+
3101
+ ::
3102
+
3103
+ sage: E = EllipticCurve(GF(257), [10,10])
3104
+ sage: E.montgomery_model()
3105
+ Traceback (most recent call last):
3106
+ ...
3107
+ ValueError: Elliptic Curve defined by y^2 = x^3 + 10*x + 10
3108
+ over Finite Field of size 257 has no untwisted Montgomery model
3109
+
3110
+ However, as hinted by the error message, the latter curve does
3111
+ admit a *twisted* Montgomery model, which can be computed by
3112
+ passing ``twisted=True``::
3113
+
3114
+ sage: E.montgomery_model(twisted=True)
3115
+ Projective Plane Curve over Finite Field of size 257
3116
+ defined by -x^3 + 8*x^2*z - 127*y^2*z - x*z^2
3117
+
3118
+ Since Sage internally represents elliptic curves as (long) Weierstrass
3119
+ curves, which do not feature the Montgomery `B` coefficient, the
3120
+ returned curve in this case is merely a
3121
+ :class:`~sage.schemes.curves.projective_curve.ProjectivePlaneCurve`
3122
+ rather than the usual :class:`EllipticCurve_generic`.
3123
+
3124
+ Arithmetic on curves of this type is not implemented natively,
3125
+ but can easily be emulated by mapping back and forth to the
3126
+ corresponding Weierstrass curve::
3127
+
3128
+ sage: C, f = E.montgomery_model(twisted=True, morphism=True)
3129
+ sage: f
3130
+ Scheme morphism:
3131
+ From: Elliptic Curve defined by y^2 = x^3 + 10*x + 10
3132
+ over Finite Field of size 257
3133
+ To: Projective Plane Curve over Finite Field of size 257
3134
+ defined by -x^3 + 8*x^2*z - 127*y^2*z - x*z^2
3135
+ Defn: Defined on coordinates by sending (x : y : z) to
3136
+ (x + 116*z : -y : -85*z)
3137
+ sage: g = f.inverse(); g
3138
+ Scheme morphism:
3139
+ From: Projective Plane Curve over Finite Field of size 257
3140
+ defined by -x^3 + 8*x^2*z - 127*y^2*z - x*z^2
3141
+ To: Elliptic Curve defined by y^2 = x^3 + 10*x + 10
3142
+ over Finite Field of size 257
3143
+ Defn: Defined on coordinates by sending (x : y : z) to
3144
+ (-85*x - 116*z : 85*y : z)
3145
+ sage: P = C(70, 8)
3146
+ sage: Q = C(17, 17)
3147
+ sage: P + Q # this doesn't work...
3148
+ Traceback (most recent call last):
3149
+ ...
3150
+ TypeError: unsupported operand parent(s) for +: ...
3151
+ sage: f(g(P) + g(Q)) # ...but this does
3152
+ (107 : 168 : 1)
3153
+
3154
+ Using the fact that the Weil pairing satisfies `e(\psi(P),\psi(Q)) =
3155
+ e(P,Q)^{\deg\psi}`, even pairings can be emulated in this way (note
3156
+ that isomorphisms have degree `1`)::
3157
+
3158
+ sage: # needs sage.rings.finite_rings
3159
+ sage: F.<z2> = GF(257^2)
3160
+ sage: C_ = C.change_ring(F)
3161
+ sage: g_ = g.change_ring(F)
3162
+ sage: g_(P).order()
3163
+ 12
3164
+ sage: T = C_(-7 * z2 - 57, 31 * z2 - 52, 1)
3165
+ sage: g_(T).order()
3166
+ 12
3167
+ sage: g_(P).weil_pairing(g_(T), 12)
3168
+ 15*z2 + 204
3169
+
3170
+ Another alternative is to simply extend the base field enough
3171
+ for the curve to have an untwisted Montgomery model::
3172
+
3173
+ sage: C_ = E.change_ring(F).montgomery_model(); C_ # needs sage.rings.finite_rings
3174
+ Elliptic Curve defined by y^2 = x^3 + 249*x^2 + x
3175
+ over Finite Field in z2 of size 257^2
3176
+ sage: h = C.defining_polynomial().change_ring(F); h # needs sage.rings.finite_rings
3177
+ -x^3 + 8*x^2*z - 127*y^2*z - x*z^2
3178
+ sage: C_.is_isomorphic(EllipticCurve_from_cubic(h).codomain()) # needs sage.rings.finite_rings
3179
+ True
3180
+
3181
+ .. SEEALSO::
3182
+
3183
+ The inverse conversion --- computing a Weierstrass model for a
3184
+ given Montgomery curve --- can be performed using
3185
+ :func:`~sage.schemes.elliptic_curves.constructor.EllipticCurve_from_cubic`.
3186
+
3187
+ ALGORITHM: [CS2018]_, §2.4
3188
+
3189
+ REFERENCES:
3190
+
3191
+ - Original publication: [Mont1987]_, §10.3.1
3192
+ - More recent survey article: [CS2018]_
3193
+ """
3194
+ Ew = self.short_weierstrass_model()
3195
+ _, _, _, a, b = Ew.a_invariants()
3196
+
3197
+ R = self.base_ring()
3198
+ P = PolynomialRing(R, 'v')
3199
+
3200
+ sols = []
3201
+ for r in P([b, a, 0, 1]).roots(multiplicities=False):
3202
+ for s in P([3 * r**2 + a, 0, -1]).roots(multiplicities=False):
3203
+ sols.append((r,s))
3204
+
3205
+ if not sols:
3206
+ raise ValueError(f'{self} has no Montgomery model')
3207
+
3208
+ # square s allows us to take B=1
3209
+ r,s = max(sols, key=lambda t: t[1].is_square())
3210
+
3211
+ A = 3 * r / s
3212
+ B = R.one() if s.is_square() else ~s
3213
+
3214
+ if not twisted:
3215
+ if B != 1:
3216
+ raise ValueError(f'{self} has no untwisted Montgomery model')
3217
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
3218
+ E = EllipticCurve([0, A, 0, 1, 0])
3219
+ if morphism:
3220
+ return E, self.isomorphism_to(E)
3221
+ return E
3222
+
3223
+ P2, (x, y, z) = self.ambient_space().objgens()
3224
+ f = B * y**2*z - x * (x * (x + A*z) + z**2)
3225
+ C = plane_curve.ProjectivePlaneCurve(P2, f)
3226
+
3227
+ if not morphism:
3228
+ return C
3229
+
3230
+ t = ~(B * s).sqrt()
3231
+ iso_maps = (x - r * z, t * y, s * z)
3232
+ inv_maps = (x * s + r * z, s * y / t, z)
3233
+
3234
+ w = self.isomorphism_to(Ew)
3235
+ wmap, winv = w.rational_maps(), (~w).rational_maps()
3236
+ wmap, winv = (tuple(f(x, y) for f in fs) + (z,) for fs in (wmap, winv))
3237
+
3238
+ iso = [f(*wmap) for f in iso_maps]
3239
+ inv = [f(*inv_maps) for f in winv]
3240
+
3241
+ from sage.schemes.elliptic_curves.weierstrass_transform \
3242
+ import WeierstrassTransformationWithInverse as WTI
3243
+ iso = WTI(self, C, iso, 1, inv, s**-3)
3244
+ return C, iso
3245
+
3246
+ def plot(self, xmin=None, xmax=None, components='both', **args):
3247
+ """
3248
+ Draw a graph of this elliptic curve.
3249
+
3250
+ The plot method is only implemented when there is a natural coercion
3251
+ from the base ring of ``self`` to ``RR``. In this case, ``self`` is
3252
+ plotted as if it was defined over ``RR``.
3253
+
3254
+ INPUT:
3255
+
3256
+ - ``xmin``, ``xmax`` -- (optional) points will be computed at
3257
+ least within this range, but possibly farther
3258
+
3259
+ - ``components`` -- string; one of the following:
3260
+
3261
+ - ``both`` -- (default), scale so that both bounded and
3262
+ unbounded components appear
3263
+
3264
+ - ``bounded`` -- scale the plot to show the bounded
3265
+ component. Raises an error if there is only one real
3266
+ component.
3267
+
3268
+ - ``unbounded`` -- scale the plot to show the unbounded
3269
+ component, including the two flex points
3270
+
3271
+ - ``plot_points`` -- passed to
3272
+ :func:`sage.plot.generate_plot_points`
3273
+
3274
+ - ``adaptive_tolerance`` -- passed to
3275
+ :func:`sage.plot.generate_plot_points`
3276
+
3277
+ - ``adaptive_recursion`` -- passed to
3278
+ :func:`sage.plot.generate_plot_points`
3279
+
3280
+ - ``randomize`` -- passed to
3281
+ :func:`sage.plot.generate_plot_points`
3282
+
3283
+ - ``**args`` -- all other options are passed to
3284
+ :class:`sage.plot.line.Line`
3285
+
3286
+ EXAMPLES::
3287
+
3288
+ sage: E = EllipticCurve([0, -1])
3289
+ sage: plot(E, rgbcolor=hue(0.7)) # needs sage.plot
3290
+ Graphics object consisting of 1 graphics primitive
3291
+ sage: E = EllipticCurve('37a')
3292
+ sage: plot(E) # needs sage.plot
3293
+ Graphics object consisting of 2 graphics primitives
3294
+ sage: plot(E, xmin=25, xmax=26) # needs sage.plot
3295
+ Graphics object consisting of 2 graphics primitives
3296
+
3297
+ With :issue:`12766` we added the components keyword::
3298
+
3299
+ sage: E.real_components()
3300
+ 2
3301
+ sage: E.plot(components='bounded') # needs sage.plot
3302
+ Graphics object consisting of 1 graphics primitive
3303
+ sage: E.plot(components='unbounded') # needs sage.plot
3304
+ Graphics object consisting of 1 graphics primitive
3305
+
3306
+ If there is only one component then specifying
3307
+ components='bounded' raises a ValueError::
3308
+
3309
+ sage: E = EllipticCurve('9990be2')
3310
+ sage: E.plot(components='bounded') # needs sage.plot
3311
+ Traceback (most recent call last):
3312
+ ...
3313
+ ValueError: no bounded component for this curve
3314
+
3315
+ An elliptic curve defined over the Complex Field can not be plotted::
3316
+
3317
+ sage: E = EllipticCurve(CC, [0,0,1,-1,0])
3318
+ sage: E.plot() # needs sage.plot
3319
+ Traceback (most recent call last):
3320
+ ...
3321
+ NotImplementedError: plotting of curves over Complex Field
3322
+ with 53 bits of precision is not implemented yet
3323
+ """
3324
+ RR = RealField()
3325
+ K = self.base_ring()
3326
+ if not RR.has_coerce_map_from(K):
3327
+ raise NotImplementedError("plotting of curves over %s is not implemented yet" % K)
3328
+ if components not in ['both', 'bounded', 'unbounded']:
3329
+ raise ValueError("component must be one of 'both', 'bounded' or 'unbounded'")
3330
+
3331
+ a1, a2, a3, a4, a6 = self.ainvs()
3332
+ d = self.division_polynomial(2)
3333
+
3334
+ def f1(z):
3335
+ # Internal function for plotting first branch of the curve
3336
+ return (-(a1*z + a3) + sqrt(abs(d(z))))/2
3337
+
3338
+ def f2(z):
3339
+ # Internal function for plotting second branch of the curve
3340
+ return (-(a1*z + a3) - sqrt(abs(d(z))))/2
3341
+
3342
+ r = sorted(d.roots(RR, multiplicities=False))
3343
+ if components == 'bounded' and len(r) == 1:
3344
+ raise ValueError("no bounded component for this curve")
3345
+ if isinstance(xmin, (tuple, list)):
3346
+ if xmax is not None:
3347
+ raise ValueError("xmax must be None if xmin is a tuple")
3348
+ if len(xmin) != 2:
3349
+ raise ValueError("if xmin is a tuple it must have length 2")
3350
+ xmin, xmax = xmin
3351
+ if xmin is None or xmax is None:
3352
+ xmins = []
3353
+ xmaxs = []
3354
+ if components in ['both','bounded'] and len(r) > 1:
3355
+ xmins.append(r[0])
3356
+ xmaxs.append(r[1])
3357
+
3358
+ # The following 3 is an aesthetic choice. It's possible
3359
+ # that we should compute both of the following when
3360
+ # components=='both' and len(r) > 1 and take the maximum
3361
+ # generated xmax.
3362
+ if components == 'unbounded' or components == 'both' and (len(r) == 1 or r[2] - r[1] > 3*(r[1] - r[0])):
3363
+ flex = sorted(self.division_polynomial(3).roots(RR, multiplicities=False))
3364
+ flex = flex[-1]
3365
+ xmins.append(r[-1])
3366
+ # The doubling here is an aesthetic choice
3367
+ xmaxs.append(flex + 2*(flex - r[-1]))
3368
+ elif components == 'both':
3369
+ # First the easy part.
3370
+ xmins.append(r[-1])
3371
+ # There are two components and the unbounded component
3372
+ # is not too far from the bounded one. We scale so
3373
+ # that the unbounded component is twice as tall as the
3374
+ # bounded component. The y values corresponding to
3375
+ # horizontal tangent lines are determined as follows.
3376
+ # We implicitly differentiate the equation for this
3377
+ # curve and get
3378
+ # 2 yy' + a1 y + a1 xy' + a3 y' = 3 x^2 + 2a2 x + a4
3379
+
3380
+ R = RR['x']
3381
+ x = R.gen()
3382
+ if a1 == 0:
3383
+ # a horizontal tangent line can only occur at a root of
3384
+ Ederiv = 3*x**2 + 2*a2*x + a4
3385
+ else:
3386
+ # y' = 0 ==> y = (3*x^2 + 2*a2*x + a4) / a1
3387
+ y = (3*x**2 + 2*a2*x + a4) / a1
3388
+ Ederiv = y**2 + a1*x*y + a3*y - (x**3 + a2*x**2 + a4*x + a6)
3389
+ critx = [a for a in Ederiv.roots(RR, multiplicities=False)
3390
+ if r[0] < a < r[1]]
3391
+ if not critx:
3392
+ raise RuntimeError("No horizontal tangent lines on bounded component")
3393
+ # The 2.5 here is an aesthetic choice
3394
+ ymax = 2.5 * max([f1(a) for a in critx])
3395
+ ymin = 2.5 * min([f2(a) for a in critx])
3396
+ top_branch = ymax**2 + a1*x*ymax + a3*ymax - (x**3 + a2*x**2 + a4*x + a6)
3397
+ bottom_branch = ymin**2 + a1*x*ymin + a3*ymin - (x**3 + a2*x**2 + a4*x + a6)
3398
+ xmaxs.append(max(top_branch.roots(RR,multiplicities=False) + bottom_branch.roots(RR,multiplicities=False)))
3399
+ xmins = min(xmins)
3400
+ xmaxs = max(xmaxs)
3401
+ span = xmaxs - xmins
3402
+ if xmin is None:
3403
+ xmin = xmins - .02*span
3404
+ if xmax is None:
3405
+ xmax = xmaxs + .02*span
3406
+ elif xmin >= xmax:
3407
+ raise ValueError("xmin must be less than xmax")
3408
+
3409
+ I = []
3410
+ if components in ['unbounded', 'both'] and xmax > r[-1]:
3411
+ # one real root; 1 component
3412
+ if xmin <= r[-1]:
3413
+ I.append((r[-1],xmax,'<'))
3414
+ else:
3415
+ I.append((xmin, xmax,'='))
3416
+ if components in ['bounded','both'] and len(r) > 1 and (xmin < r[1] or xmax > r[0]):
3417
+ if xmin <= r[0]:
3418
+ if xmax >= r[1]:
3419
+ I.append((r[0],r[1],'o'))
3420
+ else:
3421
+ I.append((r[0],xmax,'<'))
3422
+ elif xmax >= r[1]:
3423
+ I.append((xmin, r[1], '>'))
3424
+ else:
3425
+ I.append((xmin, xmax, '='))
3426
+
3427
+ from sage.plot.graphics import Graphics
3428
+ from sage.plot.line import line
3429
+ from sage.plot.plot import generate_plot_points
3430
+
3431
+ g = Graphics()
3432
+ plot_points = int(args.pop('plot_points',200))
3433
+ adaptive_tolerance = args.pop('adaptive_tolerance',0.01)
3434
+ adaptive_recursion = args.pop('adaptive_recursion',5)
3435
+ randomize = args.pop('randomize',True)
3436
+ for j in range(len(I)):
3437
+ a, b, shape = I[j]
3438
+ v = generate_plot_points(f1, (a, b), plot_points, adaptive_tolerance, adaptive_recursion, randomize)
3439
+ w = generate_plot_points(f2, (a, b), plot_points, adaptive_tolerance, adaptive_recursion, randomize)
3440
+ if shape == 'o':
3441
+ g += line(v + list(reversed(w)) + [v[0]], **args)
3442
+ elif shape == '<':
3443
+ g += line(list(reversed(v)) + w, **args)
3444
+ elif shape == '>':
3445
+ g += line(v + list(reversed(w)), **args)
3446
+ else:
3447
+ g += line(v, **args)
3448
+ g += line(w, **args)
3449
+ return g
3450
+
3451
+ @cached_method
3452
+ def formal_group(self):
3453
+ r"""
3454
+ Return the formal group associated to this elliptic curve.
3455
+
3456
+ This method is cached.
3457
+
3458
+ EXAMPLES::
3459
+
3460
+ sage: E = EllipticCurve("37a")
3461
+ sage: E.formal_group()
3462
+ Formal Group associated to the Elliptic Curve
3463
+ defined by y^2 + y = x^3 - x over Rational Field
3464
+ """
3465
+ return formal_group.EllipticCurveFormalGroup(self)
3466
+
3467
+ formal = formal_group
3468
+
3469
+ def _p_primary_torsion_basis(self, p, m=None):
3470
+ r"""
3471
+ Find a basis for the `p`-primary part of the torsion
3472
+ subgroup of this elliptic curve.
3473
+
3474
+ INPUT:
3475
+
3476
+ - ``p`` -- integer; a prime number
3477
+
3478
+ - ``m`` -- integer or ``None``; if not ``None``, the `p`-primary
3479
+ torsion will be assumed to have order at most `p^m`
3480
+
3481
+ OUTPUT:
3482
+
3483
+ A list of 0, 1 or 2 pairs `[T,k]` where `T` is a generator of
3484
+ order `p^k`. That is, either `[]` or `[[T_1,k_1]]` or
3485
+ `[[T_1,k_1],[T_2,k_2]]` with `[]`, `[T_1]`, or `[T_1,T_2]` a
3486
+ basis and `p^{k_1} \ge p^{k_2} \ge 1` their orders.
3487
+
3488
+ .. WARNING::
3489
+
3490
+ 1. Do not call this on a curve whose group is
3491
+ `p`-divisible (i.e., whose `p`-primary part
3492
+ is infinite)!
3493
+
3494
+ 2. The code uses division polynomials and will be slow for
3495
+ large `p`.
3496
+
3497
+ EXAMPLES::
3498
+
3499
+ sage: E = EllipticCurve('11a1')
3500
+ sage: E._p_primary_torsion_basis(5)
3501
+ [[(5 : -6 : 1), 1]]
3502
+
3503
+ sage: # needs sage.rings.number_field
3504
+ sage: x = polygen(ZZ, 'x')
3505
+ sage: K.<t> = NumberField(x^4 + x^3 + 11*x^2 + 41*x + 101)
3506
+ sage: EK = E.base_extend(K)
3507
+ sage: EK._p_primary_torsion_basis(5) # long time
3508
+ [[(16 : 60 : 1), 1], [(t : 1/11*t^3 + 6/11*t^2 + 19/11*t + 48/11 : 1), 1]]
3509
+ sage: EF = E.change_ring(GF(101)) # needs sage.rings.finite_rings
3510
+ sage: EF._p_primary_torsion_basis(5) # needs sage.rings.finite_rings
3511
+ [[(0 : 13 : 1), 1], [(5 : 5 : 1), 1]]
3512
+
3513
+ sage: F.<z> = CyclotomicField(21) # needs sage.rings.number_field
3514
+ sage: E = EllipticCurve([2, -z^7, -z^7, 0, 0]) # needs sage.rings.number_field
3515
+ sage: E._p_primary_torsion_basis(7,2) # long time # needs sage.rings.number_field
3516
+ [[(0 : z^7 : 1), 1],
3517
+ [(z^7 - z^6 + z^4 - z^3 + z^2 - 1
3518
+ : z^8 - 2*z^7 + z^6 + 2*z^5 - 3*z^4 + 2*z^3 - 2*z + 2 : 1), 1]]
3519
+
3520
+ TESTS:
3521
+
3522
+ This shows that the bug at :issue:`4937` is fixed::
3523
+
3524
+ sage: a = 804515977734860566494239770982282063895480484302363715494873
3525
+ sage: b = 584772221603632866665682322899297141793188252000674256662071
3526
+ sage: E = EllipticCurve(GF(10^60 + 3201), [0,a,0,b,0]) # needs sage.rings.finite_rings
3527
+ sage: [t[1] for t in E._p_primary_torsion_basis(2)] # long time, needs sage.rings.finite_rings
3528
+ [16, 1]
3529
+ """
3530
+ p = Integer(p)
3531
+ if not p.is_prime():
3532
+ raise ValueError("p (=%s) should be prime" % p)
3533
+
3534
+ if m is None:
3535
+ from sage.rings.infinity import Infinity
3536
+ m = Infinity
3537
+
3538
+ if m == 0:
3539
+ return []
3540
+
3541
+ # First find the p-torsion:
3542
+ Ep = self(0).division_points(p)
3543
+ p_rank = Integer(len(Ep)).exact_log(p)
3544
+ assert p_rank in [0, 1, 2]
3545
+
3546
+ if p_rank == 0:
3547
+ return []
3548
+
3549
+ if p_rank == 1:
3550
+ P = Ep[0]
3551
+ if P.is_zero():
3552
+ P = Ep[1]
3553
+ k = 1
3554
+ if m == 1:
3555
+ return [[P, k]]
3556
+ pts = P.division_points(p) # length 0 or p
3557
+ while pts:
3558
+ k += 1
3559
+ P = pts[0]
3560
+ if m <= k:
3561
+ return [[P, k]]
3562
+ pts = P.division_points(p)
3563
+ # now P generates the p-power-torsion and has order p^k
3564
+ return [[P, k]]
3565
+
3566
+ Epi = iter(Ep) # used to iterate through Ep
3567
+ # Find P1,P2 which generate the p-torsion:
3568
+ P1 = next(Epi)
3569
+ while P1.is_zero():
3570
+ P1 = next(Epi)
3571
+ P2 = next(Epi)
3572
+ while generic.linear_relation(P1, P2, '+')[0] != 0:
3573
+ P2 = next(Epi)
3574
+
3575
+ k = 1
3576
+ log_order = 2
3577
+ if m <= log_order:
3578
+ return [[P1, 1], [P2, 1]]
3579
+
3580
+ pts1 = P1.division_points(p)
3581
+ pts2 = P2.division_points(p)
3582
+ while pts1 and pts2:
3583
+ k += 1
3584
+ P1 = pts1[0]
3585
+ P2 = pts2[0]
3586
+ log_order += 2
3587
+ if m <= log_order:
3588
+ return [[P1, k], [P2, k]]
3589
+ pts1 = P1.division_points(p)
3590
+ pts2 = P2.division_points(p)
3591
+
3592
+ # Now P1,P2 are a basis for the p^k torsion, which is
3593
+ # isomorphic to (Z/p^k)^2, and k is the maximal integer for
3594
+ # which this is the case.
3595
+
3596
+ # We now determine whether a combination (P2 or P1+a*P2 for
3597
+ # some a) can be further divided for some a mod p; if so,
3598
+ # replace P1 by that combination, set pts to be the list of
3599
+ # solutions Q to p*Q=P1. If no combination can be divided,
3600
+ # then the structure is (p^k,p^k) and we can stop.
3601
+
3602
+ if pts1:
3603
+ pts = pts1
3604
+ elif pts2:
3605
+ P1, P2 = P2, P1
3606
+ pts = pts2
3607
+ else:
3608
+ for Q in generic.multiples(P2, p-1, P1 + P2, operation='+'):
3609
+ # Q runs through P1+a*P2 for a=1,2,...,p-1
3610
+ pts = Q.division_points(p)
3611
+ if pts:
3612
+ P1 = Q
3613
+ break
3614
+
3615
+ if not pts:
3616
+ return [[P1, k], [P2, k]]
3617
+
3618
+ # Now the structure is (p^n,p^k) for some n>k. We need to
3619
+ # replace P1 by an element of maximal order p^n. So far we
3620
+ # have pts = list of Q satisfying p*Q=P1, and all such Q have
3621
+ # order p^{k+1}.
3622
+
3623
+ # We keep trying to divide P1 by p. At each step, if we
3624
+ # succeed, replace P1 by any of the results and increment n.
3625
+ # If we fails try again with P1+a*P2 for a in [1..p-1]. If any
3626
+ # succeed, replace P1 by one of the resulting divided points.
3627
+ # If all fail, the structure is (p^n,p^k) and P1,P2 are
3628
+ # generators.
3629
+
3630
+ n = k
3631
+ while True:
3632
+ P1 = pts[0]
3633
+ n += 1
3634
+ log_order += 1
3635
+ if m <= log_order:
3636
+ return [[P1, n], [P2, k]]
3637
+ pts = P1.division_points(p)
3638
+ if not pts:
3639
+ for Q in generic.multiples(P2, p-1, P1+P2, operation='+'):
3640
+ # Q runs through P1+a*P2 for a=1,2,...,p-1
3641
+ pts = Q.division_points(p)
3642
+ if pts:
3643
+ break
3644
+ if not pts:
3645
+ return [[P1, n], [P2, k]]
3646
+
3647
+ def hyperelliptic_polynomials(self):
3648
+ r"""
3649
+ Return a pair of polynomials `g(x)`, `h(x)` such that this elliptic
3650
+ curve can be defined by the standard hyperelliptic equation
3651
+
3652
+ .. MATH::
3653
+
3654
+ y^2 + h(x)y = g(x).
3655
+
3656
+ EXAMPLES::
3657
+
3658
+ sage: R.<a1,a2,a3,a4,a6>=QQ[]
3659
+ sage: E = EllipticCurve([a1,a2,a3,a4,a6])
3660
+ sage: E.hyperelliptic_polynomials()
3661
+ (x^3 + a2*x^2 + a4*x + a6, a1*x + a3)
3662
+ """
3663
+ K = self.base_ring()
3664
+ R = PolynomialRing(K, 'x')
3665
+ a1, a2, a3, a4, a6 = self.ainvs()
3666
+ return R([a6, a4, a2, 1]), R([a3, a1])
3667
+
3668
+ # This caching is important since PARI also caches certain
3669
+ # things. This wouldn't work if we would call ellinit()
3670
+ # every time.
3671
+ @cached_method
3672
+ def pari_curve(self):
3673
+ """
3674
+ Return the PARI curve corresponding to this elliptic curve.
3675
+
3676
+ The result is cached.
3677
+
3678
+ EXAMPLES::
3679
+
3680
+ sage: # needs sage.libs.pari
3681
+ sage: E = EllipticCurve([RR(0), RR(0), RR(1), RR(-1), RR(0)])
3682
+ sage: e = E.pari_curve()
3683
+ sage: type(e)
3684
+ <... 'cypari2.gen.Gen'>
3685
+ sage: e.type()
3686
+ 't_VEC'
3687
+ sage: e.disc()
3688
+ 37.0000000000000
3689
+
3690
+ Over a finite field::
3691
+
3692
+ sage: EllipticCurve(GF(41), [2,5]).pari_curve() # needs sage.libs.pari
3693
+ [Mod(0, 41), Mod(0, 41), Mod(0, 41), Mod(2, 41), Mod(5, 41),
3694
+ Mod(0, 41), Mod(4, 41), Mod(20, 41), Mod(37, 41), Mod(27, 41),
3695
+ Mod(26, 41), Mod(4, 41), Mod(11, 41),
3696
+ Vecsmall([3]),
3697
+ [41, [9, 31, [6, 0, 0, 0]]], [0, 0, 0, 0]]
3698
+
3699
+ Over a `p`-adic field::
3700
+
3701
+ sage: # needs sage.libs.pari sage.rings.padics
3702
+ sage: Qp = pAdicField(5, prec=3)
3703
+ sage: E = EllipticCurve(Qp, [3, 4])
3704
+ sage: E.pari_curve()
3705
+ [0, 0, 0, 3, 4, 0, 6, 16, -9, -144, -3456, -8640, 1728/5,
3706
+ Vecsmall([2]), [O(5^3)], [0, 0]]
3707
+ sage: E.j_invariant()
3708
+ 3*5^-1 + O(5)
3709
+
3710
+ Over a number field::
3711
+
3712
+ sage: K.<a> = QuadraticField(2) # needs sage.libs.pari sage.rings.number_field
3713
+ sage: E = EllipticCurve([1,a]) # needs sage.libs.pari sage.rings.number_field
3714
+ sage: E.pari_curve() # needs sage.libs.pari sage.rings.number_field
3715
+ [0, 0, 0, Mod(1, y^2 - 2),
3716
+ Mod(y, y^2 - 2), 0, Mod(2, y^2 - 2), Mod(4*y, y^2 - 2),
3717
+ Mod(-1, y^2 - 2), Mod(-48, y^2 - 2), Mod(-864*y, y^2 - 2),
3718
+ Mod(-928, y^2 - 2), Mod(3456/29, y^2 - 2),
3719
+ Vecsmall([5]),
3720
+ [[y^2 - 2, [2, 0], 8, 1, [[1, -1.41421356237310; 1, 1.41421356237310],
3721
+ [1, -1.41421356237310; 1, 1.41421356237310],
3722
+ [16, -23; 16, 23], [2, 0; 0, 4], [4, 0; 0, 2], [2, 0; 0, 1],
3723
+ [2, [0, 2; 1, 0]], [2]], [-1.41421356237310, 1.41421356237310],
3724
+ [1, y], [1, 0; 0, 1], [1, 0, 0, 2; 0, 1, 1, 0]]], [0, 0, 0, 0, 0]]
3725
+
3726
+ PARI no longer requires that the `j`-invariant has negative `p`-adic valuation::
3727
+
3728
+ sage: E = EllipticCurve(Qp,[1, 1]) # needs sage.libs.pari sage.rings.padics
3729
+ sage: E.j_invariant() # the j-invariant is a p-adic integer # needs sage.libs.pari sage.rings.padics
3730
+ 2 + 4*5^2 + O(5^3)
3731
+ sage: E.pari_curve() # needs sage.libs.pari sage.rings.padics
3732
+ [0, 0, 0, 1, 1, 0, 2, 4, -1, -48, -864, -496, 6912/31,
3733
+ Vecsmall([2]), [O(5^3)], [0, 0]]
3734
+ """
3735
+ from sage.categories.number_fields import NumberFields
3736
+ from sage.libs.pari import pari
3737
+ if self.base_ring() in NumberFields():
3738
+ return pari.ellinit(self.a_invariants(), self.base_ring())
3739
+ else:
3740
+ return pari.ellinit(self.a_invariants())
3741
+
3742
+ # This method is defined so that pari(E) returns exactly the same
3743
+ # as E.pari_curve(). This works even for classes that inherit from
3744
+ # EllipticCurve_generic, such as EllipticCurve_rational_field.
3745
+ def __pari__(self):
3746
+ """
3747
+ Return the PARI curve corresponding to this elliptic curve.
3748
+
3749
+ EXAMPLES::
3750
+
3751
+ sage: E = EllipticCurve('11a1')
3752
+ sage: pari(E) # needs sage.libs.pari
3753
+ [0, -1, 1, -10, -20, -4, -20, -79, -21, 496, 20008, -161051, -122023936/161051, Vecsmall([1]), [Vecsmall([64, -1])], [0, 0, 0, 0, 0, 0, 0, 0]]
3754
+
3755
+ Over a finite field::
3756
+
3757
+ sage: EllipticCurve(GF(2), [0,0,1,1,1]).__pari__() # needs sage.libs.pari
3758
+ [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, Vecsmall([4]), [1, [[Vecsmall([0, 1]), Vecsmall([0, 1]), Vecsmall([0, 1])], Vecsmall([0, 1]), [Vecsmall([0, 1]), Vecsmall([0]), Vecsmall([0]), Vecsmall([0])]]], [0, 0, 0, 0]]
3759
+ """
3760
+ return self.pari_curve()