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.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.6.40.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
- passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.40.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-darwin.so +0 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
- sage/modular/modform/notes.py +45 -0
- sage/modular/modform/numerical.py +514 -0
- sage/modular/modform/periods.py +14 -0
- sage/modular/modform/ring.py +1257 -0
- sage/modular/modform/space.py +1860 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3846 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-314-darwin.so +0 -0
- sage/modular/modsym/manin_symbol.pxd +5 -0
- sage/modular/modsym/manin_symbol.pyx +497 -0
- sage/modular/modsym/manin_symbol_list.py +1295 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
- sage/modular/modsym/p1list.pxd +29 -0
- sage/modular/modsym/p1list.pyx +1372 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-314-darwin.so +0 -0
- sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
- sage/modular/modsym/space.py +2468 -0
- sage/modular/modsym/subspace.py +455 -0
- sage/modular/modsym/tests.py +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +1036 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +682 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +943 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-314-darwin.so +0 -0
- sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
- sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
- sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
- sage/schemes/elliptic_curves/padics.py +1816 -0
- sage/schemes/elliptic_curves/period_lattice.py +2234 -0
- sage/schemes/elliptic_curves/period_lattice_region.cpython-314-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +715 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +580 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- 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()))
|