passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

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