passagemath-schemes 10.6.47__cp312-cp312-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.6.47.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
  9. passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.47.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-312-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-312-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +720 -0
  40. sage/modular/abvar/homspace.py +998 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-312-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-312-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-312-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-312-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2017 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1071 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +815 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-312-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-312-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list_nf.py +1241 -0
  154. sage/modular/modsym/relation_matrix.py +591 -0
  155. sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
  156. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  157. sage/modular/modsym/space.py +2468 -0
  158. sage/modular/modsym/subspace.py +455 -0
  159. sage/modular/modsym/tests.py +375 -0
  160. sage/modular/multiple_zeta.py +2632 -0
  161. sage/modular/multiple_zeta_F_algebra.py +786 -0
  162. sage/modular/overconvergent/all.py +6 -0
  163. sage/modular/overconvergent/genus0.py +1878 -0
  164. sage/modular/overconvergent/hecke_series.py +1187 -0
  165. sage/modular/overconvergent/weightspace.py +778 -0
  166. sage/modular/pollack_stevens/all.py +4 -0
  167. sage/modular/pollack_stevens/distributions.py +874 -0
  168. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  169. sage/modular/pollack_stevens/manin_map.py +859 -0
  170. sage/modular/pollack_stevens/modsym.py +1593 -0
  171. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  172. sage/modular/pollack_stevens/sigma0.py +534 -0
  173. sage/modular/pollack_stevens/space.py +1076 -0
  174. sage/modular/quasimodform/all.py +3 -0
  175. sage/modular/quasimodform/element.py +845 -0
  176. sage/modular/quasimodform/ring.py +828 -0
  177. sage/modular/quatalg/all.py +3 -0
  178. sage/modular/quatalg/brandt.py +1642 -0
  179. sage/modular/ssmod/all.py +8 -0
  180. sage/modular/ssmod/ssmod.py +827 -0
  181. sage/rings/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  183. sage/rings/polynomial/binary_form_reduce.py +585 -0
  184. sage/schemes/all.py +41 -0
  185. sage/schemes/berkovich/all.py +6 -0
  186. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  187. sage/schemes/berkovich/berkovich_space.py +748 -0
  188. sage/schemes/curves/affine_curve.py +2928 -0
  189. sage/schemes/curves/all.py +33 -0
  190. sage/schemes/curves/closed_point.py +434 -0
  191. sage/schemes/curves/constructor.py +381 -0
  192. sage/schemes/curves/curve.py +542 -0
  193. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  194. sage/schemes/curves/point.py +463 -0
  195. sage/schemes/curves/projective_curve.py +3026 -0
  196. sage/schemes/curves/zariski_vankampen.py +1932 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +1036 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1102 -0
  208. sage/schemes/elliptic_curves/constructor.py +1552 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7335 -0
  229. sage/schemes/elliptic_curves/height.py +2109 -0
  230. sage/schemes/elliptic_curves/hom.py +1406 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  232. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  233. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  234. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  235. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  236. sage/schemes/elliptic_curves/homset.py +271 -0
  237. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  238. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  239. sage/schemes/elliptic_curves/jacobian.py +237 -0
  240. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  241. sage/schemes/elliptic_curves/kraus.py +1014 -0
  242. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  243. sage/schemes/elliptic_curves/mod5family.py +105 -0
  244. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  245. sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  247. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  248. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  249. sage/schemes/elliptic_curves/padics.py +1816 -0
  250. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  251. sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  253. sage/schemes/elliptic_curves/saturation.py +715 -0
  254. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  255. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  256. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  257. sage/schemes/hyperelliptic_curves/all.py +6 -0
  258. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  259. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  264. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  265. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  270. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  271. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  272. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  273. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  274. sage/schemes/jacobians/all.py +2 -0
  275. sage/schemes/overview.py +161 -0
  276. sage/schemes/plane_conics/all.py +22 -0
  277. sage/schemes/plane_conics/con_field.py +1296 -0
  278. sage/schemes/plane_conics/con_finite_field.py +158 -0
  279. sage/schemes/plane_conics/con_number_field.py +456 -0
  280. sage/schemes/plane_conics/con_rational_field.py +406 -0
  281. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  282. sage/schemes/plane_conics/constructor.py +249 -0
  283. sage/schemes/plane_quartics/all.py +2 -0
  284. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  285. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  286. sage/schemes/riemann_surfaces/all.py +1 -0
  287. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  288. sage_wheels/share/cremona/cremona_mini.db +0 -0
  289. sage_wheels/share/ellcurves/rank0 +30427 -0
  290. sage_wheels/share/ellcurves/rank1 +31871 -0
  291. sage_wheels/share/ellcurves/rank10 +6 -0
  292. sage_wheels/share/ellcurves/rank11 +6 -0
  293. sage_wheels/share/ellcurves/rank12 +1 -0
  294. sage_wheels/share/ellcurves/rank14 +1 -0
  295. sage_wheels/share/ellcurves/rank15 +1 -0
  296. sage_wheels/share/ellcurves/rank17 +1 -0
  297. sage_wheels/share/ellcurves/rank19 +1 -0
  298. sage_wheels/share/ellcurves/rank2 +2388 -0
  299. sage_wheels/share/ellcurves/rank20 +1 -0
  300. sage_wheels/share/ellcurves/rank21 +1 -0
  301. sage_wheels/share/ellcurves/rank22 +1 -0
  302. sage_wheels/share/ellcurves/rank23 +1 -0
  303. sage_wheels/share/ellcurves/rank24 +1 -0
  304. sage_wheels/share/ellcurves/rank28 +1 -0
  305. sage_wheels/share/ellcurves/rank3 +836 -0
  306. sage_wheels/share/ellcurves/rank4 +10 -0
  307. sage_wheels/share/ellcurves/rank5 +5 -0
  308. sage_wheels/share/ellcurves/rank6 +5 -0
  309. sage_wheels/share/ellcurves/rank7 +5 -0
  310. sage_wheels/share/ellcurves/rank8 +6 -0
  311. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1117 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Isomorphisms between Weierstrass models of elliptic curves
