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,373 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# sage.doctest: needs sage.libs.pari sage.modules
|
|
3
|
+
"""
|
|
4
|
+
Local Masses and Siegel Densities
|
|
5
|
+
"""
|
|
6
|
+
########################################################################
|
|
7
|
+
# Computes the local masses (rep'n densities of a form by itself) for a quadratic form over ZZ
|
|
8
|
+
# using the papers of Pall [PSPUM VIII (1965), pp95--105] for p>2, and Watson [Mathematika
|
|
9
|
+
# 23, no. 1, (1976), pp 94--106] for p=2. These formulas will also work for any local field
|
|
10
|
+
# which is unramified at p=2.
|
|
11
|
+
##
|
|
12
|
+
# Copyright by Jonathan Hanke 2007 <jonhanke@gmail.com>
|
|
13
|
+
########################################################################
|
|
14
|
+
|
|
15
|
+
from copy import deepcopy
|
|
16
|
+
|
|
17
|
+
from sage.arith.misc import kronecker, legendre_symbol, prime_divisors
|
|
18
|
+
from sage.matrix.matrix_space import MatrixSpace
|
|
19
|
+
from sage.misc.functional import squarefree_part
|
|
20
|
+
from sage.misc.misc_c import prod
|
|
21
|
+
from sage.misc.mrange import mrange
|
|
22
|
+
from sage.quadratic_forms.special_values import gamma__exact, zeta__exact, quadratic_L_function__exact
|
|
23
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
24
|
+
from sage.rings.integer_ring import ZZ
|
|
25
|
+
from sage.rings.rational_field import QQ
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def mass__by_Siegel_densities(self, odd_algorithm='Pall', even_algorithm='Watson'):
|
|
29
|
+
"""
|
|
30
|
+
Return the mass of transformations (det 1 and -1).
|
|
31
|
+
|
|
32
|
+
.. WARNING::
|
|
33
|
+
|
|
34
|
+
This is broken right now...
|
|
35
|
+
|
|
36
|
+
INPUT:
|
|
37
|
+
|
|
38
|
+
- ``odd_algorithm`` -- algorithm to be used when `p>2`; ``'Pall'`` (only
|
|
39
|
+
one choice for now)
|
|
40
|
+
- ``even_algorithm`` -- algorithm to be used when `p=2`; either
|
|
41
|
+
``'Kitaoka'`` or ``'Watson'`` (the default)
|
|
42
|
+
|
|
43
|
+
REFERENCES:
|
|
44
|
+
|
|
45
|
+
- Nipp's Book "Tables of Quaternary Quadratic Forms".
|
|
46
|
+
- Papers of Pall (only for `p>2`) and Watson (for `p=2` -- tricky!).
|
|
47
|
+
- Siegel, Milnor-Hussemoller, Conway-Sloane Paper IV, Kitoaka (all of which
|
|
48
|
+
have problems...)
|
|
49
|
+
|
|
50
|
+
EXAMPLES::
|
|
51
|
+
|
|
52
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
|
|
53
|
+
sage: m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic
|
|
54
|
+
1/384
|
|
55
|
+
sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # needs sage.symbolic
|
|
56
|
+
0
|
|
57
|
+
|
|
58
|
+
::
|
|
59
|
+
|
|
60
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
61
|
+
sage: m = Q.mass__by_Siegel_densities(); m # needs sage.symbolic
|
|
62
|
+
1/48
|
|
63
|
+
sage: m - (2^Q.dim() * factorial(Q.dim()))^(-1) # needs sage.symbolic
|
|
64
|
+
0
|
|
65
|
+
"""
|
|
66
|
+
from sage.symbolic.constants import pi
|
|
67
|
+
|
|
68
|
+
# Setup
|
|
69
|
+
n = self.dim()
|
|
70
|
+
s = (n - 1) // 2
|
|
71
|
+
if n % 2 != 0:
|
|
72
|
+
char_d = squarefree_part(2 * self.det()) # Accounts for the det as a QF
|
|
73
|
+
else:
|
|
74
|
+
char_d = squarefree_part(self.det())
|
|
75
|
+
|
|
76
|
+
# Form the generic zeta product
|
|
77
|
+
generic_prod = ZZ(2) * (pi)**(-ZZ(n) * (n + 1) / 4)
|
|
78
|
+
##########################################
|
|
79
|
+
generic_prod *= self.det()**(ZZ(n + 1) / 2) # ***** This uses the Hessian Determinant ********
|
|
80
|
+
##########################################
|
|
81
|
+
generic_prod *= prod([gamma__exact(ZZ(j) / 2) for j in range(1, n + 1)])
|
|
82
|
+
generic_prod *= prod([zeta__exact(ZZ(j)) for j in range(2, 2 * s + 1, 2)])
|
|
83
|
+
if n % 2 == 0:
|
|
84
|
+
generic_prod *= quadratic_L_function__exact(n // 2, ZZ(-1)**(n // 2) * char_d)
|
|
85
|
+
# Determine the adjustment factors
|
|
86
|
+
adj_prod = ZZ.one()
|
|
87
|
+
for p in prime_divisors(2 * self.det()):
|
|
88
|
+
# Cancel out the generic factors
|
|
89
|
+
p_adjustment = prod([1 - ZZ(p)**(-j) for j in range(2, 2 * s + 1, 2)])
|
|
90
|
+
if n % 2 == 0:
|
|
91
|
+
p_adjustment *= (1 - kronecker((-1)**(n // 2) * char_d, p) * ZZ(p)**(-n // 2))
|
|
92
|
+
# Insert the new mass factors
|
|
93
|
+
if p == 2:
|
|
94
|
+
if even_algorithm == "Kitaoka":
|
|
95
|
+
p_adjustment = p_adjustment / self.Kitaoka_mass_at_2()
|
|
96
|
+
elif even_algorithm == "Watson":
|
|
97
|
+
p_adjustment = p_adjustment / self.Watson_mass_at_2()
|
|
98
|
+
else:
|
|
99
|
+
raise TypeError("There is a problem -- your even_algorithm argument is invalid. Try again. =(")
|
|
100
|
+
else:
|
|
101
|
+
if odd_algorithm == "Pall":
|
|
102
|
+
p_adjustment = p_adjustment / self.Pall_mass_density_at_odd_prime(p)
|
|
103
|
+
else:
|
|
104
|
+
raise TypeError("There is a problem -- your optional arguments are invalid. Try again. =(")
|
|
105
|
+
|
|
106
|
+
# Put them together (cumulatively)
|
|
107
|
+
adj_prod *= p_adjustment
|
|
108
|
+
|
|
109
|
+
# Extra adjustment for the case of a 2-dimensional form.
|
|
110
|
+
# if (n == 2):
|
|
111
|
+
# generic_prod *= 2
|
|
112
|
+
|
|
113
|
+
# Return the mass
|
|
114
|
+
mass = generic_prod * adj_prod
|
|
115
|
+
return mass
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def Pall_mass_density_at_odd_prime(self, p):
|
|
119
|
+
r"""
|
|
120
|
+
Return the local representation density of a form (for
|
|
121
|
+
representing itself) defined over `\ZZ`, at some prime `p>2`.
|
|
122
|
+
|
|
123
|
+
REFERENCES:
|
|
124
|
+
|
|
125
|
+
Pall's article "The Weight of a Genus of Positive n-ary Quadratic Forms"
|
|
126
|
+
appearing in Proc. Symp. Pure Math. VIII (1965), pp95--105.
|
|
127
|
+
|
|
128
|
+
INPUT:
|
|
129
|
+
|
|
130
|
+
- ``p`` -- a prime number > 2
|
|
131
|
+
|
|
132
|
+
OUTPUT: a rational number
|
|
133
|
+
|
|
134
|
+
EXAMPLES::
|
|
135
|
+
|
|
136
|
+
sage: Q = QuadraticForm(ZZ, 3, [1,0,0,1,0,1])
|
|
137
|
+
sage: Q.Pall_mass_density_at_odd_prime(3)
|
|
138
|
+
[(0, Quadratic form in 3 variables over Integer Ring with coefficients:
|
|
139
|
+
[ 1 0 0 ]
|
|
140
|
+
[ * 1 0 ]
|
|
141
|
+
[ * * 1 ])] [(0, 3, 8)] [8/9] 8/9
|
|
142
|
+
8/9
|
|
143
|
+
"""
|
|
144
|
+
# Check that p is a positive prime -- unnecessary since it's done implicitly in the next step. =)
|
|
145
|
+
if p <= 2:
|
|
146
|
+
raise TypeError("we need p to be a prime > 2")
|
|
147
|
+
|
|
148
|
+
# Step 1: Obtain a p-adic (diagonal) local normal form, and
|
|
149
|
+
# compute the invariants for each Jordan block.
|
|
150
|
+
jordan_list = self.jordan_blocks_by_scale_and_unimodular(p)
|
|
151
|
+
modified_jordan_list = [(a, Q.dim(), Q.det()) for a, Q in jordan_list] # List of pairs (scale, det)
|
|
152
|
+
|
|
153
|
+
# Step 2: Compute the list of local masses for each Jordan block
|
|
154
|
+
jordan_mass_list = []
|
|
155
|
+
for (s, n, d) in modified_jordan_list:
|
|
156
|
+
generic_factor = prod([1 - p**(-2 * j) for j in range(1, (n - 1) // 2 + 1)])
|
|
157
|
+
if n % 2 == 0:
|
|
158
|
+
m = n // 2
|
|
159
|
+
generic_factor *= (1 + legendre_symbol(((-1)**m) * d, p) * p**(-m))
|
|
160
|
+
jordan_mass_list = jordan_mass_list + [generic_factor]
|
|
161
|
+
|
|
162
|
+
# Step 3: Compute the local mass $\al_p$ at p.
|
|
163
|
+
MJL = modified_jordan_list
|
|
164
|
+
s = len(modified_jordan_list)
|
|
165
|
+
M = [sum([MJL[j][1] for j in range(i, s)]) for i in range(s - 1)] # Note: It's s-1 since we don't need the last M.
|
|
166
|
+
nu = sum([M[i] * MJL[i][0] * MJL[i][1] for i in range(s - 1)]) - ZZ(sum([J[0] * J[1] * (J[1] - 1) for J in MJL])) / ZZ(2)
|
|
167
|
+
p_mass = prod(jordan_mass_list)
|
|
168
|
+
p_mass *= 2**(s - 1) * p**nu
|
|
169
|
+
|
|
170
|
+
print(jordan_list, MJL, jordan_mass_list, p_mass)
|
|
171
|
+
|
|
172
|
+
# Return the result
|
|
173
|
+
return p_mass
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def Watson_mass_at_2(self):
|
|
177
|
+
"""
|
|
178
|
+
Return the local mass of the quadratic form when `p=2`, according
|
|
179
|
+
to Watson's Theorem 1 of "The 2-adic density of a quadratic form"
|
|
180
|
+
in Mathematika 23 (1976), pp 94--106.
|
|
181
|
+
|
|
182
|
+
OUTPUT: a rational number
|
|
183
|
+
|
|
184
|
+
EXAMPLES::
|
|
185
|
+
|
|
186
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
187
|
+
sage: Q.Watson_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY! # needs sage.symbolic
|
|
188
|
+
384
|
|
189
|
+
"""
|
|
190
|
+
from sage.functions.all import sgn
|
|
191
|
+
|
|
192
|
+
# Make a 0-dim'l quadratic form (for initialization purposes)
|
|
193
|
+
Null_Form = deepcopy(self)
|
|
194
|
+
Null_Form.__init__(ZZ, 0)
|
|
195
|
+
|
|
196
|
+
# Step 0: Compute Jordan blocks and bounds of the scales to keep track of
|
|
197
|
+
Jordan_Blocks = self.jordan_blocks_by_scale_and_unimodular(2)
|
|
198
|
+
scale_list = [B[0] for B in Jordan_Blocks]
|
|
199
|
+
s_min = min(scale_list)
|
|
200
|
+
s_max = max(scale_list)
|
|
201
|
+
|
|
202
|
+
# Step 1: Compute dictionaries of the diagonal block and 2x2 block for each scale
|
|
203
|
+
diag_dict = {i: Null_Form for i in range(s_min - 2, s_max + 4)} # Initialize with the zero form
|
|
204
|
+
dim2_dict = {i: Null_Form for i in range(s_min, s_max + 4)} # Initialize with the zero form
|
|
205
|
+
for s, L in Jordan_Blocks:
|
|
206
|
+
i = 0
|
|
207
|
+
while i < L.dim() - 1 and L[i, i + 1] == 0: # Find where the 2x2 blocks start
|
|
208
|
+
i += 1
|
|
209
|
+
if i < L.dim() - 1:
|
|
210
|
+
diag_dict[s] = L.extract_variables(range(i)) # Diagonal Form
|
|
211
|
+
dim2_dict[s + 1] = L.extract_variables(range(i, L.dim())) # Non-diagonal Form
|
|
212
|
+
else:
|
|
213
|
+
diag_dict[s] = L
|
|
214
|
+
|
|
215
|
+
# Step 2: Compute three dictionaries of invariants (for n_j, m_j, nu_j)
|
|
216
|
+
n_dict = {j: 0 for j in range(s_min + 1, s_max + 2)}
|
|
217
|
+
m_dict = {j: 0 for j in range(s_min, s_max + 4)}
|
|
218
|
+
for s, L in Jordan_Blocks:
|
|
219
|
+
n_dict[s + 1] = L.dim()
|
|
220
|
+
if diag_dict[s].dim() == 0:
|
|
221
|
+
m_dict[s + 1] = ZZ.one() / ZZ(2) * L.dim()
|
|
222
|
+
else:
|
|
223
|
+
m_dict[s + 1] = ZZ(L.dim() - 1) // ZZ(2)
|
|
224
|
+
|
|
225
|
+
nu_dict = {j: n_dict[j + 1] - 2 * m_dict[j + 1]
|
|
226
|
+
for j in range(s_min, s_max + 1)}
|
|
227
|
+
nu_dict[s_max + 1] = 0
|
|
228
|
+
|
|
229
|
+
# Step 3: Compute the e_j dictionary
|
|
230
|
+
eps_dict = {}
|
|
231
|
+
for j in range(s_min, s_max + 3):
|
|
232
|
+
two_form = (diag_dict[j - 2] + diag_dict[j] + dim2_dict[j]).scale_by_factor(2)
|
|
233
|
+
j_form = (two_form + diag_dict[j - 1]).change_ring(IntegerModRing(4))
|
|
234
|
+
|
|
235
|
+
if j_form.dim() == 0:
|
|
236
|
+
eps_dict[j] = 1
|
|
237
|
+
else:
|
|
238
|
+
iter_vec = [4] * j_form.dim()
|
|
239
|
+
alpha = sum(1 for x in mrange(iter_vec) if j_form(x) == 0)
|
|
240
|
+
beta = sum(1 for x in mrange(iter_vec) if j_form(x) == 2)
|
|
241
|
+
if alpha > beta:
|
|
242
|
+
eps_dict[j] = 1
|
|
243
|
+
elif alpha == beta:
|
|
244
|
+
eps_dict[j] = 0
|
|
245
|
+
else:
|
|
246
|
+
eps_dict[j] = -1
|
|
247
|
+
|
|
248
|
+
# Step 4: Compute the quantities nu, q, P, E for the local mass at 2
|
|
249
|
+
nu = sum([j * n_dict[j] * (ZZ(n_dict[j] + 1) / ZZ(2) +
|
|
250
|
+
sum([n_dict[r] for r in range(j + 1, s_max + 2)])) for j in range(s_min + 1, s_max + 2)])
|
|
251
|
+
q = sum([sgn(nu_dict[j - 1] * (n_dict[j] + sgn(nu_dict[j]))) for j in range(s_min + 1, s_max + 2)])
|
|
252
|
+
P = prod([prod([1 - QQ(4)**(-k) for k in range(1, m_dict[j] + 1)]) for j in range(s_min + 1, s_max + 2)])
|
|
253
|
+
E = prod([ZZ(1) / ZZ(2) * (1 + eps_dict[j] * QQ(2)**(-m_dict[j])) for j in range(s_min, s_max + 3)])
|
|
254
|
+
|
|
255
|
+
# Step 5: Compute the local mass for the prime 2.
|
|
256
|
+
mass_at_2 = QQ(2)**(nu - q) * P / E
|
|
257
|
+
return mass_at_2
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def Kitaoka_mass_at_2(self):
|
|
261
|
+
"""
|
|
262
|
+
Return the local mass of the quadratic form when `p=2`, according
|
|
263
|
+
to Theorem 5.6.3 on pp108--9 of Kitaoka's Book "The Arithmetic of
|
|
264
|
+
Quadratic Forms".
|
|
265
|
+
|
|
266
|
+
OUTPUT: a rational number > 0
|
|
267
|
+
|
|
268
|
+
EXAMPLES::
|
|
269
|
+
|
|
270
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
271
|
+
sage: Q.Kitaoka_mass_at_2() # WARNING: WE NEED TO CHECK THIS CAREFULLY!
|
|
272
|
+
1/2
|
|
273
|
+
"""
|
|
274
|
+
# Make a 0-dim'l quadratic form (for initialization purposes)
|
|
275
|
+
Null_Form = deepcopy(self)
|
|
276
|
+
Null_Form.__init__(ZZ, 0)
|
|
277
|
+
|
|
278
|
+
# Step 0: Compute Jordan blocks and bounds of the scales to keep track of
|
|
279
|
+
Jordan_Blocks = self.jordan_blocks_by_scale_and_unimodular(2)
|
|
280
|
+
scale_list = [B[0] for B in Jordan_Blocks]
|
|
281
|
+
s_min = min(scale_list)
|
|
282
|
+
s_max = max(scale_list)
|
|
283
|
+
|
|
284
|
+
# Step 1: Compute dictionaries of the diagonal block and 2x2 block for each scale
|
|
285
|
+
diag_dict = {i: Null_Form for i in range(s_min - 2, s_max + 4)} # Initialize with the zero form
|
|
286
|
+
dim2_dict = {i: Null_Form for i in range(s_min, s_max + 4)} # Initialize with the zero form
|
|
287
|
+
for s, L in Jordan_Blocks:
|
|
288
|
+
i = 0
|
|
289
|
+
while i < L.dim() - 1 and L[i, i + 1] == 0: # Find where the 2x2 blocks start
|
|
290
|
+
i += 1
|
|
291
|
+
if i < L.dim() - 1:
|
|
292
|
+
diag_dict[s] = L.extract_variables(range(i)) # Diagonal Form
|
|
293
|
+
dim2_dict[s + 1] = L.extract_variables(range(i, L.dim())) # Non-diagonal Form
|
|
294
|
+
else:
|
|
295
|
+
diag_dict[s] = L
|
|
296
|
+
|
|
297
|
+
# ################ START EDITING HERE ##################
|
|
298
|
+
|
|
299
|
+
# Compute q := sum of the q_j
|
|
300
|
+
q = 0
|
|
301
|
+
for j in range(s_min, s_max + 1):
|
|
302
|
+
if diag_dict[j].dim() > 0: # Check that N_j is odd (i.e. rep'ns an odd #)
|
|
303
|
+
if diag_dict[j + 1].dim() == 0:
|
|
304
|
+
q += Jordan_Blocks[j][1].dim() # When N_{j+1} is "even", add n_j
|
|
305
|
+
else:
|
|
306
|
+
q += Jordan_Blocks[j][1].dim() + 1 # When N_{j+1} is "odd", add n_j + 1
|
|
307
|
+
|
|
308
|
+
# Compute P = product of the P_j
|
|
309
|
+
P = QQ.one()
|
|
310
|
+
for j in range(s_min, s_max + 1):
|
|
311
|
+
tmp_m = dim2_dict[j].dim() // 2
|
|
312
|
+
P *= prod(QQ.one() - QQ(4**(-k)) for k in range(1, tmp_m + 1))
|
|
313
|
+
|
|
314
|
+
# Compute the product E := prod_j (1 / E_j)
|
|
315
|
+
E = QQ.one()
|
|
316
|
+
for j in range(s_min - 1, s_max + 2):
|
|
317
|
+
if (diag_dict[j - 1].dim() == 0) and (diag_dict[j + 1].dim() == 0) and \
|
|
318
|
+
((diag_dict[j].dim() != 2) or (((diag_dict[j][0, 0] - diag_dict[j][1, 1]) % 4) != 0)):
|
|
319
|
+
|
|
320
|
+
# Deal with the complicated case:
|
|
321
|
+
tmp_m = dim2_dict[j].dim() // 2
|
|
322
|
+
if dim2_dict[j].is_hyperbolic(2):
|
|
323
|
+
E *= QQ(2) / (1 + 2**(-tmp_m))
|
|
324
|
+
else:
|
|
325
|
+
E *= QQ(2) / (1 - 2**(-tmp_m))
|
|
326
|
+
|
|
327
|
+
else:
|
|
328
|
+
E *= 2
|
|
329
|
+
|
|
330
|
+
# Compute the exponent w
|
|
331
|
+
w = QQ.zero()
|
|
332
|
+
for j in range(s_min, s_max + 1):
|
|
333
|
+
n_j = Jordan_Blocks[j][1].dim()
|
|
334
|
+
for k in range(j + 1, s_max + 1):
|
|
335
|
+
n_k = Jordan_Blocks[k][1].dim()
|
|
336
|
+
w += j * n_j * (n_k + QQ(n_j + 1) / 2)
|
|
337
|
+
|
|
338
|
+
# Step 5: Compute the local mass for the prime 2.
|
|
339
|
+
mass_at_2 = (QQ(2)**(w - q)) * P * E
|
|
340
|
+
return mass_at_2
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def mass_at_two_by_counting_mod_power(self, k):
|
|
344
|
+
r"""
|
|
345
|
+
Compute the local mass at `p=2` assuming that it's stable (mod `2^k`).
|
|
346
|
+
|
|
347
|
+
.. NOTE::
|
|
348
|
+
|
|
349
|
+
This is **way** too slow to be useful, even when `k=1`.
|
|
350
|
+
|
|
351
|
+
.. TODO::
|
|
352
|
+
|
|
353
|
+
Remove this routine, or try to compile it!
|
|
354
|
+
|
|
355
|
+
INPUT:
|
|
356
|
+
|
|
357
|
+
- ``k`` -- integer `\geq 1`
|
|
358
|
+
|
|
359
|
+
OUTPUT: a rational number
|
|
360
|
+
|
|
361
|
+
EXAMPLES::
|
|
362
|
+
|
|
363
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
364
|
+
sage: Q.mass_at_two_by_counting_mod_power(1)
|
|
365
|
+
4
|
|
366
|
+
"""
|
|
367
|
+
R = IntegerModRing(2**k)
|
|
368
|
+
Q1 = self.change_ring(R)
|
|
369
|
+
n = self.dim()
|
|
370
|
+
MS = MatrixSpace(R, n)
|
|
371
|
+
|
|
372
|
+
ct = sum(1 for x in mrange([2**k] * (n**2)) if Q1(MS(x)) == Q1) # Count the solutions mod 2^k
|
|
373
|
+
return ZZ.one() / 2 * (ZZ(ct) / ZZ(2)**(k * n * (n - 1) / 2))
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# sage.doctest: needs sage.libs.flint sage.libs.pari sage.modules
|
|
3
|
+
"""
|
|
4
|
+
Siegel Products
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# ****************************************************************************
|
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
|
10
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
11
|
+
# (at your option) any later version.
|
|
12
|
+
# https://www.gnu.org/licenses/
|
|
13
|
+
# ****************************************************************************
|
|
14
|
+
|
|
15
|
+
from sage.arith.misc import (bernoulli,
|
|
16
|
+
fundamental_discriminant,
|
|
17
|
+
kronecker as kronecker_symbol,
|
|
18
|
+
prime_divisors)
|
|
19
|
+
from sage.misc.functional import sqrt
|
|
20
|
+
from sage.misc.verbose import verbose
|
|
21
|
+
from sage.quadratic_forms.special_values import QuadraticBernoulliNumber
|
|
22
|
+
from sage.rings.integer_ring import ZZ
|
|
23
|
+
from sage.rings.rational_field import QQ
|
|
24
|
+
|
|
25
|
+
# /*! \brief Computes the product of all local densities for comparison with independently computed Eisenstein coefficients.
|
|
26
|
+
# *
|
|
27
|
+
# * \todo We fixed the generic factors to compensate for using the matrix of 2Q, but we need to document this better! =)
|
|
28
|
+
# */
|
|
29
|
+
|
|
30
|
+
# /////////////////////////////////////////////////////////////////
|
|
31
|
+
# ///
|
|
32
|
+
# /////////////////////////////////////////////////////////////////
|
|
33
|
+
|
|
34
|
+
# mpq_class Matrix_mpz::siegel_product(mpz_class u) const {
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def siegel_product(self, u):
|
|
38
|
+
"""
|
|
39
|
+
Compute the infinite product of local densities of the quadratic
|
|
40
|
+
form for the number `u`.
|
|
41
|
+
|
|
42
|
+
EXAMPLES::
|
|
43
|
+
|
|
44
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1,1])
|
|
45
|
+
sage: Q.theta_series(11)
|
|
46
|
+
1 + 8*q + 24*q^2 + 32*q^3 + 24*q^4 + 48*q^5 + 96*q^6 + 64*q^7 + 24*q^8 + 104*q^9 + 144*q^10 + O(q^11)
|
|
47
|
+
|
|
48
|
+
sage: Q.siegel_product(1)
|
|
49
|
+
8
|
|
50
|
+
sage: Q.siegel_product(2) # This one is wrong -- expect 24, and the higher powers of 2 don't work... =(
|
|
51
|
+
24
|
|
52
|
+
sage: Q.siegel_product(3)
|
|
53
|
+
32
|
|
54
|
+
sage: Q.siegel_product(5)
|
|
55
|
+
48
|
|
56
|
+
sage: Q.siegel_product(6)
|
|
57
|
+
96
|
|
58
|
+
sage: Q.siegel_product(7)
|
|
59
|
+
64
|
|
60
|
+
sage: Q.siegel_product(9)
|
|
61
|
+
104
|
|
62
|
+
|
|
63
|
+
sage: Q.local_density(2,1)
|
|
64
|
+
1
|
|
65
|
+
sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3
|
|
66
|
+
1
|
|
67
|
+
sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 1]) / M^3 # long time (2s on sage.math, 2014)
|
|
68
|
+
1
|
|
69
|
+
|
|
70
|
+
sage: Q.local_density(2,2)
|
|
71
|
+
3/2
|
|
72
|
+
sage: M = 4; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3
|
|
73
|
+
3/2
|
|
74
|
+
sage: M = 16; len([v for v in mrange([M,M,M,M]) if Q(v) % M == 2]) / M^3 # long time (2s on sage.math, 2014)
|
|
75
|
+
3/2
|
|
76
|
+
|
|
77
|
+
TESTS::
|
|
78
|
+
|
|
79
|
+
sage: [1] + [Q.siegel_product(ZZ(a)) for a in range(1,11)] == Q.theta_series(11).list() # long time (2s on sage.math, 2014)
|
|
80
|
+
True
|
|
81
|
+
"""
|
|
82
|
+
# Protect u (since it fails often if it's an just an int!)
|
|
83
|
+
u = ZZ(u)
|
|
84
|
+
|
|
85
|
+
n = self.dim()
|
|
86
|
+
d = self.det() # ??? Warning: This is a factor of 2^n larger than it should be!
|
|
87
|
+
|
|
88
|
+
# DIAGNOSTIC
|
|
89
|
+
verbose("n = " + str(n))
|
|
90
|
+
verbose("d = " + str(d))
|
|
91
|
+
verbose("In siegel_product: d = " + str(d) + "\n")
|
|
92
|
+
|
|
93
|
+
# Product of "bad" places to omit
|
|
94
|
+
S = 2 * d * u
|
|
95
|
+
|
|
96
|
+
# DIAGNOSTIC
|
|
97
|
+
verbose("siegel_product Break 1. \n")
|
|
98
|
+
verbose(" u = " + str(u) + "\n")
|
|
99
|
+
|
|
100
|
+
# Make the odd generic factors
|
|
101
|
+
if n % 2:
|
|
102
|
+
m = (n - 1) // 2
|
|
103
|
+
d1 = fundamental_discriminant(((-1)**m) * 2*d * u) # Replaced d by 2d here to compensate for the determinant
|
|
104
|
+
f = abs(d1)
|
|
105
|
+
# gaining an odd power of 2 by using the matrix of 2Q instead
|
|
106
|
+
# of the matrix of Q.
|
|
107
|
+
# --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u);
|
|
108
|
+
|
|
109
|
+
# Make the ratio of factorials factor: [(2m)! / m!] * prod_{i=1}^m (2*i-1)
|
|
110
|
+
factor1 = 1
|
|
111
|
+
for i in range(1, m+1):
|
|
112
|
+
factor1 *= 2*i - 1
|
|
113
|
+
for i in range(m+1, 2*m + 1):
|
|
114
|
+
factor1 *= i
|
|
115
|
+
|
|
116
|
+
genericfactor = factor1 * ((u / f) ** m) \
|
|
117
|
+
* QQ(sqrt((2 ** n) * f) / (u * d)) \
|
|
118
|
+
* abs(QuadraticBernoulliNumber(m, d1) / bernoulli(2*m))
|
|
119
|
+
|
|
120
|
+
# DIAGNOSTIC
|
|
121
|
+
verbose("siegel_product Break 2. \n")
|
|
122
|
+
|
|
123
|
+
# Make the even generic factor
|
|
124
|
+
if ((n % 2) == 0):
|
|
125
|
+
m = n // 2
|
|
126
|
+
d1 = fundamental_discriminant(((-1)**m) * d)
|
|
127
|
+
f = abs(d1)
|
|
128
|
+
|
|
129
|
+
# DIAGNOSTIC
|
|
130
|
+
# cout << " mpz_class(-1)^m = " << (mpz_class(-1)^m) << " and d = " << d << endl;
|
|
131
|
+
# cout << " f = " << f << " and d1 = " << d1 << endl;
|
|
132
|
+
|
|
133
|
+
genericfactor = m / QQ(sqrt(f*d)) \
|
|
134
|
+
* ((u/2) ** (m-1)) * (f ** m) \
|
|
135
|
+
/ abs(QuadraticBernoulliNumber(m, d1)) \
|
|
136
|
+
* (2 ** m) # This last factor compensates for using the matrix of 2*Q
|
|
137
|
+
|
|
138
|
+
# return genericfactor
|
|
139
|
+
|
|
140
|
+
# Omit the generic factors in S and compute them separately
|
|
141
|
+
omit = 1
|
|
142
|
+
include = 1
|
|
143
|
+
|
|
144
|
+
S_divisors = prime_divisors(S)
|
|
145
|
+
|
|
146
|
+
# DIAGNOSTIC
|
|
147
|
+
# cout << "\n S is " << S << endl;
|
|
148
|
+
# cout << " The Prime divisors of S are :";
|
|
149
|
+
# PrintV(S_divisors);
|
|
150
|
+
|
|
151
|
+
for p in S_divisors:
|
|
152
|
+
Q_normal = self.local_normal_form(p)
|
|
153
|
+
|
|
154
|
+
# DIAGNOSTIC
|
|
155
|
+
verbose(" p = " + str(p) + " and its Kronecker symbol (d1/p) = (" + str(d1) + "/" + str(p) + ") is " + str(kronecker_symbol(d1, p)) + "\n")
|
|
156
|
+
|
|
157
|
+
omit *= 1 / (1 - (kronecker_symbol(d1, p) / (p**m)))
|
|
158
|
+
|
|
159
|
+
# DIAGNOSTIC
|
|
160
|
+
verbose(" omit = " + str(omit) + "\n")
|
|
161
|
+
verbose(" Q_normal is \n" + str(Q_normal) + "\n")
|
|
162
|
+
verbose(" Q_normal = \n" + str(Q_normal))
|
|
163
|
+
verbose(" p = " + str(p) + "\n")
|
|
164
|
+
verbose(" u = " + str(u) + "\n")
|
|
165
|
+
verbose(" include = " + str(include) + "\n")
|
|
166
|
+
|
|
167
|
+
include *= Q_normal.local_density(p, u)
|
|
168
|
+
|
|
169
|
+
# DIAGNOSTIC
|
|
170
|
+
# cout << " Including the p = " << p << " factor: " << local_density(Q_normal, p, u) << endl;
|
|
171
|
+
|
|
172
|
+
# DIAGNOSTIC
|
|
173
|
+
verbose(" --- Exiting loop \n")
|
|
174
|
+
|
|
175
|
+
# // **************** Important *******************
|
|
176
|
+
# // Additional fix (only included for n=4) to deal
|
|
177
|
+
# // with the power of 2 introduced at the real place
|
|
178
|
+
# // by working with Q instead of 2*Q. This needs to
|
|
179
|
+
# // be done for all other n as well...
|
|
180
|
+
# /*
|
|
181
|
+
# if (n==4)
|
|
182
|
+
# genericfactor = 4 * genericfactor;
|
|
183
|
+
# */
|
|
184
|
+
|
|
185
|
+
# DIAGNOSTIC
|
|
186
|
+
# cout << endl;
|
|
187
|
+
# cout << " generic factor = " << genericfactor << endl;
|
|
188
|
+
# cout << " omit = " << omit << endl;
|
|
189
|
+
# cout << " include = " << include << endl;
|
|
190
|
+
# cout << endl;
|
|
191
|
+
|
|
192
|
+
# DIAGNOSTIC
|
|
193
|
+
# // cout << "siegel_product Break 3. " << endl;
|
|
194
|
+
|
|
195
|
+
# Return the final factor (and divide by 2 if n=2)
|
|
196
|
+
if n == 2:
|
|
197
|
+
return genericfactor * omit * include / 2
|
|
198
|
+
return genericfactor * omit * include
|