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,49 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
"""
|
|
3
|
+
Exported elliptic curves functionality
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# *****************************************************************************
|
|
7
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
8
|
+
#
|
|
9
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
10
|
+
#
|
|
11
|
+
# This code is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14
|
+
# General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# The full text of the GPL is available at:
|
|
17
|
+
#
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
# *****************************************************************************
|
|
20
|
+
|
|
21
|
+
from sage.schemes.elliptic_curves.constructor import (EllipticCurve,
|
|
22
|
+
EllipticCurve_from_c4c6,
|
|
23
|
+
EllipticCurve_from_j,
|
|
24
|
+
EllipticCurve_from_cubic,
|
|
25
|
+
EllipticCurves_with_good_reduction_outside_S)
|
|
26
|
+
|
|
27
|
+
from sage.misc.lazy_import import lazy_import
|
|
28
|
+
lazy_import('sage.schemes.elliptic_curves.jacobian', 'Jacobian')
|
|
29
|
+
|
|
30
|
+
lazy_import('sage.schemes.elliptic_curves.ell_finite_field', 'special_supersingular_curve')
|
|
31
|
+
lazy_import('sage.schemes.elliptic_curves.ell_rational_field',
|
|
32
|
+
['cremona_curves', 'cremona_optimal_curves'])
|
|
33
|
+
|
|
34
|
+
from sage.schemes.elliptic_curves.ell_finite_field import EllipticCurve_with_prime_order
|
|
35
|
+
from sage.schemes.elliptic_curves.cm import (cm_orders,
|
|
36
|
+
cm_j_invariants,
|
|
37
|
+
cm_j_invariants_and_orders,
|
|
38
|
+
hilbert_class_polynomial)
|
|
39
|
+
|
|
40
|
+
lazy_import('sage.schemes.elliptic_curves.ec_database', 'elliptic_curves')
|
|
41
|
+
|
|
42
|
+
from sage.schemes.elliptic_curves.kodaira_symbol import KodairaSymbol
|
|
43
|
+
|
|
44
|
+
from sage.schemes.elliptic_curves.ell_curve_isogeny import EllipticCurveIsogeny, isogeny_codomain_from_kernel
|
|
45
|
+
|
|
46
|
+
lazy_import('sage.schemes.elliptic_curves.mod_poly', 'classical_modular_polynomial')
|
|
47
|
+
|
|
48
|
+
from sage.schemes.elliptic_curves.heegner import heegner_points, heegner_point
|
|
49
|
+
del lazy_import
|
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
# sage.doctest: needs sage.rings.finite_rings
|
|
3
|
+
"""
|
|
4
|
+
Specific algorithms to compute cardinality of elliptic curves over a finite field
|
|
5
|
+
|
|
6
|
+
Since point counting now uses PARI/GP, this code is only used when a
|
|
7
|
+
specific algorithm was specified or when the j-invariant lies in a subfield.
|
|
8
|
+
|
|
9
|
+
AUTHORS:
|
|
10
|
+
|
|
11
|
+
- John Cremona (2008-2009): Original point counting code
|
|
12
|
+
|
|
13
|
+
- Jeroen Demeyer (2017-2018): Refactored and moved to ``cardinality.py``.
|
|
14
|
+
"""
|
|
15
|
+
# ****************************************************************************
|
|
16
|
+
# Copyright (C) 2008-2009 John Cremona
|
|
17
|
+
#
|
|
18
|
+
# This program is free software: you can redistribute it and/or modify
|
|
19
|
+
# it under the terms of the GNU General Public License as published by
|
|
20
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
21
|
+
# (at your option) any later version.
|
|
22
|
+
# https://www.gnu.org/licenses/
|
|
23
|
+
# ****************************************************************************
|
|
24
|
+
from .constructor import EllipticCurve, EllipticCurve_from_j
|
|
25
|
+
from sage.schemes.curves.projective_curve import Hasse_bounds
|
|
26
|
+
from sage.rings.integer import Integer
|
|
27
|
+
from sage.rings.integer_ring import ZZ
|
|
28
|
+
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
|
|
29
|
+
from sage.rings.polynomial.polynomial_ring import polygen
|
|
30
|
+
from sage.groups.generic import order_from_bounds
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _cardinality_with_j_invariant_1728(self):
|
|
34
|
+
r"""
|
|
35
|
+
Special function to compute cardinality when j=1728.
|
|
36
|
+
|
|
37
|
+
EXAMPLES::
|
|
38
|
+
|
|
39
|
+
sage: from sage.schemes.elliptic_curves.cardinality import _cardinality_with_j_invariant_1728
|
|
40
|
+
|
|
41
|
+
An example with q=p=1 (mod 4)::
|
|
42
|
+
|
|
43
|
+
sage: F = GF(10009)
|
|
44
|
+
sage: [_cardinality_with_j_invariant_1728(EllipticCurve(F, [0,0,0,11^i,0]))
|
|
45
|
+
....: for i in range(4)]
|
|
46
|
+
[10016, 10210, 10004, 9810]
|
|
47
|
+
|
|
48
|
+
An example with q=p=3 (mod 4)::
|
|
49
|
+
|
|
50
|
+
sage: F = GF(10007)
|
|
51
|
+
sage: [_cardinality_with_j_invariant_1728(EllipticCurve(F, [0,0,0,5^i,0]))
|
|
52
|
+
....: for i in range(4)]
|
|
53
|
+
[10008, 10008, 10008, 10008]
|
|
54
|
+
|
|
55
|
+
An example with `q=p^2`, p=3 (mod 4)::
|
|
56
|
+
|
|
57
|
+
sage: F.<a> = GF(10007^2,'a')
|
|
58
|
+
sage: [_cardinality_with_j_invariant_1728(EllipticCurve(F,[0,0,0,a^i,0]))
|
|
59
|
+
....: for i in range(4)]
|
|
60
|
+
[100160064, 100140050, 100120036, 100140050]
|
|
61
|
+
|
|
62
|
+
Examples with `q=2^d`, d odd (3 isomorphism classes)::
|
|
63
|
+
|
|
64
|
+
sage: F.<a> = GF(2**15,'a')
|
|
65
|
+
sage: ais = [[0,0,1,0,0],[0,0,1,1,0],[0,0,1,1,1]]
|
|
66
|
+
sage: curves = [EllipticCurve(F,ai) for ai in ais]
|
|
67
|
+
sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves)
|
|
68
|
+
True
|
|
69
|
+
sage: [_cardinality_with_j_invariant_1728(e) for e in curves]
|
|
70
|
+
[32769, 33025, 32513]
|
|
71
|
+
|
|
72
|
+
Examples with `q=2^d`, d even (7 isomorphism classes)::
|
|
73
|
+
|
|
74
|
+
sage: F.<a> = GF(2**16,'a')
|
|
75
|
+
sage: b = a^11 # trace 1
|
|
76
|
+
sage: ais = [[0,0,1,0,0], [0,0,1,0,b], [0,0,1,b,0], [0,0,a,0,0],
|
|
77
|
+
....: [0,0,a,0,a^2*b], [0,0,a^2,0,0], [0,0,a^2,0,a^4*b]]
|
|
78
|
+
sage: curves = [EllipticCurve(F, ai) for ai in ais]
|
|
79
|
+
sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves)
|
|
80
|
+
True
|
|
81
|
+
sage: [_cardinality_with_j_invariant_1728(e) for e in curves]
|
|
82
|
+
[65025, 66049, 65537, 65793, 65281, 65793, 65281]
|
|
83
|
+
|
|
84
|
+
Examples with `q=3^d`, d odd (4 isomorphism classes)::
|
|
85
|
+
|
|
86
|
+
sage: F.<a> = GF(3**15,'a')
|
|
87
|
+
sage: b = a^7 # has trace 1
|
|
88
|
+
sage: ais = [[0,0,0,1,0], [0,0,0,-1,0], [0,0,0,-1,b], [0,0,0,-1,-b]]
|
|
89
|
+
sage: curves = [EllipticCurve(F, ai) for ai in ais]
|
|
90
|
+
sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves)
|
|
91
|
+
True
|
|
92
|
+
sage: [_cardinality_with_j_invariant_1728(e) for e in curves]
|
|
93
|
+
[14348908, 14348908, 14342347, 14355469]
|
|
94
|
+
|
|
95
|
+
Examples with `q=3^d`, d even (6 isomorphism classes)::
|
|
96
|
+
|
|
97
|
+
sage: F.<g> = GF(3^18,'g')
|
|
98
|
+
sage: i = F(-1).sqrt()
|
|
99
|
+
sage: a = g^8 # has trace 1
|
|
100
|
+
sage: ais = [[0,0,0,1,0], [0,0,0,1,i*a], [0,0,0,g,0],
|
|
101
|
+
....: [0,0,0,g^3,0], [0,0,0,g^2,0], [0,0,0,g^2,i*a*g^3]]
|
|
102
|
+
sage: curves = [EllipticCurve(F, ai) for ai in ais]
|
|
103
|
+
sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves)
|
|
104
|
+
True
|
|
105
|
+
sage: [_cardinality_with_j_invariant_1728(e) for e in curves]
|
|
106
|
+
[387459856, 387400807, 387420490, 387420490, 387381124, 387440173]
|
|
107
|
+
|
|
108
|
+
TESTS:
|
|
109
|
+
|
|
110
|
+
Check that a bug noted at :issue:`15667` is fixed::
|
|
111
|
+
|
|
112
|
+
sage: F.<a> = GF(3^6,'a')
|
|
113
|
+
sage: EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1]).cardinality()
|
|
114
|
+
784
|
|
115
|
+
sage: EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1]).cardinality_exhaustive()
|
|
116
|
+
784
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
return self._order
|
|
120
|
+
except AttributeError:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
k = self.base_ring()
|
|
124
|
+
assert self.j_invariant() == k(1728)
|
|
125
|
+
q = k.cardinality()
|
|
126
|
+
p = k.characteristic()
|
|
127
|
+
d = k.degree()
|
|
128
|
+
x = polygen(ZZ)
|
|
129
|
+
|
|
130
|
+
# p=2, j=0=1728
|
|
131
|
+
#
|
|
132
|
+
# Number of isomorphism classes is 3 (in odd degree) or 7 (in even degree)
|
|
133
|
+
#
|
|
134
|
+
if p == 2:
|
|
135
|
+
if d % 2:
|
|
136
|
+
# The 3 classes are represented, independently of d,
|
|
137
|
+
# by [0,0,1,0,0], [0,0,1,1,0], [0,0,1,1,1]
|
|
138
|
+
E = EllipticCurve(k, [0, 0, 1, 0, 0])
|
|
139
|
+
if self.is_isomorphic(E):
|
|
140
|
+
t = 0
|
|
141
|
+
else:
|
|
142
|
+
n = (d + 1) // 2
|
|
143
|
+
t = 2**n
|
|
144
|
+
n = n % 4
|
|
145
|
+
if n == 0 or n == 1:
|
|
146
|
+
t = -t
|
|
147
|
+
E = EllipticCurve(k, [0, 0, 1, 1, 1])
|
|
148
|
+
if self.is_isomorphic(E):
|
|
149
|
+
t = -t
|
|
150
|
+
else:
|
|
151
|
+
# The 7 classes are represented by E1=[0,0,1,0,0],
|
|
152
|
+
# E2=[0,0,1,0,b], E3=[0,0,1,b,0], E4=[0,0,a,0,0],
|
|
153
|
+
# E4=[0,0,a,0,a^2*b], E6=[0,0,a^2,0,0],
|
|
154
|
+
# E7=[0,0,a^2,0,a^4*b], where a is a non-cube and b
|
|
155
|
+
# has trace 1. E1's Frobenius is pi=(-2)**(d//2); the
|
|
156
|
+
# Frobeniuses are then pi, -pi, 0; w*pi, -w*pi;
|
|
157
|
+
# w^2*pi, -w^2*pi where w is either cube root of
|
|
158
|
+
# unity, so the traces are 2*pi, -2*pi, 0, -pi, +pi;
|
|
159
|
+
# -pi, +pi.
|
|
160
|
+
delta = self.discriminant()
|
|
161
|
+
discube = (delta**((q - 1) // 3) == k(1))
|
|
162
|
+
pi = (-2)**(d // 2)
|
|
163
|
+
if discube:
|
|
164
|
+
a = k.gen()
|
|
165
|
+
b = a
|
|
166
|
+
while b.trace() == 0:
|
|
167
|
+
b *= a
|
|
168
|
+
if self.is_isomorphic(EllipticCurve(k, [0, 0, 1, b, 0])):
|
|
169
|
+
t = 0
|
|
170
|
+
else:
|
|
171
|
+
t = 2 * pi
|
|
172
|
+
if not self.is_isomorphic(EllipticCurve(k, [0, 0, 1, 0, 0])):
|
|
173
|
+
t = -t
|
|
174
|
+
|
|
175
|
+
else:
|
|
176
|
+
t = pi
|
|
177
|
+
if self.is_isomorphic(EllipticCurve(k, [0, 0, delta, 0, 0])):
|
|
178
|
+
t = -t
|
|
179
|
+
|
|
180
|
+
# p=3, j=0=1728
|
|
181
|
+
#
|
|
182
|
+
# Number of isomorphism classes is 4 (odd degree) or 6 (even degree)
|
|
183
|
+
#
|
|
184
|
+
elif p == 3:
|
|
185
|
+
if d % 2:
|
|
186
|
+
# The 4 classes are represented by [0,0,0,1,0],
|
|
187
|
+
# [0,0,0,-1,0], [0,0,0,-1,a], [0,0,0,-1,-a] where a
|
|
188
|
+
# has trace 1
|
|
189
|
+
delta = self.discriminant()
|
|
190
|
+
if (-delta).is_square():
|
|
191
|
+
t = 0
|
|
192
|
+
else:
|
|
193
|
+
u = delta.sqrt()
|
|
194
|
+
if not u.is_square():
|
|
195
|
+
u = -u
|
|
196
|
+
tr = ((self.a3()**2 + self.a6()) / u).trace()
|
|
197
|
+
if tr == 0:
|
|
198
|
+
t = 0
|
|
199
|
+
else:
|
|
200
|
+
d2 = (d + 1) // 2
|
|
201
|
+
t = 3**d2
|
|
202
|
+
if d2 % 2:
|
|
203
|
+
t = -t
|
|
204
|
+
if tr == -1:
|
|
205
|
+
t = -t
|
|
206
|
+
else:
|
|
207
|
+
# The 6 classes are represented by: [0,0,0,1,0],
|
|
208
|
+
# [0,0,0,1,i*a]; [0,0,0,g,0], [0,0,0,g^3,0];
|
|
209
|
+
# [0,0,0,g^2,0], [0,0,0,g^2,i*a*g^3]; where g
|
|
210
|
+
# generates the multiplicative group modulo 4th
|
|
211
|
+
# powers, and a has nonzero trace.
|
|
212
|
+
|
|
213
|
+
# The curve is isomorphic to [0,0,0,A4,A6]
|
|
214
|
+
|
|
215
|
+
A4 = self.a4() - self.a1() * self.a3() # = -b4 = 2*b4
|
|
216
|
+
if A4.is_square():
|
|
217
|
+
u = A4.sqrt()
|
|
218
|
+
t = (-3)**(d // 2)
|
|
219
|
+
i = k(-1).sqrt()
|
|
220
|
+
A6 = self.a3()**2 + self.a6() # = b6
|
|
221
|
+
if (A6 / (i * u * A4)).trace() == 0:
|
|
222
|
+
t *= 2
|
|
223
|
+
else:
|
|
224
|
+
t *= -1
|
|
225
|
+
if not u.is_square():
|
|
226
|
+
t *= -1
|
|
227
|
+
else:
|
|
228
|
+
t = 0
|
|
229
|
+
|
|
230
|
+
# p>3, j=1728
|
|
231
|
+
#
|
|
232
|
+
# Number of isomorphism classes is 4 if q=1 (mod 4), else 2
|
|
233
|
+
#
|
|
234
|
+
elif p % 4 == 3:
|
|
235
|
+
if d % 2:
|
|
236
|
+
t = 0
|
|
237
|
+
else:
|
|
238
|
+
t = (-p)**(d // 2)
|
|
239
|
+
w = (self.c4() / k(48))**((q - 1) // 4)
|
|
240
|
+
if w == 1:
|
|
241
|
+
t = 2 * t
|
|
242
|
+
elif w == -1:
|
|
243
|
+
t = -2 * t
|
|
244
|
+
else:
|
|
245
|
+
t = 0
|
|
246
|
+
|
|
247
|
+
# p=1 (mod 4). First find Frobenius pi=a+b*i for [0,0,0,-1,0] over GF(p):
|
|
248
|
+
# N(pi)=p and N(pi-1)=0 (mod 8).
|
|
249
|
+
#
|
|
250
|
+
else:
|
|
251
|
+
R = ZZ.extension(x**2 + 1, 'i')
|
|
252
|
+
i = R.gen(1)
|
|
253
|
+
pi = R.fraction_field().factor(p)[0][0].gens_reduced()[0]
|
|
254
|
+
a, b = pi.list()
|
|
255
|
+
if a % 2 == 0:
|
|
256
|
+
a, b = -b, a
|
|
257
|
+
if (a + b + 1) % 4 == 0:
|
|
258
|
+
a, b = -a, -b
|
|
259
|
+
pi = a + b * i # Now pi=a+b*i with (a,b)=(1,0),(3,2) mod 4
|
|
260
|
+
|
|
261
|
+
# Lift to Frobenius for [0,0,0,-1,0] over GF(p^d):
|
|
262
|
+
if d > 1:
|
|
263
|
+
pi = pi**d
|
|
264
|
+
a, b = pi.list()
|
|
265
|
+
|
|
266
|
+
# Compute appropriate quartic twist:
|
|
267
|
+
w = (self.c4() / k(48))**((q - 1) // 4)
|
|
268
|
+
if w == 1:
|
|
269
|
+
t = 2 * a
|
|
270
|
+
elif w == -1:
|
|
271
|
+
t = -2 * a
|
|
272
|
+
elif k(b) == w * k(a):
|
|
273
|
+
t = 2 * b
|
|
274
|
+
else:
|
|
275
|
+
t = -2 * b
|
|
276
|
+
|
|
277
|
+
return Integer(q + 1 - t)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _cardinality_with_j_invariant_0(self):
|
|
281
|
+
r"""
|
|
282
|
+
Special function to compute cardinality when j=0.
|
|
283
|
+
|
|
284
|
+
EXAMPLES::
|
|
285
|
+
|
|
286
|
+
sage: from sage.schemes.elliptic_curves.cardinality import _cardinality_with_j_invariant_0
|
|
287
|
+
|
|
288
|
+
An example with q=p=1 (mod 6)::
|
|
289
|
+
|
|
290
|
+
sage: F = GF(1009)
|
|
291
|
+
sage: [_cardinality_with_j_invariant_0(EllipticCurve(F,[0,0,0,0,11^i])) for i in range(6)]
|
|
292
|
+
[948, 967, 1029, 1072, 1053, 991]
|
|
293
|
+
|
|
294
|
+
An example with q=p=5 (mod 6)::
|
|
295
|
+
|
|
296
|
+
sage: F = GF(1013)
|
|
297
|
+
sage: [_cardinality_with_j_invariant_0(EllipticCurve(F,[0,0,0,0,3^i])) for i in range(6)]
|
|
298
|
+
[1014, 1014, 1014, 1014, 1014, 1014]
|
|
299
|
+
|
|
300
|
+
An example with `q=p^2`, p=5 (mod 6)::
|
|
301
|
+
|
|
302
|
+
sage: F.<a> = GF(1013^2,'a')
|
|
303
|
+
sage: [_cardinality_with_j_invariant_0(EllipticCurve(F,[0,0,0,0,a^i])) for i in range(6)]
|
|
304
|
+
[1028196, 1027183, 1025157, 1024144, 1025157, 1027183]
|
|
305
|
+
|
|
306
|
+
For examples in characteristic 2 and 3, see the function
|
|
307
|
+
:func:`_cardinality_with_j_invariant_1728`.
|
|
308
|
+
"""
|
|
309
|
+
k = self.base_ring()
|
|
310
|
+
assert self.j_invariant() == k.zero()
|
|
311
|
+
p = k.characteristic()
|
|
312
|
+
if p == 2 or p == 3: # then 0==1728
|
|
313
|
+
return _cardinality_with_j_invariant_1728(self)
|
|
314
|
+
|
|
315
|
+
q = k.cardinality()
|
|
316
|
+
d = k.degree()
|
|
317
|
+
x = polygen(ZZ)
|
|
318
|
+
|
|
319
|
+
# p>3, j=0
|
|
320
|
+
#
|
|
321
|
+
# Number of isomorphism classes is 4 if q=1 (mod 4), else 2
|
|
322
|
+
#
|
|
323
|
+
if p % 6 == 5:
|
|
324
|
+
if d % 2:
|
|
325
|
+
t = 0
|
|
326
|
+
else:
|
|
327
|
+
t = (-p)**(d // 2)
|
|
328
|
+
w = (self.c6() / k(-864))**((q - 1) // 6)
|
|
329
|
+
if w == 1:
|
|
330
|
+
t = 2 * t
|
|
331
|
+
elif w == -1:
|
|
332
|
+
t = -2 * t
|
|
333
|
+
elif w**3 == 1:
|
|
334
|
+
t = -t
|
|
335
|
+
|
|
336
|
+
# p=1 (mod 6). First find Frobenius pi=a+b*w for [0,0,0,0,1] over GF(p):
|
|
337
|
+
# N(pi)=p and N(pi-1)=0 (mod 12).
|
|
338
|
+
#
|
|
339
|
+
else:
|
|
340
|
+
R = ZZ.extension(x**2 - x + 1, 'zeta6')
|
|
341
|
+
zeta6 = R.gen(1)
|
|
342
|
+
pi = R.fraction_field().factor(p)[0][0].gens_reduced()[0]
|
|
343
|
+
while (pi - 1).norm() % 12:
|
|
344
|
+
pi *= zeta6
|
|
345
|
+
a, b = pi.list()
|
|
346
|
+
z = k(-b) / k(a) # a *specific* 6th root of unity in k
|
|
347
|
+
|
|
348
|
+
# Now pi=a+b*zeta6 with N(pi-1)=0 (mod 12)
|
|
349
|
+
|
|
350
|
+
# Lift to Frobenius for [0,0,0,0,1] over GF(p^d):
|
|
351
|
+
if d > 1:
|
|
352
|
+
pi = pi**d
|
|
353
|
+
a, b = pi.list()
|
|
354
|
+
|
|
355
|
+
# Compute appropriate sextic twist:
|
|
356
|
+
w = (self.c6() / k(-864))**((q - 1) // 6)
|
|
357
|
+
|
|
358
|
+
if w == 1:
|
|
359
|
+
t = 2 * a + b # = Trace(pi)
|
|
360
|
+
elif w == -1:
|
|
361
|
+
t = -2 * a - b # = Trace(-pi)
|
|
362
|
+
elif w == z:
|
|
363
|
+
t = a - b # = Trace(pi*zeta6)
|
|
364
|
+
elif w == z**2:
|
|
365
|
+
t = -a - 2 * b # = Trace(pi*zeta6**2)
|
|
366
|
+
elif w == z**4:
|
|
367
|
+
t = b - a # = Trace(pi*zeta6**4)
|
|
368
|
+
elif w == z**5:
|
|
369
|
+
t = a + 2 * b # = Trace(pi*zeta6**5)
|
|
370
|
+
|
|
371
|
+
return Integer(q + 1 - t)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def cardinality_exhaustive(self):
|
|
375
|
+
r"""
|
|
376
|
+
Return the cardinality of ``self`` over the base field.
|
|
377
|
+
|
|
378
|
+
This simply adds up the number of points with each x-coordinate:
|
|
379
|
+
only used for small field sizes!
|
|
380
|
+
|
|
381
|
+
EXAMPLES::
|
|
382
|
+
|
|
383
|
+
sage: p = next_prime(10^3)
|
|
384
|
+
sage: E = EllipticCurve(GF(p), [3,4])
|
|
385
|
+
sage: E.cardinality_exhaustive()
|
|
386
|
+
1020
|
|
387
|
+
sage: E = EllipticCurve(GF(3^4,'a'), [1,1])
|
|
388
|
+
sage: E.cardinality_exhaustive()
|
|
389
|
+
64
|
|
390
|
+
"""
|
|
391
|
+
self._order = Integer(1 + sum(len(self.lift_x(x, all=True))
|
|
392
|
+
for x in self.base_field()))
|
|
393
|
+
return self._order
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def cardinality_bsgs(self, verbose=False):
|
|
397
|
+
r"""
|
|
398
|
+
Return the cardinality of ``self`` over the base field.
|
|
399
|
+
|
|
400
|
+
ALGORITHM: A variant of "Mestre's trick" extended to all finite
|
|
401
|
+
fields by Cremona and Sutherland, 2008.
|
|
402
|
+
|
|
403
|
+
.. NOTE::
|
|
404
|
+
|
|
405
|
+
1. The Mestre-Schoof-Cremona-Sutherland algorithm may fail for
|
|
406
|
+
a small finite number of curves over `F_q` for `q` at most 49, so
|
|
407
|
+
for `q<50` we use an exhaustive count.
|
|
408
|
+
|
|
409
|
+
2. Quadratic twists are not implemented in characteristic 2
|
|
410
|
+
when `j=0 (=1728)`; but this case is treated separately.
|
|
411
|
+
|
|
412
|
+
EXAMPLES::
|
|
413
|
+
|
|
414
|
+
sage: p = next_prime(10^3)
|
|
415
|
+
sage: E = EllipticCurve(GF(p), [3,4])
|
|
416
|
+
sage: E.cardinality_bsgs()
|
|
417
|
+
1020
|
|
418
|
+
sage: E = EllipticCurve(GF(3^4,'a'), [1,1])
|
|
419
|
+
sage: E.cardinality_bsgs()
|
|
420
|
+
64
|
|
421
|
+
sage: F.<a> = GF(101^3,'a')
|
|
422
|
+
sage: E = EllipticCurve([2*a^2 + 48*a + 27, 89*a^2 + 76*a + 24])
|
|
423
|
+
sage: E.cardinality_bsgs()
|
|
424
|
+
1031352
|
|
425
|
+
"""
|
|
426
|
+
E1 = self
|
|
427
|
+
k = self.base_field()
|
|
428
|
+
q = k.order()
|
|
429
|
+
if q < 50:
|
|
430
|
+
if verbose:
|
|
431
|
+
print("q=", q, "< 50 so using exhaustive count")
|
|
432
|
+
return cardinality_exhaustive(self)
|
|
433
|
+
|
|
434
|
+
# Construct the quadratic twist:
|
|
435
|
+
E2 = E1.quadratic_twist()
|
|
436
|
+
if verbose:
|
|
437
|
+
print("Quadratic twist is ", E2.ainvs())
|
|
438
|
+
|
|
439
|
+
bounds = Hasse_bounds(q)
|
|
440
|
+
lower, upper = bounds
|
|
441
|
+
B = upper - q - 1 # = floor(2*sqrt(q))
|
|
442
|
+
a = ZZ(0)
|
|
443
|
+
N1 = N2 = M = ZZ(1)
|
|
444
|
+
kmin = -B
|
|
445
|
+
kmax = B
|
|
446
|
+
q1 = q + 1
|
|
447
|
+
# Throughout, we have #E=q+1-t where |t|<=B and t=a+k*M = a
|
|
448
|
+
# (mod M) where kmin <= k <= kmax.
|
|
449
|
+
|
|
450
|
+
# M is the lcm of the orders of all the points found on E1 and
|
|
451
|
+
# E2, which will eventually exceed 2*B, at which point
|
|
452
|
+
# kmin=kmax.
|
|
453
|
+
|
|
454
|
+
if q > 2**10:
|
|
455
|
+
N1 = ZZ(2)**sum([e for P, e in E1._p_primary_torsion_basis(2)])
|
|
456
|
+
N2 = ZZ(2)**sum([e for P, e in E2._p_primary_torsion_basis(2)])
|
|
457
|
+
if q > 2**20:
|
|
458
|
+
N1 *= ZZ(3)**sum([e for P, e in E1._p_primary_torsion_basis(3)])
|
|
459
|
+
N2 *= ZZ(3)**sum([e for P, e in E2._p_primary_torsion_basis(3)])
|
|
460
|
+
if q > 2**40:
|
|
461
|
+
N1 *= ZZ(5)**sum([e for P, e in E1._p_primary_torsion_basis(5)])
|
|
462
|
+
N2 *= ZZ(5)**sum([e for P, e in E2._p_primary_torsion_basis(5)])
|
|
463
|
+
# We now know that t=q+1 (mod N1) and t=-(q+1) (mod N2)
|
|
464
|
+
a = q1
|
|
465
|
+
M = N1
|
|
466
|
+
g, u, v = M.xgcd(N2) # g==u*M+v*N2
|
|
467
|
+
if N2 > g:
|
|
468
|
+
a = (a * v * N2 - q1 * u * M) // g
|
|
469
|
+
M *= (N2 // g) # = lcm(M,N2)
|
|
470
|
+
a = a % M
|
|
471
|
+
if verbose:
|
|
472
|
+
print("(a,M)=", (a, M))
|
|
473
|
+
kmin = ((-B - a) / M).ceil()
|
|
474
|
+
kmax = ((B - a) / M).floor()
|
|
475
|
+
if kmin == kmax:
|
|
476
|
+
self._order = q1 - a - kmin * M
|
|
477
|
+
if verbose:
|
|
478
|
+
print("no random points were needed")
|
|
479
|
+
return self._order
|
|
480
|
+
if verbose:
|
|
481
|
+
print("(2,3,5)-torsion subgroup gives M=", M)
|
|
482
|
+
|
|
483
|
+
# N1, N2 are divisors of the orders of E1, E2 separately,
|
|
484
|
+
# which are used to speed up the computation of the orders of
|
|
485
|
+
# points on each curve. For large q it is worth initializing
|
|
486
|
+
# these with the full order of the (2,3,5)-torsion which are
|
|
487
|
+
# often non-trivial.
|
|
488
|
+
while kmax != kmin:
|
|
489
|
+
# Get a random point on E1 and find its order, using the
|
|
490
|
+
# Hasse bounds and the fact that we know that the group
|
|
491
|
+
# order is a multiple of N1:
|
|
492
|
+
n = order_from_bounds(E1.random_point(), bounds, N1, operation='+')
|
|
493
|
+
if verbose:
|
|
494
|
+
print("New point on E has order ", n)
|
|
495
|
+
# update N1 and M
|
|
496
|
+
N1 = N1.lcm(n)
|
|
497
|
+
g, u, v = M.xgcd(n) # g==u*M+v*n
|
|
498
|
+
if n > g:
|
|
499
|
+
# update congruence a (mod M) with q+1 (mod n)
|
|
500
|
+
a = (a * v * n + q1 * u * M) // g
|
|
501
|
+
M *= (n // g) # = lcm(M,n)
|
|
502
|
+
a = a % M
|
|
503
|
+
if verbose:
|
|
504
|
+
print("(a,M)=", (a, M))
|
|
505
|
+
kmin = ((-B - a) / M).ceil()
|
|
506
|
+
kmax = ((B - a) / M).floor()
|
|
507
|
+
if kmin == kmax:
|
|
508
|
+
self._order = q1 - a - kmin * M
|
|
509
|
+
return self._order
|
|
510
|
+
if verbose:
|
|
511
|
+
print("number of possibilities is now ", kmax - kmin + 1)
|
|
512
|
+
|
|
513
|
+
# Get a random point on E2 and find its order, using the
|
|
514
|
+
# Hasse bounds and the fact that we know that the group
|
|
515
|
+
# order is a multiple of N2:
|
|
516
|
+
n = order_from_bounds(E2.random_point(), bounds, N2, operation='+')
|
|
517
|
+
if verbose:
|
|
518
|
+
print("New point on E' has order ", n)
|
|
519
|
+
# update N2 and M
|
|
520
|
+
N2 = N2.lcm(n)
|
|
521
|
+
g, u, v = M.xgcd(n) # g==u*M+v*n
|
|
522
|
+
if n > g:
|
|
523
|
+
# update congruence a (mod M) with -(q+1) (mod n)
|
|
524
|
+
a = (a * v * n - q1 * u * M) // g
|
|
525
|
+
M *= (n // g) # = lcm(M,n)
|
|
526
|
+
a = a % M
|
|
527
|
+
if verbose:
|
|
528
|
+
print("(a,M)=", (a, M))
|
|
529
|
+
kmin = ((-B - a) / M).ceil()
|
|
530
|
+
kmax = ((B - a) / M).floor()
|
|
531
|
+
if kmin == kmax:
|
|
532
|
+
self._order = q1 - a - kmin * M
|
|
533
|
+
return self._order
|
|
534
|
+
if verbose:
|
|
535
|
+
print("number of possibilities is now ", kmax - kmin + 1)
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def _cardinality_subfield(self, jpol):
|
|
539
|
+
"""
|
|
540
|
+
Count the number of points on the elliptic curve ``self``, assuming
|
|
541
|
+
that the j-invariant lies in a subfield.
|
|
542
|
+
|
|
543
|
+
INPUT:
|
|
544
|
+
|
|
545
|
+
- ``jpol`` -- minimal polynomial (over the prime field) of the
|
|
546
|
+
j-invariant of ``self``
|
|
547
|
+
|
|
548
|
+
EXAMPLES::
|
|
549
|
+
|
|
550
|
+
sage: from sage.schemes.elliptic_curves.cardinality import _cardinality_subfield
|
|
551
|
+
sage: k.<a> = GF(7^5)
|
|
552
|
+
sage: E = EllipticCurve(k, [1,2,3,4,5]); E
|
|
553
|
+
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5
|
|
554
|
+
over Finite Field in a of size 7^5
|
|
555
|
+
sage: _cardinality_subfield(E, E.j_invariant().minimal_polynomial())
|
|
556
|
+
17019
|
|
557
|
+
|
|
558
|
+
TESTS::
|
|
559
|
+
|
|
560
|
+
sage: k.<a> = GF(2^6)
|
|
561
|
+
sage: for c in range(500): # long time
|
|
562
|
+
....: ainvs = [k.random_element() for i in range(5)]
|
|
563
|
+
....: try:
|
|
564
|
+
....: E = EllipticCurve(ainvs)
|
|
565
|
+
....: except ArithmeticError:
|
|
566
|
+
....: continue # Singular curve
|
|
567
|
+
....: jpol = E.j_invariant().minimal_polynomial()
|
|
568
|
+
....: if jpol.degree() < 6:
|
|
569
|
+
....: N1 = _cardinality_subfield(E, jpol)
|
|
570
|
+
....: N2 = pari.ellcard(E)
|
|
571
|
+
....: assert N1 == N2
|
|
572
|
+
"""
|
|
573
|
+
k = self.base_ring()
|
|
574
|
+
p = k.characteristic()
|
|
575
|
+
d = k.degree()
|
|
576
|
+
|
|
577
|
+
jdeg = jpol.degree()
|
|
578
|
+
if jdeg >= d:
|
|
579
|
+
raise ValueError("j-invariant does not lie in a subfield")
|
|
580
|
+
|
|
581
|
+
# we count points on a standard curve with the same
|
|
582
|
+
# j-invariant, defined over the field it generates, then lift
|
|
583
|
+
# to the curve's own field, and finally allow for twists
|
|
584
|
+
|
|
585
|
+
# Let j be the j-invariant as element of the smallest finite
|
|
586
|
+
# field over which j is defined.
|
|
587
|
+
GFj = GF((p, jdeg), name='j', modulus=jpol)
|
|
588
|
+
j = GFj.gen()
|
|
589
|
+
|
|
590
|
+
# Use special code for j = 0, 1728
|
|
591
|
+
if j == 1728:
|
|
592
|
+
return _cardinality_with_j_invariant_1728(self)
|
|
593
|
+
elif j == 0:
|
|
594
|
+
return _cardinality_with_j_invariant_0(self)
|
|
595
|
+
|
|
596
|
+
# Recursive call which does all the real work:
|
|
597
|
+
E0 = EllipticCurve_from_j(j)
|
|
598
|
+
N = E0.cardinality(extension_degree=d // jdeg)
|
|
599
|
+
|
|
600
|
+
# Map to the original larger field
|
|
601
|
+
phi = GFj.hom([self.j_invariant()])
|
|
602
|
+
|
|
603
|
+
# Check if we got a twist. Since j is not 0, 1728 the only twists
|
|
604
|
+
# are quadratic.
|
|
605
|
+
if self.is_isomorphic(E0.base_extend(phi)):
|
|
606
|
+
return N
|
|
607
|
+
else:
|
|
608
|
+
q = k.cardinality()
|
|
609
|
+
return 2 * (q + 1) - N
|