4
+
5
+ AUTHORS:
6
+
7
+ - Robert Bradshaw (2007): initial version
8
+ - John Cremona (Jan 2008): isomorphisms, automorphisms and twists
9
+ in all characteristics
10
+ - Lorenz Panny (2021): :class:`EllipticCurveHom` interface
11
+ """
12
+ # ****************************************************************************
13
+ # Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
14
+ #
15
+ # Distributed under the terms of the GNU General Public License (GPL)
16
+ #
17
+ # This code is distributed in the hope that it will be useful,
18
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
+ # General Public License for more details.
21
+ #
22
+ # The full text of the GPL is available at:
23
+ #
24
+ # https://www.gnu.org/licenses/
25
+ # ****************************************************************************
26
+
27
+ from sage.structure.element import get_coercion_model
28
+
29
+ from .constructor import EllipticCurve
30
+ from sage.schemes.elliptic_curves.hom import EllipticCurveHom
31
+ from sage.structure.richcmp import (richcmp, richcmp_not_equal, op_EQ, op_NE)
32
+ from sage.structure.sequence import Sequence
33
+ from sage.rings.integer import Integer
34
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
35
+
36
+
37
+ class baseWI:
38
+ r"""
39
+ This class implements the basic arithmetic of isomorphisms between
40
+ Weierstrass models of elliptic curves.
41
+
42
+ These are specified by lists of the form `[u,r,s,t]` (with `u \neq 0`)
43
+ which specifies a transformation `(x,y) \mapsto (x',y')` where
44
+
45
+ `(x,y) = (u^2x'+r , u^3y' + su^2x' + t).`
46
+
47
+ INPUT:
48
+
49
+ - ``u``, ``r``, ``s``, ``t`` -- (default: `1`, `0`, `0`, `0`); standard
50
+ parameters of an isomorphism between Weierstrass models
51
+
52
+ EXAMPLES::
53
+
54
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
55
+ sage: baseWI()
56
+ (1, 0, 0, 0)
57
+ sage: baseWI(2,3,4,5)
58
+ (2, 3, 4, 5)
59
+ sage: R.<u,r,s,t> = QQ[]
60
+ sage: baseWI(u,r,s,t)
61
+ (u, r, s, t)
62
+ """
63
+ def __init__(self, u=1, r=0, s=0, t=0):
64
+ r"""
65
+ Constructor: check for valid parameters (defaults to identity).
66
+
67
+ INPUT:
68
+
69
+ - ``u``, ``r``, ``s``, ``t`` -- (default: `1`, `0`, `0`, `0`); standard
70
+ parameters of an isomorphism between Weierstrass models
71
+
72
+ EXAMPLES::
73
+
74
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
75
+ sage: baseWI()
76
+ (1, 0, 0, 0)
77
+ sage: baseWI(2,3,4,5)
78
+ (2, 3, 4, 5)
79
+ sage: R.<u,r,s,t> = QQ[]
80
+ sage: baseWI(u,r,s,t)
81
+ (u, r, s, t)
82
+ """
83
+ if not u:
84
+ raise ValueError("u!=0 required for baseWI")
85
+ self.u = u
86
+ self.r = r
87
+ self.s = s
88
+ self.t = t
89
+
90
+ def tuple(self):
91
+ r"""
92
+ Return the parameters `u,r,s,t` as a tuple.
93
+
94
+ EXAMPLES::
95
+
96
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
97
+ sage: w = baseWI(2,3,4,5)
98
+ sage: w.tuple()
99
+ (2, 3, 4, 5)
100
+ """
101
+ return (self.u, self.r, self.s, self.t)
102
+
103
+ def __mul__(self, other):
104
+ r"""
105
+ Return the composition of this isomorphism and another.
106
+
107
+ EXAMPLES::
108
+
109
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
110
+ sage: baseWI(1,2,3,4)*baseWI(5,6,7,8)
111
+ (5, 56, 22, 858)
112
+ sage: baseWI()*baseWI(1,2,3,4)*baseWI()
113
+ (1, 2, 3, 4)
114
+ """
115
+ u1, r1, s1, t1 = other.tuple()
116
+ u2, r2, s2, t2 = self.tuple()
117
+ return baseWI(u1 * u2,
118
+ (u1**2) * r2 + r1,
119
+ u1 * s2 + s1,
120
+ (u1**3) * t2 + s1 * (u1**2) * r2 + t1)
121
+
122
+ def __invert__(self):
123
+ r"""
124
+ Return the inverse of this isomorphism.
125
+
126
+ EXAMPLES::
127
+
128
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
129
+ sage: w = baseWI(2,3,4,5)
130
+ sage: ~w
131
+ (1/2, -3/4, -2, 7/8)
132
+ sage: w*~w
133
+ (1, 0, 0, 0)
134
+ sage: ~w*w
135
+ (1, 0, 0, 0)
136
+ sage: R.<u,r,s,t> = QQ[]
137
+ sage: w = baseWI(u,r,s,t)
138
+ sage: ~w
139
+ (1/u, (-r)/u^2, (-s)/u, (r*s - t)/u^3)
140
+ sage: ~w*w
141
+ (1, 0, 0, 0)
142
+ """
143
+ u, r, s, t = self.tuple()
144
+ return baseWI(1/u, -r/u**2, -s/u, (r*s-t)/u**3)
145
+
146
+ def __repr__(self):
147
+ r"""
148
+ Return the string representation of this isomorphism.
149
+
150
+ EXAMPLES::
151
+
152
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
153
+ sage: baseWI(2,3,4,5)
154
+ (2, 3, 4, 5)
155
+ """
156
+ return repr(self.tuple())
157
+
158
+ def is_identity(self):
159
+ r"""
160
+ Return ``True`` if this is the identity isomorphism.
161
+
162
+ EXAMPLES::
163
+
164
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
165
+ sage: w = baseWI(); w.is_identity()
166
+ True
167
+ sage: w = baseWI(2,3,4,5); w.is_identity()
168
+ False
169
+ """
170
+ return self.tuple() == (1, 0, 0, 0)
171
+
172
+ def __call__(self, EorP):
173
+ r"""
174
+ Base application of isomorphisms to curves and points.
175
+
176
+ A baseWI `w` may be applied to a list `[a1,a2,a3,a4,a6]`
177
+ representing the `a`-invariants of an elliptic curve `E`,
178
+ returning the `a`-invariants of `w(E)`; or to `P=[x,y]` or
179
+ `P=[x,y,z]` representing a point in `\mathbb{A}^2` or
180
+ `\mathbb{P}^2`, returning the transformed point.
181
+
182
+ INPUT:
183
+
184
+ - ``EorP`` -- either an elliptic curve, or a point on an elliptic curve
185
+
186
+ OUTPUT: the transformed curve or point
187
+
188
+ EXAMPLES::
189
+
190
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
191
+ sage: E = EllipticCurve([0,0,1,-7,6])
192
+ sage: w = baseWI(2,3,4,5)
193
+ sage: w(E.ainvs())
194
+ [4, -7/4, 11/8, -3/2, -9/32]
195
+ sage: P = E(-2,3)
196
+ sage: w(P.xy())
197
+ [-5/4, 9/4]
198
+ sage: EllipticCurve(w(E.ainvs()))(w(P.xy()))
199
+ (-5/4 : 9/4 : 1)
200
+ """
201
+ u, r, s, t = self.tuple()
202
+ if len(EorP) == 5:
203
+ a1, a2, a3, a4, a6 = EorP
204
+ a6 += r*(a4 + r*(a2 + r)) - t*(a3 + r*a1 + t)
205
+ a4 += -s*a3 + 2*r*a2 - (t + r*s)*a1 + 3*r*r - 2*s*t
206
+ a3 += r*a1 + t + t
207
+ a2 += -s*a1 + 3*r - s*s
208
+ a1 += 2*s
209
+ return [a1/u, a2/u**2, a3/u**3, a4/u**4, a6/u**6]
210
+ if len(EorP) == 2:
211
+ x, y = EorP
212
+ x -= r
213
+ y -= (s*x+t)
214
+ return [x/u**2, y/u**3]
215
+ if len(EorP) == 3:
216
+ x, y, z = EorP
217
+ x -= r*z
218
+ y -= (s*x+t*z)
219
+ return [x/u**2, y/u**3, z]
220
+ raise ValueError("baseWI(a) only for a=(x,y), (x:y:z) or (a1,a2,a3,a4,a6)")
221
+
222
+
223
+ def _isomorphisms(E, F):
224
+ r"""
225
+ Enumerate all isomorphisms between two elliptic curves,
226
+ as a generator object.
227
+
228
+ INPUT:
229
+
230
+ - ``E``, ``F`` -- two elliptic curves
231
+
232
+ OUTPUT:
233
+
234
+ A generator object producing 4-tuples `(u,r,s,t)` representing an isomorphism.
235
+
236
+ EXAMPLES::
237
+
238
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import _isomorphisms
239
+ sage: list(_isomorphisms(EllipticCurve_from_j(0), EllipticCurve('27a3'))) # needs database_cremona_mini_ellcurve
240
+ [(1, 0, 0, 0), (-1, 0, 0, -1)]
241
+ sage: list(_isomorphisms(EllipticCurve_from_j(0), EllipticCurve('27a1'))) # needs database_cremona_mini_ellcurve
242
+ []
243
+
244
+ TESTS:
245
+
246
+ Check that :issue:`32632` is fixed::
247
+
248
+ sage: z8 = GF(2^8).gen()
249
+ sage: E1 = EllipticCurve([z8, z8, z8, z8, z8])
250
+ sage: list(_isomorphisms(E1, E1))
251
+ [(1, 0, 0, 0), (1, 0, z8, z8)]
252
+ sage: E2 = EllipticCurve([z8^2, 0, 0, 0, z8^7 + z8^4])
253
+ sage: list(_isomorphisms(E1, E2))
254
+ [(z8^7 + z8^3 + z8^2 + z8, 1, 1, z8^7 + z8^3 + z8^2 + z8 + 1),
255
+ (z8^7 + z8^3 + z8^2 + z8, 1, z8 + 1, z8^7 + z8^3 + z8^2 + z8 + 1)]
256
+
257
+ Random testing::
258
+
259
+ sage: p = random_prime(100)
260
+ sage: F = GF(p).algebraic_closure()
261
+ sage: j = F.random_element()
262
+ sage: while j in (0, 1728): # skip the hard case
263
+ ....: j = F.random_element()
264
+ sage: j = F(choice((0, 1728))) # long time -- do the hard case
265
+ sage: E = EllipticCurve_from_j(j)
266
+ sage: u,r,s,t = (F^4).random_element()
267
+ sage: u = u or 1
268
+ sage: E = E.change_weierstrass_model(u,r,s,t)
269
+ sage: Aut = E.automorphisms()
270
+ sage: len(set(Aut)) == len(Aut)
271
+ True
272
+ sage: all(-a in Aut for a in Aut)
273
+ True
274
+ sage: len(Aut) in (2, 4, 6, 12, 24)
275
+ True
276
+ sage: j = E.j_invariant()
277
+ sage: {
278
+ ....: 2: j not in (0, 1728),
279
+ ....: 4: p >= 5 and j == 1728,
280
+ ....: 6: p >= 5 and j == 0,
281
+ ....: 12: p == 3 and j == 0, # note 1728 == 0
282
+ ....: 24: p == 2 and j == 0, # note 1728 == 0
283
+ ....: }[len(Aut)]
284
+ True
285
+ sage: u,r,s,t = (F^4).random_element()
286
+ sage: u = u or 1
287
+ sage: F = E.change_weierstrass_model(u,r,s,t)
288
+ sage: Iso = E.isomorphisms(F)
289
+ sage: len(set(Iso)) == len(Iso)
290
+ True
291
+ sage: all(-f in Iso for f in Iso)
292
+ True
293
+ sage: len(Iso) == len(Aut)
294
+ True
295
+ sage: all({iso2*iso1 for iso1 in Iso} == set(Aut) for iso2 in F.isomorphisms(E))
296
+ True
297
+ """
298
+ from .ell_generic import EllipticCurve_generic
299
+ if not isinstance(E, EllipticCurve_generic) or not isinstance(F, EllipticCurve_generic):
300
+ raise ValueError("arguments are not elliptic curves")
301
+
302
+ j = E.j_invariant()
303
+ if j != F.j_invariant():
304
+ return
305
+
306
+ K = E.base_ring()
307
+
308
+ from sage.rings.polynomial.polynomial_ring import polygen
309
+ x = polygen(K, 'x')
310
+
311
+ a1E, a2E, a3E, a4E, a6E = E.ainvs()
312
+ a1F, a2F, a3F, a4F, a6F = F.ainvs()
313
+
314
+ char = K.characteristic()
315
+
316
+ if char == 2:
317
+ if j == 0:
318
+ ulist = (x**3 - a3E/a3F).roots(multiplicities=False)
319
+ for u in ulist:
320
+ slist = (x**4 + a3E*x + (a2F**2 + a4F)*u**4 + a2E**2 + a4E).roots(multiplicities=False)
321
+ for s in slist:
322
+ r = s**2 + a2E + a2F*u**2
323
+ tlist = (x**2 + a3E*x + r**3 + a2E*r**2 + a4E*r + a6E + a6F*u**6).roots(multiplicities=False)
324
+ for t in tlist:
325
+ yield (u, r, s, t)
326
+ else:
327
+ u = a1E/a1F
328
+ r = (a3E + a3F*u**3)/a1E
329
+ slist = (x**2 + a1E*x + r + a2E + a2F*u**2).roots(multiplicities=False)
330
+ for s in slist:
331
+ t = (a4E + a4F*u**4 + s*a3E + r*s*a1E + r**2) / a1E
332
+ yield (u, r, s, t)
333
+ return
334
+
335
+ b2E, b4E, b6E, b8E = E.b_invariants()
336
+ b2F, b4F, b6F, b8F = F.b_invariants()
337
+
338
+ if char == 3:
339
+ if j == 0:
340
+ ulist = (x**4 - b4E/b4F).roots(multiplicities=False)
341
+ for u in ulist:
342
+ s = a1E - a1F*u
343
+ t = a3E - a3F*u**3
344
+ rlist = (x**3 - b4E*x + b6E - b6F*u**6).roots(multiplicities=False)
345
+ for r in rlist:
346
+ yield (u, r, s, t + r*a1E)
347
+ else:
348
+ ulist = (x**2 - b2E/b2F).roots(multiplicities=False)
349
+ for u in ulist:
350
+ r = (b4F * u**4 - b4E) / b2E
351
+ s = a1E - a1F * u
352
+ t = a3E - a3F * u**3 + a1E * r
353
+ yield (u, r, s, t)
354
+ return
355
+
356
+ # now char != 2,3:
357
+
358
+ c4E, c6E = E.c_invariants()
359
+ c4F, c6F = F.c_invariants()
360
+
361
+ if j == 0:
362
+ m, um = 6, c6E/c6F
363
+ elif j == 1728:
364
+ m, um = 4, c4E/c4F
365
+ else:
366
+ m, um = 2, (c6E*c4F)/(c6F*c4E)
367
+ ulist = (x**m - um).roots(multiplicities=False)
368
+ for u in ulist:
369
+ s = (a1F*u - a1E)/2
370
+ r = (a2F*u**2 + a1E*s + s**2 - a2E)/3
371
+ t = (a3F*u**3 - a1E*r - a3E)/2
372
+ yield (u, r, s, t)
373
+
374
+
375
+ class WeierstrassIsomorphism(EllipticCurveHom, baseWI):
376
+ r"""
377
+ Class representing a Weierstrass isomorphism between two elliptic curves.
378
+
379
+ INPUT:
380
+
381
+ - ``E`` -- an ``EllipticCurve``, or ``None`` (see below)
382
+
383
+ - ``urst`` -- a 4-tuple `(u,r,s,t)`, a :class:`baseWI` object,
384
+ or ``None`` (see below)
385
+
386
+ - ``F`` -- an ``EllipticCurve``, or ``None`` (see below)
387
+
388
+ Given two Elliptic Curves ``E`` and ``F`` (represented by Weierstrass
389
+ models as usual), and a transformation ``urst`` from ``E`` to ``F``,
390
+ construct an isomorphism from ``E`` to ``F``.
391
+ An exception is raised if ``urst(E) != F``. At most one of ``E``,
392
+ ``F``, ``urst`` can be ``None``. In this case, the missing input is
393
+ constructed from the others in such a way that ``urst(E) == F`` holds,
394
+ and an exception is raised if this is impossible (typically because
395
+ ``E`` and ``F`` are not isomorphic).
396
+
397
+ Users will not usually need to use this class directly, but instead use
398
+ methods such as
399
+ :meth:`~sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic.isomorphism_to`
400
+ or
401
+ :meth:`~sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic.isomorphisms`.
402
+
403
+ Explicitly, the isomorphism defined by `(u,r,s,t)` maps a point `(x,y)`
404
+ to the point
405
+
406
+ .. MATH::
407
+
408
+ ((x-r) / u^2, \; (y - s(x-r) - t) / u^3) .
409
+
410
+ If the domain `E` has Weierstrass coefficients `[a_1,a_2,a_3,a_4,a_6]`,
411
+ the codomain `F` is given by
412
+
413
+ .. MATH::
414
+
415
+ a_1' &= (a_1 + 2s) / u \\
416
+ a_2' &= (a_2 - a_1s + 3r - s^2) / u^2 \\
417
+ a_3' &= (a_3 + a_1r + 2t) / u^3 \\
418
+ a_4' &= (a_4 + 2a_2r - a_1(rs+t) - a_3s + 3r^2 - 2st) / u^4 \\
419
+ a_6' &= (a_6 - a_1rt + a_2r^2 - a_3t + a_4r + r^3 - t^2) / u^6 .
420
+
421
+ EXAMPLES::
422
+
423
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
424
+ sage: WeierstrassIsomorphism(EllipticCurve([0,1,2,3,4]), (-1,2,3,4))
425
+ Elliptic-curve morphism:
426
+ From: Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field
427
+ To: Elliptic Curve defined by y^2 - 6*x*y - 10*y = x^3 - 2*x^2 - 11*x - 2 over Rational Field
428
+ Via: (u,r,s,t) = (-1, 2, 3, 4)
429
+
430
+ sage: # needs database_cremona_mini_ellcurve
431
+ sage: E = EllipticCurve([0,1,2,3,4])
432
+ sage: F = EllipticCurve(E.cremona_label())
433
+ sage: WeierstrassIsomorphism(E, None, F)
434
+ Elliptic-curve morphism:
435
+ From: Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field
436
+ To: Elliptic Curve defined by y^2 = x^3 + x^2 + 3*x + 5 over Rational Field
437
+ Via: (u,r,s,t) = (1, 0, 0, -1)
438
+ sage: w = WeierstrassIsomorphism(None, (1,0,0,-1), F)
439
+ sage: w._domain == E
440
+ True
441
+ """
442
+ def __init__(self, E=None, urst=None, F=None):
443
+ r"""
444
+ Constructor for the ``WeierstrassIsomorphism`` class.
445
+
446
+ TESTS:
447
+
448
+ Check for :issue:`33215`::
449
+
450
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
451
+ sage: E = EllipticCurve(GF(71^2), [5,5]) # needs sage.rings.finite_rings
452
+ sage: iso = WeierstrassIsomorphism(E, (1,2,3,4)) # needs sage.rings.finite_rings
453
+ sage: ~iso # indirect doctest # needs sage.rings.finite_rings
454
+ Elliptic-curve morphism:
455
+ From: Elliptic Curve defined by y^2 + 6*x*y + 8*y = x^3 + 68*x^2 + 64*x + 7 over Finite Field in z2 of size 71^2
456
+ To: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field in z2 of size 71^2
457
+ Via: (u,r,s,t) = (1, 69, 68, 2)
458
+
459
+ Test for :issue:`33312`::
460
+
461
+ sage: type(iso.degree()) # needs sage.rings.finite_rings
462
+ <class 'sage.rings.integer.Integer'>
463
+ """
464
+ from .ell_generic import EllipticCurve_generic
465
+
466
+ if E is not None:
467
+ if not isinstance(E, EllipticCurve_generic):
468
+ raise ValueError("first argument must be an elliptic curve or None")
469
+ if F is not None:
470
+ if not isinstance(F, EllipticCurve_generic):
471
+ raise ValueError("third argument must be an elliptic curve or None")
472
+ if urst is not None:
473
+ if len(urst) != 4:
474
+ raise ValueError("second argument must be [u,r,s,t] or None")
475
+ if len([par for par in [E, urst, F] if par is not None]) < 2:
476
+ raise ValueError("at most 1 argument can be None")
477
+
478
+ inps = []
479
+ if E is not None:
480
+ inps.append(E.base_ring())
481
+ if F is not None:
482
+ inps.append(F.base_ring())
483
+ if urst is not None:
484
+ inps += list(urst)
485
+ base_ring = get_coercion_model().common_parent(*inps)
486
+
487
+ if urst is not None:
488
+ urst = Sequence(urst, base_ring)
489
+
490
+ if F is None: # easy case
491
+ baseWI.__init__(self, *urst)
492
+ F = EllipticCurve(baseWI.__call__(self, list(E.a_invariants())))
493
+
494
+ elif E is None: # easy case in reverse
495
+ baseWI.__init__(self, *urst)
496
+ inv_urst = baseWI.__invert__(self)
497
+ E = EllipticCurve(baseWI.__call__(inv_urst, list(F.a_invariants())))
498
+
499
+ elif urst is None: # try to construct the morphism
500
+ try:
501
+ urst = next(_isomorphisms(E, F))
502
+ except StopIteration:
503
+ raise ValueError("elliptic curves not isomorphic")
504
+ baseWI.__init__(self, *urst)
505
+
506
+ else: # none of the parameters is None:
507
+ baseWI.__init__(self, *urst)
508
+ if F != EllipticCurve(baseWI.__call__(self, list(E.a_invariants()))):
509
+ raise ValueError("second argument is not an isomorphism from first argument to third argument")
510
+
511
+ self._mpoly_ring = PolynomialRing(base_ring, ['x','y'])
512
+ self._poly_ring = PolynomialRing(base_ring, ['x'])
513
+ self._xyfield = self._mpoly_ring.fraction_field()
514
+ self._xfield = self._poly_ring.fraction_field()
515
+
516
+ self._domain = E
517
+ self._codomain = F
518
+ self._degree = Integer(1)
519
+ EllipticCurveHom.__init__(self, self._domain, self._codomain)
520
+
521
+ @staticmethod
522
+ def _comparison_impl(left, right, op):
523
+ r"""
524
+ Compare an isomorphism to another elliptic-curve morphism.
525
+
526
+ Called by :meth:`EllipticCurveHom._richcmp_`.
527
+
528
+ EXAMPLES::
529
+
530
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
531
+
532
+ sage: # needs database_cremona_mini_ellcurve
533
+ sage: E = EllipticCurve('389a1')
534
+ sage: F = E.change_weierstrass_model(1,2,3,4)
535
+ sage: w1 = E.isomorphism_to(F)
536
+ sage: w1 == w1
537
+ True
538
+ sage: w2 = F.automorphisms()[1] * w1
539
+ sage: w1 == w2
540
+ False
541
+
542
+ sage: E = EllipticCurve_from_j(GF(7)(0))
543
+ sage: F = E.change_weierstrass_model(2,3,4,5)
544
+ sage: a = E.isomorphisms(F)
545
+ sage: b = [w*a[0] for w in F.automorphisms()]
546
+ sage: b.sort()
547
+ sage: a == b
548
+ True
549
+ sage: c = [a[0]*w for w in E.automorphisms()]
550
+ sage: c.sort()
551
+ sage: a == c
552
+ True
553
+ """
554
+ if not isinstance(left, WeierstrassIsomorphism) or not isinstance(right, WeierstrassIsomorphism):
555
+ return NotImplemented
556
+
557
+ lx = left._domain
558
+ rx = right._domain
559
+ if lx != rx:
560
+ return richcmp_not_equal(lx, rx, op)
561
+
562
+ lx = left._codomain
563
+ rx = right._codomain
564
+ if lx != rx:
565
+ return richcmp_not_equal(lx, rx, op)
566
+
567
+ if op in (op_EQ, op_NE):
568
+ return richcmp(left.tuple(), right.tuple(), op)
569
+
570
+ # This makes sure that the identity and negation morphisms
571
+ # come first in a sorted list of WeierstrassIsomorphisms.
572
+ # More generally, we're making sure that a morphism and its
573
+ # negative appear next to each other, and that those pairs
574
+ # of isomorphisms satisfying u=+-1 come first.
575
+ def _sorting_key(iso):
576
+ v, w = iso.tuple(), (-iso).tuple()
577
+ i = 0 if (1,0,0,0) in (v,w) else 1
578
+ j = 0 if v[0] == 1 else 1 if w[0] == 1 else 2
579
+ return (i,) + min(v,w) + (j,) + v
580
+
581
+ return richcmp(_sorting_key(left), _sorting_key(right), op)
582
+
583
+ def _eval(self, P):
584
+ r"""
585
+ Less strict evaluation method for internal use.
586
+
587
+ In particular, this can be used to evaluate ``self`` at a
588
+ point defined over an extension field.
589
+
590
+ INPUT: a sequence of 3 coordinates defining a point on ``self``
591
+
592
+ OUTPUT: the result of evaluating ``self`` at the given point
593
+
594
+ EXAMPLES::
595
+
596
+ sage: # needs sage.rings.number_field
597
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
598
+ sage: E = EllipticCurve([i, 0]); E
599
+ Elliptic Curve defined by y^2 = x^3 + I*x
600
+ over Number Field in I with defining polynomial x^2 + 1 with I = 1*I
601
+ sage: iso = WeierstrassIsomorphism(E, (i,1,2,3))
602
+ sage: P = E.change_ring(QQbar).lift_x(QQbar.random_element())
603
+ sage: Q = iso._eval(P)
604
+ sage: Q.curve()
605
+ Elliptic Curve defined by y^2 + (-4*I)*x*y + 6*I*y = x^3 + x^2 + (I-9)*x + (-I+8)
606
+ over Algebraic Field
607
+ sage: y = next(filter(bool, iter(QQbar.random_element, None))) # sample until nonzero
608
+ sage: iso._eval((0, y, 0)) == 0
609
+ True
610
+ """
611
+ if self._domain.defining_polynomial()(*P):
612
+ raise ValueError(f'{P} not on {self._domain}')
613
+ k = Sequence(P).universe()
614
+
615
+ Q = baseWI.__call__(self, P)
616
+ return self._codomain.base_extend(k).point(Q)
617
+
618
+ def _call_(self, P):
619
+ r"""
620
+ Call function for WeierstrassIsomorphism class.
621
+
622
+ INPUT:
623
+
624
+ - ``P`` -- Point; a point on the domain curve
625
+
626
+ OUTPUT:
627
+
628
+ (Point) the transformed point on the codomain curve.
629
+
630
+ EXAMPLES::
631
+
632
+ sage: # needs database_cremona_mini_ellcurve
633
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
634
+ sage: E = EllipticCurve('37a1')
635
+ sage: w = WeierstrassIsomorphism(E,(2,3,4,5))
636
+ sage: P = E(0,-1)
637
+ sage: w(P)
638
+ (-3/4 : 3/4 : 1)
639
+ sage: w(P).curve() == E.change_weierstrass_model((2,3,4,5))
640
+ True
641
+
642
+ TESTS:
643
+
644
+ Check that copying the order over works::
645
+
646
+ sage: # needs sage.rings.finite_rings
647
+ sage: E = EllipticCurve(GF(431^2), [1,0])
648
+ sage: i = next(a for a in E.automorphisms() if a^2 == -a^24)
649
+ sage: P,_ = E.gens()
650
+ sage: P._order
651
+ 432
652
+ sage: i(P)._order
653
+ 432
654
+ sage: E(i(P))._order
655
+ 432
656
+
657
+ Check that the isomorphism cannot be evaluated on points outside
658
+ its domain (see :issue:`35799`)::
659
+
660
+ sage: # needs sage.rings.finite_rings
661
+ sage: E = EllipticCurve(GF(101), [1,1])
662
+ sage: f = E.automorphisms()[0]
663
+ sage: EE = EllipticCurve(GF(101), [5,5])
664
+ sage: P = EE.lift_x(2)
665
+ sage: P in f.domain()
666
+ False
667
+ sage: f(P)
668
+ Traceback (most recent call last):
669
+ ...
670
+ TypeError: (2 : 15 : 1) fails to convert into the map's
671
+ domain Elliptic Curve defined by y^2 = x^3 + x + 1 over
672
+ Finite Field of size 101, but a `pushforward` method is
673
+ not properly implemented
674
+ """
675
+ if P[2] == 0:
676
+ return self._codomain(0)
677
+ res = baseWI.__call__(self, tuple(P._coords))
678
+ Q = self._codomain.point(res, check=False)
679
+ if hasattr(P, '_order'):
680
+ Q._order = P._order
681
+ return Q
682
+
683
+ def __invert__(self):
684
+ r"""
685
+ Return the inverse of this WeierstrassIsomorphism.
686
+
687
+ EXAMPLES::
688
+
689
+ sage: # needs database_cremona_mini_ellcurve
690
+ sage: E = EllipticCurve('5077')
691
+ sage: F = E.change_weierstrass_model([2,3,4,5]); F
692
+ Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 7/4*x^2 - 3/2*x - 9/32 over Rational Field
693
+ sage: w = E.isomorphism_to(F)
694
+ sage: P = E(-2,3,1)
695
+ sage: w(P)
696
+ (-5/4 : 9/4 : 1)
697
+ sage: ~w
698
+ Elliptic-curve morphism:
699
+ From: Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 7/4*x^2 - 3/2*x - 9/32 over Rational Field
700
+ To: Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
701
+ Via: (u,r,s,t) = (1/2, -3/4, -2, 7/8)
702
+ sage: Q = w(P); Q
703
+ (-5/4 : 9/4 : 1)
704
+ sage: (~w)(Q)
705
+ (-2 : 3 : 1)
706
+ """
707
+ winv = baseWI.__invert__(self).tuple()
708
+ return WeierstrassIsomorphism(self._codomain, winv, self._domain)
709
+
710
+ @staticmethod
711
+ def _composition_impl(left, right):
712
+ r"""
713
+ Return the composition of a ``WeierstrassIsomorphism``
714
+ with another elliptic-curve morphism.
715
+
716
+ Called by :meth:`EllipticCurveHom._composition_`.
717
+
718
+ EXAMPLES::
719
+
720
+ sage: # needs database_cremona_mini_ellcurve
721
+ sage: E1 = EllipticCurve('5077')
722
+ sage: E2 = E1.change_weierstrass_model([2,3,4,5])
723
+ sage: w1 = E1.isomorphism_to(E2)
724
+ sage: E3 = E2.change_weierstrass_model([6,7,8,9])
725
+ sage: w2 = E2.isomorphism_to(E3)
726
+ sage: P = E1(-2,3,1)
727
+ sage: (w2*w1)(P) == w2(w1(P))
728
+ True
729
+
730
+ TESTS:
731
+
732
+ We should return ``NotImplemented`` when passed a combination of
733
+ elliptic-curve morphism types that we don't handle here::
734
+
735
+ sage: E1 = EllipticCurve([1,0])
736
+ sage: phi = E1.isogeny(E1(0,0))
737
+ sage: E2 = phi.codomain()
738
+ sage: psi = E2.isogeny(E2(0,0))
739
+ sage: w1._composition_impl(psi, phi) # needs database_cremona_mini_ellcurve
740
+ NotImplemented
741
+ """
742
+ if isinstance(left, WeierstrassIsomorphism) and isinstance(right, WeierstrassIsomorphism):
743
+ if left._domain != right._codomain:
744
+ raise ValueError("Domain of first argument must equal codomain of second")
745
+ w = baseWI.__mul__(left, right)
746
+ return WeierstrassIsomorphism(right._domain, w.tuple(), left._codomain)
747
+
748
+ return NotImplemented
749
+
750
+ def __repr__(self):
751
+ r"""
752
+ Return the string representation of this WeierstrassIsomorphism.
753
+
754
+ OUTPUT:
755
+
756
+ (string) The underlying morphism, together with an extra line
757
+ showing the `(u,r,s,t)` parameters.
758
+
759
+ EXAMPLES::
760
+
761
+ sage: # needs database_cremona_mini_ellcurve
762
+ sage: E1 = EllipticCurve('5077')
763
+ sage: E2 = E1.change_weierstrass_model([2,3,4,5])
764
+ sage: E1.isomorphism_to(E2)
765
+ Elliptic-curve morphism:
766
+ From: Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
767
+ To: Elliptic Curve defined by y^2 + 4*x*y + 11/8*y = x^3 - 7/4*x^2 - 3/2*x - 9/32 over Rational Field
768
+ Via: (u,r,s,t) = (2, 3, 4, 5)
769
+ """
770
+ return EllipticCurveHom.__repr__(self) + "\n Via: (u,r,s,t) = " + baseWI.__repr__(self)
771
+
772
+ # EllipticCurveHom methods
773
+
774
+ def rational_maps(self):
775
+ """
776
+ Return the pair of rational maps defining this isomorphism.
777
+
778
+ EXAMPLES::
779
+
780
+ sage: E1 = EllipticCurve([11,22,33,44,55])
781
+ sage: E2 = EllipticCurve_from_j(E1.j_invariant())
782
+ sage: iso = E1.isomorphism_to(E2); iso
783
+ Elliptic-curve morphism:
784
+ From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55
785
+ over Rational Field
786
+ To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681
787
+ over Rational Field
788
+ Via: (u,r,s,t) = (1, -17, -5, 77)
789
+ sage: iso.rational_maps()
790
+ (x + 17, 5*x + y + 8)
791
+ sage: f = E2.defining_polynomial()(*iso.rational_maps(), 1)
792
+ sage: I = E1.defining_ideal()
793
+ sage: x,y,z = I.ring().gens()
794
+ sage: f in I + Ideal(z-1)
795
+ True
796
+
797
+ ::
798
+
799
+ sage: # needs sage.rings.finite_rings
800
+ sage: E = EllipticCurve(GF(65537), [1,1,1,1,1])
801
+ sage: w = E.isomorphism_to(E.short_weierstrass_model())
802
+ sage: f,g = w.rational_maps()
803
+ sage: P = E.random_point()
804
+ sage: w(P).xy() == (f(P.xy()), g(P.xy()))
805
+ True
806
+
807
+ TESTS:
808
+
809
+ Check for :issue:`34811`::
810
+
811
+ sage: iso.rational_maps()[0].parent()
812
+ Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field
813
+ sage: iso.rational_maps()[1].parent()
814
+ Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field
815
+ """
816
+ return tuple(baseWI.__call__(self, self._xyfield.gens()))
817
+
818
+ def x_rational_map(self):
819
+ """
820
+ Return the `x`-coordinate rational map of this isomorphism.
821
+
822
+ EXAMPLES::
823
+
824
+ sage: E1 = EllipticCurve([11,22,33,44,55])
825
+ sage: E2 = EllipticCurve_from_j(E1.j_invariant())
826
+ sage: iso = E1.isomorphism_to(E2); iso
827
+ Elliptic-curve morphism:
828
+ From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55
829
+ over Rational Field
830
+ To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681
831
+ over Rational Field
832
+ Via: (u,r,s,t) = (1, -17, -5, 77)
833
+ sage: iso.x_rational_map()
834
+ x + 17
835
+ sage: iso.x_rational_map() == iso.rational_maps()[0]
836
+ True
837
+
838
+ TESTS:
839
+
840
+ Check for :issue:`34811`::
841
+
842
+ sage: iso.x_rational_map().parent()
843
+ Fraction Field of Univariate Polynomial Ring in x over Rational Field
844
+ """
845
+ x, = self._xfield.gens()
846
+ return (x - self.r) / self.u**2
847
+
848
+ def kernel_polynomial(self):
849
+ """
850
+ Return the kernel polynomial of this isomorphism.
851
+
852
+ Isomorphisms have trivial kernel by definition, hence this
853
+ method always returns `1`.
854
+
855
+ EXAMPLES::
856
+
857
+ sage: E1 = EllipticCurve([11,22,33,44,55])
858
+ sage: E2 = EllipticCurve_from_j(E1.j_invariant())
859
+ sage: iso = E1.isomorphism_to(E2)
860
+ sage: iso.kernel_polynomial()
861
+ 1
862
+ sage: psi = E1.isogeny(iso.kernel_polynomial(), codomain=E2); psi
863
+ Isogeny of degree 1
864
+ from Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55
865
+ over Rational Field
866
+ to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681
867
+ over Rational Field
868
+ sage: psi in {iso, -iso}
869
+ True
870
+
871
+ TESTS::
872
+
873
+ sage: iso.kernel_polynomial().parent()
874
+ Univariate Polynomial Ring in x over Rational Field
875
+ """
876
+ return self._poly_ring(1)
877
+
878
+ def dual(self):
879
+ """
880
+ Return the dual isogeny of this isomorphism.
881
+
882
+ For isomorphisms, the dual is just the inverse.
883
+
884
+ EXAMPLES::
885
+
886
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
887
+ sage: E = EllipticCurve(QuadraticField(-3), [0,1]) # needs sage.rings.number_field
888
+ sage: w = WeierstrassIsomorphism(E, (CyclotomicField(3).gen(),0,0,0)) # needs sage.rings.number_field
889
+ sage: (w.dual() * w).rational_maps() # needs sage.rings.number_field
890
+ (x, y)
891
+
892
+ ::
893
+
894
+ sage: E1 = EllipticCurve([11,22,33,44,55])
895
+ sage: E2 = E1.short_weierstrass_model()
896
+ sage: iso = E1.isomorphism_to(E2)
897
+ sage: iso.dual() == ~iso
898
+ True
899
+ """
900
+ return ~self
901
+
902
+ def __neg__(self):
903
+ """
904
+ Return the negative of this isomorphism, i.e., its composition
905
+ with the negation map `[-1]`.
906
+
907
+ EXAMPLES::
908
+
909
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
910
+ sage: E = EllipticCurve([11,22,33,44,55])
911
+ sage: w = WeierstrassIsomorphism(E, (66,77,88,99))
912
+ sage: -w
913
+ Elliptic-curve morphism:
914
+ From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field
915
+ To: Elliptic Curve defined by y^2 + 17/6*x*y + 49/13068*y = x^3 - 769/396*x^2 - 3397/862488*x + 44863/7513995456
916
+ over Rational Field
917
+ Via: (u,r,s,t) = (-66, 77, -99, -979)
918
+ sage: -(-w) == w
919
+ True
920
+
921
+ ::
922
+
923
+ sage: # needs sage.rings.number_field
924
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
925
+ sage: K.<a> = QuadraticField(-3)
926
+ sage: E = EllipticCurve(K, [0,1])
927
+ sage: w = WeierstrassIsomorphism(E, (CyclotomicField(3).gen(),0,0,0))
928
+ sage: w.tuple()
929
+ (1/2*a - 1/2, 0, 0, 0)
930
+ sage: (-w).tuple()
931
+ (-1/2*a + 1/2, 0, 0, 0)
932
+ sage: (-w)^3 == -(w^3)
933
+ True
934
+
935
+ ::
936
+
937
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism, identity_morphism
938
+ sage: E = EllipticCurve(QuadraticField(-1), [1,0]) # needs sage.rings.number_field
939
+ sage: t = WeierstrassIsomorphism(E, (i,0,0,0)) # needs sage.rings.number_field
940
+ sage: -t^2 == identity_morphism(E) # needs sage.rings.number_field
941
+ True
942
+ """
943
+ a1,_,a3,_,_ = self._domain.a_invariants()
944
+ w = baseWI(-1, 0, -a1, -a3)
945
+ urst = baseWI.__mul__(self, w).tuple()
946
+ return WeierstrassIsomorphism(self._domain, urst, self._codomain)
947
+
948
+ def scaling_factor(self):
949
+ r"""
950
+ Return the Weierstrass scaling factor associated to this
951
+ Weierstrass isomorphism.
952
+
953
+ The scaling factor is the constant `u` (in the base field)
954
+ such that `\varphi^* \omega_2 = u \omega_1`, where
955
+ `\varphi: E_1\to E_2` is this isomorphism and `\omega_i` are
956
+ the standard Weierstrass differentials on `E_i` defined by
957
+ `\mathrm dx/(2y+a_1x+a_3)`.
958
+
959
+ EXAMPLES::
960
+
961
+ sage: E = EllipticCurve(QQbar, [0,1]) # needs sage.rings.number_field
962
+ sage: all(f.scaling_factor() == f.formal()[1] for f in E.automorphisms()) # needs sage.rings.number_field
963
+ True
964
+
965
+ ALGORITHM: The scaling factor equals the `u` component of
966
+ the tuple `(u,r,s,t)` defining the isomorphism.
967
+ """
968
+ return self.u
969
+
970
+ def inseparable_degree(self):
971
+ r"""
972
+ Return the inseparable degree of this Weierstrass isomorphism.
973
+
974
+ For isomorphisms, this method always returns one.
975
+
976
+ TESTS::
977
+
978
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
979
+ sage: WeierstrassIsomorphism.inseparable_degree(None)
980
+ 1
981
+ """
982
+ return Integer(1)
983
+
984
+ def is_identity(self):
985
+ r"""
986
+ Check if this Weierstrass isomorphism is the identity.
987
+
988
+ EXAMPLES::
989
+
990
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
991
+ sage: p = 97
992
+ sage: Fp = GF(p)
993
+ sage: E = EllipticCurve(Fp, [1, 28])
994
+ sage: ws = WeierstrassIsomorphism(E, None, E)
995
+ sage: ws.is_identity()
996
+ False
997
+
998
+ ::
999
+
1000
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
1001
+ sage: p = 97
1002
+ sage: Fp = GF(p)
1003
+ sage: E = EllipticCurve(Fp, [1, 28])
1004
+ sage: ws = WeierstrassIsomorphism(E, (1, 0, 0, 0), None)
1005
+ sage: ws.is_identity()
1006
+ True
1007
+ """
1008
+ return self.tuple() == (1, 0, 0, 0)
1009
+
1010
+ def order(self):
1011
+ r"""
1012
+ Compute the order of this Weierstrass isomorphism if it is an automorphism.
1013
+
1014
+ A :exc:`ValueError` is raised if the domain is not equal to the codomain.
1015
+
1016
+ A :exc:`NotImplementedError` is raised if the order of the automorphism is not 1, 2, 3, 4 or 6.
1017
+
1018
+ EXAMPLES::
1019
+
1020
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
1021
+ sage: p = 97
1022
+ sage: Fp = GF(p)
1023
+ sage: E = EllipticCurve(Fp, [1, 28])
1024
+ sage: ws = WeierstrassIsomorphism(E, None, E)
1025
+ sage: ws.order()
1026
+ 2
1027
+
1028
+ TESTS::
1029
+
1030
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import *
1031
+ sage: p = 97
1032
+ sage: Fp = GF(p)
1033
+ sage: E = EllipticCurve(Fp, [1, 28])
1034
+ sage: ws = WeierstrassIsomorphism(E, None, E)
1035
+ sage: ws.order()
1036
+ 2
1037
+ sage: E1 = EllipticCurve(Fp, [1, 69])
1038
+ sage: ws = E.isomorphism_to(E1)
1039
+ sage: ws.order()
1040
+ Traceback (most recent call last):
1041
+ ...
1042
+ ValueError: the domain is different from the codomain
1043
+
1044
+ ::
1045
+
1046
+ sage: E = EllipticCurve_from_j(Fp(0))
1047
+ sage: ws = WeierstrassIsomorphism(E, (Fp(36), 0, 0, 0), None)
1048
+ sage: ws.order()
1049
+ 6
1050
+ sage: ws2 = ws*ws
1051
+ sage: ws2.order()
1052
+ 3
1053
+ sage: F2_bar = GF(2).algebraic_closure()
1054
+ sage: E = EllipticCurve_from_j(F2_bar(0))
1055
+ sage: ws = WeierstrassIsomorphism(E, None, E)
1056
+ sage: ws.order()
1057
+ 3
1058
+ """
1059
+ # Check if it is an actual endomorphism
1060
+ if self._domain != self._codomain:
1061
+ raise ValueError("the domain is different from the codomain")
1062
+
1063
+ if self.is_identity():
1064
+ return Integer(1)
1065
+
1066
+ ws2 = WeierstrassIsomorphism._composition_impl(self, self)
1067
+ if ws2.is_identity():
1068
+ return Integer(2)
1069
+
1070
+ ws3 = WeierstrassIsomorphism._composition_impl(self, ws2)
1071
+ if ws3.is_identity():
1072
+ return Integer(3)
1073
+
1074
+ ws4 = WeierstrassIsomorphism._composition_impl(ws2, ws2)
1075
+ if ws4.is_identity():
1076
+ return Integer(4)
1077
+
1078
+ ws6 = WeierstrassIsomorphism._composition_impl(ws2, ws4)
1079
+ if ws6.is_identity():
1080
+ return Integer(6)
1081
+
1082
+ raise NotImplementedError("the order of the endomorphism is not 1, 2, 3, 4 or 6")
1083
+
1084
+
1085
+ def identity_morphism(E):
1086
+ r"""
1087
+ Given an elliptic curve `E`, return the identity morphism
1088
+ on `E` as a :class:`WeierstrassIsomorphism`.
1089
+
1090
+ EXAMPLES::
1091
+
1092
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import identity_morphism
1093
+ sage: E = EllipticCurve([5,6,7,8,9])
1094
+ sage: id_ = identity_morphism(E)
1095
+ sage: id_.rational_maps()
1096
+ (x, y)
1097
+ """
1098
+ R = E.base_ring()
1099
+ zero = R.zero()
1100
+ return WeierstrassIsomorphism(E, (R.one(), zero, zero, zero))
1101
+
1102
+
1103
+ def negation_morphism(E):
1104
+ r"""
1105
+ Given an elliptic curve `E`, return the negation endomorphism
1106
+ `[-1]` of `E` as a :class:`WeierstrassIsomorphism`.
1107
+
1108
+ EXAMPLES::
1109
+
1110
+ sage: from sage.schemes.elliptic_curves.weierstrass_morphism import negation_morphism
1111
+ sage: E = EllipticCurve([5,6,7,8,9])
1112
+ sage: neg = negation_morphism(E)
1113
+ sage: neg.rational_maps()
1114
+ (x, -5*x - y - 7)
1115
+ """
1116
+ R = E.base_ring()
1117
+ return WeierstrassIsomorphism(E, (-R.one(), R.zero(), -E.a1(), -E.a3()))