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.
- 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.47.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
- passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.47.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-312-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-312-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-312-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-312-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-312-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-312-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-312-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-312-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_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-312-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-312-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-312-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,682 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
r"""
|
|
3
|
+
Sums of morphisms of elliptic curves
|
|
4
|
+
|
|
5
|
+
The set `\mathrm{Hom}(E,E')` of morphisms between two elliptic curves
|
|
6
|
+
forms an abelian group under pointwise addition. An important special
|
|
7
|
+
case is the endomorphism ring `\mathrm{End}(E) = \mathrm{Hom}(E,E)`.
|
|
8
|
+
However, it is not immediately obvious how to compute some properties
|
|
9
|
+
of the sum `\varphi+\psi` of two isogenies, even when both are given
|
|
10
|
+
explicitly. This class provides functionality for representing sums of
|
|
11
|
+
elliptic-curve morphisms (in particular, isogenies and endomorphisms)
|
|
12
|
+
formally, and explicitly computing important properties (such as the
|
|
13
|
+
degree or the kernel polynomial) from the formal representation.
|
|
14
|
+
|
|
15
|
+
EXAMPLES::
|
|
16
|
+
|
|
17
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
18
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
19
|
+
sage: phi + phi
|
|
20
|
+
Sum morphism:
|
|
21
|
+
From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
22
|
+
To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
|
|
23
|
+
Via: (Isogeny of degree 7
|
|
24
|
+
from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
25
|
+
to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101,
|
|
26
|
+
Isogeny of degree 7
|
|
27
|
+
from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
28
|
+
to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101)
|
|
29
|
+
sage: phi + phi == phi * E.scalar_multiplication(2) # needs sage.symbolic
|
|
30
|
+
True
|
|
31
|
+
sage: phi + phi + phi == phi * E.scalar_multiplication(3) # needs sage.symbolic
|
|
32
|
+
True
|
|
33
|
+
|
|
34
|
+
An example of computing with a supersingular endomorphism ring::
|
|
35
|
+
|
|
36
|
+
sage: # needs sage.symbolic
|
|
37
|
+
sage: E = EllipticCurve(GF(419^2), [1,0])
|
|
38
|
+
sage: i = E.automorphisms()[-1]
|
|
39
|
+
sage: j = E.frobenius_isogeny()
|
|
40
|
+
sage: i * j == - j * i # i,j anticommute
|
|
41
|
+
True
|
|
42
|
+
sage: (i + j) * i == i^2 - i*j # distributive law
|
|
43
|
+
True
|
|
44
|
+
sage: (j - E.scalar_multiplication(1)).degree() # point counting!
|
|
45
|
+
420
|
|
46
|
+
|
|
47
|
+
AUTHORS:
|
|
48
|
+
|
|
49
|
+
- Lorenz Panny (2023)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from sage.misc.cachefunc import cached_method
|
|
53
|
+
from sage.structure.sequence import Sequence
|
|
54
|
+
|
|
55
|
+
from sage.arith.misc import gcd
|
|
56
|
+
|
|
57
|
+
from sage.rings.integer_ring import ZZ
|
|
58
|
+
from sage.rings.polynomial.polynomial_ring import polygen
|
|
59
|
+
|
|
60
|
+
from sage.sets.primes import Primes
|
|
61
|
+
|
|
62
|
+
from sage.schemes.elliptic_curves.ell_field import point_of_order
|
|
63
|
+
from sage.groups.generic import discrete_log, order_from_multiple
|
|
64
|
+
|
|
65
|
+
from sage.schemes.elliptic_curves.hom import EllipticCurveHom, compare_via_evaluation
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class EllipticCurveHom_sum(EllipticCurveHom):
|
|
69
|
+
|
|
70
|
+
_degree = None
|
|
71
|
+
_phis = None
|
|
72
|
+
|
|
73
|
+
def __init__(self, phis, domain=None, codomain=None):
|
|
74
|
+
r"""
|
|
75
|
+
Construct a sum morphism of elliptic curves from its summands.
|
|
76
|
+
(For empty sums, the domain and codomain curves must be given.)
|
|
77
|
+
|
|
78
|
+
EXAMPLES::
|
|
79
|
+
|
|
80
|
+
sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum
|
|
81
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
82
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
83
|
+
sage: EllipticCurveHom_sum([phi, phi])
|
|
84
|
+
Sum morphism:
|
|
85
|
+
From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
86
|
+
To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
|
|
87
|
+
Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101)
|
|
88
|
+
|
|
89
|
+
The zero morphism can be constructed even between non-isogenous curves::
|
|
90
|
+
|
|
91
|
+
sage: E1 = EllipticCurve(GF(101), [5,5])
|
|
92
|
+
sage: E2 = EllipticCurve(GF(101), [7,7])
|
|
93
|
+
sage: E1.is_isogenous(E2)
|
|
94
|
+
False
|
|
95
|
+
sage: EllipticCurveHom_sum([], E1, E2)
|
|
96
|
+
Sum morphism:
|
|
97
|
+
From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
98
|
+
To: Elliptic Curve defined by y^2 = x^3 + 7*x + 7 over Finite Field of size 101
|
|
99
|
+
Via: ()
|
|
100
|
+
"""
|
|
101
|
+
phis = tuple(phis)
|
|
102
|
+
|
|
103
|
+
if not phis and (domain is None or codomain is None):
|
|
104
|
+
raise ValueError('need either phis or both domain and codomain')
|
|
105
|
+
|
|
106
|
+
for phi in phis:
|
|
107
|
+
if not isinstance(phi, EllipticCurveHom):
|
|
108
|
+
raise ValueError(f'not an elliptic-curve morphism: {phi}')
|
|
109
|
+
|
|
110
|
+
if domain is None:
|
|
111
|
+
domain = phis[0].domain()
|
|
112
|
+
if codomain is None:
|
|
113
|
+
codomain = phis[0].codomain()
|
|
114
|
+
for phi in phis:
|
|
115
|
+
if phi.domain() != domain:
|
|
116
|
+
raise ValueError(f'summand {phi} has incorrect domain (need {domain})')
|
|
117
|
+
if phi.codomain() != codomain:
|
|
118
|
+
raise ValueError(f'summand {phi} has incorrect codomain (need {codomain})')
|
|
119
|
+
|
|
120
|
+
self._phis = phis
|
|
121
|
+
self._domain = domain
|
|
122
|
+
self._codomain = codomain
|
|
123
|
+
|
|
124
|
+
# We temporarily overwrite the _degree attribute here to prevent the
|
|
125
|
+
# EllipticCurveHom constructor from attempting to compute the degree.
|
|
126
|
+
self._degree = 0
|
|
127
|
+
EllipticCurveHom.__init__(self, self._domain, self._codomain)
|
|
128
|
+
self._degree = None
|
|
129
|
+
|
|
130
|
+
def _call_(self, P):
|
|
131
|
+
r"""
|
|
132
|
+
Evaluate this sum morphism at a point.
|
|
133
|
+
|
|
134
|
+
EXAMPLES::
|
|
135
|
+
|
|
136
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
137
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
138
|
+
sage: P = E.lift_x(0)
|
|
139
|
+
sage: (phi + phi)(P)
|
|
140
|
+
(72 : 56 : 1)
|
|
141
|
+
sage: (phi - phi)(P)
|
|
142
|
+
(0 : 1 : 0)
|
|
143
|
+
"""
|
|
144
|
+
return sum((phi(P) for phi in self._phis), self._codomain(0))
|
|
145
|
+
|
|
146
|
+
def _eval(self, P):
|
|
147
|
+
r"""
|
|
148
|
+
Less strict evaluation method for internal use.
|
|
149
|
+
|
|
150
|
+
In particular, this can be used to evaluate ``self`` at a
|
|
151
|
+
point defined over an extension field.
|
|
152
|
+
|
|
153
|
+
INPUT: a sequence of 3 coordinates defining a point on ``self``
|
|
154
|
+
|
|
155
|
+
OUTPUT: the result of evaluating ``self`` at the given point
|
|
156
|
+
|
|
157
|
+
EXAMPLES::
|
|
158
|
+
|
|
159
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
160
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
161
|
+
sage: P = E.change_ring(GF(101^2)).lift_x(1)
|
|
162
|
+
sage: (phi + phi)._eval(P)
|
|
163
|
+
(11 : 15*z2 + 71 : 1)
|
|
164
|
+
sage: (phi - phi)._eval(P)
|
|
165
|
+
(0 : 1 : 0)
|
|
166
|
+
"""
|
|
167
|
+
if self._domain.defining_polynomial()(*P):
|
|
168
|
+
raise ValueError(f'{P} not on {self._domain}')
|
|
169
|
+
k = Sequence(P).universe()
|
|
170
|
+
return sum((phi._eval(P) for phi in self._phis), self._codomain.base_extend(k)(0))
|
|
171
|
+
|
|
172
|
+
def _repr_(self):
|
|
173
|
+
r"""
|
|
174
|
+
Return basic facts about this sum morphism as a string.
|
|
175
|
+
|
|
176
|
+
EXAMPLES::
|
|
177
|
+
|
|
178
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
179
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
180
|
+
sage: phi + phi # indirect doctest
|
|
181
|
+
Sum morphism:
|
|
182
|
+
From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
183
|
+
To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
|
|
184
|
+
Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101)
|
|
185
|
+
"""
|
|
186
|
+
return f'Sum morphism:' \
|
|
187
|
+
f'\n From: {self._domain}' \
|
|
188
|
+
f'\n To: {self._codomain}' \
|
|
189
|
+
f'\n Via: {self._phis}'
|
|
190
|
+
|
|
191
|
+
def summands(self):
|
|
192
|
+
r"""
|
|
193
|
+
Return the individual summands making up this sum morphism.
|
|
194
|
+
|
|
195
|
+
EXAMPLES::
|
|
196
|
+
|
|
197
|
+
sage: E = EllipticCurve(j=5)
|
|
198
|
+
sage: m2 = E.scalar_multiplication(2)
|
|
199
|
+
sage: m3 = E.scalar_multiplication(3)
|
|
200
|
+
sage: m2 + m3
|
|
201
|
+
Sum morphism:
|
|
202
|
+
From: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
|
|
203
|
+
To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
|
|
204
|
+
Via: (Scalar-multiplication endomorphism [2] of Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field, Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field)
|
|
205
|
+
"""
|
|
206
|
+
return self._phis
|
|
207
|
+
|
|
208
|
+
@cached_method
|
|
209
|
+
def to_isogeny_chain(self):
|
|
210
|
+
r"""
|
|
211
|
+
Convert this formal sum of elliptic-curve morphisms into a
|
|
212
|
+
:class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite`
|
|
213
|
+
object representing the same morphism.
|
|
214
|
+
|
|
215
|
+
EXAMPLES::
|
|
216
|
+
|
|
217
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
218
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
219
|
+
sage: (phi + phi).to_isogeny_chain()
|
|
220
|
+
Composite morphism of degree 28 = 4*1*7:
|
|
221
|
+
From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
222
|
+
To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
|
|
223
|
+
|
|
224
|
+
::
|
|
225
|
+
|
|
226
|
+
sage: p = 419
|
|
227
|
+
sage: E = EllipticCurve(GF(p^2), [1,0])
|
|
228
|
+
sage: iota = E.automorphisms()[2] # sqrt(-1)
|
|
229
|
+
sage: pi = E.frobenius_isogeny() # sqrt(-p)
|
|
230
|
+
sage: endo = iota + pi
|
|
231
|
+
sage: endo.degree()
|
|
232
|
+
420
|
|
233
|
+
sage: endo.to_isogeny_chain()
|
|
234
|
+
Composite morphism of degree 420 = 4*1*3*5*7:
|
|
235
|
+
From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2
|
|
236
|
+
To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2
|
|
237
|
+
|
|
238
|
+
The decomposition is impossible for the constant zero map::
|
|
239
|
+
|
|
240
|
+
sage: endo = iota*pi + pi*iota
|
|
241
|
+
sage: endo.degree()
|
|
242
|
+
0
|
|
243
|
+
sage: endo.to_isogeny_chain()
|
|
244
|
+
Traceback (most recent call last):
|
|
245
|
+
...
|
|
246
|
+
ValueError: zero morphism cannot be written as a composition of isogenies
|
|
247
|
+
|
|
248
|
+
Isomorphisms are supported as well::
|
|
249
|
+
|
|
250
|
+
sage: E = EllipticCurve(j=5); E
|
|
251
|
+
Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
|
|
252
|
+
sage: m2 = E.scalar_multiplication(2)
|
|
253
|
+
sage: m3 = E.scalar_multiplication(3)
|
|
254
|
+
sage: (m2 - m3).to_isogeny_chain()
|
|
255
|
+
Composite morphism of degree 1 = 1^2:
|
|
256
|
+
From: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
|
|
257
|
+
To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
|
|
258
|
+
sage: (m2 - m3).rational_maps()
|
|
259
|
+
(x, -x - y)
|
|
260
|
+
"""
|
|
261
|
+
deg = self.degree()
|
|
262
|
+
if deg.is_zero():
|
|
263
|
+
raise ValueError('zero morphism cannot be written as a composition of isogenies')
|
|
264
|
+
|
|
265
|
+
p = self.base_ring().characteristic()
|
|
266
|
+
insep = self.inseparable_degree().valuation(p) if p else 0
|
|
267
|
+
|
|
268
|
+
scalar = 1 #TODO Can we detect scalar factors earlier to save some extensions below?
|
|
269
|
+
|
|
270
|
+
ker = []
|
|
271
|
+
for l,m in deg.factor():
|
|
272
|
+
if l == p: # possibly inseparable
|
|
273
|
+
if insep < m:
|
|
274
|
+
# kernel of the separable p-power part is unique
|
|
275
|
+
P = point_of_order(self.domain(), p**(m-insep))
|
|
276
|
+
ker.append(P)
|
|
277
|
+
continue
|
|
278
|
+
|
|
279
|
+
# F = self.domain().division_field(l**m) #FIXME this can be used once #35936 is done; workaround below
|
|
280
|
+
F = self.domain().division_polynomial(l**m).splitting_field('X').extension(2,'Y')
|
|
281
|
+
|
|
282
|
+
P,Q = self.domain().change_ring(F).torsion_basis(l**m)
|
|
283
|
+
if self.is_endomorphism():
|
|
284
|
+
R,S = P,Q
|
|
285
|
+
else:
|
|
286
|
+
R,S = self.codomain().change_ring(F).torsion_basis(l**m)
|
|
287
|
+
M = self.matrix_on_subgroup((P,Q), (R,S))
|
|
288
|
+
g = ZZ(gcd(M.list())).p_primary_part(l)
|
|
289
|
+
if g > 1:
|
|
290
|
+
scalar *= g
|
|
291
|
+
M = (M.change_ring(ZZ) / g).change_ring(M.base_ring())
|
|
292
|
+
K = M.left_kernel_matrix()
|
|
293
|
+
for row in K:
|
|
294
|
+
u,v = map(ZZ, row)
|
|
295
|
+
pt = u*P + v*Q
|
|
296
|
+
pt.set_order(row.additive_order())
|
|
297
|
+
ker.append(pt)
|
|
298
|
+
|
|
299
|
+
from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
|
|
300
|
+
phi = EllipticCurveHom_composite(self.domain(), [])
|
|
301
|
+
|
|
302
|
+
if scalar != 1:
|
|
303
|
+
phi *= phi.codomain().scalar_multiplication(scalar)
|
|
304
|
+
|
|
305
|
+
while ker:
|
|
306
|
+
K = ker.pop(0)
|
|
307
|
+
|
|
308
|
+
(l,e), = K.order().factor()
|
|
309
|
+
for i in reversed(range(e)):
|
|
310
|
+
Kl = l**i * K
|
|
311
|
+
Kl.set_order(l)
|
|
312
|
+
|
|
313
|
+
from sage.groups.generic import multiples
|
|
314
|
+
from sage.misc.misc_c import prod
|
|
315
|
+
x = polygen(Kl.base_ring())
|
|
316
|
+
poly = prod(x - T.x() for T in multiples(Kl, l//2, Kl))
|
|
317
|
+
poly = poly.change_ring(self.base_ring())
|
|
318
|
+
|
|
319
|
+
psi = phi.codomain().isogeny(poly)
|
|
320
|
+
phi = psi * phi
|
|
321
|
+
K = psi._eval(K)
|
|
322
|
+
ker = [psi._eval(P) for P in ker]
|
|
323
|
+
|
|
324
|
+
if insep:
|
|
325
|
+
frob = phi.codomain().frobenius_isogeny(insep)
|
|
326
|
+
phi = frob * phi
|
|
327
|
+
|
|
328
|
+
from sage.schemes.elliptic_curves.hom import find_post_isomorphism
|
|
329
|
+
iso = find_post_isomorphism(phi, self)
|
|
330
|
+
return iso * phi
|
|
331
|
+
|
|
332
|
+
# EllipticCurveHom methods
|
|
333
|
+
|
|
334
|
+
def _degree_bounds(self):
|
|
335
|
+
r"""
|
|
336
|
+
Return a lower and upper bound on the degree of this sum morphism.
|
|
337
|
+
|
|
338
|
+
EXAMPLES::
|
|
339
|
+
|
|
340
|
+
sage: E = EllipticCurve(GF(307), [5,5])
|
|
341
|
+
sage: phi = E.isogenies_prime_degree(3)[0]; phi
|
|
342
|
+
Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 307 to Elliptic Curve defined by y^2 = x^3 + 227*x + 163 over Finite Field of size 307
|
|
343
|
+
sage: psi = next(iso*psi for psi in E.isogenies_prime_degree(43)
|
|
344
|
+
....: for iso in psi.codomain().isomorphisms(phi.codomain())); psi
|
|
345
|
+
Isogeny of degree 43 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 307 to Elliptic Curve defined by y^2 = x^3 + 227*x + 163 over Finite Field of size 307
|
|
346
|
+
sage: (phi + psi)._degree_bounds()
|
|
347
|
+
(24, 68)
|
|
348
|
+
sage: (phi + psi).degree()
|
|
349
|
+
31
|
|
350
|
+
sage: (phi - phi)._degree_bounds()
|
|
351
|
+
(0, 12)
|
|
352
|
+
sage: (phi - phi).degree()
|
|
353
|
+
0
|
|
354
|
+
|
|
355
|
+
::
|
|
356
|
+
|
|
357
|
+
sage: E = EllipticCurve(GF(443), [1,1])
|
|
358
|
+
sage: pi = E.frobenius_endomorphism()
|
|
359
|
+
sage: m1 = E.scalar_multiplication(1)
|
|
360
|
+
sage: (pi - m1)._degree_bounds()
|
|
361
|
+
(402, 486)
|
|
362
|
+
sage: (pi - m1)._degree_bounds() == Hasse_bounds(443)
|
|
363
|
+
True
|
|
364
|
+
sage: (pi - m1).degree()
|
|
365
|
+
433
|
|
366
|
+
|
|
367
|
+
ALGORITHM: Repeated application of the Cauchy-Schwarz inequality,
|
|
368
|
+
here in the form
|
|
369
|
+
`|\deg(f+g) - \deg(f) - \deg(g)| \leq 2\sqrt{\deg(f)\cdot\deg(g)}`.
|
|
370
|
+
See for instance Lemma V.1.2 of [Sil2009]_.
|
|
371
|
+
"""
|
|
372
|
+
lo, hi = ZZ.zero(), ZZ.zero()
|
|
373
|
+
for phi in self._phis:
|
|
374
|
+
m = (hi * phi.degree()).isqrt()
|
|
375
|
+
hi += phi.degree() + 2*m
|
|
376
|
+
lo += phi.degree() - 2*m
|
|
377
|
+
lo = max(lo, 0)
|
|
378
|
+
return lo, hi
|
|
379
|
+
|
|
380
|
+
def _compute_degree(self):
|
|
381
|
+
r"""
|
|
382
|
+
Internal method to compute and cache the degree of this sum morphism
|
|
383
|
+
(and its dual).
|
|
384
|
+
|
|
385
|
+
ALGORITHM: Evaluate the composition with the dual on points of small
|
|
386
|
+
order and solve logarithms to eventually recover the degree using CRT.
|
|
387
|
+
(This is essentially Schoof's algorithm, applied to a scalar.)
|
|
388
|
+
|
|
389
|
+
EXAMPLES::
|
|
390
|
+
|
|
391
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
392
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
393
|
+
sage: isog = phi + phi
|
|
394
|
+
sage: print(isog._degree)
|
|
395
|
+
None
|
|
396
|
+
sage: isog._compute_degree()
|
|
397
|
+
sage: isog._degree
|
|
398
|
+
28
|
|
399
|
+
|
|
400
|
+
::
|
|
401
|
+
|
|
402
|
+
sage: E = EllipticCurve(GF(443), [1,1])
|
|
403
|
+
sage: pi = E.frobenius_endomorphism()
|
|
404
|
+
sage: m1 = E.scalar_multiplication(1)
|
|
405
|
+
sage: endo = pi - m1
|
|
406
|
+
sage: print(endo._degree)
|
|
407
|
+
None
|
|
408
|
+
sage: endo._compute_degree()
|
|
409
|
+
sage: endo._degree
|
|
410
|
+
433
|
|
411
|
+
sage: endo.dual()._degree
|
|
412
|
+
433
|
|
413
|
+
"""
|
|
414
|
+
if self._degree is not None:
|
|
415
|
+
return
|
|
416
|
+
if not self._phis:
|
|
417
|
+
self._degree = ZZ.zero()
|
|
418
|
+
elif len(self._phis) == 1:
|
|
419
|
+
self._degree = self._phis[0].degree()
|
|
420
|
+
else:
|
|
421
|
+
#TODO In some cases it would probably be faster to simply
|
|
422
|
+
# compute the kernel polynomial using the addition formulas?
|
|
423
|
+
from sage.rings.finite_rings.integer_mod import Mod
|
|
424
|
+
|
|
425
|
+
lo, hi = self._degree_bounds()
|
|
426
|
+
M = hi - lo + 1
|
|
427
|
+
rem = Mod(0,1)
|
|
428
|
+
for l in Primes():
|
|
429
|
+
if rem.modulus() >= M:
|
|
430
|
+
break
|
|
431
|
+
try:
|
|
432
|
+
P = point_of_order(self._domain, l)
|
|
433
|
+
except ValueError:
|
|
434
|
+
continue # supersingular and l == p
|
|
435
|
+
|
|
436
|
+
Q = self.dual()._eval(self._eval(P))
|
|
437
|
+
d = discrete_log(Q, P, ord=l, operation='+')
|
|
438
|
+
rem = rem.crt(Mod(d-lo, l))
|
|
439
|
+
|
|
440
|
+
self._degree = lo + rem.lift()
|
|
441
|
+
self.dual()._degree = self._degree
|
|
442
|
+
|
|
443
|
+
@staticmethod
|
|
444
|
+
def _comparison_impl(left, right, op):
|
|
445
|
+
r"""
|
|
446
|
+
Compare a sum morphism to another elliptic-curve morphism.
|
|
447
|
+
|
|
448
|
+
Called by :meth:`EllipticCurveHom._richcmp_`.
|
|
449
|
+
|
|
450
|
+
If possible, we use
|
|
451
|
+
:func:`~sage.schemes.elliptic_curves.hom.compare_via_evaluation`.
|
|
452
|
+
The complexity in that case is polynomial in the logarithm of
|
|
453
|
+
the degree.
|
|
454
|
+
|
|
455
|
+
TESTS::
|
|
456
|
+
|
|
457
|
+
sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum
|
|
458
|
+
sage: E = EllipticCurve(GF(419^2), [1,0])
|
|
459
|
+
sage: i = E.automorphisms()[-1]
|
|
460
|
+
sage: j = E.frobenius_isogeny()
|
|
461
|
+
sage: i + j == j + i # needs sage.symbolic
|
|
462
|
+
True
|
|
463
|
+
"""
|
|
464
|
+
from sage.structure.richcmp import op_EQ
|
|
465
|
+
if op != op_EQ:
|
|
466
|
+
return NotImplemented
|
|
467
|
+
try:
|
|
468
|
+
return compare_via_evaluation(left, right)
|
|
469
|
+
except NotImplementedError:
|
|
470
|
+
return NotImplemented
|
|
471
|
+
|
|
472
|
+
def degree(self):
|
|
473
|
+
r"""
|
|
474
|
+
Return the degree of this sum morphism.
|
|
475
|
+
|
|
476
|
+
EXAMPLES::
|
|
477
|
+
|
|
478
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
479
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
480
|
+
sage: (phi + phi).degree()
|
|
481
|
+
28
|
|
482
|
+
|
|
483
|
+
This method yields a simple toy point-counting algorithm::
|
|
484
|
+
|
|
485
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
486
|
+
sage: m1 = E.scalar_multiplication(1)
|
|
487
|
+
sage: pi = E.frobenius_endomorphism()
|
|
488
|
+
sage: (pi - m1).degree()
|
|
489
|
+
119
|
|
490
|
+
sage: E.count_points()
|
|
491
|
+
119
|
|
492
|
+
|
|
493
|
+
ALGORITHM: Essentially Schoof's algorithm; see :meth:`_compute_degree`.
|
|
494
|
+
"""
|
|
495
|
+
if self._degree is None:
|
|
496
|
+
self._compute_degree()
|
|
497
|
+
return self._degree
|
|
498
|
+
|
|
499
|
+
def rational_maps(self):
|
|
500
|
+
r"""
|
|
501
|
+
Return the rational maps of this sum morphism.
|
|
502
|
+
|
|
503
|
+
EXAMPLES::
|
|
504
|
+
|
|
505
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
506
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
507
|
+
sage: (phi + phi).rational_maps()
|
|
508
|
+
((5*x^28 + 43*x^27 + 26*x^26 - ... + 7*x^2 - 23*x + 38)/(23*x^27 + 16*x^26 + 9*x^25 + ... - 43*x^2 - 22*x + 37),
|
|
509
|
+
(42*x^42*y - 44*x^41*y - 22*x^40*y + ... - 26*x^2*y - 50*x*y - 18*y)/(-24*x^42 - 47*x^41 - 12*x^40 + ... + 18*x^2 - 48*x + 18))
|
|
510
|
+
|
|
511
|
+
ALGORITHM: :meth:`to_isogeny_chain`.
|
|
512
|
+
"""
|
|
513
|
+
#TODO In some cases it would probably be faster to compute this
|
|
514
|
+
# directly using the addition formulas?
|
|
515
|
+
return self.to_isogeny_chain().rational_maps()
|
|
516
|
+
|
|
517
|
+
def x_rational_map(self):
|
|
518
|
+
r"""
|
|
519
|
+
Return the `x`-coordinate rational map of this sum morphism.
|
|
520
|
+
|
|
521
|
+
EXAMPLES::
|
|
522
|
+
|
|
523
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
524
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
525
|
+
sage: (phi + phi).x_rational_map()
|
|
526
|
+
(9*x^28 + 37*x^27 + 67*x^26 + ... + 53*x^2 + 100*x + 28)/(x^27 + 49*x^26 + 97*x^25 + ... + 64*x^2 + 21*x + 6)
|
|
527
|
+
|
|
528
|
+
ALGORITHM: :meth:`to_isogeny_chain`.
|
|
529
|
+
"""
|
|
530
|
+
#TODO In some cases it would probably be faster to compute this
|
|
531
|
+
# directly using the addition formulas?
|
|
532
|
+
return self.to_isogeny_chain().x_rational_map()
|
|
533
|
+
|
|
534
|
+
def kernel_polynomial(self):
|
|
535
|
+
r"""
|
|
536
|
+
Return the kernel polynomial of this sum morphism.
|
|
537
|
+
|
|
538
|
+
EXAMPLES::
|
|
539
|
+
|
|
540
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
541
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
542
|
+
sage: (phi + phi).kernel_polynomial()
|
|
543
|
+
x^15 + 75*x^14 + 16*x^13 + 59*x^12 + 28*x^11 + 60*x^10 + 69*x^9 + 79*x^8 + 79*x^7 + 52*x^6 + 35*x^5 + 11*x^4 + 37*x^3 + 69*x^2 + 66*x + 63
|
|
544
|
+
|
|
545
|
+
::
|
|
546
|
+
|
|
547
|
+
sage: E = EllipticCurve(GF(11), [5,5])
|
|
548
|
+
sage: pi = E.frobenius_endomorphism()
|
|
549
|
+
sage: m1 = E.scalar_multiplication(1)
|
|
550
|
+
sage: (pi - m1).kernel_polynomial()
|
|
551
|
+
x^9 + 7*x^8 + 2*x^7 + 4*x^6 + 10*x^4 + 4*x^3 + 9*x^2 + 7*x
|
|
552
|
+
|
|
553
|
+
ALGORITHM: :meth:`to_isogeny_chain`.
|
|
554
|
+
"""
|
|
555
|
+
#TODO In some cases it would probably be faster to compute this
|
|
556
|
+
# directly using the addition formulas?
|
|
557
|
+
return self.to_isogeny_chain().kernel_polynomial()
|
|
558
|
+
|
|
559
|
+
def scaling_factor(self):
|
|
560
|
+
r"""
|
|
561
|
+
Return the Weierstrass scaling factor associated to this
|
|
562
|
+
sum morphism.
|
|
563
|
+
|
|
564
|
+
The scaling factor is the constant `u` (in the base field)
|
|
565
|
+
such that `\varphi^* \omega_2 = u \omega_1`, where
|
|
566
|
+
`\varphi: E_1\to E_2` is this morphism and `\omega_i` are
|
|
567
|
+
the standard Weierstrass differentials on `E_i` defined by
|
|
568
|
+
`\mathrm dx/(2y+a_1x+a_3)`.
|
|
569
|
+
|
|
570
|
+
EXAMPLES::
|
|
571
|
+
|
|
572
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
573
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
574
|
+
sage: phi.scaling_factor()
|
|
575
|
+
84
|
|
576
|
+
sage: (phi + phi).scaling_factor()
|
|
577
|
+
67
|
|
578
|
+
|
|
579
|
+
ALGORITHM: The scaling factor is additive under addition
|
|
580
|
+
of elliptic-curve morphisms, so we simply add together the
|
|
581
|
+
scaling factors of the :meth:`summands`.
|
|
582
|
+
"""
|
|
583
|
+
return sum(phi.scaling_factor() for phi in self._phis)
|
|
584
|
+
|
|
585
|
+
@cached_method
|
|
586
|
+
def dual(self):
|
|
587
|
+
r"""
|
|
588
|
+
Return the dual of this sum morphism.
|
|
589
|
+
|
|
590
|
+
EXAMPLES::
|
|
591
|
+
|
|
592
|
+
sage: E = EllipticCurve(GF(101), [5,5])
|
|
593
|
+
sage: phi = E.isogenies_prime_degree(7)[0]
|
|
594
|
+
sage: (phi + phi).dual()
|
|
595
|
+
Sum morphism:
|
|
596
|
+
From: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
|
|
597
|
+
To: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
|
|
598
|
+
Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101)
|
|
599
|
+
sage: (phi + phi).dual() == phi.dual() + phi.dual() # needs sage.symbolic
|
|
600
|
+
True
|
|
601
|
+
|
|
602
|
+
::
|
|
603
|
+
|
|
604
|
+
sage: E = EllipticCurve(GF(431^2), [1,0])
|
|
605
|
+
sage: iota = E.automorphisms()[2]
|
|
606
|
+
sage: m2 = E.scalar_multiplication(2)
|
|
607
|
+
sage: endo = m2 + iota
|
|
608
|
+
sage: endo.dual()
|
|
609
|
+
Sum morphism:
|
|
610
|
+
From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
|
|
611
|
+
To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
|
|
612
|
+
Via: (Scalar-multiplication endomorphism [2] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2, Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
|
|
613
|
+
Via: (u,r,s,t) = (8*z2 + 427, 0, 0, 0))
|
|
614
|
+
sage: endo.dual() == (m2 - iota) # needs sage.symbolic
|
|
615
|
+
True
|
|
616
|
+
|
|
617
|
+
ALGORITHM: Taking the dual distributes over addition.
|
|
618
|
+
"""
|
|
619
|
+
psi = EllipticCurveHom_sum((phi.dual() for phi in self._phis),
|
|
620
|
+
domain=self._codomain, codomain=self._domain)
|
|
621
|
+
psi._degree = self._degree
|
|
622
|
+
if self.trace.is_in_cache():
|
|
623
|
+
psi.trace.set_cache(-self.trace.cache)
|
|
624
|
+
psi.dual.set_cache(self)
|
|
625
|
+
return psi
|
|
626
|
+
|
|
627
|
+
@cached_method
|
|
628
|
+
def inseparable_degree(self):
|
|
629
|
+
r"""
|
|
630
|
+
Compute the inseparable degree of this sum morphism.
|
|
631
|
+
|
|
632
|
+
EXAMPLES::
|
|
633
|
+
|
|
634
|
+
sage: E = EllipticCurve(GF(7), [0,1])
|
|
635
|
+
sage: m3 = E.scalar_multiplication(3)
|
|
636
|
+
sage: m3.inseparable_degree()
|
|
637
|
+
1
|
|
638
|
+
sage: m4 = E.scalar_multiplication(4)
|
|
639
|
+
sage: m7 = m3 + m4; m7
|
|
640
|
+
Sum morphism:
|
|
641
|
+
From: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
|
|
642
|
+
To: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
|
|
643
|
+
Via: (Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7, Scalar-multiplication endomorphism [4] of Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7)
|
|
644
|
+
sage: m7.degree()
|
|
645
|
+
49
|
|
646
|
+
sage: m7.inseparable_degree()
|
|
647
|
+
7
|
|
648
|
+
|
|
649
|
+
A supersingular example::
|
|
650
|
+
|
|
651
|
+
sage: E = EllipticCurve(GF(7), [1,0])
|
|
652
|
+
sage: m3 = E.scalar_multiplication(3)
|
|
653
|
+
sage: m3.inseparable_degree()
|
|
654
|
+
1
|
|
655
|
+
sage: m4 = E.scalar_multiplication(4)
|
|
656
|
+
sage: m7 = m3 + m4; m7
|
|
657
|
+
Sum morphism:
|
|
658
|
+
From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7
|
|
659
|
+
To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7
|
|
660
|
+
Via: (Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7, Scalar-multiplication endomorphism [4] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7)
|
|
661
|
+
sage: m7.inseparable_degree()
|
|
662
|
+
49
|
|
663
|
+
"""
|
|
664
|
+
if self.is_zero():
|
|
665
|
+
raise ValueError('zero morphism is not an isogeny')
|
|
666
|
+
|
|
667
|
+
p = self.base_ring().characteristic()
|
|
668
|
+
if not p:
|
|
669
|
+
return ZZ.one()
|
|
670
|
+
|
|
671
|
+
m = self.degree().valuation(p)
|
|
672
|
+
if not m:
|
|
673
|
+
return ZZ.one()
|
|
674
|
+
|
|
675
|
+
try:
|
|
676
|
+
P = point_of_order(self.domain(), p**m)
|
|
677
|
+
except ValueError:
|
|
678
|
+
# supersingular; every p-isogeny is purely inseparable
|
|
679
|
+
return p**m
|
|
680
|
+
|
|
681
|
+
Q = self._eval(P)
|
|
682
|
+
return order_from_multiple(Q, p**m)
|