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,663 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# sage.doctest: needs sage.libs.pari sage.modules
|
|
3
|
+
"""
|
|
4
|
+
Conway-Sloane masses
|
|
5
|
+
"""
|
|
6
|
+
from sage.arith.misc import (fundamental_discriminant,
|
|
7
|
+
is_prime,
|
|
8
|
+
kronecker as kronecker_symbol,
|
|
9
|
+
legendre_symbol,
|
|
10
|
+
prime_divisors)
|
|
11
|
+
from sage.misc.misc_c import prod
|
|
12
|
+
from sage.rings.integer_ring import ZZ
|
|
13
|
+
from sage.rings.rational_field import QQ
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def parity(self, allow_rescaling_flag=True):
|
|
17
|
+
r"""
|
|
18
|
+
Return the parity ("even" or "odd") of an integer-valued quadratic
|
|
19
|
+
form over `\ZZ`, defined up to similitude/rescaling of the form so that
|
|
20
|
+
its Jordan component of smallest scale is unimodular. After this
|
|
21
|
+
rescaling, we say a form is even if it only represents even numbers,
|
|
22
|
+
and odd if it represents some odd number.
|
|
23
|
+
|
|
24
|
+
If the ``allow_rescaling_flag`` is set to False, then we require that
|
|
25
|
+
the quadratic form have a Gram matrix with coefficients in `\ZZ`, and
|
|
26
|
+
look at the unimodular Jordan block to determine its parity. This
|
|
27
|
+
returns an error if the form is not integer-matrix, meaning that it
|
|
28
|
+
has Jordan components at `p=2` which do not have an integer scale.
|
|
29
|
+
|
|
30
|
+
We determine the parity by looking for a `1 \times 1` block in the 0-th
|
|
31
|
+
Jordan component, after a possible rescaling.
|
|
32
|
+
|
|
33
|
+
INPUT:
|
|
34
|
+
|
|
35
|
+
- ``self`` -- a quadratic form with base ring `\ZZ`, which we may
|
|
36
|
+
require to have integer Gram matrix
|
|
37
|
+
|
|
38
|
+
OUTPUT: one of the strings: ``'even'`` or ``'odd'``
|
|
39
|
+
|
|
40
|
+
EXAMPLES::
|
|
41
|
+
|
|
42
|
+
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 3, 2]); Q
|
|
43
|
+
Quadratic form in 3 variables over Integer Ring with coefficients:
|
|
44
|
+
[ 4 -2 0 ]
|
|
45
|
+
[ * 2 3 ]
|
|
46
|
+
[ * * 2 ]
|
|
47
|
+
sage: Q.parity()
|
|
48
|
+
'even'
|
|
49
|
+
|
|
50
|
+
::
|
|
51
|
+
|
|
52
|
+
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 3, 1]); Q
|
|
53
|
+
Quadratic form in 3 variables over Integer Ring with coefficients:
|
|
54
|
+
[ 4 -2 0 ]
|
|
55
|
+
[ * 2 3 ]
|
|
56
|
+
[ * * 1 ]
|
|
57
|
+
sage: Q.parity()
|
|
58
|
+
'even'
|
|
59
|
+
|
|
60
|
+
::
|
|
61
|
+
|
|
62
|
+
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 2, 2]); Q
|
|
63
|
+
Quadratic form in 3 variables over Integer Ring with coefficients:
|
|
64
|
+
[ 4 -2 0 ]
|
|
65
|
+
[ * 2 2 ]
|
|
66
|
+
[ * * 2 ]
|
|
67
|
+
sage: Q.parity()
|
|
68
|
+
'even'
|
|
69
|
+
|
|
70
|
+
::
|
|
71
|
+
|
|
72
|
+
sage: Q = QuadraticForm(ZZ, 3, [4, -2, 0, 2, 2, 1]); Q
|
|
73
|
+
Quadratic form in 3 variables over Integer Ring with coefficients:
|
|
74
|
+
[ 4 -2 0 ]
|
|
75
|
+
[ * 2 2 ]
|
|
76
|
+
[ * * 1 ]
|
|
77
|
+
sage: Q.parity()
|
|
78
|
+
'odd'
|
|
79
|
+
"""
|
|
80
|
+
# Deal with 0-dim'l forms
|
|
81
|
+
if self.dim() == 0:
|
|
82
|
+
return "even"
|
|
83
|
+
|
|
84
|
+
# Identify the correct Jordan component to use.
|
|
85
|
+
Jordan_list = self.jordan_blocks_by_scale_and_unimodular(2)
|
|
86
|
+
scale_pow_list = [J[0] for J in Jordan_list]
|
|
87
|
+
min_scale_pow = min(scale_pow_list)
|
|
88
|
+
if allow_rescaling_flag:
|
|
89
|
+
ind = scale_pow_list.index(min_scale_pow)
|
|
90
|
+
else:
|
|
91
|
+
if min_scale_pow < 0:
|
|
92
|
+
raise TypeError("if rescaling is not allowed, then we require our form to have an integral Gram matrix")
|
|
93
|
+
ind = scale_pow_list.index(0)
|
|
94
|
+
|
|
95
|
+
# Find the component of scale (power) zero, and then look for an odd dim'l component.
|
|
96
|
+
J0 = Jordan_list[ind]
|
|
97
|
+
Q0 = J0[1]
|
|
98
|
+
|
|
99
|
+
# The lattice is even if there is no component of scale (power) 0
|
|
100
|
+
if J0 is None:
|
|
101
|
+
return "even"
|
|
102
|
+
|
|
103
|
+
# Look for a 1x1 block in the 0-th Jordan component (which by
|
|
104
|
+
# convention of the local_normal_form routine will appear first).
|
|
105
|
+
if Q0.dim() == 1:
|
|
106
|
+
return "odd"
|
|
107
|
+
if Q0[0, 1] == 0:
|
|
108
|
+
return "odd"
|
|
109
|
+
return "even"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def is_even(self, allow_rescaling_flag=True) -> bool:
|
|
113
|
+
r"""
|
|
114
|
+
Return true iff after rescaling by some appropriate factor, the
|
|
115
|
+
form represents no odd integers. For more details, see :meth:`parity`.
|
|
116
|
+
|
|
117
|
+
Requires that `Q` is defined over `\ZZ`.
|
|
118
|
+
|
|
119
|
+
EXAMPLES::
|
|
120
|
+
|
|
121
|
+
sage: Q = QuadraticForm(ZZ, 2, [1, 0, 1])
|
|
122
|
+
sage: Q.is_even()
|
|
123
|
+
False
|
|
124
|
+
sage: Q = QuadraticForm(ZZ, 2, [1, 1, 1])
|
|
125
|
+
sage: Q.is_even()
|
|
126
|
+
True
|
|
127
|
+
"""
|
|
128
|
+
return self.parity(allow_rescaling_flag) == "even"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def is_odd(self, allow_rescaling_flag=True) -> bool:
|
|
132
|
+
r"""
|
|
133
|
+
Return true iff after rescaling by some appropriate factor, the
|
|
134
|
+
form represents some odd integers. For more details, see :meth:`parity`.
|
|
135
|
+
|
|
136
|
+
Requires that `Q` is defined over `\ZZ`.
|
|
137
|
+
|
|
138
|
+
EXAMPLES::
|
|
139
|
+
|
|
140
|
+
sage: Q = QuadraticForm(ZZ, 2, [1, 0, 1])
|
|
141
|
+
sage: Q.is_odd()
|
|
142
|
+
True
|
|
143
|
+
sage: Q = QuadraticForm(ZZ, 2, [1, 1, 1])
|
|
144
|
+
sage: Q.is_odd()
|
|
145
|
+
False
|
|
146
|
+
"""
|
|
147
|
+
return self.parity(allow_rescaling_flag) == "odd"
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def conway_species_list_at_odd_prime(self, p):
|
|
151
|
+
r"""
|
|
152
|
+
Return an integer called the 'species' which determines the type
|
|
153
|
+
of the orthogonal group over the finite field `\GF{p}`.
|
|
154
|
+
|
|
155
|
+
This assumes that the given quadratic form is a unimodular Jordan
|
|
156
|
+
block at an odd prime `p`. When the dimension is odd then this
|
|
157
|
+
number is always positive, otherwise it may be positive or
|
|
158
|
+
negative (or zero, but that is considered positive by convention).
|
|
159
|
+
|
|
160
|
+
.. NOTE::
|
|
161
|
+
|
|
162
|
+
The species of a zero dimensional form is always 0+, so we
|
|
163
|
+
interpret the return value of zero as positive here! =)
|
|
164
|
+
|
|
165
|
+
INPUT:
|
|
166
|
+
|
|
167
|
+
- ``p`` -- a positive prime number
|
|
168
|
+
|
|
169
|
+
OUTPUT: list of integers
|
|
170
|
+
|
|
171
|
+
EXAMPLES::
|
|
172
|
+
|
|
173
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,10))
|
|
174
|
+
sage: Q.conway_species_list_at_odd_prime(3)
|
|
175
|
+
[6, 2, 1]
|
|
176
|
+
|
|
177
|
+
::
|
|
178
|
+
|
|
179
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8))
|
|
180
|
+
sage: Q.conway_species_list_at_odd_prime(3)
|
|
181
|
+
[5, 2]
|
|
182
|
+
sage: Q.conway_species_list_at_odd_prime(5)
|
|
183
|
+
[-6, 1]
|
|
184
|
+
"""
|
|
185
|
+
# Sanity Check:
|
|
186
|
+
if not (p > 2 and is_prime(p)):
|
|
187
|
+
raise TypeError("we are assuming that p is an odd positive prime number")
|
|
188
|
+
|
|
189
|
+
# Deal with the zero-dim'l form
|
|
190
|
+
if self.dim() == 0:
|
|
191
|
+
return [0]
|
|
192
|
+
|
|
193
|
+
# List the (unscaled/unimodular) Jordan blocks by their scale power
|
|
194
|
+
jordan_list = self.jordan_blocks_in_unimodular_list_by_scale_power(p)
|
|
195
|
+
|
|
196
|
+
# Make a list of species (including the two zero-dim'l forms missing at either end of the list of Jordan blocks)
|
|
197
|
+
species_list = []
|
|
198
|
+
for tmp_Q in jordan_list:
|
|
199
|
+
|
|
200
|
+
# Some useful variables
|
|
201
|
+
n = tmp_Q.dim()
|
|
202
|
+
d = tmp_Q.det()
|
|
203
|
+
|
|
204
|
+
# Determine the species
|
|
205
|
+
if n % 2 != 0: # Deal with odd dim'l forms
|
|
206
|
+
species = n
|
|
207
|
+
elif n % 4 == 2 and p % 4 == 3: # Deal with even dim'l forms
|
|
208
|
+
species = (-1) * legendre_symbol(d, p) * n
|
|
209
|
+
else:
|
|
210
|
+
species = legendre_symbol(d, p) * n
|
|
211
|
+
|
|
212
|
+
# Append the species to the list
|
|
213
|
+
species_list.append(species)
|
|
214
|
+
|
|
215
|
+
# Return the species list
|
|
216
|
+
return species_list
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def conway_species_list_at_2(self):
|
|
220
|
+
r"""
|
|
221
|
+
Return an integer called the 'species' which determines the type
|
|
222
|
+
of the orthogonal group over the finite field `\GF{p}`.
|
|
223
|
+
|
|
224
|
+
This assumes that the given quadratic form is a unimodular Jordan
|
|
225
|
+
block at an odd prime `p`. When the dimension is odd then this
|
|
226
|
+
number is always positive, otherwise it may be positive or
|
|
227
|
+
negative.
|
|
228
|
+
|
|
229
|
+
.. NOTE::
|
|
230
|
+
|
|
231
|
+
The species of a zero dimensional form is always 0+, so we
|
|
232
|
+
interpret the return value of zero as positive here! =)
|
|
233
|
+
|
|
234
|
+
OUTPUT: list of integers
|
|
235
|
+
|
|
236
|
+
EXAMPLES::
|
|
237
|
+
|
|
238
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,10))
|
|
239
|
+
sage: Q.conway_species_list_at_2()
|
|
240
|
+
[1, 5, 1, 1, 1, 1]
|
|
241
|
+
|
|
242
|
+
::
|
|
243
|
+
|
|
244
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8))
|
|
245
|
+
sage: Q.conway_species_list_at_2()
|
|
246
|
+
[1, 3, 1, 1, 1]
|
|
247
|
+
"""
|
|
248
|
+
# Some useful variables
|
|
249
|
+
n = self.dim()
|
|
250
|
+
d = self.det()
|
|
251
|
+
|
|
252
|
+
# Deal with the zero-dim'l form
|
|
253
|
+
if n == 0:
|
|
254
|
+
return 0
|
|
255
|
+
|
|
256
|
+
# List the (unscaled/unimodular) Jordan blocks by their scale power
|
|
257
|
+
jordan_list = self.jordan_blocks_in_unimodular_list_by_scale_power(2)
|
|
258
|
+
|
|
259
|
+
# Make a list of species (including the two zero-dim'l forms missing at either end of the list of Jordan blocks)
|
|
260
|
+
species_list = []
|
|
261
|
+
|
|
262
|
+
if jordan_list[0].parity() == "odd": # Add an entry for the unlisted "-1" Jordan component as well.
|
|
263
|
+
species_list.append(1)
|
|
264
|
+
|
|
265
|
+
for i in range(len(jordan_list)): # Add an entry for each (listed) Jordan component
|
|
266
|
+
|
|
267
|
+
# Make the number 2*t in the C-S Table 1.
|
|
268
|
+
d = jordan_list[i].dim()
|
|
269
|
+
if jordan_list[i].is_even():
|
|
270
|
+
two_t = d
|
|
271
|
+
else:
|
|
272
|
+
two_t = ZZ(2) * ((d - 1) // 2)
|
|
273
|
+
|
|
274
|
+
# Determine if the form is bound
|
|
275
|
+
if len(jordan_list) == 1:
|
|
276
|
+
is_bound = False
|
|
277
|
+
elif i == 0:
|
|
278
|
+
is_bound = jordan_list[i + 1].is_odd()
|
|
279
|
+
elif i == len(jordan_list) - 1:
|
|
280
|
+
is_bound = jordan_list[i - 1].is_odd()
|
|
281
|
+
else:
|
|
282
|
+
is_bound = jordan_list[i - 1].is_odd() or jordan_list[i + 1].is_odd()
|
|
283
|
+
|
|
284
|
+
# Determine the species
|
|
285
|
+
octane = jordan_list[i].conway_octane_of_this_unimodular_Jordan_block_at_2()
|
|
286
|
+
if is_bound or (octane == 2) or (octane == 6):
|
|
287
|
+
species = two_t + 1
|
|
288
|
+
elif (octane == 0) or (octane == 1) or (octane == 7):
|
|
289
|
+
species = two_t
|
|
290
|
+
else:
|
|
291
|
+
species = (-1) * two_t
|
|
292
|
+
|
|
293
|
+
# Append the species to the list
|
|
294
|
+
species_list.append(species)
|
|
295
|
+
|
|
296
|
+
if jordan_list[-1].is_odd(): # Add an entry for the unlisted "s_max + 1" Jordan component as well.
|
|
297
|
+
species_list.append(1)
|
|
298
|
+
|
|
299
|
+
# Return the species list
|
|
300
|
+
return species_list
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def conway_octane_of_this_unimodular_Jordan_block_at_2(self):
|
|
304
|
+
r"""
|
|
305
|
+
Determines the 'octane' of this full unimodular Jordan block at
|
|
306
|
+
the prime `p=2`. This is an invariant defined (mod 8), ad.
|
|
307
|
+
|
|
308
|
+
This assumes that the form is given as a block diagonal form with
|
|
309
|
+
unimodular blocks of size `\leq 2` and the `1 \times 1` blocks are all in the upper
|
|
310
|
+
leftmost position.
|
|
311
|
+
|
|
312
|
+
OUTPUT: integer `0 \leq x \leq 7`
|
|
313
|
+
|
|
314
|
+
EXAMPLES::
|
|
315
|
+
|
|
316
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7])
|
|
317
|
+
sage: Q.conway_octane_of_this_unimodular_Jordan_block_at_2()
|
|
318
|
+
0
|
|
319
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,5,13])
|
|
320
|
+
sage: Q.conway_octane_of_this_unimodular_Jordan_block_at_2()
|
|
321
|
+
3
|
|
322
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [3,7,13])
|
|
323
|
+
sage: Q.conway_octane_of_this_unimodular_Jordan_block_at_2()
|
|
324
|
+
7
|
|
325
|
+
"""
|
|
326
|
+
# Deal with 'even' forms
|
|
327
|
+
if self.parity() == "even":
|
|
328
|
+
d = self.Gram_matrix().det()
|
|
329
|
+
if d % 8 == 1 or d % 8 == 7:
|
|
330
|
+
return 0
|
|
331
|
+
else:
|
|
332
|
+
return 4
|
|
333
|
+
|
|
334
|
+
# Deal with 'odd' forms by diagonalizing, and then computing the octane.
|
|
335
|
+
n = self.dim()
|
|
336
|
+
u = self[0, 0]
|
|
337
|
+
tmp_diag_vec = [None] * n
|
|
338
|
+
tmp_diag_vec[0] = u # This should be an odd integer!
|
|
339
|
+
ind = 1 # The next index to diagonalize
|
|
340
|
+
|
|
341
|
+
# Use u to diagonalize the form -- WHAT ARE THE POSSIBLE LOCAL NORMAL FORMS?
|
|
342
|
+
while ind < n:
|
|
343
|
+
|
|
344
|
+
# Check for a 1x1 block and diagonalize it
|
|
345
|
+
if ind == n - 1 or self[ind, ind + 1] == 0:
|
|
346
|
+
tmp_diag_vec[ind] = self[ind, ind]
|
|
347
|
+
ind += 1
|
|
348
|
+
|
|
349
|
+
# Diagonalize the 2x2 block
|
|
350
|
+
else:
|
|
351
|
+
B = self[ind, ind + 1]
|
|
352
|
+
if B % 2:
|
|
353
|
+
raise RuntimeError("we expected the mixed term to be even")
|
|
354
|
+
|
|
355
|
+
a = self[ind, ind]
|
|
356
|
+
b = B // ZZ(2)
|
|
357
|
+
c = self[ind + 1, ind + 1]
|
|
358
|
+
tmp_disc = b * b - a * c
|
|
359
|
+
|
|
360
|
+
# Perform the diagonalization
|
|
361
|
+
if tmp_disc % 8 == 1: # 2xy
|
|
362
|
+
tmp_diag_vec[ind] = 1
|
|
363
|
+
tmp_diag_vec[ind + 1] = -1
|
|
364
|
+
ind += 2
|
|
365
|
+
elif tmp_disc % 8 == 5: # 2x^2 + 2xy + 2y^2
|
|
366
|
+
tmp_diag_vec[0] = 3 * u
|
|
367
|
+
tmp_diag_vec[ind] = -u
|
|
368
|
+
tmp_diag_vec[ind + 1] = -u
|
|
369
|
+
ind += 2
|
|
370
|
+
u = tmp_diag_vec[0]
|
|
371
|
+
else:
|
|
372
|
+
raise RuntimeError("this should not happen -- the odd 2x2 blocks have disc 1 or 5 (mod 8)")
|
|
373
|
+
|
|
374
|
+
# Compute the octane
|
|
375
|
+
octane = 0
|
|
376
|
+
for a in tmp_diag_vec:
|
|
377
|
+
if a % 4 == 1:
|
|
378
|
+
octane += 1
|
|
379
|
+
elif a % 4 == 3:
|
|
380
|
+
octane += -1
|
|
381
|
+
else:
|
|
382
|
+
raise RuntimeError("the diagonal elements should all be odd")
|
|
383
|
+
|
|
384
|
+
# Return its value
|
|
385
|
+
return octane % 8
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def conway_diagonal_factor(self, p):
|
|
389
|
+
r"""
|
|
390
|
+
Compute the diagonal factor of Conway's `p`-mass.
|
|
391
|
+
|
|
392
|
+
INPUT:
|
|
393
|
+
|
|
394
|
+
- ``p`` -- a prime number > 0
|
|
395
|
+
|
|
396
|
+
OUTPUT: a rational number > 0
|
|
397
|
+
|
|
398
|
+
EXAMPLES::
|
|
399
|
+
|
|
400
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,6))
|
|
401
|
+
sage: Q.conway_diagonal_factor(3)
|
|
402
|
+
81/256
|
|
403
|
+
"""
|
|
404
|
+
# Get the species list at p
|
|
405
|
+
if p == 2:
|
|
406
|
+
species_list = self.conway_species_list_at_2()
|
|
407
|
+
else:
|
|
408
|
+
species_list = self.conway_species_list_at_odd_prime(p)
|
|
409
|
+
|
|
410
|
+
# Evaluate the diagonal factor
|
|
411
|
+
diag_factor = QQ(1)
|
|
412
|
+
for s in species_list:
|
|
413
|
+
if s == 0:
|
|
414
|
+
pass
|
|
415
|
+
elif s % 2 == 1: # Note: Here always s > 0.
|
|
416
|
+
diag_factor = diag_factor / (2 * prod([1 - QQ(p)**(-i)
|
|
417
|
+
for i in range(2, s, 2)]))
|
|
418
|
+
else:
|
|
419
|
+
diag_factor = diag_factor / (2 * prod([1 - QQ(p)**(-i)
|
|
420
|
+
for i in range(2, abs(s), 2)]))
|
|
421
|
+
s_sign = ZZ(s / abs(s))
|
|
422
|
+
diag_factor = diag_factor / (ZZ(1) - s_sign * QQ(p) ** ZZ(-abs(s) / ZZ(2)))
|
|
423
|
+
|
|
424
|
+
# Return the diagonal factor
|
|
425
|
+
return diag_factor
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def conway_cross_product_doubled_power(self, p):
|
|
429
|
+
r"""
|
|
430
|
+
Compute twice the power of `p` which evaluates the 'cross product'
|
|
431
|
+
term in Conway's mass formula.
|
|
432
|
+
|
|
433
|
+
INPUT:
|
|
434
|
+
|
|
435
|
+
- ``p`` -- a prime number > 0
|
|
436
|
+
|
|
437
|
+
OUTPUT: a rational number
|
|
438
|
+
|
|
439
|
+
EXAMPLES::
|
|
440
|
+
|
|
441
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8))
|
|
442
|
+
sage: Q.conway_cross_product_doubled_power(2)
|
|
443
|
+
18
|
|
444
|
+
sage: Q.conway_cross_product_doubled_power(3)
|
|
445
|
+
10
|
|
446
|
+
sage: Q.conway_cross_product_doubled_power(5)
|
|
447
|
+
6
|
|
448
|
+
sage: Q.conway_cross_product_doubled_power(7)
|
|
449
|
+
6
|
|
450
|
+
sage: Q.conway_cross_product_doubled_power(11)
|
|
451
|
+
0
|
|
452
|
+
sage: Q.conway_cross_product_doubled_power(13)
|
|
453
|
+
0
|
|
454
|
+
"""
|
|
455
|
+
dim_list = [J.dim() for J in self.jordan_blocks_in_unimodular_list_by_scale_power(p)]
|
|
456
|
+
return sum((i - j) * dimi * dim_list[j]
|
|
457
|
+
for i, dimi in enumerate(dim_list)
|
|
458
|
+
for j in range(i))
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def conway_type_factor(self):
|
|
462
|
+
r"""
|
|
463
|
+
This is a special factor only present in the mass formula when `p=2`.
|
|
464
|
+
|
|
465
|
+
OUTPUT: a rational number
|
|
466
|
+
|
|
467
|
+
EXAMPLES::
|
|
468
|
+
|
|
469
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1,8))
|
|
470
|
+
sage: Q.conway_type_factor()
|
|
471
|
+
4
|
|
472
|
+
"""
|
|
473
|
+
jordan_list = self.jordan_blocks_in_unimodular_list_by_scale_power(2)
|
|
474
|
+
n2 = sum([J.dim() for J in jordan_list if J.is_even()])
|
|
475
|
+
n11 = sum([1 for i in range(len(jordan_list) - 1)
|
|
476
|
+
if jordan_list[i].is_odd() and jordan_list[i + 1].is_odd()])
|
|
477
|
+
|
|
478
|
+
return ZZ(2)**(n11 - n2)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def conway_p_mass(self, p):
|
|
482
|
+
r"""
|
|
483
|
+
Compute Conway's `p`-mass.
|
|
484
|
+
|
|
485
|
+
INPUT:
|
|
486
|
+
|
|
487
|
+
- ``p`` -- a prime number > 0
|
|
488
|
+
|
|
489
|
+
OUTPUT: a rational number > 0
|
|
490
|
+
|
|
491
|
+
EXAMPLES::
|
|
492
|
+
|
|
493
|
+
sage: Q = DiagonalQuadraticForm(ZZ, range(1, 6))
|
|
494
|
+
sage: Q.conway_p_mass(2)
|
|
495
|
+
16/3
|
|
496
|
+
sage: Q.conway_p_mass(3)
|
|
497
|
+
729/256
|
|
498
|
+
"""
|
|
499
|
+
# Compute the first two factors of the p-mass
|
|
500
|
+
p_mass = self.conway_diagonal_factor(p) * (p ** (self.conway_cross_product_doubled_power(p) / ZZ(2)))
|
|
501
|
+
|
|
502
|
+
# Multiply by the 'type factor' when p = 2
|
|
503
|
+
if p == 2:
|
|
504
|
+
p_mass *= self.conway_type_factor()
|
|
505
|
+
|
|
506
|
+
# Return the result
|
|
507
|
+
return p_mass
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def conway_standard_p_mass(self, p):
|
|
511
|
+
r"""
|
|
512
|
+
Compute the standard (generic) Conway-Sloane `p`-mass.
|
|
513
|
+
|
|
514
|
+
INPUT:
|
|
515
|
+
|
|
516
|
+
- ``p`` -- a prime number > 0
|
|
517
|
+
|
|
518
|
+
OUTPUT: a rational number > 0
|
|
519
|
+
|
|
520
|
+
EXAMPLES::
|
|
521
|
+
|
|
522
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
523
|
+
sage: Q.conway_standard_p_mass(2)
|
|
524
|
+
2/3
|
|
525
|
+
"""
|
|
526
|
+
# Some useful variables
|
|
527
|
+
n = self.dim()
|
|
528
|
+
if n % 2 == 0:
|
|
529
|
+
s = n // 2
|
|
530
|
+
else:
|
|
531
|
+
s = (n + 1) // 2
|
|
532
|
+
|
|
533
|
+
# Compute the inverse of the generic p-mass
|
|
534
|
+
p_mass_inv = 2 * prod([1 - p**(-i) for i in range(2, 2 * s, 2)])
|
|
535
|
+
if n % 2 == 0:
|
|
536
|
+
D = (-1)**s * self.det() * (2**n)
|
|
537
|
+
# We should have something like D = (-1)**s * self.det() / (2**n), but that's not an integer and here we only care about the square-class.
|
|
538
|
+
# d = self.det() # Note: No normalizing power of 2 is needed since the power is even.
|
|
539
|
+
# if not ((p == 2) or (d % p == 0)):
|
|
540
|
+
p_mass_inv *= (1 - kronecker_symbol(fundamental_discriminant(D), p) * p**(-s))
|
|
541
|
+
|
|
542
|
+
# Return the standard p-mass
|
|
543
|
+
return ZZ.one() / p_mass_inv
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def conway_standard_mass(self):
|
|
547
|
+
r"""
|
|
548
|
+
Return the infinite product of the standard mass factors.
|
|
549
|
+
|
|
550
|
+
OUTPUT: a rational number > 0
|
|
551
|
+
|
|
552
|
+
EXAMPLES::
|
|
553
|
+
|
|
554
|
+
sage: Q = QuadraticForm(ZZ, 3, [2, -2, 0, 3, -5, 4])
|
|
555
|
+
sage: Q.conway_standard_mass() # needs sage.symbolic
|
|
556
|
+
1/6
|
|
557
|
+
|
|
558
|
+
::
|
|
559
|
+
|
|
560
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
561
|
+
sage: Q.conway_standard_mass() # needs sage.symbolic
|
|
562
|
+
1/6
|
|
563
|
+
"""
|
|
564
|
+
from sage.quadratic_forms.special_values import gamma__exact, zeta__exact, quadratic_L_function__exact
|
|
565
|
+
from sage.symbolic.constants import pi
|
|
566
|
+
|
|
567
|
+
n = self.dim()
|
|
568
|
+
if n % 2 == 0:
|
|
569
|
+
s = n // 2
|
|
570
|
+
else:
|
|
571
|
+
s = (n + 1) // 2
|
|
572
|
+
|
|
573
|
+
generic_mass = 2 * pi**((-1) * n * (n + 1) / ZZ(4)) \
|
|
574
|
+
* prod([gamma__exact(j / ZZ(2)) for j in range(1, n + 1)]) \
|
|
575
|
+
* prod([zeta__exact(2 * k) for k in range(1, s)])
|
|
576
|
+
|
|
577
|
+
if n % 2 == 0:
|
|
578
|
+
D = (-1)**s * self.det() * (2**n)
|
|
579
|
+
# We should have something like D = (-1)**s * self.det() / (2**n), but
|
|
580
|
+
# that's not an integer and here we only care about the square-class.
|
|
581
|
+
generic_mass *= quadratic_L_function__exact(s, D)
|
|
582
|
+
|
|
583
|
+
return generic_mass
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def conway_mass(self):
|
|
587
|
+
r"""
|
|
588
|
+
Compute the mass by using the Conway-Sloane mass formula.
|
|
589
|
+
|
|
590
|
+
OUTPUT: a rational number > 0
|
|
591
|
+
|
|
592
|
+
EXAMPLES::
|
|
593
|
+
|
|
594
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [1,1,1])
|
|
595
|
+
sage: Q.conway_mass() # needs sage.symbolic
|
|
596
|
+
1/48
|
|
597
|
+
|
|
598
|
+
sage: Q = DiagonalQuadraticForm(ZZ, [7,1,1])
|
|
599
|
+
sage: Q.conway_mass() # needs sage.symbolic
|
|
600
|
+
3/16
|
|
601
|
+
|
|
602
|
+
sage: Q = QuadraticForm(ZZ, 3, [7, 2, 2, 2, 0, 2]) + DiagonalQuadraticForm(ZZ, [1])
|
|
603
|
+
sage: Q.conway_mass() # needs sage.symbolic
|
|
604
|
+
3/32
|
|
605
|
+
|
|
606
|
+
sage: Q = QuadraticForm(Matrix(ZZ, 2, [2,1,1,2]))
|
|
607
|
+
sage: Q.conway_mass() # needs sage.symbolic
|
|
608
|
+
1/12
|
|
609
|
+
"""
|
|
610
|
+
# Try to use the cached result
|
|
611
|
+
try:
|
|
612
|
+
return self.__conway_mass
|
|
613
|
+
except AttributeError:
|
|
614
|
+
# Double the form so it's integer-matrix
|
|
615
|
+
Q = self.scale_by_factor(2)
|
|
616
|
+
|
|
617
|
+
# Compute the standard mass
|
|
618
|
+
mass = Q.conway_standard_mass()
|
|
619
|
+
|
|
620
|
+
# Adjust the p-masses when p|2d
|
|
621
|
+
d = self.det()
|
|
622
|
+
for p in prime_divisors(2 * d):
|
|
623
|
+
mass *= (Q.conway_p_mass(p) / Q.conway_standard_p_mass(p))
|
|
624
|
+
|
|
625
|
+
# Cache and return the (simplified) result
|
|
626
|
+
self.__conway_mass = QQ(mass.canonicalize_radical()).abs()
|
|
627
|
+
return self.__conway_mass
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
# def conway_generic_mass(self):
|
|
631
|
+
# """
|
|
632
|
+
# Computes the generic mass given as
|
|
633
|
+
# 2 \pi^{-n(n+1)/4} \prod_{j=1}^{n} \Gamma\(\tfrac{j}{2}\)
|
|
634
|
+
# \zeta(2) \cdots \zeta(2s-2) \zeta_{D}(s)
|
|
635
|
+
# where $n = 2s$ or $2s-1$ depending on the parity of $n$,
|
|
636
|
+
# and $D = (-1)^{s} d$. We interpret the symbol $\(\frac{D}{p}\)$
|
|
637
|
+
# as 0 if $p\mid 2d$.
|
|
638
|
+
# (Conway and Sloane, Mass formula paper, p??)
|
|
639
|
+
#
|
|
640
|
+
# This is possibly equal to
|
|
641
|
+
# 2^{-td} * \tau(G) *[\prod_{i=1}^{t} \zeta(1-2i) ]* L(1-t, \chi)
|
|
642
|
+
# where $\dim(Q) = n = 2t$ or $2t+1$, and the last factor is omitted
|
|
643
|
+
# when $n$ is odd.
|
|
644
|
+
# (GHY, Prop 7.4 and 7.5, p121)
|
|
645
|
+
# """
|
|
646
|
+
# RR = RealField(200)
|
|
647
|
+
# n = self.dim()
|
|
648
|
+
# if n % 2 == 0:
|
|
649
|
+
# s = n / 2
|
|
650
|
+
# else:
|
|
651
|
+
# s = (n-1) / 2
|
|
652
|
+
#
|
|
653
|
+
# # Form the generic zeta product
|
|
654
|
+
# ans = 2 * RR(pi)^(-n * (n+1) / 4)
|
|
655
|
+
# for j in range(1,n+1):
|
|
656
|
+
# ans *= gamma(RR(j/2))
|
|
657
|
+
# for j in range(2, 2*s, 2): # j = 2, ..., 2s-2
|
|
658
|
+
# ans *= zeta(RR(j))
|
|
659
|
+
#
|
|
660
|
+
# # Extra L-factor for even dimensional forms -- DO THIS!!!
|
|
661
|
+
# raise NotImplementedError("This routine is not finished yet")
|
|
662
|
+
#
|
|
663
|
+
# return ans
|