passagemath-pari 10.6.32__cp314-cp314-musllinux_1_2_x86_64.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-pari might be problematic. Click here for more details.
- PARIKernel/__init__.py +2 -0
- PARIKernel/__main__.py +5 -0
- PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/io.pxd +7 -0
- PARIKernel/io.pyx +84 -0
- PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/kernel.pyx +260 -0
- PARIKernel/paridecl.pxd +95 -0
- PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/svg.pyx +52 -0
- cypari2/__init__.py +8 -0
- cypari2/auto_paridecl.pxd +1070 -0
- cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/closure.pxd +5 -0
- cypari2/closure.pyx +246 -0
- cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/convert.pxd +80 -0
- cypari2/convert.pyx +613 -0
- cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/custom_block.pyx +30 -0
- cypari2/cypari.h +13 -0
- cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/gen.pxd +69 -0
- cypari2/gen.pyx +4819 -0
- cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/handle_error.pxd +7 -0
- cypari2/handle_error.pyx +232 -0
- cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/pari_instance.pxd +27 -0
- cypari2/pari_instance.pyx +1438 -0
- cypari2/paridecl.pxd +5353 -0
- cypari2/paripriv.pxd +34 -0
- cypari2/pycore_long.h +98 -0
- cypari2/pycore_long.pxd +9 -0
- cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/stack.pxd +27 -0
- cypari2/stack.pyx +278 -0
- cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/string_utils.pxd +29 -0
- cypari2/string_utils.pyx +65 -0
- cypari2/types.pxd +147 -0
- passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
- passagemath_pari-10.6.32.dist-info/METADATA +209 -0
- passagemath_pari-10.6.32.dist-info/RECORD +331 -0
- passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
- passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
- passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
- passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
- passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
- passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
- passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
- passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
- passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
- passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
- passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
- passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
- passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
- passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
- passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
- passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
- sage/all__sagemath_pari.py +26 -0
- sage/databases/all__sagemath_pari.py +7 -0
- sage/databases/conway.py +274 -0
- sage/ext/all__sagemath_pari.py +1 -0
- sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
- sage/ext/memory.pyx +98 -0
- sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
- sage/ext_data/pari/buzzard/Tpprog.g +179 -0
- sage/ext_data/pari/buzzard/genusn.g +129 -0
- sage/ext_data/pari/dokchitser/computel.gp +740 -0
- sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
- sage/ext_data/pari/dokchitser/ex-bsw +43 -0
- sage/ext_data/pari/dokchitser/ex-chgen +48 -0
- sage/ext_data/pari/dokchitser/ex-chqua +37 -0
- sage/ext_data/pari/dokchitser/ex-delta +35 -0
- sage/ext_data/pari/dokchitser/ex-eisen +30 -0
- sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
- sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
- sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
- sage/ext_data/pari/dokchitser/ex-nf +48 -0
- sage/ext_data/pari/dokchitser/ex-shin +50 -0
- sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
- sage/ext_data/pari/dokchitser/ex-zeta +27 -0
- sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
- sage/ext_data/pari/dokchitser/testall +13 -0
- sage/ext_data/pari/simon/ell.gp +2129 -0
- sage/ext_data/pari/simon/ellQ.gp +2151 -0
- sage/ext_data/pari/simon/ellcommon.gp +126 -0
- sage/ext_data/pari/simon/qfsolve.gp +722 -0
- sage/ext_data/pari/simon/resultant3.gp +306 -0
- sage/groups/all__sagemath_pari.py +3 -0
- sage/groups/pari_group.py +175 -0
- sage/interfaces/all__sagemath_pari.py +1 -0
- sage/interfaces/genus2reduction.py +464 -0
- sage/interfaces/gp.py +1114 -0
- sage/libs/all__sagemath_pari.py +2 -0
- sage/libs/linkages/__init__.py +1 -0
- sage/libs/linkages/padics/API.pxi +617 -0
- sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
- sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
- sage/libs/linkages/padics/__init__.py +1 -0
- sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
- sage/libs/linkages/padics/mpz.pxi +691 -0
- sage/libs/linkages/padics/relaxed/API.pxi +518 -0
- sage/libs/linkages/padics/relaxed/__init__.py +1 -0
- sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
- sage/libs/linkages/padics/unram_shared.pxi +247 -0
- sage/libs/pari/__init__.py +210 -0
- sage/libs/pari/all.py +5 -0
- sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_flint.pxd +14 -0
- sage/libs/pari/convert_flint.pyx +159 -0
- sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_gmp.pxd +14 -0
- sage/libs/pari/convert_gmp.pyx +210 -0
- sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage.pxd +16 -0
- sage/libs/pari/convert_sage.pyx +588 -0
- sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_complex_double.pxd +14 -0
- sage/libs/pari/convert_sage_complex_double.pyx +132 -0
- sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_matrix.pyx +106 -0
- sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_double.pxd +5 -0
- sage/libs/pari/convert_sage_real_double.pyx +14 -0
- sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
- sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
- sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/misc.pxd +4 -0
- sage/libs/pari/misc.pyx +26 -0
- sage/libs/pari/tests.py +1848 -0
- sage/matrix/all__sagemath_pari.py +1 -0
- sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_integer_pari.pyx +187 -0
- sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_rational_pari.pyx +160 -0
- sage/quadratic_forms/all__sagemath_pari.py +10 -0
- sage/quadratic_forms/genera/all.py +9 -0
- sage/quadratic_forms/genera/genus.py +3506 -0
- sage/quadratic_forms/genera/normal_form.py +1519 -0
- sage/quadratic_forms/genera/spinor_genus.py +243 -0
- sage/quadratic_forms/qfsolve.py +255 -0
- sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
- sage/quadratic_forms/quadratic_form__genus.py +141 -0
- sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
- sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
- sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
- sage/quadratic_forms/quadratic_form__mass.py +69 -0
- sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
- sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
- sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
- sage/quadratic_forms/special_values.py +323 -0
- sage/rings/all__sagemath_pari.py +15 -0
- sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/factorint_pari.pyx +80 -0
- sage/rings/finite_rings/all__sagemath_pari.py +1 -0
- sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_givaro.pxd +91 -0
- sage/rings/finite_rings/element_givaro.pyx +1769 -0
- sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
- sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
- sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
- sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
- sage/rings/finite_rings/finite_field_givaro.py +612 -0
- sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
- sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
- sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
- sage/rings/function_field/all__sagemath_pari.py +1 -0
- sage/rings/function_field/valuation.py +1450 -0
- sage/rings/function_field/valuation_ring.py +212 -0
- sage/rings/number_field/all__sagemath_pari.py +14 -0
- sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal.pyx +509 -0
- sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal_data.pxd +26 -0
- sage/rings/number_field/totallyreal_data.pyx +928 -0
- sage/rings/number_field/totallyreal_phc.py +144 -0
- sage/rings/number_field/totallyreal_rel.py +1018 -0
- sage/rings/padics/CA_template.pxi +1847 -0
- sage/rings/padics/CA_template_header.pxi +50 -0
- sage/rings/padics/CR_template.pxi +2563 -0
- sage/rings/padics/CR_template_header.pxi +57 -0
- sage/rings/padics/FM_template.pxi +1575 -0
- sage/rings/padics/FM_template_header.pxi +50 -0
- sage/rings/padics/FP_template.pxi +2176 -0
- sage/rings/padics/FP_template_header.pxi +57 -0
- sage/rings/padics/all.py +3 -0
- sage/rings/padics/all__sagemath_pari.py +11 -0
- sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/common_conversion.pxd +15 -0
- sage/rings/padics/common_conversion.pyx +508 -0
- sage/rings/padics/eisenstein_extension_generic.py +232 -0
- sage/rings/padics/factory.py +3623 -0
- sage/rings/padics/generic_nodes.py +1615 -0
- sage/rings/padics/lattice_precision.py +2889 -0
- sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/morphism.pxd +11 -0
- sage/rings/padics/morphism.pyx +366 -0
- sage/rings/padics/padic_base_generic.py +467 -0
- sage/rings/padics/padic_base_leaves.py +1235 -0
- sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
- sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
- sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_relative_element.pxd +14 -0
- sage/rings/padics/padic_capped_relative_element.pyx +614 -0
- sage/rings/padics/padic_extension_generic.py +990 -0
- sage/rings/padics/padic_extension_leaves.py +738 -0
- sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
- sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
- sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_floating_point_element.pxd +14 -0
- sage/rings/padics/padic_floating_point_element.pyx +447 -0
- sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_generic_element.pxd +48 -0
- sage/rings/padics/padic_generic_element.pyx +4642 -0
- sage/rings/padics/padic_lattice_element.py +1342 -0
- sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_printing.pxd +38 -0
- sage/rings/padics/padic_printing.pyx +1505 -0
- sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_element.pxd +56 -0
- sage/rings/padics/padic_relaxed_element.pyx +18 -0
- sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_errors.pxd +11 -0
- sage/rings/padics/padic_relaxed_errors.pyx +71 -0
- sage/rings/padics/padic_template_element.pxi +1212 -0
- sage/rings/padics/padic_template_element_header.pxi +50 -0
- sage/rings/padics/padic_valuation.py +1423 -0
- sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_flint.pxd +38 -0
- sage/rings/padics/pow_computer_flint.pyx +641 -0
- sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_relative.pxd +29 -0
- sage/rings/padics/pow_computer_relative.pyx +415 -0
- sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CA.pxd +21 -0
- sage/rings/padics/qadic_flint_CA.pyx +130 -0
- sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CR.pxd +13 -0
- sage/rings/padics/qadic_flint_CR.pyx +172 -0
- sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FM.pxd +14 -0
- sage/rings/padics/qadic_flint_FM.pyx +111 -0
- sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FP.pxd +12 -0
- sage/rings/padics/qadic_flint_FP.pyx +165 -0
- sage/rings/padics/relative_extension_leaves.py +429 -0
- sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CA.pxd +9 -0
- sage/rings/padics/relative_ramified_CA.pyx +33 -0
- sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CR.pxd +8 -0
- sage/rings/padics/relative_ramified_CR.pyx +33 -0
- sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FM.pxd +9 -0
- sage/rings/padics/relative_ramified_FM.pyx +33 -0
- sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FP.pxd +8 -0
- sage/rings/padics/relative_ramified_FP.pyx +33 -0
- sage/rings/padics/relaxed_template.pxi +4229 -0
- sage/rings/padics/relaxed_template_header.pxi +160 -0
- sage/rings/padics/tests.py +35 -0
- sage/rings/padics/tutorial.py +341 -0
- sage/rings/padics/unramified_extension_generic.py +335 -0
- sage/rings/padics/witt_vector.py +917 -0
- sage/rings/padics/witt_vector_ring.py +934 -0
- sage/rings/pari_ring.py +235 -0
- sage/rings/polynomial/all__sagemath_pari.py +1 -0
- sage/rings/polynomial/padics/all.py +1 -0
- sage/rings/polynomial/padics/polynomial_padic.py +360 -0
- sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
- sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
- sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/power_series_pari.pxd +6 -0
- sage/rings/power_series_pari.pyx +934 -0
- sage/rings/tate_algebra.py +1282 -0
- sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_element.pxd +49 -0
- sage/rings/tate_algebra_element.pyx +3464 -0
- sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_ideal.pxd +7 -0
- sage/rings/tate_algebra_ideal.pyx +1307 -0
- sage/rings/valuation/all.py +7 -0
- sage/rings/valuation/augmented_valuation.py +2118 -0
- sage/rings/valuation/developing_valuation.py +362 -0
- sage/rings/valuation/gauss_valuation.py +812 -0
- sage/rings/valuation/inductive_valuation.py +1686 -0
- sage/rings/valuation/limit_valuation.py +946 -0
- sage/rings/valuation/mapped_valuation.py +656 -0
- sage/rings/valuation/scaled_valuation.py +322 -0
- sage/rings/valuation/trivial_valuation.py +382 -0
- sage/rings/valuation/valuation.py +1119 -0
- sage/rings/valuation/valuation_space.py +1615 -0
- sage/rings/valuation/valuations_catalog.py +10 -0
- sage/rings/valuation/value_group.py +697 -0
- sage/schemes/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
- sage_wheels/bin/gp +0 -0
- sage_wheels/bin/gp2c +0 -0
- sage_wheels/bin/gp2c-run +57 -0
- sage_wheels/bin/xeus-gp +0 -0
- sage_wheels/share/gp2c/func.dsc +18414 -0
|
@@ -0,0 +1,2151 @@
|
|
|
1
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
2
|
+
\\ Copyright (C) 2014 Denis Simon
|
|
3
|
+
\\
|
|
4
|
+
\\ Distributed under the terms of the GNU General Public License (GPL)
|
|
5
|
+
\\
|
|
6
|
+
\\ This code is distributed in the hope that it will be useful,
|
|
7
|
+
\\ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
8
|
+
\\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
9
|
+
\\ General Public License for more details.
|
|
10
|
+
\\
|
|
11
|
+
\\ The full text of the GPL is available at:
|
|
12
|
+
\\
|
|
13
|
+
\\ http://www.gnu.org/licenses/
|
|
14
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
Auteur :
|
|
18
|
+
Denis SIMON -> simon@math.unicaen.fr
|
|
19
|
+
adresse du fichier :
|
|
20
|
+
www.math.unicaen.fr/~simon/ellQ.gp
|
|
21
|
+
|
|
22
|
+
*********************************************
|
|
23
|
+
* VERSION 13/01/2014 *
|
|
24
|
+
*********************************************
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
28
|
+
\\ English \\
|
|
29
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
30
|
+
|
|
31
|
+
This package provides functions to compute the rank of elliptic
|
|
32
|
+
curves over Q using 2-descent.
|
|
33
|
+
This package requires the other package qfsolve.gp downloadable at
|
|
34
|
+
www.math.unicaen.fr/~simon/qfsolve.gp
|
|
35
|
+
It also requires the package ellcommon.gp downloadable at
|
|
36
|
+
www.math.unicaen.fr/~simon/ellcommon.gp
|
|
37
|
+
|
|
38
|
+
They can be run under GP by the commands
|
|
39
|
+
gp > \r qfsolve.gp
|
|
40
|
+
gp > \r ellcommon.gp
|
|
41
|
+
gp > \r ellQ.gp
|
|
42
|
+
|
|
43
|
+
The main function is ellQ_ellrank(), which takes as an argument
|
|
44
|
+
any elliptic curve in the form [a1,a2,a3,a4,a6]
|
|
45
|
+
the result is a vector [r,s,v], where
|
|
46
|
+
r is a lower bound for the rank,
|
|
47
|
+
s is the rank of the 2-Selmer group
|
|
48
|
+
v is a set of independant points in E(Q)/2E(Q).
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
|
|
52
|
+
gp > ell = [1,2,3,4,5];
|
|
53
|
+
gp > ellQ_ellrank(ell)
|
|
54
|
+
%1 = [1, 1, [[1,2]]
|
|
55
|
+
In this example, the rank is exactly 1, and [1,2] has infinite order.
|
|
56
|
+
|
|
57
|
+
more details on the computations may be obtained by setting
|
|
58
|
+
DEBUGLEVEL_ell = 1 (the higher value, the more details)
|
|
59
|
+
|
|
60
|
+
Other functions:
|
|
61
|
+
|
|
62
|
+
ell2descent_complete, ell2descent_gen, ell2descent_viaisog,
|
|
63
|
+
ellhalf, ellredgen, ellsort, elltors2, elltorseven,
|
|
64
|
+
locallysoluble, ratpoint, redquartic,
|
|
65
|
+
bnfpSelmer, reducemodsquares
|
|
66
|
+
|
|
67
|
+
Quick information is obtained by typing
|
|
68
|
+
gp > ?NameOfTheFunction
|
|
69
|
+
|
|
70
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
71
|
+
\\ Comment utiliser ce programme ? \\
|
|
72
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
73
|
+
|
|
74
|
+
Ce module contient des fonctions pour calculer le rang des courbes
|
|
75
|
+
elliptiques sur Q, en utilisant la 2-descente.
|
|
76
|
+
langage : GP
|
|
77
|
+
|
|
78
|
+
Ce module utilise les modules complementaires suivants :
|
|
79
|
+
qfsolve.gp
|
|
80
|
+
ellcommon.gp
|
|
81
|
+
qui sont disponibles a l'adresse
|
|
82
|
+
www.math.unicaen.fr/~simon/qfsolve.gp
|
|
83
|
+
www.math.unicaen.fr/~simon/ellcommon.gp
|
|
84
|
+
|
|
85
|
+
Pour l'utiliser, lancer gp, puis taper
|
|
86
|
+
\r qfsolve.gp
|
|
87
|
+
\r ellcommon.gp
|
|
88
|
+
\r ellQ.gp
|
|
89
|
+
|
|
90
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
91
|
+
\\ Description des principales fonctions \\
|
|
92
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
93
|
+
|
|
94
|
+
Explications succintes :
|
|
95
|
+
La fonction ellQ_ellrank() accepte toutes les courbes sous la forme
|
|
96
|
+
[a1,a2,a3,a4,a6]
|
|
97
|
+
Les coefficients peuvent etre entiers ou non.
|
|
98
|
+
L'algorithme utilise est celui de la 2-descente.
|
|
99
|
+
La 2-torsion peut etre quelconque.
|
|
100
|
+
Il suffit de taper :
|
|
101
|
+
|
|
102
|
+
gp > ell = [a1,a2,a3,a4,a6];
|
|
103
|
+
gp > ellQ_ellrank(ell)
|
|
104
|
+
|
|
105
|
+
Retourne un vecteur [r,s,v] ou
|
|
106
|
+
r est le rang probable (c'est toujours une minoration du rang),
|
|
107
|
+
s est le 2-rang du groupe de Selmer,
|
|
108
|
+
v est une liste de points independants dans E(Q)/2E(Q).
|
|
109
|
+
|
|
110
|
+
Exemple :
|
|
111
|
+
|
|
112
|
+
gp > ell = [1,2,3,4,5];
|
|
113
|
+
gp > ellQ_ellrank(ell)
|
|
114
|
+
%1 = [1, 1, [[1,2]]
|
|
115
|
+
Ici, le rang est exactement 1, et le point [1,2] est d'ordre infini.
|
|
116
|
+
|
|
117
|
+
Courbes de la forme : k*y^2 = x^3+A*x^2+B*x+C
|
|
118
|
+
sans 2-torsion, A,B,C entiers.
|
|
119
|
+
gp > bnf = bnfinit(x^3+A*x^2+B*x+C);
|
|
120
|
+
gp > ell = ellinit([0,A,0,B,C]);
|
|
121
|
+
gp > rank = ell2descent_gen(ell,bnf,k);
|
|
122
|
+
|
|
123
|
+
Courbes avec #E[2](Q) >= 2 :
|
|
124
|
+
ell doit etre sous la forme
|
|
125
|
+
y^2 = x^3 + A*x^2 + B*x
|
|
126
|
+
avec A et B entiers.
|
|
127
|
+
gp > ell = [0,A,0,B,0]
|
|
128
|
+
gp > ell2descent_viaisog(ell)
|
|
129
|
+
= algorithme de la 2-descente par isogenies
|
|
130
|
+
Attention A et B doivent etre entiers
|
|
131
|
+
|
|
132
|
+
Courbes avec #E[2](Q) = 4 : y^2 = (x-e1)*(x-e2)*(x-e3)
|
|
133
|
+
gp > ell2descent_complete(e1,e2,e3)
|
|
134
|
+
= algorithme de la 2-descente complete
|
|
135
|
+
Attention : les ei doivent etre entiers.
|
|
136
|
+
|
|
137
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
138
|
+
\\ Autres fonctions utiles \\
|
|
139
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
140
|
+
|
|
141
|
+
elltors2(E) : determine le groupe E[2](Q)
|
|
142
|
+
elltorseven(E) : determine le groupe E[2^*](Q)
|
|
143
|
+
ellhalf(E,P) : liste les points Q tels que 2Q = P
|
|
144
|
+
ellredgen(E,v) : reduction des points de v sur E
|
|
145
|
+
|
|
146
|
+
locallysoluble(pol): teste si y^2=pol(x) est ELS
|
|
147
|
+
ratpoint(pol,lim): cherche un point sur y^2=pol(x)
|
|
148
|
+
redquartic(pol): reduction de la quartique pol
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
Aide en ligne :
|
|
152
|
+
?NomDeLaFonction
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
156
|
+
\\ Affichage des calculs \\
|
|
157
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
158
|
+
|
|
159
|
+
On peut avoir plus ou moins de details de calculs avec
|
|
160
|
+
DEBUGLEVEL_ell = 0;
|
|
161
|
+
DEBUGLEVEL_ell = 1; 2; 3;...
|
|
162
|
+
|
|
163
|
+
*/
|
|
164
|
+
|
|
165
|
+
\\
|
|
166
|
+
\\ Usual global variables
|
|
167
|
+
\\
|
|
168
|
+
|
|
169
|
+
global(DEBUGLEVEL_ell, LIM1, LIM3, LIMTRIV, ELLREDGENFLAG, COMPLETE):small;
|
|
170
|
+
|
|
171
|
+
DEBUGLEVEL_ell = 0; \\ From 0 to 5: choose a higher value to have
|
|
172
|
+
\\ more details printed.
|
|
173
|
+
LIM1 = 5; \\ Limit for the search of trivial points on quartics
|
|
174
|
+
LIM3 = 50; \\ Limit for the search of points on ELS quartics
|
|
175
|
+
LIMTRIV = 3; \\ Limit for the search of trivial points on the elliptic curve
|
|
176
|
+
ELLREDGENFLAG = 1; \\ to reduce the generators at the end
|
|
177
|
+
COMPLETE = 0; \\ Use Complete 2-descent when full 2-torsion,
|
|
178
|
+
\\ otherwise 2-descent via isogenies.
|
|
179
|
+
|
|
180
|
+
\\
|
|
181
|
+
\\ Technical global variables
|
|
182
|
+
\\
|
|
183
|
+
|
|
184
|
+
global(MAXPROB, LIMBIGPRIME):small;
|
|
185
|
+
|
|
186
|
+
MAXPROB = 20;
|
|
187
|
+
LIMBIGPRIME = 30; \\ for primes larger than this limit: use a probabilistic test
|
|
188
|
+
\\ LIMBIGPRIME = 0 means: only deterministic tests
|
|
189
|
+
|
|
190
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
191
|
+
\\ SCRIPT \\
|
|
192
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
193
|
+
|
|
194
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
195
|
+
\\ MANIPULATION OF GLOBAL VARIABLES \\
|
|
196
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
197
|
+
|
|
198
|
+
{default_ellQ(
|
|
199
|
+
DEBUGLEVEL_ell_val:small = 0,
|
|
200
|
+
LIM1_val:small = 5,
|
|
201
|
+
LIM3_val:small = 50,
|
|
202
|
+
LIMTRIV_val:small = 3,
|
|
203
|
+
ELLREDGENFLAG_val:small = 1,
|
|
204
|
+
COMPLETE_val:small = 0,
|
|
205
|
+
MAXPROB_val:small = 20,
|
|
206
|
+
LIMBIGPRIME_val:small = 30
|
|
207
|
+
) =
|
|
208
|
+
|
|
209
|
+
DEBUGLEVEL_ell = DEBUGLEVEL_ell_val;
|
|
210
|
+
print(" DEBUGLEVEL_ell = ",DEBUGLEVEL_ell);
|
|
211
|
+
|
|
212
|
+
LIM1 = LIM1_val;
|
|
213
|
+
print(" LIM1 = ",LIM1);
|
|
214
|
+
|
|
215
|
+
LIM3 = LIM3_val;
|
|
216
|
+
print(" LIM3 = ",LIM3);
|
|
217
|
+
|
|
218
|
+
LIMTRIV = LIMTRIV_val;
|
|
219
|
+
print(" LIMTRIV = ",LIMTRIV);
|
|
220
|
+
|
|
221
|
+
ELLREDGENFLAG = ELLREDGENFLAG_val;
|
|
222
|
+
print(" ELLREDGENFLAG = ",ELLREDGENFLAG);
|
|
223
|
+
|
|
224
|
+
COMPLETE = COMPLETE_val;
|
|
225
|
+
print(" COMPLETE = ",COMPLETE);
|
|
226
|
+
|
|
227
|
+
MAXPROB = MAXPROB_val;
|
|
228
|
+
print(" MAXPROB = ",MAXPROB);
|
|
229
|
+
|
|
230
|
+
LIMBIGPRIME = LIMBIGPRIME_val;
|
|
231
|
+
print(" LIMBIGPRIME = ",LIMBIGPRIME);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
235
|
+
\\ FUNCTIONS FOR POLYNOMIALS \\
|
|
236
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
237
|
+
|
|
238
|
+
{ratpoint( pol, lim:small = 1, singlepoint = 1, infinity = 1) =
|
|
239
|
+
\\ Search for points on y^2=pol(x).
|
|
240
|
+
\\ The coeff of pol must be integers.
|
|
241
|
+
\\ If singlepoint >= 1, stop after a first point is found.
|
|
242
|
+
|
|
243
|
+
my(listpoints,point1,odd,deg4,pol16,tab16,pol9,tab9,pol5,tab5,pol0,vecz,vecx,lead,zz,xx,evpol,iz,factpol,deg,vz,epsmax);
|
|
244
|
+
|
|
245
|
+
if( DEBUGLEVEL_ell >= 4,
|
|
246
|
+
print(" Starting ratpoint with pol = ",pol);
|
|
247
|
+
print(" lim = ",lim););
|
|
248
|
+
|
|
249
|
+
if( !singlepoint, listpoints = []);
|
|
250
|
+
point1 = [];
|
|
251
|
+
|
|
252
|
+
\\
|
|
253
|
+
\\ trivial solutions
|
|
254
|
+
\\
|
|
255
|
+
|
|
256
|
+
\\ the leading coeff is a square
|
|
257
|
+
if( infinity && issquare(pollead(pol)),
|
|
258
|
+
point1 = [ 1, sqrtrat(pollead(pol)), 0];
|
|
259
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial solution: lead(pol) is a square"));
|
|
260
|
+
if( singlepoint,
|
|
261
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint"));
|
|
262
|
+
return(point1));
|
|
263
|
+
listpoints = concat(listpoints,[point1]));
|
|
264
|
+
|
|
265
|
+
\\ the constant coeff is a square
|
|
266
|
+
if( issquare(polcoeff(pol,0)),
|
|
267
|
+
point1 = [ 0, sqrtrat(polcoeff(pol,0)) ];
|
|
268
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial solution: pol(0) is a square"));
|
|
269
|
+
if( singlepoint,
|
|
270
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint"));
|
|
271
|
+
return(point1));
|
|
272
|
+
listpoints = concat(listpoints,[point1]));
|
|
273
|
+
|
|
274
|
+
\\ roots of pol ?
|
|
275
|
+
factpol = nfroots(,pol);
|
|
276
|
+
if( #factpol,
|
|
277
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial solution: roots of pol",factpol));
|
|
278
|
+
if( singlepoint,
|
|
279
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint"));
|
|
280
|
+
return([factpol[1],0]));
|
|
281
|
+
listpoints = concat(listpoints,vector(#factpol,i,[factpol[i],0]))
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
\\
|
|
285
|
+
\\ Sieve
|
|
286
|
+
\\
|
|
287
|
+
|
|
288
|
+
\\ initialisation of the sieve modulo 16, 9 and 5
|
|
289
|
+
\\ used only with even degree when lim is large
|
|
290
|
+
|
|
291
|
+
deg = poldegree(pol);
|
|
292
|
+
odd = deg%2;
|
|
293
|
+
deg4 = ( !odd && lim > 20);
|
|
294
|
+
if( deg4,
|
|
295
|
+
|
|
296
|
+
pol16 = (Vec(pol)*Mod(1,16))~;
|
|
297
|
+
tab16 = matrix(16,16);
|
|
298
|
+
for(xx = 0, 16-1,
|
|
299
|
+
for(zz = 0, 16-1,
|
|
300
|
+
tab16[xx+1,zz+1] = !issquare(vector(deg+1,i,xx^(deg+1-i)*zz^(i-1))*pol16)));
|
|
301
|
+
pol9 = (Vec(pol)~)*Mod(1,9);
|
|
302
|
+
tab9 = matrix(9,9);
|
|
303
|
+
for(xx = 0, 9-1,
|
|
304
|
+
for(zz = 0, 9-1,
|
|
305
|
+
tab9[xx+1,zz+1] = !issquare(vector(deg+1,i,xx^(deg+1-i)*zz^(i-1))*pol9)));
|
|
306
|
+
pol5 = (Vec(pol)~)*Mod(1,5);
|
|
307
|
+
tab5 = matrix(5,5);
|
|
308
|
+
for(xx = 0, 5-1,
|
|
309
|
+
for(zz = 0, 5-1,
|
|
310
|
+
tab5[xx+1,zz+1] = !issquare(vector(deg+1,i,xx^(deg+1-i)*zz^(i-1))*pol5)));
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
\\ if the degree is odd, search only for square denominators
|
|
314
|
+
if( odd,
|
|
315
|
+
vecz = vector(lim,i,i^2);
|
|
316
|
+
,
|
|
317
|
+
\\ if the degree is even, the leading coeff must be
|
|
318
|
+
\\ a square modulo zz.
|
|
319
|
+
lead = pollead(pol);
|
|
320
|
+
vecz = vector(lim);
|
|
321
|
+
zz = 0;
|
|
322
|
+
for( i = 1, lim,
|
|
323
|
+
zz++; while( !issquare(Mod(lead,zz)),zz++); vecz[i] = zz
|
|
324
|
+
));
|
|
325
|
+
|
|
326
|
+
\\ the constant coeff must be a square modulo xx.
|
|
327
|
+
pol0 = polcoeff(pol,0);
|
|
328
|
+
vecx = vector(lim);
|
|
329
|
+
xx = 0;
|
|
330
|
+
for( i = 1, lim,
|
|
331
|
+
xx++; while( !issquare(Mod(pol0,xx)),xx++); vecx[i] = xx);
|
|
332
|
+
|
|
333
|
+
if( DEBUGLEVEL_ell >= 4, print(" xmax = ",vecx[lim]));
|
|
334
|
+
if( DEBUGLEVEL_ell >= 4, print(" zmax = ",vecz[lim]));
|
|
335
|
+
|
|
336
|
+
if( DEBUGLEVEL_ell >= 5, print(" vecx = ",vecx));
|
|
337
|
+
if( DEBUGLEVEL_ell >= 5, print(" vecz = ",vecz));
|
|
338
|
+
|
|
339
|
+
if( deg4,
|
|
340
|
+
vz = vector(lim,i,Pol(
|
|
341
|
+
vector(deg+1,j,polcoeff(pol,deg+1-j)*vecz[i]^(j-1))));
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
\\ if deg is even and pol has no odd terms,
|
|
345
|
+
\\ it is enough to consider xx > 0
|
|
346
|
+
if( !odd && subst(pol,x,-x)==pol, epsmax = 1, epsmax = 2);
|
|
347
|
+
|
|
348
|
+
\\ loop over x = xx/zz
|
|
349
|
+
\\ the loop on [xx,zz] is done diagonally
|
|
350
|
+
\\ to start with the smallest values of both xx and zz.
|
|
351
|
+
for( somme = 2, 2*lim,
|
|
352
|
+
for( ix = max(1,somme-lim), min(lim,somme-1),
|
|
353
|
+
xx = vecx[ix]; iz = somme-ix; zz = vecz[iz];
|
|
354
|
+
if( gcd(zz,xx) != 1, next);
|
|
355
|
+
for( eps = 1, epsmax,
|
|
356
|
+
\\ when eps = 1, xx > 0; when eps = 2, xx < 0.
|
|
357
|
+
if( deg4,
|
|
358
|
+
if( tab16[xx%16+1,zz%16+1], xx=-xx;next);
|
|
359
|
+
if( tab9[xx%9+1,zz%9+1], xx=-xx;next);
|
|
360
|
+
if( tab5[xx%5+1,zz%5+1], xx=-xx;next);
|
|
361
|
+
evpol = subst(vz[iz],'x,xx)
|
|
362
|
+
,
|
|
363
|
+
evpol = subst(pol,variable(pol),xx/zz)
|
|
364
|
+
);
|
|
365
|
+
if( issquare(evpol),
|
|
366
|
+
point1 = [xx/zz,sqrtrat(subst(pol,variable(pol),xx/zz))];
|
|
367
|
+
if( DEBUGLEVEL_ell >= 4, print(" point found by ratpoint = ",point1));
|
|
368
|
+
if( singlepoint, break(3));
|
|
369
|
+
listpoints = concat(listpoints,[point1])
|
|
370
|
+
);
|
|
371
|
+
xx = -xx
|
|
372
|
+
)));
|
|
373
|
+
|
|
374
|
+
if( point1 != [],
|
|
375
|
+
if( DEBUGLEVEL_ell >= 3, print(" point found by ratpoint = ",point1));
|
|
376
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of ratpoint "));
|
|
377
|
+
if( singlepoint, return(point1), return(listpoints))
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
return([]);
|
|
381
|
+
}
|
|
382
|
+
{redquartic(pol) =
|
|
383
|
+
\\ reduction of the quartic polynomial.
|
|
384
|
+
\\ (also works with other degrees)
|
|
385
|
+
my(local_prec,prec0,d,disc2,test,r,normderiv,disc2v,q,M);
|
|
386
|
+
|
|
387
|
+
if( DEBUGLEVEL_ell >= 4, print(" starting redquartic"));
|
|
388
|
+
if( DEBUGLEVEL_ell >= 3, print(" reduction of the quartic ",pol));
|
|
389
|
+
|
|
390
|
+
\\ choice of the real precision used in the computation
|
|
391
|
+
local_prec = prec0 = default(realprecision);
|
|
392
|
+
d = poldegree(pol);
|
|
393
|
+
disc2 = poldisc(pol)^2;
|
|
394
|
+
test = 0;
|
|
395
|
+
while( test == 0,
|
|
396
|
+
if( DEBUGLEVEL_ell >= 4, print(" precision = ",local_prec));
|
|
397
|
+
r = polroots(pol);
|
|
398
|
+
normderiv = vector( d, i, norm(subst(pol',variable(pol),r[i])));
|
|
399
|
+
disc2v = prod( i = 1, d, normderiv[i]) * pollead(pol)^(2*d-4);
|
|
400
|
+
test = abs(disc2v-disc2) < 10^(-local_prec\2);
|
|
401
|
+
if( !test, default(realprecision, local_prec *= 2))
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
\\ former choice of the quadratic form
|
|
405
|
+
\\ q = Vec(sum( i = 1, d, norm(x-r[i])));
|
|
406
|
+
\\ Now, uses the quadratic form normalized as in Cremona-Stoll
|
|
407
|
+
q = Vec(sum( i = 1, d, norm('x-r[i]) / normderiv[i]^(1/(d-2))));
|
|
408
|
+
M = qfbreduce([q[1],q[2]/2;q[2]/2,q[3]]);
|
|
409
|
+
pol = subst(pol,variable(pol),Pol(M[1,])/Pol(M[2,]))*Pol(M[2,])^poldegree(pol);
|
|
410
|
+
|
|
411
|
+
if( local_prec != prec0, default(realprecision,prec0));
|
|
412
|
+
|
|
413
|
+
if( DEBUGLEVEL_ell >= 3, print(" reduced quartic = ",pol));
|
|
414
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of redquartic"));
|
|
415
|
+
|
|
416
|
+
return([pol,M]);
|
|
417
|
+
}
|
|
418
|
+
{listratpoint( pol, redflag = 0) =
|
|
419
|
+
my(list,i,K,ff,C,p,M,U,newpol,factpol,ll,listf,rr);
|
|
420
|
+
|
|
421
|
+
if( DEBUGLEVEL_ell >= 5, print(" Starting listratpoint with ",pol));
|
|
422
|
+
list = [[pol,matid(2),1,1]];
|
|
423
|
+
i = 1;
|
|
424
|
+
while( i <= #list,
|
|
425
|
+
|
|
426
|
+
pol = list[i][1];
|
|
427
|
+
|
|
428
|
+
K = abs(content(pol));
|
|
429
|
+
if( K != 1,
|
|
430
|
+
pol = (list[i][1] /= K);
|
|
431
|
+
list[i][3] *= K
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
K = list[i][3];
|
|
435
|
+
if( K == 1, i++; next);
|
|
436
|
+
|
|
437
|
+
ff = factor(K);
|
|
438
|
+
if( vecmax(ff[,2]) > 1,
|
|
439
|
+
ff[,2] \= 2;
|
|
440
|
+
C = factorback(ff);
|
|
441
|
+
list[i][4] *= C;
|
|
442
|
+
K = ( list[i][3] /= C^2);
|
|
443
|
+
if( K == 1, i++; next);
|
|
444
|
+
ff = factor(K);
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
p = ff[1,1];
|
|
448
|
+
M = list[i][2];
|
|
449
|
+
C = list[i][4];
|
|
450
|
+
|
|
451
|
+
if( pollead(pol)%p == 0,
|
|
452
|
+
U = M*[1,0;0,p];
|
|
453
|
+
if( content(U) == 1,
|
|
454
|
+
newpol = subst(pol,'x,'x/p)*p^(poldegree(pol)-1);
|
|
455
|
+
list = concat(list, [[newpol,U,K/p,C*p]])
|
|
456
|
+
)
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
factpol = centerlift(polrootsmod(pol,p));
|
|
460
|
+
for( j = 1, #factpol,
|
|
461
|
+
U = M*[p,factpol[j];0,1];
|
|
462
|
+
if( content(U) == 1,
|
|
463
|
+
newpol = subst(pol,'x,p*'x+factpol[j])/p;
|
|
464
|
+
list = concat(list, [[newpol,U,K/p,C*p]])
|
|
465
|
+
));
|
|
466
|
+
|
|
467
|
+
i++;
|
|
468
|
+
);
|
|
469
|
+
|
|
470
|
+
ll = sum( i = 1, #list, list[i][3] == 1);
|
|
471
|
+
listf = vector(ll);
|
|
472
|
+
i = 1;
|
|
473
|
+
for( j = 1, #list,
|
|
474
|
+
if( list[j][3] == 1,
|
|
475
|
+
listf[i] = list[j]; i++));
|
|
476
|
+
|
|
477
|
+
if( redflag,
|
|
478
|
+
for( i = 1, #listf,
|
|
479
|
+
rr = redquartic(listf[i][1]);
|
|
480
|
+
listf[i][1] = rr[1];
|
|
481
|
+
listf[i][2] = listf[i][2]*rr[2]
|
|
482
|
+
)
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
if( DEBUGLEVEL_ell >= 5, print(" Output of listratpoint = ",listf));
|
|
486
|
+
|
|
487
|
+
return(listf);
|
|
488
|
+
}
|
|
489
|
+
{ratpoint2( pol, lim:small = 1, singlepoint = 1, redflag = 0) =
|
|
490
|
+
my(listpoints,list,rr,y2,aux);
|
|
491
|
+
|
|
492
|
+
listpoints = [];
|
|
493
|
+
list = listratpoint(pol,redflag);
|
|
494
|
+
for( i = 1, #list,
|
|
495
|
+
rr = ratpoint(list[i][1],lim,singlepoint);
|
|
496
|
+
if( singlepoint && #rr, rr=[rr]);
|
|
497
|
+
for( j = 1, #rr,
|
|
498
|
+
y2 = rr[j][2]*list[i][4];
|
|
499
|
+
if( #rr[j] == 2,
|
|
500
|
+
aux = [rr[j][1],1]~
|
|
501
|
+
, aux = [rr[j][1],rr[j][3]]~
|
|
502
|
+
);
|
|
503
|
+
aux = list[i][2] * aux;
|
|
504
|
+
if( aux[2] == 0,
|
|
505
|
+
rr[j] = [aux[1],y2,0]
|
|
506
|
+
, rr[j] = [aux[1]/aux[2],y2/aux[2]^(poldegree(pol)\2)]
|
|
507
|
+
);
|
|
508
|
+
);
|
|
509
|
+
if( singlepoint && #rr, return(rr[1]));
|
|
510
|
+
listpoints = concat(listpoints,rr);
|
|
511
|
+
);
|
|
512
|
+
listpoints = vecsort(listpoints,,2);
|
|
513
|
+
return(listpoints);
|
|
514
|
+
}
|
|
515
|
+
{polrealrootsisolate(pol) =
|
|
516
|
+
\\ pol is a squarefree polynomial in Z[x].
|
|
517
|
+
\\ Returns a list of vectors [a,b] with a and b rationals
|
|
518
|
+
\\ such that the intervals ]a,b] are disjoint and contain
|
|
519
|
+
\\ all the real roots of pol, and exactly one in each interval.
|
|
520
|
+
my(st,a,res,ind,b,c,stab,stac);
|
|
521
|
+
|
|
522
|
+
if( DEBUGLEVEL_ell >= 5, print(" starting polrealrootsisolate with pol = ",pol));
|
|
523
|
+
st = polsturm(pol);
|
|
524
|
+
if( !st, return([]));
|
|
525
|
+
a = 1;
|
|
526
|
+
while( polsturm(pol,-a,a) < st, a <<= 1);
|
|
527
|
+
res = [[-a,a,st]];
|
|
528
|
+
ind = 1;
|
|
529
|
+
while( #res < st,
|
|
530
|
+
while( res[ind][3] == 1, ind++);
|
|
531
|
+
a = res[ind][1]; b = res[ind][2]; stab = res[ind][3];
|
|
532
|
+
c = (a+b)/2;
|
|
533
|
+
stac = polsturm(pol,a,c);
|
|
534
|
+
if( stac == 0, res[ind][1] = c; next);
|
|
535
|
+
if( stac == stab, res[ind][2] = c; next);
|
|
536
|
+
res[ind] = [a,c,stac];
|
|
537
|
+
res = concat(res,[[c,b,stab-stac]]);
|
|
538
|
+
);
|
|
539
|
+
res = vector(st,i,[res[i][1],res[i][2]]);
|
|
540
|
+
res = vecsort(res,1);
|
|
541
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of polrealrootsisolate with res = ",res));
|
|
542
|
+
return(res);
|
|
543
|
+
}
|
|
544
|
+
{polrealrootsimprove(pol,v) =
|
|
545
|
+
\\ pol is a polynomial and v is a vector v=[a,b]
|
|
546
|
+
\\ such that pol contains exactly one root in the interval ]a,b].
|
|
547
|
+
\\ Returns another interval with the same property, but with half length.
|
|
548
|
+
\\ (dichotomy)
|
|
549
|
+
my(c,v2,vc);
|
|
550
|
+
|
|
551
|
+
c = (v[1]+v[2])/2;
|
|
552
|
+
v2 = subst(pol,variable(pol),v[2]);
|
|
553
|
+
if( v2 == 0, return([c,v[2]]));
|
|
554
|
+
vc = subst(pol,variable(pol),c);
|
|
555
|
+
if( sign(v2)*sign(vc) >= 0, v[2] = c, v[1] = c);
|
|
556
|
+
return(v);
|
|
557
|
+
}
|
|
558
|
+
{polrootsmodpn(pol,p) =
|
|
559
|
+
\\ Compute a list v. Each element of v is of the form
|
|
560
|
+
\\ [a,b], with maximal b <= valuation(poldisc(pol),p)
|
|
561
|
+
\\ and a is a root of pol modulo p^b.
|
|
562
|
+
my(vd,rac,i,pol2,r,newrac);
|
|
563
|
+
|
|
564
|
+
if( DEBUGLEVEL_ell >= 5, print(" starting polrootsmodpn ",p,":",pol));
|
|
565
|
+
|
|
566
|
+
vd = valuation(poldisc(pol),p);
|
|
567
|
+
rac = [[0,0]];
|
|
568
|
+
i = 1;
|
|
569
|
+
while (i <= #rac,
|
|
570
|
+
\\ if( rac[i][2] > vd, i++; next);
|
|
571
|
+
if( rac[i][2] >= vd, i++; next);
|
|
572
|
+
pol2 = subst(pol,'x,rac[i][1]+'x*p^rac[i][2]);
|
|
573
|
+
pol2 /= content(pol2);
|
|
574
|
+
r = lift(polrootsmod(pol2,p));
|
|
575
|
+
if( #r == 0, i++; next);
|
|
576
|
+
newrac = vector(#r,j,[rac[i][1] + p^rac[i][2]*r[j],rac[i][2]+1]);
|
|
577
|
+
rac = concat(rac, vector(#r-1,j,newrac[j+1]));
|
|
578
|
+
rac[i] = newrac[1];
|
|
579
|
+
);
|
|
580
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of polrootsmodpn ",rac));
|
|
581
|
+
return(rac);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
585
|
+
\\ FUNCTIONS FOR LOCAL COMPUTATIONS \\
|
|
586
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
587
|
+
|
|
588
|
+
{ppinit( nf, p) =
|
|
589
|
+
\\ a little more structure than idealprimedec()
|
|
590
|
+
my(pdec,pp);
|
|
591
|
+
|
|
592
|
+
pdec = idealprimedec(nf,p);
|
|
593
|
+
pp = vector(#pdec,i,
|
|
594
|
+
[ pdec[i]
|
|
595
|
+
, nfbasistoalg(nf,pdec[i][2])
|
|
596
|
+
, if( p == 2, idealstar(nf,idealpow(nf,pdec[i],1+2*pdec[i].e)),0)
|
|
597
|
+
, nfmodprinit(nf,pdec[i])
|
|
598
|
+
]);
|
|
599
|
+
return(pp);
|
|
600
|
+
}
|
|
601
|
+
{nfpsquareodd( nf, a, pr) =
|
|
602
|
+
\\ pr is a prime ideal of nf as output by nfmodprinit
|
|
603
|
+
\\ a is an element of nf.
|
|
604
|
+
\\ Returns 1 if a is a square in the p-adics, 0 otherwise
|
|
605
|
+
\\ works only for p odd.
|
|
606
|
+
my(p,v,ap,den,norme);
|
|
607
|
+
|
|
608
|
+
if( DEBUGLEVEL_ell >= 5, print(" starting nfpsquareodd(",a,",",pr));
|
|
609
|
+
if( a == 0,
|
|
610
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
|
|
611
|
+
return(1));
|
|
612
|
+
|
|
613
|
+
p = pr[3];
|
|
614
|
+
v = idealval(nf,lift(a),p);
|
|
615
|
+
if( v%2,
|
|
616
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
|
|
617
|
+
return(0));
|
|
618
|
+
ap = nfalgtobasis(nf,a/nfbasistoalg(nf,p[2])^v);
|
|
619
|
+
den = valuation(denominator(content(ap)),p.p);
|
|
620
|
+
if( den,
|
|
621
|
+
den += den%2;
|
|
622
|
+
ap = p.p^den*nfeltmul(nf,ap,nfeltpow(nf,p[2],-den*p.e))
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
norme = (p.p^p.f-1)/2;
|
|
626
|
+
ap = nfeltpowmodpr(nf,ap,norme,pr);
|
|
627
|
+
ap[1] -= 1;
|
|
628
|
+
if( ap == 0,
|
|
629
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
|
|
630
|
+
return(1));
|
|
631
|
+
if( idealval(nf,ap,p) > 0,
|
|
632
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
|
|
633
|
+
return(1));
|
|
634
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of nfpsquareodd"));
|
|
635
|
+
return(0);
|
|
636
|
+
}
|
|
637
|
+
{psquare( a, p) =
|
|
638
|
+
\\ a is an integer.
|
|
639
|
+
\\ p is a prime integer.
|
|
640
|
+
\\ Returns 1 if a is a square in the p-adics, 0 otherwise.
|
|
641
|
+
my(v,ap);
|
|
642
|
+
|
|
643
|
+
if( DEBUGLEVEL_ell >= 5, print(" starting psquare ",[a,p]));
|
|
644
|
+
|
|
645
|
+
if( a == 0,
|
|
646
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of psquare 1"));
|
|
647
|
+
return(1));
|
|
648
|
+
|
|
649
|
+
v = valuation(a,p);
|
|
650
|
+
if( v%2,
|
|
651
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of psquare 0"));
|
|
652
|
+
return(0));
|
|
653
|
+
if( p == 2,
|
|
654
|
+
ap = (a>>v)%8-1,
|
|
655
|
+
ap = kronecker(a/p^v,p)-1
|
|
656
|
+
);
|
|
657
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of psquare ", !ap));
|
|
658
|
+
return(!ap);
|
|
659
|
+
}
|
|
660
|
+
{lemma6(pol, p, nu, xx) =
|
|
661
|
+
\\ technical lemma for local solubility of quartics
|
|
662
|
+
\\ Only for p <> 2.
|
|
663
|
+
my(gx,gpx,lambda,mu);
|
|
664
|
+
|
|
665
|
+
gx = subst( pol, variable(pol), xx);
|
|
666
|
+
if( psquare(gx,p), return(1));
|
|
667
|
+
gpx = subst( pol', variable(pol), xx);
|
|
668
|
+
lambda = valuation(gx,p); mu = valuation(gpx,p);
|
|
669
|
+
|
|
670
|
+
if( gpx != 0 && lambda > 2*mu, return(1));
|
|
671
|
+
\\ if( (lambda >= mu+nu) && (nu > mu), return(1));
|
|
672
|
+
if( (lambda >= 2*nu) && (mu >= nu), return(0));
|
|
673
|
+
return(-1);
|
|
674
|
+
}
|
|
675
|
+
{lemma7( pol, nu, xx) =
|
|
676
|
+
\\ technical lemma for local solubility of quartics
|
|
677
|
+
\\ at p = 2.
|
|
678
|
+
my(gx,gpx,lambda,mu,q);
|
|
679
|
+
|
|
680
|
+
gx = subst( pol, variable(pol), xx);
|
|
681
|
+
if( psquare(gx,2), return(1));
|
|
682
|
+
gpx = subst( pol', variable(pol), xx);
|
|
683
|
+
lambda = valuation(gx,2); mu = valuation(gpx,2);
|
|
684
|
+
if( gpx != 0 && lambda > 2*mu, return(1));
|
|
685
|
+
if( nu > mu,
|
|
686
|
+
if( lambda%2, return(-1));
|
|
687
|
+
q = mu+nu-lambda;
|
|
688
|
+
if( q == 1, return(1));
|
|
689
|
+
if( q == 2 && (gx>>lambda)%4 == 1, return(1));
|
|
690
|
+
return(-1));
|
|
691
|
+
q = lambda-2*nu;
|
|
692
|
+
if( q >= 0, return(0));
|
|
693
|
+
if( q == -2 && (gx>>lambda)%4 == 1, return(0));
|
|
694
|
+
return(-1);
|
|
695
|
+
}
|
|
696
|
+
{zp_soluble(pol, p, nu, pnu, x0, pnup) =
|
|
697
|
+
my(result,pol2,fact,x1);
|
|
698
|
+
|
|
699
|
+
if( DEBUGLEVEL_ell >= 5, print(" starting zp_soluble ",[pol,p,x0,nu]));
|
|
700
|
+
if( p == 2,
|
|
701
|
+
result = lemma7(pol,nu,x0),
|
|
702
|
+
result = lemma6(pol,p,nu,x0));
|
|
703
|
+
if( result == +1,
|
|
704
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble 1 lemma"));
|
|
705
|
+
return(1));
|
|
706
|
+
if( result == -1,
|
|
707
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble 0 lemma"));
|
|
708
|
+
return(0));
|
|
709
|
+
pnup = pnu*p;
|
|
710
|
+
nu++;
|
|
711
|
+
if( p < LIMBIGPRIME || !LIMBIGPRIME,
|
|
712
|
+
for( i = 0, p-1,
|
|
713
|
+
if( zp_soluble(pol,p,nu,pnup,x0+pnu*i),
|
|
714
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
|
|
715
|
+
return(1)))
|
|
716
|
+
,
|
|
717
|
+
pol2 = subst(pol,variable(pol),x0+pnu*variable(pol));
|
|
718
|
+
pol2 /= content(pol2);
|
|
719
|
+
pol2 = pol2*Mod(1,p);
|
|
720
|
+
if( !poldegree(pol2), return(0));
|
|
721
|
+
fact = factormod(pol2,p)[,1];
|
|
722
|
+
for( i = 1, #fact,
|
|
723
|
+
x1 = -centerlift(polcoeff(fact[i],0));
|
|
724
|
+
if( zp_soluble(pol,p,nu,pnup,x0+pnu*x1),
|
|
725
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
|
|
726
|
+
return(1)));
|
|
727
|
+
for( i = 1, MAXPROB,
|
|
728
|
+
x1 = random(p);
|
|
729
|
+
if( zp_soluble(pol,p,nu,pnup,x0+pnu*x1),
|
|
730
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
|
|
731
|
+
return(1)))
|
|
732
|
+
);
|
|
733
|
+
if( DEBUGLEVEL_ell >= 2,
|
|
734
|
+
if( p >= LIMBIGPRIME,
|
|
735
|
+
print(" ******* probabilistic test at p = ",p,"*******")));
|
|
736
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of zp_soluble"));
|
|
737
|
+
return(0);
|
|
738
|
+
}
|
|
739
|
+
{qp_soluble(pol, p) =
|
|
740
|
+
if( DEBUGLEVEL_ell >= 5,
|
|
741
|
+
print(" starting qp_soluble ",p);
|
|
742
|
+
print(" pol = ",pol));
|
|
743
|
+
if( psquare(pollead(pol),p),
|
|
744
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
|
|
745
|
+
return(1));
|
|
746
|
+
if( psquare(polcoeff(pol,0),p),
|
|
747
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
|
|
748
|
+
return(1));
|
|
749
|
+
if( zp_soluble(pol,p,0,1,0),
|
|
750
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
|
|
751
|
+
return(1));
|
|
752
|
+
if( zp_soluble(polrecip(pol),p,1,p,0),
|
|
753
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 1"));
|
|
754
|
+
return(1));
|
|
755
|
+
if( DEBUGLEVEL_ell >= 5, print(" end of qp_soluble 0"));
|
|
756
|
+
return(0);
|
|
757
|
+
}
|
|
758
|
+
{locallysoluble(pol) =
|
|
759
|
+
\\ Determines if y^2 = pol(x,z) is everywhere locally soluble
|
|
760
|
+
my(c,disc0,plist,p,vc);
|
|
761
|
+
|
|
762
|
+
if( DEBUGLEVEL_ell >= 4, print(" starting locallysoluble: ",pol));
|
|
763
|
+
|
|
764
|
+
\\ real place
|
|
765
|
+
if( !(poldegree(pol)%2) && sign(pollead(pol)) < 0
|
|
766
|
+
&& sign(polcoeff(pol,0)) < 0 && polsturm(pol) == 0,
|
|
767
|
+
if( DEBUGLEVEL_ell >= 3, print(" not ELS at infinity"));
|
|
768
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of locallysoluble"));
|
|
769
|
+
return(0));
|
|
770
|
+
|
|
771
|
+
\\
|
|
772
|
+
\\ finite places
|
|
773
|
+
\\
|
|
774
|
+
pol *= denominator(content(pol))^2;
|
|
775
|
+
c = content(pol);
|
|
776
|
+
|
|
777
|
+
disc0 = poldisc(pol);
|
|
778
|
+
plist = factor (abs(2*disc0));
|
|
779
|
+
if( DEBUGLEVEL_ell >= 4, print(" list of bad primes = ",plist));
|
|
780
|
+
for( i = 1, #plist[,1],
|
|
781
|
+
p = plist[i,1];
|
|
782
|
+
if( DEBUGLEVEL_ell >= 4, print(" p = ",p));
|
|
783
|
+
vc = valuation(c,p);
|
|
784
|
+
if( vc >= 2,
|
|
785
|
+
pol /= p^(2*(vc\2));
|
|
786
|
+
plist[i,2] -= 2*(vc\2)*(2*poldegree(pol)-2)
|
|
787
|
+
);
|
|
788
|
+
if( poldegree(pol) == 4 && p != 2 && plist[i,2] < 2, next);
|
|
789
|
+
if( !qp_soluble(pol,p),
|
|
790
|
+
if( DEBUGLEVEL_ell >= 3, print(" not ELS at ",p));
|
|
791
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of locallysoluble"));
|
|
792
|
+
return(0)));
|
|
793
|
+
|
|
794
|
+
if( DEBUGLEVEL_ell >= 2, print(" quartic ELS: Y^2 = ",pol));
|
|
795
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of locallysoluble"));
|
|
796
|
+
return(1);
|
|
797
|
+
}
|
|
798
|
+
{LS2localimage(nf,gen,pp) =
|
|
799
|
+
my(p,LS2image,ph,ival,delta);
|
|
800
|
+
|
|
801
|
+
if( DEBUGLEVEL_ell >= 4, print(" starting LS2localimage"));
|
|
802
|
+
|
|
803
|
+
p = pp[1][1].p;
|
|
804
|
+
LS2image = matrix( if( p == 2, sum(i=1,#pp,1+#pp[i][3].cyc), 2*#pp), #gen);
|
|
805
|
+
|
|
806
|
+
for( j = 1, #gen,
|
|
807
|
+
ph = [];
|
|
808
|
+
for( i = 1, #pp,
|
|
809
|
+
ival = idealval(nf,gen[j],pp[i][1]);
|
|
810
|
+
ph = concat(ph,[ival]);
|
|
811
|
+
delta = gen[j]/pp[i][2]^ival;
|
|
812
|
+
if( p == 2,
|
|
813
|
+
ph = concat(ph,ideallog(nf,delta,pp[i][3])~);
|
|
814
|
+
, ph = concat(ph,[1-nfpsquareodd(nf,delta,pp[i][4])]);
|
|
815
|
+
)
|
|
816
|
+
);
|
|
817
|
+
LS2image[,j] = ph~
|
|
818
|
+
);
|
|
819
|
+
LS2image *= Mod(1,2);
|
|
820
|
+
|
|
821
|
+
if( DEBUGLEVEL_ell >= 4, print(" LS2image = ",lift(LS2image)));
|
|
822
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of LS2localimage"));
|
|
823
|
+
return(LS2image);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
827
|
+
\\ GENERIC FUNCTIONS FOR ELLIPTIC CURVES \\
|
|
828
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
829
|
+
|
|
830
|
+
{ellhalf(ell,P)=
|
|
831
|
+
\\ returns all the points Q on ell such that 2Q = P.
|
|
832
|
+
my(pol2,ratroots,half,x2,y2,P2);
|
|
833
|
+
|
|
834
|
+
if(#ell < 13, ell=ellinit(ell));
|
|
835
|
+
|
|
836
|
+
pol2 = Pol([4,ell.b2,2*ell.b4,ell.b6]); \\ 2-division polynomial
|
|
837
|
+
|
|
838
|
+
if( P == [0],
|
|
839
|
+
ratroots = nfroots(,pol2);
|
|
840
|
+
half = vector(#ratroots,i,[ratroots[i],-(ell.a1*ratroots[i]+ell.a3)/2]);
|
|
841
|
+
half = concat( [[0]], half);
|
|
842
|
+
return(half)
|
|
843
|
+
);
|
|
844
|
+
|
|
845
|
+
x2 = Pol([1,0,-ell.b4,-2*ell.b6,-ell.b8]); \\ x(2P) = x2/pol2
|
|
846
|
+
|
|
847
|
+
half = [];
|
|
848
|
+
ratroots = nfroots(,x2-P[1]*pol2);
|
|
849
|
+
if( #ratroots == 0, return(half));
|
|
850
|
+
for( i = 1, #ratroots,
|
|
851
|
+
y2 = ellordinate(ell,ratroots[i]);
|
|
852
|
+
for( j = 1, #y2,
|
|
853
|
+
P2 = [ratroots[i],y2[j]];
|
|
854
|
+
if( ellpow(ell,P2,2) == P, half = concat(half,[P2]))
|
|
855
|
+
)
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
return(half);
|
|
859
|
+
}
|
|
860
|
+
{elltors2(ell)=
|
|
861
|
+
\\ Compute the 2-torsion subgroup of the elliptic curve ell.
|
|
862
|
+
my(tors2);
|
|
863
|
+
|
|
864
|
+
if( DEBUGLEVEL_ell >= 3, print(" computing the 2-torsion"));
|
|
865
|
+
|
|
866
|
+
tors2 = ellhalf(ell,[0]);
|
|
867
|
+
if( #tors2 == 1,
|
|
868
|
+
tors2 = [1, [], []],
|
|
869
|
+
if( #tors2 == 2,
|
|
870
|
+
tors2 = [2, [2], [tors2[2]]]
|
|
871
|
+
, tors2 = [4, [2,2], [tors2[2],tors2[3]]]
|
|
872
|
+
));
|
|
873
|
+
if( DEBUGLEVEL_ell >= 3, print(" E[2] = ",tors2));
|
|
874
|
+
return(tors2);
|
|
875
|
+
}
|
|
876
|
+
{elltorseven(ell)=
|
|
877
|
+
\\ Compute the 2-Sylow subgroup of the torsion of the elliptic curve ell.
|
|
878
|
+
my(torseven,P2);
|
|
879
|
+
|
|
880
|
+
if( DEBUGLEVEL_ell >= 4, print(" computing the 2^n-torsion"));
|
|
881
|
+
if(#ell < 13, ell=ellinit(ell));
|
|
882
|
+
torseven = elltors2(ell);
|
|
883
|
+
|
|
884
|
+
while( torseven[1] != 1,
|
|
885
|
+
P2 = ellhalf(ell,torseven[3][1]);
|
|
886
|
+
if( #P2 > 0,
|
|
887
|
+
torseven[1] *= 2;
|
|
888
|
+
torseven[2][1] *= 2;
|
|
889
|
+
torseven[3][1] = P2[1];
|
|
890
|
+
next
|
|
891
|
+
);
|
|
892
|
+
if( #torseven[3] == 1, break());
|
|
893
|
+
|
|
894
|
+
P2 = ellhalf(ell,torseven[3][2]);
|
|
895
|
+
if( #P2 > 0,
|
|
896
|
+
torseven[1] *= 2;
|
|
897
|
+
torseven[2][2] *= 2;
|
|
898
|
+
torseven[3][2] = P2[1];
|
|
899
|
+
next
|
|
900
|
+
);
|
|
901
|
+
P2 = ellhalf(ell,elladd(ell,torseven[3][1],torseven[3][2]));
|
|
902
|
+
if( #P2 > 0,
|
|
903
|
+
torseven[1] *= 2;
|
|
904
|
+
torseven[2][1] *= 2;
|
|
905
|
+
torseven[3][1] = P2[1];
|
|
906
|
+
next
|
|
907
|
+
);
|
|
908
|
+
break()
|
|
909
|
+
);
|
|
910
|
+
|
|
911
|
+
if( DEBUGLEVEL_ell >= 4, print(" E[2^n] = ",torseven));
|
|
912
|
+
return(torseven);
|
|
913
|
+
}
|
|
914
|
+
{ellsort(listpts) =
|
|
915
|
+
\\ Sorting the points listpts on an elliptic curve
|
|
916
|
+
\\ using the naive height.
|
|
917
|
+
my(n,v,aux,ord);
|
|
918
|
+
|
|
919
|
+
v = vector(n = #listpts);
|
|
920
|
+
for( i = 1, n,
|
|
921
|
+
if( listpts[i] == [0], v[i] = [0,0,0]; next);
|
|
922
|
+
aux = denominator(listpts[i][2])/denominator(listpts[i][1]);
|
|
923
|
+
v[i] = vecsort(abs([listpts[i][1]*aux^2, listpts[i][2]*aux^3,aux]),,4);
|
|
924
|
+
);
|
|
925
|
+
ord = Vec(vecsort(v,,3)); \\ ord = vecsort(v,,3);
|
|
926
|
+
return(vector(n,i,listpts[ord[i]]));
|
|
927
|
+
}
|
|
928
|
+
{ellremovetorsion(ell,listgen) =
|
|
929
|
+
\\ Extracting the points of infinite order from listgen
|
|
930
|
+
my(d,extra);
|
|
931
|
+
|
|
932
|
+
if( DEBUGLEVEL_ell >= 5, print(" removing torsion from ",listgen));
|
|
933
|
+
d = #listgen;
|
|
934
|
+
extra = 0;
|
|
935
|
+
for( i = 1, d,
|
|
936
|
+
\\ points of order 1 or 2
|
|
937
|
+
if( listgen[i] == [0]
|
|
938
|
+
|| listgen[i] == ellpow(ell,listgen[i],-1)
|
|
939
|
+
, extra += 1<<(i-1);
|
|
940
|
+
next
|
|
941
|
+
);
|
|
942
|
+
\\ detection of infinite order points by looking at
|
|
943
|
+
\\ 8*9*5*7*P modulo the prime 1048583
|
|
944
|
+
if( ell.disc%1048583 != 0
|
|
945
|
+
&& denominator(listgen[i])%1048583 != 0
|
|
946
|
+
&& ellpow(ell,listgen[i]*Mod(1,1048583),2520) != [0]
|
|
947
|
+
, next
|
|
948
|
+
);
|
|
949
|
+
\\ detection of torsion points by ellorder()
|
|
950
|
+
if( ellorder(ell,listgen[i]),
|
|
951
|
+
extra += 1<<(i-1)
|
|
952
|
+
)
|
|
953
|
+
);
|
|
954
|
+
if( extra,
|
|
955
|
+
listgen = vecextract(listgen,1<<#listgen-1-extra);
|
|
956
|
+
);
|
|
957
|
+
if( DEBUGLEVEL_ell >= 5, print(" without torsion = ",listgen));
|
|
958
|
+
return(listgen);
|
|
959
|
+
}
|
|
960
|
+
{ellredgen(ell0,listgen,K=1) =
|
|
961
|
+
\\ reduction of the generators of points in listgen
|
|
962
|
+
\\ on the elliptic curve ell = [a1,a2,a3,a4,a6]
|
|
963
|
+
\\ or K*y^2 = x^3 + a2*x^2 + a4*x + a6 (when a1 = a3 = 0);
|
|
964
|
+
\\ using the canonical height.
|
|
965
|
+
my(d,ell=ell0,sqrtK,urst,extra,M,U,listgen2,tors2,vt);
|
|
966
|
+
|
|
967
|
+
if( DEBUGLEVEL_ell >= 3, print(" Reduction of the generators ",listgen));
|
|
968
|
+
if( DEBUGLEVEL_ell >= 5, print(" ell=",ell));
|
|
969
|
+
d = #listgen;
|
|
970
|
+
if( d == 0, return([]));
|
|
971
|
+
|
|
972
|
+
\\ removing torsion points from listgen
|
|
973
|
+
listgen = ellremovetorsion(ell0,listgen);
|
|
974
|
+
d = #listgen;
|
|
975
|
+
if( d == 0, return([]));
|
|
976
|
+
|
|
977
|
+
if( #ell < 13, ell = ellinit(ell));
|
|
978
|
+
|
|
979
|
+
if( K != 1,
|
|
980
|
+
if( ell.a1 != 0 || ell.a3 != 0, error(" ellredgen: a1*a3 != 0"));
|
|
981
|
+
ell[2] *= K; ell[4] *= K^2; ell[5] *= K^3;
|
|
982
|
+
ell[6] *= K; ell[7] *= K^2; ell[8] *= K^3; ell[9] *= K^4;
|
|
983
|
+
ell[10] *= K^2; ell[11] *= K^3; ell[12] *= K^6;
|
|
984
|
+
sqrtK = sqrt(K);
|
|
985
|
+
if( #ell == 19,
|
|
986
|
+
ell[14] *= K;
|
|
987
|
+
ell[15] /= sqrtK; ell[16] /= sqrtK;
|
|
988
|
+
ell[17] *= sqrtK; ell[18] *= sqrtK;
|
|
989
|
+
ell[19] /= K
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
for( i = 1, d,
|
|
993
|
+
for( j = 1, #listgen[i],
|
|
994
|
+
listgen[i][j] *= K^j))
|
|
995
|
+
);
|
|
996
|
+
|
|
997
|
+
if( d == 1,
|
|
998
|
+
urst = [1,0,0,0];
|
|
999
|
+
,
|
|
1000
|
+
if( #ell < 19, ell = ellinit(ell));
|
|
1001
|
+
ell = ellminimalmodel(ell,&urst);
|
|
1002
|
+
listgen = ellchangepoint(listgen,urst);
|
|
1003
|
+
if( DEBUGLEVEL_ell >= 5, print(" ell = ",ell));
|
|
1004
|
+
if( DEBUGLEVEL_ell >= 5, print(" listgen = ",listgen));
|
|
1005
|
+
|
|
1006
|
+
\\ Looking for relations between the points in listgen
|
|
1007
|
+
\\ using LLL on the height matrix
|
|
1008
|
+
|
|
1009
|
+
extra = 1;
|
|
1010
|
+
while( extra,
|
|
1011
|
+
M = ellheightmatrix(ell,listgen);
|
|
1012
|
+
if( DEBUGLEVEL_ell >= 4, print(" height matrix = ",M));
|
|
1013
|
+
if( abs(matdet(M)) > 10^(-default(realprecision)+10),break);
|
|
1014
|
+
U = qflll(round(M*10^(default(realprecision)-10)),4);
|
|
1015
|
+
U = concat(U[1],U[2]);
|
|
1016
|
+
if( DEBUGLEVEL_ell >= 4, print(" change of basis proposed by LLL = ",U));
|
|
1017
|
+
\\ the columns of U that have very small coefficients
|
|
1018
|
+
\\ are either exact relations or reductions (coeff <= 20)
|
|
1019
|
+
\\ the other ones are irrelevant.
|
|
1020
|
+
extra = 0;
|
|
1021
|
+
for( i = 1, d,
|
|
1022
|
+
if( vecmax(abs(U[,i])) > 20, extra += 1<<(i-1))
|
|
1023
|
+
);
|
|
1024
|
+
U = vecextract(U,1<<d-1-extra);
|
|
1025
|
+
U = completebasis(U);
|
|
1026
|
+
if( DEBUGLEVEL_ell >= 4, print(" change of basis 1 = ",U));
|
|
1027
|
+
|
|
1028
|
+
listgen2 = vector(d);
|
|
1029
|
+
for( i = 1, d,
|
|
1030
|
+
listgen2[i] = [0];
|
|
1031
|
+
for( j = 1, d,
|
|
1032
|
+
listgen2[i] = elladd(ell,listgen2[i],ellpow(ell,listgen[j],U[j,i]))));
|
|
1033
|
+
listgen = listgen2;
|
|
1034
|
+
);
|
|
1035
|
+
|
|
1036
|
+
\\ Extracting the points of infinite order
|
|
1037
|
+
|
|
1038
|
+
\\ removing torsion points from listgen
|
|
1039
|
+
listgen = ellremovetorsion(ell,listgen);
|
|
1040
|
+
d = #listgen;
|
|
1041
|
+
if( d == 0, return([]));
|
|
1042
|
+
);
|
|
1043
|
+
|
|
1044
|
+
if( DEBUGLEVEL_ell >= 3, print(" infinite order points = ",listgen));
|
|
1045
|
+
|
|
1046
|
+
\\ Now, the points should be of infinite order and independant
|
|
1047
|
+
\\ Reducing the points of infinite order
|
|
1048
|
+
|
|
1049
|
+
if( d > 1,
|
|
1050
|
+
M = ellheightmatrix(ell,listgen);
|
|
1051
|
+
if( DEBUGLEVEL_ell >= 4, print(" height matrix = ",M));
|
|
1052
|
+
U = qflllgram(M);
|
|
1053
|
+
if( DEBUGLEVEL_ell >= 4, print(" change of basis 2 = ",U));
|
|
1054
|
+
|
|
1055
|
+
listgen2 = vector(d);
|
|
1056
|
+
for( i = 1, d,
|
|
1057
|
+
listgen2[i] = [0];
|
|
1058
|
+
for( j = 1, d,
|
|
1059
|
+
listgen2[i] = elladd(ell,listgen2[i],ellpow(ell,listgen[j],U[j,i]))));
|
|
1060
|
+
listgen = listgen2;
|
|
1061
|
+
);
|
|
1062
|
+
|
|
1063
|
+
if( DEBUGLEVEL_ell >= 3, print(" infinite order points = ",listgen));
|
|
1064
|
+
|
|
1065
|
+
listgen = ellchangepoint(listgen,ellinverturst(urst));
|
|
1066
|
+
|
|
1067
|
+
\\ Reducing modulo the 2-torsion
|
|
1068
|
+
|
|
1069
|
+
tors2 = elltorseven(ell0);
|
|
1070
|
+
if( tors2[1] > 1,
|
|
1071
|
+
vt = vector(tors2[2][1],j,ellpow(ell0,tors2[3][1],j-1));
|
|
1072
|
+
if( #tors2[2] == 2,
|
|
1073
|
+
vt = concat(vt,vector(#vt,j,elladd(ell0,vt[j],tors2[3][2])))
|
|
1074
|
+
);
|
|
1075
|
+
for( i = 1, d,
|
|
1076
|
+
listgen[i] = ellsort(vector(#vt,j,elladd(ell0,listgen[i],vt[j])))[1];
|
|
1077
|
+
);
|
|
1078
|
+
);
|
|
1079
|
+
|
|
1080
|
+
if( DEBUGLEVEL_ell >= 3, print(" infinite order points = ",listgen));
|
|
1081
|
+
|
|
1082
|
+
if( K != 1,
|
|
1083
|
+
for( i = 1, d,
|
|
1084
|
+
for( j = 1, 2,
|
|
1085
|
+
listgen[i][j] /= K^j)));
|
|
1086
|
+
|
|
1087
|
+
\\ keep only the points (x,y) with y >= 0
|
|
1088
|
+
|
|
1089
|
+
if( ell0.a1 == 0 && ell0.a3 == 0,
|
|
1090
|
+
for( i = 1, d,
|
|
1091
|
+
if( #listgen[i] == 2,
|
|
1092
|
+
listgen[i][2] = abs(listgen[i][2]))));
|
|
1093
|
+
|
|
1094
|
+
if( DEBUGLEVEL_ell >= 2, print(" reduced generators = ",listgen));
|
|
1095
|
+
return(listgen);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1099
|
+
\\ FUNCTIONS FOR NUMBER FIELDS \\
|
|
1100
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1101
|
+
|
|
1102
|
+
{reducemodsquares(delta,d) =
|
|
1103
|
+
\\ Uses LLL to find z such that delta*z^2 has a small coefficient in x^d.
|
|
1104
|
+
\\ delta must be a t_POLMOD
|
|
1105
|
+
my(deg,xx,z,qd,Qd,reduc);
|
|
1106
|
+
|
|
1107
|
+
deg = poldegree(component(delta,1)); \\ deg = poldegree(delta.mod);
|
|
1108
|
+
xx = Mod('x,component(delta,1)); \\ xx = Mod(x,delta.mod);
|
|
1109
|
+
z = subst(Pol(vector(deg,i,eval(Str("a"i)))),'x,xx);
|
|
1110
|
+
qd = polcoeff(lift(delta*z^2),d,'x);
|
|
1111
|
+
Qd = simplify(matrix(deg,deg,i,j,deriv(deriv(qd,eval(Str("a"i))),eval(Str("a"j)))/2));
|
|
1112
|
+
|
|
1113
|
+
reduc = qflllgram_indef(Qd);
|
|
1114
|
+
if( #reduc == 2, reduc = reduc[2][,1]);
|
|
1115
|
+
|
|
1116
|
+
return(delta*subst(Pol(reduc),'x,xx)^2);
|
|
1117
|
+
}
|
|
1118
|
+
{bnfpSelmer(bnf,S=1,p) =
|
|
1119
|
+
\\ p is a prime integer and bnf a big number field.
|
|
1120
|
+
\\ Compute the p-Selmer group of the number field bnf
|
|
1121
|
+
\\ relative to the prime ideals dividing S.
|
|
1122
|
+
\\ This group is denoted by LS2 in the sequel.
|
|
1123
|
+
\\ Returns [gen,S'] where gen is a vector containing the generators
|
|
1124
|
+
\\ of the p-Selmer group, represented has elements of bnf modulo p-powers,
|
|
1125
|
+
\\ and S' is the support of gen.
|
|
1126
|
+
my(S1,oddclass,multS,Slist,LS2gen,newprimes,newprimesval,kerval);
|
|
1127
|
+
|
|
1128
|
+
if( DEBUGLEVEL_ell >= 3, print(" Constructing the field Selmer group: L(S,",p,")"));
|
|
1129
|
+
S1 = idealhnf(bnf,S);
|
|
1130
|
+
|
|
1131
|
+
oddclass = 0; multS = 1;
|
|
1132
|
+
while( !oddclass,
|
|
1133
|
+
if( multS != 1, S1 = idealmul(bnf,S1,multS));
|
|
1134
|
+
Slist = idealfactor(bnf,S1)[,1]~;
|
|
1135
|
+
if( DEBUGLEVEL_ell >= 4, print(" constructing the S-units "));
|
|
1136
|
+
if( DEBUGLEVEL_ell >= 4, print(" S1 = ",Slist));
|
|
1137
|
+
LS2gen = bnfsunit(bnf,Slist);
|
|
1138
|
+
|
|
1139
|
+
\\ If the class group is divisible by p,
|
|
1140
|
+
\\ need to enlarge S1.
|
|
1141
|
+
oddclass = LS2gen[5].no % p;
|
|
1142
|
+
if( !oddclass,
|
|
1143
|
+
if( DEBUGLEVEL_ell >= 4, print(" class group divisible by p = ",LS2gen[5].no));
|
|
1144
|
+
multS = idealmul(bnf,S,LS2gen[5].gen[1]);
|
|
1145
|
+
)
|
|
1146
|
+
);
|
|
1147
|
+
LS2gen = Mod(LS2gen[1],bnf.pol);
|
|
1148
|
+
|
|
1149
|
+
\\ The valuation of the generators must be divisible by p outside S.
|
|
1150
|
+
newprimes = [];
|
|
1151
|
+
for( i = 1, #Slist,
|
|
1152
|
+
if( idealadd(bnf,S,Slist[i]) == 1,
|
|
1153
|
+
newprimes = concat(newprimes,[Slist[i]])));
|
|
1154
|
+
if( DEBUGLEVEL_ell >= 4, print(" newprimes = ",newprimes));
|
|
1155
|
+
newprimesval = matrix(#newprimes,#LS2gen,i,j,
|
|
1156
|
+
idealval(bnf,LS2gen[j],newprimes[i]));
|
|
1157
|
+
if( DEBUGLEVEL_ell >= 4, print(" newprimesval = ",newprimesval));
|
|
1158
|
+
kerval = lift(matker(newprimesval*Mod(1,p)));
|
|
1159
|
+
if( DEBUGLEVEL_ell >= 4, print(" kerval = ",kerval));
|
|
1160
|
+
LS2gen = vector(#kerval,i,
|
|
1161
|
+
prod( j = 1, #LS2gen,
|
|
1162
|
+
LS2gen[j]^kerval[j,i]));
|
|
1163
|
+
|
|
1164
|
+
\\ Add the units
|
|
1165
|
+
LS2gen = concat(bnf.fu,LS2gen); \\ LS2gen = concat(bnf.fu,LS2gen);
|
|
1166
|
+
\\ Add also the torsion unit if its order is divisible by p.
|
|
1167
|
+
if( bnf[8][4][1]%p == 0, \\ if( bnf.tu[1]%p == 0,
|
|
1168
|
+
LS2gen = concat( [Mod(bnf[8][4][2],bnf.pol)], LS2gen)); \\ LS2gen = concat( [Mod(bnf.tu[2],bnf.pol)], LS2gen));
|
|
1169
|
+
if( DEBUGLEVEL_ell >= 3, print(" #LS2gen = ",#LS2gen));
|
|
1170
|
+
if( DEBUGLEVEL_ell >= 4, print(" LS2gen = ",LS2gen));
|
|
1171
|
+
return([LS2gen,Slist]);
|
|
1172
|
+
}
|
|
1173
|
+
{kersign(gen,rootapprox) =
|
|
1174
|
+
\\ Determine the kernel of the sign map
|
|
1175
|
+
\\ restricted to the subgroup generated by gen,
|
|
1176
|
+
\\ and relative to the real embedding corresponding to
|
|
1177
|
+
\\ the root of pol contained in the interval rootapprox.
|
|
1178
|
+
my(signs,elt,elt2,d,st,kers,compt);
|
|
1179
|
+
|
|
1180
|
+
if( DEBUGLEVEL_ell >= 3, print(" Computing the kernel of the sign ",rootapprox));
|
|
1181
|
+
|
|
1182
|
+
\\ determination of the signs
|
|
1183
|
+
|
|
1184
|
+
signs = vector(#gen);
|
|
1185
|
+
for( i = 1, #gen,
|
|
1186
|
+
elt = lift(gen[i]);
|
|
1187
|
+
if( DEBUGLEVEL_ell >= 5, print(" Computing the sign of elt = ",elt));
|
|
1188
|
+
if( poldegree(elt) == 0, signs[i] = sign(simplify(elt)) < 0; next);
|
|
1189
|
+
d = poldisc(elt);
|
|
1190
|
+
if( poldegree(elt) == 2,
|
|
1191
|
+
if( d <= 0, signs[i] = sign(pollead(elt)) < 0; next));
|
|
1192
|
+
elt2 = if( d == 0, elt/gcd(elt,elt'), elt);
|
|
1193
|
+
st = 1;
|
|
1194
|
+
compt = 0;
|
|
1195
|
+
while( st,
|
|
1196
|
+
st = polsturm(elt2,rootapprox[1],rootapprox[2]);
|
|
1197
|
+
if( st,
|
|
1198
|
+
rootapprox = polrealrootsimprove(component(gen[i],1),rootapprox);
|
|
1199
|
+
\\ rootapprox = polrealrootsimprove(gen[i].mod,rootapprox);
|
|
1200
|
+
\\ if the sign of elt is too difficult to determine,
|
|
1201
|
+
\\ try a reduction modulo squares
|
|
1202
|
+
if( compt++ == 5, gen[i] = reducemodsquares(gen[i]); i--; next(2));
|
|
1203
|
+
\\ if the sign of elt is still too difficult to determine,
|
|
1204
|
+
\\ try the sign of 1/elt.
|
|
1205
|
+
if( compt%5 == 0, gen[i] = 1/gen[i]; i--; next(2))
|
|
1206
|
+
));
|
|
1207
|
+
signs[i] = sign(subst(elt,variable(elt),rootapprox[2])) < 0
|
|
1208
|
+
);
|
|
1209
|
+
if( DEBUGLEVEL_ell >= 4, print(" signs = ",signs));
|
|
1210
|
+
|
|
1211
|
+
\\ construction of the kernel
|
|
1212
|
+
kers = matker(Mat(signs*Mod(1,2)))*Mod(1,2);
|
|
1213
|
+
if( DEBUGLEVEL_ell >= 4, print(" kers = ",lift(kers)));
|
|
1214
|
+
return(kers);
|
|
1215
|
+
}
|
|
1216
|
+
{kernorm(gen,S,p) =
|
|
1217
|
+
\\ gen is a generating set for a subgroup of K^* / K^p.
|
|
1218
|
+
\\ Compute the kernel of the norm map.
|
|
1219
|
+
\\ Uses the fact that all valuations are 0 mod p,
|
|
1220
|
+
\\ except maybe at primes in S.
|
|
1221
|
+
my(normgen,normmap,kern);
|
|
1222
|
+
|
|
1223
|
+
if( DEBUGLEVEL_ell >= 3, print(" Computing the kernel of the norm map"));
|
|
1224
|
+
|
|
1225
|
+
if( p == 2, S = concat([-1],S));
|
|
1226
|
+
normgen = norm(gen);
|
|
1227
|
+
if( DEBUGLEVEL_ell >= 4, print(" normgen = ",normgen));
|
|
1228
|
+
|
|
1229
|
+
\\ matrix of the norm map
|
|
1230
|
+
normmap = matrix(#S,#normgen,i,j,
|
|
1231
|
+
if( i == 1 && p == 2,
|
|
1232
|
+
sign(normgen[j]) < 0
|
|
1233
|
+
, valuation(normgen[j],S[i])));
|
|
1234
|
+
if( DEBUGLEVEL_ell >= 4, print(" normmap = ",normmap));
|
|
1235
|
+
|
|
1236
|
+
\\ construction of the kernel
|
|
1237
|
+
kern = matker(normmap*Mod(1,p))*Mod(1,p);
|
|
1238
|
+
if( DEBUGLEVEL_ell >= 4, print(" ker = ",lift(kern)));
|
|
1239
|
+
return(kern);
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1243
|
+
\\ FUNCTIONS FOR 2-DESCENT \\
|
|
1244
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1245
|
+
|
|
1246
|
+
{elllocalimage( nf, pp, K = 1) =
|
|
1247
|
+
\\ pol is the cubic polynomial defining the elliptic curve,
|
|
1248
|
+
\\ nf is nfinit(pol),
|
|
1249
|
+
\\ p is a prime integer, and pp = ppinit(p).
|
|
1250
|
+
\\ Returns the image of the p-adic points
|
|
1251
|
+
\\ E(Qp)/2E(Qp) in Kp/Kp^2.
|
|
1252
|
+
\\ The algorithm consists of choosing random p-adic points in E(Qp)
|
|
1253
|
+
\\ until the number of images is equal to #E(Qp)[2] / |2|_p
|
|
1254
|
+
my(X,p,prank,rac,pts,bound,essai,mrank,r,xx,delta,ph,delta2,local_prec,ival);
|
|
1255
|
+
|
|
1256
|
+
if( DEBUGLEVEL_ell >= 4, print(" starting elllocalimage"));
|
|
1257
|
+
|
|
1258
|
+
X = Mod('x,nf.pol);
|
|
1259
|
+
p = pp[1][1][1];
|
|
1260
|
+
prank = #pp - (p != 2);
|
|
1261
|
+
if( DEBUGLEVEL_ell >= 4, print(" prank = ",prank));
|
|
1262
|
+
|
|
1263
|
+
rac = polrootsmodpn(K*nf.pol,p);
|
|
1264
|
+
if( DEBUGLEVEL_ell >= 5, print(" rac = ",rac));
|
|
1265
|
+
|
|
1266
|
+
pts = matrix(0,0);
|
|
1267
|
+
bound = p+6;
|
|
1268
|
+
essai = 0;
|
|
1269
|
+
mrank = 0;
|
|
1270
|
+
while( mrank < prank,
|
|
1271
|
+
|
|
1272
|
+
essai ++;
|
|
1273
|
+
if( essai%16 == 0,
|
|
1274
|
+
pts = matimage(pts);
|
|
1275
|
+
bound *= p;
|
|
1276
|
+
);
|
|
1277
|
+
|
|
1278
|
+
r = random(#rac)+1; local_prec = random(rac[r][2]+3)-2;
|
|
1279
|
+
xx = rac[r][1]+p^local_prec*random(bound);
|
|
1280
|
+
if( DEBUGLEVEL_ell >= 5, print(" xx = ",xx));
|
|
1281
|
+
delta = K*(xx-X);
|
|
1282
|
+
|
|
1283
|
+
\\ rem: K*pol(xx) = norm(delta) ( = y^2 for a point on the elliptic curve)
|
|
1284
|
+
if( !psquare(K*subst(nf.pol,'x,xx),p), next);
|
|
1285
|
+
ph = [];
|
|
1286
|
+
for( i = 1, #pp,
|
|
1287
|
+
ph = concat(ph,[ ival = idealval(nf,delta,pp[i][1])]);
|
|
1288
|
+
delta2 = delta/pp[i][2]^ival;
|
|
1289
|
+
if( p == 2,
|
|
1290
|
+
ph = concat(ph,ideallog(nf,delta2,pp[i][3])~);
|
|
1291
|
+
, ph = concat(ph,[1-nfpsquareodd(nf,delta2,pp[i][4])])
|
|
1292
|
+
)
|
|
1293
|
+
);
|
|
1294
|
+
if( DEBUGLEVEL_ell >= 5, print(" ph = ",ph));
|
|
1295
|
+
|
|
1296
|
+
pts = concat(pts,ph~*Mod(1,2));
|
|
1297
|
+
mrank = matrank(pts*Mod(1,2));
|
|
1298
|
+
if( DEBUGLEVEL_ell >= 5, print(" pts = ",lift(pts)));
|
|
1299
|
+
if( DEBUGLEVEL_ell >= 5, print(" matrank = ",mrank));
|
|
1300
|
+
);
|
|
1301
|
+
|
|
1302
|
+
pts = matimage(pts);
|
|
1303
|
+
if( DEBUGLEVEL_ell >= 5, print(" essai = ",essai));
|
|
1304
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of elllocalimage"));
|
|
1305
|
+
return(pts);
|
|
1306
|
+
}
|
|
1307
|
+
{ell2descent_gen(ell,bnf,K=1,help=[],redflag=0) =
|
|
1308
|
+
\\ This algorithm performs 2-descent on the elliptic curve ell
|
|
1309
|
+
\\ when ell has trivial 2-torsion.
|
|
1310
|
+
|
|
1311
|
+
\\ ell must be of the form K*y^2=x^3+A*x^2+B*x+C
|
|
1312
|
+
\\ ie ell=[0,A,0,B,C], with K,A,B,C integers.
|
|
1313
|
+
\\ bnf is bnfinit(x^3+A*x^2+B*x+C,1).
|
|
1314
|
+
|
|
1315
|
+
\\
|
|
1316
|
+
\\ help is a list of known points (maybe empty) on ell.
|
|
1317
|
+
\\ if redflag != 0, reduces the elements
|
|
1318
|
+
\\ of the field Selmer group modulo squares.
|
|
1319
|
+
|
|
1320
|
+
my(A,B,C,polrel,polprime,ttheta,badprimes,S,LS2,selmer,rootapprox,p,pp,locimage,LS2image,listpointstriv,listpoints,iwhile,expo,zc,liftzc,den,point,idealfactorzc,idealzc,baseidealzc,q2,sol,param,q1,pol,redq,q0,pointxx,point2,rang);
|
|
1321
|
+
|
|
1322
|
+
if( DEBUGLEVEL_ell >= 4, print(" starting ell2descent_gen"));
|
|
1323
|
+
|
|
1324
|
+
if( #ell < 13, ell = ellinit(ell));
|
|
1325
|
+
|
|
1326
|
+
if( ell.a1 != 0 || ell.a3 != 0,
|
|
1327
|
+
error(" ell2descent_gen: the curve is not of the form [0,a,0,b,c]"));
|
|
1328
|
+
if( denominator(ell.a2) > 1 || denominator(ell.a4) > 1 || denominator(ell.a6) >1,
|
|
1329
|
+
error(" ell2descent_gen: non integral coefficients"));
|
|
1330
|
+
|
|
1331
|
+
A = ell.a2; if( DEBUGLEVEL_ell >= 2, print(" A = ",A));
|
|
1332
|
+
B = ell.a4; if( DEBUGLEVEL_ell >= 2, print(" B = ",B));
|
|
1333
|
+
C = ell.a6; if( DEBUGLEVEL_ell >= 2, print(" C = ",C));
|
|
1334
|
+
|
|
1335
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1336
|
+
\\ Construction of L(S,2) \\
|
|
1337
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1338
|
+
|
|
1339
|
+
if( DEBUGLEVEL_ell >= 2, print(); print(" Computing L(S,2)"));
|
|
1340
|
+
|
|
1341
|
+
polrel = Pol([1,A,B,C]);
|
|
1342
|
+
polprime = polrel';
|
|
1343
|
+
ttheta = Mod('x,polrel);
|
|
1344
|
+
|
|
1345
|
+
if( !bnf,
|
|
1346
|
+
if( DEBUGLEVEL_ell >= 3, print(" bnfinit(",polrel,")"));
|
|
1347
|
+
bnf = bnfinit(polrel,1));
|
|
1348
|
+
|
|
1349
|
+
badprimes = abs(K*idealadd(bnf,polprime,bnf.index));
|
|
1350
|
+
if( DEBUGLEVEL_ell >= 5, print(" badprimes = ",badprimes[1,1]));
|
|
1351
|
+
S = bnfpSelmer(bnf,badprimes,2);
|
|
1352
|
+
LS2 = S[1]; S = S[2];
|
|
1353
|
+
|
|
1354
|
+
if( DEBUGLEVEL_ell >= 2, print(" L(S,2) = ",LS2));
|
|
1355
|
+
|
|
1356
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1357
|
+
\\ Construction of the Selmer group \\
|
|
1358
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1359
|
+
|
|
1360
|
+
if( DEBUGLEVEL_ell >= 2, print(); print(" Computing the Selmer group"));
|
|
1361
|
+
|
|
1362
|
+
\\ elements with square norm
|
|
1363
|
+
selmer = kernorm(LS2,vector(#S,i,S[i].p),2);
|
|
1364
|
+
if( DEBUGLEVEL_ell >= 3, print(" selmer = ",lift(selmer)));
|
|
1365
|
+
|
|
1366
|
+
\\ the first real embedding must be > 0
|
|
1367
|
+
\\ since the norm is a square, this is automatic
|
|
1368
|
+
\\ if there is a single real embedding.
|
|
1369
|
+
if( bnf.r1 == 3,
|
|
1370
|
+
rootapprox = polrealrootsisolate(polrel)[1];
|
|
1371
|
+
selmer = matintersect(selmer,kersign(LS2,rootapprox))*Mod(1,2);
|
|
1372
|
+
if( DEBUGLEVEL_ell >= 3, print(" selmer = ",lift(selmer)));
|
|
1373
|
+
);
|
|
1374
|
+
|
|
1375
|
+
\\ p-adic points
|
|
1376
|
+
if( DEBUGLEVEL_ell >= 3, print(" p-adic points"));
|
|
1377
|
+
badprimes = factorint(badprimes[1,1]*2)[,1];
|
|
1378
|
+
if( DEBUGLEVEL_ell >= 2, print(" badprimes = ",badprimes));
|
|
1379
|
+
for( i = 1, #badprimes,
|
|
1380
|
+
p = badprimes[i];
|
|
1381
|
+
if( DEBUGLEVEL_ell >= 4, print(" p = ",p));
|
|
1382
|
+
pp = ppinit(bnf.nf,p);
|
|
1383
|
+
locimage = elllocalimage(bnf.nf,pp,K);
|
|
1384
|
+
LS2image = LS2localimage(bnf.nf,LS2,pp);
|
|
1385
|
+
locimage = matintersect(LS2image,locimage);
|
|
1386
|
+
selmer = matintersect(
|
|
1387
|
+
selmer,
|
|
1388
|
+
concat(
|
|
1389
|
+
matker(LS2image),
|
|
1390
|
+
matinverseimage(LS2image,locimage)*Mod(1,2)));
|
|
1391
|
+
selmer = matimage(selmer*Mod(1,2));
|
|
1392
|
+
if( DEBUGLEVEL_ell >= 4, print(" selmer = ",lift(selmer)));
|
|
1393
|
+
if( !#selmer, break);
|
|
1394
|
+
);
|
|
1395
|
+
|
|
1396
|
+
if( DEBUGLEVEL_ell >= 2, print(" selmer = ",lift(selmer)));
|
|
1397
|
+
if( DEBUGLEVEL_ell >= 2, print(" Selmer rank = ",#selmer));
|
|
1398
|
+
|
|
1399
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1400
|
+
\\ Search for trivial points \\
|
|
1401
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1402
|
+
|
|
1403
|
+
if( #selmer,
|
|
1404
|
+
if( DEBUGLEVEL_ell >= 2, print(); print(" Search for trivial points on the curve"));
|
|
1405
|
+
listpointstriv = ratpoint(K^3*subst(polrel,'x,'x/K),LIMTRIV,0);
|
|
1406
|
+
for( i = 1, #listpointstriv,
|
|
1407
|
+
if( #listpointstriv[i] == 3,
|
|
1408
|
+
listpointstriv[i] = [0]
|
|
1409
|
+
, for( j = 1, 2, listpointstriv[i][j] /= K^j))
|
|
1410
|
+
);
|
|
1411
|
+
listpointstriv = concat(help,listpointstriv);
|
|
1412
|
+
if( DEBUGLEVEL_ell >= 2, print(" Trivial points on the curve = ",listpointstriv));
|
|
1413
|
+
);
|
|
1414
|
+
|
|
1415
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1416
|
+
\\ Run through the Selmer group \\
|
|
1417
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1418
|
+
|
|
1419
|
+
if( DEBUGLEVEL_ell >= 2, print(); print(" Run through the Selmer group"));
|
|
1420
|
+
|
|
1421
|
+
listpoints = [];
|
|
1422
|
+
selmer = lift(selmer);
|
|
1423
|
+
iwhile = 1;
|
|
1424
|
+
while( iwhile < 1<<#selmer,
|
|
1425
|
+
if( DEBUGLEVEL_ell >= 2, print());
|
|
1426
|
+
if( DEBUGLEVEL_ell >= 4, print(" iwhile = ",iwhile));
|
|
1427
|
+
|
|
1428
|
+
\\ the next element zc as an algebraic number modulo squares
|
|
1429
|
+
|
|
1430
|
+
expo = selmer*vectorv(#selmer,i,bittest(iwhile,i-1));
|
|
1431
|
+
zc = prod( i = 1, #LS2, LS2[i]^expo[i]);
|
|
1432
|
+
if( DEBUGLEVEL_ell >= 2, print(" zc = ",zc));
|
|
1433
|
+
liftzc = lift(zc);
|
|
1434
|
+
|
|
1435
|
+
\\ Reduction modulo squares
|
|
1436
|
+
|
|
1437
|
+
if( redflag,
|
|
1438
|
+
zc = reducemodsquares(zc,2);
|
|
1439
|
+
liftzc = lift(zc);
|
|
1440
|
+
den = denominator(content(liftzc))^2;
|
|
1441
|
+
zc *= den; liftzc *= den;
|
|
1442
|
+
if( DEBUGLEVEL_ell >= 2, print(" zc reduced = ",zc))
|
|
1443
|
+
);
|
|
1444
|
+
|
|
1445
|
+
\\ Does it come from a trivial point ?
|
|
1446
|
+
|
|
1447
|
+
for( i = 1, #listpointstriv,
|
|
1448
|
+
point = listpointstriv[i];
|
|
1449
|
+
if( #point == 2,
|
|
1450
|
+
if( nfissquare(bnf.nf,K*(point[1]-'x)*liftzc),
|
|
1451
|
+
if( DEBUGLEVEL_ell >= 2, print(" comes from the trivial point ",point));
|
|
1452
|
+
listpoints = concat(listpoints,[point]);
|
|
1453
|
+
iwhile = 1 << (degre(iwhile)+1);
|
|
1454
|
+
next(2)
|
|
1455
|
+
)));
|
|
1456
|
+
|
|
1457
|
+
if( DEBUGLEVEL_ell >= 2, print(" does not come from a trivial point"));
|
|
1458
|
+
|
|
1459
|
+
\\ Construction of the quadratic form q2
|
|
1460
|
+
\\ Change the basis using the square factors of zc
|
|
1461
|
+
|
|
1462
|
+
idealfactorzc = idealfactor(bnf,zc);
|
|
1463
|
+
idealfactorzc[,2] *= -1;
|
|
1464
|
+
idealfactorzc[,2] \= 2;
|
|
1465
|
+
\\ idealzc = idealfactorback(bnf,idealfactorzc);
|
|
1466
|
+
idealzc = matid(3);
|
|
1467
|
+
for( i = 1, #idealfactorzc[,1],
|
|
1468
|
+
idealzc = idealmul(bnf,idealzc,idealpow(bnf,idealfactorzc[i,1],idealfactorzc[i,2]));
|
|
1469
|
+
);
|
|
1470
|
+
baseidealzc = vector(3,i,nfbasistoalg(bnf,idealzc[,i]));
|
|
1471
|
+
q2 = matrix(3,3,i,j,trace(zc*baseidealzc[i]*baseidealzc[j]/polprime));
|
|
1472
|
+
if( DEBUGLEVEL_ell >= 4, print(" q2 = ",q2));
|
|
1473
|
+
if( DEBUGLEVEL_ell >= 4, print(" q2/content(q2) = ",q2/content(q2)));
|
|
1474
|
+
|
|
1475
|
+
\\ Solution of the quadratic equation q2=0
|
|
1476
|
+
|
|
1477
|
+
sol = qfsolve(q2/content(q2));
|
|
1478
|
+
if( DEBUGLEVEL_ell >= 4,print(" sol = ",sol));
|
|
1479
|
+
if( type(sol) == "t_INT",
|
|
1480
|
+
error(" ell2descent_gen: WRONG ELEMENT IN THE SELMER GROUP, please report"));
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
\\ Parametrizing the solutions of q2=0
|
|
1484
|
+
|
|
1485
|
+
param = qfparam(q2,sol,3)*['x^2,'x,1]~;
|
|
1486
|
+
param /= content(param);
|
|
1487
|
+
|
|
1488
|
+
\\ Construction of the quartic
|
|
1489
|
+
|
|
1490
|
+
q1 = -matrix(3,3,i,j,trace(zc*baseidealzc[i]*baseidealzc[j]*(ttheta+A)/polprime));
|
|
1491
|
+
pol = param~*q1*param;
|
|
1492
|
+
if( DEBUGLEVEL_ell >= 2, print(" quartic: ",K,"*Y^2 = ",pol));
|
|
1493
|
+
redq = redquartic(pol);
|
|
1494
|
+
pol = redq[1];
|
|
1495
|
+
den = denominator(content(K*pol));
|
|
1496
|
+
pol *= den^2;
|
|
1497
|
+
if( DEBUGLEVEL_ell >= 2, print(" reduced: ",K,"*Y^2 = ",pol));
|
|
1498
|
+
|
|
1499
|
+
\\ Search for points on the quartic
|
|
1500
|
+
|
|
1501
|
+
point = ratpoint(K*pol,LIM1,1);
|
|
1502
|
+
if( point == [], point = ratpoint2(K*pol,LIM3,1));
|
|
1503
|
+
if( point == [], iwhile ++; next );
|
|
1504
|
+
|
|
1505
|
+
if( #point == 2, point = concat(point,[1]));
|
|
1506
|
+
if( DEBUGLEVEL_ell >= 2, print(" point on the reduced quartic = ",point));
|
|
1507
|
+
point = concat(redq[2]*[point[1],point[3]]~,[point[2]/den]~);
|
|
1508
|
+
if( DEBUGLEVEL_ell >= 2, print(" point on the quartic = ",point));
|
|
1509
|
+
|
|
1510
|
+
\\ Construction of the point on the elliptic curve from the point on the quartic
|
|
1511
|
+
|
|
1512
|
+
param = subst(param,'x,'x/'y)*'y^2;
|
|
1513
|
+
param = subst(subst(param,'x,point[1]),'y,point[2]);
|
|
1514
|
+
param *= K/point[3];
|
|
1515
|
+
if( DEBUGLEVEL_ell >= 3, print(" reconstruction of the point on the curve"));
|
|
1516
|
+
q0 = matrix(3,3,i,j,trace(zc*baseidealzc[i]*baseidealzc[j]*(ttheta^2+A*ttheta+B)/polprime));
|
|
1517
|
+
pointxx = param~*q0*param/K;
|
|
1518
|
+
point2 = [ pointxx, sqrtrat(subst(polrel,'x,pointxx)/K)];
|
|
1519
|
+
if( DEBUGLEVEL_ell >= 1, print(" point on the curve = ",point2));
|
|
1520
|
+
listpoints = concat(listpoints,[point2]);
|
|
1521
|
+
iwhile = 1 << (degre(iwhile)+1)
|
|
1522
|
+
);
|
|
1523
|
+
|
|
1524
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1525
|
+
\\ Conclusion report \\
|
|
1526
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1527
|
+
|
|
1528
|
+
rang = #listpoints;
|
|
1529
|
+
|
|
1530
|
+
if( DEBUGLEVEL_ell >= 2,
|
|
1531
|
+
print();
|
|
1532
|
+
print(" rank of found points = ",#listpoints);
|
|
1533
|
+
print(" rank of the Selmer group = ",#selmer));
|
|
1534
|
+
|
|
1535
|
+
if( DEBUGLEVEL_ell >= 1, afficheselmer(rang,#selmer));
|
|
1536
|
+
|
|
1537
|
+
if( (#selmer - rang)%2,
|
|
1538
|
+
rang ++;
|
|
1539
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
1540
|
+
print(" III should be a square, hence ");
|
|
1541
|
+
afficheselmer(rang,#selmer));
|
|
1542
|
+
);
|
|
1543
|
+
|
|
1544
|
+
\\ Verification
|
|
1545
|
+
|
|
1546
|
+
if( DEBUGLEVEL_ell >= 1, print("listpoints = ",listpoints));
|
|
1547
|
+
for( i = 1, #listpoints,
|
|
1548
|
+
if( subst(polrel,'x,listpoints[i][1])-K*listpoints[i][2]^2,
|
|
1549
|
+
error(" ell2descent_gen: WRONG POINT = ",listpoints[i]," please report")));
|
|
1550
|
+
|
|
1551
|
+
\\ Reduction of the points
|
|
1552
|
+
|
|
1553
|
+
listpoints = vecsort(listpoints,,2);
|
|
1554
|
+
if( #listpoints >= 2 && ELLREDGENFLAG,
|
|
1555
|
+
listpoints = ellredgen(ell,listpoints,K));
|
|
1556
|
+
|
|
1557
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of ell2descent_gen"));
|
|
1558
|
+
return([rang,#selmer,listpoints]);
|
|
1559
|
+
}
|
|
1560
|
+
{afficheselmer(m1,m2,tors2) =
|
|
1561
|
+
|
|
1562
|
+
print("#E(Q)[2] = ",1<<tors2);
|
|
1563
|
+
print("#S(E/Q)[2] = ",1<<m2);
|
|
1564
|
+
if( m1+tors2 == m2,
|
|
1565
|
+
print("#E(Q)/2E(Q) = ",1<<(m1+tors2));
|
|
1566
|
+
print("#III(E/Q)[2] = 1");
|
|
1567
|
+
print("rank(E/Q) = ",m1);
|
|
1568
|
+
,
|
|
1569
|
+
print("#E(Q)/2E(Q) >= ",1<<(m1+tors2));
|
|
1570
|
+
print("#III(E/Q)[2] <= ",1<<(m2-m1-tors2));
|
|
1571
|
+
print("rank(E/Q) >= ",m1)
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
{ellQ_ellrank(ell,help=[]) =
|
|
1575
|
+
\\ Algorithm of 2-descent on the elliptic curve ell.
|
|
1576
|
+
\\ help is a list of known points on ell.
|
|
1577
|
+
my(urst,urst1,den,eqell,tors2,bnf,rang,time1);
|
|
1578
|
+
|
|
1579
|
+
if( DEBUGLEVEL_ell >= 3, print(" starting ellQ_ellrank"));
|
|
1580
|
+
if( #ell < 13, ell = ellinit(ell));
|
|
1581
|
+
|
|
1582
|
+
\\ kill the coefficients a1 and a3
|
|
1583
|
+
urst = [1,0,0,0];
|
|
1584
|
+
if( ell.a1 != 0 || ell.a3 != 0,
|
|
1585
|
+
urst1 = [1,0,-ell.a1/2,-ell.a3/2];
|
|
1586
|
+
ell = ellchangecurve(ell,urst1);
|
|
1587
|
+
urst = ellcomposeurst(urst,urst1)
|
|
1588
|
+
);
|
|
1589
|
+
|
|
1590
|
+
\\ kill denominators
|
|
1591
|
+
while( (den = denominator([ell.a2,ell.a4,ell.a6])) > 1,
|
|
1592
|
+
den = factor(den); den[,2] = vectorv(#den[,2],i,1);
|
|
1593
|
+
den = factorback(den);
|
|
1594
|
+
urst1 = [1/den,0,0,0];
|
|
1595
|
+
ell = ellchangecurve(ell,urst1);
|
|
1596
|
+
urst = ellcomposeurst(urst,urst1)
|
|
1597
|
+
);
|
|
1598
|
+
|
|
1599
|
+
help = ellchangepoint(help,urst);
|
|
1600
|
+
eqell = Pol([1,ell.a2,ell.a4,ell.a6]);
|
|
1601
|
+
if( DEBUGLEVEL_ell >= 1, print(" Elliptic curve: Y^2 = ",eqell));
|
|
1602
|
+
|
|
1603
|
+
\\ Choice of the algorithm depending on the 2-torsion structure
|
|
1604
|
+
|
|
1605
|
+
tors2 = ellhalf(ell,[0]);
|
|
1606
|
+
if( DEBUGLEVEL_ell >= 1, print(" E[2] = ",tors2));
|
|
1607
|
+
|
|
1608
|
+
if( #tors2 == 1, \\ case 1: 2-torsion trivial
|
|
1609
|
+
if( DEBUGLEVEL_ell >= 3, print1(" bnfinit(",eqell,")"));
|
|
1610
|
+
if( DEBUGLEVEL_ell >= 4, gettime());
|
|
1611
|
+
bnf = bnfinit(eqell,1);
|
|
1612
|
+
if( DEBUGLEVEL_ell >= 4, time1 = gettime());
|
|
1613
|
+
if( DEBUGLEVEL_ell >= 3, print(" done"));
|
|
1614
|
+
rang = ell2descent_gen(ell,bnf,1,help);
|
|
1615
|
+
if( DEBUGLEVEL_ell >= 4, print(" time for bnfinit = ",time1));
|
|
1616
|
+
if( DEBUGLEVEL_ell >= 4, print(" time for the rest = ",gettime()));
|
|
1617
|
+
,
|
|
1618
|
+
if( #tors2 == 2 || !COMPLETE, \\ case 2: 2-torsion >= Z/2Z
|
|
1619
|
+
if( ell.a6 != 0,
|
|
1620
|
+
urst1 = [1,tors2[2][1],0,0];
|
|
1621
|
+
ell = ellchangecurve(ell,urst1);
|
|
1622
|
+
urst = ellcomposeurst(urst,urst1)
|
|
1623
|
+
);
|
|
1624
|
+
eqell = Pol([1,ell.a2,ell.a4,ell.a6]);
|
|
1625
|
+
if( DEBUGLEVEL_ell >= 1, print(" Elliptic curve: Y^2 = ",eqell));
|
|
1626
|
+
|
|
1627
|
+
rang = ell2descent_viaisog(ell,help)
|
|
1628
|
+
, \\ case 3: 2-torsion = Z/2Z*Z/2Z
|
|
1629
|
+
rang = ell2descent_complete(tors2[2][1],tors2[3][1],tors2[4][1])
|
|
1630
|
+
));
|
|
1631
|
+
|
|
1632
|
+
rang[3] = ellchangepoint(rang[3],ellinverturst(urst));
|
|
1633
|
+
if( DEBUGLEVEL_ell >= 3, print(" end of ellQ_ellrank"));
|
|
1634
|
+
|
|
1635
|
+
return(rang);
|
|
1636
|
+
}
|
|
1637
|
+
{ell2descent_complete(e1,e2,e3,help) =
|
|
1638
|
+
\\ Compute the rank of the elliptic curve
|
|
1639
|
+
\\ E: Y^2 = (x-e1)*(x-e2)*(x-e3)
|
|
1640
|
+
\\ using the complete 2-descent algorithm (see J.Silverman).
|
|
1641
|
+
\\ Returns [r,s,v] with
|
|
1642
|
+
\\ r is a lower bound for the rank of E(Q)
|
|
1643
|
+
\\ s is the rank of Selmer[2]
|
|
1644
|
+
\\ v is a system of independant points on E(Q)/2E(Q)
|
|
1645
|
+
|
|
1646
|
+
\\ e1, e2, e3 must be integers.
|
|
1647
|
+
\\ help is a list of known points on E.
|
|
1648
|
+
|
|
1649
|
+
my(ee,d32,d31,d21,G1,G2,G3,vect1,vect2,vect3,selmer,rang,listpoints,b1,b2,q1,sol1,param1,param1x,quart,point,z1,solx,soly,strange,ell);
|
|
1650
|
+
|
|
1651
|
+
if( DEBUGLEVEL_ell >= 2, print(" Algorithm of complete 2-descent"));
|
|
1652
|
+
|
|
1653
|
+
\\ sort the integers e1, e2, e3 in increasing order
|
|
1654
|
+
|
|
1655
|
+
ee = vecsort([e1,e2,e3]);
|
|
1656
|
+
e1 = ee[1]; e2 = ee[2]; e3 = ee[3];
|
|
1657
|
+
|
|
1658
|
+
\\ Computation of the groups G1 and G2
|
|
1659
|
+
|
|
1660
|
+
d32 = e3-e2; d31 = e3-e1; d21 = e2-e1;
|
|
1661
|
+
G1 = factor(d31*d21)[,1]; \\ (G1 > 0)
|
|
1662
|
+
G2 = factor(-d32*d21)[,1]; \\ (G2 < 0)
|
|
1663
|
+
G3 = d31*d32;
|
|
1664
|
+
|
|
1665
|
+
if( DEBUGLEVEL_ell >= 3, print(" G1 = ",G1));
|
|
1666
|
+
if( DEBUGLEVEL_ell >= 3, print(" G2 = ",G2));
|
|
1667
|
+
|
|
1668
|
+
\\ Run through G1*G2
|
|
1669
|
+
|
|
1670
|
+
vect1 = vector(#G1,i,[0,1]);
|
|
1671
|
+
vect2 = vector(#G2,i,[0,1]);
|
|
1672
|
+
selmer = 0;
|
|
1673
|
+
rang = 0;
|
|
1674
|
+
listpoints = [];
|
|
1675
|
+
|
|
1676
|
+
forvec( X = vect1,
|
|
1677
|
+
b1 = prod( i = 1, #G1, G1[i]^X[i]);
|
|
1678
|
+
|
|
1679
|
+
\\ b1*b2*b3 must be a square, where b3 is a divisor of d32*d31
|
|
1680
|
+
vect3 = vect2;
|
|
1681
|
+
for( i = 2, #G2,
|
|
1682
|
+
if( G3%G2[i] !=0,
|
|
1683
|
+
vect3[i] = [1,1]*valuation(b1,G2[i])));
|
|
1684
|
+
|
|
1685
|
+
forvec( Y = vect3,
|
|
1686
|
+
b2 = prod( i = 1, #G2, G2[i]^Y[i]);
|
|
1687
|
+
|
|
1688
|
+
if( DEBUGLEVEL_ell >= 3, print(" [b1,b2] = ",lift([b1,b2])));
|
|
1689
|
+
|
|
1690
|
+
\\ Trivial points coming from the 2-torsion
|
|
1691
|
+
|
|
1692
|
+
if( b1==1 && b2==1,
|
|
1693
|
+
if( DEBUGLEVEL_ell >= 4, print(" trivial point [0]"));
|
|
1694
|
+
selmer++; rang++; next);
|
|
1695
|
+
if( issquare(-d21*b2) && issquare(d31*d21*b1),
|
|
1696
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial point [e1,0]"));
|
|
1697
|
+
selmer++; rang++; listpoints = concat(listpoints,[[e1,0]]); next);
|
|
1698
|
+
if( issquare(d21*b1) && issquare(-d32*d21*b2),
|
|
1699
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial point [e2,0]"));
|
|
1700
|
+
selmer++; rang++; listpoints = concat(listpoints,[[e2,0]]); next);
|
|
1701
|
+
if( issquare(d31*b1) && issquare(d32*b2),
|
|
1702
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial point [e3,0]"));
|
|
1703
|
+
selmer++; rang++; listpoints = concat(listpoints,[[e3,0]]); next);
|
|
1704
|
+
|
|
1705
|
+
\\ Trivial points coming from help
|
|
1706
|
+
|
|
1707
|
+
for( i = 1, #help,
|
|
1708
|
+
if( #help[i] != 2 || help[i][2] == 0, next);
|
|
1709
|
+
if( issquare(b1*(help[i][1]-e1)) && issquare(b2*(help[i][1]-e2)),
|
|
1710
|
+
if( DEBUGLEVEL_ell >= 3, print(" trivial point from help ",help[i]));
|
|
1711
|
+
selmer++; rang++;
|
|
1712
|
+
listpoints = concat(listpoints,[help[i]]); next(2));
|
|
1713
|
+
);
|
|
1714
|
+
|
|
1715
|
+
\\ If one can solve 2 quadratic equations
|
|
1716
|
+
\\ (1) q1: b1*z1^2-b2*z2^2 = e2-e1
|
|
1717
|
+
\\ (2) q2: b1*z1^2-b1*b2*z3^2 = e3-e1
|
|
1718
|
+
\\ then (x,y) = (b1*z1^2+e1,b1*b2*z1*z2*z3) is a point on E
|
|
1719
|
+
\\ we also have
|
|
1720
|
+
\\ (3) q3 = q1-q2: b1*b2*z3^2-b2*z2^2=e2-e3
|
|
1721
|
+
|
|
1722
|
+
\\ Solution of the q1
|
|
1723
|
+
|
|
1724
|
+
q1 = matdiagonal([b1,-b2,-d21]);
|
|
1725
|
+
if( DEBUGLEVEL_ell >= 3, print(" q1 = ",q1));
|
|
1726
|
+
sol1 = qfsolve(q1);
|
|
1727
|
+
if( type(sol1) == "t_INT",
|
|
1728
|
+
if( DEBUGLEVEL_ell >= 3, print(" q1 not ELS at ",sol1));
|
|
1729
|
+
next);
|
|
1730
|
+
if( DEBUGLEVEL_ell >= 3, print(" solution of q1 = ",sol1));
|
|
1731
|
+
param1 = qfparam(q1,sol1,1);
|
|
1732
|
+
param1 /= content(param1);
|
|
1733
|
+
if( DEBUGLEVEL_ell >= 3, print(" parametrization of q1 = ",param1));
|
|
1734
|
+
param1x = param1*['x^2,'x,1]~;
|
|
1735
|
+
|
|
1736
|
+
\\ Solution of the q2
|
|
1737
|
+
\\ only useful to detect local non solubility
|
|
1738
|
+
|
|
1739
|
+
\\ my(q2,sol2);
|
|
1740
|
+
\\ q2 = matdiagonal([b1,-b1*b2,-d31]);
|
|
1741
|
+
\\if( DEBUGLEVEL_ell >= 3, print(" q2 = ",q2));
|
|
1742
|
+
\\ sol2 = qfsolve(q2);
|
|
1743
|
+
\\ if( type(sol2) == "t_INT",
|
|
1744
|
+
\\if( DEBUGLEVEL_ell >= 3, print(" q2 not ELS at ",sol2));
|
|
1745
|
+
\\ next);
|
|
1746
|
+
|
|
1747
|
+
\\ Construction of the quartic
|
|
1748
|
+
|
|
1749
|
+
quart = b1*b2/gcd(b1,b2)^2*(b1*param1x[1]^2-d31*param1x[3]^2);
|
|
1750
|
+
if( DEBUGLEVEL_ell >= 3, print(" quart = ",quart));
|
|
1751
|
+
|
|
1752
|
+
\\ Search for trivial points on the quartic
|
|
1753
|
+
|
|
1754
|
+
point = [];
|
|
1755
|
+
\\ point = ratpoint(quart,LIM1,1);
|
|
1756
|
+
|
|
1757
|
+
\\ Local solubility of the quartic
|
|
1758
|
+
|
|
1759
|
+
if( point == [] && !locallysoluble(quart),
|
|
1760
|
+
if( DEBUGLEVEL_ell >= 3, print(" quartic not ELS "));
|
|
1761
|
+
next);
|
|
1762
|
+
if( DEBUGLEVEL_ell >= 2, print(" y^2 = ",quart));
|
|
1763
|
+
selmer++;
|
|
1764
|
+
|
|
1765
|
+
\\ Search for points on the quartic
|
|
1766
|
+
|
|
1767
|
+
if( point == [], point = ratpoint2(quart,LIM3,1));
|
|
1768
|
+
if( point != [],
|
|
1769
|
+
if( DEBUGLEVEL_ell >= 2, print(" point found on the quartic !!"));
|
|
1770
|
+
if( DEBUGLEVEL_ell >= 3, print(" ",point));
|
|
1771
|
+
if( #point == 2,
|
|
1772
|
+
z1 = subst(param1x[1],'x,point[1])/subst(param1x[3],'x,point[1])
|
|
1773
|
+
, z1 = param1[1,1]/param1[3,1]);
|
|
1774
|
+
solx = b1*z1^2+e1;
|
|
1775
|
+
soly = sqrtrat((solx-e1)*(solx-e2)*(solx-e3));
|
|
1776
|
+
listpoints = concat(listpoints,[[solx,soly]]);
|
|
1777
|
+
if( DEBUGLEVEL_ell >= 1, print(" point on the elliptic curve = ",[solx,soly]));
|
|
1778
|
+
rang++
|
|
1779
|
+
,
|
|
1780
|
+
if( DEBUGLEVEL_ell >= 2, print(" no point found on the quartic"))
|
|
1781
|
+
)
|
|
1782
|
+
)
|
|
1783
|
+
);
|
|
1784
|
+
|
|
1785
|
+
\\ end
|
|
1786
|
+
|
|
1787
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
1788
|
+
print("#S^(2) = ",selmer));
|
|
1789
|
+
if( rang > selmer/2, rang = selmer);
|
|
1790
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
1791
|
+
strange = rang != selmer;
|
|
1792
|
+
if( strange,
|
|
1793
|
+
print("#E[K]/2E[K]>= ",rang)
|
|
1794
|
+
, print("#E[K]/2E[K] = ",rang));
|
|
1795
|
+
print("#E[2] = 4");
|
|
1796
|
+
);
|
|
1797
|
+
rang = ceil(log(rang)/log(2))-2;
|
|
1798
|
+
selmer = valuation(selmer,2);
|
|
1799
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
1800
|
+
if( strange,
|
|
1801
|
+
print(selmer-2," >= rank >= ",rang)
|
|
1802
|
+
, print("rank = ",rang));
|
|
1803
|
+
if( rang, print("points = ",listpoints));
|
|
1804
|
+
);
|
|
1805
|
+
ell = ellinit([0,-(e1+e2+e3),0,e1*e2+e2*e3+e3*e1,-e1*e2*e3],1);
|
|
1806
|
+
listpoints = vecsort(listpoints,,2);
|
|
1807
|
+
if( ELLREDGENFLAG, listpoints = ellredgen(ell,listpoints));
|
|
1808
|
+
listpoints = concat(ellsort(elltorseven(ell)[3]),listpoints);
|
|
1809
|
+
|
|
1810
|
+
return([rang,selmer,listpoints]);
|
|
1811
|
+
}
|
|
1812
|
+
{ellcount( c, d, KS2gen, listpointstriv=[]) =
|
|
1813
|
+
my(found,listgen,listpointscount,m1,m2,lastloc,mask,i,d1,iaux,j,triv,pol,point,qf,solqf,para,point1,v);
|
|
1814
|
+
|
|
1815
|
+
if( DEBUGLEVEL_ell >= 4, print(" starting ellcount ",[c,d]));
|
|
1816
|
+
if( DEBUGLEVEL_ell >= 4, print(" KS2gen = ",KS2gen));
|
|
1817
|
+
if( DEBUGLEVEL_ell >= 4, print(" listpointstriv = ",listpointstriv));
|
|
1818
|
+
|
|
1819
|
+
found = 0;
|
|
1820
|
+
listgen = KS2gen;
|
|
1821
|
+
listpointscount = [];
|
|
1822
|
+
|
|
1823
|
+
m1 = m2 = 0; lastloc = -1;
|
|
1824
|
+
|
|
1825
|
+
mask = 1 << #KS2gen;
|
|
1826
|
+
i = 1;
|
|
1827
|
+
while( i < mask,
|
|
1828
|
+
d1 = 1; iaux = i; j = 1;
|
|
1829
|
+
while( iaux,
|
|
1830
|
+
if( iaux%2, d1 *= listgen[j]);
|
|
1831
|
+
iaux >>= 1; j++);
|
|
1832
|
+
if( DEBUGLEVEL_ell >= 3, print(" d1 = ",d1));
|
|
1833
|
+
triv = 0;
|
|
1834
|
+
for( j = 1, #listpointstriv,
|
|
1835
|
+
if( listpointstriv[j][1] && issquare(d1*listpointstriv[j][1]),
|
|
1836
|
+
listpointscount = concat(listpointscount,[listpointstriv[j]]);
|
|
1837
|
+
if( DEBUGLEVEL_ell >= 2, print(" trivial point"));
|
|
1838
|
+
triv = 1; m1++;
|
|
1839
|
+
if( degre(i) > lastloc, m2++);
|
|
1840
|
+
found = 1; lastloc = -1; break));
|
|
1841
|
+
if( !triv,
|
|
1842
|
+
pol = Pol([d1,0,c,0,d/d1]);
|
|
1843
|
+
if( DEBUGLEVEL_ell >= 3, print(" quartic = y^2 = ",pol));
|
|
1844
|
+
point = ratpoint(pol,LIM1,1);
|
|
1845
|
+
if( point != [],
|
|
1846
|
+
if( DEBUGLEVEL_ell >= 2, print(" point on the quartic"));
|
|
1847
|
+
if( DEBUGLEVEL_ell >= 3, print( point));
|
|
1848
|
+
m1++;
|
|
1849
|
+
listpointscount = concat(listpointscount,[d1*point[1]*point]);
|
|
1850
|
+
if( degre(i) > lastloc, m2++);
|
|
1851
|
+
found = 1; lastloc = -1
|
|
1852
|
+
,
|
|
1853
|
+
if( locallysoluble(pol),
|
|
1854
|
+
if( degre(i) > lastloc, m2++; lastloc = degre(i));
|
|
1855
|
+
\\ point = ratpoint2(pol,LIM3,1);
|
|
1856
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1857
|
+
\\ Instead of solving directly y^2 = d1*x^4+c*x^2+d/d1,
|
|
1858
|
+
\\ we solve first y^2 = d1*X^2+c*X+d/d1, then solve the quartic X = x^2
|
|
1859
|
+
\\ which gives a new quartic
|
|
1860
|
+
qf = 2*[d1,c/2,0;c/2,d/d1,0;0,0,-1];
|
|
1861
|
+
solqf = qfsolve(qf);
|
|
1862
|
+
para = qfparam(qf,solqf,2)*['x^2,'x,1]~;
|
|
1863
|
+
if( DEBUGLEVEL_ell >= 3,
|
|
1864
|
+
print(" the conic y^2 = ",Pol([d1,c,d/d1]));
|
|
1865
|
+
print(" is parametrized by [x,y] = "subst([para[1]/para[2],para[3]/para[2]],'x,'t)));
|
|
1866
|
+
point1 = ratpoint2(para[1]*para[2],LIM3,1);
|
|
1867
|
+
if( point1 != [],
|
|
1868
|
+
if(#point1 == 2,
|
|
1869
|
+
para = subst(para,'x,point1[1])
|
|
1870
|
+
, point1 = [1,point1[2]/point1[1]^2,0];
|
|
1871
|
+
para = vector(3,ii,polcoeff(para[ii],2))
|
|
1872
|
+
);
|
|
1873
|
+
point = [point1[2]/para[2],para[3]/para[2]];
|
|
1874
|
+
, point = [];
|
|
1875
|
+
);
|
|
1876
|
+
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
1877
|
+
if( point != [],
|
|
1878
|
+
if( DEBUGLEVEL_ell >= 2, print(" point on the quartic"));
|
|
1879
|
+
if( DEBUGLEVEL_ell >= 3, print( point));
|
|
1880
|
+
m1++;
|
|
1881
|
+
listpointscount = concat(listpointscount,[d1*point[1]*point]);
|
|
1882
|
+
if( degre(i) > lastloc, m2++);
|
|
1883
|
+
found = 1; lastloc = -1
|
|
1884
|
+
,
|
|
1885
|
+
if( DEBUGLEVEL_ell >= 2, print(" no point found on the quartic"))
|
|
1886
|
+
))));
|
|
1887
|
+
if( found,
|
|
1888
|
+
found = 0;
|
|
1889
|
+
v = 0; iaux = (i>>1);
|
|
1890
|
+
while( iaux, iaux >>= 1; v++);
|
|
1891
|
+
mask >>= 1;
|
|
1892
|
+
listgen = vecextract(listgen,(1<<#listgen)-(1<<v)-1);
|
|
1893
|
+
i = (1<<v)
|
|
1894
|
+
, i++)
|
|
1895
|
+
);
|
|
1896
|
+
|
|
1897
|
+
for( i = 1, #listpointscount,
|
|
1898
|
+
if( #listpointscount[i] > 1,
|
|
1899
|
+
if( subst('x^3+c*'x^2+d*'x,'x,listpointscount[i][1])-listpointscount[i][2]^2 != 0,
|
|
1900
|
+
error(" ellcount: WRONG POINT, please report ",i))));
|
|
1901
|
+
if( DEBUGLEVEL_ell >= 4, print(" end of ellcount"));
|
|
1902
|
+
|
|
1903
|
+
return([listpointscount,[m1,m2]]);
|
|
1904
|
+
}
|
|
1905
|
+
{ell2descent_viaisog(ell,help=[]) =
|
|
1906
|
+
\\ Computation of the rank of the elliptic curve ell
|
|
1907
|
+
\\ having rational 2-torsion, using the algorithm via 2-isogenies.
|
|
1908
|
+
\\
|
|
1909
|
+
\\ ell must be on the form
|
|
1910
|
+
\\ y^2=x^3+ax^2+bx -> ell = [0,a,0,b,0]
|
|
1911
|
+
\\ with a and b integers.
|
|
1912
|
+
|
|
1913
|
+
my(P,Pfact,tors,listpointstriv,KS2prod,KS2gen,listpoints,pointgen,n1,n2,certain,apinit,bpinit,np1,np2,listpoints2,aux1,aux2,certainp,rang,strange);
|
|
1914
|
+
|
|
1915
|
+
if( DEBUGLEVEL_ell >= 2, print(" Algorithm of 2-descent via isogenies"));
|
|
1916
|
+
if( #ell < 13, ell = ellinit(ell));
|
|
1917
|
+
|
|
1918
|
+
if( ell.disc == 0,
|
|
1919
|
+
error(" ell2descent_viaisog: singular curve !!"));
|
|
1920
|
+
if( ell.a1 != 0 || ell.a3 != 0 || ell.a6 != 0,
|
|
1921
|
+
error(" ell2descent_viaisog: the curve is not on the form [0,a,0,b,0]"));
|
|
1922
|
+
if( denominator(ell.a2) > 1 || denominator(ell.a4) > 1,
|
|
1923
|
+
error(" ell2descent_viaisog: non-integral coefficients"));
|
|
1924
|
+
|
|
1925
|
+
\\
|
|
1926
|
+
\\ Working with the initial curve
|
|
1927
|
+
\\
|
|
1928
|
+
|
|
1929
|
+
\\ Construction of trivial points: torsion
|
|
1930
|
+
|
|
1931
|
+
P = Pol([1,ell.a2,ell.a4]);
|
|
1932
|
+
Pfact = factor(P)[,1];
|
|
1933
|
+
tors = #Pfact;
|
|
1934
|
+
listpointstriv = concat(help,elltorseven(ell)[3]);
|
|
1935
|
+
|
|
1936
|
+
\\ Construction of trivial points: small naive height
|
|
1937
|
+
|
|
1938
|
+
if( DEBUGLEVEL_ell >= 3, print(" Search for trivial points on the curve"));
|
|
1939
|
+
P *= 'x;
|
|
1940
|
+
if( DEBUGLEVEL_ell >= 3, print(" Y^2 = ",P));
|
|
1941
|
+
listpointstriv = concat( listpointstriv, ratpoint(P,LIMTRIV,0));
|
|
1942
|
+
if( DEBUGLEVEL_ell >= 1, print(" trivial points on E(Q) = ",listpointstriv); print());
|
|
1943
|
+
|
|
1944
|
+
KS2prod = -abs(ell.a4);
|
|
1945
|
+
if( ell.a2^2-4*ell.a4 < 0, KS2prod *= -1);
|
|
1946
|
+
KS2gen = factor(KS2prod)[,1];
|
|
1947
|
+
|
|
1948
|
+
if( DEBUGLEVEL_ell >= 2,
|
|
1949
|
+
print(" #K(b,2)gen = ",#KS2gen);
|
|
1950
|
+
print(" K(b,2)gen = ",KS2gen));
|
|
1951
|
+
|
|
1952
|
+
listpoints = ellcount(ell.a2,ell.a4,KS2gen,listpointstriv);
|
|
1953
|
+
pointgen = listpoints[1];
|
|
1954
|
+
if( DEBUGLEVEL_ell >= 1, print(" points on E(Q) = ",pointgen); print());
|
|
1955
|
+
n1 = listpoints[2][1]; n2 = listpoints[2][2];
|
|
1956
|
+
|
|
1957
|
+
certain = (n1 == n2);
|
|
1958
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
1959
|
+
if( certain,
|
|
1960
|
+
print("[E(Q):phi'(E'(Q))] = ",1<<n1);
|
|
1961
|
+
print("#S^(phi')(E'/Q) = ",1<<n2);
|
|
1962
|
+
print("#III(E'/Q)[phi'] = 1"); print()
|
|
1963
|
+
,
|
|
1964
|
+
print("[E(Q):phi'(E'(Q))] >= ",1<<n1);
|
|
1965
|
+
print("#S^(phi')(E'/Q) = ",1<<n2);
|
|
1966
|
+
print("#III(E'/Q)[phi'] <= ",1<<(n2-n1)); print())
|
|
1967
|
+
);
|
|
1968
|
+
|
|
1969
|
+
\\
|
|
1970
|
+
\\ Working with the isogeneous curve
|
|
1971
|
+
\\
|
|
1972
|
+
|
|
1973
|
+
apinit = -2*ell.a2; bpinit = ell.a2^2-4*ell.a4;
|
|
1974
|
+
KS2prod = -abs(bpinit);
|
|
1975
|
+
if( ell.a4 < 0, KS2prod *= -1);
|
|
1976
|
+
KS2gen = factor(KS2prod)[,1];
|
|
1977
|
+
|
|
1978
|
+
if( DEBUGLEVEL_ell >= 2,
|
|
1979
|
+
print(" #K(a^2-4b,2)gen = ",#KS2gen);
|
|
1980
|
+
print(" K(a^2-4b,2)gen = ",KS2gen));
|
|
1981
|
+
|
|
1982
|
+
\\ Construction of trivial points: torsion
|
|
1983
|
+
|
|
1984
|
+
P = Pol([1,apinit,bpinit]);
|
|
1985
|
+
listpointstriv = elltorseven([0,apinit,0,bpinit,0])[3];
|
|
1986
|
+
|
|
1987
|
+
\\ Construction of trivial points: small naive height
|
|
1988
|
+
|
|
1989
|
+
if( DEBUGLEVEL_ell >= 3, print(" Search for trivial points on the curve"));
|
|
1990
|
+
P *= 'x;
|
|
1991
|
+
if( DEBUGLEVEL_ell >= 3, print(" Y^2 = ",P));
|
|
1992
|
+
listpointstriv = concat( listpointstriv, ratpoint(P,LIMTRIV,0));
|
|
1993
|
+
if( DEBUGLEVEL_ell >= 1, print(" trivial points on E'(Q) = ",listpointstriv); print());
|
|
1994
|
+
|
|
1995
|
+
listpoints = ellcount(apinit,bpinit,KS2gen,listpointstriv);
|
|
1996
|
+
|
|
1997
|
+
if( DEBUGLEVEL_ell >= 1, print(" points on E'(Q) = ",listpoints[1]));
|
|
1998
|
+
np1 = listpoints[2][1]; np2 = listpoints[2][2];
|
|
1999
|
+
listpoints2 = vector(#listpoints[1],i,0);
|
|
2000
|
+
for( i = 1, #listpoints[1],
|
|
2001
|
+
listpoints2[i] = [0,0];
|
|
2002
|
+
aux1 = listpoints[1][i][1]^2;
|
|
2003
|
+
if( aux1 != 0,
|
|
2004
|
+
aux2 = listpoints[1][i][2];
|
|
2005
|
+
listpoints2[i][1] = aux2^2/aux1/4;
|
|
2006
|
+
listpoints2[i][2] = aux2*(bpinit-aux1)/aux1/8
|
|
2007
|
+
, listpoints2[i] = listpoints[1][i]));
|
|
2008
|
+
if( DEBUGLEVEL_ell >= 1, print(" points on E(Q) = ",listpoints2); print());
|
|
2009
|
+
pointgen = concat(pointgen,listpoints2);
|
|
2010
|
+
|
|
2011
|
+
certainp = (np1 == np2);
|
|
2012
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2013
|
+
if( certainp,
|
|
2014
|
+
print("[E'(Q):phi(E(Q))] = ",1<<np1);
|
|
2015
|
+
print("#S^(phi)(E/Q) = ",1<<np2);
|
|
2016
|
+
print("#III(E/Q)[phi] = 1"); print()
|
|
2017
|
+
,
|
|
2018
|
+
print("[E'(Q):phi(E(Q))] >= ",1<<np1);
|
|
2019
|
+
print("#S^(phi)(E/Q) = ",1<<np2);
|
|
2020
|
+
print("#III(E/Q)[phi] <= ",1<<(np2-np1)); print());
|
|
2021
|
+
|
|
2022
|
+
if( !certain && (np2 > np1), print1(1<<(np2-np1)," <= "));
|
|
2023
|
+
print1("#III(E/Q)[2] ");
|
|
2024
|
+
if( certain && certainp, print1(" "), print1("<"));
|
|
2025
|
+
print("= ",1<<(n2+np2-n1-np1));
|
|
2026
|
+
|
|
2027
|
+
print("#E(Q)[2] = ",1<<tors);
|
|
2028
|
+
);
|
|
2029
|
+
rang = n1+np1-2;
|
|
2030
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2031
|
+
if( certain && certainp,
|
|
2032
|
+
print("#E(Q)/2E(Q) = ",(1<<(rang+tors)));
|
|
2033
|
+
print("rank = ",rang); print()
|
|
2034
|
+
,
|
|
2035
|
+
print("#E(Q)/2E(Q) >= ",(1<<(rang+tors))); print();
|
|
2036
|
+
print("",rang," <= rank <= ",n2+np2-2); print()
|
|
2037
|
+
));
|
|
2038
|
+
|
|
2039
|
+
strange = (n2+np2-n1-np1)%2;
|
|
2040
|
+
if( strange,
|
|
2041
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2042
|
+
print(" !!! III should be a square !!!"); print("hence"));
|
|
2043
|
+
if( certain,
|
|
2044
|
+
np1++;
|
|
2045
|
+
certainp = (np1 == np2);
|
|
2046
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2047
|
+
if( certainp,
|
|
2048
|
+
print("[E'(Q):phi(E(Q))] = ",1<<np1);
|
|
2049
|
+
print("#S^(phi)(E/Q) = ",1<<np2);
|
|
2050
|
+
print("#III(E/Q)[phi] = 1"); print()
|
|
2051
|
+
,
|
|
2052
|
+
print("[E'(Q):phi(E(Q))] >= ",1<<np1);
|
|
2053
|
+
print("#S^(phi)(E/Q) = ",1<<np2);
|
|
2054
|
+
print("#III(E/Q)[phi] <= ",1<<(np2-np1)); print())
|
|
2055
|
+
)
|
|
2056
|
+
,
|
|
2057
|
+
if( certainp,
|
|
2058
|
+
n1++;
|
|
2059
|
+
certain = (n1 == n2);
|
|
2060
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2061
|
+
if( certain,
|
|
2062
|
+
print("[E(Q):phi'(E'(Q))] = ",1<<n1);
|
|
2063
|
+
print("#S^(phi')(E'/Q) = ",1<<n2);
|
|
2064
|
+
print("#III(E'/Q)[phi'] = 1"); print()
|
|
2065
|
+
,
|
|
2066
|
+
print("[E(Q):phi'(E'(Q))] >= ",1<<n1);
|
|
2067
|
+
print("#S^(phi')(E'/Q) = ",1<<n2);
|
|
2068
|
+
print("#III(E'/Q)[phi'] <= ",1<<(n2-n1)); print())
|
|
2069
|
+
)
|
|
2070
|
+
, n1++)
|
|
2071
|
+
);
|
|
2072
|
+
|
|
2073
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2074
|
+
print("#S^(2)(E/Q) = ",1<<(n2+np2-1));
|
|
2075
|
+
if( !certain && (np2 > np1), print1(" ",1<<(np2-np1)," <= "));
|
|
2076
|
+
print1("#III(E/Q)[2] ");
|
|
2077
|
+
if( certain && certainp, print1(" "), print1("<"));
|
|
2078
|
+
print("= ",1<<(n2+np2-n1-np1));
|
|
2079
|
+
print("#E(Q)[2] = ",1<<tors);
|
|
2080
|
+
);
|
|
2081
|
+
rang = n1+np1-2;
|
|
2082
|
+
if( DEBUGLEVEL_ell >= 1,
|
|
2083
|
+
if( certain && certainp,
|
|
2084
|
+
print("#E(Q)/2E(Q) = ",(1<<(rang+tors))); print();
|
|
2085
|
+
print("rank = ",rang); print()
|
|
2086
|
+
,
|
|
2087
|
+
print("#E(Q)/2E(Q) >= ",(1<<(rang+tors))); print();
|
|
2088
|
+
print(rang," <= rank <= ",n2+np2-2); print())
|
|
2089
|
+
));
|
|
2090
|
+
|
|
2091
|
+
\\ end of strange
|
|
2092
|
+
|
|
2093
|
+
pointgen = vecsort(pointgen,,2);
|
|
2094
|
+
if( ELLREDGENFLAG, pointgen = ellredgen(ell,pointgen));
|
|
2095
|
+
pointgen = concat(ellsort(elltorseven(ell)[3]),pointgen);
|
|
2096
|
+
if( DEBUGLEVEL_ell >= 1, print("points = ",pointgen));
|
|
2097
|
+
if( DEBUGLEVEL_ell >= 3, print(" end of ell2descent_viaisog"));
|
|
2098
|
+
|
|
2099
|
+
return([rang,n2+np2-2+tors,pointgen]);
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
2103
|
+
\\ HELP MESSAGES \\
|
|
2104
|
+
\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
|
|
2105
|
+
|
|
2106
|
+
{
|
|
2107
|
+
\\ functions for elliptic curves
|
|
2108
|
+
addhelp(ell2descent_complete,
|
|
2109
|
+
"ell2descent_complete(e1,e2,e3): Performs a complete 2-descent on the elliptic curve y^2 = (x-e1)*(x-e2)*(x-e3). See ?ellQ_ellrank for the format of the output.");
|
|
2110
|
+
addhelp(ell2descent_gen,
|
|
2111
|
+
"ell2descent_gen((E,bnf,k=1,help=[]): E is a vector of the form [0,A,0,B,C], (or the result of ellinit of such a vector) A,B,C integers such that x^3+A*x^2+B*x+C; bnf is the corresponding bnfinit(,1); Performs 2-descent on the elliptic curve Ek: k*y^2=x^3+A*x^2+B*x+C. See ?ellQ_ellrank for the format of the output.");
|
|
2112
|
+
addhelp(ell2descent_viaisog,
|
|
2113
|
+
"ell2descent_viaisog(E,help=[]): E is an elliptic curve of the form [0,a,0,b,0], with a, b integers. Performs a 2-descent via isogeny on E. See ?ellQ_ellrank for the format of the output.");
|
|
2114
|
+
addhelp(ellQ_ellrank,
|
|
2115
|
+
"ellQ_ellrank(E,help=[]): E is any elliptic curve defined over Q. Returns a vector [r,s,v], where r is a lower bound for the rank of E, s is the rank of its 2-Selmer group and v is a list of independant points in E(Q)/2E(Q). If help is a vector of nontrivial points on E, the result might be faster. This function might be used in conjunction with elltors2(E). See also ?default_ellQ");
|
|
2116
|
+
addhelp(ellhalf,
|
|
2117
|
+
"ellhalf(E,P): returns the vector of all points Q on the elliptic curve E such that 2Q = P");
|
|
2118
|
+
addhelp(ellredgen,
|
|
2119
|
+
"ellredgen(E,v): returns a vector of smallest possible points on the elliptic curve E generating the same subgroup as v, up to torsion.");
|
|
2120
|
+
addhelp(ellsort,
|
|
2121
|
+
"ellsort(v): v being a vector of points on some elliptic curve, returns the vector v sorted according to the naive height.");
|
|
2122
|
+
addhelp(elltors2,
|
|
2123
|
+
"elltors2(E): for an elliptic curve E, returns the group E(K)[2], where K is the field of definition of the coefficients of E (Q, R, Qp or Fp).");
|
|
2124
|
+
addhelp(elltorseven,
|
|
2125
|
+
"elltorseven(E): for an elliptic curve E, returns 2-Sylow subgroup of E(K)_tors, where K is the field of definition of the coefficients of E: (Q, R, Qp or Fp).");
|
|
2126
|
+
|
|
2127
|
+
|
|
2128
|
+
\\ functions for polynomials
|
|
2129
|
+
addhelp(locallysoluble,
|
|
2130
|
+
"locallysoluble(pol): returns 1 if y^2=pol(x) is everywhere locally soluble, 0 otherwise.");
|
|
2131
|
+
addhelp(ratpoint,
|
|
2132
|
+
"ratpoint(pol,lim=1,singlepoint=1): search for rational points on y^2=pol(x), for about within the bounds given by lim. The coefficients of pol must be integral. If singlepoint=1, returns at most one point, otherwise as many as possible.");
|
|
2133
|
+
addhelp(redquartic,
|
|
2134
|
+
"redquartic(pol): reduction of the quartic pol using Cremona-Stoll algorithm. Returns [p,M], where p is the reduced quartic and M is the GL2(Z) transformation. Also works with other degree polynomials.");
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
\\ functions for number fields
|
|
2138
|
+
addhelp(bnfpSelmer,
|
|
2139
|
+
"bnfpSelmer(K,S,p): K being a number field given by bnfinit, S an ideal of K, and p a prime number, computes a set of generators of the group K(S,p) = { x in K^* / K^*^p, v_P(x) = 0 (mod p) for all P coprime to S}");
|
|
2140
|
+
addhelp(reducemodsquares,
|
|
2141
|
+
"reducemodsquares(delta,d): delta being a t_POLMOD, returns another delta'=delta*z^2, such that delta' has a small coefficient in x^d.");
|
|
2142
|
+
|
|
2143
|
+
|
|
2144
|
+
\\ others
|
|
2145
|
+
addhelp(default_ellQ,
|
|
2146
|
+
"default_ellQ(DEBUGLEVEL_ell, LIM1, LIM3, LIMTRIV, ELLREDGENFLAG, COMPLETE, MAXPROB, LIMBIGPRIME): set the value of the global variables used for ellQ_ellrank() and other related functions. DEBUGLEVEL_ell: 0-5: choose the quantity of information printed during the computation (default=0: print nothing); LIM1 (resp LIM3): search limit for easy (resp hard) points on quartics; LIMTRIV: search limit for trivial points on elliptic curves; ELLREDGENFLAG: if != 0, try to reduce the generators at the end; COMPLETE: if != 0 and full 2-torsion, use complete 2-descent, otherwise via 2-isogeny; MAXPROB, LIMBIGPRIME: technical.");
|
|
2147
|
+
/* addhelp(DEBUGLEVEL_ell,
|
|
2148
|
+
"DEBUGLEVEL_ell: Choose a higher value of this global variable to have more details of the computations printed during the 2-descent algorithm. 0 = don't print anything; 1 = (default) just print the result; 2 = print more details including the Selmer group and the nontrivial quartics.");
|
|
2149
|
+
*/
|
|
2150
|
+
}
|
|
2151
|
+
|