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,1552 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-schemes
|
|
2
|
+
"""
|
|
3
|
+
Elliptic curve constructor
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- William Stein (2005): Initial version
|
|
8
|
+
|
|
9
|
+
- John Cremona (2008-01): EllipticCurve(j) fixed for all cases
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
#*****************************************************************************
|
|
13
|
+
# Copyright (C) 2005 William Stein <wstein@gmail.com>
|
|
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
|
+
# http://www.gnu.org/licenses/
|
|
25
|
+
#*****************************************************************************
|
|
26
|
+
|
|
27
|
+
from sage.rings.integer_ring import ZZ
|
|
28
|
+
from sage.rings.rational_field import QQ
|
|
29
|
+
from sage.rings.rational_field import RationalField
|
|
30
|
+
|
|
31
|
+
import sage.rings.abc
|
|
32
|
+
from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
|
|
33
|
+
from sage.rings.number_field.number_field_base import NumberField
|
|
34
|
+
from sage.rings.finite_rings.finite_field_base import FiniteField
|
|
35
|
+
from sage.rings.polynomial.multi_polynomial import MPolynomial
|
|
36
|
+
|
|
37
|
+
from sage.categories.rings import Rings
|
|
38
|
+
from sage.categories.fields import Fields
|
|
39
|
+
_Fields = Fields()
|
|
40
|
+
|
|
41
|
+
from sage.structure.sequence import Sequence
|
|
42
|
+
from sage.structure.element import parent, Expression
|
|
43
|
+
from sage.structure.factory import UniqueFactory
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class EllipticCurveFactory(UniqueFactory):
|
|
47
|
+
r"""
|
|
48
|
+
Construct an elliptic curve.
|
|
49
|
+
|
|
50
|
+
In Sage, an elliptic curve is always specified by
|
|
51
|
+
(the coefficients of) a long Weierstrass equation
|
|
52
|
+
|
|
53
|
+
.. MATH::
|
|
54
|
+
|
|
55
|
+
y^2 + a_1 xy + a_3 y = x^3 + a_2 x^2 + a_4 x + a_6.
|
|
56
|
+
|
|
57
|
+
INPUT:
|
|
58
|
+
|
|
59
|
+
There are several ways to construct an elliptic curve:
|
|
60
|
+
|
|
61
|
+
- ``EllipticCurve([a1,a2,a3,a4,a6])``: Elliptic curve with given
|
|
62
|
+
`a`-invariants. The invariants are coerced into a common parent.
|
|
63
|
+
If all are integers, they are coerced into the rational numbers.
|
|
64
|
+
|
|
65
|
+
- ``EllipticCurve([a4,a6])``: Same as above, but `a_1=a_2=a_3=0`.
|
|
66
|
+
|
|
67
|
+
- ``EllipticCurve(label)``: Returns the elliptic curve over `\QQ`
|
|
68
|
+
from the Cremona database with the given label. The label is a
|
|
69
|
+
string, such as ``'11a'`` or ``'37b2'``. The letters in the
|
|
70
|
+
label *must* be lower case (Cremona's new labeling).
|
|
71
|
+
|
|
72
|
+
- ``EllipticCurve(R, [a1,a2,a3,a4,a6])``: Create the elliptic
|
|
73
|
+
curve over `R` with given `a`-invariants. Here `R` can be an
|
|
74
|
+
arbitrary commutative ring, although most functionality is only
|
|
75
|
+
implemented over fields.
|
|
76
|
+
|
|
77
|
+
- ``EllipticCurve(j=j0)`` or ``EllipticCurve_from_j(j0)``: Return
|
|
78
|
+
an elliptic curve with `j`-invariant ``j0``.
|
|
79
|
+
|
|
80
|
+
- ``EllipticCurve(polynomial)``: Read off the `a`-invariants from
|
|
81
|
+
the polynomial coefficients, see
|
|
82
|
+
:func:`EllipticCurve_from_Weierstrass_polynomial`.
|
|
83
|
+
|
|
84
|
+
- ``EllipticCurve(cubic, point)``: The elliptic curve defined by a
|
|
85
|
+
plane cubic (homogeneous polynomial in three variables), with a
|
|
86
|
+
rational point.
|
|
87
|
+
|
|
88
|
+
Instead of giving the coefficients as a *list* of length 2 or 5,
|
|
89
|
+
one can also give a *tuple*.
|
|
90
|
+
|
|
91
|
+
EXAMPLES:
|
|
92
|
+
|
|
93
|
+
We illustrate creating elliptic curves::
|
|
94
|
+
|
|
95
|
+
sage: EllipticCurve([0,0,1,-1,0])
|
|
96
|
+
Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
|
|
97
|
+
|
|
98
|
+
We create a curve from a Cremona label::
|
|
99
|
+
|
|
100
|
+
sage: EllipticCurve('37b2')
|
|
101
|
+
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 1873*x - 31833 over Rational Field
|
|
102
|
+
sage: EllipticCurve('5077a')
|
|
103
|
+
Elliptic Curve defined by y^2 + y = x^3 - 7*x + 6 over Rational Field
|
|
104
|
+
sage: EllipticCurve('389a')
|
|
105
|
+
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
|
|
106
|
+
|
|
107
|
+
Old Cremona labels are allowed::
|
|
108
|
+
|
|
109
|
+
sage: EllipticCurve('2400FF')
|
|
110
|
+
Elliptic Curve defined by y^2 = x^3 + x^2 + 2*x + 8 over Rational Field
|
|
111
|
+
|
|
112
|
+
Unicode labels are allowed::
|
|
113
|
+
|
|
114
|
+
sage: EllipticCurve(u'389a')
|
|
115
|
+
Elliptic Curve defined by y^2 + y = x^3 + x^2 - 2*x over Rational Field
|
|
116
|
+
|
|
117
|
+
We create curves over a finite field as follows::
|
|
118
|
+
|
|
119
|
+
sage: EllipticCurve([GF(5)(0),0,1,-1,0])
|
|
120
|
+
Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
|
|
121
|
+
sage: EllipticCurve(GF(5), [0, 0,1,-1,0])
|
|
122
|
+
Elliptic Curve defined by y^2 + y = x^3 + 4*x over Finite Field of size 5
|
|
123
|
+
|
|
124
|
+
Elliptic curves over `\ZZ/N\ZZ` with `N` prime are of type
|
|
125
|
+
"elliptic curve over a finite field"::
|
|
126
|
+
|
|
127
|
+
sage: F = Zmod(101)
|
|
128
|
+
sage: EllipticCurve(F, [2, 3])
|
|
129
|
+
Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 101
|
|
130
|
+
sage: E = EllipticCurve([F(2), F(3)])
|
|
131
|
+
sage: type(E)
|
|
132
|
+
<class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
|
|
133
|
+
sage: E.category()
|
|
134
|
+
Category of abelian varieties over Ring of integers modulo 101
|
|
135
|
+
|
|
136
|
+
In contrast, elliptic curves over `\ZZ/N\ZZ` with `N` composite
|
|
137
|
+
are of type "generic elliptic curve"::
|
|
138
|
+
|
|
139
|
+
sage: F = Zmod(95)
|
|
140
|
+
sage: EllipticCurve(F, [2, 3])
|
|
141
|
+
Elliptic Curve defined by y^2 = x^3 + 2*x + 3 over Ring of integers modulo 95
|
|
142
|
+
sage: E = EllipticCurve([F(2), F(3)])
|
|
143
|
+
sage: type(E)
|
|
144
|
+
<class 'sage.schemes.elliptic_curves.ell_generic.EllipticCurve_generic_with_category'>
|
|
145
|
+
sage: E.category()
|
|
146
|
+
Category of schemes over Ring of integers modulo 95
|
|
147
|
+
|
|
148
|
+
The following is a curve over the complex numbers::
|
|
149
|
+
|
|
150
|
+
sage: E = EllipticCurve(CC, [0,0,1,-1,0])
|
|
151
|
+
sage: E
|
|
152
|
+
Elliptic Curve defined by y^2 + 1.00000000000000*y = x^3 + (-1.00000000000000)*x
|
|
153
|
+
over Complex Field with 53 bits of precision
|
|
154
|
+
sage: E.j_invariant()
|
|
155
|
+
2988.97297297297
|
|
156
|
+
|
|
157
|
+
We can also create elliptic curves by giving the Weierstrass equation::
|
|
158
|
+
|
|
159
|
+
sage: R2.<x,y> = PolynomialRing(QQ,2)
|
|
160
|
+
sage: EllipticCurve(y^2 + y - ( x^3 + x - 9 ))
|
|
161
|
+
Elliptic Curve defined by y^2 + y = x^3 + x - 9 over Rational Field
|
|
162
|
+
|
|
163
|
+
sage: R.<x,y> = GF(5)[]
|
|
164
|
+
sage: EllipticCurve(x^3 + x^2 + 2 - y^2 - y*x)
|
|
165
|
+
Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 2 over Finite Field of size 5
|
|
166
|
+
|
|
167
|
+
We can also create elliptic curves by giving a smooth plane cubic with a rational point::
|
|
168
|
+
|
|
169
|
+
sage: R3.<x,y,z> = PolynomialRing(QQ,3)
|
|
170
|
+
sage: F = x^3 + y^3 + 30*z^3
|
|
171
|
+
sage: P = [1,-1,0]
|
|
172
|
+
sage: EllipticCurve(F,P)
|
|
173
|
+
Elliptic Curve defined by y^2 - 270*y = x^3 - 24300 over Rational Field
|
|
174
|
+
|
|
175
|
+
We can explicitly specify the `j`-invariant::
|
|
176
|
+
|
|
177
|
+
sage: E = EllipticCurve(j=1728); E; E.j_invariant(); E.label()
|
|
178
|
+
Elliptic Curve defined by y^2 = x^3 - x over Rational Field
|
|
179
|
+
1728
|
|
180
|
+
'32a2'
|
|
181
|
+
|
|
182
|
+
sage: E = EllipticCurve(j=GF(5)(2)); E; E.j_invariant()
|
|
183
|
+
Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
|
|
184
|
+
2
|
|
185
|
+
|
|
186
|
+
See :issue:`6657` ::
|
|
187
|
+
|
|
188
|
+
sage: EllipticCurve(GF(144169), j=1728) # needs sage.rings.finite_rings
|
|
189
|
+
Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 144169
|
|
190
|
+
|
|
191
|
+
Elliptic curves over the same ring with the same Weierstrass
|
|
192
|
+
coefficients are identical, even when they are constructed in
|
|
193
|
+
different ways (see :issue:`11474`)::
|
|
194
|
+
|
|
195
|
+
sage: EllipticCurve('11a3') is EllipticCurve(QQ, [0, -1, 1, 0, 0])
|
|
196
|
+
True
|
|
197
|
+
|
|
198
|
+
By default, when a rational value of `j` is given, the constructed
|
|
199
|
+
curve is a minimal twist (minimal conductor for curves with that
|
|
200
|
+
`j`-invariant). This can be changed by setting the optional
|
|
201
|
+
parameter ``minimal_twist``, which is ``True`` by default, to ``False``::
|
|
202
|
+
|
|
203
|
+
sage: EllipticCurve(j=100)
|
|
204
|
+
Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
|
|
205
|
+
sage: E =EllipticCurve(j=100); E
|
|
206
|
+
Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
|
|
207
|
+
sage: E.conductor()
|
|
208
|
+
33129800
|
|
209
|
+
sage: E.j_invariant()
|
|
210
|
+
100
|
|
211
|
+
sage: E =EllipticCurve(j=100, minimal_twist=False); E
|
|
212
|
+
Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
|
|
213
|
+
sage: E.conductor()
|
|
214
|
+
298168200
|
|
215
|
+
sage: E.j_invariant()
|
|
216
|
+
100
|
|
217
|
+
|
|
218
|
+
Without this option, constructing the curve could take a long time
|
|
219
|
+
since both `j` and `j-1728` have to be factored to compute the
|
|
220
|
+
minimal twist (see :issue:`13100`)::
|
|
221
|
+
|
|
222
|
+
sage: E = EllipticCurve_from_j(2^256+1, minimal_twist=False)
|
|
223
|
+
sage: E.j_invariant() == 2^256+1
|
|
224
|
+
True
|
|
225
|
+
|
|
226
|
+
TESTS::
|
|
227
|
+
|
|
228
|
+
sage: R = ZZ['u', 'v']
|
|
229
|
+
sage: EllipticCurve(R, [1,1])
|
|
230
|
+
Elliptic Curve defined by y^2 = x^3 + x + 1 over Multivariate Polynomial Ring in u, v
|
|
231
|
+
over Integer Ring
|
|
232
|
+
|
|
233
|
+
We create a curve and a point over ``QQbar`` (see :issue:`6879`)::
|
|
234
|
+
|
|
235
|
+
sage: E = EllipticCurve(QQbar, [0,1]) # needs sage.rings.number_field
|
|
236
|
+
sage: E(0) # needs sage.rings.number_field
|
|
237
|
+
(0 : 1 : 0)
|
|
238
|
+
sage: E.base_field() # needs sage.rings.number_field
|
|
239
|
+
Algebraic Field
|
|
240
|
+
|
|
241
|
+
sage: E = EllipticCurve(RR, [1,2]); E; E.base_field()
|
|
242
|
+
Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 2.00000000000000
|
|
243
|
+
over Real Field with 53 bits of precision
|
|
244
|
+
Real Field with 53 bits of precision
|
|
245
|
+
sage: E = EllipticCurve(CC,[3,4]); E; E.base_field()
|
|
246
|
+
Elliptic Curve defined by y^2 = x^3 + 3.00000000000000*x + 4.00000000000000
|
|
247
|
+
over Complex Field with 53 bits of precision
|
|
248
|
+
Complex Field with 53 bits of precision
|
|
249
|
+
sage: E = EllipticCurve(QQbar, [5,6]); E; E.base_field() # needs sage.rings.number_field
|
|
250
|
+
Elliptic Curve defined by y^2 = x^3 + 5*x + 6 over Algebraic Field
|
|
251
|
+
Algebraic Field
|
|
252
|
+
|
|
253
|
+
See :issue:`6657` ::
|
|
254
|
+
|
|
255
|
+
sage: EllipticCurve(3, j=1728)
|
|
256
|
+
Traceback (most recent call last):
|
|
257
|
+
...
|
|
258
|
+
ValueError: First parameter (if present) must be a ring when j is specified
|
|
259
|
+
|
|
260
|
+
sage: EllipticCurve(GF(5), j=3/5)
|
|
261
|
+
Traceback (most recent call last):
|
|
262
|
+
...
|
|
263
|
+
ValueError: First parameter must be a ring containing 3/5
|
|
264
|
+
|
|
265
|
+
If the universe of the coefficients is a general field, the object
|
|
266
|
+
constructed has type :class:`EllipticCurve_field`. Otherwise it is
|
|
267
|
+
:class:`EllipticCurve_generic`. See :issue:`9816` ::
|
|
268
|
+
|
|
269
|
+
sage: E = EllipticCurve([QQbar(1), 3]); E # needs sage.rings.number_field
|
|
270
|
+
Elliptic Curve defined by y^2 = x^3 + x + 3 over Algebraic Field
|
|
271
|
+
sage: type(E) # needs sage.rings.number_field
|
|
272
|
+
<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
|
|
273
|
+
|
|
274
|
+
sage: E = EllipticCurve([RR(1), 3]); E
|
|
275
|
+
Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 3.00000000000000
|
|
276
|
+
over Real Field with 53 bits of precision
|
|
277
|
+
sage: type(E)
|
|
278
|
+
<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
|
|
279
|
+
|
|
280
|
+
sage: # needs sage.symbolic
|
|
281
|
+
sage: E = EllipticCurve([SR(i),i]); E
|
|
282
|
+
Elliptic Curve defined by y^2 = x^3 + I*x + I over Symbolic Ring
|
|
283
|
+
sage: type(E)
|
|
284
|
+
<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
|
|
285
|
+
sage: E.category()
|
|
286
|
+
Category of abelian varieties over Symbolic Ring
|
|
287
|
+
sage: SR in Fields()
|
|
288
|
+
True
|
|
289
|
+
|
|
290
|
+
sage: F = FractionField(PolynomialRing(QQ,'t'))
|
|
291
|
+
sage: t = F.gen()
|
|
292
|
+
sage: E = EllipticCurve([t,0]); E
|
|
293
|
+
Elliptic Curve defined by y^2 = x^3 + t*x
|
|
294
|
+
over Fraction Field of Univariate Polynomial Ring in t over Rational Field
|
|
295
|
+
sage: type(E)
|
|
296
|
+
<class 'sage.schemes.elliptic_curves.ell_field.EllipticCurve_field_with_category'>
|
|
297
|
+
sage: E.category()
|
|
298
|
+
Category of abelian varieties over
|
|
299
|
+
Fraction Field of Univariate Polynomial Ring in t over Rational Field
|
|
300
|
+
|
|
301
|
+
See :issue:`12517`::
|
|
302
|
+
|
|
303
|
+
sage: E = EllipticCurve([1..5])
|
|
304
|
+
sage: EllipticCurve(E.a_invariants())
|
|
305
|
+
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
|
|
306
|
+
|
|
307
|
+
See :issue:`11773`::
|
|
308
|
+
|
|
309
|
+
sage: E = EllipticCurve()
|
|
310
|
+
Traceback (most recent call last):
|
|
311
|
+
...
|
|
312
|
+
TypeError: invalid input to EllipticCurve constructor
|
|
313
|
+
"""
|
|
314
|
+
def create_key_and_extra_args(self, x=None, y=None, j=None, minimal_twist=True, **kwds):
|
|
315
|
+
r"""
|
|
316
|
+
Return a ``UniqueFactory`` key and possibly extra parameters.
|
|
317
|
+
|
|
318
|
+
INPUT: See the documentation for :class:`EllipticCurveFactory`.
|
|
319
|
+
|
|
320
|
+
OUTPUT:
|
|
321
|
+
|
|
322
|
+
A pair ``(key, extra_args)``:
|
|
323
|
+
|
|
324
|
+
- ``key`` has the form `(R, (a_1, a_2, a_3, a_4, a_6))`,
|
|
325
|
+
representing a ring and the Weierstrass coefficients of an
|
|
326
|
+
elliptic curve over that ring;
|
|
327
|
+
|
|
328
|
+
- ``extra_args`` is a dictionary containing additional data to
|
|
329
|
+
be inserted into the elliptic curve structure.
|
|
330
|
+
|
|
331
|
+
EXAMPLES::
|
|
332
|
+
|
|
333
|
+
sage: EllipticCurve.create_key_and_extra_args(j=8000)
|
|
334
|
+
((Rational Field, (0, 1, 0, -3, 1)), {})
|
|
335
|
+
|
|
336
|
+
When constructing a curve over `\QQ` from a Cremona or LMFDB
|
|
337
|
+
label, the invariants from the database are returned as
|
|
338
|
+
``extra_args``::
|
|
339
|
+
|
|
340
|
+
sage: key, data = EllipticCurve.create_key_and_extra_args('389.a1')
|
|
341
|
+
sage: key
|
|
342
|
+
(Rational Field, (0, 1, 1, -2, 0))
|
|
343
|
+
sage: data['conductor']
|
|
344
|
+
389
|
|
345
|
+
sage: data['cremona_label']
|
|
346
|
+
'389a1'
|
|
347
|
+
sage: data['lmfdb_label']
|
|
348
|
+
'389.a1'
|
|
349
|
+
sage: data['rank']
|
|
350
|
+
2
|
|
351
|
+
sage: data['torsion_order']
|
|
352
|
+
1
|
|
353
|
+
|
|
354
|
+
User-specified keywords are also included in ``extra_args``::
|
|
355
|
+
|
|
356
|
+
sage: key, data = EllipticCurve.create_key_and_extra_args((0, 0, 1, -23737, 960366), rank=4)
|
|
357
|
+
sage: data['rank']
|
|
358
|
+
4
|
|
359
|
+
|
|
360
|
+
Furthermore, keywords takes precedence over data from the
|
|
361
|
+
database, which can be used to specify an alternative set of
|
|
362
|
+
generators for the Mordell-Weil group::
|
|
363
|
+
|
|
364
|
+
sage: key, data = EllipticCurve.create_key_and_extra_args('5077a1', gens=[[1, -1], [-2, 3], [4, -7]])
|
|
365
|
+
sage: data['gens']
|
|
366
|
+
[[1, -1], [-2, 3], [4, -7]]
|
|
367
|
+
sage: E = EllipticCurve.create_object(0, key, **data)
|
|
368
|
+
sage: E.gens()
|
|
369
|
+
[(-2 : 3 : 1), (1 : -1 : 1), (4 : -7 : 1)]
|
|
370
|
+
|
|
371
|
+
Note that elliptic curves are equal if and only they have the
|
|
372
|
+
same base ring and Weierstrass equation; the data in
|
|
373
|
+
``extra_args`` do not influence comparison of elliptic curves.
|
|
374
|
+
A consequence of this is that passing keyword arguments only
|
|
375
|
+
works when constructing an elliptic curve the first time::
|
|
376
|
+
|
|
377
|
+
sage: E = EllipticCurve('433a1', gens=[[-1, 1], [3, 4]])
|
|
378
|
+
sage: E.gens()
|
|
379
|
+
[(-1 : 1 : 1), (3 : 4 : 1)]
|
|
380
|
+
sage: E = EllipticCurve('433a1', gens=[[-1, 0], [0, 1]])
|
|
381
|
+
sage: E.gens()
|
|
382
|
+
[(-1 : 1 : 1), (3 : 4 : 1)]
|
|
383
|
+
|
|
384
|
+
.. WARNING::
|
|
385
|
+
|
|
386
|
+
Manually specifying extra data is almost never necessary
|
|
387
|
+
and is not guaranteed to have any effect, as the above
|
|
388
|
+
example shows. Almost no checking is done, so specifying
|
|
389
|
+
incorrect data may lead to wrong results of computations
|
|
390
|
+
instead of errors or warnings.
|
|
391
|
+
|
|
392
|
+
TESTS::
|
|
393
|
+
|
|
394
|
+
sage: # needs sage.symbolic
|
|
395
|
+
sage: var('x', 'y', 'v', 'w')
|
|
396
|
+
(x, y, v, w)
|
|
397
|
+
sage: EllipticCurve(y^2 + y > x^3 + x - 9)
|
|
398
|
+
Traceback (most recent call last):
|
|
399
|
+
...
|
|
400
|
+
ValueError: no symbolic relations other than equalities are allowed
|
|
401
|
+
sage: E = EllipticCurve(y^2 + y == x^3 + x - 9)
|
|
402
|
+
sage: E is EllipticCurve(y^2 + y - ( x^3 + x - 9 ))
|
|
403
|
+
True
|
|
404
|
+
sage: R.<x,y> = QQ[]
|
|
405
|
+
sage: E is EllipticCurve(y^2 + y - ( x^3 + x - 9 ))
|
|
406
|
+
True
|
|
407
|
+
"""
|
|
408
|
+
R = None
|
|
409
|
+
if x in Rings():
|
|
410
|
+
R, x = (x, y)
|
|
411
|
+
|
|
412
|
+
if j is not None:
|
|
413
|
+
if R is not None:
|
|
414
|
+
try:
|
|
415
|
+
j = R(j)
|
|
416
|
+
except (ZeroDivisionError, ValueError, TypeError):
|
|
417
|
+
raise ValueError("First parameter must be a ring containing %s" % j)
|
|
418
|
+
elif x is not None:
|
|
419
|
+
raise ValueError("First parameter (if present) must be a ring when j is specified")
|
|
420
|
+
x = coefficients_from_j(j, minimal_twist)
|
|
421
|
+
|
|
422
|
+
if isinstance(x, Expression) and x.is_relational():
|
|
423
|
+
import operator
|
|
424
|
+
if x.operator() != operator.eq:
|
|
425
|
+
raise ValueError("no symbolic relations other than equalities are allowed")
|
|
426
|
+
x = x.lhs() - x.rhs()
|
|
427
|
+
|
|
428
|
+
if isinstance(parent(x), sage.rings.abc.SymbolicRing):
|
|
429
|
+
x = x._polynomial_(QQ['x', 'y'])
|
|
430
|
+
|
|
431
|
+
if isinstance(x, MPolynomial):
|
|
432
|
+
if y is None:
|
|
433
|
+
x = coefficients_from_Weierstrass_polynomial(x)
|
|
434
|
+
else:
|
|
435
|
+
# x is a cubic, y a rational point
|
|
436
|
+
x = EllipticCurve_from_cubic(x, y, morphism=False).ainvs()
|
|
437
|
+
|
|
438
|
+
if isinstance(x, str):
|
|
439
|
+
# Interpret x as a Cremona or LMFDB label.
|
|
440
|
+
from sage.databases.cremona import CremonaDatabase
|
|
441
|
+
x, data = CremonaDatabase().coefficients_and_data(x)
|
|
442
|
+
# data is only valid for elliptic curves over QQ.
|
|
443
|
+
if R not in (None, QQ):
|
|
444
|
+
data = {}
|
|
445
|
+
# User-provided keywords may override database entries.
|
|
446
|
+
data.update(kwds)
|
|
447
|
+
kwds = data
|
|
448
|
+
|
|
449
|
+
if not isinstance(x, (list, tuple)):
|
|
450
|
+
raise TypeError("invalid input to EllipticCurve constructor")
|
|
451
|
+
|
|
452
|
+
if len(x) == 2:
|
|
453
|
+
x = (0, 0, 0, x[0], x[1])
|
|
454
|
+
elif len(x) != 5:
|
|
455
|
+
raise ValueError("sequence of coefficients must have length 2 or 5")
|
|
456
|
+
|
|
457
|
+
if R is None:
|
|
458
|
+
R = Sequence(x).universe()
|
|
459
|
+
if R in (ZZ, int):
|
|
460
|
+
R = QQ
|
|
461
|
+
|
|
462
|
+
return (R, tuple(R(a) for a in x)), kwds
|
|
463
|
+
|
|
464
|
+
def create_object(self, version, key, *, names=None, **kwds):
|
|
465
|
+
r"""
|
|
466
|
+
Create an object from a ``UniqueFactory`` key.
|
|
467
|
+
|
|
468
|
+
EXAMPLES::
|
|
469
|
+
|
|
470
|
+
sage: E = EllipticCurve.create_object(0, (GF(3), (1, 2, 0, 1, 2)))
|
|
471
|
+
sage: type(E)
|
|
472
|
+
<class 'sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field_with_category'>
|
|
473
|
+
|
|
474
|
+
``names`` is ignored at the moment, however it is used to support a convenient way to get a generator::
|
|
475
|
+
|
|
476
|
+
sage: # needs eclib
|
|
477
|
+
sage: E.<P> = EllipticCurve(QQ, [1, 3])
|
|
478
|
+
sage: P
|
|
479
|
+
(-1 : 1 : 1)
|
|
480
|
+
sage: E.<P> = EllipticCurve(GF(5), [1, 3])
|
|
481
|
+
sage: P
|
|
482
|
+
(4 : 1 : 1)
|
|
483
|
+
|
|
484
|
+
.. NOTE::
|
|
485
|
+
|
|
486
|
+
Keyword arguments are currently only passed to the
|
|
487
|
+
constructor for elliptic curves over `\QQ`; elliptic
|
|
488
|
+
curves over other fields do not support them.
|
|
489
|
+
|
|
490
|
+
TESTS::
|
|
491
|
+
|
|
492
|
+
sage: E = EllipticCurve.create_object(0, (QQ, (1, 2, 0, 1, 2)), rank=2)
|
|
493
|
+
sage: E = EllipticCurve.create_object(0, (GF(3), (1, 2, 0, 1, 2)), rank=2)
|
|
494
|
+
Traceback (most recent call last):
|
|
495
|
+
...
|
|
496
|
+
TypeError: unexpected keyword arguments: {'rank': 2}
|
|
497
|
+
|
|
498
|
+
Coverage tests::
|
|
499
|
+
|
|
500
|
+
sage: E = EllipticCurve(QQ, [2, 5], modular_degree=944, regulator=1)
|
|
501
|
+
sage: E.modular_degree()
|
|
502
|
+
944
|
|
503
|
+
sage: E.regulator()
|
|
504
|
+
1.00000000000000
|
|
505
|
+
"""
|
|
506
|
+
R, x = key
|
|
507
|
+
|
|
508
|
+
if R is QQ:
|
|
509
|
+
from .ell_rational_field import EllipticCurve_rational_field
|
|
510
|
+
return EllipticCurve_rational_field(x, **kwds)
|
|
511
|
+
elif kwds:
|
|
512
|
+
raise TypeError(f"unexpected keyword arguments: {kwds}")
|
|
513
|
+
|
|
514
|
+
if isinstance(R, NumberField):
|
|
515
|
+
from .ell_number_field import EllipticCurve_number_field
|
|
516
|
+
return EllipticCurve_number_field(R, x)
|
|
517
|
+
elif isinstance(R, sage.rings.abc.pAdicField):
|
|
518
|
+
from .ell_padic_field import EllipticCurve_padic_field
|
|
519
|
+
return EllipticCurve_padic_field(R, x)
|
|
520
|
+
elif isinstance(R, FiniteField) or (isinstance(R, sage.rings.abc.IntegerModRing) and R.characteristic().is_prime()):
|
|
521
|
+
from .ell_finite_field import EllipticCurve_finite_field
|
|
522
|
+
return EllipticCurve_finite_field(R, x)
|
|
523
|
+
elif R in _Fields:
|
|
524
|
+
from .ell_field import EllipticCurve_field
|
|
525
|
+
return EllipticCurve_field(R, x)
|
|
526
|
+
from .ell_generic import EllipticCurve_generic
|
|
527
|
+
return EllipticCurve_generic(R, x)
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
EllipticCurve = EllipticCurveFactory('sage.schemes.elliptic_curves.constructor.EllipticCurve')
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def EllipticCurve_from_Weierstrass_polynomial(f):
|
|
534
|
+
r"""
|
|
535
|
+
Return the elliptic curve defined by a cubic in (long) Weierstrass
|
|
536
|
+
form.
|
|
537
|
+
|
|
538
|
+
INPUT:
|
|
539
|
+
|
|
540
|
+
- ``f`` -- a inhomogeneous cubic polynomial in long Weierstrass form
|
|
541
|
+
|
|
542
|
+
OUTPUT: the elliptic curve defined by it
|
|
543
|
+
|
|
544
|
+
EXAMPLES::
|
|
545
|
+
|
|
546
|
+
sage: R.<x,y> = QQ[]
|
|
547
|
+
sage: f = y^2 + 1*x*y + 3*y - (x^3 + 2*x^2 + 4*x + 6)
|
|
548
|
+
sage: EllipticCurve(f)
|
|
549
|
+
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 6 over Rational Field
|
|
550
|
+
sage: EllipticCurve(f).a_invariants()
|
|
551
|
+
(1, 2, 3, 4, 6)
|
|
552
|
+
|
|
553
|
+
The polynomial ring may have extra variables as long as they
|
|
554
|
+
do not occur in the polynomial itself::
|
|
555
|
+
|
|
556
|
+
sage: R.<x,y,z,w> = QQ[]
|
|
557
|
+
sage: EllipticCurve(-y^2 + x^3 + 1)
|
|
558
|
+
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
|
|
559
|
+
sage: EllipticCurve(-x^2 + y^3 + 1)
|
|
560
|
+
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
|
|
561
|
+
sage: EllipticCurve(-w^2 + z^3 + 1)
|
|
562
|
+
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
|
|
563
|
+
|
|
564
|
+
TESTS::
|
|
565
|
+
|
|
566
|
+
sage: from sage.schemes.elliptic_curves.constructor import EllipticCurve_from_Weierstrass_polynomial
|
|
567
|
+
sage: EllipticCurve_from_Weierstrass_polynomial(-w^2 + z^3 + 1)
|
|
568
|
+
Elliptic Curve defined by y^2 = x^3 + 1 over Rational Field
|
|
569
|
+
"""
|
|
570
|
+
return EllipticCurve(coefficients_from_Weierstrass_polynomial(f))
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
def coefficients_from_Weierstrass_polynomial(f):
|
|
574
|
+
r"""
|
|
575
|
+
Return the coefficients `[a_1, a_2, a_3, a_4, a_6]` of a cubic in
|
|
576
|
+
Weierstrass form.
|
|
577
|
+
|
|
578
|
+
EXAMPLES::
|
|
579
|
+
|
|
580
|
+
sage: from sage.schemes.elliptic_curves.constructor import coefficients_from_Weierstrass_polynomial
|
|
581
|
+
sage: R.<w,z> = QQ[]
|
|
582
|
+
sage: coefficients_from_Weierstrass_polynomial(-w^2 + z^3 + 1)
|
|
583
|
+
[0, 0, 0, 0, 1]
|
|
584
|
+
"""
|
|
585
|
+
R = f.parent()
|
|
586
|
+
cubic_variables = [ x for x in R.gens() if f.degree(x) == 3 ]
|
|
587
|
+
quadratic_variables = [ y for y in R.gens() if f.degree(y) == 2 ]
|
|
588
|
+
try:
|
|
589
|
+
x = cubic_variables[0]
|
|
590
|
+
y = quadratic_variables[0]
|
|
591
|
+
except IndexError:
|
|
592
|
+
raise ValueError('polynomial is not in long Weierstrass form')
|
|
593
|
+
|
|
594
|
+
a1 = a2 = a3 = a4 = a6 = 0
|
|
595
|
+
x3 = y2 = None
|
|
596
|
+
for coeff, mon in f:
|
|
597
|
+
if mon == x**3:
|
|
598
|
+
x3 = coeff
|
|
599
|
+
elif mon == x**2:
|
|
600
|
+
a2 = coeff
|
|
601
|
+
elif mon == x:
|
|
602
|
+
a4 = coeff
|
|
603
|
+
elif mon == 1:
|
|
604
|
+
a6 = coeff
|
|
605
|
+
elif mon == y**2:
|
|
606
|
+
y2 = -coeff
|
|
607
|
+
elif mon == x*y:
|
|
608
|
+
a1 = -coeff
|
|
609
|
+
elif mon == y:
|
|
610
|
+
a3 = -coeff
|
|
611
|
+
else:
|
|
612
|
+
raise ValueError('polynomial is not in long Weierstrass form')
|
|
613
|
+
|
|
614
|
+
if x3 != y2:
|
|
615
|
+
raise ValueError('the coefficient of x^3 and -y^2 must be the same')
|
|
616
|
+
elif x3 != 1:
|
|
617
|
+
a1, a2, a3, a4, a6 = a1/x3, a2/x3, a3/x3, a4/x3, a6/x3
|
|
618
|
+
return [a1, a2, a3, a4, a6]
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def EllipticCurve_from_c4c6(c4, c6):
|
|
622
|
+
r"""
|
|
623
|
+
Return an elliptic curve with given `c_4` and
|
|
624
|
+
`c_6` invariants.
|
|
625
|
+
|
|
626
|
+
EXAMPLES::
|
|
627
|
+
|
|
628
|
+
sage: E = EllipticCurve_from_c4c6(17, -2005)
|
|
629
|
+
sage: E
|
|
630
|
+
Elliptic Curve defined by y^2 = x^3 - 17/48*x + 2005/864 over Rational Field
|
|
631
|
+
sage: E.c_invariants()
|
|
632
|
+
(17, -2005)
|
|
633
|
+
"""
|
|
634
|
+
try:
|
|
635
|
+
K = c4.parent()
|
|
636
|
+
except AttributeError:
|
|
637
|
+
K = RationalField()
|
|
638
|
+
if K not in _Fields:
|
|
639
|
+
K = K.fraction_field()
|
|
640
|
+
return EllipticCurve([-K(c4)/K(48), -K(c6)/K(864)])
|
|
641
|
+
|
|
642
|
+
|
|
643
|
+
def EllipticCurve_from_j(j, minimal_twist=True):
|
|
644
|
+
r"""
|
|
645
|
+
Return an elliptic curve with given `j`-invariant.
|
|
646
|
+
|
|
647
|
+
INPUT:
|
|
648
|
+
|
|
649
|
+
- ``j`` -- an element of some field
|
|
650
|
+
|
|
651
|
+
- ``minimal_twist``-- boolean (default: ``True``); if ``True`` and ``j``
|
|
652
|
+
is in `\QQ`, the curve returned is a minimal twist, i.e. has
|
|
653
|
+
minimal conductor; when there is more than one curve with
|
|
654
|
+
minimal conductor, the curve returned is the one whose label
|
|
655
|
+
comes first if the curves are in the CremonaDatabase, otherwise
|
|
656
|
+
the one whose minimal a-invariants are first lexicographically.
|
|
657
|
+
If `j` is not in `\QQ` this parameter is ignored.
|
|
658
|
+
|
|
659
|
+
OUTPUT: an elliptic curve with `j`-invariant `j`
|
|
660
|
+
|
|
661
|
+
EXAMPLES::
|
|
662
|
+
|
|
663
|
+
sage: E = EllipticCurve_from_j(0); E; E.j_invariant(); E.label()
|
|
664
|
+
Elliptic Curve defined by y^2 + y = x^3 over Rational Field
|
|
665
|
+
0
|
|
666
|
+
'27a3'
|
|
667
|
+
|
|
668
|
+
sage: E = EllipticCurve_from_j(1728); E; E.j_invariant(); E.label()
|
|
669
|
+
Elliptic Curve defined by y^2 = x^3 - x over Rational Field
|
|
670
|
+
1728
|
|
671
|
+
'32a2'
|
|
672
|
+
|
|
673
|
+
sage: E = EllipticCurve_from_j(1); E; E.j_invariant()
|
|
674
|
+
Elliptic Curve defined by y^2 + x*y = x^3 + 36*x + 3455 over Rational Field
|
|
675
|
+
1
|
|
676
|
+
|
|
677
|
+
The ``minimal_twist`` parameter (ignored except over `\QQ` and
|
|
678
|
+
``True`` by default) controls whether or not a minimal twist is
|
|
679
|
+
computed::
|
|
680
|
+
|
|
681
|
+
sage: EllipticCurve_from_j(100)
|
|
682
|
+
Elliptic Curve defined by y^2 = x^3 + x^2 + 3392*x + 307888 over Rational Field
|
|
683
|
+
sage: _.conductor()
|
|
684
|
+
33129800
|
|
685
|
+
sage: EllipticCurve_from_j(100, minimal_twist=False)
|
|
686
|
+
Elliptic Curve defined by y^2 = x^3 + 488400*x - 530076800 over Rational Field
|
|
687
|
+
sage: _.conductor()
|
|
688
|
+
298168200
|
|
689
|
+
|
|
690
|
+
Since computing the minimal twist requires factoring both `j` and
|
|
691
|
+
`j-1728` the following example would take a long time without
|
|
692
|
+
setting ``minimal_twist`` to False::
|
|
693
|
+
|
|
694
|
+
sage: E = EllipticCurve_from_j(2^256+1, minimal_twist=False)
|
|
695
|
+
sage: E.j_invariant() == 2^256+1
|
|
696
|
+
True
|
|
697
|
+
"""
|
|
698
|
+
return EllipticCurve(coefficients_from_j(j, minimal_twist))
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
def coefficients_from_j(j, minimal_twist=True):
|
|
702
|
+
r"""
|
|
703
|
+
Return Weierstrass coefficients `(a_1, a_2, a_3, a_4, a_6)` for an
|
|
704
|
+
elliptic curve with given `j`-invariant.
|
|
705
|
+
|
|
706
|
+
INPUT: See :func:`EllipticCurve_from_j`.
|
|
707
|
+
|
|
708
|
+
EXAMPLES::
|
|
709
|
+
|
|
710
|
+
sage: from sage.schemes.elliptic_curves.constructor import coefficients_from_j
|
|
711
|
+
sage: coefficients_from_j(0)
|
|
712
|
+
[0, 0, 1, 0, 0]
|
|
713
|
+
sage: coefficients_from_j(1728)
|
|
714
|
+
[0, 0, 0, -1, 0]
|
|
715
|
+
sage: coefficients_from_j(1)
|
|
716
|
+
[1, 0, 0, 36, 3455]
|
|
717
|
+
|
|
718
|
+
The ``minimal_twist`` parameter (ignored except over `\QQ` and
|
|
719
|
+
``True`` by default) controls whether or not a minimal twist is
|
|
720
|
+
computed::
|
|
721
|
+
|
|
722
|
+
sage: coefficients_from_j(100)
|
|
723
|
+
[0, 1, 0, 3392, 307888]
|
|
724
|
+
sage: coefficients_from_j(100, minimal_twist=False)
|
|
725
|
+
[0, 0, 0, 488400, -530076800]
|
|
726
|
+
"""
|
|
727
|
+
try:
|
|
728
|
+
K = j.parent()
|
|
729
|
+
except AttributeError:
|
|
730
|
+
K = RationalField()
|
|
731
|
+
if K not in _Fields:
|
|
732
|
+
K = K.fraction_field()
|
|
733
|
+
|
|
734
|
+
char = K.characteristic()
|
|
735
|
+
if char == 2:
|
|
736
|
+
if j == 0:
|
|
737
|
+
return Sequence([0, 0, 1, 0, 0], universe=K)
|
|
738
|
+
else:
|
|
739
|
+
return Sequence([1, 0, 0, 0, 1/j], universe=K)
|
|
740
|
+
if char == 3:
|
|
741
|
+
if j == 0:
|
|
742
|
+
return Sequence([0, 0, 0, 1, 0], universe=K)
|
|
743
|
+
else:
|
|
744
|
+
return Sequence([0, j, 0, 0, -j**2], universe=K)
|
|
745
|
+
|
|
746
|
+
if K is RationalField():
|
|
747
|
+
# we construct the minimal twist, i.e. the curve with minimal
|
|
748
|
+
# conductor with this j_invariant:
|
|
749
|
+
if j == 0:
|
|
750
|
+
return Sequence([0, 0, 1, 0, 0], universe=K) # 27a3
|
|
751
|
+
if j == 1728:
|
|
752
|
+
return Sequence([0, 0, 0, -1, 0], universe=K) # 32a2
|
|
753
|
+
|
|
754
|
+
if not minimal_twist:
|
|
755
|
+
k = j-1728
|
|
756
|
+
return Sequence([0, 0, 0, -3*j*k, -2*j*k**2], universe=K)
|
|
757
|
+
|
|
758
|
+
n = j.numerator()
|
|
759
|
+
m = n-1728*j.denominator()
|
|
760
|
+
a4 = -3*n*m
|
|
761
|
+
a6 = -2*n*m**2
|
|
762
|
+
|
|
763
|
+
# Now E=[0,0,0,a4,a6] has j-invariant j=n/d
|
|
764
|
+
from sage.sets.set import Set
|
|
765
|
+
for p in Set(n.prime_divisors()+m.prime_divisors()):
|
|
766
|
+
e = min(a4.valuation(p)//2,a6.valuation(p)//3)
|
|
767
|
+
if e > 0:
|
|
768
|
+
p = p**e
|
|
769
|
+
a4 /= p**2
|
|
770
|
+
a6 /= p**3
|
|
771
|
+
|
|
772
|
+
# Now E=[0,0,0,a4,a6] is minimal at all p != 2,3
|
|
773
|
+
tw = [-1,2,-2,3,-3,6,-6]
|
|
774
|
+
E1 = EllipticCurve([0,0,0,a4,a6])
|
|
775
|
+
Elist = [E1] + [E1.quadratic_twist(t) for t in tw]
|
|
776
|
+
min_cond = min(E.conductor() for E in Elist)
|
|
777
|
+
Elist = [E for E in Elist if E.conductor() == min_cond]
|
|
778
|
+
if len(Elist) > 1:
|
|
779
|
+
from sage.databases.cremona import CremonaDatabase, parse_cremona_label
|
|
780
|
+
if min_cond <= CremonaDatabase().largest_conductor():
|
|
781
|
+
sorter = lambda E: parse_cremona_label(E.label(), numerical_class_code=True)
|
|
782
|
+
else:
|
|
783
|
+
sorter = lambda E: E.ainvs()
|
|
784
|
+
Elist.sort(key=sorter)
|
|
785
|
+
return Sequence(Elist[0].ainvs())
|
|
786
|
+
|
|
787
|
+
# defaults for all other fields:
|
|
788
|
+
if j == 0:
|
|
789
|
+
return Sequence([0, 0, 0, 0, 1], universe=K)
|
|
790
|
+
if j == 1728:
|
|
791
|
+
return Sequence([0, 0, 0, 1, 0], universe=K)
|
|
792
|
+
k = j-1728
|
|
793
|
+
return Sequence([0, 0, 0, -3*j*k, -2*j*k**2], universe=K)
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
def EllipticCurve_from_cubic(F, P=None, morphism=True):
|
|
797
|
+
r"""
|
|
798
|
+
Construct an elliptic curve from a ternary cubic with a rational point.
|
|
799
|
+
|
|
800
|
+
If you just want the Weierstrass form and are not interested in
|
|
801
|
+
the morphism then it is easier to use the function
|
|
802
|
+
:func:`~sage.schemes.elliptic_curves.jacobian.Jacobian`
|
|
803
|
+
instead. If there is a rational point on the given cubic, this
|
|
804
|
+
function will construct the same elliptic curve but you do not have to
|
|
805
|
+
supply the point ``P``.
|
|
806
|
+
|
|
807
|
+
INPUT:
|
|
808
|
+
|
|
809
|
+
- ``F`` -- a homogeneous cubic in three variables with rational
|
|
810
|
+
coefficients, as a polynomial ring element, defining a smooth
|
|
811
|
+
plane cubic curve `C`
|
|
812
|
+
|
|
813
|
+
- ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on `C`,
|
|
814
|
+
or ``None``. If ``None`` then a rational flex will be used as a
|
|
815
|
+
base point if one exists, otherwise an error will be raised.
|
|
816
|
+
|
|
817
|
+
- ``morphism`` -- boolean (default: ``True``); if ``True``
|
|
818
|
+
returns a birational isomorphism from `C` to a Weierstrass
|
|
819
|
+
elliptic curve `E`, otherwise just returns `E`
|
|
820
|
+
|
|
821
|
+
OUTPUT:
|
|
822
|
+
|
|
823
|
+
Either (when ``morphism``=``False``) an elliptic curve `E` in long
|
|
824
|
+
Weierstrass form isomorphic to the plane cubic curve `C` defined
|
|
825
|
+
by the equation `F=0`.
|
|
826
|
+
|
|
827
|
+
Or (when ``morphism=True``), a birational isomorphism from `C` to
|
|
828
|
+
the elliptic curve `E`. If the given point is a flex, this is a
|
|
829
|
+
linear isomorphism.
|
|
830
|
+
|
|
831
|
+
.. NOTE::
|
|
832
|
+
|
|
833
|
+
The function
|
|
834
|
+
:func:`~sage.schemes.elliptic_curves.jacobian.Jacobian` may be
|
|
835
|
+
used instead. It constructs the same elliptic curve (which is in
|
|
836
|
+
all cases the Jacobian of `(F=0)`) and needs no base point to be
|
|
837
|
+
provided, but also returns no isomorphism since in general there
|
|
838
|
+
is none: the plane cubic is only isomorphic to its Jacobian when
|
|
839
|
+
it has a rational point.
|
|
840
|
+
|
|
841
|
+
.. NOTE::
|
|
842
|
+
|
|
843
|
+
When ``morphism=True``, a birational isomorphism between the
|
|
844
|
+
curve `F=0` and the Weierstrass curve is returned. If the point
|
|
845
|
+
happens to be a flex, then this is a linear isomorphism. The
|
|
846
|
+
morphism does not necessarily take the given point `P` to the
|
|
847
|
+
point at infinity on `E`, since we always use a rational flex
|
|
848
|
+
on `C` as base-point when one exists.
|
|
849
|
+
|
|
850
|
+
EXAMPLES:
|
|
851
|
+
|
|
852
|
+
First we find that the Fermat cubic is isomorphic to the curve
|
|
853
|
+
with Cremona label 27a1::
|
|
854
|
+
|
|
855
|
+
sage: R.<x,y,z> = QQ[]
|
|
856
|
+
sage: cubic = x^3 + y^3 + z^3
|
|
857
|
+
sage: P = [1,-1,0]
|
|
858
|
+
sage: E = EllipticCurve_from_cubic(cubic, P, morphism=False); E
|
|
859
|
+
Elliptic Curve defined by y^2 - 9*y = x^3 - 27 over Rational Field
|
|
860
|
+
sage: E.cremona_label()
|
|
861
|
+
'27a1'
|
|
862
|
+
sage: EllipticCurve_from_cubic(cubic, [0,1,-1], morphism=False).cremona_label()
|
|
863
|
+
'27a1'
|
|
864
|
+
sage: EllipticCurve_from_cubic(cubic, [1,0,-1], morphism=False).cremona_label()
|
|
865
|
+
'27a1'
|
|
866
|
+
|
|
867
|
+
Next we find the minimal model and conductor of the Jacobian of the
|
|
868
|
+
Selmer curve::
|
|
869
|
+
|
|
870
|
+
sage: R.<a,b,c> = QQ[]
|
|
871
|
+
sage: cubic = a^3 + b^3 + 60*c^3
|
|
872
|
+
sage: P = [1,-1,0]
|
|
873
|
+
sage: E = EllipticCurve_from_cubic(cubic, P, morphism=False); E
|
|
874
|
+
Elliptic Curve defined by y^2 - 540*y = x^3 - 97200 over Rational Field
|
|
875
|
+
sage: E.minimal_model()
|
|
876
|
+
Elliptic Curve defined by y^2 = x^3 - 24300 over Rational Field
|
|
877
|
+
sage: E.conductor()
|
|
878
|
+
24300
|
|
879
|
+
|
|
880
|
+
We can also get the birational isomorphism to and from the
|
|
881
|
+
Weierstrass form. We start with an example where ``P`` is a flex
|
|
882
|
+
and the equivalence is a linear isomorphism::
|
|
883
|
+
|
|
884
|
+
sage: f = EllipticCurve_from_cubic(cubic, P, morphism=True)
|
|
885
|
+
sage: f
|
|
886
|
+
Scheme morphism:
|
|
887
|
+
From: Projective Plane Curve over Rational Field defined by a^3 + b^3 + 60*c^3
|
|
888
|
+
To: Elliptic Curve defined by y^2 - 540*y = x^3 - 97200 over Rational Field
|
|
889
|
+
Defn: Defined on coordinates by sending (a : b : c) to
|
|
890
|
+
(-c : 3*a : 1/180*a + 1/180*b)
|
|
891
|
+
|
|
892
|
+
sage: finv = f.inverse(); finv
|
|
893
|
+
Scheme morphism:
|
|
894
|
+
From: Elliptic Curve defined by y^2 - 540*y = x^3 - 97200 over Rational Field
|
|
895
|
+
To: Projective Plane Curve over Rational Field defined by a^3 + b^3 + 60*c^3
|
|
896
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
897
|
+
(1/3*y : -1/3*y + 180*z : -x)
|
|
898
|
+
|
|
899
|
+
Scheme morphism:
|
|
900
|
+
From: Elliptic Curve defined by y^2 + 2*x*y + 20*y = x^3 - x^2 - 20*x - 400/3
|
|
901
|
+
over Rational Field
|
|
902
|
+
To: Closed subscheme of Projective Space of dimension 2 over Rational Field
|
|
903
|
+
defined by: a^3 + b^3 + 60*c^3
|
|
904
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
905
|
+
(x + y + 20*z : -x - y : -x)
|
|
906
|
+
|
|
907
|
+
We verify that `f` maps the chosen point `P=(1,-1,0)` on the cubic
|
|
908
|
+
to the origin of the elliptic curve::
|
|
909
|
+
|
|
910
|
+
sage: f([1,-1,0])
|
|
911
|
+
(0 : 1 : 0)
|
|
912
|
+
sage: finv([0,1,0])
|
|
913
|
+
(-1 : 1 : 0)
|
|
914
|
+
|
|
915
|
+
To verify the output, we plug in the polynomials to check that
|
|
916
|
+
this indeed transforms the cubic into Weierstrass form::
|
|
917
|
+
|
|
918
|
+
sage: cubic(finv.defining_polynomials()) * finv.post_rescaling()
|
|
919
|
+
-x^3 + y^2*z - 540*y*z^2 + 97200*z^3
|
|
920
|
+
|
|
921
|
+
sage: E.defining_polynomial()(f.defining_polynomials()) * f.post_rescaling()
|
|
922
|
+
a^3 + b^3 + 60*c^3
|
|
923
|
+
|
|
924
|
+
If the given point is not a flex and the cubic has no rational
|
|
925
|
+
flexes, then the cubic can not be transformed to a Weierstrass
|
|
926
|
+
equation by a linear transformation. The general birational
|
|
927
|
+
transformation is still a birational isomorphism, but is
|
|
928
|
+
quadratic::
|
|
929
|
+
|
|
930
|
+
sage: R.<x,y,z> = QQ[]
|
|
931
|
+
sage: cubic = x^2*y + 4*x*y^2 + x^2*z + 8*x*y*z + 4*y^2*z + 9*x*z^2 + 9*y*z^2
|
|
932
|
+
sage: f = EllipticCurve_from_cubic(cubic, [1,-1,1], morphism=True); f
|
|
933
|
+
Scheme morphism:
|
|
934
|
+
From: Projective Plane Curve over Rational Field defined
|
|
935
|
+
by x^2*y + 4*x*y^2 + x^2*z + 8*x*y*z + 4*y^2*z + 9*x*z^2 + 9*y*z^2
|
|
936
|
+
To: Elliptic Curve defined
|
|
937
|
+
by y^2 + 7560/19*x*y + 552960000000/2352637*y = x^3 - 3445200/133*x^2
|
|
938
|
+
over Rational Field
|
|
939
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
940
|
+
(2527/17280*x^2 + 133/2160*x*y + 133/108000*y^2 + 133/2880*x*z
|
|
941
|
+
+ 931/18000*y*z - 3857/48000*z^2
|
|
942
|
+
: -6859/288*x^2 + 323/36*x*y + 359/1800*y^2 + 551/48*x*z
|
|
943
|
+
+ 2813/300*y*z + 24389/800*z^2
|
|
944
|
+
: -2352637/99532800000*x^2 - 2352637/124416000000*x*y
|
|
945
|
+
- 2352637/622080000000*y^2 + 2352637/82944000000*x*z
|
|
946
|
+
+ 2352637/207360000000*y*z - 2352637/276480000000*z^2)
|
|
947
|
+
|
|
948
|
+
Note that the morphism returned cannot be evaluated directly at
|
|
949
|
+
the given point ``P=(1:-1:1)`` since the polynomials defining it
|
|
950
|
+
all vanish there::
|
|
951
|
+
|
|
952
|
+
sage: f([1,-1,1])
|
|
953
|
+
Traceback (most recent call last):
|
|
954
|
+
...
|
|
955
|
+
ValueError: [0, 0, 0] does not define a valid projective point since all entries are zero
|
|
956
|
+
|
|
957
|
+
Using the group law on the codomain elliptic curve, which has rank
|
|
958
|
+
1 and full 2-torsion, and the inverse morphism, we can find many
|
|
959
|
+
points on the cubic. First we find the preimages of multiples of
|
|
960
|
+
the generator::
|
|
961
|
+
|
|
962
|
+
sage: # needs eclib
|
|
963
|
+
sage: E = f.codomain()
|
|
964
|
+
sage: E.label()
|
|
965
|
+
'720e2'
|
|
966
|
+
sage: E.rank()
|
|
967
|
+
1
|
|
968
|
+
sage: R = E.gens()[0]; R
|
|
969
|
+
(-17280000/2527 : 9331200000/6859 : 1)
|
|
970
|
+
sage: finv = f.inverse()
|
|
971
|
+
sage: [finv(k*R) for k in range(1,10)]
|
|
972
|
+
[(-4 : 1 : 0),
|
|
973
|
+
(-1 : 4 : 1),
|
|
974
|
+
(-20 : -55/76 : 1),
|
|
975
|
+
(319/399 : -11339/7539 : 1),
|
|
976
|
+
(159919/14360 : -4078139/1327840 : 1),
|
|
977
|
+
(-27809119/63578639 : 1856146436/3425378659 : 1),
|
|
978
|
+
(-510646582340/56909753439 : 424000923715/30153806197284 : 1),
|
|
979
|
+
(-56686114363679/4050436059492161 : -2433034816977728281/1072927821085503881 : 1),
|
|
980
|
+
(650589589099815846721/72056273157352822480 : -347376189546061993109881/194127383495944026752320 : 1)]
|
|
981
|
+
|
|
982
|
+
The elliptic curve also has torsion, which we can map back::
|
|
983
|
+
|
|
984
|
+
sage: # needs eclib
|
|
985
|
+
sage: E.torsion_points()
|
|
986
|
+
[(0 : 1 : 0),
|
|
987
|
+
(-144000000/17689 : 3533760000000/2352637 : 1),
|
|
988
|
+
(-92160000/17689 : 2162073600000/2352637 : 1),
|
|
989
|
+
(-5760000/17689 : -124070400000/2352637 : 1)]
|
|
990
|
+
sage: [finv(Q) for Q in E.torsion_points() if Q]
|
|
991
|
+
[(9 : -9/4 : 1), (-9 : 0 : 1), (0 : 1 : 0)]
|
|
992
|
+
|
|
993
|
+
In this example, the given point ``P`` is not a flex but the cubic
|
|
994
|
+
does have a rational flex, ``(-4:0:1)``. We return a linear
|
|
995
|
+
isomorphism which maps this flex to the point at infinity on the
|
|
996
|
+
Weierstrass model::
|
|
997
|
+
|
|
998
|
+
sage: R.<a,b,c> = QQ[]
|
|
999
|
+
sage: cubic = a^3 + 7*b^3 + 64*c^3
|
|
1000
|
+
sage: P = [2,2,-1]
|
|
1001
|
+
sage: f = EllipticCurve_from_cubic(cubic, P, morphism=True)
|
|
1002
|
+
sage: E = f.codomain(); E
|
|
1003
|
+
Elliptic Curve defined by y^2 - 258048*y = x^3 - 22196256768 over Rational Field
|
|
1004
|
+
sage: E.minimal_model()
|
|
1005
|
+
Elliptic Curve defined by y^2 + y = x^3 - 331 over Rational Field
|
|
1006
|
+
|
|
1007
|
+
sage: f
|
|
1008
|
+
Scheme morphism:
|
|
1009
|
+
From: Projective Plane Curve over Rational Field defined by a^3 + 7*b^3 + 64*c^3
|
|
1010
|
+
To: Elliptic Curve defined by y^2 - 258048*y = x^3 - 22196256768 over Rational Field
|
|
1011
|
+
Defn: Defined on coordinates by sending (a : b : c) to
|
|
1012
|
+
(b : -48*a : -1/5376*a - 1/1344*c)
|
|
1013
|
+
|
|
1014
|
+
sage: finv = f.inverse(); finv
|
|
1015
|
+
Scheme morphism:
|
|
1016
|
+
From: Elliptic Curve defined by y^2 - 258048*y = x^3 - 22196256768 over Rational Field
|
|
1017
|
+
To: Projective Plane Curve over Rational Field defined by a^3 + 7*b^3 + 64*c^3
|
|
1018
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
1019
|
+
(-1/48*y : x : 1/192*y - 1344*z)
|
|
1020
|
+
|
|
1021
|
+
sage: cubic(finv.defining_polynomials()) * finv.post_rescaling()
|
|
1022
|
+
-x^3 + y^2*z - 258048*y*z^2 + 22196256768*z^3
|
|
1023
|
+
|
|
1024
|
+
sage: E.defining_polynomial()(f.defining_polynomials()) * f.post_rescaling()
|
|
1025
|
+
a^3 + 7*b^3 + 64*c^3
|
|
1026
|
+
|
|
1027
|
+
sage: f(P)
|
|
1028
|
+
(5376 : -258048 : 1)
|
|
1029
|
+
sage: f([-4,0,1])
|
|
1030
|
+
(0 : 1 : 0)
|
|
1031
|
+
|
|
1032
|
+
It is possible to not provide a base point ``P`` provided that the
|
|
1033
|
+
cubic has a rational flex. In this case the flexes will be found
|
|
1034
|
+
and one will be used as a base point::
|
|
1035
|
+
|
|
1036
|
+
sage: R.<x,y,z> = QQ[]
|
|
1037
|
+
sage: cubic = x^3 + y^3 + z^3
|
|
1038
|
+
sage: f = EllipticCurve_from_cubic(cubic, morphism=True)
|
|
1039
|
+
sage: f
|
|
1040
|
+
Scheme morphism:
|
|
1041
|
+
From: Projective Plane Curve over Rational Field defined by x^3 + y^3 + z^3
|
|
1042
|
+
To: Elliptic Curve defined by y^2 - 9*y = x^3 - 27 over Rational Field
|
|
1043
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
1044
|
+
(y : -3*x : -1/3*x - 1/3*z)
|
|
1045
|
+
|
|
1046
|
+
An error will be raised if no point is given and there are no rational flexes::
|
|
1047
|
+
|
|
1048
|
+
sage: R.<x,y,z> = QQ[]
|
|
1049
|
+
sage: cubic = 3*x^3 + 4*y^3 + 5*z^3
|
|
1050
|
+
sage: EllipticCurve_from_cubic(cubic)
|
|
1051
|
+
Traceback (most recent call last):
|
|
1052
|
+
...
|
|
1053
|
+
ValueError: A point must be given when the cubic has no rational flexes
|
|
1054
|
+
|
|
1055
|
+
An example over a finite field, using a flex::
|
|
1056
|
+
|
|
1057
|
+
sage: K = GF(17)
|
|
1058
|
+
sage: R.<x,y,z> = K[]
|
|
1059
|
+
sage: cubic = 2*x^3 + 3*y^3 + 4*z^3
|
|
1060
|
+
sage: EllipticCurve_from_cubic(cubic, [0,3,1])
|
|
1061
|
+
Scheme morphism:
|
|
1062
|
+
From: Projective Plane Curve over Finite Field of size 17
|
|
1063
|
+
defined by 2*x^3 + 3*y^3 + 4*z^3
|
|
1064
|
+
To: Elliptic Curve defined by y^2 + 16*y = x^3 + 11 over Finite Field of size 17
|
|
1065
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
1066
|
+
(-x : 4*y : 4*y + 5*z)
|
|
1067
|
+
|
|
1068
|
+
An example in characteristic 3::
|
|
1069
|
+
|
|
1070
|
+
sage: K = GF(3)
|
|
1071
|
+
sage: R.<x,y,z> = K[]
|
|
1072
|
+
sage: cubic = x^3 + y^3 + z^3 + x*y*z
|
|
1073
|
+
sage: EllipticCurve_from_cubic(cubic, [0,1,-1])
|
|
1074
|
+
Scheme morphism:
|
|
1075
|
+
From: Projective Plane Curve over Finite Field of size 3
|
|
1076
|
+
defined by x^3 + y^3 + x*y*z + z^3
|
|
1077
|
+
To: Elliptic Curve defined by y^2 + x*y = x^3 + 1 over Finite Field of size 3
|
|
1078
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
1079
|
+
(y + z : -y : x)
|
|
1080
|
+
|
|
1081
|
+
An example over a number field, using a non-flex and where there are no rational flexes::
|
|
1082
|
+
|
|
1083
|
+
sage: # needs sage.rings.number_field
|
|
1084
|
+
sage: K.<a> = QuadraticField(-3)
|
|
1085
|
+
sage: R.<x,y,z> = K[]
|
|
1086
|
+
sage: cubic = 2*x^3 + 3*y^3 + 5*z^3
|
|
1087
|
+
sage: EllipticCurve_from_cubic(cubic, [1,1,-1])
|
|
1088
|
+
Scheme morphism:
|
|
1089
|
+
From: Projective Plane Curve over Number Field in a
|
|
1090
|
+
with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
|
|
1091
|
+
defined by 2*x^3 + 3*y^3 + 5*z^3
|
|
1092
|
+
To: Elliptic Curve defined by
|
|
1093
|
+
y^2 + 1754460/2053*x*y + 5226454388736000/8653002877*y
|
|
1094
|
+
= x^3 + (-652253285700/4214809)*x^2
|
|
1095
|
+
over Number Field in a with defining polynomial x^2 + 3
|
|
1096
|
+
with a = 1.732050807568878?*I
|
|
1097
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
1098
|
+
(-16424/127575*x^2 - 231989/680400*x*y - 14371/64800*y^2 - 26689/81648*x*z - 10265/27216*y*z - 2053/163296*z^2
|
|
1099
|
+
: 24496/315*x^2 + 119243/840*x*y + 4837/80*y^2 + 67259/504*x*z + 25507/168*y*z + 5135/1008*z^2
|
|
1100
|
+
: 8653002877/2099914709760000*x^2 + 8653002877/699971569920000*x*y + 8653002877/933295426560000*y^2 + 8653002877/419982941952000*x*z + 8653002877/279988627968000*y*z + 8653002877/335986353561600*z^2)
|
|
1101
|
+
|
|
1102
|
+
An example over a function field, using a non-flex::
|
|
1103
|
+
|
|
1104
|
+
sage: K.<t> = FunctionField(QQ)
|
|
1105
|
+
sage: R.<x,y,z> = K[]
|
|
1106
|
+
sage: cubic = x^3 + t*y^3 + (1+t)*z^3
|
|
1107
|
+
sage: EllipticCurve_from_cubic(cubic, [1,1,-1], morphism=False) # needs sage.libs.singular
|
|
1108
|
+
Elliptic Curve defined by y^2 + ((162*t^6+486*t^5+810*t^4+810*t^3+486*t^2+162*t)/(t^6+12*t^5-3*t^4-20*t^3-3*t^2+12*t+1))*x*y + ((314928*t^14+4094064*t^13+23462136*t^12+78102144*t^11+167561379*t^10+243026001*t^9+243026001*t^8+167561379*t^7+78102144*t^6+23462136*t^5+4094064*t^4+314928*t^3)/(t^14+40*t^13+577*t^12+3524*t^11+8075*t^10+5288*t^9-8661*t^8-17688*t^7-8661*t^6+5288*t^5+8075*t^4+3524*t^3+577*t^2+40*t+1))*y = x^3 + ((2187*t^12+13122*t^11-17496*t^10-207765*t^9-516132*t^8-673596*t^7-516132*t^6-207765*t^5-17496*t^4+13122*t^3+2187*t^2)/(t^12+24*t^11+138*t^10-112*t^9-477*t^8+72*t^7+708*t^6+72*t^5-477*t^4-112*t^3+138*t^2+24*t+1))*x^2
|
|
1109
|
+
over Rational function field in t over Rational Field
|
|
1110
|
+
|
|
1111
|
+
TESTS:
|
|
1112
|
+
|
|
1113
|
+
Here is a test for :issue:`21092`::
|
|
1114
|
+
|
|
1115
|
+
sage: R.<x,y,z> = QQ[]
|
|
1116
|
+
sage: cubic = -3*x^2*y + 3*x*y^2 + 4*x^2*z + 4*y^2*z - 3*x*z^2 + 3*y*z^2 - 8*z^3
|
|
1117
|
+
sage: EllipticCurve_from_cubic(cubic, (-4/5, 4/5, 3/5) )
|
|
1118
|
+
Scheme morphism:
|
|
1119
|
+
From: Projective Plane Curve over Rational Field defined
|
|
1120
|
+
by -3*x^2*y + 3*x*y^2 + 4*x^2*z + 4*y^2*z - 3*x*z^2 + 3*y*z^2 - 8*z^3
|
|
1121
|
+
To: Elliptic Curve defined by y^2 + 24*x*y + 3024*y = x^3 + 495*x^2 + 36288*x
|
|
1122
|
+
over Rational Field
|
|
1123
|
+
Defn: Defined on coordinates by sending (x : y : z) to
|
|
1124
|
+
(-1/3*z : 3*x : -1/1008*x + 1/1008*y + 1/378*z)
|
|
1125
|
+
"""
|
|
1126
|
+
from sage.schemes.curves.constructor import Curve
|
|
1127
|
+
from sage.matrix.constructor import Matrix
|
|
1128
|
+
from sage.schemes.elliptic_curves.weierstrass_transform import \
|
|
1129
|
+
WeierstrassTransformationWithInverse
|
|
1130
|
+
|
|
1131
|
+
# check the input
|
|
1132
|
+
R = F.parent()
|
|
1133
|
+
K = R.base_ring()
|
|
1134
|
+
if not isinstance(R, MPolynomialRing_base):
|
|
1135
|
+
raise TypeError('equation must be a polynomial')
|
|
1136
|
+
if R.ngens() != 3 or F.nvariables() != 3:
|
|
1137
|
+
raise TypeError('equation must be a polynomial in three variables')
|
|
1138
|
+
if not F.is_homogeneous():
|
|
1139
|
+
raise TypeError('equation must be a homogeneous polynomial')
|
|
1140
|
+
|
|
1141
|
+
C = Curve(F)
|
|
1142
|
+
if P:
|
|
1143
|
+
try:
|
|
1144
|
+
CP = C(P)
|
|
1145
|
+
except (TypeError, ValueError):
|
|
1146
|
+
raise TypeError('{} does not define a point on a projective curve over {} defined by {}'.format(P,K,F))
|
|
1147
|
+
|
|
1148
|
+
x, y, z = R.gens()
|
|
1149
|
+
|
|
1150
|
+
# Test whether P is a flex; if not test whether there are any rational flexes:
|
|
1151
|
+
|
|
1152
|
+
hessian = Matrix([[F.derivative(v1, v2) for v1 in R.gens()] for v2 in R.gens()]).det()
|
|
1153
|
+
if P and hessian(P) == 0:
|
|
1154
|
+
flex_point = P
|
|
1155
|
+
else:
|
|
1156
|
+
flexes = C.intersection(Curve(hessian)).rational_points()
|
|
1157
|
+
if flexes:
|
|
1158
|
+
flex_point = list(flexes[0])
|
|
1159
|
+
if not P:
|
|
1160
|
+
P = flex_point
|
|
1161
|
+
CP = C(P)
|
|
1162
|
+
else:
|
|
1163
|
+
flex_point = None
|
|
1164
|
+
|
|
1165
|
+
if flex_point is not None: # first case: base point is a flex
|
|
1166
|
+
P = flex_point
|
|
1167
|
+
L = tangent_at_smooth_point(C,P)
|
|
1168
|
+
dx, dy, dz = (L.coefficient(v) for v in R.gens())
|
|
1169
|
+
|
|
1170
|
+
# find an invertible matrix M such that (0,1,0)M=P and
|
|
1171
|
+
# ML'=(0,0,1)' where L=[dx,dy,dx]. Then the linear transform
|
|
1172
|
+
# by M takes P to [0,1,0] and L to Z=0:
|
|
1173
|
+
|
|
1174
|
+
if P[0]:
|
|
1175
|
+
Q1 = [0,-dz,dy]
|
|
1176
|
+
Q2 = [0,1,0] if dy else [0,0,1]
|
|
1177
|
+
elif P[1]:
|
|
1178
|
+
Q1 = [dz,0,-dx]
|
|
1179
|
+
Q2 = [1,0,0] if dx else [0,0,1]
|
|
1180
|
+
else:
|
|
1181
|
+
Q1 = [-dy,dx,0]
|
|
1182
|
+
Q2 = [1,0,0] if dx else [0,1,0]
|
|
1183
|
+
|
|
1184
|
+
M = Matrix(K,[Q1,P,Q2])
|
|
1185
|
+
# assert M.is_invertible()
|
|
1186
|
+
# assert list(vector([0,1,0])*M) == P
|
|
1187
|
+
# assert list(M*vector([dx,dy,dz]))[:2] == [0,0]
|
|
1188
|
+
|
|
1189
|
+
M = M.transpose()
|
|
1190
|
+
F2 = R(M.act_on_polynomial(F))
|
|
1191
|
+
|
|
1192
|
+
# scale and dehomogenise
|
|
1193
|
+
a = K(F2.coefficient(x**3))
|
|
1194
|
+
b = K(F2.coefficient(y*y*z))
|
|
1195
|
+
|
|
1196
|
+
F3 = F2([-x, y/b, z*a*b]) / a
|
|
1197
|
+
# assert F3.coefficient(x**3) == -1
|
|
1198
|
+
# assert F3.coefficient(y*y*z) == 1
|
|
1199
|
+
E = EllipticCurve(F3([x,y,1]))
|
|
1200
|
+
if not morphism:
|
|
1201
|
+
return E
|
|
1202
|
+
|
|
1203
|
+
# Construct the (linear) morphism
|
|
1204
|
+
M = M * Matrix(K,[[-1,0,0],[0,1/b,0],[0,0,a*b]])
|
|
1205
|
+
inv_defining_poly = [ M[i,0]*x + M[i,1]*y + M[i,2]*z for i in range(3) ]
|
|
1206
|
+
inv_post = 1/a
|
|
1207
|
+
M = M.inverse()
|
|
1208
|
+
fwd_defining_poly = [ M[i,0]*x + M[i,1]*y + M[i,2]*z for i in range(3) ]
|
|
1209
|
+
fwd_post = a
|
|
1210
|
+
|
|
1211
|
+
else: # Second case: no flexes
|
|
1212
|
+
if not P:
|
|
1213
|
+
raise ValueError('A point must be given when the cubic has no rational flexes')
|
|
1214
|
+
L = tangent_at_smooth_point(C,P)
|
|
1215
|
+
Qlist = [Q for Q in C.intersection(Curve(L)).rational_points() if C(Q) != CP]
|
|
1216
|
+
# assert Qlist
|
|
1217
|
+
P2 = C(Qlist[0])
|
|
1218
|
+
L2 = tangent_at_smooth_point(C,P2)
|
|
1219
|
+
Qlist = [Q for Q in C.intersection(Curve(L2)).rational_points() if C(Q) != P2]
|
|
1220
|
+
# assert Qlist
|
|
1221
|
+
P3 = C(Qlist[0])
|
|
1222
|
+
|
|
1223
|
+
# NB This construction of P3 relies on P2 not being a flex.
|
|
1224
|
+
# If we want to use a non-flex as P when there are rational
|
|
1225
|
+
# flexes this would be a problem. However, the only condition
|
|
1226
|
+
# which P3 must satisfy is that it is on the tangent at P2, it
|
|
1227
|
+
# need not lie on the cubic.
|
|
1228
|
+
|
|
1229
|
+
# send P, P2, P3 to (1:0:0), (0:1:0), (0:0:1) respectively
|
|
1230
|
+
M = Matrix(K, [P, list(P2), list(P3)]).transpose()
|
|
1231
|
+
F2 = M.act_on_polynomial(F)
|
|
1232
|
+
xyzM = [ M[i,0]*x + M[i,1]*y + M[i,2]*z for i in range(3) ]
|
|
1233
|
+
# assert F(xyzM)==F2
|
|
1234
|
+
|
|
1235
|
+
# substitute x = U^2, y = V*W, z = U*W, and rename (x,y,z)=(U,V,W)
|
|
1236
|
+
T1 = [x*x,y*z,x*z]
|
|
1237
|
+
S1 = x**2*z
|
|
1238
|
+
F3 = F2(T1) // S1
|
|
1239
|
+
xyzC = [ t(T1) for t in xyzM ]
|
|
1240
|
+
# assert F3 == F(xyzC) // S1
|
|
1241
|
+
|
|
1242
|
+
# scale and dehomogenise
|
|
1243
|
+
a = K(F3.coefficient(x**3))
|
|
1244
|
+
b = K(F3.coefficient(y*y*z))
|
|
1245
|
+
ab = a*b
|
|
1246
|
+
|
|
1247
|
+
T2 = [-x, y/b, ab*z]
|
|
1248
|
+
F4 = F3(T2) / a
|
|
1249
|
+
# assert F4.coefficient(x**3) == -1
|
|
1250
|
+
# assert F4.coefficient(y*y*z) == 1
|
|
1251
|
+
xyzW = [ t(T2) for t in xyzC ]
|
|
1252
|
+
S2 = a*S1(T2)
|
|
1253
|
+
# assert F4 == F(xyzW) // S2
|
|
1254
|
+
|
|
1255
|
+
E = EllipticCurve(F4([x,y,1]))
|
|
1256
|
+
if not morphism:
|
|
1257
|
+
return E
|
|
1258
|
+
|
|
1259
|
+
inv_defining_poly = xyzW
|
|
1260
|
+
inv_post = 1/S2
|
|
1261
|
+
# assert F4==F(inv_defining_poly)*inv_post
|
|
1262
|
+
MI = M.inverse()
|
|
1263
|
+
xyzI = [ (MI[i,0]*x + MI[i,1]*y + MI[i,2]*z) for i in range(3) ]
|
|
1264
|
+
T1I = [x*z,x*y,z*z] # inverse of T1
|
|
1265
|
+
xyzIC = [ t(xyzI) for t in T1I ]
|
|
1266
|
+
T2I = [-x, b*y, z/ab] # inverse of T2
|
|
1267
|
+
xyzIW = [ t(xyzIC) for t in T2I ]
|
|
1268
|
+
fwd_defining_poly = xyzIW
|
|
1269
|
+
fwd_post = a/(x*z*z)(xyzI)
|
|
1270
|
+
# assert F4(fwd_defining_poly)*fwd_post == F
|
|
1271
|
+
|
|
1272
|
+
# Construct the morphism
|
|
1273
|
+
|
|
1274
|
+
return WeierstrassTransformationWithInverse(
|
|
1275
|
+
C, E, fwd_defining_poly, fwd_post, inv_defining_poly, inv_post)
|
|
1276
|
+
|
|
1277
|
+
|
|
1278
|
+
def tangent_at_smooth_point(C, P):
|
|
1279
|
+
r"""Return the tangent at the smooth point `P` of projective curve `C`.
|
|
1280
|
+
|
|
1281
|
+
INPUT:
|
|
1282
|
+
|
|
1283
|
+
- ``C`` -- a projective plane curve
|
|
1284
|
+
|
|
1285
|
+
- ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on `C`
|
|
1286
|
+
|
|
1287
|
+
OUTPUT: the linear form defining the tangent at `P` to `C`
|
|
1288
|
+
|
|
1289
|
+
EXAMPLES::
|
|
1290
|
+
|
|
1291
|
+
sage: R.<x,y,z> = QQ[]
|
|
1292
|
+
sage: from sage.schemes.elliptic_curves.constructor import tangent_at_smooth_point
|
|
1293
|
+
sage: C = Curve(x^3 + y^3 + 60*z^3)
|
|
1294
|
+
sage: tangent_at_smooth_point(C, [1,-1,0])
|
|
1295
|
+
x + y
|
|
1296
|
+
|
|
1297
|
+
sage: K.<t> = FunctionField(QQ)
|
|
1298
|
+
sage: R.<x,y,z> = K[]
|
|
1299
|
+
sage: C = Curve(x^3 + 2*y^3 + 3*z^3)
|
|
1300
|
+
sage: from sage.schemes.elliptic_curves.constructor import tangent_at_smooth_point
|
|
1301
|
+
sage: tangent_at_smooth_point(C,[1,1,-1])
|
|
1302
|
+
3*x + 6*y + 9*z
|
|
1303
|
+
"""
|
|
1304
|
+
# Over function fields such as QQ(t) an error is raised with the
|
|
1305
|
+
# default (factor=True). Note that factor=False returns the
|
|
1306
|
+
# product of the tangents in case of a multiple point, while here
|
|
1307
|
+
# `P` is assumed smooth so factorization is unnecessary, but over
|
|
1308
|
+
# QQ (for example) including the factorization gives better
|
|
1309
|
+
# results, for example returning x+y instead of 3x+3y in the
|
|
1310
|
+
# doctest.
|
|
1311
|
+
try:
|
|
1312
|
+
return C.tangents(P)[0]
|
|
1313
|
+
except NotImplementedError:
|
|
1314
|
+
return C.tangents(P,factor=False)[0]
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
def chord_and_tangent(F, P):
|
|
1318
|
+
r"""Return the third point of intersection of a cubic with the tangent at one point.
|
|
1319
|
+
|
|
1320
|
+
INPUT:
|
|
1321
|
+
|
|
1322
|
+
- ``F`` -- a homogeneous cubic in three variables with rational
|
|
1323
|
+
coefficients, as a polynomial ring element, defining a smooth
|
|
1324
|
+
plane cubic curve.
|
|
1325
|
+
|
|
1326
|
+
- ``P`` -- a 3-tuple `(x,y,z)` defining a projective point on the
|
|
1327
|
+
curve `F=0`
|
|
1328
|
+
|
|
1329
|
+
OUTPUT:
|
|
1330
|
+
|
|
1331
|
+
A point ``Q`` such that ``F(Q)=0``, namely the third point of
|
|
1332
|
+
intersection of the tangent at ``P`` with the curve ``F=0``, so
|
|
1333
|
+
``Q=P`` if and only if ``P`` is a flex.
|
|
1334
|
+
|
|
1335
|
+
EXAMPLES::
|
|
1336
|
+
|
|
1337
|
+
sage: R.<x,y,z> = QQ[]
|
|
1338
|
+
sage: from sage.schemes.elliptic_curves.constructor import chord_and_tangent
|
|
1339
|
+
sage: F = x^3 + y^3 + 60*z^3
|
|
1340
|
+
sage: chord_and_tangent(F, [1,-1,0])
|
|
1341
|
+
(-1 : 1 : 0)
|
|
1342
|
+
|
|
1343
|
+
sage: F = x^3 + 7*y^3 + 64*z^3
|
|
1344
|
+
sage: p0 = [2,2,-1]
|
|
1345
|
+
sage: p1 = chord_and_tangent(F, p0); p1
|
|
1346
|
+
(5 : -3 : 1)
|
|
1347
|
+
sage: p2 = chord_and_tangent(F, p1); p2
|
|
1348
|
+
(-1265/314 : 183/314 : 1)
|
|
1349
|
+
|
|
1350
|
+
TESTS::
|
|
1351
|
+
|
|
1352
|
+
sage: F(list(p2))
|
|
1353
|
+
0
|
|
1354
|
+
sage: list(map(type, p2))
|
|
1355
|
+
[<... 'sage.rings.rational.Rational'>,
|
|
1356
|
+
<... 'sage.rings.rational.Rational'>,
|
|
1357
|
+
<... 'sage.rings.rational.Rational'>]
|
|
1358
|
+
|
|
1359
|
+
See :issue:`16068`::
|
|
1360
|
+
|
|
1361
|
+
sage: F = x**3 - 4*x**2*y - 65*x*y**2 + 3*x*y*z - 76*y*z**2
|
|
1362
|
+
sage: chord_and_tangent(F, [0, 1, 0])
|
|
1363
|
+
(0 : 0 : 1)
|
|
1364
|
+
"""
|
|
1365
|
+
from sage.schemes.curves.constructor import Curve
|
|
1366
|
+
# check the input
|
|
1367
|
+
R = F.parent()
|
|
1368
|
+
if not isinstance(R, MPolynomialRing_base):
|
|
1369
|
+
raise TypeError('equation must be a polynomial')
|
|
1370
|
+
if R.ngens() != 3:
|
|
1371
|
+
raise TypeError('{} is not a polynomial in three variables'.format(F))
|
|
1372
|
+
if not F.is_homogeneous():
|
|
1373
|
+
raise TypeError('{} is not a homogeneous polynomial'.format(F))
|
|
1374
|
+
x, y, z = R.gens()
|
|
1375
|
+
if len(P) != 3:
|
|
1376
|
+
raise TypeError('{} is not a projective point'.format(P))
|
|
1377
|
+
K = R.base_ring()
|
|
1378
|
+
try:
|
|
1379
|
+
C = Curve(F)
|
|
1380
|
+
P = C(P)
|
|
1381
|
+
except (TypeError, ValueError):
|
|
1382
|
+
raise TypeError('{} does not define a point on a projective curve over {} defined by {}'.format(P,K,F))
|
|
1383
|
+
|
|
1384
|
+
L = Curve(tangent_at_smooth_point(C,P))
|
|
1385
|
+
Qlist = [Q for Q in C.intersection(L).rational_points() if Q != P]
|
|
1386
|
+
if Qlist:
|
|
1387
|
+
return Qlist[0]
|
|
1388
|
+
return P
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
def projective_point(p):
|
|
1392
|
+
r"""
|
|
1393
|
+
Return equivalent point with denominators removed.
|
|
1394
|
+
|
|
1395
|
+
INPUT:
|
|
1396
|
+
|
|
1397
|
+
- ``P``, ``Q`` -- list/tuple of projective coordinates
|
|
1398
|
+
|
|
1399
|
+
OUTPUT: list of projective coordinates
|
|
1400
|
+
|
|
1401
|
+
EXAMPLES::
|
|
1402
|
+
|
|
1403
|
+
sage: from sage.schemes.elliptic_curves.constructor import projective_point
|
|
1404
|
+
sage: projective_point([4/5, 6/5, 8/5])
|
|
1405
|
+
[2, 3, 4]
|
|
1406
|
+
sage: F = GF(11)
|
|
1407
|
+
sage: projective_point([F(4), F(8), F(2)])
|
|
1408
|
+
[4, 8, 2]
|
|
1409
|
+
"""
|
|
1410
|
+
from sage.rings.integer import GCD_list
|
|
1411
|
+
from sage.arith.functions import LCM_list
|
|
1412
|
+
try:
|
|
1413
|
+
p_gcd = GCD_list([x.numerator() for x in p])
|
|
1414
|
+
p_lcm = LCM_list(x.denominator() for x in p)
|
|
1415
|
+
except AttributeError:
|
|
1416
|
+
return p
|
|
1417
|
+
scale = p_lcm / p_gcd
|
|
1418
|
+
return [scale * x for x in p]
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
def are_projectively_equivalent(P, Q, base_ring):
|
|
1422
|
+
r"""
|
|
1423
|
+
Test whether ``P`` and ``Q`` are projectively equivalent.
|
|
1424
|
+
|
|
1425
|
+
INPUT:
|
|
1426
|
+
|
|
1427
|
+
- ``P``, ``Q`` -- list/tuple of projective coordinates
|
|
1428
|
+
|
|
1429
|
+
- ``base_ring`` -- the base ring
|
|
1430
|
+
|
|
1431
|
+
OUTPUT: boolean
|
|
1432
|
+
|
|
1433
|
+
EXAMPLES::
|
|
1434
|
+
|
|
1435
|
+
sage: from sage.schemes.elliptic_curves.constructor import are_projectively_equivalent
|
|
1436
|
+
sage: are_projectively_equivalent([0,1,2,3], [0,1,2,2], base_ring=QQ)
|
|
1437
|
+
False
|
|
1438
|
+
sage: are_projectively_equivalent([0,1,2,3], [0,2,4,6], base_ring=QQ)
|
|
1439
|
+
True
|
|
1440
|
+
"""
|
|
1441
|
+
from sage.matrix.constructor import matrix
|
|
1442
|
+
return matrix(base_ring, [P, Q]).rank() < 2
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
def EllipticCurves_with_good_reduction_outside_S(S=[], proof=None, verbose=False):
|
|
1446
|
+
r"""
|
|
1447
|
+
Return a sorted list of all elliptic curves defined over `\QQ`
|
|
1448
|
+
with good reduction outside the set `S` of primes.
|
|
1449
|
+
|
|
1450
|
+
INPUT:
|
|
1451
|
+
|
|
1452
|
+
- ``S`` -- list of primes (default: empty list)
|
|
1453
|
+
|
|
1454
|
+
- ``proof`` -- boolean (default: ``True``); the MW basis for
|
|
1455
|
+
auxiliary curves will be computed with this proof flag
|
|
1456
|
+
|
|
1457
|
+
- ``verbose`` -- boolean (default: ``False``); if ``True``, some details
|
|
1458
|
+
of the computation will be output
|
|
1459
|
+
|
|
1460
|
+
.. NOTE::
|
|
1461
|
+
|
|
1462
|
+
Proof flag: The algorithm used requires determining all
|
|
1463
|
+
S-integral points on several auxiliary curves, which in turn
|
|
1464
|
+
requires the computation of their generators. This is not
|
|
1465
|
+
always possible (even in theory) using current knowledge.
|
|
1466
|
+
|
|
1467
|
+
The value of this flag is passed to the function which
|
|
1468
|
+
computes generators of various auxiliary elliptic curves, in
|
|
1469
|
+
order to find their S-integral points. Set to ``False`` if the
|
|
1470
|
+
default (``True``) causes warning messages, but note that you can
|
|
1471
|
+
then not rely on the set of curves returned being
|
|
1472
|
+
complete.
|
|
1473
|
+
|
|
1474
|
+
EXAMPLES::
|
|
1475
|
+
|
|
1476
|
+
sage: # needs eclib sage.symbolic
|
|
1477
|
+
sage: EllipticCurves_with_good_reduction_outside_S([])
|
|
1478
|
+
[]
|
|
1479
|
+
sage: elist = EllipticCurves_with_good_reduction_outside_S([2])
|
|
1480
|
+
sage: elist
|
|
1481
|
+
[Elliptic Curve defined by y^2 = x^3 + 4*x over Rational Field,
|
|
1482
|
+
Elliptic Curve defined by y^2 = x^3 - x over Rational Field,
|
|
1483
|
+
...
|
|
1484
|
+
Elliptic Curve defined by y^2 = x^3 - x^2 - 13*x + 21 over Rational Field]
|
|
1485
|
+
sage: len(elist)
|
|
1486
|
+
24
|
|
1487
|
+
sage: ', '.join(e.label() for e in elist)
|
|
1488
|
+
'32a1, 32a2, 32a3, 32a4, 64a1, 64a2, 64a3, 64a4, 128a1, 128a2, 128b1, 128b2, 128c1, 128c2, 128d1, 128d2, 256a1, 256a2, 256b1, 256b2, 256c1, 256c2, 256d1, 256d2'
|
|
1489
|
+
|
|
1490
|
+
Without ``Proof=False``, this example gives two warnings::
|
|
1491
|
+
|
|
1492
|
+
sage: # needs eclib sage.symbolic
|
|
1493
|
+
sage: elist = EllipticCurves_with_good_reduction_outside_S([11], proof=False) # long time (14s on sage.math, 2011)
|
|
1494
|
+
sage: len(elist) # long time
|
|
1495
|
+
12
|
|
1496
|
+
sage: ', '.join(e.label() for e in elist) # long time
|
|
1497
|
+
'11a1, 11a2, 11a3, 121a1, 121a2, 121b1, 121b2, 121c1, 121c2, 121d1, 121d2, 121d3'
|
|
1498
|
+
|
|
1499
|
+
sage: # long time, needs eclib sage.symbolic
|
|
1500
|
+
sage: elist = EllipticCurves_with_good_reduction_outside_S([2,3]) # long time (26s on sage.math, 2011)
|
|
1501
|
+
sage: len(elist)
|
|
1502
|
+
752
|
|
1503
|
+
sage: conds = sorted(set([e.conductor() for e in elist]))
|
|
1504
|
+
sage: max(conds)
|
|
1505
|
+
62208
|
|
1506
|
+
sage: [N.factor() for N in conds]
|
|
1507
|
+
[2^3 * 3,
|
|
1508
|
+
3^3,
|
|
1509
|
+
2^5,
|
|
1510
|
+
2^2 * 3^2,
|
|
1511
|
+
2^4 * 3,
|
|
1512
|
+
2 * 3^3,
|
|
1513
|
+
2^6,
|
|
1514
|
+
2^3 * 3^2,
|
|
1515
|
+
2^5 * 3,
|
|
1516
|
+
2^2 * 3^3,
|
|
1517
|
+
2^7,
|
|
1518
|
+
2^4 * 3^2,
|
|
1519
|
+
2 * 3^4,
|
|
1520
|
+
2^6 * 3,
|
|
1521
|
+
2^3 * 3^3,
|
|
1522
|
+
3^5,
|
|
1523
|
+
2^8,
|
|
1524
|
+
2^5 * 3^2,
|
|
1525
|
+
2^2 * 3^4,
|
|
1526
|
+
2^7 * 3,
|
|
1527
|
+
2^4 * 3^3,
|
|
1528
|
+
2 * 3^5,
|
|
1529
|
+
2^6 * 3^2,
|
|
1530
|
+
2^3 * 3^4,
|
|
1531
|
+
2^8 * 3,
|
|
1532
|
+
2^5 * 3^3,
|
|
1533
|
+
2^2 * 3^5,
|
|
1534
|
+
2^7 * 3^2,
|
|
1535
|
+
2^4 * 3^4,
|
|
1536
|
+
2^6 * 3^3,
|
|
1537
|
+
2^3 * 3^5,
|
|
1538
|
+
2^8 * 3^2,
|
|
1539
|
+
2^5 * 3^4,
|
|
1540
|
+
2^7 * 3^3,
|
|
1541
|
+
2^4 * 3^5,
|
|
1542
|
+
2^6 * 3^4,
|
|
1543
|
+
2^8 * 3^3,
|
|
1544
|
+
2^5 * 3^5,
|
|
1545
|
+
2^7 * 3^4,
|
|
1546
|
+
2^6 * 3^5,
|
|
1547
|
+
2^8 * 3^4,
|
|
1548
|
+
2^7 * 3^5,
|
|
1549
|
+
2^8 * 3^5]
|
|
1550
|
+
"""
|
|
1551
|
+
from .ell_egros import egros_from_jlist, egros_get_j
|
|
1552
|
+
return egros_from_jlist(egros_get_j(S, proof=proof, verbose=verbose), S)
|