passagemath-schemes 10.6.40__cp314-cp314-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.

Potentially problematic release.


This version of passagemath-schemes might be problematic. Click here for more details.

Files changed (314) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.6.40.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
  9. passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.40.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +720 -0
  40. sage/modular/abvar/homspace.py +998 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2017 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1071 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +815 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-314-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
  154. sage/modular/modsym/p1list.pxd +29 -0
  155. sage/modular/modsym/p1list.pyx +1372 -0
  156. sage/modular/modsym/p1list_nf.py +1241 -0
  157. sage/modular/modsym/relation_matrix.py +591 -0
  158. sage/modular/modsym/relation_matrix_pyx.cpython-314-darwin.so +0 -0
  159. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  160. sage/modular/modsym/space.py +2468 -0
  161. sage/modular/modsym/subspace.py +455 -0
  162. sage/modular/modsym/tests.py +375 -0
  163. sage/modular/multiple_zeta.py +2632 -0
  164. sage/modular/multiple_zeta_F_algebra.py +786 -0
  165. sage/modular/overconvergent/all.py +6 -0
  166. sage/modular/overconvergent/genus0.py +1878 -0
  167. sage/modular/overconvergent/hecke_series.py +1187 -0
  168. sage/modular/overconvergent/weightspace.py +778 -0
  169. sage/modular/pollack_stevens/all.py +4 -0
  170. sage/modular/pollack_stevens/distributions.py +874 -0
  171. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  172. sage/modular/pollack_stevens/manin_map.py +859 -0
  173. sage/modular/pollack_stevens/modsym.py +1593 -0
  174. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  175. sage/modular/pollack_stevens/sigma0.py +534 -0
  176. sage/modular/pollack_stevens/space.py +1076 -0
  177. sage/modular/quasimodform/all.py +3 -0
  178. sage/modular/quasimodform/element.py +845 -0
  179. sage/modular/quasimodform/ring.py +828 -0
  180. sage/modular/quatalg/all.py +3 -0
  181. sage/modular/quatalg/brandt.py +1642 -0
  182. sage/modular/ssmod/all.py +8 -0
  183. sage/modular/ssmod/ssmod.py +827 -0
  184. sage/rings/all__sagemath_schemes.py +1 -0
  185. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  186. sage/rings/polynomial/binary_form_reduce.py +585 -0
  187. sage/schemes/all.py +41 -0
  188. sage/schemes/berkovich/all.py +6 -0
  189. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  190. sage/schemes/berkovich/berkovich_space.py +748 -0
  191. sage/schemes/curves/affine_curve.py +2928 -0
  192. sage/schemes/curves/all.py +33 -0
  193. sage/schemes/curves/closed_point.py +434 -0
  194. sage/schemes/curves/constructor.py +381 -0
  195. sage/schemes/curves/curve.py +542 -0
  196. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  197. sage/schemes/curves/point.py +463 -0
  198. sage/schemes/curves/projective_curve.py +3026 -0
  199. sage/schemes/curves/zariski_vankampen.py +1932 -0
  200. sage/schemes/cyclic_covers/all.py +2 -0
  201. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  202. sage/schemes/cyclic_covers/constructor.py +137 -0
  203. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  204. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  205. sage/schemes/elliptic_curves/BSD.py +1036 -0
  206. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  207. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  208. sage/schemes/elliptic_curves/all.py +49 -0
  209. sage/schemes/elliptic_curves/cardinality.py +609 -0
  210. sage/schemes/elliptic_curves/cm.py +1102 -0
  211. sage/schemes/elliptic_curves/constructor.py +1552 -0
  212. sage/schemes/elliptic_curves/ec_database.py +175 -0
  213. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  214. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  215. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  216. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  217. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  218. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  219. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  220. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  221. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  222. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  223. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  224. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  225. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  226. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  227. sage/schemes/elliptic_curves/formal_group.py +760 -0
  228. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  229. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  230. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  231. sage/schemes/elliptic_curves/heegner.py +7335 -0
  232. sage/schemes/elliptic_curves/height.py +2109 -0
  233. sage/schemes/elliptic_curves/hom.py +1406 -0
  234. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  235. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  236. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  237. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  238. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  239. sage/schemes/elliptic_curves/homset.py +271 -0
  240. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  241. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  242. sage/schemes/elliptic_curves/jacobian.py +237 -0
  243. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  244. sage/schemes/elliptic_curves/kraus.py +1014 -0
  245. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  246. sage/schemes/elliptic_curves/mod5family.py +105 -0
  247. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  248. sage/schemes/elliptic_curves/mod_sym_num.cpython-314-darwin.so +0 -0
  249. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  250. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  251. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  252. sage/schemes/elliptic_curves/padics.py +1816 -0
  253. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  254. sage/schemes/elliptic_curves/period_lattice_region.cpython-314-darwin.so +0 -0
  255. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  256. sage/schemes/elliptic_curves/saturation.py +715 -0
  257. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  258. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  259. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  260. sage/schemes/hyperelliptic_curves/all.py +6 -0
  261. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  265. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  266. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  267. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  271. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  272. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  273. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  274. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  275. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  276. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  277. sage/schemes/jacobians/all.py +2 -0
  278. sage/schemes/overview.py +161 -0
  279. sage/schemes/plane_conics/all.py +22 -0
  280. sage/schemes/plane_conics/con_field.py +1296 -0
  281. sage/schemes/plane_conics/con_finite_field.py +158 -0
  282. sage/schemes/plane_conics/con_number_field.py +456 -0
  283. sage/schemes/plane_conics/con_rational_field.py +406 -0
  284. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  285. sage/schemes/plane_conics/constructor.py +249 -0
  286. sage/schemes/plane_quartics/all.py +2 -0
  287. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  288. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  289. sage/schemes/riemann_surfaces/all.py +1 -0
  290. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  291. sage_wheels/share/cremona/cremona_mini.db +0 -0
  292. sage_wheels/share/ellcurves/rank0 +30427 -0
  293. sage_wheels/share/ellcurves/rank1 +31871 -0
  294. sage_wheels/share/ellcurves/rank10 +6 -0
  295. sage_wheels/share/ellcurves/rank11 +6 -0
  296. sage_wheels/share/ellcurves/rank12 +1 -0
  297. sage_wheels/share/ellcurves/rank14 +1 -0
  298. sage_wheels/share/ellcurves/rank15 +1 -0
  299. sage_wheels/share/ellcurves/rank17 +1 -0
  300. sage_wheels/share/ellcurves/rank19 +1 -0
  301. sage_wheels/share/ellcurves/rank2 +2388 -0
  302. sage_wheels/share/ellcurves/rank20 +1 -0
  303. sage_wheels/share/ellcurves/rank21 +1 -0
  304. sage_wheels/share/ellcurves/rank22 +1 -0
  305. sage_wheels/share/ellcurves/rank23 +1 -0
  306. sage_wheels/share/ellcurves/rank24 +1 -0
  307. sage_wheels/share/ellcurves/rank28 +1 -0
  308. sage_wheels/share/ellcurves/rank3 +836 -0
  309. sage_wheels/share/ellcurves/rank4 +10 -0
  310. sage_wheels/share/ellcurves/rank5 +5 -0
  311. sage_wheels/share/ellcurves/rank6 +5 -0
  312. sage_wheels/share/ellcurves/rank7 +5 -0
  313. sage_wheels/share/ellcurves/rank8 +6 -0
  314. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,4787 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Points on elliptic curves
