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,928 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# distutils: libraries = gmp
|
|
3
|
+
# sage.doctest: needs sage.rings.real_mpfr
|
|
4
|
+
"""
|
|
5
|
+
Enumeration of totally real fields: data
|
|
6
|
+
|
|
7
|
+
AUTHORS:
|
|
8
|
+
|
|
9
|
+
- John Voight (2007-09-01): Initial version
|
|
10
|
+
- John Voight (2007-09-19): various optimization tweaks
|
|
11
|
+
- John Voight (2007-10-09): improvements: Smyth bound, Lagrange multipliers for b
|
|
12
|
+
- Craig Citro and John Voight (2007-11-04): type checking and other polishing
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
#*****************************************************************************
|
|
16
|
+
# Copyright (C) 2007 William Stein and John Voight
|
|
17
|
+
#
|
|
18
|
+
# This program is free software: you can redistribute it and/or modify
|
|
19
|
+
# it under the terms of the GNU General Public License as published by
|
|
20
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
21
|
+
# (at your option) any later version.
|
|
22
|
+
# http://www.gnu.org/licenses/
|
|
23
|
+
#*****************************************************************************
|
|
24
|
+
|
|
25
|
+
from libc.math cimport sqrt
|
|
26
|
+
from cysignals.memory cimport sig_malloc, sig_free
|
|
27
|
+
|
|
28
|
+
from sage.arith.misc import binomial
|
|
29
|
+
from sage.arith.misc import GCD as gcd
|
|
30
|
+
from sage.libs.gmp.mpz cimport *
|
|
31
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
32
|
+
from sage.rings.real_mpfr import RealField
|
|
33
|
+
from sage.rings.integer_ring import ZZ
|
|
34
|
+
from sage.rings.integer cimport Integer
|
|
35
|
+
|
|
36
|
+
# Other global variables
|
|
37
|
+
ZZx = PolynomialRing(ZZ, 'x')
|
|
38
|
+
|
|
39
|
+
from libc.math cimport lrint, floor, ceil, fabs, round
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
#*********************************************************************
|
|
43
|
+
# Auxiliary routine
|
|
44
|
+
# Hermite constant, naive Newton-Raphson, and a specialized Lagrange
|
|
45
|
+
# multiplier solver.
|
|
46
|
+
#*********************************************************************
|
|
47
|
+
|
|
48
|
+
def hermite_constant(n):
|
|
49
|
+
r"""
|
|
50
|
+
Return the `n`-th Hermite constant.
|
|
51
|
+
|
|
52
|
+
The `n`-th Hermite constant (typically denoted `\gamma_n`), is defined
|
|
53
|
+
to be
|
|
54
|
+
|
|
55
|
+
.. MATH::
|
|
56
|
+
|
|
57
|
+
\max_L \min_{0 \neq x \in L} ||x||^2
|
|
58
|
+
|
|
59
|
+
where `L` runs over all lattices of dimension `n` and determinant `1`.
|
|
60
|
+
|
|
61
|
+
For `n \leq 8` it returns the exact value of `\gamma_n`, and for
|
|
62
|
+
`n > 9` it returns an upper bound on `\gamma_n`.
|
|
63
|
+
|
|
64
|
+
INPUT:
|
|
65
|
+
|
|
66
|
+
- ``n`` -- integer
|
|
67
|
+
|
|
68
|
+
OUTPUT:
|
|
69
|
+
|
|
70
|
+
(an upper bound for) the Hermite constant `\gamma_n`
|
|
71
|
+
|
|
72
|
+
EXAMPLES::
|
|
73
|
+
|
|
74
|
+
sage: hermite_constant(1) # trivial one-dimensional lattice
|
|
75
|
+
1.0
|
|
76
|
+
sage: hermite_constant(2) # Eisenstein lattice
|
|
77
|
+
1.1547005383792515
|
|
78
|
+
sage: 2/sqrt(3.)
|
|
79
|
+
1.15470053837925
|
|
80
|
+
sage: hermite_constant(8) # E_8
|
|
81
|
+
2.0
|
|
82
|
+
|
|
83
|
+
.. NOTE::
|
|
84
|
+
|
|
85
|
+
The upper bounds used can be found in [CS1999]_ and [CE2003]_.
|
|
86
|
+
|
|
87
|
+
AUTHORS:
|
|
88
|
+
|
|
89
|
+
- John Voight (2007-09-03)
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
if n <= 8:
|
|
93
|
+
# Exact values are known for gamma_n.
|
|
94
|
+
gamman = [1, 1, 4./3, 2, 4, 8, 64./3, 64, 256][n]
|
|
95
|
+
gamma = gamman**(1./n)
|
|
96
|
+
elif n <= 36:
|
|
97
|
+
gamma = [2.13263235569928, 2.26363016185702, 2.39334691240146,
|
|
98
|
+
2.52178702088414, 2.64929462619823, 2.77580405570023,
|
|
99
|
+
2.90147761892077, 3.02639364467182, 3.15067928476872,
|
|
100
|
+
3.27433066745617, 3.39744386110070, 3.52006195697466,
|
|
101
|
+
3.64224310140724, 3.76403701226104, 3.88547626036618,
|
|
102
|
+
4.00659977840648, 4.12744375027069, 4.24804458298177,
|
|
103
|
+
4.36843113799634, 4.48863097933934, 4.60866759008263,
|
|
104
|
+
4.72856660611662, 4.84834821242630, 4.96803435811402,
|
|
105
|
+
5.08764086822471, 5.20718687262715, 5.32668836123079,
|
|
106
|
+
5.44615801810606][n-9]
|
|
107
|
+
else:
|
|
108
|
+
# Mordell's inequality.
|
|
109
|
+
gamma = 5.44615801810606**((n-1.)/35)
|
|
110
|
+
|
|
111
|
+
return gamma
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
cdef double eval_seq_as_poly(int *f, int n, double x) noexcept:
|
|
115
|
+
r"""
|
|
116
|
+
Evaluates the sequence a, thought of as a polynomial with
|
|
117
|
+
|
|
118
|
+
.. MATH::
|
|
119
|
+
|
|
120
|
+
f[n]*x^n + f[n-1]*x^(n-1) + ... + f[0].
|
|
121
|
+
"""
|
|
122
|
+
cdef double s
|
|
123
|
+
|
|
124
|
+
# Horner's method: With polynomials of small degree, we shouldn't
|
|
125
|
+
# expect asymptotic methods to be any faster.
|
|
126
|
+
s = f[n]
|
|
127
|
+
for i from n > i >= 0:
|
|
128
|
+
s = s * x + f[i]
|
|
129
|
+
return s
|
|
130
|
+
|
|
131
|
+
cdef double newton(int *f, int *df, int n, double x0, double eps) noexcept:
|
|
132
|
+
r"""
|
|
133
|
+
Find the real root x of f (with derivative df) near x0
|
|
134
|
+
with provable precision eps, i.e. |x-z| < eps where z is the actual
|
|
135
|
+
root.
|
|
136
|
+
The sequence a corresponds to the polynomial f with
|
|
137
|
+
|
|
138
|
+
.. MATH::
|
|
139
|
+
|
|
140
|
+
f(x) = x^n + a[n-1]*x^(n-1) + ... + a[0].
|
|
141
|
+
|
|
142
|
+
This function (for speed reasons) has no error checking and no
|
|
143
|
+
guarantees are made as to the convergence; a naive Newton-Raphson
|
|
144
|
+
method is used.
|
|
145
|
+
"""
|
|
146
|
+
cdef double x, rdx, dx, fx
|
|
147
|
+
|
|
148
|
+
x = x0
|
|
149
|
+
dx = eval_seq_as_poly(f,n,x)/eval_seq_as_poly(df,n-1,x)
|
|
150
|
+
x -= dx
|
|
151
|
+
while fabs(dx) > eps:
|
|
152
|
+
# In truly optimized code, one could tune by automatically
|
|
153
|
+
# iterating a certain number of times based on the size of dx to
|
|
154
|
+
# save on a few comparisons.
|
|
155
|
+
# This savings should be almost negligible...?
|
|
156
|
+
dx = eval_seq_as_poly(f,n,x)/eval_seq_as_poly(df,n-1,x)
|
|
157
|
+
x -= dx
|
|
158
|
+
|
|
159
|
+
# Small hack for improved performance elsewhere: if it is close to an
|
|
160
|
+
# integer, give it full precision as an integer.
|
|
161
|
+
rdx = round(x)
|
|
162
|
+
if fabs(rdx-x) < eps:
|
|
163
|
+
x = rdx
|
|
164
|
+
|
|
165
|
+
# Now ensure that either f(x-eps) or f(x+eps) has opposite sign
|
|
166
|
+
# as f(x), which implies that |x-z| < eps.
|
|
167
|
+
fx = eval_seq_as_poly(f,n,x)
|
|
168
|
+
while not (fx == 0 or fx*eval_seq_as_poly(f,n,x+eps) < 0 or
|
|
169
|
+
fx*eval_seq_as_poly(f,n,x-eps) < 0):
|
|
170
|
+
dx = eval_seq_as_poly(f,n,x)/eval_seq_as_poly(df,n-1,x)
|
|
171
|
+
x -= dx
|
|
172
|
+
fx = eval_seq_as_poly(f,n,x)
|
|
173
|
+
return x
|
|
174
|
+
|
|
175
|
+
cdef void newton_in_intervals(int *f, int *df, int n, double *beta,
|
|
176
|
+
double eps, double *rts) noexcept:
|
|
177
|
+
r"""
|
|
178
|
+
Find the real roots of f in the intervals specified by beta:
|
|
179
|
+
|
|
180
|
+
(beta[0],beta[1]), (beta[1],beta[2]), ..., (beta[n-1], beta[n])
|
|
181
|
+
|
|
182
|
+
Calls newton_kernel, so same provisos apply---in particular,
|
|
183
|
+
each interval should contain a unique simple root.
|
|
184
|
+
Note the derivative *df is passed but is recomputed--this is
|
|
185
|
+
just a way to save a malloc and free for each call.
|
|
186
|
+
"""
|
|
187
|
+
cdef int i
|
|
188
|
+
|
|
189
|
+
for i from 0 <= i < n:
|
|
190
|
+
df[i] = f[i+1]*(i+1)
|
|
191
|
+
for i from 0 <= i < n:
|
|
192
|
+
rts[i] = newton(f, df, n, (beta[i]+beta[i+1])/2, eps)
|
|
193
|
+
|
|
194
|
+
cpdef lagrange_degree_3(int n, int an1, int an2, int an3):
|
|
195
|
+
r"""
|
|
196
|
+
Private function. Solves the equations which arise in the Lagrange multiplier
|
|
197
|
+
for degree 3: for each `1 \leq r \leq n-2`, we solve
|
|
198
|
+
|
|
199
|
+
.. MATH::
|
|
200
|
+
|
|
201
|
+
r*x^i + (n-1-r)\cdot y^i + z^i = s_i \quad (i = 1,2,3)
|
|
202
|
+
|
|
203
|
+
where the `s_i` are the power sums determined by the coefficients `a`.
|
|
204
|
+
We output the largest value of `z` which occurs.
|
|
205
|
+
We use a precomputed elimination ideal.
|
|
206
|
+
|
|
207
|
+
EXAMPLES::
|
|
208
|
+
|
|
209
|
+
sage: from sage.rings.number_field.totallyreal_data import lagrange_degree_3
|
|
210
|
+
sage: ls = lagrange_degree_3(3,0,1,2)
|
|
211
|
+
sage: [RealField(10)(x) for x in ls]
|
|
212
|
+
[-1.0, -1.0]
|
|
213
|
+
sage: lagrange_degree_3(3,6,1,2) # random
|
|
214
|
+
[-5.8878, -5.8878]
|
|
215
|
+
|
|
216
|
+
TESTS:
|
|
217
|
+
|
|
218
|
+
Check that :issue:`13101` is solved::
|
|
219
|
+
|
|
220
|
+
sage: lagrange_degree_3(4,12,19,42)
|
|
221
|
+
[0.0, -1.0]
|
|
222
|
+
"""
|
|
223
|
+
cdef long coeffs[7]
|
|
224
|
+
cdef int r, rsq, rcu
|
|
225
|
+
cdef int nr, nrsq, nrcu
|
|
226
|
+
cdef int s1, s1sq, s1cu, s1fo, s2, s2sq, s2cu, s3, s3sq
|
|
227
|
+
|
|
228
|
+
RRx = PolynomialRing(RealField(20),'x')
|
|
229
|
+
|
|
230
|
+
# Newton's relations.
|
|
231
|
+
s1 = -an1
|
|
232
|
+
s2 = -(an1*s1 + 2*an2)
|
|
233
|
+
s3 = -(an1*s2 + an2*s1 + 3*an3)
|
|
234
|
+
|
|
235
|
+
s1sq = s1*s1
|
|
236
|
+
s1cu = s1*s1sq
|
|
237
|
+
s1fo = s1*s1cu
|
|
238
|
+
s2sq = s2*s2
|
|
239
|
+
s2cu = s2*s2sq
|
|
240
|
+
s3sq = s3*s3
|
|
241
|
+
|
|
242
|
+
z4minmax = []
|
|
243
|
+
|
|
244
|
+
for r from 1 <= r <= n-2:
|
|
245
|
+
nr = n-1-r
|
|
246
|
+
# common subexpressions
|
|
247
|
+
rsq = r*r
|
|
248
|
+
rcu = r*rsq
|
|
249
|
+
nrsq = nr*nr
|
|
250
|
+
nrcu = nr*nrsq
|
|
251
|
+
|
|
252
|
+
## x^6
|
|
253
|
+
coeffs[6] = rcu*nr + rcu + 2*rsq*nrsq + 5*rsq*nr + 3*rsq + \
|
|
254
|
+
r*nrcu + 5*r*nrsq + 7*r*nr + 3*r + nrcu + \
|
|
255
|
+
3*nrsq + 3*nr + 1
|
|
256
|
+
|
|
257
|
+
## x^5
|
|
258
|
+
coeffs[5] = -6*rsq*nr*s1 - 6*rsq*s1 - 6*r*nrsq*s1 - 18*r*nr*s1 - \
|
|
259
|
+
12*r*s1 - 6*nrsq*s1 - 12*nr*s1 - 6*s1
|
|
260
|
+
|
|
261
|
+
## x^4
|
|
262
|
+
coeffs[4] = -3*rcu*s2 - 3*rsq*nr*s2 + 3*rsq*s1sq - 6*rsq*s2 - \
|
|
263
|
+
3*r*nrsq*s2 + 15*r*nr*s1sq - 6*r*nr*s2 + 18*r*s1sq - \
|
|
264
|
+
3*r*s2 - 3*nrcu*s2 + 3*nrsq*s1sq - 6*nrsq*s2 + \
|
|
265
|
+
18*nr*s1sq - 3*nr*s2 + 15*s1sq
|
|
266
|
+
|
|
267
|
+
## x^3
|
|
268
|
+
coeffs[3] = -2*rcu*nr*s3 - 4*rsq*nrsq*s3 + 6*rsq*nr*s1*s2 - \
|
|
269
|
+
6*rsq*nr*s3 + 12*rsq*s1*s2 - 2*r*nrcu*s3 + \
|
|
270
|
+
6*r*nrsq*s1*s2 - 6*r*nrsq*s3 - 4*r*nr*s1cu + \
|
|
271
|
+
12*r*nr*s1*s2 - 4*r*nr*s3 - 12*r*s1cu + 12*r*s1*s2 + \
|
|
272
|
+
12*nrsq*s1*s2 - 12*nr*s1cu + 12*nr*s1*s2 - \
|
|
273
|
+
20*s1cu
|
|
274
|
+
|
|
275
|
+
## x^2
|
|
276
|
+
coeffs[2] = 3*rcu*s2sq + 6*rsq*nr*s1*s3 - 3*rsq*nr*s2sq - \
|
|
277
|
+
6*rsq*s1sq*s2 + 3*rsq*s2sq + 6*r*nrsq*s1*s3 - \
|
|
278
|
+
3*r*nrsq*s2sq - 6*r*nr*s1sq*s2 + 12*r*nr*s1*s3 + \
|
|
279
|
+
3*r*nr*s2sq + 3*r*s1fo - 18*r*s1sq*s2 + \
|
|
280
|
+
3*nrcu*s2sq - 6*nrsq*s1sq*s2 + 3*nrsq*s2sq + \
|
|
281
|
+
3*nr*s1fo - 18*nr*s1sq*s2 + 15*s1fo
|
|
282
|
+
|
|
283
|
+
## x^1
|
|
284
|
+
coeffs[1] = 6*rsq*nr*s2*s3 - 6*rsq*s1*s2sq + 6*r*nrsq*s2*s3 - \
|
|
285
|
+
12*r*nr*s1sq*s3 - 6*r*nr*s1*s2sq + 12*r*s1cu*s2 - \
|
|
286
|
+
6*nrsq*s1*s2sq + 12*nr*s1cu*s2 - 6*s1*s1fo
|
|
287
|
+
|
|
288
|
+
## x^0
|
|
289
|
+
coeffs[0] = rcu*nr*s3sq - rcu*s2cu + 2*rsq*nrsq*s3sq - \
|
|
290
|
+
6*rsq*nr*s1*s2*s3 + rsq*nr*s2cu + 3*rsq*s1sq*s2sq + \
|
|
291
|
+
r*nrcu*s3sq - 6*r*nrsq*s1*s2*s3 + r*nrsq*s2cu + \
|
|
292
|
+
4*r*nr*s1cu*s3 + 3*r*nr*s1sq*s2sq - \
|
|
293
|
+
3*r*s1fo*s2 - nrcu*s2cu + \
|
|
294
|
+
3*nrsq*s1sq*s2sq - 3*nr*s1fo*s2 + \
|
|
295
|
+
s1sq*s1fo
|
|
296
|
+
|
|
297
|
+
fcoeff = [ int(coeffs[i]) for i in range(7) ]
|
|
298
|
+
f = ZZx(fcoeff)
|
|
299
|
+
df = ZZx([i*coeffs[i] for i in range(1,7)])
|
|
300
|
+
f = f//gcd(f, df)
|
|
301
|
+
fcoeff = [int(c) for c in f.list()]
|
|
302
|
+
|
|
303
|
+
rts = RRx(fcoeff).roots()
|
|
304
|
+
|
|
305
|
+
if rts:
|
|
306
|
+
rts = [rtsi[0] for rtsi in rts]
|
|
307
|
+
z4minmax = [min(rts + z4minmax), max(rts + z4minmax)]
|
|
308
|
+
|
|
309
|
+
if not z4minmax:
|
|
310
|
+
return [0.0, -1.0]
|
|
311
|
+
|
|
312
|
+
return z4minmax
|
|
313
|
+
|
|
314
|
+
cdef int __len_primes = 46
|
|
315
|
+
cdef long primessq[46]
|
|
316
|
+
primessq_py = [4, 9, 25, 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681, 1849, 2209, 2809, 3481, 3721, 4489, 5041, 5329, 6241, 6889, 7921, 9409, 10201, 10609, 11449, 11881, 12769, 16129, 17161, 18769, 19321, 22201, 22801, 24649, 26569, 27889, 29929, 32041, 32761, 36481, 37249, 38809, 39601]
|
|
317
|
+
for i from 0 <= i < 46:
|
|
318
|
+
primessq[i] = primessq_py[i]
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def int_has_small_square_divisor(sage.rings.integer.Integer d):
|
|
322
|
+
r"""
|
|
323
|
+
Return the largest `a` such that `a^2` divides `d` and `a` has prime divisors `< 200`.
|
|
324
|
+
|
|
325
|
+
EXAMPLES::
|
|
326
|
+
|
|
327
|
+
sage: from sage.rings.number_field.totallyreal_data import int_has_small_square_divisor
|
|
328
|
+
sage: int_has_small_square_divisor(500)
|
|
329
|
+
100
|
|
330
|
+
sage: is_prime(691)
|
|
331
|
+
True
|
|
332
|
+
sage: int_has_small_square_divisor(691)
|
|
333
|
+
1
|
|
334
|
+
sage: int_has_small_square_divisor(691^2)
|
|
335
|
+
1
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
cdef int i
|
|
339
|
+
cdef Integer asq
|
|
340
|
+
|
|
341
|
+
asq = ZZ(1)
|
|
342
|
+
for i from 0 <= i < __len_primes:
|
|
343
|
+
while mpz_divisible_ui_p(d.value, primessq[i]):
|
|
344
|
+
asq *= primessq[i]
|
|
345
|
+
mpz_divexact_ui(d.value, d.value, primessq[i])
|
|
346
|
+
|
|
347
|
+
return asq
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
cdef int eval_seq_as_poly_int(int *f, int n, int x) noexcept:
|
|
351
|
+
r"""
|
|
352
|
+
Evaluates the sequence a, thought of as a polynomial with
|
|
353
|
+
|
|
354
|
+
.. MATH::
|
|
355
|
+
|
|
356
|
+
f[n]*x^n + f[n-1]*x^(n-1) + ... + f[0].
|
|
357
|
+
"""
|
|
358
|
+
cdef int s
|
|
359
|
+
|
|
360
|
+
s = f[n]
|
|
361
|
+
for i from n > i >= 0:
|
|
362
|
+
s = s * x + f[i]
|
|
363
|
+
return s
|
|
364
|
+
|
|
365
|
+
cdef double eps_abs, phi, sqrt2
|
|
366
|
+
eps_abs = 10.**(-12)
|
|
367
|
+
phi = 0.618033988749895
|
|
368
|
+
sqrt2 = 1.41421356237310
|
|
369
|
+
|
|
370
|
+
cdef int easy_is_irreducible(int *a, int n) noexcept:
|
|
371
|
+
r"""
|
|
372
|
+
Very often, polynomials have roots in {+/-1, +/-2, +/-phi, sqrt2}, so we rule
|
|
373
|
+
these out quickly. Returns 0 if reducible, 1 if inconclusive.
|
|
374
|
+
"""
|
|
375
|
+
cdef int s, t, st, i
|
|
376
|
+
|
|
377
|
+
# Check if a has a root in {1,-1,2,-2}.
|
|
378
|
+
if eval_seq_as_poly_int(a,n,1) == 0 or eval_seq_as_poly_int(a,n,-1) == 0 or eval_seq_as_poly_int(a,n,2) == 0 or eval_seq_as_poly_int(a,n,-2) == 0:
|
|
379
|
+
return 0
|
|
380
|
+
|
|
381
|
+
# Check if f has factors x^2-x-1, x^2+x-1, x^2-2, respectively.
|
|
382
|
+
# Note we only call the ZZx constructor if we're almost certain to reject.
|
|
383
|
+
if fabs(eval_seq_as_poly(a,n,-phi)) < eps_abs:
|
|
384
|
+
s = 2*a[n]
|
|
385
|
+
t = 0
|
|
386
|
+
for i from n > i >= 0:
|
|
387
|
+
st = (s+t)//2
|
|
388
|
+
s = 2*t+st+2*a[i]
|
|
389
|
+
t = st
|
|
390
|
+
if s == 0 and t == 0:
|
|
391
|
+
return 0
|
|
392
|
+
if fabs(eval_seq_as_poly(a,n,phi)) < eps_abs:
|
|
393
|
+
s = 2*a[n]
|
|
394
|
+
t = 0
|
|
395
|
+
for i from n > i >= 0:
|
|
396
|
+
st = (s-t)//2
|
|
397
|
+
s = 2*t-st+2*a[i]
|
|
398
|
+
t = st
|
|
399
|
+
if s == 0 and t == 0:
|
|
400
|
+
return 0
|
|
401
|
+
if fabs(eval_seq_as_poly(a,n,sqrt2)) < eps_abs:
|
|
402
|
+
s = a[n]
|
|
403
|
+
t = 0
|
|
404
|
+
for i from n > i >= 0:
|
|
405
|
+
st = s
|
|
406
|
+
s = 2*t+a[i]
|
|
407
|
+
t = st
|
|
408
|
+
if s == 0 and t == 0:
|
|
409
|
+
return 0
|
|
410
|
+
|
|
411
|
+
return 1
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def easy_is_irreducible_py(f):
|
|
415
|
+
"""
|
|
416
|
+
Used solely for testing easy_is_irreducible.
|
|
417
|
+
|
|
418
|
+
EXAMPLES::
|
|
419
|
+
|
|
420
|
+
sage: from sage.rings.number_field.totallyreal_data import easy_is_irreducible_py
|
|
421
|
+
sage: easy_is_irreducible_py(pari('x^2+1'))
|
|
422
|
+
1
|
|
423
|
+
sage: easy_is_irreducible_py(pari('x^2-1'))
|
|
424
|
+
0
|
|
425
|
+
"""
|
|
426
|
+
cdef int a[10]
|
|
427
|
+
|
|
428
|
+
for i from 0 <= i < len(f):
|
|
429
|
+
a[i] = f[i]
|
|
430
|
+
return easy_is_irreducible(a, len(f)-1)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
#****************************************************************************
|
|
434
|
+
# Main class and routine
|
|
435
|
+
#****************************************************************************
|
|
436
|
+
|
|
437
|
+
# Global precision to find roots; this should probably depend on the
|
|
438
|
+
# architecture in some way. Algorithm gives provably correct results
|
|
439
|
+
# for any eps, but an optimal value of eps will be neither too large
|
|
440
|
+
# (which gives trivial bounds on coefficients) nor too small (which
|
|
441
|
+
# spends needless time computing higher precision on the roots).
|
|
442
|
+
cdef double eps_global
|
|
443
|
+
eps_global = 10.**(-4)
|
|
444
|
+
|
|
445
|
+
from sage.rings.number_field.totallyreal_phc import __lagrange_bounds_phc
|
|
446
|
+
|
|
447
|
+
cdef class tr_data:
|
|
448
|
+
r"""
|
|
449
|
+
This class encodes the data used in the enumeration of totally real
|
|
450
|
+
fields.
|
|
451
|
+
|
|
452
|
+
We do not give a complete description here. For more information,
|
|
453
|
+
see the attached functions; all of these are used internally by the
|
|
454
|
+
functions in :mod:`.totallyreal`, so see that file for examples and
|
|
455
|
+
further documentation.
|
|
456
|
+
"""
|
|
457
|
+
|
|
458
|
+
def __init__(self, int n, B, a=[]):
|
|
459
|
+
r"""
|
|
460
|
+
Initialization routine (constructor).
|
|
461
|
+
|
|
462
|
+
INPUT:
|
|
463
|
+
|
|
464
|
+
- ``n`` -- integer; the degree
|
|
465
|
+
- ``B`` -- integer; the discriminant bound
|
|
466
|
+
- ``a`` -- list (default: ``[]``); the coefficient list to begin with,
|
|
467
|
+
where ``a[len(a)]*x^n + ... + a[0]x^(n-len(a))``
|
|
468
|
+
|
|
469
|
+
OUTPUT:
|
|
470
|
+
|
|
471
|
+
the data initialized to begin enumeration of totally real fields
|
|
472
|
+
with degree n, discriminant bounded by B, and starting with
|
|
473
|
+
coefficients a.
|
|
474
|
+
|
|
475
|
+
EXAMPLES::
|
|
476
|
+
|
|
477
|
+
sage: from sage.rings.number_field.totallyreal_data import tr_data
|
|
478
|
+
sage: T = tr_data(2,100)
|
|
479
|
+
sage: T.printa()
|
|
480
|
+
k = 0
|
|
481
|
+
a = [0, -1, 1]
|
|
482
|
+
amax = [0, 0, 1]
|
|
483
|
+
beta = [...]
|
|
484
|
+
gnk = [...]
|
|
485
|
+
"""
|
|
486
|
+
|
|
487
|
+
cdef int i
|
|
488
|
+
|
|
489
|
+
# Initialize constants.
|
|
490
|
+
self.n = n
|
|
491
|
+
self.B = B
|
|
492
|
+
self.gamma = hermite_constant(n-1)
|
|
493
|
+
|
|
494
|
+
# Declare the coefficients of the polynomials (and max such).
|
|
495
|
+
self.a = <int*>sig_malloc(sizeof(int)*(n+1))
|
|
496
|
+
if self.a == NULL: raise MemoryError
|
|
497
|
+
self.amax = <int*>sig_malloc(sizeof(int)*(n+1))
|
|
498
|
+
if self.amax == NULL: raise MemoryError
|
|
499
|
+
# df is memory set aside for the derivative, as
|
|
500
|
+
# used in Newton iteration above.
|
|
501
|
+
self.df = <int*>sig_malloc(sizeof(int)*(n+1))
|
|
502
|
+
if self.df == NULL: raise MemoryError
|
|
503
|
+
|
|
504
|
+
for i from 0 <= i < n+1:
|
|
505
|
+
self.a[i] = 0
|
|
506
|
+
self.amax[i] = 0
|
|
507
|
+
self.df[i] = 0
|
|
508
|
+
|
|
509
|
+
# beta is an array of arrays (of length n) which list the
|
|
510
|
+
# roots of the derivatives.
|
|
511
|
+
self.beta = <double*>sig_malloc(sizeof(double)*n*(n+1))
|
|
512
|
+
if self.beta == NULL: raise MemoryError
|
|
513
|
+
# gnk is the collection of (normalized) derivatives.
|
|
514
|
+
self.gnk = <int*>sig_malloc(sizeof(int)*(n+1)*n)
|
|
515
|
+
if self.gnk == NULL: raise MemoryError
|
|
516
|
+
|
|
517
|
+
for i from 0 <= i < (n+1)*n:
|
|
518
|
+
self.beta[i] = <double>0
|
|
519
|
+
self.gnk[i] = 0
|
|
520
|
+
|
|
521
|
+
# Initialize variables.
|
|
522
|
+
if a == []:
|
|
523
|
+
# No starting input, all polynomials will be found; initialize to zero.
|
|
524
|
+
a = [0]*n + [1]
|
|
525
|
+
for i from 0 <= i < n+1:
|
|
526
|
+
self.a[i] = a[i]
|
|
527
|
+
self.amax[i] = a[i]
|
|
528
|
+
self.a[n-1] = -(n//2)
|
|
529
|
+
self.amax[n-1] = 0
|
|
530
|
+
self.k = n-2
|
|
531
|
+
elif len(a) <= n+1:
|
|
532
|
+
# First few coefficients have been specified.
|
|
533
|
+
# The value of k is the largest index of the coefficients of a which is
|
|
534
|
+
# currently unknown; e.g., if k == -1, then we can iterate
|
|
535
|
+
# over polynomials, and if k == n-1, then we have finished iterating.
|
|
536
|
+
if a[len(a)-1] != 1:
|
|
537
|
+
raise ValueError("a[len(a)-1](=%s) must be 1 so polynomial is monic" % a[len(a)-1])
|
|
538
|
+
|
|
539
|
+
k = n-len(a)
|
|
540
|
+
self.k = k
|
|
541
|
+
a = [0]*(k+1) + a
|
|
542
|
+
for i from 0 <= i < n+1:
|
|
543
|
+
self.a[i] = a[i]
|
|
544
|
+
self.amax[i] = a[i]
|
|
545
|
+
|
|
546
|
+
# Bounds come from an application of Lagrange multipliers in degrees 2,3.
|
|
547
|
+
self.b_lower = -1./n*(self.a[n-1] + (n-1.)*sqrt((1.*self.a[n-1])**2 - 2.*(1+1./(n-1))*self.a[n-2]))
|
|
548
|
+
self.b_upper = -1./n*(self.a[n-1] - (n-1.)*sqrt((1.*self.a[n-1])**2 - 2.*(1+1./(n-1))*self.a[n-2]))
|
|
549
|
+
if k < n-3:
|
|
550
|
+
bminmax = lagrange_degree_3(n,a[n-1],a[n-2],a[n-3])
|
|
551
|
+
if bminmax:
|
|
552
|
+
self.b_lower = bminmax[0]
|
|
553
|
+
self.b_upper = bminmax[1]
|
|
554
|
+
|
|
555
|
+
# Annoying, but must reverse coefficients for NumPy.
|
|
556
|
+
gnk = [int(binomial(j,k+2))*a[j] for j in range(k+2,n+1)]
|
|
557
|
+
gnk.reverse()
|
|
558
|
+
import numpy
|
|
559
|
+
rts = numpy.roots(gnk).tolist()
|
|
560
|
+
rts.sort()
|
|
561
|
+
self.beta[(k+1)*(n+1)+0] = self.b_lower
|
|
562
|
+
for i from 0 <= i < n-k-2:
|
|
563
|
+
self.beta[(k+1)*(n+1)+(i+1)] = rts[i]
|
|
564
|
+
self.beta[(k+1)*(n+1)+(n-k-1)] = self.b_upper
|
|
565
|
+
|
|
566
|
+
# Now to really initialize gnk.
|
|
567
|
+
gnk = [0] + [binomial(j,k+1)*a[j] for j in range(k + 2, n + 1)]
|
|
568
|
+
for i from 0 <= i < n-k:
|
|
569
|
+
self.gnk[(k+1)*n+i] = gnk[i]
|
|
570
|
+
else:
|
|
571
|
+
# Bad input!
|
|
572
|
+
raise ValueError("a has length %s > n+1" % len(a))
|
|
573
|
+
|
|
574
|
+
def __dealloc__(self):
|
|
575
|
+
r"""
|
|
576
|
+
Destructor.
|
|
577
|
+
"""
|
|
578
|
+
sig_free(self.df)
|
|
579
|
+
sig_free(self.a)
|
|
580
|
+
sig_free(self.amax)
|
|
581
|
+
sig_free(self.beta)
|
|
582
|
+
sig_free(self.gnk)
|
|
583
|
+
|
|
584
|
+
def increment(self, verbose=False, haltk=0, phc=False):
|
|
585
|
+
r"""
|
|
586
|
+
'Increment' the totally real data to the next
|
|
587
|
+
value which satisfies the bounds essentially given by Rolle's
|
|
588
|
+
theorem, and return the next polynomial as a sequence of
|
|
589
|
+
integers.
|
|
590
|
+
|
|
591
|
+
The default or usual case just increments the constant
|
|
592
|
+
coefficient; then inductively, if this is outside of the
|
|
593
|
+
bounds we increment the next higher coefficient, and so on.
|
|
594
|
+
|
|
595
|
+
If there are no more coefficients to be had, returns the zero
|
|
596
|
+
polynomial.
|
|
597
|
+
|
|
598
|
+
INPUT:
|
|
599
|
+
|
|
600
|
+
- ``verbose`` -- boolean to print verbosely computational details
|
|
601
|
+
- ``haltk`` -- integer; the level at which to halt the inductive
|
|
602
|
+
coefficient bounds
|
|
603
|
+
- ``phc`` -- boolean, if PHCPACK is available, use it when `k = n-5` to
|
|
604
|
+
compute an improved Lagrange multiplier bound
|
|
605
|
+
|
|
606
|
+
OUTPUT: the next polynomial, as a sequence of integers
|
|
607
|
+
|
|
608
|
+
EXAMPLES::
|
|
609
|
+
|
|
610
|
+
sage: from sage.rings.number_field.totallyreal_data import tr_data
|
|
611
|
+
sage: T = tr_data(2,100)
|
|
612
|
+
sage: T.increment()
|
|
613
|
+
[-24, -1, 1]
|
|
614
|
+
sage: for i in range(19): _ = T.increment()
|
|
615
|
+
sage: T.increment()
|
|
616
|
+
[-3, -1, 1]
|
|
617
|
+
sage: T.increment()
|
|
618
|
+
[-25, 0, 1]
|
|
619
|
+
"""
|
|
620
|
+
cdef int *f_out
|
|
621
|
+
cdef int i
|
|
622
|
+
|
|
623
|
+
f_out = <int *>sig_malloc(sizeof(int) * (self.n + 1))
|
|
624
|
+
if f_out == NULL:
|
|
625
|
+
raise MemoryError("unable to allocate coefficient list")
|
|
626
|
+
for i from 0 <= i < self.n:
|
|
627
|
+
f_out[i] = 0
|
|
628
|
+
f_out[self.n] = 1
|
|
629
|
+
|
|
630
|
+
self.incr(f_out, verbose, haltk, phc)
|
|
631
|
+
|
|
632
|
+
g = [0] * (1 + self.n)
|
|
633
|
+
for i from 0 <= i <= self.n:
|
|
634
|
+
g[i] = f_out[i]
|
|
635
|
+
sig_free(f_out)
|
|
636
|
+
|
|
637
|
+
return g
|
|
638
|
+
|
|
639
|
+
cdef void incr(self, int *f_out, int verbose, int haltk, int phc) noexcept:
|
|
640
|
+
r"""
|
|
641
|
+
This function 'increments' the totally real data to the next
|
|
642
|
+
value which satisfies the bounds essentially given by Rolle's
|
|
643
|
+
theorem, and returns the next polynomial in the sequence
|
|
644
|
+
f_out.
|
|
645
|
+
|
|
646
|
+
The default or usual case just increments the constant
|
|
647
|
+
coefficient; then inductively, if this is outside of the
|
|
648
|
+
bounds we increment the next higher coefficient, and so on.
|
|
649
|
+
|
|
650
|
+
If there are no more coefficients to be had, returns the zero
|
|
651
|
+
polynomial.
|
|
652
|
+
|
|
653
|
+
INPUT:
|
|
654
|
+
|
|
655
|
+
- ``f_out`` -- integer sequence, to be written with the coefficients of
|
|
656
|
+
the next polynomial
|
|
657
|
+
- ``verbose`` -- boolean to print verbosely computational details
|
|
658
|
+
- ``haltk`` -- integer; the level at which to halt the inductive
|
|
659
|
+
coefficient bounds
|
|
660
|
+
- ``phc`` -- boolean; if PHCPACK is available, use it when ``k == n-5``
|
|
661
|
+
to compute an improved Lagrange multiplier bound
|
|
662
|
+
|
|
663
|
+
OUTPUT:
|
|
664
|
+
|
|
665
|
+
None. The return value is stored in the variable f_out.
|
|
666
|
+
"""
|
|
667
|
+
cdef int n, np1, k, i, nk, kz
|
|
668
|
+
cdef int *gnkm
|
|
669
|
+
cdef int *gnkm1
|
|
670
|
+
cdef double *betak
|
|
671
|
+
cdef double bl, br, akmin, akmax, tmp_dbl
|
|
672
|
+
cdef bint maxoutflag
|
|
673
|
+
|
|
674
|
+
n = self.n
|
|
675
|
+
np1 = n+1
|
|
676
|
+
k = self.k
|
|
677
|
+
|
|
678
|
+
# If k == -1, we have a full polynomial, so we add 1 to the constant coefficient.
|
|
679
|
+
if k == -1:
|
|
680
|
+
self.a[0] += 1
|
|
681
|
+
# Can't have constant coefficient zero!
|
|
682
|
+
if self.a[0] == 0:
|
|
683
|
+
self.a[0] += 1
|
|
684
|
+
if self.a[0] <= self.amax[0] and easy_is_irreducible(self.a, n):
|
|
685
|
+
for i from 0 <= i < n:
|
|
686
|
+
f_out[i] = self.a[i]
|
|
687
|
+
return
|
|
688
|
+
else:
|
|
689
|
+
if verbose:
|
|
690
|
+
print(" ", end="")
|
|
691
|
+
for i from 0 <= i < np1:
|
|
692
|
+
print(self.a[i], end="")
|
|
693
|
+
print(">", end="")
|
|
694
|
+
for i from 0 <= i < np1:
|
|
695
|
+
print(self.amax[i], end="")
|
|
696
|
+
print("")
|
|
697
|
+
|
|
698
|
+
# Already reached maximum, so "carry the 1" to find the next value of k.
|
|
699
|
+
k += 1
|
|
700
|
+
while k <= n-1 and self.a[k] >= self.amax[k]:
|
|
701
|
+
k += 1
|
|
702
|
+
self.a[k] += 1
|
|
703
|
+
self.gnk[n*k] = 0
|
|
704
|
+
k -= 1
|
|
705
|
+
# If we are working through an initialization routine, treat that.
|
|
706
|
+
elif haltk and k == haltk-1:
|
|
707
|
+
self.a[k] += 1
|
|
708
|
+
if self.a[k] > self.amax[k]:
|
|
709
|
+
k += 1
|
|
710
|
+
while k <= n-1 and self.a[k] >= self.amax[k]:
|
|
711
|
+
k += 1
|
|
712
|
+
self.a[k] += 1
|
|
713
|
+
self.gnk[n*k] = 0
|
|
714
|
+
k -= 1
|
|
715
|
+
|
|
716
|
+
# If in the previous step we finished all possible values of
|
|
717
|
+
# the lastmost coefficient, so we must compute bounds on the next coefficient.
|
|
718
|
+
# Recall k == n-1 implies iteration is complete.
|
|
719
|
+
while k < n-1:
|
|
720
|
+
# maxoutflag flags a required abort along the way
|
|
721
|
+
maxoutflag = 0
|
|
722
|
+
|
|
723
|
+
# Recall k == -1 means all coefficients are good to go.
|
|
724
|
+
while k >= 0 and (not haltk or k >= haltk):
|
|
725
|
+
if verbose:
|
|
726
|
+
print(k, ":", end="")
|
|
727
|
+
for i from 0 <= i < np1:
|
|
728
|
+
print(self.a[i], end="")
|
|
729
|
+
print("")
|
|
730
|
+
|
|
731
|
+
if k == n-2:
|
|
732
|
+
# We only know the value of a[n-1], the trace. Need to apply
|
|
733
|
+
# basic bounds from Hunter's theorem and Siegel's theorem, with
|
|
734
|
+
# improvements due to Smyth to get bounds on a[n-2].
|
|
735
|
+
bl = 1./2*(1-1./n)*(1.*self.a[n-1])**2 \
|
|
736
|
+
- 1./2*self.gamma*(1./n*self.B)**(1./(n-1))
|
|
737
|
+
self.a[k] = lrint(ceil(bl))
|
|
738
|
+
br = 1./2*(1.*self.a[n-1])**2 - 0.88595*n
|
|
739
|
+
self.amax[k] = lrint(floor(br))
|
|
740
|
+
|
|
741
|
+
# If maximum is already greater than the minimum, break!
|
|
742
|
+
if self.a[k] > self.amax[k]:
|
|
743
|
+
if verbose:
|
|
744
|
+
print(" ", end="")
|
|
745
|
+
for i from 0 <= i < np1:
|
|
746
|
+
print(self.a[i], end="")
|
|
747
|
+
print(">", end="")
|
|
748
|
+
for i from 0 <= i < np1:
|
|
749
|
+
print(self.amax[i], end="")
|
|
750
|
+
print("")
|
|
751
|
+
maxoutflag = 1
|
|
752
|
+
break
|
|
753
|
+
|
|
754
|
+
# Knowing a[n-1] and a[n-2] means we can apply bounds from
|
|
755
|
+
# the Lagrange multiplier in degree 2, which can be solved
|
|
756
|
+
# immediately.
|
|
757
|
+
self.b_lower = -1./n*(self.a[n-1] + (n-1.)*sqrt((1.*self.a[n-1])**2 - 2.*(1+1./(n-1))*self.a[n-2]))
|
|
758
|
+
self.b_upper = -1./n*(self.a[n-1] - (n-1.)*sqrt((1.*self.a[n-1])**2 - 2.*(1+1./(n-1))*self.a[n-2]))
|
|
759
|
+
|
|
760
|
+
# Initialize the second derivative.
|
|
761
|
+
self.beta[k*np1+0] = self.b_lower
|
|
762
|
+
self.beta[k*np1+1] = -self.a[n-1]*1./n
|
|
763
|
+
self.beta[k*np1+2] = self.b_upper
|
|
764
|
+
self.gnk[k*n+0] = 0
|
|
765
|
+
self.gnk[k*n+1] = (n-1)*self.a[n-1]
|
|
766
|
+
self.gnk[k*n+2] = n*(n-1)/2
|
|
767
|
+
|
|
768
|
+
if verbose:
|
|
769
|
+
print(" ", '%.2f' % self.beta[k * np1 + 1])
|
|
770
|
+
else:
|
|
771
|
+
# Compute the roots of the derivative.
|
|
772
|
+
self.gnk[(k+1)*n+0] += self.a[k+1]
|
|
773
|
+
newton_in_intervals(&self.gnk[(k+1)*n], self.df, n-(k+1),
|
|
774
|
+
&self.beta[(k+1)*np1],
|
|
775
|
+
eps_global, &self.beta[k*np1+1])
|
|
776
|
+
if verbose:
|
|
777
|
+
print(" ", end="")
|
|
778
|
+
for i from 0 <= i < n-k-1:
|
|
779
|
+
print('%.2f' % self.beta[k * np1 + 1 + i], end="")
|
|
780
|
+
print("")
|
|
781
|
+
|
|
782
|
+
for i from 0 <= i < n-k-1:
|
|
783
|
+
if fabs(self.beta[k*np1+i]
|
|
784
|
+
- self.beta[k*np1+(i+1)]) < 10*eps_global:
|
|
785
|
+
# This happens reasonably infrequently, so calling
|
|
786
|
+
# the Python routine should be sufficiently fast...
|
|
787
|
+
f = ZZx([self.gnk[(k+1)*n+i] for i in range(n-(k+1)+1)])
|
|
788
|
+
# Could just take self.gnk(k+2)*n+i, but this may not be initialized...
|
|
789
|
+
df = ZZx([i*self.gnk[(k+1)*n+i] for i in range(1,n-(k+1)+1)])
|
|
790
|
+
if gcd(f,df) != 1:
|
|
791
|
+
if verbose:
|
|
792
|
+
print(" gnk has multiple factor!")
|
|
793
|
+
maxoutflag = 1
|
|
794
|
+
break
|
|
795
|
+
if maxoutflag:
|
|
796
|
+
break
|
|
797
|
+
|
|
798
|
+
# Bounds come from an application of Lagrange multipliers in degrees 2,3.
|
|
799
|
+
if k == n-3:
|
|
800
|
+
self.b_lower = -1./n*(self.a[n-1] + (n-1.)*sqrt((1.*self.a[n-1])**2 - 2.*(1+1./(n-1))*self.a[n-2]))
|
|
801
|
+
self.b_upper = -1./n*(self.a[n-1] - (n-1.)*sqrt((1.*self.a[n-1])**2 - 2.*(1+1./(n-1))*self.a[n-2]))
|
|
802
|
+
elif k == n-4:
|
|
803
|
+
# New bounds from Lagrange multiplier in degree 3.
|
|
804
|
+
bminmax = lagrange_degree_3(n,self.a[n-1],self.a[n-2],self.a[n-3])
|
|
805
|
+
if bminmax:
|
|
806
|
+
self.b_lower = bminmax[0]
|
|
807
|
+
self.b_upper = bminmax[1]
|
|
808
|
+
elif k == n-5 and phc:
|
|
809
|
+
# New bounds using phc/Lagrange multiplier in degree 4.
|
|
810
|
+
bminmax = __lagrange_bounds_phc(n, 4, [self.a[i] for i from 0 <= i <= n])
|
|
811
|
+
if bminmax:
|
|
812
|
+
self.b_lower = bminmax[0]
|
|
813
|
+
self.b_upper = bminmax[1]
|
|
814
|
+
else:
|
|
815
|
+
maxoutflag = 1
|
|
816
|
+
break
|
|
817
|
+
|
|
818
|
+
if verbose:
|
|
819
|
+
print(" [LM bounds:", '%.2f' % self.b_lower,
|
|
820
|
+
'%.2f' % self.b_upper, end="")
|
|
821
|
+
tb = sqrt((1.*self.a[n-1])**2 - 2.*self.a[n-2])
|
|
822
|
+
print("vs. +/-", '%.2f' % tb, ']')
|
|
823
|
+
|
|
824
|
+
self.beta[k*np1+0] = self.b_lower
|
|
825
|
+
self.beta[k*np1+n-k] = self.b_upper
|
|
826
|
+
|
|
827
|
+
# Compute next g_(n-(k+1)), k times the formal integral of g_(n-k).
|
|
828
|
+
gnkm = &self.gnk[k*n]
|
|
829
|
+
gnkm1 = &self.gnk[(k+1)*n]
|
|
830
|
+
gnkm[0] = 0
|
|
831
|
+
for i from 1 <= i < n-k+1:
|
|
832
|
+
gnkm[i] = gnkm[n+i-1]*(k+1)/i
|
|
833
|
+
nk = n-(k+1)
|
|
834
|
+
|
|
835
|
+
# Compute upper and lower bounds which guarantee one retains
|
|
836
|
+
# a polynomial with all real roots.
|
|
837
|
+
betak = &self.beta[k*np1]
|
|
838
|
+
akmin = -eval_seq_as_poly(gnkm, n-k, betak[nk+1]) \
|
|
839
|
+
-fabs(eval_seq_as_poly(gnkm1, nk, betak[nk+1]))*eps_global
|
|
840
|
+
for i from 1 <= i < (nk+1)/2+1:
|
|
841
|
+
# Use the fact that f(z) <= f(x)+|f'(x)|eps if |x-z| < eps
|
|
842
|
+
# for sufficiently small eps, f(z) = 0, and f''(z) < 0.
|
|
843
|
+
tmp_dbl = -eval_seq_as_poly(gnkm, n-k, betak[nk+1-2*i]) \
|
|
844
|
+
-fabs(eval_seq_as_poly(gnkm1, nk, betak[nk+1-2*i]))*eps_global
|
|
845
|
+
if tmp_dbl > akmin:
|
|
846
|
+
akmin = tmp_dbl
|
|
847
|
+
|
|
848
|
+
akmax = -eval_seq_as_poly(gnkm, n-k, betak[nk]) \
|
|
849
|
+
+fabs(eval_seq_as_poly(gnkm1, n-(k+1), betak[nk]))*eps_global
|
|
850
|
+
for i from 1 <= i < nk/2+1:
|
|
851
|
+
# Similar calculus statement here.
|
|
852
|
+
tmp_dbl = -eval_seq_as_poly(gnkm, n-k, betak[nk-2*i]) \
|
|
853
|
+
+fabs(eval_seq_as_poly(gnkm1, nk, betak[nk-2*i]))*eps_global
|
|
854
|
+
if tmp_dbl < akmax:
|
|
855
|
+
akmax = tmp_dbl
|
|
856
|
+
|
|
857
|
+
self.a[k] = lrint(ceil(akmin))
|
|
858
|
+
self.amax[k] = lrint(floor(akmax))
|
|
859
|
+
|
|
860
|
+
if self.a[n-1] == 0 and (n-k) % 2 == 1:
|
|
861
|
+
# Can replace alpha by -alpha, so if all
|
|
862
|
+
# "odd" coefficients are zero, may assume next
|
|
863
|
+
# "odd" coefficient is positive.
|
|
864
|
+
kz = n-3
|
|
865
|
+
while kz > k and self.a[kz] == 0:
|
|
866
|
+
kz -= 2
|
|
867
|
+
if kz == k:
|
|
868
|
+
if self.a[k] < 0:
|
|
869
|
+
self.a[k] = 0
|
|
870
|
+
if self.a[k] == 0 and self.a[k+1] == 0:
|
|
871
|
+
self.a[k] += 1
|
|
872
|
+
# Can't have constant coefficient zero!
|
|
873
|
+
if k == 0 and self.a[k] == 0:
|
|
874
|
+
self.a[k] = 1
|
|
875
|
+
|
|
876
|
+
if self.a[k] > self.amax[k]:
|
|
877
|
+
if verbose:
|
|
878
|
+
print(" ", end="")
|
|
879
|
+
for i from 0 <= i < np1:
|
|
880
|
+
print(self.a[i], end="")
|
|
881
|
+
print(">", end="")
|
|
882
|
+
for i from 0 <= i < np1:
|
|
883
|
+
print(self.amax[i], end="")
|
|
884
|
+
print("")
|
|
885
|
+
maxoutflag = 1
|
|
886
|
+
break
|
|
887
|
+
|
|
888
|
+
self.k -= 1
|
|
889
|
+
k -= 1
|
|
890
|
+
|
|
891
|
+
if not maxoutflag and easy_is_irreducible(self.a, n):
|
|
892
|
+
self.k = k
|
|
893
|
+
for i from 0 <= i < n:
|
|
894
|
+
f_out[i] = self.a[i]
|
|
895
|
+
return
|
|
896
|
+
else:
|
|
897
|
+
k += 1
|
|
898
|
+
while k <= n-1 and self.a[k] >= self.amax[k]:
|
|
899
|
+
k += 1
|
|
900
|
+
self.a[k] += 1
|
|
901
|
+
self.gnk[n*k] = 0
|
|
902
|
+
k -= 1
|
|
903
|
+
|
|
904
|
+
# k == n-1, so iteration is complete; return the zero polynomial (of degree n+1).
|
|
905
|
+
self.k = k
|
|
906
|
+
f_out[n] = 0
|
|
907
|
+
return
|
|
908
|
+
|
|
909
|
+
def printa(self):
|
|
910
|
+
"""
|
|
911
|
+
Print relevant data for ``self``.
|
|
912
|
+
|
|
913
|
+
EXAMPLES::
|
|
914
|
+
|
|
915
|
+
sage: from sage.rings.number_field.totallyreal_data import tr_data
|
|
916
|
+
sage: T = tr_data(3,2^10)
|
|
917
|
+
sage: T.printa()
|
|
918
|
+
k = 1
|
|
919
|
+
a = [0, 0, -1, 1]
|
|
920
|
+
amax = [0, 0, 0, 1]
|
|
921
|
+
beta = [...]
|
|
922
|
+
gnk = [...]
|
|
923
|
+
"""
|
|
924
|
+
print("k =", self.k)
|
|
925
|
+
print("a =", [self.a[i] for i in range(self.n + 1)])
|
|
926
|
+
print("amax =", [self.amax[i] for i in range(self.n + 1)])
|
|
927
|
+
print("beta = ", [self.beta[i] for i in range(self.n * (self.n + 1))])
|
|
928
|
+
print("gnk = ", [self.gnk[i] for i in range(self.n * (self.n + 1))])
|