4
+
5
+ The base class :class:`EllipticCurvePoint` provides support for
6
+ points on elliptic curves defined over general rings, including
7
+ generic addition formulas.
8
+
9
+ The derived classes :class:`EllipticCurvePoint_field` and its
10
+ child classes :class:`EllipticCurvePoint_number_field` and
11
+ :class:`EllipticCurvePoint_finite_field` provide further support
12
+ for points on curves defined over arbitrary fields, as well as
13
+ specialized functionality for points on curves over number fields
14
+ (including the rational field `\QQ`) and finite fields.
15
+
16
+ EXAMPLES:
17
+
18
+ An example over `\QQ`::
19
+
20
+ sage: # needs database_cremona_mini_ellcurve
21
+ sage: E = EllipticCurve('389a1')
22
+ sage: P = E(-1,1); P
23
+ (-1 : 1 : 1)
24
+ sage: Q = E(0,-1); Q
25
+ (0 : -1 : 1)
26
+ sage: P+Q
27
+ (4 : 8 : 1)
28
+ sage: P-Q
29
+ (1 : 0 : 1)
30
+ sage: 3*P-5*Q
31
+ (328/361 : -2800/6859 : 1)
32
+
33
+ An example over a number field::
34
+
35
+ sage: # needs sage.rings.number_field
36
+ sage: K.<i> = QuadraticField(-1)
37
+ sage: E = EllipticCurve(K, [1,0,0,0,-1])
38
+ sage: P = E(0,i); P
39
+ (0 : i : 1)
40
+ sage: P.order()
41
+ +Infinity
42
+ sage: 101*P - 100*P == P
43
+ True
44
+
45
+ An example over a finite field::
46
+
47
+ sage: # needs sage.rings.finite_rings
48
+ sage: K.<a> = GF((101,3))
49
+ sage: E = EllipticCurve(K, [1,0,0,0,-1])
50
+ sage: P = E(40*a^2 + 69*a + 84 , 58*a^2 + 73*a + 45)
51
+ sage: P.order()
52
+ 1032210
53
+ sage: E.cardinality()
54
+ 1032210
55
+
56
+ Arithmetic with a point over an extension of a finite field::
57
+
58
+ sage: # needs sage.rings.finite_rings
59
+ sage: k.<a> = GF((5,2))
60
+ sage: E = EllipticCurve(k,[1,0]); E
61
+ Elliptic Curve defined by y^2 = x^3 + x over Finite Field in a of size 5^2
62
+ sage: P = E([a,2*a+4])
63
+ sage: 5*P
64
+ (2*a + 3 : 2*a : 1)
65
+ sage: P*5
66
+ (2*a + 3 : 2*a : 1)
67
+ sage: P + P + P + P + P
68
+ (2*a + 3 : 2*a : 1)
69
+
70
+ ::
71
+
72
+ sage: F = Zmod(3)
73
+ sage: E = EllipticCurve(F, [1,0]);
74
+ sage: P = E([2,1])
75
+ sage: import sys
76
+ sage: n = sys.maxsize
77
+ sage: P*(n+1)-P*n == P
78
+ True
79
+
80
+ Arithmetic over `\Zmod{N}` with composite `N` is supported::
81
+
82
+ sage: N = 1715761513
83
+ sage: E = EllipticCurve(Integers(N), [3,-13])
84
+ sage: P = E(2,1)
85
+ sage: LCM([2..60])*P
86
+ (1643112467 : 9446995 : 26927)
87
+
88
+ However, some algorithms (e.g., toy examples of ECM) involve performing
89
+ elliptic-curve operations as if the base ring were a field even when it
90
+ is not, and exploit the failures when attempting to invert a non-unit.
91
+ Sage provides a *hack* to support such educational examples via the
92
+ :meth:`EllipticCurve_generic.assume_base_ring_is_field` method.
93
+ Example::
94
+
95
+ sage: E.assume_base_ring_is_field()
96
+ sage: P = E(2,1)
97
+ sage: LCM([2..60])*P
98
+ Traceback (most recent call last):
99
+ ...
100
+ ZeroDivisionError: Inverse of 26927 does not exist
101
+ (characteristic = 1715761513 = 26927*63719)
102
+
103
+ AUTHORS:
104
+
105
+ - William Stein (2005) -- Initial version
106
+
107
+ - Robert Bradshaw et al....
108
+
109
+ - John Cremona (Feb 2008) -- Point counting and group structure for
110
+ non-prime fields, Frobenius endomorphism and order, elliptic logs
111
+
112
+ - John Cremona (Aug 2008) -- Introduced ``EllipticCurvePoint_number_field`` class
113
+
114
+ - Tobias Nagel, Michael Mardaus, John Cremona (Dec 2008) -- `p`-adic elliptic logarithm over `\QQ`
115
+
116
+ - David Hansen (Jan 2009) -- Added ``weil_pairing`` function to ``EllipticCurvePoint_finite_field`` class
117
+
118
+ - Mariah Lenox (March 2011) -- Added ``tate_pairing`` and ``ate_pairing``
119
+ functions to ``EllipticCurvePoint_finite_field`` class
120
+
121
+ - Lorenz Panny (2022): point addition over general rings
122
+ """
123
+
124
+ # ****************************************************************************
125
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
126
+ #
127
+ # Distributed under the terms of the GNU General Public License (GPL)
128
+ # as published by the Free Software Foundation; either version 2 of
129
+ # the License, or (at your option) any later version.
130
+ # https://www.gnu.org/licenses/
131
+ # ****************************************************************************
132
+
133
+ import math
134
+
135
+ import sage.groups.generic as generic
136
+ import sage.rings.abc
137
+
138
+ from sage.misc.lazy_import import lazy_import
139
+ from sage.rings.finite_rings.integer_mod import Mod
140
+ from sage.rings.infinity import Infinity as oo
141
+ from sage.rings.integer import Integer
142
+ from sage.rings.integer_ring import ZZ
143
+ from sage.rings.padics.precision_error import PrecisionError
144
+ from sage.rings.rational_field import QQ
145
+ from sage.rings.real_mpfr import RealField, RR
146
+ from sage.rings.quotient_ring import QuotientRing_generic
147
+
148
+ from sage.structure.element import AdditiveGroupElement
149
+ from sage.structure.sequence import Sequence
150
+ from sage.structure.richcmp import richcmp
151
+
152
+ from sage.structure.coerce_actions import IntegerMulAction
153
+
154
+ from sage.schemes.curves.projective_curve import Hasse_bounds
155
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
156
+ from sage.schemes.projective.projective_point import (SchemeMorphism_point_projective_ring,
157
+ SchemeMorphism_point_abelian_variety_field)
158
+
159
+ lazy_import('sage.rings.padics.factory', 'Qp')
160
+ lazy_import('sage.schemes.generic.morphism', 'SchemeMorphism')
161
+
162
+ try:
163
+ from sage.libs.pari import pari
164
+ from cypari2.handle_error import PariError
165
+ except ImportError:
166
+ PariError = ()
167
+
168
+
169
+ class EllipticCurvePoint(AdditiveGroupElement,
170
+ SchemeMorphism_point_projective_ring):
171
+ """
172
+ A point on an elliptic curve.
173
+ """
174
+ def __init__(self, *args, **kwds):
175
+ r"""
176
+ Initialize this elliptic-curve point.
177
+
178
+ EXAMPLES::
179
+
180
+ sage: E = EllipticCurve(Zmod(77), [1,1,1,1,1])
181
+ sage: E(0)
182
+ (0 : 1 : 0)
183
+ sage: E(3, 9)
184
+ (3 : 9 : 1)
185
+ sage: E(6, 18, 2)
186
+ (3 : 9 : 1)
187
+ sage: E(66, 23, 22)
188
+ (33 : 50 : 11)
189
+ """
190
+ super().__init__(*args, **kwds)
191
+ try:
192
+ self.normalize_coordinates()
193
+ except NotImplementedError:
194
+ pass
195
+
196
+ def curve(self):
197
+ """
198
+ Return the curve that this point is on.
199
+
200
+ This is a synonym for :meth:`scheme`.
201
+
202
+ EXAMPLES::
203
+
204
+ sage: # needs database_cremona_mini_ellcurve
205
+ sage: E = EllipticCurve('389a')
206
+ sage: P = E([-1, 1])
207
+ sage: P.curve()
208
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
209
+
210
+ sage: E = EllipticCurve(QQ, [1, 1])
211
+ sage: P = E(0, 1)
212
+ sage: P.scheme()
213
+ Elliptic Curve defined by y^2 = x^3 + x + 1 over Rational Field
214
+ sage: P.scheme() == P.curve()
215
+ True
216
+ sage: x = polygen(ZZ, 'x')
217
+ sage: K.<a> = NumberField(x^2 - 3,'a') # needs sage.rings.number_field
218
+ sage: P = E.base_extend(K)(1, a) # needs sage.rings.number_field
219
+ sage: P.scheme() # needs sage.rings.number_field
220
+ Elliptic Curve defined by y^2 = x^3 + x + 1 over
221
+ Number Field in a with defining polynomial x^2 - 3
222
+ """
223
+ return self.scheme()
224
+
225
+ def _add_(self, other):
226
+ r"""
227
+ Add this point to another point on the same elliptic curve.
228
+
229
+ This method computes point additions for fairly general rings.
230
+
231
+ ALGORITHM:
232
+
233
+ Over quotient rings of Euclidean domains modulo principal ideals:
234
+ The standard formulas for fields, extended to non-fields via the
235
+ Chinese remainder theorem.
236
+
237
+ In more general rings: Formulas due to Bosma and Lenstra [BL1995]_
238
+ with corrections by Best [Best2021]_ (Appendix A).
239
+ See :mod:`sage.schemes.elliptic_curves.addition_formulas_ring`.
240
+
241
+ EXAMPLES::
242
+
243
+ sage: N = 1113121
244
+ sage: E = EllipticCurve(Zmod(N), [1,0])
245
+ sage: R1 = E(301098, 673883, 644675)
246
+ sage: R2 = E(411415, 758555, 255837)
247
+ sage: R3 = E(983009, 342673, 207687)
248
+ sage: R1 + R2 == R3
249
+ True
250
+
251
+ TESTS:
252
+
253
+ We check on random examples that the results are compatible modulo
254
+ all divisors of the characteristic. (In particular, this includes
255
+ prime divisors, for which the result is computed using the "old",
256
+ much simpler formulas for fields.) ::
257
+
258
+ sage: N = ZZ(randrange(2, 10**5))
259
+ sage: E = None
260
+ sage: while True:
261
+ ....: try:
262
+ ....: E = EllipticCurve(list((Zmod(N)^5).random_element()))
263
+ ....: except ArithmeticError:
264
+ ....: pass
265
+ ....: else:
266
+ ....: if E.discriminant().is_unit():
267
+ ....: break
268
+ sage: pts = []
269
+ sage: X = polygen(Zmod(N^2))
270
+ sage: while len(pts) < 2:
271
+ ....: y, z = (Zmod(N)^2).random_element()
272
+ ....: f = E.defining_polynomial()(X, y, z)
273
+ ....: xs = f.roots(multiplicities=False)
274
+ ....: xs = [x for x in xs if 1 in Zmod(N).ideal([x,y,z])]
275
+ ....: if xs:
276
+ ....: pts.append(E(choice(xs), y, z))
277
+ sage: P, Q = pts
278
+ sage: R = P + Q # not tested (:issue:`39191`)
279
+ sage: for d in N.divisors(): # not tested (:issue:`39191`)
280
+ ....: if d > 1:
281
+ ....: assert R.change_ring(Zmod(d)) == P.change_ring(Zmod(d)) + Q.change_ring(Zmod(d))
282
+ """
283
+ if self.is_zero():
284
+ return other
285
+ if other.is_zero():
286
+ return self
287
+
288
+ E = self.curve()
289
+ R = E.base_ring()
290
+
291
+ # We handle Euclidean domains modulo principal ideals separately.
292
+ # Important special cases of this include quotient rings of the
293
+ # integers as well as of univariate polynomial rings over fields.
294
+ if isinstance(R, QuotientRing_generic):
295
+ from sage.categories.euclidean_domains import EuclideanDomains
296
+ if R.cover_ring() in EuclideanDomains():
297
+ I = R.defining_ideal()
298
+ if I.ngens() == 1:
299
+ mod, = I.gens()
300
+
301
+ a1, a2, a3, a4, a6 = E.ainvs()
302
+ x1, y1, z1 = map(R, self)
303
+ x2, y2, z2 = map(R, other)
304
+
305
+ mod_1st = mod.gcd(z2.lift())
306
+ mod //= mod_1st
307
+ mod_2nd = mod.gcd(z1.lift())
308
+ mod //= mod_2nd
309
+
310
+ xz, zx = x1*z2, x2*z1
311
+ yz, zy = y1*z2, y2*z1
312
+ zz = z1*z2
313
+
314
+ # addition
315
+ num_add = yz - zy
316
+ den_add = xz - zx
317
+ mod_dbl = mod.gcd(num_add.lift()).gcd(den_add.lift())
318
+ mod_add = mod // mod_dbl
319
+
320
+ # doubling
321
+ if not mod_dbl.is_one():
322
+ num_dbl = (3*x1 + 2*a2*z1) * x1 + (a4*z1 - a1*y1) * z1
323
+ den_dbl = (2*y1 + a1*x1 + a3*z1) * z1
324
+ else:
325
+ num_dbl = den_dbl = 0
326
+
327
+ if mod_dbl.gcd(mod_add).is_one():
328
+ from sage.arith.misc import CRT_vectors
329
+ if mod_dbl.is_one():
330
+ num, den = num_add, den_add
331
+ elif mod_add.is_one():
332
+ num, den = num_dbl, den_dbl
333
+ else:
334
+ num, den = CRT_vectors([(num_add, den_add), (num_dbl, den_dbl)], [mod_add, mod_dbl])
335
+
336
+ den2 = den**2
337
+ x3 = ((num + a1*den)*zz*num - (xz + zx + a2*zz)*den2) * den
338
+ y3 = ((2*xz + zx + (a2 - a1**2)*zz)*num + (a1*(xz + zx + a2*zz) - a3*zz - yz)*den) * den2 - (num + 2*a1*den)*zz*num**2
339
+ z3 = zz * den * den2
340
+
341
+ pt = x3.lift(), y3.lift(), z3.lift()
342
+ if not mod_1st.is_one():
343
+ pt = CRT_vectors([pt, [x1.lift(), y1.lift(), z1.lift()]], [mod, mod_1st])
344
+ mod = mod.lcm(mod_1st)
345
+ if not mod_2nd.is_one():
346
+ pt = CRT_vectors([pt, [x2.lift(), y2.lift(), z2.lift()]], [mod, mod_2nd])
347
+
348
+ return E.point(Sequence(pt, E.base_ring()), check=False)
349
+
350
+ from sage.schemes.elliptic_curves.addition_formulas_ring import _add
351
+ from sage.modules.free_module_element import vector
352
+
353
+ pts = []
354
+ for pt in filter(any, _add(E, self, other)):
355
+ if R.one() in R.ideal(pt):
356
+ return E.point(pt)
357
+ pts.append(pt)
358
+ assert len(pts) == 2, 'bug in elliptic-curve point addition'
359
+
360
+ #TODO: If the base ring has trivial Picard group, it is known
361
+ # that some linear combination of the two vectors is a valid
362
+ # projective point (whose coordinates generate the unit ideal).
363
+ # Below, we simply try random linear combinations until we
364
+ # find a good choice. Is there a general method that doesn't
365
+ # involve guessing?
366
+
367
+ pts = [vector(R, pt) for pt in pts]
368
+ for _ in range(1000):
369
+ result = tuple(sum(R.random_element() * pt for pt in pts))
370
+ if R.one() in R.ideal(result):
371
+ return E.point(result, check=False)
372
+
373
+ assert False, 'bug: failed to compute elliptic-curve point addition'
374
+
375
+ def _neg_(self):
376
+ """
377
+ Return the negative of this elliptic-curve point, over a general ring.
378
+
379
+ EXAMPLES::
380
+
381
+ sage: # needs database_cremona_mini_ellcurve
382
+ sage: E = EllipticCurve('389a')
383
+ sage: P = E([-1,1])
384
+ sage: Q = -P; Q
385
+ (-1 : -2 : 1)
386
+ sage: Q + P
387
+ (0 : 1 : 0)
388
+
389
+ ::
390
+
391
+ sage: N = 1113121
392
+ sage: E = EllipticCurve(Zmod(N), [1,0])
393
+ sage: R = E(301098, 673883, 644675)
394
+ sage: -R
395
+ (136211 : 914033 : 107)
396
+ sage: ((-R) + R) == 0
397
+ True
398
+ """
399
+ if self.is_zero():
400
+ return self
401
+ E = self.curve()
402
+ a1, _, a3, _, _ = E.a_invariants()
403
+ x, y, z = self
404
+ return E.point([x, -y - a1*x - a3*z, z], check=False)
405
+
406
+ def _sub_(self, other):
407
+ """
408
+ Subtract ``other`` from ``self``.
409
+
410
+ ALGORITHM: :meth:`_add_` and :meth:`_neg_`.
411
+
412
+ EXAMPLES::
413
+
414
+ sage: # needs database_cremona_mini_ellcurve
415
+ sage: E = EllipticCurve('389a')
416
+ sage: P = E([-1,1]); Q = E([0,0])
417
+ sage: P - Q
418
+ (4 : 8 : 1)
419
+ sage: P - Q == P._sub_(Q)
420
+ True
421
+ sage: (P - Q) + Q
422
+ (-1 : 1 : 1)
423
+ sage: P
424
+ (-1 : 1 : 1)
425
+
426
+ ::
427
+
428
+ sage: N = 1113121
429
+ sage: E = EllipticCurve(Zmod(N), [1,0])
430
+ sage: R1 = E(301098, 673883, 644675)
431
+ sage: R2 = E(411415, 758555, 255837)
432
+ sage: R3 = E(983009, 342673, 207687)
433
+ sage: R1 == R3 - R2
434
+ True
435
+ """
436
+ return self + (-other)
437
+
438
+ def _acted_upon_(self, other, side):
439
+ r"""
440
+ We implement ``_acted_upon_`` to provide scalar multiplications.
441
+
442
+ EXAMPLES::
443
+
444
+ sage: # needs sage.rings.finite_rings
445
+ sage: N = 1113121
446
+ sage: E = EllipticCurve(Zmod(N), [1,0])
447
+ sage: R = E(301098, 673883, 644675)
448
+ sage: 123*R
449
+ (703739 : 464106 : 107)
450
+ sage: 70200*R
451
+ (0 : 1 : 0)
452
+ """
453
+ return IntegerMulAction(ZZ, self.parent())._act_(other, self)
454
+
455
+ def __bool__(self):
456
+ r"""
457
+ Test whether this elliptic-curve point equals the neutral
458
+ element of the group (i.e., the point at infinity).
459
+
460
+ EXAMPLES::
461
+
462
+ sage: E = EllipticCurve(GF(7), [1,1])
463
+ sage: bool(E(0))
464
+ False
465
+ sage: bool(E.lift_x(2))
466
+ True
467
+
468
+ sage:
469
+
470
+ sage: E = EllipticCurve(Zmod(77), [1,1,1,1,1])
471
+ sage: bool(E(0))
472
+ False
473
+ sage: P = E(66, 23, 22); P
474
+ (33 : 50 : 11)
475
+ sage: bool(P)
476
+ True
477
+ """
478
+ return bool(self[2])
479
+
480
+
481
+ class EllipticCurvePoint_field(EllipticCurvePoint,
482
+ SchemeMorphism_point_abelian_variety_field):
483
+ """
484
+ A point on an elliptic curve over a field. The point has coordinates
485
+ in the base field.
486
+
487
+ EXAMPLES::
488
+
489
+ sage: # needs database_cremona_mini_ellcurve
490
+ sage: E = EllipticCurve('37a')
491
+ sage: E([0,0])
492
+ (0 : 0 : 1)
493
+ sage: E(0,0) # brackets are optional
494
+ (0 : 0 : 1)
495
+ sage: E([GF(5)(0), 0]) # entries are coerced
496
+ (0 : 0 : 1)
497
+ sage: E(0.000, 0)
498
+ (0 : 0 : 1)
499
+ sage: E(1,0,0)
500
+ Traceback (most recent call last):
501
+ ...
502
+ TypeError: Coordinates [1, 0, 0] do not define a point on
503
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
504
+
505
+ ::
506
+
507
+ sage: E = EllipticCurve([0,0,1,-1,0])
508
+ sage: S = E(QQ); S
509
+ Abelian group of points on
510
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
511
+
512
+ sage: # needs sage.rings.number_field
513
+ sage: x = polygen(ZZ, 'x')
514
+ sage: K.<i> = NumberField(x^2 + 1)
515
+ sage: E = EllipticCurve(K, [0,1,0,-160,308])
516
+ sage: P = E(26, -120)
517
+ sage: Q = E(2+12*i, -36+48*i)
518
+ sage: P.order() == Q.order() == 4 # long time
519
+ True
520
+ sage: 2*P == 2*Q
521
+ False
522
+
523
+ ::
524
+
525
+ sage: K.<t> = FractionField(PolynomialRing(QQ,'t'))
526
+ sage: E = EllipticCurve([0,0,0,0,t^2])
527
+ sage: P = E(0,t)
528
+ sage: P, 2*P, 3*P
529
+ ((0 : t : 1), (0 : -t : 1), (0 : 1 : 0))
530
+
531
+ TESTS::
532
+
533
+ sage: loads(S.dumps()) == S
534
+ True
535
+
536
+ sage: # needs database_cremona_mini_ellcurve
537
+ sage: E = EllipticCurve('37a')
538
+ sage: P = E(0,0); P
539
+ (0 : 0 : 1)
540
+ sage: loads(P.dumps()) == P
541
+ True
542
+ sage: T = 100*P
543
+ sage: loads(T.dumps()) == T
544
+ True
545
+
546
+ Test pickling an elliptic curve that has known points on it::
547
+
548
+ sage: e = EllipticCurve([0, 0, 1, -1, 0]); g = e.gens(); loads(dumps(e)) == e # needs eclib
549
+ True
550
+
551
+ Test that the refactoring from :issue:`14711` did preserve the behaviour
552
+ of domain and codomain::
553
+
554
+ sage: E = EllipticCurve(QQ,[1,1])
555
+ sage: P = E(0,1)
556
+ sage: P.domain()
557
+ Spectrum of Rational Field
558
+ sage: K.<a> = NumberField(x^2 - 3, 'a') # needs sage.rings.number_field
559
+ sage: P = E.base_extend(K)(1,a) # needs sage.rings.number_field
560
+ sage: P.domain() # needs sage.rings.number_field
561
+ Spectrum of Number Field in a with defining polynomial x^2 - 3
562
+ sage: P.codomain() # needs sage.rings.number_field
563
+ Elliptic Curve defined by y^2 = x^3 + x + 1
564
+ over Number Field in a with defining polynomial x^2 - 3
565
+ sage: P.codomain() == P.curve() # needs sage.rings.number_field
566
+ True
567
+ """
568
+ def __init__(self, curve, v, check=True):
569
+ """
570
+ Constructor for a point on an elliptic curve.
571
+
572
+ INPUT:
573
+
574
+ - ``curve`` -- an elliptic curve
575
+ - ``v`` -- data determining a point (another point, the integer
576
+ 0, or a tuple of coordinates)
577
+
578
+ EXAMPLES::
579
+
580
+ sage: # needs database_cremona_mini_ellcurve
581
+ sage: E = EllipticCurve('43a')
582
+ sage: P = E([2, -4, 2]); P
583
+ (1 : -2 : 1)
584
+ sage: P == E([1,-2])
585
+ True
586
+ sage: P = E(0); P
587
+ (0 : 1 : 0)
588
+ sage: P=E(2, -4, 2); P
589
+ (1 : -2 : 1)
590
+ """
591
+ point_homset = curve.point_homset()
592
+ R = point_homset.value_ring()
593
+ if isinstance(v, SchemeMorphism):
594
+ v = list(v)
595
+ elif v == 0:
596
+ v = (R.zero(), R.one(), R.zero())
597
+
598
+ SchemeMorphism_point_abelian_variety_field.__init__(self, point_homset, v, check=check)
599
+
600
+ self.normalize_coordinates()
601
+
602
+ def _repr_(self):
603
+ """
604
+ Return a string representation of this point.
605
+
606
+ EXAMPLES::
607
+
608
+ sage: # needs database_cremona_mini_ellcurve
609
+ sage: E = EllipticCurve('39a')
610
+ sage: P = E([-2, 1, 1])
611
+ sage: P._repr_()
612
+ '(-2 : 1 : 1)'
613
+ """
614
+ return self.codomain().ambient_space()._repr_generic_point(self._coords)
615
+
616
+ def _latex_(self):
617
+ """
618
+ Return a LaTeX representation of this point.
619
+
620
+ EXAMPLES::
621
+
622
+ sage: # needs database_cremona_mini_ellcurve
623
+ sage: E = EllipticCurve('40a')
624
+ sage: P = E([3, 0])
625
+ sage: P._latex_()
626
+ '\\left(3 : 0 : 1\\right)'
627
+ """
628
+ return self.codomain().ambient_space()._latex_generic_point(self._coords)
629
+
630
+ def __getitem__(self, n):
631
+ """
632
+ Return the n'th coordinate of this point.
633
+
634
+ EXAMPLES::
635
+
636
+ sage: # needs database_cremona_mini_ellcurve
637
+ sage: E = EllipticCurve('42a')
638
+ sage: P = E([-17, -51, 17])
639
+ sage: [P[i] for i in [2,1,0]]
640
+ [1, -3, -1]
641
+ """
642
+ return self._coords[n]
643
+
644
+ def __iter__(self):
645
+ """
646
+ Return the coordinates of this point as a list.
647
+
648
+ EXAMPLES::
649
+
650
+ sage: # needs database_cremona_mini_ellcurve
651
+ sage: E = EllipticCurve('37a')
652
+ sage: list(E([0,0]))
653
+ [0, 0, 1]
654
+ """
655
+ return iter(self._coords)
656
+
657
+ def __tuple__(self):
658
+ """
659
+ Return the coordinates of this point as a tuple.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: # needs database_cremona_mini_ellcurve
664
+ sage: E = EllipticCurve('44a')
665
+ sage: P = E([1, -2, 1])
666
+ sage: P.__tuple__()
667
+ (1, -2, 1)
668
+ """
669
+ return tuple(self._coords) # Warning: _coords is a list!
670
+
671
+ def _richcmp_(self, other, op):
672
+ """
673
+ Comparison function for points to allow sorting and equality testing.
674
+
675
+ EXAMPLES::
676
+
677
+ sage: # needs database_cremona_mini_ellcurve
678
+ sage: E = EllipticCurve('45a')
679
+ sage: P = E([2, -1, 1])
680
+ sage: P == E(0)
681
+ False
682
+ sage: P+P == E(0)
683
+ True
684
+
685
+ The additive identity is always the minimum element::
686
+
687
+ sage: E = EllipticCurve(GF(103), [3, 5])
688
+ sage: min(E.points()) == 0
689
+ True
690
+ """
691
+ if not isinstance(other, EllipticCurvePoint_field):
692
+ try:
693
+ other = self.codomain().ambient_space()(other)
694
+ except TypeError:
695
+ return NotImplemented
696
+ # op_EQ
697
+ if op == 2:
698
+ return richcmp(self._coords, other._coords, op)
699
+
700
+ try:
701
+ return richcmp(self._zxy_coords, other._zxy_coords, op)
702
+ except AttributeError:
703
+ # Compute _zxy_coords
704
+ # There is a chance that we recompute this for either ``self`` or
705
+ # ``other`` However, in the most common use case which is sorting
706
+ # list of `n` variables This will cause a O(n) cost only. If there
707
+ # is a better way feel free to implement it!
708
+ self._zxy_coords = (self._coords[2], self._coords[0], self._coords[1])
709
+ other._zxy_coords = (other._coords[2], other._coords[0], other._coords[1])
710
+ return richcmp(self._zxy_coords, other._zxy_coords, op)
711
+
712
+ def __pari__(self):
713
+ r"""
714
+ Convert this point to PARI format.
715
+
716
+ EXAMPLES::
717
+
718
+ sage: E = EllipticCurve([0,0,0,3,0])
719
+ sage: O = E(0)
720
+ sage: P = E.point([1,2])
721
+ sage: O.__pari__()
722
+ [0]
723
+ sage: P.__pari__()
724
+ [1, 2]
725
+
726
+ The following implicitly calls O.__pari__() and P.__pari__()::
727
+
728
+ sage: pari(E).elladd(O,P)
729
+ [1, 2]
730
+
731
+ TESTS:
732
+
733
+ Try the same over a finite field::
734
+
735
+ sage: E = EllipticCurve(GF(11), [0,0,0,3,0])
736
+ sage: O = E(0)
737
+ sage: P = E.point([1,2])
738
+ sage: O.__pari__()
739
+ [0]
740
+ sage: P.__pari__()
741
+ [Mod(1, 11), Mod(2, 11)]
742
+
743
+ We no longer need to explicitly call ``pari(O)`` and ``pari(P)``
744
+ after :issue:`11868`::
745
+
746
+ sage: pari(E).elladd(O, P)
747
+ [Mod(1, 11), Mod(2, 11)]
748
+ """
749
+ x,y,z = self._coords
750
+ if z:
751
+ return pari([x/z, y/z])
752
+ else:
753
+ return pari([0])
754
+
755
+ def order(self):
756
+ r"""
757
+ Return the order of this point on the elliptic curve.
758
+
759
+ If the point is zero, returns 1, otherwise raise a
760
+ :exc:`NotImplementedError`.
761
+
762
+ For curves over number fields and finite fields, see below.
763
+
764
+ .. NOTE::
765
+
766
+ :meth:`additive_order` is a synonym for :meth:`order`
767
+
768
+ EXAMPLES::
769
+
770
+ sage: K.<t> = FractionField(PolynomialRing(QQ,'t'))
771
+ sage: E = EllipticCurve([0, 0, 0, -t^2, 0])
772
+ sage: P = E(t,0)
773
+ sage: P.order()
774
+ Traceback (most recent call last):
775
+ ...
776
+ NotImplementedError: Computation of order of a point not implemented
777
+ over general fields.
778
+ sage: E(0).additive_order()
779
+ 1
780
+ sage: E(0).order() == 1
781
+ True
782
+ """
783
+ if hasattr(self, "_order"):
784
+ return self._order
785
+ if self.is_zero():
786
+ self._order = Integer(1)
787
+ return self._order
788
+ raise NotImplementedError("Computation of order of a point "
789
+ "not implemented over general fields.")
790
+
791
+ additive_order = order
792
+
793
+ def __bool__(self) -> bool:
794
+ """
795
+ Return ``True`` if this is not the zero point on the curve.
796
+
797
+ EXAMPLES::
798
+
799
+ sage: # needs database_cremona_mini_ellcurve
800
+ sage: E = EllipticCurve('37a')
801
+ sage: P = E(0); P
802
+ (0 : 1 : 0)
803
+ sage: P.is_zero()
804
+ True
805
+ sage: P = E.gens()[0] # needs eclib
806
+ sage: P.is_zero() # needs eclib
807
+ False
808
+ """
809
+ return bool(self._coords[2])
810
+
811
+ def has_order(self, n) -> bool:
812
+ r"""
813
+ Test if this point has order exactly `n`.
814
+
815
+ INPUT:
816
+
817
+ - ``n`` -- integer or its :class:`~sage.structure.factorization.Factorization`
818
+
819
+ ALGORITHM:
820
+
821
+ Compare a cached order if available, otherwise use :func:`sage.groups.generic.has_order`.
822
+
823
+ EXAMPLES::
824
+
825
+ sage: # needs database_cremona_mini_ellcurve
826
+ sage: E = EllipticCurve('26b1')
827
+ sage: P = E(1, 0)
828
+ sage: P.has_order(7)
829
+ True
830
+ sage: P._order
831
+ 7
832
+ sage: P.has_order(7)
833
+ True
834
+
835
+ It also works with a :class:`~sage.structure.factorization.Factorization` object::
836
+
837
+ sage: E = EllipticCurve(GF(419), [1,0])
838
+ sage: P = E(-33, 8)
839
+ sage: P.has_order(factor(21))
840
+ True
841
+ sage: P._order
842
+ 21
843
+ sage: P.has_order(factor(21))
844
+ True
845
+
846
+ This method can be much faster than computing the order and comparing::
847
+
848
+ sage: # not tested -- timings are different each time
849
+ sage: p = 4 * prod(primes(3,377)) * 587 - 1
850
+ sage: E = EllipticCurve(GF(p), [1,0])
851
+ sage: %timeit P = E.random_point(); P.set_order(multiple=p+1)
852
+ 72.4 ms ± 773 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
853
+ sage: %timeit P = E.random_point(); P.has_order(p+1)
854
+ 32.8 ms ± 3.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
855
+ sage: fac = factor(p+1)
856
+ sage: %timeit P = E.random_point(); P.has_order(fac)
857
+ 30.6 ms ± 3.48 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
858
+
859
+ The order is cached once it has been confirmed once, and the cache is
860
+ shared with :meth:`order`::
861
+
862
+ sage: # not tested -- timings are different each time
863
+ sage: P, = E.gens()
864
+ sage: delattr(P, '_order')
865
+ sage: %time P.has_order(p+1)
866
+ CPU times: user 83.6 ms, sys: 30 µs, total: 83.6 ms
867
+ Wall time: 83.8 ms
868
+ True
869
+ sage: %time P.has_order(p+1)
870
+ CPU times: user 31 µs, sys: 2 µs, total: 33 µs
871
+ Wall time: 37.9 µs
872
+ True
873
+ sage: %time P.order()
874
+ CPU times: user 11 µs, sys: 0 ns, total: 11 µs
875
+ Wall time: 16 µs
876
+ 5326738796327623094747867617954605554069371494832722337612446642054009560026576537626892113026381253624626941643949444792662881241621373288942880288065660
877
+ sage: delattr(P, '_order')
878
+ sage: %time P.has_order(fac)
879
+ CPU times: user 68.6 ms, sys: 17 µs, total: 68.7 ms
880
+ Wall time: 68.7 ms
881
+ True
882
+ sage: %time P.has_order(fac)
883
+ CPU times: user 92 µs, sys: 0 ns, total: 92 µs
884
+ Wall time: 97.5 µs
885
+ True
886
+ sage: %time P.order()
887
+ CPU times: user 10 µs, sys: 1e+03 ns, total: 11 µs
888
+ Wall time: 14.5 µs
889
+ 5326738796327623094747867617954605554069371494832722337612446642054009560026576537626892113026381253624626941643949444792662881241621373288942880288065660
890
+
891
+ TESTS::
892
+
893
+ sage: E = EllipticCurve([1,2,3,4,5])
894
+ sage: E(0).has_order(1)
895
+ True
896
+ sage: E(0).has_order(Factorization([]))
897
+ True
898
+ """
899
+ if hasattr(self, '_order'): # already known
900
+ if not isinstance(n, Integer):
901
+ n = n.value()
902
+ return self._order == n
903
+ ret = generic.has_order(self, n, operation='+')
904
+ if ret and not hasattr(self, '_order'): # known now; cache
905
+ if not isinstance(n, Integer):
906
+ n = n.value()
907
+ self._order = n
908
+ return ret
909
+
910
+ def has_finite_order(self) -> bool:
911
+ """
912
+ Return ``True`` if this point has finite additive order as an
913
+ element of the group of points on this curve.
914
+
915
+ For fields other than number fields and finite fields, this is
916
+ NotImplemented unless self.is_zero().
917
+
918
+ EXAMPLES::
919
+
920
+ sage: K.<t> = FractionField(PolynomialRing(QQ,'t'))
921
+ sage: E = EllipticCurve([0, 0, 0, -t^2, 0])
922
+ sage: P = E(0)
923
+ sage: P.has_finite_order()
924
+ True
925
+ sage: P = E(t,0)
926
+ sage: P.has_finite_order()
927
+ Traceback (most recent call last):
928
+ ...
929
+ NotImplementedError: Computation of order of a point not implemented
930
+ over general fields.
931
+ sage: (2*P).is_zero()
932
+ True
933
+ """
934
+ if self.is_zero():
935
+ return True
936
+ return self.order() != oo
937
+
938
+ is_finite_order = has_finite_order # for backward compatibility
939
+
940
+ def has_infinite_order(self) -> bool:
941
+ """
942
+ Return ``True`` if this point has infinite additive order as an element
943
+ of the group of points on this curve.
944
+
945
+ For fields other than number fields and finite fields, this is
946
+ NotImplemented unless ``self.is_zero()``.
947
+
948
+ EXAMPLES::
949
+
950
+ sage: K.<t> = FractionField(PolynomialRing(QQ,'t'))
951
+ sage: E = EllipticCurve([0, 0, 0, -t^2, 0])
952
+ sage: P = E(0)
953
+ sage: P.has_infinite_order()
954
+ False
955
+ sage: P = E(t,0)
956
+ sage: P.has_infinite_order()
957
+ Traceback (most recent call last):
958
+ ...
959
+ NotImplementedError: Computation of order of a point not implemented over general fields.
960
+ sage: (2*P).is_zero()
961
+ True
962
+ """
963
+ if self.is_zero():
964
+ return False
965
+ return self.order() == oo
966
+
967
+ def plot(self, **args):
968
+ """
969
+ Plot this point on an elliptic curve.
970
+
971
+ INPUT:
972
+
973
+ - ``**args`` -- all arguments get passed directly onto the point
974
+ plotting function
975
+
976
+ EXAMPLES::
977
+
978
+ sage: # needs database_cremona_mini_ellcurve
979
+ sage: E = EllipticCurve('389a')
980
+ sage: P = E([-1,1])
981
+ sage: P.plot(pointsize=30, rgbcolor=(1,0,0)) # needs sage.plot
982
+ Graphics object consisting of 1 graphics primitive
983
+ """
984
+ from sage.plot.point import point
985
+ from sage.plot.text import text
986
+
987
+ if self.is_zero():
988
+ return text("$\\infty$", (-3, 3), **args)
989
+ else:
990
+ return point((self[0], self[1]), **args)
991
+
992
+ def _add_(self, other):
993
+ r"""
994
+ Add this point to another point on the same elliptic curve.
995
+
996
+ This method is specialized to elliptic curves over fields.
997
+
998
+ EXAMPLES::
999
+
1000
+ sage: # needs database_cremona_mini_ellcurve
1001
+ sage: E = EllipticCurve('389a')
1002
+ sage: P = E([-1,1]); Q = E([0,0])
1003
+ sage: P + Q
1004
+ (1 : 0 : 1)
1005
+ sage: P._add_(Q) == P + Q
1006
+ True
1007
+
1008
+ TESTS:
1009
+
1010
+ Example to show that bug :issue:`4820` is fixed::
1011
+
1012
+ sage: # needs database_cremona_mini_ellcurve
1013
+ sage: [type(c) for c in 2*EllipticCurve('37a1').gen(0)] # needs eclib
1014
+ [<... 'sage.rings.rational.Rational'>,
1015
+ <... 'sage.rings.rational.Rational'>,
1016
+ <... 'sage.rings.rational.Rational'>]
1017
+
1018
+ Checks that :issue:`15964` is fixed::
1019
+
1020
+ sage: N = 1715761513
1021
+ sage: E = EllipticCurve(Integers(N), [3,-13])
1022
+ sage: E.assume_base_ring_is_field()
1023
+ sage: P = E(2,1)
1024
+ sage: LCM([2..60])*P
1025
+ Traceback (most recent call last):
1026
+ ...
1027
+ ZeroDivisionError: Inverse of 26927 does not exist
1028
+ (characteristic = 1715761513 = 26927*63719)
1029
+
1030
+ sage: N = 35
1031
+ sage: E = EllipticCurve(Integers(N), [5,1])
1032
+ sage: E.assume_base_ring_is_field()
1033
+ sage: P = E(0,1)
1034
+ sage: 4*P
1035
+ Traceback (most recent call last):
1036
+ ...
1037
+ ZeroDivisionError: Inverse of 7 does not exist
1038
+ (characteristic = 35 = 7*5)
1039
+
1040
+ Checks that :issue:`34681` is fixed::
1041
+
1042
+ sage: P+P
1043
+ (15 : 14 : 1)
1044
+ sage: 2*P
1045
+ (15 : 14 : 1)
1046
+ """
1047
+ # Use Prop 7.1.7 of Cohen "A Course in Computational Algebraic Number Theory"
1048
+
1049
+ if self.is_zero():
1050
+ return other
1051
+ if other.is_zero():
1052
+ return self
1053
+
1054
+ E = self.curve()
1055
+ a1, a2, a3, a4, a6 = E.ainvs()
1056
+ x1, y1 = self.xy()
1057
+ x2, y2 = other.xy()
1058
+
1059
+ if x1 == x2 and y1 == -y2 - a1*x2 - a3:
1060
+ return E(0) # point at infinity
1061
+
1062
+ try:
1063
+ if x1 == x2 and y1 == y2:
1064
+ m = (3*x1*x1 + 2*a2*x1 + a4 - a1*y1) / (2*y1 + a1*x1 + a3)
1065
+ else:
1066
+ m = (y1 - y2) / (x1 - x2)
1067
+ except ZeroDivisionError as ex:
1068
+ try:
1069
+ d = next(d for d in (x1 - x2, 2*y1 + a1*x1 + a3) if d and not d.is_unit())
1070
+ m, = d.parent().defining_ideal().gens()
1071
+ f1 = d.lift().gcd(m)
1072
+ f2 = m // f1
1073
+ assert m == f1 * f2
1074
+ except Exception:
1075
+ raise ex
1076
+ else:
1077
+ raise ZeroDivisionError(f'Inverse of {d} does not exist (characteristic = {m} = {f1}*{f2})')
1078
+
1079
+ x3 = -x1 - x2 - a2 + m*(m+a1)
1080
+ y3 = -y1 - a3 - a1*x3 + m*(x1-x3)
1081
+ # See trac #4820 for why we need to coerce 1 into the base ring here:
1082
+ return E.point([x3, y3, E.base_ring().one()], check=False)
1083
+
1084
+ _sub_ = EllipticCurvePoint._sub_
1085
+
1086
+ def _neg_(self):
1087
+ """
1088
+ Return the additive inverse of this point.
1089
+
1090
+ Same as :meth:`EllipticCurvePoint._neg_`, but specialized
1091
+ to points over fields, which are normalized to satisfy `z=1`.
1092
+
1093
+ EXAMPLES::
1094
+
1095
+ sage: # needs database_cremona_mini_ellcurve
1096
+ sage: E = EllipticCurve('389a')
1097
+ sage: P = E([-1,1])
1098
+ sage: Q = -P; Q
1099
+ (-1 : -2 : 1)
1100
+ sage: Q + P
1101
+ (0 : 1 : 0)
1102
+
1103
+ Example to show that bug :issue:`4820` is fixed::
1104
+
1105
+ sage: # needs database_cremona_mini_ellcurve
1106
+ sage: [type(c) for c in -EllipticCurve('37a1').gen(0)] # needs eclib
1107
+ [<... 'sage.rings.rational.Rational'>,
1108
+ <... 'sage.rings.rational.Rational'>,
1109
+ <... 'sage.rings.rational.Rational'>]
1110
+ """
1111
+ if self.is_zero():
1112
+ return self
1113
+ E, x, y = self.curve(), self[0], self[1]
1114
+ # See trac #4820 for why we need to coerce 1 into the base ring here:
1115
+ return E.point([x, -y - E.a1()*x - E.a3(), E.base_ring().one()], check=False)
1116
+
1117
+ def xy(self):
1118
+ """
1119
+ Return the `x` and `y` coordinates of this point, as a 2-tuple.
1120
+ If this is the point at infinity, a :exc:`ZeroDivisionError` is raised.
1121
+
1122
+ EXAMPLES::
1123
+
1124
+ sage: # needs database_cremona_mini_ellcurve
1125
+ sage: E = EllipticCurve('389a')
1126
+ sage: P = E([-1,1])
1127
+ sage: P.xy()
1128
+ (-1, 1)
1129
+ sage: Q = E(0); Q
1130
+ (0 : 1 : 0)
1131
+ sage: Q.xy()
1132
+ Traceback (most recent call last):
1133
+ ...
1134
+ ZeroDivisionError: rational division by zero
1135
+ """
1136
+ if self[2].is_one():
1137
+ return self[0], self[1]
1138
+ else:
1139
+ return self[0]/self[2], self[1]/self[2]
1140
+
1141
+ def x(self):
1142
+ """
1143
+ Return the `x` coordinate of this point, as an element of the base field.
1144
+ If this is the point at infinity, a :exc:`ZeroDivisionError` is raised.
1145
+
1146
+ EXAMPLES::
1147
+
1148
+ sage: # needs database_cremona_mini_ellcurve
1149
+ sage: E = EllipticCurve('389a')
1150
+ sage: P = E([-1,1])
1151
+ sage: P.x()
1152
+ -1
1153
+ sage: Q = E(0); Q
1154
+ (0 : 1 : 0)
1155
+ sage: Q.x()
1156
+ Traceback (most recent call last):
1157
+ ...
1158
+ ZeroDivisionError: rational division by zero
1159
+ """
1160
+ if self[2].is_one():
1161
+ return self[0]
1162
+ else:
1163
+ return self[0]/self[2]
1164
+
1165
+ def y(self):
1166
+ """
1167
+ Return the `y` coordinate of this point, as an element of the base field.
1168
+ If this is the point at infinity, a :exc:`ZeroDivisionError` is raised.
1169
+
1170
+ EXAMPLES::
1171
+
1172
+ sage: # needs database_cremona_mini_ellcurve
1173
+ sage: E = EllipticCurve('389a')
1174
+ sage: P = E([-1,1])
1175
+ sage: P.y()
1176
+ 1
1177
+ sage: Q = E(0); Q
1178
+ (0 : 1 : 0)
1179
+ sage: Q.y()
1180
+ Traceback (most recent call last):
1181
+ ...
1182
+ ZeroDivisionError: rational division by zero
1183
+ """
1184
+ if self[2].is_one():
1185
+ return self[1]
1186
+ else:
1187
+ return self[1]/self[2]
1188
+
1189
+ def is_divisible_by(self, m):
1190
+ """
1191
+ Return ``True`` if there exists a point `Q` defined over the same
1192
+ field as ``self`` such that `mQ` == ``self``.
1193
+
1194
+ INPUT:
1195
+
1196
+ - ``m`` -- positive integer
1197
+
1198
+ OUTPUT:
1199
+
1200
+ boolean; ``True`` if there is a solution, else False.
1201
+
1202
+ .. WARNING::
1203
+
1204
+ This function usually triggers the computation of the
1205
+ `m`-th division polynomial of the associated elliptic
1206
+ curve, which will be expensive if `m` is large, though it
1207
+ will be cached for subsequent calls with the same `m`.
1208
+
1209
+ EXAMPLES::
1210
+
1211
+ sage: # needs database_cremona_mini_ellcurve
1212
+ sage: E = EllipticCurve('389a')
1213
+ sage: Q = 5*E(0,0); Q
1214
+ (-2739/1444 : -77033/54872 : 1)
1215
+ sage: Q.is_divisible_by(4)
1216
+ False
1217
+ sage: Q.is_divisible_by(5)
1218
+ True
1219
+
1220
+ A finite field example::
1221
+
1222
+ sage: E = EllipticCurve(GF(101), [23,34])
1223
+ sage: E.cardinality().factor()
1224
+ 2 * 53
1225
+ sage: Set([T.order() for T in E.points()])
1226
+ {1, 106, 2, 53}
1227
+ sage: len([T for T in E.points() if T.is_divisible_by(2)])
1228
+ 53
1229
+ sage: len([T for T in E.points() if T.is_divisible_by(3)])
1230
+ 106
1231
+
1232
+ TESTS:
1233
+
1234
+ This shows that the bug reported at :issue:`10076` is fixed::
1235
+
1236
+ sage: # needs sage.rings.number_field
1237
+ sage: K = QuadraticField(8,'a')
1238
+ sage: E = EllipticCurve([K(0),0,0,-1,0])
1239
+ sage: P = E([-1,0])
1240
+ sage: P.is_divisible_by(2)
1241
+ False
1242
+ sage: P.division_points(2)
1243
+ []
1244
+
1245
+ Note that it is not sufficient to test that
1246
+ ``self.division_points(m,poly_only=True)`` has roots::
1247
+
1248
+ sage: P.division_points(2, poly_only=True).roots() # needs sage.rings.number_field
1249
+ [(1/2*a - 1, 1), (-1/2*a - 1, 1)]
1250
+
1251
+ sage: # needs sage.rings.number_field
1252
+ sage: tor = E.torsion_points(); len(tor)
1253
+ 8
1254
+ sage: [T.order() for T in tor]
1255
+ [1, 2, 4, 4, 2, 2, 4, 4]
1256
+ sage: all(T.is_divisible_by(3) for T in tor)
1257
+ True
1258
+ sage: sorted(T for T in tor if T.is_divisible_by(2))
1259
+ [(0 : 1 : 0), (1 : 0 : 1)]
1260
+ sage: sorted(Set([2*T for T in tor]))
1261
+ [(0 : 1 : 0), (1 : 0 : 1)]
1262
+ """
1263
+ # Coerce the input m to an integer
1264
+ m = Integer(m)
1265
+
1266
+ # Check for trivial cases of m = 1, -1 and 0.
1267
+ if m == 1 or m == -1:
1268
+ return True
1269
+ if m == 0:
1270
+ return self == 0 # then m*self=self for all m!
1271
+ m = m.abs()
1272
+
1273
+ # Now the following line would of course be correct, but we
1274
+ # work harder to be more efficient:
1275
+ # return len(self.division_points(m)) > 0
1276
+
1277
+ P = self
1278
+
1279
+ # If P has finite order n and gcd(m,n)=1 then the result is
1280
+ # True. However, over general fields computing P.order() is
1281
+ # not implemented.
1282
+
1283
+ try:
1284
+ n = P.order()
1285
+ if not n == oo:
1286
+ if m.gcd(n) == 1:
1287
+ return True
1288
+ except NotImplementedError:
1289
+ pass
1290
+
1291
+ P_is_2_torsion = (P == -P)
1292
+ g = P.division_points(m, poly_only=True)
1293
+
1294
+ if not P_is_2_torsion:
1295
+ # In this case deg(g)=m^2, and each root in K lifts to two
1296
+ # points Q,-Q both in E(K), of which exactly one is a
1297
+ # solution. So we just check the existence of roots:
1298
+ return len(g.roots()) > 0
1299
+
1300
+ # Now 2*P==0
1301
+
1302
+ if m % 2 == 1:
1303
+ return True # P itself is a solution when m is odd
1304
+
1305
+ # Now m is even and 2*P=0. Roots of g in K may or may not
1306
+ # lift to solutions in E(K), so we fall back to the default.
1307
+ # Note that division polynomials are cached so this is not
1308
+ # inefficient:
1309
+
1310
+ return len(self.division_points(m)) > 0
1311
+
1312
+ def division_points(self, m, poly_only=False):
1313
+ r"""
1314
+ Return a list of all points `Q` such that `mQ=P` where `P` = ``self``.
1315
+
1316
+ Only points on the elliptic curve containing ``self`` and defined
1317
+ over the base field are included.
1318
+
1319
+ INPUT:
1320
+
1321
+ - ``m`` -- positive integer
1322
+
1323
+ - ``poly_only`` -- boolean (default: ``False``); if ``True`` return
1324
+ polynomial whose roots give all possible `x`-coordinates of
1325
+ `m`-th roots of ``self``
1326
+
1327
+ OUTPUT: a (possibly empty) list of solutions `Q` to `mQ=P`,
1328
+ where `P` = ``self``
1329
+
1330
+ EXAMPLES:
1331
+
1332
+ We find the five 5-torsion points on an elliptic curve::
1333
+
1334
+ sage: # needs database_cremona_mini_ellcurve
1335
+ sage: E = EllipticCurve('11a'); E
1336
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
1337
+ sage: P = E(0); P
1338
+ (0 : 1 : 0)
1339
+ sage: P.division_points(5)
1340
+ [(0 : 1 : 0), (5 : -6 : 1), (5 : 5 : 1), (16 : -61 : 1), (16 : 60 : 1)]
1341
+
1342
+ Note above that 0 is included since [5]*0 = 0.
1343
+
1344
+ We create a curve of rank 1 with no torsion and do a consistency check::
1345
+
1346
+ sage: # needs database_cremona_mini_ellcurve
1347
+ sage: E = EllipticCurve('11a').quadratic_twist(-7)
1348
+ sage: Q = E([44,-270])
1349
+ sage: (4*Q).division_points(4)
1350
+ [(44 : -270 : 1)]
1351
+
1352
+ We create a curve over a non-prime finite field with group of
1353
+ order `18`::
1354
+
1355
+ sage: # needs sage.rings.finite_rings
1356
+ sage: k.<a> = GF((5,2))
1357
+ sage: E = EllipticCurve(k, [1,2+a,3,4*a,2])
1358
+ sage: P = E([3, 3*a+4])
1359
+ sage: factor(E.order())
1360
+ 2 * 3^2
1361
+ sage: P.order()
1362
+ 9
1363
+
1364
+ We find the `1`-division points as a consistency check -- there
1365
+ is just one, of course::
1366
+
1367
+ sage: P.division_points(1) # needs sage.rings.finite_rings
1368
+ [(3 : 3*a + 4 : 1)]
1369
+
1370
+ The point `P` has order coprime to 2 but divisible by 3, so::
1371
+
1372
+ sage: P.division_points(2) # needs sage.rings.finite_rings
1373
+ [(2*a + 1 : 3*a + 4 : 1), (3*a + 1 : a : 1)]
1374
+
1375
+ We check that each of the 2-division points works as claimed::
1376
+
1377
+ sage: [2*Q for Q in P.division_points(2)] # needs sage.rings.finite_rings
1378
+ [(3 : 3*a + 4 : 1), (3 : 3*a + 4 : 1)]
1379
+
1380
+ Some other checks::
1381
+
1382
+ sage: P.division_points(3) # needs sage.rings.finite_rings
1383
+ []
1384
+ sage: P.division_points(4) # needs sage.rings.finite_rings
1385
+ [(0 : 3*a + 2 : 1), (1 : 0 : 1)]
1386
+ sage: P.division_points(5) # needs sage.rings.finite_rings
1387
+ [(1 : 1 : 1)]
1388
+
1389
+ An example over a number field (see :issue:`3383`)::
1390
+
1391
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
1392
+ sage: E = EllipticCurve('19a1')
1393
+ sage: x = polygen(ZZ, 'x')
1394
+ sage: K.<t> = NumberField(x^9 - 3*x^8 - 4*x^7 + 16*x^6 - 3*x^5
1395
+ ....: - 21*x^4 + 5*x^3 + 7*x^2 - 7*x + 1)
1396
+ sage: EK = E.base_extend(K)
1397
+ sage: E(0).division_points(3)
1398
+ [(0 : 1 : 0), (5 : -10 : 1), (5 : 9 : 1)]
1399
+ sage: EK(0).division_points(3)
1400
+ [(0 : 1 : 0), (5 : 9 : 1), (5 : -10 : 1)]
1401
+ sage: E(0).division_points(9)
1402
+ [(0 : 1 : 0), (5 : -10 : 1), (5 : 9 : 1)]
1403
+ sage: EK(0).division_points(9)
1404
+ [(0 : 1 : 0), (5 : 9 : 1), (5 : -10 : 1), (-150/121*t^8 + 414/121*t^7 + 1481/242*t^6 - 2382/121*t^5 - 103/242*t^4 + 629/22*t^3 - 367/242*t^2 - 1307/121*t + 625/121 : 35/484*t^8 - 133/242*t^7 + 445/242*t^6 - 799/242*t^5 + 373/484*t^4 + 113/22*t^3 - 2355/484*t^2 - 753/242*t + 1165/484 : 1), (-150/121*t^8 + 414/121*t^7 + 1481/242*t^6 - 2382/121*t^5 - 103/242*t^4 + 629/22*t^3 - 367/242*t^2 - 1307/121*t + 625/121 : -35/484*t^8 + 133/242*t^7 - 445/242*t^6 + 799/242*t^5 - 373/484*t^4 - 113/22*t^3 + 2355/484*t^2 + 753/242*t - 1649/484 : 1), (-1383/484*t^8 + 970/121*t^7 + 3159/242*t^6 - 5211/121*t^5 + 37/484*t^4 + 654/11*t^3 - 909/484*t^2 - 4831/242*t + 6791/484 : 927/121*t^8 - 5209/242*t^7 - 8187/242*t^6 + 27975/242*t^5 - 1147/242*t^4 - 1729/11*t^3 + 1566/121*t^2 + 12873/242*t - 10871/242 : 1), (-1383/484*t^8 + 970/121*t^7 + 3159/242*t^6 - 5211/121*t^5 + 37/484*t^4 + 654/11*t^3 - 909/484*t^2 - 4831/242*t + 6791/484 : -927/121*t^8 + 5209/242*t^7 + 8187/242*t^6 - 27975/242*t^5 + 1147/242*t^4 + 1729/11*t^3 - 1566/121*t^2 - 12873/242*t + 10629/242 : 1), (-4793/484*t^8 + 6791/242*t^7 + 10727/242*t^6 - 18301/121*t^5 + 2347/484*t^4 + 2293/11*t^3 - 7311/484*t^2 - 17239/242*t + 26767/484 : 30847/484*t^8 - 21789/121*t^7 - 34605/121*t^6 + 117164/121*t^5 - 10633/484*t^4 - 29437/22*t^3 + 39725/484*t^2 + 55428/121*t - 176909/484 : 1), (-4793/484*t^8 + 6791/242*t^7 + 10727/242*t^6 - 18301/121*t^5 + 2347/484*t^4 + 2293/11*t^3 - 7311/484*t^2 - 17239/242*t + 26767/484 : -30847/484*t^8 + 21789/121*t^7 + 34605/121*t^6 - 117164/121*t^5 + 10633/484*t^4 + 29437/22*t^3 - 39725/484*t^2 - 55428/121*t + 176425/484 : 1)]
1405
+
1406
+ TESTS:
1407
+
1408
+ Check that :issue:`24844` is fixed::
1409
+
1410
+ sage: # needs sage.rings.finite_rings
1411
+ sage: p = next_prime(1000000)
1412
+ sage: E = EllipticCurve(GF(p), 123, 456)
1413
+ sage: pts = E(0).division_points(3)
1414
+ sage: P = pts[1]; P
1415
+ (389063 : 124244 : 1)
1416
+ sage: P._order
1417
+ 3
1418
+
1419
+ When we successfully divide a point known to have infinite
1420
+ order, the points returned know that they also have infinite
1421
+ order::
1422
+
1423
+ sage: E = EllipticCurve([0,0,1,-1,0])
1424
+ sage: P = E(-1,0)
1425
+ sage: P.order()
1426
+ +Infinity
1427
+ sage: pts = P.division_points(3); len(pts)
1428
+ 1
1429
+ sage: [(Q,Q._order) for Q in pts]
1430
+ [((0 : -1 : 1), +Infinity)]
1431
+
1432
+ When we successfully divide a point of known finite order `n`,
1433
+ the points returned know that they also have finite order `nk`
1434
+ for some divisor `k` of `m`::
1435
+
1436
+ sage: E = EllipticCurve([1, 0, 1, -19, 26])
1437
+ sage: [(Q,Q._order) for Q in E(0).division_points(12)]
1438
+ [((0 : 1 : 0), 1),
1439
+ ((-5 : 2 : 1), 2),
1440
+ ((-2 : -7 : 1), 6),
1441
+ ((-2 : 8 : 1), 6),
1442
+ ((1 : -4 : 1), 6),
1443
+ ((1 : 2 : 1), 6),
1444
+ ((7/4 : -11/8 : 1), 2),
1445
+ ((3 : -2 : 1), 2),
1446
+ ((4 : -7 : 1), 3),
1447
+ ((4 : 2 : 1), 3),
1448
+ ((13 : -52 : 1), 6),
1449
+ ((13 : 38 : 1), 6)]
1450
+ sage: P = E(4,-7)
1451
+ sage: P.order()
1452
+ 3
1453
+ sage: [(Q,Q._order) for Q in P.division_points(4)]
1454
+ [((-2 : -7 : 1), 6), ((1 : 2 : 1), 6), ((4 : -7 : 1), 3), ((13 : 38 : 1), 6)]
1455
+
1456
+ Check for :issue:`38796`::
1457
+
1458
+ sage: E = EllipticCurve(GF(127), [1,1])
1459
+ sage: P = E(72, 24)
1460
+ sage: [-1*Q for Q in P.division_points(-1)]
1461
+ [(72 : 24 : 1)]
1462
+ """
1463
+ # Coerce the input m to an integer
1464
+ m = Integer(m)
1465
+ # Check for trivial cases of m = 1, -1 and 0.
1466
+ if m == 1 or m == -1:
1467
+ return [m*self]
1468
+ if m == 0:
1469
+ if self == 0: # then every point Q is a solution, but...
1470
+ return [self]
1471
+ else:
1472
+ return []
1473
+
1474
+ # ans will contain the list of division points.
1475
+ ans = []
1476
+
1477
+ # We compute a polynomial g whose roots give all possible x
1478
+ # coordinates of the m-division points. The number of
1479
+ # solutions (over the algebraic closure) is m^2, assuming that
1480
+ # the characteristic does not divide m.
1481
+
1482
+ E = self.curve()
1483
+ P = self
1484
+ nP = -P
1485
+ P_is_2_torsion = (P == nP)
1486
+
1487
+ # If self is the 0, then self is a solution, and the correct
1488
+ # poly is the m'th division polynomial
1489
+ if P == 0:
1490
+ ans.append(P)
1491
+ g = E.division_polynomial(m)
1492
+ else:
1493
+ # The poly g here is 0 at x(Q) iff x(m*Q) = x(P).
1494
+ g = E._multiple_x_numerator(m) - P[0]*E._multiple_x_denominator(m)
1495
+
1496
+ # When 2*P=0, then -Q is a solution iff Q is. For even m,
1497
+ # no 2-torsion point is a solution, so that g is the
1498
+ # square of a polynomial g1 of degree m^2/2, and each root
1499
+ # of g1 leads to a pair of solutions Q, -Q to m*Q=P. For
1500
+ # odd m, P itself is the only 2-torsion solution, so g has
1501
+ # the form (x-x(P))*g1(x)^2 where g1 has degree (m^2-1)/2
1502
+ # and each root of g1 leads to a pair Q, -Q.
1503
+
1504
+ if P_is_2_torsion:
1505
+ if m % 2 == 0:
1506
+ # This computes g.sqrt() which is not implemented
1507
+ g = g.gcd(g.derivative())*g.leading_coefficient().sqrt()
1508
+
1509
+ # When 2*P!=0, then for each solution Q to m*Q=P, -Q is
1510
+ # not a solution (and points of order 2 are not
1511
+ # solutions). Hence the roots of g are distinct and each
1512
+ # gives rise to precisely one solution Q.
1513
+
1514
+ else:
1515
+ g0 = g.variables()[0] - P[0]
1516
+ g = g // g0
1517
+ g = g.gcd(g.derivative())*g.leading_coefficient().sqrt()
1518
+ g = g0*g
1519
+
1520
+ if poly_only:
1521
+ return g
1522
+
1523
+ for x in g.roots(multiplicities=False):
1524
+ if E.is_x_coord(x):
1525
+ # Make a point on the curve with this x coordinate.
1526
+ Q = E.lift_x(x)
1527
+ nQ = -Q
1528
+ mQ = m*Q
1529
+ # if P==-P then Q works iff -Q works, so we include
1530
+ # both unless they are equal:
1531
+ if P_is_2_torsion:
1532
+ if mQ == P:
1533
+ ans.append(Q)
1534
+ if nQ != Q:
1535
+ ans.append(nQ)
1536
+ else:
1537
+ # P is not 2-torsion so at most one of Q, -Q works
1538
+ # and we must try both:
1539
+ if mQ == P:
1540
+ ans.append(Q)
1541
+ elif mQ == nP:
1542
+ ans.append(nQ)
1543
+
1544
+ if not ans:
1545
+ return ans
1546
+
1547
+ # set orders of points found when self's order is known:
1548
+ if self.is_zero():
1549
+ self._order = Integer(1)
1550
+ try:
1551
+ n = self._order # do not compute, just use if already known
1552
+ if n == oo:
1553
+ for Q in ans:
1554
+ Q._order = oo
1555
+ else:
1556
+ mfac = m.factor()
1557
+ for Q in ans:
1558
+ R = n * Q
1559
+ Q._order = n * generic.order_from_multiple(R, m, factorization=mfac, operation='+')
1560
+ except AttributeError: # do nothing about order if self's order unknown
1561
+ pass
1562
+
1563
+ # Finally, sort and return
1564
+ ans.sort()
1565
+ return ans
1566
+
1567
+ def _divide_out(self, p):
1568
+ r"""
1569
+ Return `(Q,k)` where `p^kQ` == ``self`` and `Q` cannot be divided by `p`.
1570
+
1571
+ .. WARNING::
1572
+
1573
+ It is up to the caller to make sure that this does not loop
1574
+ endlessly. It is used in
1575
+ ``EllipticCurve_generic._p_primary_torsion_basis()``, when
1576
+ ``self`` will always have (finite) order which is a power of `p`,
1577
+ so that the order of `Q` increases by a factor of `p` at each
1578
+ stage.
1579
+
1580
+ Since it will clearly be in danger of looping when
1581
+ ``self.is_zero()``, this case is caught, but otherwise caveat user.
1582
+
1583
+ EXAMPLES::
1584
+
1585
+ sage: # needs database_cremona_mini_ellcurve
1586
+ sage: E = EllipticCurve('37a1')
1587
+ sage: P = E([0, 0])
1588
+ sage: R = 12*P
1589
+ sage: R._divide_out(2)
1590
+ ((-1 : -1 : 1), 2)
1591
+ sage: R._divide_out(3)
1592
+ ((2 : -3 : 1), 1)
1593
+ sage: R._divide_out(5)
1594
+ ((1357/841 : 28888/24389 : 1), 0)
1595
+ sage: R._divide_out(12)
1596
+ Traceback (most recent call last):
1597
+ ...
1598
+ ValueError: p (=12) should be prime.
1599
+ """
1600
+ p = Integer(p)
1601
+ if not p.is_prime():
1602
+ raise ValueError("p (=%s) should be prime." % p)
1603
+
1604
+ if self.is_zero():
1605
+ raise ValueError("self must not be 0.")
1606
+
1607
+ k = 0
1608
+ Q = self
1609
+ pts = Q.division_points(p)
1610
+ while pts:
1611
+ Q = pts[0]
1612
+ k += 1
1613
+ pts = Q.division_points(p)
1614
+ return (Q, k)
1615
+
1616
+ def set_order(self, value=None, *, multiple=None, check=True):
1617
+ r"""
1618
+ Set the cached order of this point (i.e., the value of
1619
+ ``self._order``) to the given ``value``.
1620
+
1621
+ Alternatively, when ``multiple`` is given, this method will
1622
+ first run :func:`~sage.groups.generic.order_from_multiple`
1623
+ to determine the exact order from the given multiple of the
1624
+ point order, then cache the result.
1625
+
1626
+ Use this when you know a priori the order of this point, or
1627
+ a multiple of the order, to avoid a potentially expensive
1628
+ order calculation.
1629
+
1630
+ INPUT:
1631
+
1632
+ - ``value`` -- positive integer
1633
+ - ``multiple`` -- positive integer; mutually exclusive with ``value``
1634
+
1635
+ OUTPUT: none
1636
+
1637
+ EXAMPLES:
1638
+
1639
+ This example illustrates basic usage.
1640
+
1641
+ ::
1642
+
1643
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1644
+ sage: G = E(5, 0)
1645
+ sage: G.set_order(2)
1646
+ sage: 2*G
1647
+ (0 : 1 : 0)
1648
+ sage: G = E(0, 6)
1649
+ sage: G.set_order(multiple=12)
1650
+ sage: G._order
1651
+ 3
1652
+
1653
+ We now give a more interesting case, the NIST-P521 curve. Its
1654
+ order is too big to calculate with Sage, and takes a long time
1655
+ using other packages, so it is very useful here.
1656
+
1657
+ ::
1658
+
1659
+ sage: # needs sage.rings.finite_rings
1660
+ sage: p = 2^521 - 1
1661
+ sage: prev_proof_state = proof.arithmetic()
1662
+ sage: proof.arithmetic(False) # turn off primality checking
1663
+ sage: F = GF(p)
1664
+ sage: A = p - 3
1665
+ sage: B = 1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984
1666
+ sage: q = 6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449
1667
+ sage: E = EllipticCurve([F(A), F(B)])
1668
+ sage: G = E.random_point()
1669
+ sage: G.set_order(q)
1670
+ sage: G.order() * G # This takes practically no time.
1671
+ (0 : 1 : 0)
1672
+ sage: proof.arithmetic(prev_proof_state) # restore state
1673
+
1674
+ Using ``.set_order()`` with a ``multiple=`` argument can
1675
+ be used to compute a point's order *significantly* faster
1676
+ than calling :meth:`order` if the point is already known
1677
+ to be `m`-torsion::
1678
+
1679
+ sage: F.<a> = GF((10007, 23))
1680
+ sage: E = EllipticCurve(F, [9,9])
1681
+ sage: n = E.order()
1682
+ sage: m = 5 * 47 * 139 * 1427 * 2027 * 4831 * 275449 * 29523031
1683
+ sage: assert m.divides(n)
1684
+ sage: P = n/m * E.lift_x(6747+a)
1685
+ sage: assert m * P == 0
1686
+ sage: P.set_order(multiple=m) # compute exact order
1687
+ sage: factor(m // P.order()) # order is now cached
1688
+ 47 * 139
1689
+
1690
+ The algorithm used internally for this functionality is
1691
+ :meth:`~sage.groups.generic.order_from_multiple`.
1692
+ Indeed, simply calling :meth:`order` on ``P`` would take
1693
+ much longer since factoring ``n`` is fairly expensive::
1694
+
1695
+ sage: n == m * 6670822796985115651 * 441770032618665681677 * 9289973478285634606114927
1696
+ True
1697
+
1698
+ It is an error to pass a ``value`` equal to `0`::
1699
+
1700
+ sage: # needs sage.rings.finite_rings
1701
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1702
+ sage: G = E.random_point()
1703
+ sage: G.set_order(0)
1704
+ Traceback (most recent call last):
1705
+ ...
1706
+ ValueError: Value 0 illegal for point order
1707
+ sage: G.set_order(1000)
1708
+ Traceback (most recent call last):
1709
+ ...
1710
+ ValueError: Value 1000 illegal: outside max Hasse bound
1711
+
1712
+ It is also very likely an error to pass a value which is not the actual
1713
+ order of this point. How unlikely is determined by the factorization of
1714
+ the actual order, and the actual group structure::
1715
+
1716
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1717
+ sage: G = E(5, 0) # G has order 2
1718
+ sage: G.set_order(11)
1719
+ Traceback (most recent call last):
1720
+ ...
1721
+ ValueError: Value 11 illegal: 11 * (5 : 0 : 1) is not the identity
1722
+
1723
+ However, ``set_order`` can be fooled. For instance, the order
1724
+ can be set to a multiple the actual order::
1725
+
1726
+ sage: E = EllipticCurve(GF(7), [0, 1]) # This curve has order 12
1727
+ sage: G = E(5, 0) # G has order 2
1728
+ sage: G.set_order(8)
1729
+ sage: G.order()
1730
+ 8
1731
+
1732
+ TESTS:
1733
+
1734
+ Check that some invalid inputs are caught::
1735
+
1736
+ sage: E = EllipticCurve(GF(101), [5,5])
1737
+ sage: P = E.lift_x(11)
1738
+ sage: P.set_order(17, multiple=119)
1739
+ Traceback (most recent call last):
1740
+ ...
1741
+ ValueError: cannot pass both value and multiple
1742
+ sage: P.set_order(17)
1743
+ sage: P.set_order(multiple=119+1)
1744
+ Traceback (most recent call last):
1745
+ ...
1746
+ ValueError: previously cached order 17 does not divide given multiple 120
1747
+ sage: P.set_order(119)
1748
+ Traceback (most recent call last):
1749
+ ...
1750
+ ValueError: value 119 contradicts previously cached order 17
1751
+
1752
+ AUTHORS:
1753
+
1754
+ - Mariah Lenox (2011-02-16)
1755
+ - Lorenz Panny (2022): add ``multiple=`` option
1756
+ """
1757
+ if multiple is not None:
1758
+ if value is not None:
1759
+ raise ValueError('cannot pass both value and multiple')
1760
+
1761
+ if hasattr(self, '_order'): # already known
1762
+ if check and not self._order.divides(multiple):
1763
+ raise ValueError(f'previously cached order {self._order} does not divide given multiple {multiple}')
1764
+ return
1765
+
1766
+ from sage.groups.generic import order_from_multiple
1767
+ value = order_from_multiple(self, multiple, check=check)
1768
+ check = False
1769
+
1770
+ value = Integer(value)
1771
+
1772
+ if check:
1773
+ if value <= 0:
1774
+ raise ValueError('Value %s illegal for point order' % value)
1775
+ E = self.curve()
1776
+ q = E.base_ring().cardinality()
1777
+ if q < oo:
1778
+ _, hi = Hasse_bounds(q)
1779
+ if value > hi:
1780
+ raise ValueError('Value %s illegal: outside max Hasse bound' % value)
1781
+ if value * self != E(0):
1782
+ raise ValueError('Value %s illegal: %s * %s is not the identity' % (value, value, self))
1783
+ if hasattr(self, '_order') and self._order != value: # already known
1784
+ raise ValueError(f'value {value} contradicts previously cached order {self._order}')
1785
+
1786
+ self._order = value
1787
+
1788
+ # ############################# end ################################
1789
+
1790
+ def _line_(self, R, Q):
1791
+ r"""
1792
+ Compute the value at `Q` of a straight line through points
1793
+ ``self`` and `R`.
1794
+
1795
+ INPUT:
1796
+
1797
+ - ``R``, ``Q`` -- points on ``self.curve()`` with `Q` nonzero
1798
+
1799
+ OUTPUT:
1800
+
1801
+ An element of the base field ``self.curve().base_field()``.
1802
+ A :exc:`ValueError` is raised if `Q` is zero.
1803
+
1804
+ EXAMPLES::
1805
+
1806
+ sage: # needs sage.rings.finite_rings
1807
+ sage: F.<a> = GF((2,5))
1808
+ sage: E = EllipticCurve(F,[0,0,1,1,1])
1809
+ sage: P = E(a^4 + 1, a^3)
1810
+ sage: Q = E(a^4, a^4 + a^3)
1811
+ sage: O = E(0)
1812
+ sage: P._line_(P,-2*P) == 0
1813
+ True
1814
+ sage: P._line_(Q,-(P+Q)) == 0
1815
+ True
1816
+ sage: O._line_(O,Q) == F(1)
1817
+ True
1818
+ sage: P._line_(O,Q) == a^4 - a^4 + 1
1819
+ True
1820
+ sage: P._line_(13*P,Q) == a^4
1821
+ True
1822
+ sage: P._line_(P,Q) == a^4 + a^3 + a^2 + 1
1823
+ True
1824
+
1825
+ See :issue:`7116`::
1826
+
1827
+ sage: P._line_ (Q,O) # needs sage.rings.finite_rings
1828
+ Traceback (most recent call last):
1829
+ ...
1830
+ ValueError: Q must be nonzero.
1831
+
1832
+ .. NOTE::
1833
+
1834
+ This function is used in _miller_ algorithm.
1835
+
1836
+ AUTHORS:
1837
+
1838
+ - David Hansen (2009-01-25)
1839
+ """
1840
+ if Q.is_zero():
1841
+ raise ValueError("Q must be nonzero.")
1842
+
1843
+ if self.is_zero() or R.is_zero():
1844
+ if self == R:
1845
+ return self.curve().base_field().one()
1846
+ if self.is_zero():
1847
+ return Q[0] - R[0]
1848
+ if R.is_zero():
1849
+ return Q[0] - self[0]
1850
+ elif self != R:
1851
+ if self[0] == R[0]:
1852
+ return Q[0] - self[0]
1853
+ else:
1854
+ l = (R[1] - self[1])/(R[0] - self[0])
1855
+ return Q[1] - self[1] - l * (Q[0] - self[0])
1856
+ else:
1857
+ a1, a2, a3, a4, a6 = self.curve().a_invariants()
1858
+ numerator = (3*self[0]**2 + 2*a2*self[0] + a4 - a1*self[1])
1859
+ denominator = (2*self[1] + a1*self[0] + a3)
1860
+ if denominator == 0:
1861
+ return Q[0] - self[0]
1862
+ else:
1863
+ l = numerator/denominator
1864
+ return Q[1] - self[1] - l * (Q[0] - self[0])
1865
+
1866
+ def _miller_(self, Q, n):
1867
+ r"""
1868
+ Return the value at `Q` of the rational function `f_{n,P}`, where the
1869
+ divisor of `f_{n,P}` is `n[P]-[nP]-(n-1)[O]`.
1870
+
1871
+ INPUT:
1872
+
1873
+ - ``Q`` -- a nonzero point on ``self.curve()``
1874
+
1875
+ - ``n`` -- nonzero integer; if `n<0` then return `Q`
1876
+ evaluated at `1/(v_{nP}*f_{n,P})` (used in the ate pairing)
1877
+
1878
+ OUTPUT:
1879
+
1880
+ An element in the base field ``self.curve().base_field()``.
1881
+ A :exc:`ValueError` is raised if `Q` is zero.
1882
+
1883
+ EXAMPLES::
1884
+
1885
+ sage: # needs sage.rings.finite_rings
1886
+ sage: F.<a> = GF((2,5))
1887
+ sage: E = EllipticCurve(F, [0,0,1,1,1])
1888
+ sage: P = E(a^4 + 1, a^3)
1889
+ sage: Fx.<b> = GF((2,(4*5)))
1890
+ sage: Ex = EllipticCurve(Fx, [0,0,1,1,1])
1891
+ sage: phi = Hom(F,Fx)(F.gen().minpoly().roots(Fx)[0][0])
1892
+ sage: Px = Ex(phi(P.x()), phi(P.y()))
1893
+ sage: Qx = Ex(b^19 + b^18 + b^16 + b^12 + b^10 + b^9 + b^8 + b^5 + b^3 + 1,
1894
+ ....: b^18 + b^13 + b^10 + b^8 + b^5 + b^4 + b^3 + b)
1895
+ sage: Px._miller_(Qx,41) == b^17 + b^13 + b^12 + b^9 + b^8 + b^6 + b^4 + 1
1896
+ True
1897
+ sage: Qx._miller_(Px,41) == b^13 + b^10 + b^8 + b^7 + b^6 + b^5
1898
+ True
1899
+ sage: P._miller_(E(0),41)
1900
+ Traceback (most recent call last):
1901
+ ...
1902
+ ValueError: Q must be nonzero.
1903
+
1904
+ An example of even order::
1905
+
1906
+ sage: # needs sage.rings.finite_rings
1907
+ sage: F.<a> = GF((19,4))
1908
+ sage: E = EllipticCurve(F, [-1,0])
1909
+ sage: P = E(15*a^3 + 17*a^2 + 14*a + 13,16*a^3 + 7*a^2 + a + 18)
1910
+ sage: Q = E(10*a^3 + 16*a^2 + 4*a + 2, 6*a^3 + 4*a^2 + 3*a + 2)
1911
+ sage: x = P.weil_pairing(Q, 360)
1912
+ sage: x^360 == F(1)
1913
+ True
1914
+
1915
+ You can use the _miller_ function on linearly dependent
1916
+ points, but with the risk of a dividing with zero::
1917
+
1918
+ sage: Px._miller_(2*Px, 41) # needs sage.rings.finite_rings
1919
+ Traceback (most recent call last):
1920
+ ...
1921
+ ZeroDivisionError: division by zero in finite field
1922
+
1923
+ A small example of embedding degree 6::
1924
+
1925
+ sage: # needs sage.rings.finite_rings
1926
+ sage: q = 401; F = GF(q); a = 146; b = 400; k = 6
1927
+ sage: E = EllipticCurve([F(a), F(b)])
1928
+ sage: R.<x> = F[]
1929
+ sage: K.<a> = GF(q^k, modulus=x^6 + 4*x^4 + 115*x^3 + 81*x^2 + 51*x + 3)
1930
+ sage: EK = E.base_extend(K)
1931
+ sage: P = E([F(338), F(227)])
1932
+ sage: Q_x = 333*a^5 + 391*a^4 + 160*a^3 + 335*a^2 + 71*a + 93
1933
+ sage: Q_y = 343*a^5 + 273*a^4 + 26*a^3 + 342*a^2 + 340*a + 210
1934
+ sage: Q = EK([Q_x, Q_y])
1935
+ sage: P._miller_(Q, 127)
1936
+ 371*a^5 + 39*a^4 + 355*a^3 + 233*a^2 + 20*a + 275
1937
+
1938
+ A series of small examples and small torsions. We start with
1939
+ `n=1`, which is trivial: the function is the constant
1940
+ 1::
1941
+
1942
+ sage: E = EllipticCurve([GF(7)(0), 2])
1943
+ sage: P = E(5, 1); Q = E(0, 3); I = E(0)
1944
+ sage: I._miller_(P, 1)
1945
+ 1
1946
+ sage: I._miller_(Q, 1)
1947
+ 1
1948
+
1949
+ A two-torsion example. In this case `f_{n,P}(Q) = x_Q - x_P`::
1950
+
1951
+ sage: E = EllipticCurve([GF(7)(-1), 0])
1952
+ sage: P = E(0,0); Q = E(1, 0);
1953
+ sage: P._miller_(P, 2)
1954
+ 0
1955
+ sage: Q._miller_(Q, 2)
1956
+ 0
1957
+ sage: P._miller_(Q, 2)
1958
+ 1
1959
+ sage: Q._miller_(P, 2)
1960
+ 6
1961
+
1962
+ A three-torsion example::
1963
+
1964
+ sage: E = EllipticCurve([GF(7)(0), 2])
1965
+ sage: P = E(5, 1); Q = E(0, 3);
1966
+ sage: P._miller_(Q, 3)
1967
+ 4
1968
+
1969
+ A 4-torsion example::
1970
+
1971
+ sage: E = EllipticCurve([GF(7)(-1), 0])
1972
+ sage: P = E(5, 1); Q = E(4, 2)
1973
+ sage: P._miller_(Q, 4)
1974
+ 3
1975
+
1976
+ A 5-torsion example::
1977
+
1978
+ sage: E = EllipticCurve([GF(7)(-1), 4])
1979
+ sage: P = E(4, 1); Q = E(6, 5)
1980
+ sage: P._miller_(Q, 5)
1981
+ 1
1982
+
1983
+ A 6-torsion example::
1984
+
1985
+ sage: E = EllipticCurve([GF(7)(3), 1])
1986
+ sage: P = E(5, 1); Q = E(3, 3)
1987
+ sage: P._miller_(Q, 6)
1988
+ 5
1989
+
1990
+ An example which is part of an ate pairing calculation. The trace of
1991
+ the curve is negative, so it should exercise the `n<0` case in the
1992
+ code::
1993
+
1994
+ sage: # needs sage.rings.finite_rings
1995
+ sage: p = 2017; A = 1; B = 30; r = 29; t = -70; k = 7
1996
+ sage: F = GF(p); R.<x> = F[]
1997
+ sage: E = EllipticCurve([F(A), F(B)]); P = E(369, 716)
1998
+ sage: K.<a> = GF(p^k, modulus=x^k+2); EK = E.base_extend(K)
1999
+ sage: Qx = 1226*a^6 + 1778*a^5 + 660*a^4 + 1791*a^3 + 1750*a^2 + 867*a + 770
2000
+ sage: Qy = 1764*a^6 + 198*a^5 + 1206*a^4 + 406*a^3 + 1200*a^2 + 273*a + 1712
2001
+ sage: Q = EK(Qx, Qy)
2002
+ sage: Q._miller_(P, t - 1)
2003
+ 1311*a^6 + 1362*a^5 + 1177*a^4 + 807*a^3 + 1331*a^2 + 1530*a + 1931
2004
+
2005
+ ALGORITHM:
2006
+
2007
+ Double-and-add. See also [Mil2004]_.
2008
+
2009
+ AUTHORS:
2010
+
2011
+ - David Hansen (2009-01-25)
2012
+ - Mariah Lenox (2011-03-07) -- Added more doctests and support for
2013
+ negative n.
2014
+ """
2015
+ if Q.is_zero():
2016
+ raise ValueError("Q must be nonzero.")
2017
+ if n.is_zero():
2018
+ raise ValueError("n must be nonzero.")
2019
+ n_is_negative = False
2020
+ if n < 0:
2021
+ n = n.abs()
2022
+ n_is_negative = True
2023
+
2024
+ one = self.curve().base_field().one()
2025
+ t = one
2026
+ V = self
2027
+ nbin = n.bits()
2028
+ i = n.nbits() - 2
2029
+ while i > -1:
2030
+ S = 2*V
2031
+ ell = V._line_(V, Q)
2032
+ vee = S._line_(-S, Q)
2033
+ t = (t**2)*(ell/vee)
2034
+ V = S
2035
+ if nbin[i] == 1:
2036
+ S = V+self
2037
+ ell = V._line_(self, Q)
2038
+ vee = S._line_(-S, Q)
2039
+ t = t*(ell/vee)
2040
+ V = S
2041
+ i = i-1
2042
+ if n_is_negative:
2043
+ vee = V._line_(-V, Q)
2044
+ t = 1/(t*vee)
2045
+ return t
2046
+
2047
+ def weil_pairing(self, Q, n, algorithm=None):
2048
+ r"""
2049
+ Compute the Weil pairing of this point with another point `Q`
2050
+ on the same curve.
2051
+
2052
+ INPUT:
2053
+
2054
+ - ``Q`` -- another point on the same curve as ``self``
2055
+
2056
+ - ``n`` -- integer `n` such that `nP = nQ = (0:1:0)`, where
2057
+ `P` is ``self``
2058
+
2059
+ - ``algorithm`` -- (default: ``None``) choices are ``'pari'``
2060
+ and ``'sage'``. PARI is usually significantly faster, but it
2061
+ only works over finite fields. When ``None`` is given, a
2062
+ suitable algorithm is chosen automatically.
2063
+
2064
+ OUTPUT: an `n`-th root of unity in the base field of the curve
2065
+
2066
+ EXAMPLES::
2067
+
2068
+ sage: # needs sage.rings.finite_rings
2069
+ sage: F.<a> = GF((2,5))
2070
+ sage: E = EllipticCurve(F, [0,0,1,1,1])
2071
+ sage: P = E(a^4 + 1, a^3)
2072
+ sage: Fx.<b> = GF((2, 4*5))
2073
+ sage: Ex = EllipticCurve(Fx, [0,0,1,1,1])
2074
+ sage: phi = Hom(F, Fx)(F.gen().minpoly().roots(Fx)[0][0])
2075
+ sage: Px = Ex(phi(P.x()), phi(P.y()))
2076
+ sage: O = Ex(0)
2077
+ sage: Qx = Ex(b^19 + b^18 + b^16 + b^12 + b^10 + b^9 + b^8 + b^5 + b^3 + 1,
2078
+ ....: b^18 + b^13 + b^10 + b^8 + b^5 + b^4 + b^3 + b)
2079
+ sage: Px.weil_pairing(Qx, 41) == b^19 + b^15 + b^9 + b^8 + b^6 + b^4 + b^3 + b^2 + 1
2080
+ True
2081
+ sage: Px.weil_pairing(17*Px, 41) == Fx(1)
2082
+ True
2083
+ sage: Px.weil_pairing(O, 41) == Fx(1)
2084
+ True
2085
+
2086
+ An error is raised if either point is not `n`-torsion::
2087
+
2088
+ sage: Px.weil_pairing(O, 40) # needs sage.rings.finite_rings
2089
+ Traceback (most recent call last):
2090
+ ...
2091
+ ValueError: points must both be n-torsion
2092
+
2093
+ A larger example (see :issue:`4964`)::
2094
+
2095
+ sage: # needs sage.rings.finite_rings
2096
+ sage: P, Q = EllipticCurve(GF((19,4),'a'), [-1,0]).gens()
2097
+ sage: P.order(), Q.order()
2098
+ (360, 360)
2099
+ sage: z = P.weil_pairing(Q, 360)
2100
+ sage: z.multiplicative_order()
2101
+ 360
2102
+
2103
+ Another larger example::
2104
+
2105
+ sage: F = GF(65537^2, modulus=[3,-1,1], name='a')
2106
+ sage: F.inject_variables()
2107
+ Defining a
2108
+ sage: E = EllipticCurve(F, [0,1])
2109
+ sage: P = E(22, 28891)
2110
+ sage: Q = E(-93, 2728*a + 64173)
2111
+ sage: P.weil_pairing(Q, 7282, algorithm='sage')
2112
+ 53278*a + 36700
2113
+
2114
+ An example over a number field::
2115
+
2116
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
2117
+ sage: E = EllipticCurve('11a1').change_ring(CyclotomicField(5))
2118
+ sage: P, Q = E.torsion_subgroup().gens()
2119
+ sage: P, Q = (P.element(), Q.element())
2120
+ sage: (P.order(), Q.order())
2121
+ (5, 5)
2122
+ sage: P.weil_pairing(Q, 5)
2123
+ zeta5^2
2124
+ sage: Q.weil_pairing(P, 5)
2125
+ zeta5^3
2126
+
2127
+ TESTS:
2128
+
2129
+ Check that the original Sage implementation still works and
2130
+ that the result coincides with the PARI implementation::
2131
+
2132
+ sage: # needs sage.rings.finite_rings
2133
+ sage: GF(65537^2).inject_variables()
2134
+ Defining z2
2135
+ sage: E = EllipticCurve(GF(65537^2), [0,1])
2136
+ sage: R, S = E.torsion_basis(7282)
2137
+ sage: a, b = ZZ.random_element(), ZZ.random_element()
2138
+ sage: P = a*R + b*S
2139
+ sage: c, d = ZZ.random_element(), ZZ.random_element()
2140
+ sage: Q = c*R + d*S
2141
+ sage: P.weil_pairing(Q, 7282, algorithm='sage') == P.weil_pairing(Q, 7282, algorithm='pari')
2142
+ True
2143
+
2144
+ Passing an unknown ``algorithm=`` argument should fail::
2145
+
2146
+ sage: P.weil_pairing(Q, 7282, algorithm='_invalid_') # needs sage.rings.finite_rings
2147
+ Traceback (most recent call last):
2148
+ ...
2149
+ ValueError: unknown algorithm
2150
+
2151
+ ALGORITHM:
2152
+
2153
+ - For ``algorithm='pari'``: :pari:`ellweilpairing`.
2154
+
2155
+ - For ``algorithm='sage'``:
2156
+ Implemented using Proposition 8 in [Mil2004]_. The value 1 is
2157
+ returned for linearly dependent input points. This condition
2158
+ is caught via a :exc:`ZeroDivisionError`, since the use of a
2159
+ discrete logarithm test for linear dependence is much too slow
2160
+ for large `n`.
2161
+
2162
+ AUTHORS:
2163
+
2164
+ - David Hansen (2009-01-25)
2165
+ - Lorenz Panny (2022): ``algorithm='pari'``
2166
+ """
2167
+ P = self
2168
+ E = P.curve()
2169
+
2170
+ if Q.curve() is not E:
2171
+ raise ValueError("points must both be on the same curve")
2172
+
2173
+ if algorithm is None:
2174
+ if E.base_field().is_finite():
2175
+ algorithm = 'pari'
2176
+ else:
2177
+ algorithm = 'sage'
2178
+
2179
+ if algorithm == 'pari':
2180
+ if pari.ellmul(E,P,n) != [0] or pari.ellmul(E,Q,n) != [0]:
2181
+ raise ValueError("points must both be n-torsion")
2182
+ return E.base_field()(pari.ellweilpairing(E, P, Q, n))
2183
+
2184
+ if algorithm != 'sage':
2185
+ raise ValueError('unknown algorithm')
2186
+
2187
+ # Test if P, Q are both in E[n]
2188
+ if n*P or n*Q:
2189
+ raise ValueError("points must both be n-torsion")
2190
+
2191
+ one = E.base_field().one()
2192
+
2193
+ # Case where P = Q
2194
+ if P == Q:
2195
+ return one
2196
+
2197
+ # Case where P = O or Q = O
2198
+ if P.is_zero() or Q.is_zero():
2199
+ return one
2200
+
2201
+ # The non-trivial case P != Q
2202
+
2203
+ # Note (2010-12-29): The following code block should not be
2204
+ # used. It attempts to reduce the pairing calculation to order
2205
+ # d = gcd(|P|,|Q|) instead of order n, but this approach is
2206
+ # counterproductive, since calculating |P| and |Q| is much
2207
+ # slower than calculating the pairing [BGN05].
2208
+ #
2209
+ # [BGN05] D. Boneh, E. Goh, and K. Nissim, "Evaluating 2-DNF
2210
+ # Formulas on Ciphertexts", TCC 2005, LNCS 3378, pp. 325-341.
2211
+ #
2212
+ # Reduction to order d = gcd(|P|,|Q|); value is a d'th root of unity
2213
+ # try:
2214
+ # nP = P.order()
2215
+ # except AttributeError:
2216
+ # nP = generic.order_from_multiple(P,n,operation='+')
2217
+ # try:
2218
+ # nQ = Q.order()
2219
+ # except AttributeError:
2220
+ # nQ = generic.order_from_multiple(Q,n,operation='+')
2221
+ # d = arith.gcd(nP,nQ)
2222
+ # if d==1:
2223
+ # return one
2224
+ #
2225
+ # P = (nP//d)*P # order d
2226
+ # Q = (nQ//d)*Q # order d
2227
+ # n = d
2228
+
2229
+ try:
2230
+ return ((-1)**n.test_bit(0))*(P._miller_(Q, n)/Q._miller_(P, n))
2231
+ except ZeroDivisionError:
2232
+ return one
2233
+
2234
+ def tate_pairing(self, Q, n, k, q=None):
2235
+ r"""
2236
+ Return Tate pairing of `n`-torsion point `P = self` and point `Q`.
2237
+
2238
+ The value returned is `f_{n,P}(Q)^e` where `f_{n,P}` is a function with
2239
+ divisor `n[P]-n[O].`. This is also known as the "modified Tate
2240
+ pairing". It is a well-defined bilinear map.
2241
+
2242
+ INPUT:
2243
+
2244
+ - ``P=self`` -- elliptic curve point having order `n`
2245
+
2246
+ - ``Q`` -- elliptic curve point on same curve as `P` (can be any order)
2247
+
2248
+ - ``n`` -- positive integer; order of `P`
2249
+
2250
+ - ``k`` -- positive integer; embedding degree
2251
+
2252
+ - ``q`` -- positive integer; size of base field (the "big"
2253
+ field is `GF(q^k)`. `q` needs to be set only if its value
2254
+ cannot be deduced.)
2255
+
2256
+ OUTPUT:
2257
+
2258
+ An `n`-th root of unity in the base field ``self.curve().base_field()``.
2259
+
2260
+ EXAMPLES:
2261
+
2262
+ A simple example, pairing a point with itself, and pairing a point with
2263
+ another rational point::
2264
+
2265
+ sage: p = 103; A = 1; B = 18; E = EllipticCurve(GF(p), [A, B])
2266
+ sage: P = E(33, 91); n = P.order(); n
2267
+ 19
2268
+ sage: k = GF(n)(p).multiplicative_order(); k
2269
+ 6
2270
+ sage: P.tate_pairing(P, n, k)
2271
+ 1
2272
+ sage: Q = E(87, 51)
2273
+ sage: P.tate_pairing(Q, n, k)
2274
+ 1
2275
+ sage: set_random_seed(35)
2276
+ sage: P.tate_pairing(P, n, k)
2277
+ 1
2278
+
2279
+ We now let `Q` be a point on the same curve as above, but defined over
2280
+ the pairing extension field, and we also demonstrate the bilinearity of
2281
+ the pairing::
2282
+
2283
+ sage: # needs sage.rings.finite_rings
2284
+ sage: K.<a> = GF((p,k))
2285
+ sage: EK = E.base_extend(K); P = EK(P)
2286
+ sage: Qx = 69*a^5 + 96*a^4 + 22*a^3 + 86*a^2 + 6*a + 35
2287
+ sage: Qy = 34*a^5 + 24*a^4 + 16*a^3 + 41*a^2 + 4*a + 40
2288
+ sage: Q = EK(Qx, Qy);
2289
+
2290
+ Multiply by cofactor so Q has order n::
2291
+
2292
+ sage: # needs sage.rings.finite_rings
2293
+ sage: h = 551269674; Q = h*Q
2294
+ sage: P = EK(P); P.tate_pairing(Q, n, k)
2295
+ 24*a^5 + 34*a^4 + 3*a^3 + 69*a^2 + 86*a + 45
2296
+ sage: s = Integer(randrange(1,n))
2297
+ sage: ans1 = (s*P).tate_pairing(Q, n, k)
2298
+ sage: ans2 = P.tate_pairing(s*Q, n, k)
2299
+ sage: ans3 = P.tate_pairing(Q, n, k)^s
2300
+ sage: ans1 == ans2 == ans3
2301
+ True
2302
+ sage: (ans1 != 1) and (ans1^n == 1)
2303
+ True
2304
+
2305
+ Here is an example of using the Tate pairing to compute the Weil
2306
+ pairing (using the same data as above)::
2307
+
2308
+ sage: # needs sage.rings.finite_rings
2309
+ sage: e = Integer((p^k-1)/n); e
2310
+ 62844857712
2311
+ sage: P.weil_pairing(Q, n)^e
2312
+ 94*a^5 + 99*a^4 + 29*a^3 + 45*a^2 + 57*a + 34
2313
+ sage: P.tate_pairing(Q, n, k) == P._miller_(Q, n)^e
2314
+ True
2315
+ sage: Q.tate_pairing(P, n, k) == Q._miller_(P, n)^e
2316
+ True
2317
+ sage: P.tate_pairing(Q, n, k)/Q.tate_pairing(P, n, k)
2318
+ 94*a^5 + 99*a^4 + 29*a^3 + 45*a^2 + 57*a + 34
2319
+
2320
+ An example where we have to pass the base field size (and we again have
2321
+ agreement with the Weil pairing)::
2322
+
2323
+ sage: # needs sage.rings.finite_rings
2324
+ sage: F.<a> = GF((2,5))
2325
+ sage: E = EllipticCurve(F, [0,0,1,1,1])
2326
+ sage: P = E(a^4 + 1, a^3)
2327
+ sage: Fx.<b> = GF((2,4*5))
2328
+ sage: Ex = EllipticCurve(Fx,[0,0,1,1,1])
2329
+ sage: phi = Hom(F, Fx)(F.gen().minpoly().roots(Fx)[0][0])
2330
+ sage: Px = Ex(phi(P.x()), phi(P.y()))
2331
+ sage: Qx = Ex(b^19 + b^18 + b^16 + b^12 + b^10 + b^9 + b^8 + b^5 + b^3 + 1,
2332
+ ....: b^18 + b^13 + b^10 + b^8 + b^5 + b^4 + b^3 + b)
2333
+ sage: Px.tate_pairing(Qx, n=41, k=4)
2334
+ Traceback (most recent call last):
2335
+ ...
2336
+ ValueError: Unexpected field degree: set keyword argument q equal to
2337
+ the size of the base field (big field is GF(q^4)).
2338
+ sage: num = Px.tate_pairing(Qx, n=41, k=4, q=32); num
2339
+ b^19 + b^14 + b^13 + b^12 + b^6 + b^4 + b^3
2340
+ sage: den = Qx.tate_pairing(Px, n=41, k=4, q=32); den
2341
+ b^19 + b^17 + b^16 + b^15 + b^14 + b^10 + b^6 + b^2 + 1
2342
+ sage: e = Integer((32^4-1)/41); e
2343
+ 25575
2344
+ sage: Px.weil_pairing(Qx, 41)^e == num/den
2345
+ True
2346
+
2347
+ An example over a large base field::
2348
+
2349
+ sage: F = GF(65537^2, modulus=[3,46810,1], name='z2')
2350
+ sage: F.inject_variables()
2351
+ Defining z2
2352
+ sage: E = EllipticCurve(F, [0,1])
2353
+ sage: P = E(22, 28891)
2354
+ sage: Q = E(-93, 40438*z2 + 31573)
2355
+ sage: P.tate_pairing(Q, 7282, 2)
2356
+ 34585*z2 + 4063
2357
+
2358
+ TESTS:
2359
+
2360
+ The point ``P (self)`` must have ``n`` torsion::
2361
+
2362
+ sage: P.tate_pairing(Q, 163, 2)
2363
+ Traceback (most recent call last):
2364
+ ...
2365
+ ValueError: The point P must be n-torsion
2366
+
2367
+ We must have that ``n`` divides ``q^k - 1``, this is only checked when q is supplied::
2368
+
2369
+ sage: P.tate_pairing(Q, 7282, 2, q=123)
2370
+ Traceback (most recent call last):
2371
+ ...
2372
+ ValueError: n does not divide (q^k - 1) for the supplied value of q
2373
+
2374
+ The Tate pairing is only defined for points on curves defined over finite fields::
2375
+
2376
+ sage: E = EllipticCurve([0,1])
2377
+ sage: P = E(2,3)
2378
+ sage: P.tate_pairing(P, 6, 1)
2379
+ Traceback (most recent call last):
2380
+ ...
2381
+ NotImplementedError: Reduced Tate pairing is currently only implemented for finite fields
2382
+
2383
+ ALGORITHM:
2384
+
2385
+ - :pari:`elltatepairing` computes the
2386
+ non-reduced tate pairing and the exponentiation is handled by
2387
+ Sage using user input for `k` (and optionally `q`).
2388
+
2389
+ AUTHORS:
2390
+
2391
+ - Mariah Lenox (2011-03-07)
2392
+ - Giacomo Pope (2024): Use of PARI for the non-reduced Tate pairing
2393
+ """
2394
+ P = self
2395
+ E = P.curve()
2396
+
2397
+ if Q.curve() is not E:
2398
+ raise ValueError("Points must both be on the same curve")
2399
+
2400
+ K = E.base_ring()
2401
+ if not K.is_finite():
2402
+ raise NotImplementedError("Reduced Tate pairing is currently only implemented for finite fields")
2403
+
2404
+ d = K.degree()
2405
+ if q is None:
2406
+ if d == 1:
2407
+ q = K.order()
2408
+ elif d == k:
2409
+ q = K.base_ring().order()
2410
+ else:
2411
+ raise ValueError("Unexpected field degree: set keyword argument q equal to the size of the base field (big field is GF(q^%s))." % k)
2412
+ # The user has supplied q, so we check here that it's a sensible value
2413
+ elif Mod(q, n)**k != 1:
2414
+ raise ValueError("n does not divide (q^k - 1) for the supplied value of q")
2415
+
2416
+ if pari.ellmul(E, P, n) != [0]:
2417
+ raise ValueError("The point P must be n-torsion")
2418
+
2419
+ # NOTE: Pari returns the non-reduced Tate pairing, so we
2420
+ # must perform the exponentiation ourselves using the supplied
2421
+ # k value
2422
+ ePQ = pari.elltatepairing(E, P, Q, n)
2423
+ exp = Integer((q**k - 1)/n)
2424
+ return K(ePQ**exp) # Cast the PARI type back to the base ring
2425
+
2426
+ def ate_pairing(self, Q, n, k, t, q=None):
2427
+ r"""
2428
+ Return ate pairing of `n`-torsion points `P` (``=self``) and `Q`.
2429
+
2430
+ Also known as the `n`-th modified ate pairing. `P` is `GF(q)`-rational,
2431
+ and `Q` must be an element of `Ker(\pi-p)`, where `\pi` is the
2432
+ `q`-frobenius map (and hence `Q` is `GF(q^k)`-rational).
2433
+
2434
+ INPUT:
2435
+
2436
+ - ``P`` (``=self``) -- a point of order `n`, in `ker(\pi-1)`, where
2437
+ `\pi` is the `q`-Frobenius map (e.g., `P` is `q`-rational)
2438
+
2439
+ - ``Q`` -- a point of order `n` in `ker(\pi-q)`
2440
+
2441
+ - ``n`` -- the order of `P` and `Q`
2442
+
2443
+ - ``k`` -- the embedding degree
2444
+
2445
+ - ``t`` -- the trace of Frobenius of the curve over `GF(q)`
2446
+
2447
+ - ``q`` -- (default: ``None``) the size of base field (the "big"
2448
+ field is `GF(q^k)`). `q` needs to be set only if its value
2449
+ cannot be deduced.
2450
+
2451
+ OUTPUT:
2452
+
2453
+ FiniteFieldElement in `GF(q^k)` -- the ate pairing of `P` and `Q`.
2454
+
2455
+ EXAMPLES:
2456
+
2457
+ An example with embedding degree 6::
2458
+
2459
+ sage: # needs sage.rings.finite_rings
2460
+ sage: p = 7549; A = 0; B = 1; n = 157; k = 6; t = 14
2461
+ sage: F = GF(p); E = EllipticCurve(F, [A, B])
2462
+ sage: R.<x> = F[]; K.<a> = GF((p,k), modulus=x^k+2)
2463
+ sage: EK = E.base_extend(K)
2464
+ sage: P = EK(3050, 5371); Q = EK(6908*a^4, 3231*a^3)
2465
+ sage: P.ate_pairing(Q, n, k, t)
2466
+ 6708*a^5 + 4230*a^4 + 4350*a^3 + 2064*a^2 + 4022*a + 6733
2467
+ sage: s = Integer(randrange(1, n))
2468
+ sage: (s*P).ate_pairing(Q, n, k, t) == P.ate_pairing(s*Q, n, k, t)
2469
+ True
2470
+ sage: P.ate_pairing(s*Q, n, k, t) == P.ate_pairing(Q, n, k, t)^s
2471
+ True
2472
+
2473
+ Another example with embedding degree 7 and positive trace::
2474
+
2475
+ sage: # needs sage.rings.finite_rings
2476
+ sage: p = 2213; A = 1; B = 49; n = 1093; k = 7; t = 28
2477
+ sage: F = GF(p); E = EllipticCurve(F, [A, B])
2478
+ sage: R.<x> = F[]; K.<a> = GF((p,k), modulus=x^k+2)
2479
+ sage: EK = E.base_extend(K)
2480
+ sage: P = EK(1583, 1734)
2481
+ sage: Qx = 1729*a^6+1767*a^5+245*a^4+980*a^3+1592*a^2+1883*a+722
2482
+ sage: Qy = 1299*a^6+1877*a^5+1030*a^4+1513*a^3+1457*a^2+309*a+1636
2483
+ sage: Q = EK(Qx, Qy)
2484
+ sage: P.ate_pairing(Q, n, k, t)
2485
+ 1665*a^6 + 1538*a^5 + 1979*a^4 + 239*a^3 + 2134*a^2 + 2151*a + 654
2486
+ sage: s = Integer(randrange(1, n))
2487
+ sage: (s*P).ate_pairing(Q, n, k, t) == P.ate_pairing(s*Q, n, k, t)
2488
+ True
2489
+ sage: P.ate_pairing(s*Q, n, k, t) == P.ate_pairing(Q, n, k, t)^s
2490
+ True
2491
+
2492
+ Another example with embedding degree 7 and negative trace::
2493
+
2494
+ sage: # needs sage.rings.finite_rings
2495
+ sage: p = 2017; A = 1; B = 30; n = 29; k = 7; t = -70
2496
+ sage: F = GF(p); E = EllipticCurve(F, [A, B])
2497
+ sage: R.<x> = F[]; K.<a> = GF((p,k), modulus=x^k+2)
2498
+ sage: EK = E.base_extend(K)
2499
+ sage: P = EK(369, 716)
2500
+ sage: Qx = 1226*a^6+1778*a^5+660*a^4+1791*a^3+1750*a^2+867*a+770
2501
+ sage: Qy = 1764*a^6+198*a^5+1206*a^4+406*a^3+1200*a^2+273*a+1712
2502
+ sage: Q = EK(Qx, Qy)
2503
+ sage: P.ate_pairing(Q, n, k, t)
2504
+ 1794*a^6 + 1161*a^5 + 576*a^4 + 488*a^3 + 1950*a^2 + 1905*a + 1315
2505
+ sage: s = Integer(randrange(1, n))
2506
+ sage: (s*P).ate_pairing(Q, n, k, t) == P.ate_pairing(s*Q, n, k, t)
2507
+ True
2508
+ sage: P.ate_pairing(s*Q, n, k, t) == P.ate_pairing(Q, n, k, t)^s
2509
+ True
2510
+
2511
+ Using the same data, we show that the ate pairing is a power of the
2512
+ Tate pairing (see [HSV2006]_ end of section 3.1)::
2513
+
2514
+ sage: # needs sage.rings.finite_rings
2515
+ sage: c = (k*p^(k-1)).mod(n); T = t - 1
2516
+ sage: N = gcd(T^k - 1, p^k - 1)
2517
+ sage: s = Integer(N/n)
2518
+ sage: L = Integer((T^k - 1)/N)
2519
+ sage: M = (L*s*c.inverse_mod(n)).mod(n)
2520
+ sage: P.ate_pairing(Q, n, k, t) == Q.tate_pairing(P, n, k)^M
2521
+ True
2522
+
2523
+ An example where we have to pass the base field size (and we again have
2524
+ agreement with the Tate pairing). Note that though `Px` is not
2525
+ `F`-rational, (it is the homomorphic image of an `F`-rational point) it
2526
+ is nonetheless in `ker(\pi-1)`, and so is a legitimate input::
2527
+
2528
+ sage: # needs sage.rings.finite_rings
2529
+ sage: q = 2^5; F.<a> = GF(q)
2530
+ sage: n = 41; k = 4; t = -8
2531
+ sage: E = EllipticCurve(F,[0,0,1,1,1])
2532
+ sage: P = E(a^4 + 1, a^3)
2533
+ sage: Fx.<b> = GF(q^k)
2534
+ sage: Ex = EllipticCurve(Fx, [0,0,1,1,1])
2535
+ sage: phi = Hom(F, Fx)(F.gen().minpoly().roots(Fx)[0][0])
2536
+ sage: Px = Ex(phi(P.x()), phi(P.y()))
2537
+ sage: Qx = Ex(b^19+b^18+b^16+b^12+b^10+b^9+b^8+b^5+b^3+1,
2538
+ ....: b^18+b^13+b^10+b^8+b^5+b^4+b^3+b)
2539
+ sage: Qx = Ex(Qx[0]^q, Qx[1]^q) - Qx # ensure Qx is in ker(pi - q)
2540
+ sage: Px.ate_pairing(Qx, n, k, t)
2541
+ Traceback (most recent call last):
2542
+ ...
2543
+ ValueError: Unexpected field degree: set keyword argument q equal to
2544
+ the size of the base field (big field is GF(q^4)).
2545
+ sage: Px.ate_pairing(Qx, n, k, t, q)
2546
+ b^19 + b^18 + b^17 + b^16 + b^15 + b^14 + b^13 + b^12
2547
+ + b^11 + b^9 + b^8 + b^5 + b^4 + b^2 + b + 1
2548
+ sage: s = Integer(randrange(1, n))
2549
+ sage: (s*Px).ate_pairing(Qx, n, k, t, q) == Px.ate_pairing(s*Qx, n, k, t, q)
2550
+ True
2551
+ sage: Px.ate_pairing(s*Qx, n, k, t, q) == Px.ate_pairing(Qx, n, k, t, q)^s
2552
+ True
2553
+ sage: c = (k*q^(k-1)).mod(n); T = t - 1
2554
+ sage: N = gcd(T^k - 1, q^k - 1)
2555
+ sage: s = Integer(N/n)
2556
+ sage: L = Integer((T^k - 1)/N)
2557
+ sage: M = (L*s*c.inverse_mod(n)).mod(n)
2558
+ sage: Px.ate_pairing(Qx, n, k, t, q) == Qx.tate_pairing(Px, n, k, q)^M
2559
+ True
2560
+
2561
+ It is an error if `Q` is not in the kernel of `\pi - p`, where `\pi` is
2562
+ the Frobenius automorphism::
2563
+
2564
+ sage: # needs sage.rings.finite_rings
2565
+ sage: p = 29; A = 1; B = 0; n = 5; k = 2; t = 10
2566
+ sage: F = GF(p); R.<x> = F[]
2567
+ sage: E = EllipticCurve(F, [A, B]);
2568
+ sage: K.<a> = GF((p,k), modulus=x^k+2); EK = E.base_extend(K)
2569
+ sage: P = EK(13, 8); Q = EK(13, 21)
2570
+ sage: P.ate_pairing(Q, n, k, t)
2571
+ Traceback (most recent call last):
2572
+ ...
2573
+ ValueError: Point (13 : 21 : 1) not in Ker(pi - q)
2574
+
2575
+ It is also an error if `P` is not in the kernel os `\pi - 1`::
2576
+
2577
+ sage: # needs sage.rings.finite_rings
2578
+ sage: p = 29; A = 1; B = 0; n = 5; k = 2; t = 10
2579
+ sage: F = GF(p); R.<x> = F[]
2580
+ sage: E = EllipticCurve(F, [A, B]);
2581
+ sage: K.<a> = GF((p,k), modulus=x^k+2); EK = E.base_extend(K)
2582
+ sage: P = EK(14, 10*a); Q = EK(13, 21)
2583
+ sage: P.ate_pairing(Q, n, k, t)
2584
+ Traceback (most recent call last):
2585
+ ...
2586
+ ValueError: This point (14 : 10*a : 1) is not in Ker(pi - 1)
2587
+
2588
+ .. NOTE::
2589
+
2590
+ First defined in the paper of [HSV2006]_, the ate pairing
2591
+ can be computationally effective in those cases when the
2592
+ trace of the curve over the base field is significantly
2593
+ smaller than the expected value. This implementation is
2594
+ simply Miller's algorithm followed by a naive
2595
+ exponentiation, and makes no claims towards efficiency.
2596
+
2597
+ AUTHORS:
2598
+
2599
+ - Mariah Lenox (2011-03-08)
2600
+ """
2601
+ P = self
2602
+ # check for same curve
2603
+ E = P.curve()
2604
+ O = E(0)
2605
+ if Q.curve() is not E:
2606
+ raise ValueError("Points must both be on the same curve")
2607
+
2608
+ # set q to be the order of the base field
2609
+ K = E.base_ring()
2610
+ if q is None:
2611
+ d = K.degree()
2612
+ if d == k:
2613
+ q = K.base_ring().order()
2614
+ else:
2615
+ raise ValueError("Unexpected field degree: set keyword argument q equal to the size of the base field (big field is GF(q^%s))." % k)
2616
+
2617
+ # check order of P
2618
+ if n*P != O:
2619
+ raise ValueError('This point %s is not of order n=%s' % (P, n))
2620
+
2621
+ # check for P in kernel pi - 1:
2622
+ piP = E(P[0]**q, P[1]**q)
2623
+ if piP - P != O:
2624
+ raise ValueError('This point %s is not in Ker(pi - 1)' % P)
2625
+
2626
+ # check for Q in kernel pi - q:
2627
+ piQ = E(Q[0]**q, Q[1]**q)
2628
+ if piQ - q*Q != O:
2629
+ raise ValueError('Point %s not in Ker(pi - q)' % Q)
2630
+
2631
+ T = t-1
2632
+ ret = Q._miller_(P, T)
2633
+ e = Integer((q**k - 1)/n)
2634
+ ret = ret**e
2635
+ return ret
2636
+
2637
+ def point_of_jacobian_of_curve(self):
2638
+ r"""
2639
+ Return the point in the Jacobian of the curve.
2640
+
2641
+ The Jacobian is the one attached to the projective curve associated
2642
+ with this elliptic curve.
2643
+
2644
+ EXAMPLES::
2645
+
2646
+ sage: # needs sage.rings.finite_rings
2647
+ sage: k.<a> = GF((5,2))
2648
+ sage: E = EllipticCurve(k,[1,0]); E
2649
+ Elliptic Curve defined by y^2 = x^3 + x over Finite Field in a of size 5^2
2650
+ sage: E.order()
2651
+ 32
2652
+ sage: P = E([a, 2*a + 4])
2653
+ sage: P
2654
+ (a : 2*a + 4 : 1)
2655
+ sage: P.order()
2656
+ 8
2657
+ sage: p = P.point_of_jacobian_of_curve()
2658
+ sage: p
2659
+ [Place (x + 4*a, y + 3*a + 1)]
2660
+ sage: p.order()
2661
+ 8
2662
+ sage: Q = 3*P
2663
+ sage: q = Q.point_of_jacobian_of_curve()
2664
+ sage: q == 3*p
2665
+ True
2666
+ sage: G = p.parent()
2667
+ sage: G.order()
2668
+ 32
2669
+ sage: G
2670
+ Group of rational points of Jacobian over Finite Field in a of size 5^2 (Hess model)
2671
+ sage: J = G.parent(); J
2672
+ Jacobian of Projective Plane Curve over Finite Field in a of size 5^2
2673
+ defined by x^2*y + y^3 - x*z^2 (Hess model)
2674
+ sage: J.curve() == E.affine_patch(2).projective_closure()
2675
+ True
2676
+ """
2677
+ from sage.schemes.curves.constructor import Curve
2678
+ C = self.curve()
2679
+ A = C.ambient_space() # projective plane
2680
+ x, y, z = self
2681
+
2682
+ X = Curve(C.defining_ideal().gens(), A)
2683
+ X = X.affine_patch(2).projective_closure()
2684
+ F = X.function_field()
2685
+ P = X(z,x,y).place()
2686
+
2687
+ Pinf = F.places_infinite()[0]
2688
+ assert Pinf.degree() == 1, "no rational point at infinity"
2689
+
2690
+ J = X.jacobian(model='hess', base_div=F.genus()*Pinf)
2691
+ G = J.group(self.base_ring())
2692
+ return G(P - P.degree()*Pinf)
2693
+
2694
+
2695
+ class EllipticCurvePoint_number_field(EllipticCurvePoint_field):
2696
+ """
2697
+ A point on an elliptic curve over a number field.
2698
+
2699
+ Most of the functionality is derived from the parent class
2700
+ :class:`EllipticCurvePoint_field`. In addition we have support for
2701
+ orders, heights, reduction modulo primes, and elliptic logarithms.
2702
+
2703
+ EXAMPLES::
2704
+
2705
+ sage: # needs database_cremona_mini_ellcurve
2706
+ sage: E = EllipticCurve('37a')
2707
+ sage: E([0,0])
2708
+ (0 : 0 : 1)
2709
+ sage: E(0,0) # brackets are optional
2710
+ (0 : 0 : 1)
2711
+ sage: E([GF(5)(0), 0]) # entries are coerced
2712
+ (0 : 0 : 1)
2713
+ sage: E(0.000, 0)
2714
+ (0 : 0 : 1)
2715
+ sage: E(1,0,0)
2716
+ Traceback (most recent call last):
2717
+ ...
2718
+ TypeError: Coordinates [1, 0, 0] do not define a point on
2719
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2720
+
2721
+ ::
2722
+
2723
+ sage: E = EllipticCurve([0,0,1,-1,0])
2724
+ sage: S = E(QQ); S
2725
+ Abelian group of points on
2726
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
2727
+
2728
+ TESTS::
2729
+
2730
+ sage: loads(S.dumps()) == S
2731
+ True
2732
+ sage: P = E(0,0); P
2733
+ (0 : 0 : 1)
2734
+ sage: loads(P.dumps()) == P
2735
+ True
2736
+ sage: T = 100*P
2737
+ sage: loads(T.dumps()) == T
2738
+ True
2739
+
2740
+ Test pickling an elliptic curve that has known points on it::
2741
+
2742
+ sage: e = EllipticCurve([0, 0, 1, -1, 0]); g = e.gens(); loads(dumps(e)) == e # needs ecl
2743
+ True
2744
+ """
2745
+
2746
+ def order(self):
2747
+ r"""
2748
+ Return the order of this point on the elliptic curve.
2749
+
2750
+ If the point has infinite order, returns +Infinity. For
2751
+ curves defined over `\QQ`, we call PARI; over other
2752
+ number fields we implement the function here.
2753
+
2754
+ .. NOTE::
2755
+
2756
+ :meth:`additive_order` is a synonym for :meth:`order`
2757
+
2758
+ EXAMPLES::
2759
+
2760
+ sage: E = EllipticCurve([0,0,1,-1,0])
2761
+ sage: P = E([0,0]); P
2762
+ (0 : 0 : 1)
2763
+ sage: P.order()
2764
+ +Infinity
2765
+
2766
+ ::
2767
+
2768
+ sage: E = EllipticCurve([0,1])
2769
+ sage: P = E([-1,0])
2770
+ sage: P.order()
2771
+ 2
2772
+ sage: P.additive_order()
2773
+ 2
2774
+ """
2775
+ try:
2776
+ return self._order
2777
+ except AttributeError:
2778
+ pass
2779
+
2780
+ if self.is_zero():
2781
+ self._order = Integer(1)
2782
+ return self._order
2783
+
2784
+ E = self.curve()
2785
+
2786
+ # First try PARI
2787
+ try:
2788
+ n = E.pari_curve().ellorder(self)
2789
+ if n:
2790
+ n = Integer(n)
2791
+ else:
2792
+ n = oo
2793
+ self._order = n
2794
+ return n
2795
+ except PariError:
2796
+ pass
2797
+
2798
+ # Get the torsion order if known, else a bound on (multiple
2799
+ # of) the order. We do not compute the torsion if it is not
2800
+ # already known, since computing the bound is faster (and is
2801
+ # also cached).
2802
+
2803
+ try:
2804
+ N = E._torsion_order
2805
+ except AttributeError:
2806
+ N = E._torsion_bound()
2807
+
2808
+ # Now self is a torsion point iff it is killed by N:
2809
+ if not (N*self).is_zero():
2810
+ self._order = oo
2811
+ return self._order
2812
+
2813
+ # Finally we find the exact order using the generic code:
2814
+ self._order = generic.order_from_multiple(self, N, operation='+')
2815
+ return self._order
2816
+
2817
+ additive_order = order
2818
+
2819
+ def has_finite_order(self) -> bool:
2820
+ """
2821
+ Return ``True`` iff this point has finite order on the elliptic curve.
2822
+
2823
+ EXAMPLES::
2824
+
2825
+ sage: E = EllipticCurve([0,0,1,-1,0])
2826
+ sage: P = E([0,0]); P
2827
+ (0 : 0 : 1)
2828
+ sage: P.has_finite_order()
2829
+ False
2830
+
2831
+ ::
2832
+
2833
+ sage: E = EllipticCurve([0,1])
2834
+ sage: P = E([-1,0])
2835
+ sage: P.has_finite_order()
2836
+ True
2837
+ """
2838
+ if self.is_zero():
2839
+ return True
2840
+ return self.order() != oo
2841
+
2842
+ def has_infinite_order(self) -> bool:
2843
+ r"""
2844
+ Return ``True`` iff this point has infinite order on the elliptic curve.
2845
+
2846
+ EXAMPLES::
2847
+
2848
+ sage: E = EllipticCurve([0,0,1,-1,0])
2849
+ sage: P = E([0,0]); P
2850
+ (0 : 0 : 1)
2851
+ sage: P.has_infinite_order()
2852
+ True
2853
+
2854
+ ::
2855
+
2856
+ sage: E = EllipticCurve([0,1])
2857
+ sage: P = E([-1,0])
2858
+ sage: P.has_infinite_order()
2859
+ False
2860
+ """
2861
+ if self.is_zero():
2862
+ return False
2863
+ return self.order() == oo
2864
+
2865
+ def _has_order_at_least(self, bound, *, attempts=999):
2866
+ r"""
2867
+ Return ``True`` if this point definitely has order at least ``bound``
2868
+ on the elliptic curve, ``False`` if the point has smaller order, and
2869
+ ``None`` if the result of this test is inconclusive.
2870
+
2871
+ This method can be much faster than calling :meth:`has_infinite_order`
2872
+ if all that is needed is a lower bound on the order.
2873
+
2874
+ ALGORITHM: Compute the order of the point modulo various small primes
2875
+ and combine that information using CRT.
2876
+
2877
+ EXAMPLES::
2878
+
2879
+ sage: # needs database_cremona_mini_ellcurve
2880
+ sage: E = EllipticCurve('11a3')
2881
+ sage: P = next(filter(bool, E.torsion_points()))
2882
+ sage: P._has_order_at_least(5)
2883
+ True
2884
+ sage: P._has_order_at_least(6) # long time -- 5s
2885
+ sage: P.order()
2886
+ 5
2887
+ sage: Q = E.lift_x(10^42, extend=True)
2888
+ sage: Q._has_order_at_least(10^100)
2889
+ True
2890
+
2891
+ ::
2892
+
2893
+ sage: x = polygen(ZZ)
2894
+ sage: K.<a> = NumberField(x^2 - x + 2)
2895
+ sage: E = EllipticCurve([1, a-1, a+1, -2*a-2, -5*a+7]) # 2.0.7.1-268.3-b1
2896
+ sage: P = next(filter(bool, E.torsion_points()))
2897
+ sage: P._has_order_at_least(11)
2898
+ True
2899
+ sage: P._has_order_at_least(12)
2900
+ False
2901
+ sage: P.order()
2902
+ 11
2903
+ sage: Q = E.lift_x(123*a + 456, extend=True)
2904
+ sage: Q._has_order_at_least(10^100)
2905
+ True
2906
+ """
2907
+ n = getattr(self, '_order', None)
2908
+ if n is not None:
2909
+ return n >= bound
2910
+
2911
+ from sage.sets.primes import Primes
2912
+ from sage.rings.finite_rings.finite_field_constructor import GF
2913
+ field_deg = self.curve().base_field().absolute_degree()
2914
+ if field_deg > 1:
2915
+ K = self.curve().base_field().absolute_field('T')
2916
+ _, iso = K.structure()
2917
+ E = self.curve().change_ring(iso)
2918
+ P = self.change_ring(iso)
2919
+ poly = lambda elt: elt.polynomial()
2920
+ if field_deg == 2:
2921
+ # Kamienny-Kenku-Momose
2922
+ bound = min(bound, 18 + 1)
2923
+ else:
2924
+ K, E, P = QQ, self.curve(), self
2925
+ poly = lambda elt: QQ['x'](elt)
2926
+ # Mazur / Ogg's torsion conjecture
2927
+ # Torsion points can only have order <= 12, so order of > 12 -> infinite order
2928
+ bound = min(bound, 12 + 1)
2929
+ assert P.curve() is E
2930
+
2931
+ n = ZZ.one()
2932
+ no_progress = 0
2933
+ for p in Primes():
2934
+ try:
2935
+ f,_ = K.defining_polynomial().change_ring(GF(p)).factor()[0]
2936
+ except ZeroDivisionError:
2937
+ continue
2938
+ F = GF(p).extension(f,'t')
2939
+ red = lambda elt: F(f.parent()(poly(elt)).change_ring(GF(p)) % f)
2940
+
2941
+ try:
2942
+ Ered = E.change_ring(red)
2943
+ Pred = Ered(*map(red, P))
2944
+ except (ZeroDivisionError, ArithmeticError):
2945
+ continue
2946
+
2947
+ o = Pred.order()
2948
+ if not o.divides(n):
2949
+ n = n.lcm(o)
2950
+ no_progress = 0
2951
+ else:
2952
+ no_progress += 1
2953
+
2954
+ if n >= bound:
2955
+ return True
2956
+ if no_progress >= attempts:
2957
+ return
2958
+
2959
+ assert False # unreachable unless there are only finitely many primes
2960
+
2961
+ def is_on_identity_component(self, embedding=None):
2962
+ r"""
2963
+ Return ``True`` iff this point is on the identity component of
2964
+ its curve with respect to a given (real or complex) embedding.
2965
+
2966
+ INPUT:
2967
+
2968
+ - ``self`` -- a point on a curve over any ordered field (e.g. `\QQ`)
2969
+
2970
+ - ``embedding`` -- an embedding from the base_field of the
2971
+ point's curve into `\RR` or `\CC`; if ``None`` (the
2972
+ default) it uses the first embedding of the base_field into
2973
+ `\RR` if any, else the first embedding into `\CC`.
2974
+
2975
+ OUTPUT:
2976
+
2977
+ boolean; ``True`` iff the point is on the identity component of
2978
+ the curve. (If the point is zero then the result is ``True``.)
2979
+
2980
+ EXAMPLES:
2981
+
2982
+ For `K=\QQ` there is no need to specify an embedding::
2983
+
2984
+ sage: # needs database_cremona_mini_ellcurve
2985
+ sage: E = EllipticCurve('5077a1')
2986
+ sage: [E.lift_x(x).is_on_identity_component() for x in srange(-3,5)]
2987
+ [False, False, False, False, False, True, True, True]
2988
+
2989
+ An example over a field with two real embeddings::
2990
+
2991
+ sage: # needs sage.rings.number_field
2992
+ sage: L.<a> = QuadraticField(2)
2993
+ sage: E = EllipticCurve(L, [0,1,0,a,a])
2994
+ sage: P = E(-1,0)
2995
+ sage: [P.is_on_identity_component(e) for e in L.embeddings(RR)]
2996
+ [False, True]
2997
+
2998
+ We can check this as follows::
2999
+
3000
+ sage: # needs sage.rings.number_field
3001
+ sage: [e(E.discriminant()) > 0 for e in L.embeddings(RR)]
3002
+ [True, False]
3003
+ sage: e = L.embeddings(RR)[0]
3004
+ sage: E1 = EllipticCurve(RR, [e(ai) for ai in E.ainvs()])
3005
+ sage: e1, e2, e3 = E1.two_division_polynomial().roots(RR,
3006
+ ....: multiplicities=False)
3007
+ sage: e1 < e2 < e3 and e(P[0]) < e3
3008
+ True
3009
+ """
3010
+ if self.is_zero(): # trivial case
3011
+ return True
3012
+
3013
+ e = embedding
3014
+ # It is also trivially true if we have a complex embedding
3015
+ if e is not None:
3016
+ if not isinstance(e.codomain(), sage.rings.abc.RealField):
3017
+ return True
3018
+
3019
+ # find a suitable embedding if none was supplied:
3020
+ E = self.curve()
3021
+ K = E.base_field()
3022
+ if e is None:
3023
+ try:
3024
+ e = K.embeddings(RealField())[0]
3025
+ except IndexError:
3026
+ e = K.embeddings(ComplexField())[0]
3027
+
3028
+ # If there is only one component, the result is True:
3029
+ if not isinstance(e.codomain(), sage.rings.abc.RealField): # complex embedding
3030
+ return True
3031
+ if e(E.discriminant()) < 0: # only one component
3032
+ return True
3033
+
3034
+ # Now we have a real embedding and two components and have to work:
3035
+ gx = E.two_division_polynomial()
3036
+ gxd = gx.derivative()
3037
+ gxdd = gxd.derivative()
3038
+ return (e(gxd(self[0])) > 0 and e(gxdd(self[0])) > 0)
3039
+
3040
+ def has_good_reduction(self, P=None) -> bool:
3041
+ r"""
3042
+ Return ``True`` iff this point has good reduction modulo a prime.
3043
+
3044
+ INPUT:
3045
+
3046
+ - ``P`` -- a prime of the base_field of the point's curve, or
3047
+ ``None`` (default)
3048
+
3049
+ OUTPUT:
3050
+
3051
+ boolean; if a prime `P` of the base field is specified, returns
3052
+ ``True`` iff the point has good reduction at `P`; otherwise,
3053
+ return ``True`` if the point has god reduction at all primes in
3054
+ the support of the discriminant of this model.
3055
+
3056
+ EXAMPLES::
3057
+
3058
+ sage: # needs database_cremona_mini_ellcurve eclib
3059
+ sage: E = EllipticCurve('990e1')
3060
+ sage: P = E.gen(0); P
3061
+ (15 : 51 : 1)
3062
+ sage: [E.has_good_reduction(p) for p in [2,3,5,7]]
3063
+ [False, False, False, True]
3064
+ sage: [P.has_good_reduction(p) for p in [2,3,5,7]]
3065
+ [True, False, True, True]
3066
+ sage: [E.tamagawa_exponent(p) for p in [2,3,5,7]]
3067
+ [2, 2, 1, 1]
3068
+ sage: [(2*P).has_good_reduction(p) for p in [2,3,5,7]]
3069
+ [True, True, True, True]
3070
+ sage: P.has_good_reduction()
3071
+ False
3072
+ sage: (2*P).has_good_reduction()
3073
+ True
3074
+ sage: (3*P).has_good_reduction()
3075
+ False
3076
+
3077
+ ::
3078
+
3079
+ sage: # needs sage.rings.number_field
3080
+ sage: x = polygen(ZZ, 'x')
3081
+ sage: K.<i> = NumberField(x^2 + 1)
3082
+ sage: E = EllipticCurve(K, [0,1,0,-160,308])
3083
+ sage: P = E(26, -120)
3084
+ sage: E.discriminant().support()
3085
+ [Fractional ideal (i - 1),
3086
+ Fractional ideal (2*i - 1),
3087
+ Fractional ideal (-2*i - 1),
3088
+ Fractional ideal (3)]
3089
+ sage: [E.tamagawa_exponent(p) for p in E.discriminant().support()]
3090
+ [1, 4, 4, 4]
3091
+ sage: P.has_good_reduction()
3092
+ False
3093
+ sage: (2*P).has_good_reduction()
3094
+ False
3095
+ sage: (4*P).has_good_reduction()
3096
+ True
3097
+
3098
+ TESTS:
3099
+
3100
+ An example showing that :issue:`8498` is fixed::
3101
+
3102
+ sage: # needs database_cremona_mini_ellcurve sage.rings.number_field
3103
+ sage: E = EllipticCurve('11a1')
3104
+ sage: K.<t> = NumberField(x^2 + 47)
3105
+ sage: EK = E.base_extend(K)
3106
+ sage: T = EK(5, 5)
3107
+ sage: P = EK(-2, -1/2*t - 1/2)
3108
+ sage: p = K.ideal(11)
3109
+ sage: T.has_good_reduction(p)
3110
+ False
3111
+ sage: P.has_good_reduction(p)
3112
+ True
3113
+ """
3114
+ if self.is_zero(): # trivial case
3115
+ return True
3116
+
3117
+ E = self.curve()
3118
+ if P is None:
3119
+ return all(self.has_good_reduction(Pr)
3120
+ for Pr in E.discriminant().support())
3121
+ K = E.base_field()
3122
+ from sage.schemes.elliptic_curves.ell_local_data import check_prime
3123
+ P = check_prime(K, P)
3124
+
3125
+ # If the curve has good reduction at P, the result is True:
3126
+ t = E.local_data(P).bad_reduction_type()
3127
+ if t is None:
3128
+ return True
3129
+
3130
+ # Make sure the curve is integral and locally minimal at P:
3131
+ Emin = E.local_minimal_model(P)
3132
+ urst = E.isomorphism_to(Emin)
3133
+ Q = urst(self)
3134
+
3135
+ # Scale the homogeneous coordinates of the point to be primitive:
3136
+ xyz = list(Q)
3137
+ e = min([c.valuation(P) for c in xyz])
3138
+ if e != 0:
3139
+ if K is QQ:
3140
+ pi = P
3141
+ else:
3142
+ pi = K.uniformizer(P)
3143
+ pie = pi**e
3144
+ xyz = [c/pie for c in xyz]
3145
+
3146
+ # Evaluate the partial derivatives at the point to see if they
3147
+ # are zero mod P
3148
+
3149
+ # See #8498: sometimes evaluating F's derivatives at xyz
3150
+ # returns a constant polynomial instead of a constant
3151
+
3152
+ F = Emin.defining_polynomial()
3153
+ for v in F.variables():
3154
+ c = (F.derivative(v))(xyz)
3155
+ try:
3156
+ val = c.valuation(P)
3157
+ except AttributeError:
3158
+ val = c.constant_coefficient().valuation(P)
3159
+ if val == 0:
3160
+ return True
3161
+ return False
3162
+
3163
+ def reduction(self, p):
3164
+ """
3165
+ This finds the reduction of a point `P` on the elliptic curve
3166
+ modulo the prime `p`.
3167
+
3168
+ INPUT:
3169
+
3170
+ - ``self`` -- a point on an elliptic curve
3171
+
3172
+ - ``p`` -- a prime number
3173
+
3174
+ OUTPUT: the point reduced to be a point on the elliptic curve modulo `p`
3175
+
3176
+ EXAMPLES::
3177
+
3178
+ sage: E = EllipticCurve([1,2,3,4,0])
3179
+ sage: P = E(0,0)
3180
+ sage: P.reduction(5)
3181
+ (0 : 0 : 1)
3182
+ sage: Q = E(98,931)
3183
+ sage: Q.reduction(5)
3184
+ (3 : 1 : 1)
3185
+ sage: Q.reduction(5).curve() == E.reduction(5)
3186
+ True
3187
+
3188
+ ::
3189
+
3190
+ sage: # needs sage.rings.number_field
3191
+ sage: x = polygen(ZZ, 'x')
3192
+ sage: F.<a> = NumberField(x^2 + 5)
3193
+ sage: E = EllipticCurve(F, [1,2,3,4,0])
3194
+ sage: Q = E(98, 931)
3195
+ sage: Q.reduction(a)
3196
+ (3 : 1 : 1)
3197
+ sage: Q.reduction(11)
3198
+ (10 : 7 : 1)
3199
+
3200
+ ::
3201
+
3202
+ sage: # needs sage.rings.number_field
3203
+ sage: F.<a> = NumberField(x^3 + x^2 + 1)
3204
+ sage: E = EllipticCurve(F, [a,2])
3205
+ sage: P = E(a, 1)
3206
+ sage: P.reduction(F.ideal(5))
3207
+ (abar : 1 : 1)
3208
+ sage: P.reduction(F.ideal(a^2 - 4*a - 2))
3209
+ (abar : 1 : 1)
3210
+ """
3211
+ P = self
3212
+ E = P.curve()
3213
+ return E.reduction(p)(P)
3214
+
3215
+ def height(self, precision=None, normalised=True, algorithm='pari'):
3216
+ r"""Return the Néron-Tate canonical height of the point.
3217
+
3218
+ INPUT:
3219
+
3220
+ - ``self`` -- a point on an elliptic curve over a number field `K`
3221
+
3222
+ - ``precision`` -- positive integer, or ``None`` (default). The
3223
+ precision in bits of the result. If ``None``, the default real
3224
+ precision is used.
3225
+
3226
+ - ``normalised`` -- boolean. If ``True`` (default), the height is
3227
+ normalised to be invariant under extension of `K`. If ``False``,
3228
+ return this normalised height multiplied by the degree of `K`.
3229
+
3230
+ - ``algorithm`` -- string; either ``'pari'`` (default) or ``'sage'``.
3231
+ If ``'pari'`` and the base field is `\QQ`, use the PARI library
3232
+ function; otherwise use the Sage implementation.
3233
+
3234
+ OUTPUT:
3235
+
3236
+ The rational number 0, or a nonnegative real number.
3237
+
3238
+ There are two normalisations used in the literature, one of
3239
+ which is double the other. We use the larger of the two, which
3240
+ is the one appropriate for the BSD conjecture. This is
3241
+ consistent with [Cre1997]_ and double that of [Sil2009]_.
3242
+
3243
+ See :wikipedia:`Néron-Tate height`.
3244
+
3245
+ .. NOTE::
3246
+
3247
+ The correct height to use for the regulator in the BSD
3248
+ formula is the non-normalised height.
3249
+
3250
+ EXAMPLES::
3251
+
3252
+ sage: # needs database_cremona_mini_ellcurve
3253
+ sage: E = EllipticCurve('11a'); E
3254
+ Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
3255
+ sage: P = E([5,5]); P
3256
+ (5 : 5 : 1)
3257
+ sage: P.height()
3258
+ 0
3259
+ sage: Q = 5*P
3260
+ sage: Q.height()
3261
+ 0
3262
+
3263
+ ::
3264
+
3265
+ sage: # needs database_cremona_mini_ellcurve
3266
+ sage: E = EllipticCurve('37a'); E
3267
+ Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
3268
+ sage: P = E([0,0])
3269
+ sage: P.height()
3270
+ 0.0511114082399688
3271
+ sage: P.order()
3272
+ +Infinity
3273
+ sage: E.regulator() # needs eclib
3274
+ 0.0511114082399688...
3275
+ sage: def naive_height(P):
3276
+ ....: return log(RR(max(abs(P[0].numerator()), abs(P[0].denominator()))))
3277
+ sage: for n in [1..10]:
3278
+ ....: print(naive_height(2^n*P)/4^n)
3279
+ 0.000000000000000
3280
+ 0.0433216987849966
3281
+ 0.0502949347635656
3282
+ 0.0511006335618645
3283
+ 0.0511007834799612
3284
+ 0.0511013666152466
3285
+ 0.0511034199907743
3286
+ 0.0511106492906471
3287
+ 0.0511114081541082
3288
+ 0.0511114081541180
3289
+
3290
+ ::
3291
+
3292
+ sage: # needs database_cremona_mini_ellcurve
3293
+ sage: E = EllipticCurve('4602a1'); E
3294
+ Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 37746035*x - 89296920339
3295
+ over Rational Field
3296
+ sage: x = 77985922458974949246858229195945103471590
3297
+ sage: y = 19575260230015313702261379022151675961965157108920263594545223
3298
+ sage: d = 2254020761884782243
3299
+ sage: E([ x / d^2, y / d^3 ]).height()
3300
+ 86.7406561381275
3301
+
3302
+ ::
3303
+
3304
+ sage: # needs database_cremona_mini_ellcurve
3305
+ sage: E = EllipticCurve([17, -60, -120, 0, 0]); E
3306
+ Elliptic Curve defined by y^2 + 17*x*y - 120*y = x^3 - 60*x^2 over Rational Field
3307
+ sage: E([30, -90]).height()
3308
+ 0
3309
+
3310
+ sage: # needs database_cremona_mini_ellcurve
3311
+ sage: E = EllipticCurve('389a1'); E
3312
+ Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
3313
+ sage: P, Q = E(-1,1), E(0,-1)
3314
+ sage: P.height(precision=100)
3315
+ 0.68666708330558658572355210295
3316
+ sage: (3*Q).height(precision=100)/Q.height(precision=100)
3317
+ 9.0000000000000000000000000000
3318
+ sage: _.parent()
3319
+ Real Field with 100 bits of precision
3320
+
3321
+ Canonical heights over number fields are implemented as well::
3322
+
3323
+ sage: R.<x> = QQ[]
3324
+ sage: K.<a> = NumberField(x^3 - 2) # needs sage.rings.number_field
3325
+ sage: E = EllipticCurve([a, 4]); E # needs sage.rings.number_field
3326
+ Elliptic Curve defined by y^2 = x^3 + a*x + 4
3327
+ over Number Field in a with defining polynomial x^3 - 2
3328
+ sage: P = E((0,2)) # needs sage.rings.number_field
3329
+ sage: P.height() # needs sage.rings.number_field
3330
+ 0.810463096585925
3331
+ sage: P.height(precision=100) # needs sage.rings.number_field
3332
+ 0.81046309658592536863991810577
3333
+ sage: P.height(precision=200) # needs sage.rings.number_field
3334
+ 0.81046309658592536863991810576865158896130286417155832378086
3335
+ sage: (2*P).height() / P.height() # needs sage.rings.number_field
3336
+ 4.00000000000000
3337
+ sage: (100*P).height() / P.height() # needs sage.rings.number_field
3338
+ 10000.0000000000
3339
+
3340
+ Setting ``normalised=False`` multiplies the height by the degree of `K`::
3341
+
3342
+ sage: # needs database_cremona_mini_ellcurve
3343
+ sage: E = EllipticCurve('37a')
3344
+ sage: P = E([0,0])
3345
+ sage: P.height()
3346
+ 0.0511114082399688
3347
+ sage: P.height(normalised=False)
3348
+ 0.0511114082399688
3349
+ sage: K.<z> = CyclotomicField(5) # needs sage.rings.number_field
3350
+ sage: EK = E.change_ring(K) # needs sage.rings.number_field
3351
+ sage: PK = EK([0,0]) # needs sage.rings.number_field
3352
+ sage: PK.height() # needs sage.rings.number_field
3353
+ 0.0511114082399688
3354
+ sage: PK.height(normalised=False) # needs sage.rings.number_field
3355
+ 0.204445632959875
3356
+
3357
+ Some consistency checks::
3358
+
3359
+ sage: # needs database_cremona_mini_ellcurve
3360
+ sage: E = EllipticCurve('5077a1')
3361
+ sage: P = E([-2,3,1])
3362
+ sage: P.height()
3363
+ 1.36857250535393
3364
+ sage: EK = E.change_ring(QuadraticField(-3,'a')) # needs sage.rings.number_field
3365
+ sage: PK = EK([-2,3,1]) # needs sage.rings.number_field
3366
+ sage: PK.height() # needs sage.rings.number_field
3367
+ 1.36857250535393
3368
+
3369
+ sage: # needs sage.rings.number_field
3370
+ sage: K.<i> = NumberField(x^2 + 1)
3371
+ sage: E = EllipticCurve(K, [0,0,4,6*i,0])
3372
+ sage: Q = E.lift_x(-9/4); Q
3373
+ (-9/4 : 27/8*i - 4 : 1)
3374
+ sage: Q.height()
3375
+ 2.69518560017909
3376
+ sage: (15*Q).height() / Q.height()
3377
+ 225.000000000000
3378
+
3379
+ sage: # needs database_cremona_mini_ellcurve
3380
+ sage: E = EllipticCurve('37a')
3381
+ sage: P = E([0,-1])
3382
+ sage: P.height()
3383
+ 0.0511114082399688
3384
+ sage: K.<a> = QuadraticField(-7) # needs sage.rings.number_field
3385
+ sage: ED = E.quadratic_twist(-7) # needs sage.rings.number_field
3386
+ sage: Q = E.isomorphism_to(ED.change_ring(K))(P); Q # needs sage.rings.number_field
3387
+ (0 : -7/2*a - 1/2 : 1)
3388
+ sage: Q.height() # needs sage.rings.number_field
3389
+ 0.0511114082399688
3390
+ sage: Q.height(precision=100) # needs sage.rings.number_field
3391
+ 0.051111408239968840235886099757
3392
+
3393
+ An example to show that the bug at :issue:`5252` is fixed::
3394
+
3395
+ sage: E = EllipticCurve([1, -1, 1, -2063758701246626370773726978, 32838647793306133075103747085833809114881])
3396
+ sage: P = E([-30987785091199, 258909576181697016447])
3397
+ sage: P.height()
3398
+ 25.8603170675462
3399
+ sage: P.height(precision=100)
3400
+ 25.860317067546190743868840741
3401
+ sage: P.height(precision=250)
3402
+ 25.860317067546190743868840740735110323098872903844416215577171041783572513
3403
+ sage: P.height(precision=500)
3404
+ 25.8603170675461907438688407407351103230988729038444162155771710417835725129551130570889813281792157278507639909972112856019190236125362914195452321720
3405
+
3406
+ sage: P.height(precision=100) == P.non_archimedean_local_height(prec=100)+P.archimedean_local_height(prec=100)
3407
+ True
3408
+
3409
+ An example to show that the bug at :issue:`8319` is fixed (correct height when the curve is not minimal)::
3410
+
3411
+ sage: E = EllipticCurve([-5580472329446114952805505804593498080000,-157339733785368110382973689903536054787700497223306368000000])
3412
+ sage: xP = 204885147732879546487576840131729064308289385547094673627174585676211859152978311600/23625501907057948132262217188983681204856907657753178415430361
3413
+ sage: P = E.lift_x(xP)
3414
+ sage: P.height()
3415
+ 157.432598516754
3416
+ sage: Q = 2*P
3417
+ sage: Q.height() # long time (4s)
3418
+ 629.730394067016
3419
+ sage: Q.height()-4*P.height() # long time
3420
+ 0.000000000000000
3421
+
3422
+ An example to show that the bug at :issue:`12509` is fixed (precision issues)::
3423
+
3424
+ sage: # needs sage.rings.number_field
3425
+ sage: x = polygen(QQ)
3426
+ sage: K.<a> = NumberField(x^2 - x - 1)
3427
+ sage: v = [0, a + 1, 1, 28665*a - 46382, 2797026*a - 4525688]
3428
+ sage: E = EllipticCurve(v)
3429
+ sage: P = E([72*a - 509/5, -682/25*a - 434/25])
3430
+ sage: P.height()
3431
+ 1.38877711688727
3432
+ sage: (2*P).height()/P.height()
3433
+ 4.00000000000000
3434
+ sage: (2*P).height(precision=100)/P.height(precision=100)
3435
+ 4.0000000000000000000000000000
3436
+ sage: (2*P).height(precision=1000)/P.height(precision=1000)
3437
+ 4.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
3438
+
3439
+ This shows that the bug reported at :issue:`13951` has been fixed::
3440
+
3441
+ sage: E = EllipticCurve([0,17])
3442
+ sage: P1 = E(2,5)
3443
+ sage: P1.height()
3444
+ 1.06248137652528
3445
+ sage: F = E.change_ring(QuadraticField(-3, 'a')) # needs sage.rings.number_field
3446
+ sage: P2 = F([2,5]) # needs sage.rings.number_field
3447
+ sage: P2.height() # needs sage.rings.number_field
3448
+ 1.06248137652528
3449
+
3450
+ This shows that the bug reported at :issue:`36834` (incorrect
3451
+ value when the model is not integral) has been fixed::
3452
+
3453
+ sage: # needs sage.rings.number_field
3454
+ sage: K.<a> = NumberField(x^2 - 84131656042917)
3455
+ sage: E = EllipticCurve(K, [0, 0, 0, -5482707841/48, -244634179112639/864])
3456
+ sage: P = E(349189/12, 1/2*a)
3457
+ sage: P.height()
3458
+ 10.4560438181991
3459
+ sage: [(n*P).height()/P.height() for n in [2,3,4,5]]
3460
+ [4.00000000000000, 9.00000000000000, 16.0000000000000, 25.0000000000000]
3461
+
3462
+ """
3463
+ if self.has_finite_order():
3464
+ return QQ(0)
3465
+
3466
+ E = self.curve()
3467
+ K = E.base_ring()
3468
+
3469
+ if precision is None:
3470
+ precision = RealField().precision()
3471
+
3472
+ known_prec = -1
3473
+ try:
3474
+ height = self.__height
3475
+ known_prec = height.prec()
3476
+ if known_prec > precision:
3477
+ height = RealField(precision)(height)
3478
+ except AttributeError:
3479
+ pass
3480
+
3481
+ if known_prec < precision:
3482
+ if algorithm == 'pari' and K is QQ:
3483
+ Emin = E.minimal_model()
3484
+ iso = E.isomorphism_to(Emin)
3485
+ P = iso(self)
3486
+ h = Emin.pari_curve().ellheight(P, precision=precision)
3487
+ height = RealField(precision)(h)
3488
+ else:
3489
+ height = (self.non_archimedean_local_height(prec=precision)
3490
+ + self.archimedean_local_height(prec=precision))
3491
+
3492
+ # The cached height is the one that is independent of the base field.
3493
+ self.__height = height
3494
+ if not normalised:
3495
+ height *= K.degree()
3496
+ return height
3497
+
3498
+ def archimedean_local_height(self, v=None, prec=None, weighted=False):
3499
+ """
3500
+ Compute the local height of ``self`` at the archimedean place `v`.
3501
+
3502
+ INPUT:
3503
+
3504
+ - ``self`` -- a point on an elliptic curve over a number field `K`
3505
+
3506
+ - ``v`` -- a real or complex embedding of K, or None (default).
3507
+ If `v` is a real or complex embedding, return the local
3508
+ height of ``self`` at `v`. If `v` is None, return the total
3509
+ archimedean contribution to the global height.
3510
+
3511
+ - ``prec`` -- integer or ``None`` (default). The precision of the
3512
+ computation. If ``None``, the precision is deduced from `v`
3513
+
3514
+ - ``weighted`` -- boolean. If ``False`` (default), the height is
3515
+ normalised to be invariant under extension of `K`. If ``True``,
3516
+ return this normalised height multiplied by the local degree
3517
+ if `v` is a single place, or by the degree of `K` if `v` is ``None``.
3518
+
3519
+ OUTPUT:
3520
+
3521
+ A real number. The normalisation is twice that in Silverman's
3522
+ paper [Sil1988]_. Note that this local height depends on the
3523
+ model of the curve.
3524
+
3525
+ ALGORITHM:
3526
+
3527
+ See [Sil1988]_, Section 4.
3528
+
3529
+ EXAMPLES:
3530
+
3531
+ Examples 1, 2, and 3 from [Sil1988]_::
3532
+
3533
+ sage: # needs sage.rings.number_field
3534
+ sage: K.<a> = QuadraticField(-2)
3535
+ sage: E = EllipticCurve(K, [0,-1,1,0,0]); E
3536
+ Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 over Number Field
3537
+ in a with defining polynomial x^2 + 2 with a = 1.414213562373095?*I
3538
+ sage: P = E.lift_x(2 + a); P
3539
+ (a + 2 : -2*a - 2 : 1)
3540
+ sage: P.archimedean_local_height(K.places(prec=170)[0]) / 2
3541
+ 0.45754773287523276736211210741423654346576029814695
3542
+
3543
+ sage: # needs sage.rings.number_field
3544
+ sage: x = polygen(ZZ, 'x')
3545
+ sage: K.<i> = NumberField(x^2 + 1)
3546
+ sage: E = EllipticCurve(K, [0,0,4,6*i,0]); E
3547
+ Elliptic Curve defined by y^2 + 4*y = x^3 + 6*i*x
3548
+ over Number Field in i with defining polynomial x^2 + 1
3549
+ sage: P = E((0,0))
3550
+ sage: P.archimedean_local_height(K.places()[0]) / 2
3551
+ 0.510184995162373
3552
+
3553
+ sage: Q = E.lift_x(-9/4); Q # needs sage.rings.number_field
3554
+ (-9/4 : 27/8*i - 4 : 1)
3555
+ sage: Q.archimedean_local_height(K.places()[0]) / 2 # needs sage.rings.number_field
3556
+ 0.654445619529600
3557
+
3558
+ An example over the rational numbers::
3559
+
3560
+ sage: E = EllipticCurve([0, 0, 0, -36, 0])
3561
+ sage: P = E([-3, 9])
3562
+ sage: P.archimedean_local_height()
3563
+ 1.98723816350773
3564
+
3565
+ Local heights of torsion points can be nonzero (unlike the
3566
+ global height)::
3567
+
3568
+ sage: # needs sage.rings.number_field
3569
+ sage: K.<i> = QuadraticField(-1)
3570
+ sage: E = EllipticCurve([0, 0, 0, K(1), 0])
3571
+ sage: P = E(i, 0)
3572
+ sage: P.archimedean_local_height()
3573
+ 0.346573590279973
3574
+
3575
+ TESTS:
3576
+
3577
+ See :issue:`12509`::
3578
+
3579
+ sage: # needs sage.rings.number_field
3580
+ sage: x = polygen(QQ)
3581
+ sage: K.<a> = NumberField(x^2 - x - 1)
3582
+ sage: v = [0, a + 1, 1, 28665*a - 46382, 2797026*a - 4525688]
3583
+ sage: E = EllipticCurve(v)
3584
+ sage: P = E([72*a - 509/5, -682/25*a - 434/25])
3585
+ sage: P.archimedean_local_height()
3586
+ -0.220660795546828
3587
+
3588
+ See :issue:`19276`::
3589
+
3590
+ sage: # needs sage.rings.number_field
3591
+ sage: K.<a> = NumberField(x^2 - x - 104)
3592
+ sage: E = EllipticCurve([1, a - 1, 1, -816765673272*a - 7931030674178, 1478955604013312315*a + 14361086227143654561])
3593
+ sage: P = E(5393511/49*a + 52372721/49 , -33896210324/343*a - 329141996591/343 )
3594
+ sage: P.height()
3595
+ 0.974232017827741
3596
+
3597
+ See :issue:`29966`::
3598
+
3599
+ sage: # needs sage.rings.number_field
3600
+ sage: K.<a> = NumberField(x^3 - x^2 - 6*x + 2)
3601
+ sage: E = EllipticCurve([1, -a^2 + 2*a + 4, 0, -6056450500590472699700624*a^2 - 11239394326797569935861742*a + 4241549693833829432516231,
3602
+ ....: 1904879037869682826729875958079326124520*a^2 + 3535022146945771697732350459284777382011*a - 1334055169621036218710397707677347972626])
3603
+ sage: P = E([1033399668533*a^2 + 1917754693229*a - 723726883800 , 12536493059202326563*a^2 + 23264879148900575548*a - 8779756111574815918 , 1])
3604
+ sage: P.height()
3605
+ 0.297318833424763
3606
+ sage: (2*P).height() / P.height()
3607
+ 4.00000000000000
3608
+ sage: P.height(200)
3609
+ 0.29731883342476341806143743594519935578696537745294661858984
3610
+ sage: (2*P).height(200) / P.height(200)
3611
+ 4.0000000000000000000000000000000000000000000000000000000000
3612
+ """
3613
+ from sage.rings.number_field.number_field import refine_embedding
3614
+ from sage.rings.real_mpfr import RealField
3615
+ from sage.rings.complex_mpfr import ComplexField
3616
+ from sage.rings.infinity import Infinity
3617
+
3618
+ E = self.curve()
3619
+ K = E.base_ring()
3620
+
3621
+ if v is None:
3622
+
3623
+ if prec is None:
3624
+ prec = 53
3625
+ if K is QQ:
3626
+ v = K.embeddings(RR)[0]
3627
+ h = self.archimedean_local_height(v, prec+10)
3628
+ else:
3629
+ r1, r2 = K.signature()
3630
+ pl = K.places()
3631
+ h = (sum(self.archimedean_local_height(pl[i], prec+10, weighted=False)
3632
+ for i in range(r1))
3633
+ + 2 * sum(self.archimedean_local_height(pl[i], prec+10, weighted=False)
3634
+ for i in range(r1, r1 + r2)))
3635
+ if not weighted:
3636
+ h /= K.degree()
3637
+ return RealField(prec)(h)
3638
+
3639
+ prec_v = v.codomain().prec()
3640
+ if prec is None:
3641
+ prec = prec_v
3642
+ if K is QQ:
3643
+ v = K.embeddings(RealField())[0]
3644
+ v_inf = refine_embedding(v, Infinity)
3645
+ v_is_real = v_inf(K.gen()).imag().is_zero()
3646
+
3647
+ # Find a suitable working precision. See trac#29666 for an
3648
+ # example where 100 extra bits is not enough when the
3649
+ # discriminant is ~1e-92, but this code uses a working
3650
+ # precision of 333 and gets it right.
3651
+
3652
+ D = v_inf(E.discriminant())
3653
+
3654
+ if D.abs().real_number(RealField()).round():
3655
+ extra_prec = 100
3656
+ else: # then |D| is small
3657
+ extra_prec = 10 + (1/D).abs().real_number(RealField()).round().nbits()
3658
+
3659
+ working_prec = prec + extra_prec
3660
+ RC = RealField(working_prec) if v_is_real else ComplexField(working_prec)
3661
+ # print("Using working precision {}, |D| = {}".format(working_prec, RC(D).abs()))
3662
+
3663
+ # NB We risk losing much precision if we compute the embedding
3664
+ # of K into RR or CC to some precision and then apply that to
3665
+ # elements of K. Instead we map elements of K into AA or Qbar
3666
+ # (with infinite precision) and then trim back to RR or CC.
3667
+
3668
+ x = RC(v_inf(self[0]))
3669
+ b2, b4, b6, b8 = (RC(v_inf(b)) for b in E.b_invariants())
3670
+
3671
+ # The following comes from Silverman Theorem 4.2. Silverman
3672
+ # uses decimal precision d, so his term (5/3)d =
3673
+ # (5/3)*(log(2)/log(10))*prec = 0.5017*prec, which we round
3674
+ # up. The rest of the expression was wrongly transcribed in
3675
+ # Sage versions <5.6 (see #12509).
3676
+
3677
+ H = max(RC(4).abs(), b2.abs(), 2*b4.abs(), 2*b6.abs(), b8.abs())
3678
+ absdisc = RC(v_inf(E.discriminant())).abs()
3679
+ adl3 = 0 if absdisc >= 1 else absdisc.log() / 3
3680
+ nterms = int(math.ceil(0.51*working_prec + 0.5 + 0.75 * (7 + 4*H.log()/3 - adl3).log()))
3681
+
3682
+ b2p = b2 - 12
3683
+ b4p = b4 - b2 + 6
3684
+ b6p = b6 - 2*b4 + b2 - 4
3685
+ b8p = b8 - 3*b6 + 3*b4 - b2 + 3
3686
+
3687
+ fz = lambda T: 1 - T**2 * (b4 + T*(2*b6 + T*b8))
3688
+ fzp = lambda T: 1 - T**2 * (b4p + T*(2*b6p + T*b8p))
3689
+ fw = lambda T: T*(4 + T*(b2 + T*(2*b4 + T*b6)))
3690
+ fwp = lambda T: T*(4 + T*(b2p + T*(2*b4p + T*b6p)))
3691
+
3692
+ if abs(x) >= .5:
3693
+ t = 1/x
3694
+ beta = True
3695
+ else:
3696
+ t = 1/(x+1)
3697
+ beta = False
3698
+ lam = -t.abs().log()
3699
+ mu = 0
3700
+ four_to_n = QQ(1)
3701
+
3702
+ for n in range(nterms):
3703
+ if beta:
3704
+ w = fw(t)
3705
+ z = fz(t)
3706
+ if abs(w) <= 2 * z.abs():
3707
+ mu += four_to_n * z.abs().log()
3708
+ t = w/z
3709
+ else:
3710
+ mu += four_to_n * (z+w).abs().log()
3711
+ t = w/(z+w)
3712
+ beta = not beta
3713
+ else:
3714
+ w = fwp(t)
3715
+ z = fzp(t)
3716
+ if abs(w) <= 2 * z.abs():
3717
+ mu += four_to_n * z.abs().log()
3718
+ t = w/z
3719
+ else:
3720
+ mu += four_to_n * (z-w).abs().log()
3721
+ t = w/(z-w)
3722
+ beta = not beta
3723
+ four_to_n >>= 2
3724
+
3725
+ h = RealField(prec)(lam + mu/4)
3726
+ if weighted and not v_is_real:
3727
+ h *= 2
3728
+ return h
3729
+
3730
+ def non_archimedean_local_height(self, v=None, prec=None,
3731
+ weighted=False, is_minimal=None):
3732
+ """
3733
+ Compute the local height of ``self`` at non-archimedean places.
3734
+
3735
+ INPUT:
3736
+
3737
+ - ``self`` -- a point on an elliptic curve over a number field `K`
3738
+
3739
+ - ``v`` -- a non-archimedean place of `K`, or ``None`` (default).
3740
+ If `v` is a non-archimedean place, return the local height
3741
+ of ``self`` at `v`. If `v` is ``None``, return the total
3742
+ non-archimedean contribution to the global height.
3743
+
3744
+ - ``prec`` -- integer; or ``None`` (default). The precision of the
3745
+ computation. If ``None``, the height is returned symbolically
3746
+
3747
+ - ``weighted`` -- boolean. If ``False`` (default), the height is
3748
+ normalised to be invariant under extension of `K`. If ``True``,
3749
+ return this normalised height multiplied by the local degree
3750
+ if `v` is a single place, or by the degree of `K` if `v` is ``None``.
3751
+
3752
+ - ``is_minimal`` -- boolean, or ``None`` (default). Ignored
3753
+ when ``v`` is ``None`` (default) or ``True``. Otherwise,
3754
+ when the place ``v`` is specified: if ``True``, the model is
3755
+ assumed to be both locally integral and a local minimal
3756
+ model; if ``None`` (default) or ``False``, a local minimal
3757
+ model is computed and the computation is done on that model.
3758
+
3759
+ OUTPUT:
3760
+
3761
+ A real number. The normalisation is twice that in Silverman's
3762
+ paper [Sil1988]_. Note that this local height depends on the
3763
+ model of the curve.
3764
+
3765
+ ALGORITHM:
3766
+
3767
+ See [Sil1988]_, Section 5.
3768
+
3769
+ EXAMPLES:
3770
+
3771
+ Examples 2 and 3 from [Sil1988]_::
3772
+
3773
+ sage: # needs sage.rings.number_field sage.symbolic
3774
+ sage: x = polygen(ZZ, 'x')
3775
+ sage: K.<i> = NumberField(x^2 + 1)
3776
+ sage: E = EllipticCurve(K, [0,0,4,6*i,0]); E
3777
+ Elliptic Curve defined by y^2 + 4*y = x^3 + 6*i*x
3778
+ over Number Field in i with defining polynomial x^2 + 1
3779
+ sage: P = E((0,0))
3780
+ sage: P.non_archimedean_local_height(K.ideal(i+1))
3781
+ -1/2*log(2)
3782
+ sage: P.non_archimedean_local_height(K.ideal(3))
3783
+ 0
3784
+ sage: P.non_archimedean_local_height(K.ideal(1-2*i))
3785
+ 0
3786
+ sage: Q = E.lift_x(-9/4); Q
3787
+ (-9/4 : 27/8*i - 4 : 1)
3788
+ sage: Q.non_archimedean_local_height(K.ideal(1+i))
3789
+ 2*log(2)
3790
+ sage: Q.non_archimedean_local_height(K.ideal(3))
3791
+ 0
3792
+ sage: Q.non_archimedean_local_height(K.ideal(1-2*i))
3793
+ 0
3794
+ sage: Q.non_archimedean_local_height()
3795
+ 2*log(2)
3796
+
3797
+ An example over the rational numbers::
3798
+
3799
+ sage: E = EllipticCurve([0, 0, 0, -36, 0])
3800
+ sage: P = E([-3, 9])
3801
+ sage: P.non_archimedean_local_height() # needs sage.symbolic
3802
+ -log(3)
3803
+
3804
+ Local heights of torsion points can be nonzero (unlike the
3805
+ global height)::
3806
+
3807
+ sage: # needs sage.rings.number_field sage.symbolic
3808
+ sage: K.<i> = QuadraticField(-1)
3809
+ sage: E = EllipticCurve([0, 0, 0, K(1), 0])
3810
+ sage: P = E(i, 0)
3811
+ sage: P.non_archimedean_local_height()
3812
+ -1/2*log(2)
3813
+
3814
+ TESTS::
3815
+
3816
+ sage: Q.non_archimedean_local_height(prec=100) # needs sage.rings.number_field sage.symbolic
3817
+ 1.3862943611198906188344642429
3818
+ sage: (3*Q).non_archimedean_local_height() # needs sage.rings.number_field sage.symbolic
3819
+ 1/2*log(75923153929839865104)
3820
+
3821
+ sage: # needs sage.rings.number_field
3822
+ sage: x = polygen(ZZ, 'x')
3823
+ sage: F.<a> = NumberField(x^4 + 2*x^3 + 19*x^2 + 18*x + 288)
3824
+ sage: F.ring_of_integers().basis()
3825
+ [1, 5/6*a^3 + 1/6*a, 1/6*a^3 + 1/6*a^2, a^3]
3826
+ sage: F.class_number()
3827
+ 12
3828
+ sage: E = EllipticCurve('37a').change_ring(F)
3829
+ sage: P = E((-a^2/6 - a/6 - 1, a)); P
3830
+ (-1/6*a^2 - 1/6*a - 1 : a : 1)
3831
+ sage: P[0].is_integral()
3832
+ True
3833
+ sage: P.non_archimedean_local_height() # needs sage.symbolic
3834
+ 0
3835
+
3836
+ This shows that the bug reported at :issue:`13951` has been fixed::
3837
+
3838
+ sage: E = EllipticCurve([0,17])
3839
+ sage: P = E(2,5)
3840
+ sage: P.non_archimedean_local_height(2) # needs sage.symbolic
3841
+ -2/3*log(2)
3842
+
3843
+ This shows that the bug reported at :issue:`36834` (incorrect
3844
+ value when the model is not integral) has been fixed::
3845
+
3846
+ sage: # needs sage.rings.number_field sage.symbolic
3847
+ sage: K.<a> = QuadraticField(84131656042917)
3848
+ sage: E = EllipticCurve(K, [0, 0, 0, -5482707841/48, -244634179112639/864])
3849
+ sage: P = E(349189/12, 1/2*a)
3850
+ sage: h = P.non_archimedean_local_height()
3851
+ sage: h
3852
+ 1/2*log(144) - log(3) - 2*log(2)
3853
+ sage: h.numerator().simplify_log()
3854
+ 0
3855
+
3856
+ """
3857
+ if prec:
3858
+ log = lambda x: RealField(prec)(x).log()
3859
+ else:
3860
+ from sage.functions.log import log
3861
+
3862
+ if v is None:
3863
+ D = self.curve().discriminant()
3864
+ K = self.curve().base_ring()
3865
+ if K is QQ:
3866
+ factorD = D.factor()
3867
+ if self[0] == 0:
3868
+ c = 1
3869
+ else:
3870
+ c = self[0].denominator()
3871
+ # The last sum is for bad primes that divide c where
3872
+ # the model is not minimal.
3873
+ h = (log(c)
3874
+ + sum(self.non_archimedean_local_height(p, prec, weighted=True, is_minimal=(e < 12))
3875
+ for p, e in factorD if not p.divides(c))
3876
+ + sum(self.non_archimedean_local_height(p, prec, weighted=True)
3877
+ - c.valuation(p) * log(p)
3878
+ for p, e in factorD if e >= 12 and c.valuation(p)))
3879
+ else:
3880
+ factorD = K.factor(D)
3881
+ if self[0] == 0:
3882
+ c = K.ideal(1)
3883
+ else:
3884
+ c = K.ideal(self[0]).denominator()
3885
+ h = (log(c.norm())
3886
+ + sum(self.non_archimedean_local_height(v, prec, weighted=True)
3887
+ - c.valuation(v) * log(v.norm())
3888
+ for v, e in factorD))
3889
+ if not weighted:
3890
+ h /= K.degree()
3891
+ return h
3892
+
3893
+ if is_minimal:
3894
+ E = self.curve()
3895
+ P = self
3896
+ offset = ZZ.zero()
3897
+ else:
3898
+ E = self.curve().local_minimal_model(v)
3899
+ P = self.curve().isomorphism_to(E)(self)
3900
+ # Silverman's normalization is not invariant under change of model,
3901
+ # but it all cancels out in the global height.
3902
+ offset = (self.curve().discriminant()/E.discriminant()).valuation(v)
3903
+
3904
+ a1, a2, a3, a4, a6 = E.a_invariants()
3905
+ b2, b4, b6, b8 = E.b_invariants()
3906
+ c4 = E.c4()
3907
+ x, y = P.xy()
3908
+ D = E.discriminant()
3909
+ N = D.valuation(v)
3910
+ A = (3*x**2 + 2*a2*x + a4 - a1*y).valuation(v)
3911
+ B = (2*y+a1*x+a3).valuation(v)
3912
+ C = (3*x**4 + b2*x**3 + 3*b4*x**2 + 3*b6*x + b8).valuation(v)
3913
+ if A <= 0 or B <= 0:
3914
+ r = max(0, -x.valuation(v))
3915
+ elif c4.valuation(v) == 0:
3916
+ n = min(B, N/2)
3917
+ r = -n*(N-n)/N
3918
+ elif C >= 3*B:
3919
+ r = -2*B/3
3920
+ else:
3921
+ r = -C/4
3922
+ r -= offset/6
3923
+ if not r:
3924
+ return QQ.zero()
3925
+ else:
3926
+ if E.base_ring() is QQ:
3927
+ Nv = Integer(v)
3928
+ else:
3929
+ Nv = v.norm()
3930
+ if not weighted:
3931
+ r = r / (v.ramification_index() * v.residue_class_degree())
3932
+ return r * log(Nv)
3933
+
3934
+ def elliptic_logarithm(self, embedding=None, precision=100,
3935
+ algorithm='pari'):
3936
+ r"""
3937
+ Return the elliptic logarithm of this elliptic curve point.
3938
+
3939
+ An embedding of the base field into `\RR` or `\CC` (with
3940
+ arbitrary precision) may be given; otherwise the first real
3941
+ embedding is used (with the specified precision) if any, else
3942
+ the first complex embedding.
3943
+
3944
+ INPUT:
3945
+
3946
+ - ``embedding`` -- an embedding of the base field into `\RR` or `\CC`
3947
+
3948
+ - ``precision`` -- a positive integer (default: 100) setting the
3949
+ number of bits of precision for the computation
3950
+
3951
+ - ``algorithm`` -- either ``'pari'`` (default: for real embeddings)
3952
+ to use PARI's :pari:`ellpointtoz`, or ``'sage'`` for a native
3953
+ implementation. Ignored for complex embeddings.
3954
+
3955
+ ALGORITHM:
3956
+
3957
+ See [Coh1993]_ for the case of real embeddings,
3958
+ and Cremona, J.E. and Thongjunthug, T. 2010 for the complex
3959
+ case.
3960
+
3961
+ AUTHORS:
3962
+
3963
+ - Michael Mardaus (2008-07),
3964
+ - Tobias Nagel (2008-07) -- original version from [Coh1993]_.
3965
+ - John Cremona (2008-07) -- revision following eclib code.
3966
+ - John Cremona (2010-03) -- implementation for complex embeddings.
3967
+
3968
+ EXAMPLES::
3969
+
3970
+ sage: # needs database_cremona_mini_ellcurve
3971
+ sage: E = EllipticCurve('389a')
3972
+ sage: E.discriminant() > 0
3973
+ True
3974
+ sage: P = E([-1,1])
3975
+ sage: P.is_on_identity_component ()
3976
+ False
3977
+ sage: P.elliptic_logarithm (precision=96)
3978
+ 0.4793482501902193161295330101 + 0.985868850775824102211203849...*I
3979
+ sage: Q = E([3,5])
3980
+ sage: Q.is_on_identity_component()
3981
+ True
3982
+ sage: Q.elliptic_logarithm (precision=96)
3983
+ 1.931128271542559442488585220
3984
+
3985
+ An example with negative discriminant, and a torsion point::
3986
+
3987
+ sage: # needs database_cremona_mini_ellcurve
3988
+ sage: E = EllipticCurve('11a1')
3989
+ sage: E.discriminant() < 0
3990
+ True
3991
+ sage: P = E([16,-61])
3992
+ sage: P.elliptic_logarithm(precision=70)
3993
+ 0.25384186085591068434
3994
+ sage: E.period_lattice().real_period(prec=70) / P.elliptic_logarithm(precision=70)
3995
+ 5.0000000000000000000
3996
+
3997
+ A larger example. The default algorithm uses PARI and makes
3998
+ sure the result has the requested precision::
3999
+
4000
+ sage: E = EllipticCurve([1, 0, 1, -85357462, 303528987048]) #18074g1
4001
+ sage: P = E([4458713781401/835903744, -64466909836503771/24167649046528, 1])
4002
+ sage: P.elliptic_logarithm() # 100 bits
4003
+ 0.27656204014107061464076203097
4004
+
4005
+ The native algorithm ``'sage'`` used to have trouble with
4006
+ precision in this example, but no longer::
4007
+
4008
+ sage: P.elliptic_logarithm(algorithm='sage') # 100 bits
4009
+ 0.27656204014107061464076203097
4010
+
4011
+ This shows that the bug reported at :issue:`4901` has been fixed::
4012
+
4013
+ sage: # needs database_cremona_mini_ellcurve
4014
+ sage: E = EllipticCurve("4390c2")
4015
+ sage: P = E(683762969925/44944,-565388972095220019/9528128)
4016
+ sage: P.elliptic_logarithm()
4017
+ 0.00025638725886520225353198932529
4018
+ sage: P.elliptic_logarithm(precision=64)
4019
+ 0.000256387258865202254
4020
+ sage: P.elliptic_logarithm(precision=65)
4021
+ 0.0002563872588652022535
4022
+ sage: P.elliptic_logarithm(precision=128)
4023
+ 0.00025638725886520225353198932528666427412
4024
+ sage: P.elliptic_logarithm(precision=129)
4025
+ 0.00025638725886520225353198932528666427412
4026
+ sage: P.elliptic_logarithm(precision=256)
4027
+ 0.0002563872588652022535319893252866642741168388008346370015005142128009610936373
4028
+ sage: P.elliptic_logarithm(precision=257)
4029
+ 0.00025638725886520225353198932528666427411683880083463700150051421280096109363730
4030
+
4031
+ Examples over number fields::
4032
+
4033
+ sage: # needs sage.rings.number_field
4034
+ sage: x = polygen(ZZ, 'x')
4035
+ sage: K.<a> = NumberField(x^3 - 2)
4036
+ sage: embs = K.embeddings(CC)
4037
+ sage: E = EllipticCurve([0,1,0,a,a])
4038
+ sage: Ls = [E.period_lattice(e) for e in embs]
4039
+ sage: [L.real_flag for L in Ls]
4040
+ [0, 0, -1]
4041
+ sage: P = E(-1,0) # order 2
4042
+ sage: [L.elliptic_logarithm(P) for L in Ls]
4043
+ [-1.73964256006716 - 1.07861534489191*I,
4044
+ -0.363756518406398 - 1.50699412135253*I, 1.90726488608927]
4045
+
4046
+ sage: # needs sage.rings.number_field
4047
+ sage: E = EllipticCurve([-a^2 - a - 1, a^2 + a])
4048
+ sage: Ls = [E.period_lattice(e) for e in embs]
4049
+ sage: pts = [E(2*a^2 - a - 1 , -2*a^2 - 2*a + 6 ),
4050
+ ....: E(-2/3*a^2 - 1/3 , -4/3*a - 2/3 ),
4051
+ ....: E(5/4*a^2 - 1/2*a , -a^2 - 1/4*a + 9/4 ),
4052
+ ....: E(2*a^2 + 3*a + 4 , -7*a^2 - 10*a - 12 )]
4053
+ sage: [[L.elliptic_logarithm(P) for P in pts] for L in Ls]
4054
+ [[0.250819591818930 - 0.411963479992219*I, -0.290994550611374 - 1.37239400324105*I,
4055
+ -0.693473752205595 - 2.45028458830342*I, -0.151659609775291 - 1.48985406505459*I],
4056
+ [1.33444787667954 - 1.50889756650544*I, 0.792633734249234 - 0.548467043256610*I,
4057
+ 0.390154532655013 + 0.529423541805758*I, 0.931968675085317 - 0.431006981443071*I],
4058
+ [1.14758249500109 + 0.853389664016075*I, 2.59823462472518 + 0.853389664016075*I,
4059
+ 1.75372176444709, 0.303069634723001]]
4060
+
4061
+ ::
4062
+
4063
+ sage: # needs sage.rings.number_field
4064
+ sage: K.<i> = QuadraticField(-1)
4065
+ sage: E = EllipticCurve([0,0,0,9*i-10,21-i])
4066
+ sage: emb = K.embeddings(CC)[1]
4067
+ sage: L = E.period_lattice(emb)
4068
+ sage: P = E(2-i, 4+2*i)
4069
+ sage: L.elliptic_logarithm(P, prec=100)
4070
+ 0.70448375537782208460499649302 - 0.79246725643650979858266018068*I
4071
+ """
4072
+ from sage.rings.number_field.number_field import refine_embedding
4073
+ from sage.rings.real_mpfr import RealField
4074
+ from sage.rings.complex_mpfr import ComplexField
4075
+ from sage.rings.rational_field import QQ
4076
+
4077
+ # Check the trivial case:
4078
+
4079
+ C = ComplexField(precision)
4080
+ if self.is_zero():
4081
+ return C.zero()
4082
+
4083
+ # find a suitable embedding if none was supplied:
4084
+
4085
+ E = self.curve()
4086
+ K = E.base_field()
4087
+ rational = (K is QQ)
4088
+ emb = embedding
4089
+
4090
+ if emb is None:
4091
+ emb = K.embeddings(RealField(precision))
4092
+ if emb:
4093
+ emb = emb[0]
4094
+ else:
4095
+ emb = K.embeddings(ComplexField(precision))[0]
4096
+ else:
4097
+ # Get the precision of the supplied embedding
4098
+ prec = emb.codomain().precision()
4099
+ # if the precision parameter is greater, refine the embedding:
4100
+ if precision > prec:
4101
+ emb = refine_embedding(emb, precision)
4102
+
4103
+ L = E.period_lattice(emb)
4104
+
4105
+ if algorithm == 'sage' or not isinstance(emb.codomain, sage.rings.abc.RealField):
4106
+ return L.elliptic_logarithm(self, precision)
4107
+
4108
+ if algorithm != 'pari':
4109
+ raise ValueError("algorithm must be either 'pari' or 'sage'")
4110
+
4111
+ # From now on emb() is a real embedding of K into
4112
+ # RealField(precision). We interface with the PARI library.
4113
+
4114
+ x, y = self.xy()
4115
+ if rational: # work with exact coordinates
4116
+ E_work = E
4117
+ pt_pari = pari([x, y])
4118
+ else: # use the embedding to get real coordinates
4119
+ ai = [emb(a) for a in E.a_invariants()]
4120
+ E_work = EllipticCurve(ai) # defined over RR
4121
+ pt_pari = pari([emb(x), emb(y)])
4122
+ working_prec = precision
4123
+ E_pari = E_work.pari_curve()
4124
+ log_pari = E_pari.ellpointtoz(pt_pari, precision=working_prec)
4125
+
4126
+ while log_pari.bitprecision() < precision:
4127
+ # result is not precise enough, re-compute with double
4128
+ # precision. if the base field is not QQ, this
4129
+ # requires modifying the precision of the embedding,
4130
+ # the curve, and the point
4131
+ working_prec = 2*working_prec
4132
+ if not rational:
4133
+ emb = refine_embedding(emb, working_prec)
4134
+ ai = [emb(a) for a in E.a_invariants()]
4135
+ E_work = EllipticCurve(ai) # defined over RR
4136
+ pt_pari = pari([emb(x), emb(y)])
4137
+ E_pari = E_work.pari_curve()
4138
+ log_pari = E_pari.ellpointtoz(pt_pari, precision=working_prec)
4139
+
4140
+ # normalization step
4141
+ r, i = C(log_pari)
4142
+ wR, wI = L.basis(prec=precision)
4143
+ k = (r/wR).floor()
4144
+ if k:
4145
+ r -= k*wR
4146
+ if self.is_on_identity_component(emb):
4147
+ return C(r)
4148
+ # Now there are two components and P is on the non-identity one
4149
+ return C(r)+C(wI/2)
4150
+
4151
+ def padic_elliptic_logarithm(self, p, absprec=20):
4152
+ r"""
4153
+ Compute the `p`-adic elliptic logarithm of this point.
4154
+
4155
+ INPUT:
4156
+
4157
+ - ``p`` -- integer; a prime
4158
+
4159
+ - ``absprec`` -- integer (default: 20); the initial `p`-adic absolute
4160
+ precision of the computation
4161
+
4162
+ OUTPUT:
4163
+
4164
+ The `p`-adic elliptic logarithm of self, with precision ``absprec``.
4165
+
4166
+ AUTHORS:
4167
+
4168
+ - Tobias Nagel
4169
+ - Michael Mardaus
4170
+ - John Cremona
4171
+
4172
+ ALGORITHM:
4173
+
4174
+ For points in the formal group (i.e. not integral at `p`) we
4175
+ take the ``log()`` function from the formal groups module and
4176
+ evaluate it at `-x/y`. Otherwise we first multiply the point
4177
+ to get into the formal group, and divide the result
4178
+ afterwards.
4179
+
4180
+ .. TODO::
4181
+
4182
+ See comments at :issue:`4805`. Currently the absolute
4183
+ precision of the result may be less than the given value
4184
+ of absprec, and error-handling is imperfect.
4185
+
4186
+ EXAMPLES::
4187
+
4188
+ sage: E = EllipticCurve([0,1,1,-2,0])
4189
+ sage: E(0).padic_elliptic_logarithm(3) # needs sage.rings.padics
4190
+ 0
4191
+ sage: P = E(0, 0) # needs sage.rings.padics
4192
+ sage: P.padic_elliptic_logarithm(3) # needs sage.rings.padics
4193
+ 2 + 2*3 + 3^3 + 2*3^7 + 3^8 + 3^9 + 3^11 + 3^15 + 2*3^17 + 3^18 + O(3^19)
4194
+ sage: P.padic_elliptic_logarithm(3).lift() # needs sage.rings.padics
4195
+ 660257522
4196
+ sage: P = E(-11/9, 28/27) # needs sage.rings.padics
4197
+ sage: [(2*P).padic_elliptic_logarithm(p)/P.padic_elliptic_logarithm(p) for p in prime_range(20)] # long time, needs sage.rings.padics
4198
+ [2 + O(2^19), 2 + O(3^20), 2 + O(5^19), 2 + O(7^19), 2 + O(11^19), 2 + O(13^19), 2 + O(17^19), 2 + O(19^19)]
4199
+ sage: [(3*P).padic_elliptic_logarithm(p)/P.padic_elliptic_logarithm(p) for p in prime_range(12)] # long time, needs sage.rings.padics
4200
+ [1 + 2 + O(2^19), 3 + 3^20 + O(3^21), 3 + O(5^19), 3 + O(7^19), 3 + O(11^19)]
4201
+ sage: [(5*P).padic_elliptic_logarithm(p)/P.padic_elliptic_logarithm(p) for p in prime_range(12)] # long time, needs sage.rings.padics
4202
+ [1 + 2^2 + O(2^19), 2 + 3 + O(3^20), 5 + O(5^19), 5 + O(7^19), 5 + O(11^19)]
4203
+
4204
+ An example which arose during reviewing :issue:`4741`::
4205
+
4206
+ sage: # needs database_cremona_mini_ellcurve
4207
+ sage: E = EllipticCurve('794a1')
4208
+ sage: P = E(-1,2)
4209
+ sage: P.padic_elliptic_logarithm(2) # default precision=20 # needs sage.rings.padics
4210
+ 2^4 + 2^5 + 2^6 + 2^8 + 2^9 + 2^13 + 2^14 + 2^15 + O(2^16)
4211
+ sage: P.padic_elliptic_logarithm(2, absprec=30) # needs sage.rings.padics
4212
+ 2^4 + 2^5 + 2^6 + 2^8 + 2^9 + 2^13 + 2^14 + 2^15 + 2^22 + 2^23 + 2^24 + O(2^26)
4213
+ sage: P.padic_elliptic_logarithm(2, absprec=40) # needs sage.rings.padics
4214
+ 2^4 + 2^5 + 2^6 + 2^8 + 2^9 + 2^13 + 2^14 + 2^15 + 2^22 + 2^23 + 2^24
4215
+ + 2^28 + 2^29 + 2^31 + 2^34 + O(2^35)
4216
+ """
4217
+ if not p.is_prime():
4218
+ raise ValueError('p must be prime')
4219
+ debug = False # True
4220
+ if debug:
4221
+ print("P=", self, "; p=", p, " with precision ", absprec)
4222
+ E = self.curve()
4223
+ Q_p = Qp(p, absprec)
4224
+ if self.has_finite_order():
4225
+ return Q_p(0)
4226
+ while True:
4227
+ try:
4228
+ Ep = E.change_ring(Q_p)
4229
+ P = Ep(self)
4230
+ x, y = P.xy()
4231
+ break
4232
+ except (PrecisionError, ArithmeticError, ZeroDivisionError):
4233
+ absprec *= 2
4234
+ Q_p = Qp(p, absprec)
4235
+ if debug:
4236
+ print("x,y=", (x, y))
4237
+ f = 1 # f will be such that f*P is in the formal group E^1(Q_p)
4238
+ if x.valuation() >= 0: # P is not in E^1
4239
+ if not self.has_good_reduction(p): # P is not in E^0
4240
+ n = E.tamagawa_exponent(p) # n*P has good reduction at p
4241
+ if debug:
4242
+ print("Tamagawa exponent = =", n)
4243
+ f = n
4244
+ P = n*P # lies in E^0
4245
+ if debug:
4246
+ print("P=", P)
4247
+ try:
4248
+ x, y = P.xy()
4249
+ except ZeroDivisionError:
4250
+ raise ValueError("Insufficient precision in "
4251
+ "p-adic_elliptic_logarithm()")
4252
+ if debug:
4253
+ print("x,y=", (x, y))
4254
+ if x.valuation() >= 0: # P is still not in E^1
4255
+ t = E.local_data(p).bad_reduction_type()
4256
+ if t is None:
4257
+ m = E.reduction(p).abelian_group().exponent()
4258
+ else:
4259
+ m = p - t
4260
+ if debug:
4261
+ print("mod p exponent = =", m)
4262
+ # now m*(n*P) reduces to the identity mod p, so is
4263
+ # in E^1(Q_p)
4264
+ f *= m
4265
+ P = m*P # lies in E^1
4266
+ try:
4267
+ x, y = P.xy()
4268
+ except ZeroDivisionError:
4269
+ raise ValueError("Insufficient precision in "
4270
+ "p-adic_elliptic_logarithm()")
4271
+ if debug:
4272
+ print("f=", f)
4273
+ print("x,y=", (x, y))
4274
+ vx = x.valuation()
4275
+ vy = y.valuation()
4276
+ v = vx-vy
4277
+ if not (v > 0 and vx == -2*v and vy == -3*v):
4278
+ raise ValueError("Insufficient precision in "
4279
+ "p-adic_elliptic_logarithm()")
4280
+ try:
4281
+ t = -x/y
4282
+ except (ZeroDivisionError, PrecisionError):
4283
+ raise ValueError("Insufficient precision in "
4284
+ "p-adic_elliptic_logarithm()")
4285
+ if debug:
4286
+ print("t=", t, ", with valuation ", v)
4287
+ phi = Ep.formal().log(prec=1+absprec//v)
4288
+ return phi(t)/f
4289
+
4290
+
4291
+ class EllipticCurvePoint_finite_field(EllipticCurvePoint_field):
4292
+ r"""
4293
+ Class for elliptic curve points over finite fields.
4294
+ """
4295
+ def _magma_init_(self, magma):
4296
+ """
4297
+ Return a string representation of ``self`` that ``MAGMA`` can
4298
+ use for input.
4299
+
4300
+ EXAMPLES::
4301
+
4302
+ sage: E = EllipticCurve(GF(17), [1,-1])
4303
+ sage: P = E([13, 4])
4304
+ sage: P._magma_init_(magma) # optional - magma
4305
+ 'EllipticCurve([_sage_ref...|GF(17)!0,GF(17)!0,GF(17)!0,GF(17)!1,GF(17)!16])![13,4]'
4306
+ """
4307
+ E = self.curve()._magma_init_(magma)
4308
+ x, y = self.xy()
4309
+ return "%s![%s,%s]" % (E, x, y)
4310
+
4311
+ def _acted_upon_(self, other, side):
4312
+ r"""
4313
+ We implement ``_acted_upon_`` to make use of the specialized faster
4314
+ scalar multiplication from PARI, and to keep track of cached point
4315
+ orders when scalar multiplications are applied.
4316
+
4317
+ EXAMPLES::
4318
+
4319
+ sage: # needs sage.rings.finite_rings
4320
+ sage: P = EllipticCurve(GF(65537), [2,2]).lift_x(6)
4321
+ sage: P.order().factor()
4322
+ 2^2 * 3 * 37^2
4323
+ sage: getattr(74*P, '_order', None)
4324
+ 222
4325
+ sage: getattr(P*4070, '_order', None)
4326
+ 222
4327
+ sage: getattr(506*P*37, '_order', None)
4328
+ 222
4329
+ """
4330
+ k = ZZ(other)
4331
+ E = self.curve()
4332
+
4333
+ try:
4334
+ pariQ = pari.ellmul(E, self, k)
4335
+ except PariError as err:
4336
+ if str(err.errdata().component(1)) == "Fp_inv":
4337
+ val = err.errdata().component(2)
4338
+ a = val.lift()
4339
+ N = val.mod()
4340
+ N1 = N.gcd(a)
4341
+ N2 = N//N1
4342
+ raise ZeroDivisionError(
4343
+ f"Inverse of {a} does not exist"
4344
+ f" (characteristic = {N} = {N1}*{N2})")
4345
+ pariQ = None
4346
+
4347
+ if pariQ is not None:
4348
+ if pariQ == [0]:
4349
+ vQ = 0
4350
+ else:
4351
+ assert len(pariQ) == 2
4352
+ vQ = Sequence(tuple(pariQ) + (1,), E.base_ring())
4353
+ Q = EllipticCurvePoint_finite_field(E, vQ, check=False)
4354
+
4355
+ else:
4356
+ Q = IntegerMulAction(ZZ, self.parent())._act_(k, self)
4357
+
4358
+ n = getattr(self, '_order', None)
4359
+ if n is not None:
4360
+ Q._order = n // n.gcd(k) # Lagrange's theorem
4361
+
4362
+ return Q
4363
+
4364
+ def log(self, base):
4365
+ r"""
4366
+ Return the discrete logarithm of this point to the given ``base``.
4367
+ In other words, return an integer `x` such that `xP = Q` where
4368
+ `P` is ``base`` and `Q` is this point.
4369
+
4370
+ If ``base`` is a list or tuple of two points, then this function
4371
+ solves a two-dimensional discrete logarithm: Given `(P_1,P_2)` in
4372
+ ``base``, it returns a tuple of integers `(x,y)` such that
4373
+ `[x]P_1 + [y]P_2 = Q`, where `Q` is this point.
4374
+
4375
+ A :exc:`ValueError` is raised if there is no solution.
4376
+
4377
+ ALGORITHM:
4378
+
4379
+ To compute the actual logarithm, :pari:`elllog` is called.
4380
+
4381
+ However, ``elllog()`` does not guarantee termination if `Q`
4382
+ is not a multiple of `P`, so we first need to check subgroup
4383
+ membership. This is done as follows:
4384
+
4385
+ - Let `n` denote the order of `P`. First check that `nQ` equals
4386
+ the point at infinity (and hence the order of `Q` divides `n`).
4387
+
4388
+ - If the curve order `\#E` has been cached, check whether
4389
+ `\gcd(n^2, \#E) = n`. If this holds, the curve has cyclic
4390
+ `n`-torsion, hence all points whose order divides `n` must be
4391
+ multiples of `P` and we are done.
4392
+
4393
+ - Otherwise (if this test is inconclusive), check that the Weil
4394
+ pairing of `P` and `Q` is trivial.
4395
+
4396
+ For anomalous curves with `\#E = p`, the
4397
+ :meth:`padic_elliptic_logarithm` function is called.
4398
+
4399
+ For two-dimensional logarithms, we first compute the Weil pairings
4400
+ of `Q` with `P_1` and `P_2` and their logarithms relative to the
4401
+ pairing of `P_1` and `P_2`; this allows reading off `x` and `y`
4402
+ modulo the part of the order where `P_1` and `P_2` are independent.
4403
+ Modulo the remaining part of the order the logarithm ends up being
4404
+ effectively one-dimensional, so we can reduce the problem to the
4405
+ basic one-dimensional case and finally recombine the results.
4406
+
4407
+ INPUT:
4408
+
4409
+ - ``base`` -- another point or sequence of two points on the same
4410
+ curve as ``self``
4411
+
4412
+ OUTPUT:
4413
+
4414
+ (integer) -- The discrete logarithm of `Q` with respect to `P`,
4415
+ which is an integer `x` with `0\le x<\mathrm{ord}(P)` such that
4416
+ `xP=Q`, if one exists. In the case of two points `P_1,P_2`, two
4417
+ integers `x,y` with `0\le x<\mathrm{ord}(P_1)` and
4418
+ `0\le y<\mathrm{ord}(P_2)` such that `[x]P_1 + [y]P_2 = Q`.
4419
+
4420
+ AUTHORS:
4421
+
4422
+ - John Cremona. Adapted to use generic functions 2008-04-05.
4423
+ - Lorenz Panny (2022): switch to PARI.
4424
+ - Lorenz Panny (2024): the two-dimensional case.
4425
+
4426
+ EXAMPLES::
4427
+
4428
+ sage: # needs sage.rings.finite_rings
4429
+ sage: F = GF((3,6),'a')
4430
+ sage: a = F.gen()
4431
+ sage: E = EllipticCurve([0,1,1,a,a])
4432
+ sage: E.cardinality()
4433
+ 762
4434
+ sage: P = E.gens()[0]
4435
+ sage: Q = 400*P
4436
+ sage: Q.log(P)
4437
+ 400
4438
+
4439
+ ::
4440
+
4441
+ sage: # needs sage.rings.finite_rings
4442
+ sage: F = GF((5, 60), 'a')
4443
+ sage: E = EllipticCurve(F, [1, 1])
4444
+ sage: E.abelian_group()
4445
+ Additive abelian group isomorphic to Z/194301464603136995341424045476456938000 + Z/4464 embedded in Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in a of size 5^60
4446
+ sage: P, Q = E.gens() # cached generators from .abelian_group()
4447
+ sage: T = 1234567890987654321*P + 1337*Q
4448
+ sage: T.log([P, Q])
4449
+ (1234567890987654321, 1337)
4450
+
4451
+ TESTS:
4452
+
4453
+ Some random testing::
4454
+
4455
+ sage: # needs sage.rings.finite_rings
4456
+ sage: sz = randint(8,32)
4457
+ sage: e = randint(1,3)
4458
+ sage: p = random_prime(ceil(2**(sz/e)))
4459
+ sage: E = EllipticCurve(j=GF((p,e),'a').random_element())
4460
+ sage: P = E.random_point()
4461
+ sage: Q = randrange(2**999) * P
4462
+ sage: x = Q.log(P)
4463
+ sage: x*P == Q
4464
+ True
4465
+
4466
+ ::
4467
+
4468
+ sage: # needs sage.rings.finite_rings
4469
+ sage: sz = randint(16,24)
4470
+ sage: e = randint(1,6)
4471
+ sage: p = random_prime(ceil(2**(sz/e)))
4472
+ sage: E = EllipticCurve(j=GF((p,e),'a').random_element())
4473
+ sage: E = choice(E.twists())
4474
+ sage: P = E.random_point()
4475
+ sage: Q = E.random_point()
4476
+ sage: T = randrange(2^99) * P + randrange(2^99) * Q
4477
+ sage: x, y = T.log([P, Q])
4478
+ sage: 0 <= x < P.order()
4479
+ True
4480
+ sage: 0 <= y < Q.order()
4481
+ True
4482
+ sage: T == x*P + y*Q
4483
+ True
4484
+ """
4485
+ # handle the two-dimensional case first
4486
+ if isinstance(base, (list, tuple)):
4487
+ if not base:
4488
+ return self.log(self.curve().zero())
4489
+ elif len(base) == 1:
4490
+ return self.log(base[0])
4491
+ elif len(base) > 2:
4492
+ raise ValueError('sequence must have length <= 2')
4493
+
4494
+ P1, P2 = base
4495
+ if P1 not in self.parent() or P2 not in self.parent():
4496
+ raise ValueError('points do not lie on the same curve')
4497
+
4498
+ n1, n2 = P1.order(), P2.order()
4499
+ n = n1.lcm(n2)
4500
+ if not hasattr(self, '_order'):
4501
+ if n * self:
4502
+ raise ValueError('ECDLog problem has no solution (order does not divide order of base)')
4503
+ self.set_order(multiple=n, check=False)
4504
+ if not self.order().divides(n):
4505
+ raise ValueError('ECDLog problem has no solution (order does not divide order of base)')
4506
+
4507
+ # find the solution modulo the part where P1,P2 are independent
4508
+ z = P1.weil_pairing(P2, n)
4509
+ o = generic.order_from_multiple(z, n1.gcd(n2), operation='*')
4510
+ if o.is_one():
4511
+ # slight optimization, but also workaround for PARI bug #2562
4512
+ x0, y0 = ZZ.zero(), ZZ.zero()
4513
+ else:
4514
+ v = self.weil_pairing(P2, n)
4515
+ w = P1.weil_pairing(self, n)
4516
+ x0, y0 = v.log(z, o), w.log(z, o)
4517
+
4518
+ T = self - x0*P1 - y0*P2
4519
+ if not T:
4520
+ return x0, y0
4521
+
4522
+ T1 = n//n1 * T
4523
+ T2 = n//n2 * T
4524
+ T1.set_order(multiple=n1, check=False)
4525
+ T2.set_order(multiple=n2, check=False)
4526
+ x1 = T1.log(o*P1)
4527
+ y1 = T2.log(o*P2)
4528
+
4529
+ # assert n//n1 * self == (x1*o + n//n1*x0) * P1 + n//n1*y0 * P2
4530
+ # assert n//n2 * self == n//n2*x0 * P1 + (y1*o + n//n2*y0) * P2
4531
+
4532
+ _,u,v = (n//n1).xgcd(n//n2)
4533
+ assert _.is_one()
4534
+ x = (u * (x1*o + n//n1*x0) + v * (n//n2*x0)) % n1
4535
+ y = (u * (n//n1*y0) + v * (y1*o + n//n2*y0)) % n2
4536
+
4537
+ # assert x*P1 + y*P2 == self
4538
+ return x, y
4539
+
4540
+ if base not in self.parent():
4541
+ raise ValueError('not a point on the same curve')
4542
+ n = base.order()
4543
+ if (hasattr(self, '_order') and not self._order.divides(n)) or n*self:
4544
+ raise ValueError('ECDLog problem has no solution (order does not divide order of base)')
4545
+ E = self.curve()
4546
+ F = E.base_ring()
4547
+ p = F.cardinality()
4548
+
4549
+ if F.is_prime_field() and n == p:
4550
+ # Anomalous case
4551
+ return base.padic_elliptic_logarithm(self, p)
4552
+ elif hasattr(E, '_order') and E._order.gcd(n**2) == n:
4553
+ pass # cyclic rational n-torsion -> okay
4554
+ elif base.weil_pairing(self, n) != 1:
4555
+ raise ValueError('ECDLog problem has no solution (non-trivial Weil pairing)')
4556
+
4557
+ return ZZ(pari.elllog(self.curve(), self, base, n))
4558
+
4559
+ def discrete_log(self, Q):
4560
+ r"""
4561
+ Legacy version of :meth:`log` with its arguments swapped.
4562
+
4563
+ Note that this method uses the opposite argument ordering
4564
+ of all other logarithm methods in Sage; see :issue:`37150`.
4565
+
4566
+ EXAMPLES::
4567
+
4568
+ sage: E = EllipticCurve(j=GF(101)(5))
4569
+ sage: P, = E.gens()
4570
+ sage: (2*P).log(P)
4571
+ 2
4572
+ sage: (2*P).discrete_log(P)
4573
+ doctest:warning ...
4574
+ DeprecationWarning: The syntax P.discrete_log(Q) ... Please update your code. ...
4575
+ 45
4576
+ sage: P.discrete_log(2*P)
4577
+ 2
4578
+ """
4579
+ from sage.misc.superseded import deprecation
4580
+ deprecation(37150, 'The syntax P.discrete_log(Q) is being replaced by '
4581
+ 'Q.log(P) to make the argument ordering of logarithm'
4582
+ ' methods in Sage uniform. Please update your code.')
4583
+ return Q.log(self)
4584
+
4585
+ def padic_elliptic_logarithm(self, Q, p):
4586
+ r"""
4587
+ Return the discrete logarithm of `Q` to base `P` = ``self``,
4588
+ that is, an integer `x` such that `xP = Q` only for anomalous curves.
4589
+
4590
+ ALGORITHM:
4591
+
4592
+ Discrete logarithm computed as in [Sma1999]_ with a loop to avoid
4593
+ the canonical lift.
4594
+
4595
+ INPUT:
4596
+
4597
+ - ``Q`` -- point; another point on the same curve as ``self``
4598
+ - ``p`` -- integer; a prime equal to the order of the curve
4599
+
4600
+ OUTPUT:
4601
+
4602
+ (integer) -- The discrete logarithm of `Q` with respect to `P`,
4603
+ which is an integer `x` with `0\le x<\mathrm{ord}(P)` such that
4604
+ `xP=Q`.
4605
+
4606
+ AUTHORS:
4607
+
4608
+ - Sylvain Pelissier (2022) based on Samuel Neves code_.
4609
+
4610
+ .. _code: https://crypto.stackexchange.com/questions/70454/why-smarts-attack-doesnt-work-on-this-ecdlp/70508#70508
4611
+
4612
+ EXAMPLES::
4613
+
4614
+ sage: # needs sage.rings.finite_rings
4615
+ sage: p = 235322474717419
4616
+ sage: b = 8856682
4617
+ sage: E = EllipticCurve(GF(p), [0, b])
4618
+ sage: P = E(200673830421813, 57025307876612)
4619
+ sage: Q = E(40345734829479, 211738132651297)
4620
+ sage: x = P.padic_elliptic_logarithm(Q, p) # needs sage.rings.padics
4621
+ sage: x * P == Q # needs sage.rings.padics
4622
+ True
4623
+
4624
+ TESTS:
4625
+
4626
+ Some testing::
4627
+
4628
+ sage: # needs sage.rings.finite_rings
4629
+ sage: a = 49850651047495986645822557378918223
4630
+ sage: b = 21049438014429831351540675253466229
4631
+ sage: p = 54283205379427155782089046839411711
4632
+ sage: E = EllipticCurve(GF(p), [a, b])
4633
+ sage: P = E.random_point()
4634
+ sage: Q = randrange(0, p-1) * P
4635
+ sage: x = P.padic_elliptic_logarithm(Q, p) # needs sage.rings.padics
4636
+ sage: x*P == Q # needs sage.rings.padics
4637
+ True
4638
+ """
4639
+ E = self.curve()
4640
+ F = E.base()
4641
+
4642
+ if Q.is_zero():
4643
+ k = 0
4644
+ else:
4645
+ for k in range(p):
4646
+ Eqp = EllipticCurve(Qp(p, 2), [ZZ(t) + k * p for t in E.a_invariants()])
4647
+
4648
+ P_Qps = Eqp.lift_x(ZZ(self.x()), all=True)
4649
+ for P_Qp in P_Qps:
4650
+ if F(P_Qp.y()) == self.y():
4651
+ break
4652
+
4653
+ Q_Qps = Eqp.lift_x(ZZ(Q.x()), all=True)
4654
+ for Q_Qp in Q_Qps:
4655
+ if F(Q_Qp.y()) == Q.y():
4656
+ break
4657
+
4658
+ pP = p * P_Qp
4659
+ pQ = p * Q_Qp
4660
+ if (pP.is_zero() or pQ.is_zero()):
4661
+ # Should happen with probability 1/p
4662
+ continue
4663
+ else:
4664
+ break
4665
+
4666
+ x_P,y_P = pP.xy()
4667
+ x_Q,y_Q = pQ.xy()
4668
+
4669
+ phi_P = -(x_P / y_P)
4670
+ phi_Q = -(x_Q / y_Q)
4671
+ k = phi_Q / phi_P
4672
+
4673
+ return ZZ(k % p)
4674
+
4675
+ def has_finite_order(self) -> bool:
4676
+ r"""
4677
+ Return ``True`` if this point has finite additive order as an element
4678
+ of the group of points on this curve.
4679
+
4680
+ Since the base field is finite, the answer will always be ``True``.
4681
+
4682
+ EXAMPLES::
4683
+
4684
+ sage: E = EllipticCurve(GF(7), [1,3])
4685
+ sage: P = E.points()[3]
4686
+ sage: P.has_finite_order()
4687
+ True
4688
+ """
4689
+ return True
4690
+
4691
+ def order(self):
4692
+ r"""
4693
+ Return the order of this point on the elliptic curve.
4694
+
4695
+ ALGORITHM: Use PARI function :pari:`ellorder`.
4696
+
4697
+ .. NOTE::
4698
+
4699
+ :meth:`additive_order` is a synonym for :meth:`order`
4700
+
4701
+ EXAMPLES::
4702
+
4703
+ sage: # needs sage.rings.finite_rings
4704
+ sage: k.<a> = GF((5,5))
4705
+ sage: E = EllipticCurve(k,[2,4]); E
4706
+ Elliptic Curve defined by y^2 = x^3 + 2*x + 4 over Finite Field in a of size 5^5
4707
+ sage: P = E(3*a^4 + 3*a, 2*a + 1)
4708
+ sage: P.order()
4709
+ 3227
4710
+ sage: Q = E(0,2)
4711
+ sage: Q.order()
4712
+ 7
4713
+ sage: Q.additive_order()
4714
+ 7
4715
+
4716
+ ::
4717
+
4718
+ sage: # needs sage.rings.finite_rings
4719
+ sage: p = next_prime(2^150)
4720
+ sage: E = EllipticCurve(GF(p), [1,1])
4721
+ sage: P = E(831623307675610677632782670796608848711856078,
4722
+ ....: 42295786042873366706573292533588638217232964)
4723
+ sage: P.order()
4724
+ 1427247692705959881058262545272474300628281448
4725
+ sage: P.order() == E.cardinality()
4726
+ True
4727
+
4728
+ The next example has `j(E)=0`::
4729
+
4730
+ sage: # needs sage.rings.finite_rings
4731
+ sage: p = 33554501
4732
+ sage: F.<u> = GF((p,2))
4733
+ sage: E = EllipticCurve(F, [0,1])
4734
+ sage: E.j_invariant()
4735
+ 0
4736
+ sage: P = E.random_point()
4737
+ sage: P.order() # random
4738
+ 16777251
4739
+
4740
+ Similarly when `j(E)=1728`::
4741
+
4742
+ sage: # needs sage.rings.finite_rings
4743
+ sage: p = 33554473
4744
+ sage: F.<u> = GF((p,2))
4745
+ sage: E = EllipticCurve(F, [1,0])
4746
+ sage: E.j_invariant()
4747
+ 1728
4748
+ sage: P = E.random_point()
4749
+ sage: P.order() # random
4750
+ 46912611635760
4751
+
4752
+ TESTS:
4753
+
4754
+ Check that the order actually gets cached (:issue:`32786`)::
4755
+
4756
+ sage: # needs sage.rings.finite_rings
4757
+ sage: E = EllipticCurve(GF(31337), [42,1])
4758
+ sage: P = E.lift_x(1)
4759
+ sage: hasattr(P, '_order')
4760
+ False
4761
+ sage: P.order()
4762
+ 15649
4763
+ sage: P._order
4764
+ 15649
4765
+
4766
+ The curve order should also get cached as a side effect
4767
+ of computing a point order::
4768
+
4769
+ sage: E._order # needs sage.rings.finite_rings
4770
+ 31298
4771
+ """
4772
+ try:
4773
+ return self._order
4774
+ except AttributeError:
4775
+ pass
4776
+
4777
+ E = self.curve()
4778
+
4779
+ if getattr(E, '_order', None) is None:
4780
+ # The curve order will be computed and cached by PARI during
4781
+ # ellorder() anyway. We might as well cache it here too.
4782
+ E._order = Integer(E.pari_curve().ellcard())
4783
+
4784
+ self._order = Integer(E.pari_curve().ellorder(self, E._order))
4785
+ return self._order
4786
+
4787
+ additive_order = order