passagemath-modules 10.6.31rc3__cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_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-modules might be problematic. Click here for more details.
- passagemath_modules-10.6.31rc3.dist-info/METADATA +281 -0
- passagemath_modules-10.6.31rc3.dist-info/RECORD +807 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgfortran-83c28eba.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-6e109695.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-cda90e79.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-7f678fcf.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-82690d50.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
- passagemath_modules.libs/libquadmath-2284e583.so.0.0.0 +0 -0
- sage/algebras/all__sagemath_modules.py +20 -0
- sage/algebras/catalog.py +148 -0
- sage/algebras/clifford_algebra.py +3107 -0
- sage/algebras/clifford_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/clifford_algebra_element.pxd +16 -0
- sage/algebras/clifford_algebra_element.pyx +997 -0
- sage/algebras/commutative_dga.py +4252 -0
- sage/algebras/exterior_algebra_groebner.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/exterior_algebra_groebner.pxd +55 -0
- sage/algebras/exterior_algebra_groebner.pyx +727 -0
- sage/algebras/finite_dimensional_algebras/all.py +2 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +1029 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pxd +12 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +706 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +196 -0
- sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +255 -0
- sage/algebras/finite_gca.py +528 -0
- sage/algebras/group_algebra.py +232 -0
- sage/algebras/lie_algebras/abelian.py +197 -0
- sage/algebras/lie_algebras/affine_lie_algebra.py +1213 -0
- sage/algebras/lie_algebras/all.py +25 -0
- sage/algebras/lie_algebras/all__sagemath_modules.py +1 -0
- sage/algebras/lie_algebras/bch.py +177 -0
- sage/algebras/lie_algebras/bgg_dual_module.py +1184 -0
- sage/algebras/lie_algebras/bgg_resolution.py +232 -0
- sage/algebras/lie_algebras/center_uea.py +767 -0
- sage/algebras/lie_algebras/classical_lie_algebra.py +2516 -0
- sage/algebras/lie_algebras/examples.py +683 -0
- sage/algebras/lie_algebras/free_lie_algebra.py +973 -0
- sage/algebras/lie_algebras/heisenberg.py +820 -0
- sage/algebras/lie_algebras/lie_algebra.py +1562 -0
- sage/algebras/lie_algebras/lie_algebra_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/lie_algebras/lie_algebra_element.pxd +68 -0
- sage/algebras/lie_algebras/lie_algebra_element.pyx +2122 -0
- sage/algebras/lie_algebras/morphism.py +661 -0
- sage/algebras/lie_algebras/nilpotent_lie_algebra.py +457 -0
- sage/algebras/lie_algebras/onsager.py +1324 -0
- sage/algebras/lie_algebras/poincare_birkhoff_witt.py +816 -0
- sage/algebras/lie_algebras/quotient.py +462 -0
- sage/algebras/lie_algebras/rank_two_heisenberg_virasoro.py +355 -0
- sage/algebras/lie_algebras/representation.py +1040 -0
- sage/algebras/lie_algebras/structure_coefficients.py +459 -0
- sage/algebras/lie_algebras/subalgebra.py +967 -0
- sage/algebras/lie_algebras/symplectic_derivation.py +289 -0
- sage/algebras/lie_algebras/verma_module.py +1630 -0
- sage/algebras/lie_algebras/virasoro.py +1186 -0
- sage/algebras/octonion_algebra.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/algebras/octonion_algebra.pxd +20 -0
- sage/algebras/octonion_algebra.pyx +987 -0
- sage/algebras/orlik_solomon.py +907 -0
- sage/algebras/orlik_terao.py +779 -0
- sage/algebras/steenrod/all.py +7 -0
- sage/algebras/steenrod/steenrod_algebra.py +4258 -0
- sage/algebras/steenrod/steenrod_algebra_bases.py +1179 -0
- sage/algebras/steenrod/steenrod_algebra_misc.py +1167 -0
- sage/algebras/steenrod/steenrod_algebra_mult.py +954 -0
- sage/algebras/weyl_algebra.py +1126 -0
- sage/all__sagemath_modules.py +62 -0
- sage/calculus/all__sagemath_modules.py +19 -0
- sage/calculus/expr.py +205 -0
- sage/calculus/integration.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/riemann.pyx +1521 -0
- sage/calculus/test_sympy.py +201 -0
- sage/calculus/transforms/all.py +7 -0
- sage/calculus/transforms/dft.py +844 -0
- sage/calculus/transforms/dwt.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/transforms/dwt.pxd +7 -0
- sage/calculus/transforms/dwt.pyx +160 -0
- sage/calculus/transforms/fft.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/calculus/transforms/fft.pxd +12 -0
- sage/calculus/transforms/fft.pyx +487 -0
- sage/calculus/wester.py +662 -0
- sage/coding/abstract_code.py +1108 -0
- sage/coding/ag_code.py +868 -0
- sage/coding/ag_code_decoders.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/coding/ag_code_decoders.pyx +2639 -0
- sage/coding/all.py +15 -0
- sage/coding/bch_code.py +494 -0
- sage/coding/binary_code.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/coding/binary_code.pxd +124 -0
- sage/coding/binary_code.pyx +4139 -0
- sage/coding/bounds_catalog.py +43 -0
- sage/coding/channel.py +819 -0
- sage/coding/channels_catalog.py +29 -0
- sage/coding/code_bounds.py +755 -0
- sage/coding/code_constructions.py +804 -0
- sage/coding/codes_catalog.py +111 -0
- sage/coding/cyclic_code.py +1329 -0
- sage/coding/databases.py +316 -0
- sage/coding/decoder.py +373 -0
- sage/coding/decoders_catalog.py +88 -0
- sage/coding/delsarte_bounds.py +709 -0
- sage/coding/encoder.py +390 -0
- sage/coding/encoders_catalog.py +64 -0
- sage/coding/extended_code.py +468 -0
- sage/coding/gabidulin_code.py +1058 -0
- sage/coding/golay_code.py +404 -0
- sage/coding/goppa_code.py +441 -0
- sage/coding/grs_code.py +2371 -0
- sage/coding/guava.py +107 -0
- sage/coding/guruswami_sudan/all.py +1 -0
- sage/coding/guruswami_sudan/gs_decoder.py +897 -0
- sage/coding/guruswami_sudan/interpolation.py +409 -0
- sage/coding/guruswami_sudan/utils.py +176 -0
- sage/coding/hamming_code.py +176 -0
- sage/coding/information_set_decoder.py +1032 -0
- sage/coding/kasami_codes.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/coding/kasami_codes.pyx +351 -0
- sage/coding/linear_code.py +3067 -0
- sage/coding/linear_code_no_metric.py +1354 -0
- sage/coding/linear_rank_metric.py +961 -0
- sage/coding/parity_check_code.py +353 -0
- sage/coding/punctured_code.py +719 -0
- sage/coding/reed_muller_code.py +999 -0
- sage/coding/self_dual_codes.py +942 -0
- sage/coding/source_coding/all.py +2 -0
- sage/coding/source_coding/huffman.py +553 -0
- sage/coding/subfield_subcode.py +423 -0
- sage/coding/two_weight_db.py +399 -0
- sage/combinat/all__sagemath_modules.py +7 -0
- sage/combinat/cartesian_product.py +347 -0
- sage/combinat/family.py +11 -0
- sage/combinat/free_module.py +1977 -0
- sage/combinat/root_system/all.py +147 -0
- sage/combinat/root_system/ambient_space.py +527 -0
- sage/combinat/root_system/associahedron.py +471 -0
- sage/combinat/root_system/braid_move_calculator.py +143 -0
- sage/combinat/root_system/braid_orbit.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/combinat/root_system/braid_orbit.pyx +144 -0
- sage/combinat/root_system/branching_rules.py +2301 -0
- sage/combinat/root_system/cartan_matrix.py +1245 -0
- sage/combinat/root_system/cartan_type.py +3069 -0
- sage/combinat/root_system/coxeter_group.py +162 -0
- sage/combinat/root_system/coxeter_matrix.py +1261 -0
- sage/combinat/root_system/coxeter_type.py +681 -0
- sage/combinat/root_system/dynkin_diagram.py +900 -0
- sage/combinat/root_system/extended_affine_weyl_group.py +2993 -0
- sage/combinat/root_system/fundamental_group.py +795 -0
- sage/combinat/root_system/hecke_algebra_representation.py +1203 -0
- sage/combinat/root_system/integrable_representations.py +1227 -0
- sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +1965 -0
- sage/combinat/root_system/pieri_factors.py +1147 -0
- sage/combinat/root_system/plot.py +1615 -0
- sage/combinat/root_system/root_lattice_realization_algebras.py +1214 -0
- sage/combinat/root_system/root_lattice_realizations.py +4628 -0
- sage/combinat/root_system/root_space.py +487 -0
- sage/combinat/root_system/root_system.py +882 -0
- sage/combinat/root_system/type_A.py +348 -0
- sage/combinat/root_system/type_A_affine.py +227 -0
- sage/combinat/root_system/type_A_infinity.py +241 -0
- sage/combinat/root_system/type_B.py +347 -0
- sage/combinat/root_system/type_BC_affine.py +287 -0
- sage/combinat/root_system/type_B_affine.py +216 -0
- sage/combinat/root_system/type_C.py +317 -0
- sage/combinat/root_system/type_C_affine.py +188 -0
- sage/combinat/root_system/type_D.py +357 -0
- sage/combinat/root_system/type_D_affine.py +208 -0
- sage/combinat/root_system/type_E.py +641 -0
- sage/combinat/root_system/type_E_affine.py +231 -0
- sage/combinat/root_system/type_F.py +387 -0
- sage/combinat/root_system/type_F_affine.py +137 -0
- sage/combinat/root_system/type_G.py +293 -0
- sage/combinat/root_system/type_G_affine.py +132 -0
- sage/combinat/root_system/type_H.py +105 -0
- sage/combinat/root_system/type_I.py +110 -0
- sage/combinat/root_system/type_Q.py +150 -0
- sage/combinat/root_system/type_affine.py +509 -0
- sage/combinat/root_system/type_dual.py +704 -0
- sage/combinat/root_system/type_folded.py +301 -0
- sage/combinat/root_system/type_marked.py +748 -0
- sage/combinat/root_system/type_reducible.py +601 -0
- sage/combinat/root_system/type_relabel.py +730 -0
- sage/combinat/root_system/type_super_A.py +837 -0
- sage/combinat/root_system/weight_lattice_realizations.py +1188 -0
- sage/combinat/root_system/weight_space.py +639 -0
- sage/combinat/root_system/weyl_characters.py +2238 -0
- sage/crypto/__init__.py +4 -0
- sage/crypto/all.py +28 -0
- sage/crypto/block_cipher/all.py +7 -0
- sage/crypto/block_cipher/des.py +1065 -0
- sage/crypto/block_cipher/miniaes.py +2171 -0
- sage/crypto/block_cipher/present.py +909 -0
- sage/crypto/block_cipher/sdes.py +1527 -0
- sage/crypto/boolean_function.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/crypto/boolean_function.pxd +10 -0
- sage/crypto/boolean_function.pyx +1487 -0
- sage/crypto/cipher.py +78 -0
- sage/crypto/classical.py +3668 -0
- sage/crypto/classical_cipher.py +569 -0
- sage/crypto/cryptosystem.py +387 -0
- sage/crypto/key_exchange/all.py +7 -0
- sage/crypto/key_exchange/catalog.py +24 -0
- sage/crypto/key_exchange/diffie_hellman.py +323 -0
- sage/crypto/key_exchange/key_exchange_scheme.py +107 -0
- sage/crypto/lattice.py +312 -0
- sage/crypto/lfsr.py +295 -0
- sage/crypto/lwe.py +840 -0
- sage/crypto/mq/__init__.py +4 -0
- sage/crypto/mq/mpolynomialsystemgenerator.py +204 -0
- sage/crypto/mq/rijndael_gf.py +2345 -0
- sage/crypto/mq/sbox.py +7 -0
- sage/crypto/mq/sr.py +3344 -0
- sage/crypto/public_key/all.py +5 -0
- sage/crypto/public_key/blum_goldwasser.py +776 -0
- sage/crypto/sbox.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/crypto/sbox.pyx +2090 -0
- sage/crypto/sboxes.py +2090 -0
- sage/crypto/stream.py +390 -0
- sage/crypto/stream_cipher.py +297 -0
- sage/crypto/util.py +519 -0
- sage/ext/all__sagemath_modules.py +1 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_modules.py +2 -0
- sage/ext/interpreters/wrapper_cc.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_cc.pxd +30 -0
- sage/ext/interpreters/wrapper_cc.pyx +252 -0
- sage/ext/interpreters/wrapper_cdf.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_cdf.pxd +26 -0
- sage/ext/interpreters/wrapper_cdf.pyx +245 -0
- sage/ext/interpreters/wrapper_rdf.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_rdf.pxd +23 -0
- sage/ext/interpreters/wrapper_rdf.pyx +221 -0
- sage/ext/interpreters/wrapper_rr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/ext/interpreters/wrapper_rr.pxd +28 -0
- sage/ext/interpreters/wrapper_rr.pyx +335 -0
- sage/geometry/all__sagemath_modules.py +5 -0
- sage/geometry/toric_lattice.py +1745 -0
- sage/geometry/toric_lattice_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/geometry/toric_lattice_element.pyx +432 -0
- sage/groups/abelian_gps/abelian_group.py +1925 -0
- sage/groups/abelian_gps/abelian_group_element.py +164 -0
- sage/groups/abelian_gps/all__sagemath_modules.py +5 -0
- sage/groups/abelian_gps/dual_abelian_group.py +421 -0
- sage/groups/abelian_gps/dual_abelian_group_element.py +179 -0
- sage/groups/abelian_gps/element_base.py +341 -0
- sage/groups/abelian_gps/values.py +488 -0
- sage/groups/additive_abelian/additive_abelian_group.py +476 -0
- sage/groups/additive_abelian/additive_abelian_wrapper.py +857 -0
- sage/groups/additive_abelian/all.py +4 -0
- sage/groups/additive_abelian/qmodnz.py +231 -0
- sage/groups/additive_abelian/qmodnz_element.py +349 -0
- sage/groups/affine_gps/affine_group.py +535 -0
- sage/groups/affine_gps/all.py +1 -0
- sage/groups/affine_gps/catalog.py +17 -0
- sage/groups/affine_gps/euclidean_group.py +246 -0
- sage/groups/affine_gps/group_element.py +562 -0
- sage/groups/all__sagemath_modules.py +12 -0
- sage/groups/galois_group.py +479 -0
- sage/groups/matrix_gps/all.py +4 -0
- sage/groups/matrix_gps/all__sagemath_modules.py +13 -0
- sage/groups/matrix_gps/catalog.py +26 -0
- sage/groups/matrix_gps/coxeter_group.py +927 -0
- sage/groups/matrix_gps/finitely_generated.py +487 -0
- sage/groups/matrix_gps/group_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/groups/matrix_gps/group_element.pxd +11 -0
- sage/groups/matrix_gps/group_element.pyx +431 -0
- sage/groups/matrix_gps/linear.py +440 -0
- sage/groups/matrix_gps/matrix_group.py +617 -0
- sage/groups/matrix_gps/named_group.py +296 -0
- sage/groups/matrix_gps/orthogonal.py +544 -0
- sage/groups/matrix_gps/symplectic.py +251 -0
- sage/groups/matrix_gps/unitary.py +436 -0
- sage/groups/misc_gps/all__sagemath_modules.py +1 -0
- sage/groups/misc_gps/argument_groups.py +1905 -0
- sage/groups/misc_gps/imaginary_groups.py +479 -0
- sage/groups/perm_gps/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_modules.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pxd +41 -0
- sage/groups/perm_gps/partn_ref/refinement_binary.pyx +1167 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pxd +31 -0
- sage/groups/perm_gps/partn_ref/refinement_matrices.pyx +385 -0
- sage/homology/algebraic_topological_model.py +595 -0
- sage/homology/all.py +2 -0
- sage/homology/all__sagemath_modules.py +8 -0
- sage/homology/chain_complex.py +2148 -0
- sage/homology/chain_complex_homspace.py +165 -0
- sage/homology/chain_complex_morphism.py +629 -0
- sage/homology/chain_homotopy.py +604 -0
- sage/homology/chains.py +653 -0
- sage/homology/free_resolution.py +923 -0
- sage/homology/graded_resolution.py +567 -0
- sage/homology/hochschild_complex.py +756 -0
- sage/homology/homology_group.py +188 -0
- sage/homology/homology_morphism.py +422 -0
- sage/homology/homology_vector_space_with_basis.py +1454 -0
- sage/homology/koszul_complex.py +169 -0
- sage/homology/matrix_utils.py +205 -0
- sage/libs/all__sagemath_modules.py +1 -0
- sage/libs/gsl/__init__.py +1 -0
- sage/libs/gsl/airy.pxd +56 -0
- sage/libs/gsl/all.pxd +66 -0
- sage/libs/gsl/array.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/gsl/array.pxd +5 -0
- sage/libs/gsl/array.pyx +102 -0
- sage/libs/gsl/bessel.pxd +208 -0
- sage/libs/gsl/blas.pxd +116 -0
- sage/libs/gsl/blas_types.pxd +34 -0
- sage/libs/gsl/block.pxd +52 -0
- sage/libs/gsl/chebyshev.pxd +37 -0
- sage/libs/gsl/clausen.pxd +12 -0
- sage/libs/gsl/combination.pxd +47 -0
- sage/libs/gsl/complex.pxd +151 -0
- sage/libs/gsl/coulomb.pxd +30 -0
- sage/libs/gsl/coupling.pxd +21 -0
- sage/libs/gsl/dawson.pxd +12 -0
- sage/libs/gsl/debye.pxd +24 -0
- sage/libs/gsl/dilog.pxd +14 -0
- sage/libs/gsl/eigen.pxd +46 -0
- sage/libs/gsl/elementary.pxd +12 -0
- sage/libs/gsl/ellint.pxd +48 -0
- sage/libs/gsl/elljac.pxd +8 -0
- sage/libs/gsl/erf.pxd +32 -0
- sage/libs/gsl/errno.pxd +26 -0
- sage/libs/gsl/exp.pxd +44 -0
- sage/libs/gsl/expint.pxd +44 -0
- sage/libs/gsl/fermi_dirac.pxd +44 -0
- sage/libs/gsl/fft.pxd +121 -0
- sage/libs/gsl/fit.pxd +50 -0
- sage/libs/gsl/gamma.pxd +94 -0
- sage/libs/gsl/gegenbauer.pxd +26 -0
- sage/libs/gsl/histogram.pxd +176 -0
- sage/libs/gsl/hyperg.pxd +52 -0
- sage/libs/gsl/integration.pxd +69 -0
- sage/libs/gsl/interp.pxd +109 -0
- sage/libs/gsl/laguerre.pxd +24 -0
- sage/libs/gsl/lambert.pxd +16 -0
- sage/libs/gsl/legendre.pxd +90 -0
- sage/libs/gsl/linalg.pxd +185 -0
- sage/libs/gsl/log.pxd +26 -0
- sage/libs/gsl/math.pxd +43 -0
- sage/libs/gsl/matrix.pxd +143 -0
- sage/libs/gsl/matrix_complex.pxd +130 -0
- sage/libs/gsl/min.pxd +67 -0
- sage/libs/gsl/monte.pxd +56 -0
- sage/libs/gsl/ntuple.pxd +32 -0
- sage/libs/gsl/odeiv.pxd +70 -0
- sage/libs/gsl/permutation.pxd +78 -0
- sage/libs/gsl/poly.pxd +40 -0
- sage/libs/gsl/pow_int.pxd +12 -0
- sage/libs/gsl/psi.pxd +28 -0
- sage/libs/gsl/qrng.pxd +29 -0
- sage/libs/gsl/random.pxd +257 -0
- sage/libs/gsl/rng.pxd +100 -0
- sage/libs/gsl/roots.pxd +72 -0
- sage/libs/gsl/sort.pxd +36 -0
- sage/libs/gsl/statistics.pxd +59 -0
- sage/libs/gsl/sum.pxd +55 -0
- sage/libs/gsl/synchrotron.pxd +16 -0
- sage/libs/gsl/transport.pxd +24 -0
- sage/libs/gsl/trig.pxd +58 -0
- sage/libs/gsl/types.pxd +137 -0
- sage/libs/gsl/vector.pxd +101 -0
- sage/libs/gsl/vector_complex.pxd +83 -0
- sage/libs/gsl/wavelet.pxd +49 -0
- sage/libs/gsl/zeta.pxd +28 -0
- sage/libs/mpc/__init__.pxd +114 -0
- sage/libs/mpc/types.pxd +28 -0
- sage/libs/mpfr/__init__.pxd +299 -0
- sage/libs/mpfr/types.pxd +26 -0
- sage/libs/mpmath/__init__.py +1 -0
- sage/libs/mpmath/all.py +27 -0
- sage/libs/mpmath/all__sagemath_modules.py +1 -0
- sage/libs/mpmath/utils.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/libs/mpmath/utils.pxd +4 -0
- sage/libs/mpmath/utils.pyx +319 -0
- sage/matrix/action.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/action.pxd +26 -0
- sage/matrix/action.pyx +596 -0
- sage/matrix/all.py +9 -0
- sage/matrix/args.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/args.pxd +144 -0
- sage/matrix/args.pyx +1668 -0
- sage/matrix/benchmark.py +1258 -0
- sage/matrix/berlekamp_massey.py +95 -0
- sage/matrix/compute_J_ideal.py +926 -0
- sage/matrix/constructor.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_cdv.pxd +4 -0
- sage/matrix/matrix_cdv.pyx +93 -0
- sage/matrix/matrix_complex_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_complex_double_dense.pxd +5 -0
- sage/matrix/matrix_complex_double_dense.pyx +98 -0
- sage/matrix/matrix_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_dense.pxd +5 -0
- sage/matrix/matrix_dense.pyx +343 -0
- sage/matrix/matrix_domain_dense.pxd +5 -0
- sage/matrix/matrix_domain_sparse.pxd +5 -0
- sage/matrix/matrix_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_double_dense.pxd +7 -0
- sage/matrix/matrix_double_dense.pyx +3906 -0
- sage/matrix/matrix_double_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_double_sparse.pxd +6 -0
- sage/matrix/matrix_double_sparse.pyx +248 -0
- sage/matrix/matrix_generic_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_generic_dense.pxd +7 -0
- sage/matrix/matrix_generic_dense.pyx +354 -0
- sage/matrix/matrix_generic_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_generic_sparse.pxd +7 -0
- sage/matrix/matrix_generic_sparse.pyx +461 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pxd +5 -0
- sage/matrix/matrix_laurent_mpolynomial_dense.pyx +115 -0
- sage/matrix/matrix_misc.py +313 -0
- sage/matrix/matrix_numpy_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_numpy_dense.pxd +14 -0
- sage/matrix/matrix_numpy_dense.pyx +450 -0
- sage/matrix/matrix_numpy_integer_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_numpy_integer_dense.pxd +7 -0
- sage/matrix/matrix_numpy_integer_dense.pyx +59 -0
- sage/matrix/matrix_polynomial_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_polynomial_dense.pxd +5 -0
- sage/matrix/matrix_polynomial_dense.pyx +5341 -0
- sage/matrix/matrix_real_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_real_double_dense.pxd +7 -0
- sage/matrix/matrix_real_double_dense.pyx +122 -0
- sage/matrix/matrix_space.py +2848 -0
- sage/matrix/matrix_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_sparse.pxd +5 -0
- sage/matrix/matrix_sparse.pyx +1222 -0
- sage/matrix/matrix_window.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/matrix_window.pxd +37 -0
- sage/matrix/matrix_window.pyx +242 -0
- sage/matrix/misc_mpfr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/misc_mpfr.pyx +80 -0
- sage/matrix/operation_table.py +1182 -0
- sage/matrix/special.py +3666 -0
- sage/matrix/strassen.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matrix/strassen.pyx +851 -0
- sage/matrix/symplectic_basis.py +541 -0
- sage/matrix/template.pxd +6 -0
- sage/matrix/tests.py +71 -0
- sage/matroids/advanced.py +77 -0
- sage/matroids/all.py +13 -0
- sage/matroids/basis_exchange_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/basis_exchange_matroid.pxd +96 -0
- sage/matroids/basis_exchange_matroid.pyx +2344 -0
- sage/matroids/basis_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/basis_matroid.pxd +45 -0
- sage/matroids/basis_matroid.pyx +1217 -0
- sage/matroids/catalog.py +44 -0
- sage/matroids/chow_ring.py +473 -0
- sage/matroids/chow_ring_ideal.py +849 -0
- sage/matroids/circuit_closures_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/circuit_closures_matroid.pxd +16 -0
- sage/matroids/circuit_closures_matroid.pyx +559 -0
- sage/matroids/circuits_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/circuits_matroid.pxd +38 -0
- sage/matroids/circuits_matroid.pyx +947 -0
- sage/matroids/constructor.py +1086 -0
- sage/matroids/database_collections.py +365 -0
- sage/matroids/database_matroids.py +5338 -0
- sage/matroids/dual_matroid.py +583 -0
- sage/matroids/extension.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/flats_matroid.pxd +28 -0
- sage/matroids/flats_matroid.pyx +715 -0
- sage/matroids/gammoid.py +600 -0
- sage/matroids/graphic_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/graphic_matroid.pxd +39 -0
- sage/matroids/graphic_matroid.pyx +2024 -0
- sage/matroids/lean_matrix.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/lean_matrix.pxd +126 -0
- sage/matroids/lean_matrix.pyx +3667 -0
- sage/matroids/linear_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/linear_matroid.pxd +180 -0
- sage/matroids/linear_matroid.pyx +6649 -0
- sage/matroids/matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/matroid.pxd +243 -0
- sage/matroids/matroid.pyx +8759 -0
- sage/matroids/matroids_catalog.py +190 -0
- sage/matroids/matroids_plot_helpers.py +890 -0
- sage/matroids/minor_matroid.py +480 -0
- sage/matroids/minorfix.h +9 -0
- sage/matroids/named_matroids.py +5 -0
- sage/matroids/rank_matroid.py +268 -0
- sage/matroids/set_system.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/set_system.pxd +38 -0
- sage/matroids/set_system.pyx +800 -0
- sage/matroids/transversal_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/transversal_matroid.pxd +14 -0
- sage/matroids/transversal_matroid.pyx +893 -0
- sage/matroids/union_matroid.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/union_matroid.pxd +20 -0
- sage/matroids/union_matroid.pyx +331 -0
- sage/matroids/unpickling.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/matroids/unpickling.pyx +843 -0
- sage/matroids/utilities.py +809 -0
- sage/misc/all__sagemath_modules.py +20 -0
- sage/misc/c3.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/misc/c3.pyx +238 -0
- sage/misc/compat.py +87 -0
- sage/misc/element_with_label.py +173 -0
- sage/misc/func_persist.py +79 -0
- sage/misc/pickle_old.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/misc/pickle_old.pyx +19 -0
- sage/misc/proof.py +7 -0
- sage/misc/replace_dot_all.py +472 -0
- sage/misc/sagedoc_conf.py +168 -0
- sage/misc/sphinxify.py +167 -0
- sage/misc/test_class_pickling.py +85 -0
- sage/modules/all.py +42 -0
- sage/modules/complex_double_vector.py +25 -0
- sage/modules/diamond_cutting.py +380 -0
- sage/modules/fg_pid/all.py +1 -0
- sage/modules/fg_pid/fgp_element.py +456 -0
- sage/modules/fg_pid/fgp_module.py +2091 -0
- sage/modules/fg_pid/fgp_morphism.py +550 -0
- sage/modules/filtered_vector_space.py +1271 -0
- sage/modules/finite_submodule_iter.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/finite_submodule_iter.pxd +27 -0
- sage/modules/finite_submodule_iter.pyx +452 -0
- sage/modules/fp_graded/all.py +1 -0
- sage/modules/fp_graded/element.py +346 -0
- sage/modules/fp_graded/free_element.py +298 -0
- sage/modules/fp_graded/free_homspace.py +53 -0
- sage/modules/fp_graded/free_module.py +1060 -0
- sage/modules/fp_graded/free_morphism.py +217 -0
- sage/modules/fp_graded/homspace.py +563 -0
- sage/modules/fp_graded/module.py +1340 -0
- sage/modules/fp_graded/morphism.py +1990 -0
- sage/modules/fp_graded/steenrod/all.py +1 -0
- sage/modules/fp_graded/steenrod/homspace.py +65 -0
- sage/modules/fp_graded/steenrod/module.py +477 -0
- sage/modules/fp_graded/steenrod/morphism.py +404 -0
- sage/modules/fp_graded/steenrod/profile.py +241 -0
- sage/modules/free_module.py +8447 -0
- sage/modules/free_module_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/free_module_element.pxd +22 -0
- sage/modules/free_module_element.pyx +5445 -0
- sage/modules/free_module_homspace.py +369 -0
- sage/modules/free_module_integer.py +896 -0
- sage/modules/free_module_morphism.py +823 -0
- sage/modules/free_module_pseudohomspace.py +352 -0
- sage/modules/free_module_pseudomorphism.py +578 -0
- sage/modules/free_quadratic_module.py +1706 -0
- sage/modules/free_quadratic_module_integer_symmetric.py +1790 -0
- sage/modules/matrix_morphism.py +1745 -0
- sage/modules/misc.py +103 -0
- sage/modules/module_functors.py +192 -0
- sage/modules/multi_filtered_vector_space.py +719 -0
- sage/modules/ore_module.py +2208 -0
- sage/modules/ore_module_element.py +178 -0
- sage/modules/ore_module_homspace.py +147 -0
- sage/modules/ore_module_morphism.py +968 -0
- sage/modules/quotient_module.py +699 -0
- sage/modules/real_double_vector.py +22 -0
- sage/modules/submodule.py +255 -0
- sage/modules/tensor_operations.py +567 -0
- sage/modules/torsion_quadratic_module.py +1352 -0
- sage/modules/tutorial_free_modules.py +248 -0
- sage/modules/vector_complex_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_complex_double_dense.pxd +6 -0
- sage/modules/vector_complex_double_dense.pyx +117 -0
- sage/modules/vector_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_double_dense.pxd +6 -0
- sage/modules/vector_double_dense.pyx +604 -0
- sage/modules/vector_integer_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_integer_dense.pxd +15 -0
- sage/modules/vector_integer_dense.pyx +361 -0
- sage/modules/vector_integer_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_integer_sparse.pxd +29 -0
- sage/modules/vector_integer_sparse.pyx +406 -0
- sage/modules/vector_modn_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_modn_dense.pxd +12 -0
- sage/modules/vector_modn_dense.pyx +394 -0
- sage/modules/vector_modn_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_modn_sparse.pxd +21 -0
- sage/modules/vector_modn_sparse.pyx +298 -0
- sage/modules/vector_numpy_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_numpy_dense.pxd +15 -0
- sage/modules/vector_numpy_dense.pyx +304 -0
- sage/modules/vector_numpy_integer_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_numpy_integer_dense.pxd +7 -0
- sage/modules/vector_numpy_integer_dense.pyx +54 -0
- sage/modules/vector_rational_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_rational_dense.pxd +15 -0
- sage/modules/vector_rational_dense.pyx +387 -0
- sage/modules/vector_rational_sparse.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_rational_sparse.pxd +30 -0
- sage/modules/vector_rational_sparse.pyx +413 -0
- sage/modules/vector_real_double_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/vector_real_double_dense.pxd +6 -0
- sage/modules/vector_real_double_dense.pyx +126 -0
- sage/modules/vector_space_homspace.py +430 -0
- sage/modules/vector_space_morphism.py +989 -0
- sage/modules/with_basis/all.py +15 -0
- sage/modules/with_basis/cell_module.py +494 -0
- sage/modules/with_basis/indexed_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/modules/with_basis/indexed_element.pxd +13 -0
- sage/modules/with_basis/indexed_element.pyx +1058 -0
- sage/modules/with_basis/invariant.py +1075 -0
- sage/modules/with_basis/morphism.py +1636 -0
- sage/modules/with_basis/representation.py +2939 -0
- sage/modules/with_basis/subquotient.py +685 -0
- sage/numerical/all__sagemath_modules.py +6 -0
- sage/numerical/gauss_legendre.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/numerical/gauss_legendre.pyx +381 -0
- sage/numerical/optimize.py +910 -0
- sage/probability/all.py +10 -0
- sage/probability/probability_distribution.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/probability/probability_distribution.pyx +1242 -0
- sage/probability/random_variable.py +411 -0
- sage/quadratic_forms/all.py +4 -0
- sage/quadratic_forms/all__sagemath_modules.py +15 -0
- sage/quadratic_forms/binary_qf.py +2042 -0
- sage/quadratic_forms/bqf_class_group.py +748 -0
- sage/quadratic_forms/constructions.py +93 -0
- sage/quadratic_forms/count_local_2.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/quadratic_forms/count_local_2.pyx +365 -0
- sage/quadratic_forms/extras.py +195 -0
- sage/quadratic_forms/quadratic_form.py +1753 -0
- sage/quadratic_forms/quadratic_form__count_local_2.py +221 -0
- sage/quadratic_forms/quadratic_form__equivalence_testing.py +708 -0
- sage/quadratic_forms/quadratic_form__evaluate.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/quadratic_forms/quadratic_form__evaluate.pyx +139 -0
- sage/quadratic_forms/quadratic_form__local_density_congruence.py +977 -0
- sage/quadratic_forms/quadratic_form__local_field_invariants.py +1072 -0
- sage/quadratic_forms/quadratic_form__neighbors.py +424 -0
- sage/quadratic_forms/quadratic_form__reduction_theory.py +488 -0
- sage/quadratic_forms/quadratic_form__split_local_covering.py +416 -0
- sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +657 -0
- sage/quadratic_forms/quadratic_form__theta.py +352 -0
- sage/quadratic_forms/quadratic_form__variable_substitutions.py +370 -0
- sage/quadratic_forms/random_quadraticform.py +209 -0
- sage/quadratic_forms/ternary.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/quadratic_forms/ternary.pyx +1154 -0
- sage/quadratic_forms/ternary_qf.py +2027 -0
- sage/rings/all__sagemath_modules.py +28 -0
- sage/rings/asymptotic/all__sagemath_modules.py +1 -0
- sage/rings/asymptotic/misc.py +1252 -0
- sage/rings/cc.py +4 -0
- sage/rings/cfinite_sequence.py +1306 -0
- sage/rings/complex_conversion.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_conversion.pxd +8 -0
- sage/rings/complex_conversion.pyx +23 -0
- sage/rings/complex_double.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_double.pxd +21 -0
- sage/rings/complex_double.pyx +2654 -0
- sage/rings/complex_mpc.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_mpc.pxd +21 -0
- sage/rings/complex_mpc.pyx +2576 -0
- sage/rings/complex_mpfr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/complex_mpfr.pxd +18 -0
- sage/rings/complex_mpfr.pyx +3602 -0
- sage/rings/derivation.py +2334 -0
- sage/rings/finite_rings/all__sagemath_modules.py +1 -0
- sage/rings/finite_rings/maps_finite_field.py +191 -0
- sage/rings/function_field/all__sagemath_modules.py +8 -0
- sage/rings/function_field/derivations.py +102 -0
- sage/rings/function_field/derivations_rational.py +132 -0
- sage/rings/function_field/differential.py +853 -0
- sage/rings/function_field/divisor.py +1107 -0
- sage/rings/function_field/drinfeld_modules/action.py +199 -0
- sage/rings/function_field/drinfeld_modules/all.py +1 -0
- sage/rings/function_field/drinfeld_modules/charzero_drinfeld_module.py +673 -0
- sage/rings/function_field/drinfeld_modules/drinfeld_module.py +2087 -0
- sage/rings/function_field/drinfeld_modules/finite_drinfeld_module.py +1131 -0
- sage/rings/function_field/drinfeld_modules/homset.py +420 -0
- sage/rings/function_field/drinfeld_modules/morphism.py +820 -0
- sage/rings/function_field/hermite_form_polynomial.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/function_field/khuri_makdisi.pyx +935 -0
- sage/rings/invariants/all.py +4 -0
- sage/rings/invariants/invariant_theory.py +4597 -0
- sage/rings/invariants/reconstruction.py +395 -0
- sage/rings/polynomial/all__sagemath_modules.py +17 -0
- sage/rings/polynomial/integer_valued_polynomials.py +1230 -0
- sage/rings/polynomial/laurent_polynomial_mpair.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pxd +15 -0
- sage/rings/polynomial/laurent_polynomial_mpair.pyx +2023 -0
- sage/rings/polynomial/ore_function_element.py +952 -0
- sage/rings/polynomial/ore_function_field.py +1028 -0
- sage/rings/polynomial/ore_polynomial_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/ore_polynomial_element.pxd +48 -0
- sage/rings/polynomial/ore_polynomial_element.pyx +3145 -0
- sage/rings/polynomial/ore_polynomial_ring.py +1334 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +788 -0
- sage/rings/polynomial/q_integer_valued_polynomials.py +1264 -0
- sage/rings/polynomial/skew_polynomial_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_element.pxd +9 -0
- sage/rings/polynomial/skew_polynomial_element.pyx +684 -0
- sage/rings/polynomial/skew_polynomial_finite_field.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pxd +19 -0
- sage/rings/polynomial/skew_polynomial_finite_field.pyx +1093 -0
- sage/rings/polynomial/skew_polynomial_finite_order.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pxd +10 -0
- sage/rings/polynomial/skew_polynomial_finite_order.pyx +567 -0
- sage/rings/polynomial/skew_polynomial_ring.py +908 -0
- sage/rings/real_double_element_gsl.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/real_double_element_gsl.pxd +8 -0
- sage/rings/real_double_element_gsl.pyx +794 -0
- sage/rings/real_field.py +58 -0
- sage/rings/real_mpfr.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/real_mpfr.pxd +29 -0
- sage/rings/real_mpfr.pyx +6122 -0
- sage/rings/ring_extension.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension.pxd +42 -0
- sage/rings/ring_extension.pyx +2779 -0
- sage/rings/ring_extension_conversion.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension_conversion.pxd +16 -0
- sage/rings/ring_extension_conversion.pyx +462 -0
- sage/rings/ring_extension_element.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension_element.pxd +21 -0
- sage/rings/ring_extension_element.pyx +1635 -0
- sage/rings/ring_extension_homset.py +64 -0
- sage/rings/ring_extension_morphism.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/rings/ring_extension_morphism.pxd +35 -0
- sage/rings/ring_extension_morphism.pyx +920 -0
- sage/schemes/all__sagemath_modules.py +1 -0
- sage/schemes/projective/all__sagemath_modules.py +1 -0
- sage/schemes/projective/coherent_sheaf.py +300 -0
- sage/schemes/projective/cohomology.py +510 -0
- sage/stats/all.py +15 -0
- sage/stats/basic_stats.py +489 -0
- sage/stats/distributions/all.py +7 -0
- sage/stats/distributions/catalog.py +34 -0
- sage/stats/distributions/dgs.h +50 -0
- sage/stats/distributions/dgs.pxd +111 -0
- sage/stats/distributions/dgs_bern.h +400 -0
- sage/stats/distributions/dgs_gauss.h +614 -0
- sage/stats/distributions/dgs_misc.h +104 -0
- sage/stats/distributions/discrete_gaussian_integer.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/distributions/discrete_gaussian_integer.pxd +14 -0
- sage/stats/distributions/discrete_gaussian_integer.pyx +498 -0
- sage/stats/distributions/discrete_gaussian_lattice.py +908 -0
- sage/stats/distributions/discrete_gaussian_polynomial.py +141 -0
- sage/stats/hmm/all.py +15 -0
- sage/stats/hmm/chmm.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/distributions.pxd +29 -0
- sage/stats/hmm/distributions.pyx +531 -0
- sage/stats/hmm/hmm.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/hmm.pxd +17 -0
- sage/stats/hmm/hmm.pyx +1388 -0
- sage/stats/hmm/util.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/hmm/util.pxd +7 -0
- sage/stats/hmm/util.pyx +165 -0
- sage/stats/intlist.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/intlist.pxd +14 -0
- sage/stats/intlist.pyx +588 -0
- sage/stats/r.py +49 -0
- sage/stats/time_series.cpython-314-x86_64-linux-gnu.so +0 -0
- sage/stats/time_series.pxd +6 -0
- sage/stats/time_series.pyx +2546 -0
- sage/tensor/all.py +2 -0
- sage/tensor/modules/all.py +8 -0
- sage/tensor/modules/alternating_contr_tensor.py +761 -0
- sage/tensor/modules/comp.py +5598 -0
- sage/tensor/modules/ext_pow_free_module.py +824 -0
- sage/tensor/modules/finite_rank_free_module.py +3589 -0
- sage/tensor/modules/format_utilities.py +333 -0
- sage/tensor/modules/free_module_alt_form.py +858 -0
- sage/tensor/modules/free_module_automorphism.py +1207 -0
- sage/tensor/modules/free_module_basis.py +1074 -0
- sage/tensor/modules/free_module_element.py +284 -0
- sage/tensor/modules/free_module_homset.py +652 -0
- sage/tensor/modules/free_module_linear_group.py +564 -0
- sage/tensor/modules/free_module_morphism.py +1581 -0
- sage/tensor/modules/free_module_tensor.py +3289 -0
- sage/tensor/modules/reflexive_module.py +386 -0
- sage/tensor/modules/tensor_free_module.py +780 -0
- sage/tensor/modules/tensor_free_submodule.py +538 -0
- sage/tensor/modules/tensor_free_submodule_basis.py +140 -0
- sage/tensor/modules/tensor_with_indices.py +1043 -0
|
@@ -0,0 +1,1352 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
# sage.doctest: needs sage.libs.pari
|
|
3
|
+
r"""
|
|
4
|
+
Finite `\ZZ`-modules with bilinear and quadratic forms
|
|
5
|
+
|
|
6
|
+
AUTHORS:
|
|
7
|
+
|
|
8
|
+
- Simon Brandhorst (2017-09): First created
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
# Copyright (C) 2017 Simon Brandhorst <sbrandhorst@web.de>
|
|
13
|
+
#
|
|
14
|
+
# This program is free software: you can redistribute it and/or modify
|
|
15
|
+
# it under the terms of the GNU General Public License as published by
|
|
16
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
17
|
+
# (at your option) any later version.
|
|
18
|
+
# https://www.gnu.org/licenses/
|
|
19
|
+
# ****************************************************************************
|
|
20
|
+
|
|
21
|
+
from sage.modules.fg_pid.fgp_module import FGP_Module_class
|
|
22
|
+
from sage.modules.fg_pid.fgp_element import FGP_Element
|
|
23
|
+
from sage.modules.free_quadratic_module import FreeQuadraticModule
|
|
24
|
+
from sage.arith.misc import gcd
|
|
25
|
+
from sage.rings.integer_ring import ZZ
|
|
26
|
+
from sage.rings.rational_field import QQ
|
|
27
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
28
|
+
from sage.groups.additive_abelian.qmodnz import QmodnZ
|
|
29
|
+
from sage.matrix.constructor import matrix
|
|
30
|
+
from sage.matrix.special import diagonal_matrix
|
|
31
|
+
from sage.misc.cachefunc import cached_method
|
|
32
|
+
from sage.rings.finite_rings.integer_mod import mod
|
|
33
|
+
from sage.arith.misc import legendre_symbol
|
|
34
|
+
from sage.structure.unique_representation import CachedRepresentation
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def TorsionQuadraticForm(q):
|
|
38
|
+
r"""
|
|
39
|
+
Create a torsion quadratic form module from a rational matrix.
|
|
40
|
+
|
|
41
|
+
The resulting quadratic form takes values in `\QQ / \ZZ`
|
|
42
|
+
or `\QQ / 2 \ZZ` (depending on ``q``).
|
|
43
|
+
If it takes values modulo `2`, then it is non-degenerate.
|
|
44
|
+
In any case the bilinear form is non-degenerate.
|
|
45
|
+
|
|
46
|
+
INPUT:
|
|
47
|
+
|
|
48
|
+
- ``q`` -- a symmetric rational matrix
|
|
49
|
+
|
|
50
|
+
EXAMPLES::
|
|
51
|
+
|
|
52
|
+
sage: q1 = Matrix(QQ, 2, [1,1/2,1/2,1])
|
|
53
|
+
sage: TorsionQuadraticForm(q1)
|
|
54
|
+
Finite quadratic module over Integer Ring with invariants (2, 2)
|
|
55
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
56
|
+
[ 1 1/2]
|
|
57
|
+
[1/2 1]
|
|
58
|
+
|
|
59
|
+
In the following example the quadratic form is degenerate.
|
|
60
|
+
But the bilinear form is still non-degenerate::
|
|
61
|
+
|
|
62
|
+
sage: q2 = diagonal_matrix(QQ, [1/4,1/3])
|
|
63
|
+
sage: TorsionQuadraticForm(q2)
|
|
64
|
+
Finite quadratic module over Integer Ring with invariants (12,)
|
|
65
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
66
|
+
[7/12]
|
|
67
|
+
|
|
68
|
+
TESTS::
|
|
69
|
+
|
|
70
|
+
sage: TorsionQuadraticForm(matrix.diagonal([3/4,3/8,3/8]))
|
|
71
|
+
Finite quadratic module over Integer Ring with invariants (4, 8, 8)
|
|
72
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
73
|
+
[3/4 0 0]
|
|
74
|
+
[ 0 3/8 0]
|
|
75
|
+
[ 0 0 3/8]
|
|
76
|
+
"""
|
|
77
|
+
q = matrix(QQ, q)
|
|
78
|
+
if q.nrows() != q.ncols():
|
|
79
|
+
raise ValueError("the input must be a square matrix")
|
|
80
|
+
if q != q.transpose():
|
|
81
|
+
raise ValueError("the input must be a symmetric matrix")
|
|
82
|
+
|
|
83
|
+
Q, d = q._clear_denom()
|
|
84
|
+
S, U, V = Q.smith_form()
|
|
85
|
+
D = U * q * V
|
|
86
|
+
Q = FreeQuadraticModule(ZZ, q.ncols(), inner_product_matrix=d**2 * q)
|
|
87
|
+
denoms = [D[i, i].denominator() for i in range(D.ncols())]
|
|
88
|
+
rels = Q.span(diagonal_matrix(ZZ, denoms) * U)
|
|
89
|
+
return TorsionQuadraticModule((1/d)*Q, (1/d)*rels, modulus=1)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class TorsionQuadraticModuleElement(FGP_Element):
|
|
93
|
+
r"""
|
|
94
|
+
An element of a torsion quadratic module.
|
|
95
|
+
|
|
96
|
+
INPUT:
|
|
97
|
+
|
|
98
|
+
- ``parent`` -- parent
|
|
99
|
+
|
|
100
|
+
- ``x`` -- element of ``parent.V()``
|
|
101
|
+
|
|
102
|
+
- ``check`` -- boolean (default: ``True``)
|
|
103
|
+
|
|
104
|
+
TESTS::
|
|
105
|
+
|
|
106
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
107
|
+
sage: T = TorsionQuadraticModule(ZZ^3, 6*ZZ^3)
|
|
108
|
+
sage: loads(dumps(T)) == T
|
|
109
|
+
True
|
|
110
|
+
sage: t = T.gen(0)
|
|
111
|
+
sage: loads(dumps(t)) == t
|
|
112
|
+
True
|
|
113
|
+
|
|
114
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
115
|
+
sage: V = span([[1/2,1,1], [3/2,2,1], [0,0,1]], ZZ)
|
|
116
|
+
sage: b = V.basis()
|
|
117
|
+
sage: W = V.span([2*b[0] + 4*b[1], 9*b[0] + 12*b[1], 4*b[2]])
|
|
118
|
+
sage: Q = TorsionQuadraticModule(V, W)
|
|
119
|
+
sage: x = Q(b[0] - b[1])
|
|
120
|
+
sage: TestSuite(x).run()
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
def _mul_(self, other):
|
|
124
|
+
r"""
|
|
125
|
+
Compute the inner product of two elements.
|
|
126
|
+
|
|
127
|
+
OUTPUT:
|
|
128
|
+
|
|
129
|
+
- an element of `\QQ / m\ZZ` with `m\ZZ = (V, W)`
|
|
130
|
+
|
|
131
|
+
EXAMPLES::
|
|
132
|
+
|
|
133
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
134
|
+
sage: V = (1/2)*ZZ^2; W = ZZ^2
|
|
135
|
+
sage: T = TorsionQuadraticModule(V, W)
|
|
136
|
+
sage: g = T.gens()
|
|
137
|
+
sage: x = g[0]; x
|
|
138
|
+
(1, 0)
|
|
139
|
+
sage: y = g[0] + g[1]
|
|
140
|
+
sage: x*y
|
|
141
|
+
1/4
|
|
142
|
+
|
|
143
|
+
The inner product has further aliases::
|
|
144
|
+
|
|
145
|
+
sage: x.inner_product(y)
|
|
146
|
+
1/4
|
|
147
|
+
sage: x.b(y)
|
|
148
|
+
1/4
|
|
149
|
+
"""
|
|
150
|
+
value_module = self.parent().value_module()
|
|
151
|
+
return value_module(self.lift().inner_product(other.lift()))
|
|
152
|
+
|
|
153
|
+
inner_product = _mul_
|
|
154
|
+
b = _mul_
|
|
155
|
+
|
|
156
|
+
def quadratic_product(self):
|
|
157
|
+
r"""
|
|
158
|
+
Compute the quadratic product of ``self``.
|
|
159
|
+
|
|
160
|
+
OUTPUT:
|
|
161
|
+
|
|
162
|
+
- an element of `\QQ / n\ZZ` where `n\ZZ = 2(V,W) +
|
|
163
|
+
\ZZ \{ (w,w) | w \in W \}`
|
|
164
|
+
|
|
165
|
+
EXAMPLES::
|
|
166
|
+
|
|
167
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
168
|
+
sage: W = FreeQuadraticModule(ZZ, 2, 2*matrix.identity(2))
|
|
169
|
+
sage: V = (1/2) * W
|
|
170
|
+
sage: T = TorsionQuadraticModule(V, W)
|
|
171
|
+
sage: x = T.gen(0)
|
|
172
|
+
sage: x
|
|
173
|
+
(1, 0)
|
|
174
|
+
sage: x.quadratic_product()
|
|
175
|
+
1/2
|
|
176
|
+
sage: x.quadratic_product().parent()
|
|
177
|
+
Q/2Z
|
|
178
|
+
sage: x*x
|
|
179
|
+
1/2
|
|
180
|
+
sage: (x*x).parent()
|
|
181
|
+
Q/Z
|
|
182
|
+
"""
|
|
183
|
+
value_module_qf = self.parent().value_module_qf()
|
|
184
|
+
lift = self.lift()
|
|
185
|
+
return value_module_qf(lift.inner_product(lift))
|
|
186
|
+
|
|
187
|
+
q = quadratic_product
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class TorsionQuadraticModule(FGP_Module_class, CachedRepresentation):
|
|
191
|
+
r"""
|
|
192
|
+
Finite quotients with a bilinear and a quadratic form.
|
|
193
|
+
|
|
194
|
+
Let `V` be a symmetric :class:`FreeQuadraticModule` and `W \subseteq V` a
|
|
195
|
+
submodule of the same rank as `V`. The quotient `V / W` is a torsion
|
|
196
|
+
quadratic module. It inherits a bilinear form `b` and a quadratic
|
|
197
|
+
form `q`.
|
|
198
|
+
|
|
199
|
+
`b: V \times V \to \QQ / m\ZZ`, where `m\ZZ = (V,W)`
|
|
200
|
+
and `b(x,y) = (x,y) + m\ZZ`
|
|
201
|
+
|
|
202
|
+
`q: V \to \QQ / n\ZZ`, where `n\ZZ = 2(V,W) + \ZZ \{ (w,w) | w \in W \}`
|
|
203
|
+
|
|
204
|
+
INPUT:
|
|
205
|
+
|
|
206
|
+
- ``V`` -- a :class:`FreeModule` with a symmetric inner product matrix
|
|
207
|
+
|
|
208
|
+
- ``W`` -- a submodule of ``V`` of the same rank as ``V``
|
|
209
|
+
|
|
210
|
+
- ``check`` -- boolean (default: ``True``)
|
|
211
|
+
|
|
212
|
+
- ``modulus`` -- a rational number dividing `m` (default: `m`);
|
|
213
|
+
the inner product `b` is defined in `\QQ /` ``modulus`` `\ZZ`
|
|
214
|
+
|
|
215
|
+
- ``modulus_qf`` -- a rational number dividing `n` (default: `n`);
|
|
216
|
+
the quadratic form `q` is defined in `\QQ /` ``modulus_qf`` `\ZZ`
|
|
217
|
+
|
|
218
|
+
EXAMPLES::
|
|
219
|
+
|
|
220
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
221
|
+
sage: V = FreeModule(ZZ, 3)
|
|
222
|
+
sage: T = TorsionQuadraticModule(V, 5*V); T
|
|
223
|
+
Finite quadratic module over Integer Ring with invariants (5, 5, 5)
|
|
224
|
+
Gram matrix of the quadratic form with values in Q/5Z:
|
|
225
|
+
[1 0 0]
|
|
226
|
+
[0 1 0]
|
|
227
|
+
[0 0 1]
|
|
228
|
+
"""
|
|
229
|
+
Element = TorsionQuadraticModuleElement
|
|
230
|
+
|
|
231
|
+
@staticmethod
|
|
232
|
+
def __classcall__(cls, V, W, gens=None, modulus=None, modulus_qf=None, check=True):
|
|
233
|
+
r"""
|
|
234
|
+
Return a :class:`TorsionQuadraticModule`.
|
|
235
|
+
|
|
236
|
+
This method does the preprocessing for :meth:`sage.structure.CachedRepresentation`.
|
|
237
|
+
|
|
238
|
+
TESTS::
|
|
239
|
+
|
|
240
|
+
sage: q = matrix([1/2])
|
|
241
|
+
sage: D1 = TorsionQuadraticForm(q)
|
|
242
|
+
sage: D2 = TorsionQuadraticForm(q)
|
|
243
|
+
sage: D1 is D2
|
|
244
|
+
True
|
|
245
|
+
"""
|
|
246
|
+
if check:
|
|
247
|
+
if V.rank() != W.rank():
|
|
248
|
+
raise ValueError("modules must be of the same rank")
|
|
249
|
+
if V.base_ring() is not ZZ:
|
|
250
|
+
raise NotImplementedError("only currently implemented over ZZ")
|
|
251
|
+
if V.inner_product_matrix() != V.inner_product_matrix().transpose():
|
|
252
|
+
raise ValueError("the cover must have a symmetric inner product")
|
|
253
|
+
|
|
254
|
+
if gens is not None and V.span(gens) + W != V:
|
|
255
|
+
raise ValueError("provided gens do not generate the quotient")
|
|
256
|
+
|
|
257
|
+
# compute the modulus - this may be expensive
|
|
258
|
+
if modulus is None or check:
|
|
259
|
+
# The inner product of two elements `b(v1+W,v2+W)`
|
|
260
|
+
# is defined `mod (V,W)`
|
|
261
|
+
num = V.basis_matrix() * V.inner_product_matrix() * W.basis_matrix().T
|
|
262
|
+
max_modulus = gcd(num.list())
|
|
263
|
+
|
|
264
|
+
if modulus is None:
|
|
265
|
+
modulus = max_modulus
|
|
266
|
+
elif check and max_modulus / modulus not in V.base_ring():
|
|
267
|
+
raise ValueError("the modulus must divide (V, W)")
|
|
268
|
+
|
|
269
|
+
if modulus_qf is None or check:
|
|
270
|
+
# The quadratic_product of an element `q(v+W)` is defined
|
|
271
|
+
# `\mod 2(V,W) + ZZ\{ (w,w) | w in w\}`
|
|
272
|
+
norm = gcd(W.gram_matrix().diagonal())
|
|
273
|
+
max_modulus_qf = gcd(norm, 2 * modulus)
|
|
274
|
+
|
|
275
|
+
if modulus_qf is None:
|
|
276
|
+
modulus_qf = max_modulus_qf
|
|
277
|
+
elif check and max_modulus_qf / modulus_qf not in V.base_ring():
|
|
278
|
+
raise ValueError("the modulus_qf must divide (V, W)")
|
|
279
|
+
return super().__classcall__(cls, V, W, gens, modulus, modulus_qf)
|
|
280
|
+
|
|
281
|
+
def __init__(self, V, W, gens, modulus, modulus_qf):
|
|
282
|
+
r"""
|
|
283
|
+
Initialize ``self``.
|
|
284
|
+
|
|
285
|
+
TESTS::
|
|
286
|
+
|
|
287
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
288
|
+
sage: T = TorsionQuadraticModule(ZZ^3, 6*ZZ^3)
|
|
289
|
+
sage: TestSuite(T).run()
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
FGP_Module_class.__init__(self, V, W, check=True)
|
|
293
|
+
if gens is not None:
|
|
294
|
+
self._gens_user = tuple(self(g) for g in gens)
|
|
295
|
+
else:
|
|
296
|
+
# this is taken care of in the .gens method
|
|
297
|
+
# we do not want this at initialization
|
|
298
|
+
self._gens_user = None
|
|
299
|
+
self._modulus = modulus
|
|
300
|
+
self._modulus_qf = modulus_qf
|
|
301
|
+
|
|
302
|
+
def _repr_(self):
|
|
303
|
+
r"""
|
|
304
|
+
Return a string representation of ``self``.
|
|
305
|
+
|
|
306
|
+
EXAMPLES::
|
|
307
|
+
|
|
308
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
309
|
+
sage: V = FreeModule(ZZ, 3)
|
|
310
|
+
sage: T = TorsionQuadraticModule(V, 5*V, modulus=1)
|
|
311
|
+
sage: T
|
|
312
|
+
Finite quadratic module over Integer Ring with invariants (5, 5, 5)
|
|
313
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
314
|
+
[0 0 0]
|
|
315
|
+
[0 0 0]
|
|
316
|
+
[0 0 0]
|
|
317
|
+
"""
|
|
318
|
+
return ("Finite quadratic module over %s with invariants %s\n"
|
|
319
|
+
% (self.base_ring(), self.invariants()) +
|
|
320
|
+
"Gram matrix of the quadratic form with values in %r:\n%r"
|
|
321
|
+
% (self.value_module_qf(), self.gram_matrix_quadratic()))
|
|
322
|
+
|
|
323
|
+
def _module_constructor(self, V, W, check=False):
|
|
324
|
+
r"""
|
|
325
|
+
Construct a torsion quadratic module ``V / W``.
|
|
326
|
+
|
|
327
|
+
INPUT:
|
|
328
|
+
|
|
329
|
+
- ``V`` -- a module
|
|
330
|
+
|
|
331
|
+
- ``W`` -- a submodule of ``V`` over the same base ring
|
|
332
|
+
|
|
333
|
+
- ``check`` -- boolean (default: ``False``)
|
|
334
|
+
|
|
335
|
+
* if ``False``, then the value modulus is inherited from ``self``
|
|
336
|
+
* if ``True``, it figures it out on its own. But that is expensive
|
|
337
|
+
|
|
338
|
+
OUTPUT: the quotient ``V / W`` as a :class:`TorsionQuadraticModule`
|
|
339
|
+
|
|
340
|
+
EXAMPLES::
|
|
341
|
+
|
|
342
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
343
|
+
sage: V = span([[1/2,1,1], [3/2,2,1], [0,0,1]], ZZ)
|
|
344
|
+
sage: b = V.basis()
|
|
345
|
+
sage: W = V.span([2*b[0] + 4*b[1], 9*b[0] + 12*b[1], 4*b[2]])
|
|
346
|
+
sage: Q = TorsionQuadraticModule(V, W); Q
|
|
347
|
+
Finite quadratic module over Integer Ring with invariants (4, 12)
|
|
348
|
+
Gram matrix of the quadratic form with values in Q/(1/4)Z:
|
|
349
|
+
[0 0]
|
|
350
|
+
[0 0]
|
|
351
|
+
sage: Q._module_constructor(V, W)
|
|
352
|
+
Finite quadratic module over Integer Ring with invariants (4, 12)
|
|
353
|
+
Gram matrix of the quadratic form with values in Q/(1/4)Z:
|
|
354
|
+
[0 0]
|
|
355
|
+
[0 0]
|
|
356
|
+
"""
|
|
357
|
+
if check:
|
|
358
|
+
# figuring out the modulus can be expensive
|
|
359
|
+
return TorsionQuadraticModule(V, W, check=check)
|
|
360
|
+
else:
|
|
361
|
+
return TorsionQuadraticModule(V, W, check=check,
|
|
362
|
+
modulus=self._modulus,
|
|
363
|
+
modulus_qf=self._modulus_qf)
|
|
364
|
+
|
|
365
|
+
def all_submodules(self):
|
|
366
|
+
r"""
|
|
367
|
+
Return a list of all submodules of ``self``.
|
|
368
|
+
|
|
369
|
+
.. WARNING::
|
|
370
|
+
|
|
371
|
+
This method creates all submodules in memory. The number of submodules
|
|
372
|
+
grows rapidly with the number of generators. For example consider a
|
|
373
|
+
vector space of dimension `n` over a finite field of prime order `p`.
|
|
374
|
+
The number of subspaces is (very) roughly `p^{(n^2-n)/2}`.
|
|
375
|
+
|
|
376
|
+
EXAMPLES::
|
|
377
|
+
|
|
378
|
+
sage: D = IntegralLattice("D4").discriminant_group() # needs sage.combinat sage.graphs
|
|
379
|
+
sage: D.all_submodules() # needs sage.combinat sage.graphs
|
|
380
|
+
[Finite quadratic module over Integer Ring with invariants ()
|
|
381
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
382
|
+
[],
|
|
383
|
+
Finite quadratic module over Integer Ring with invariants (2,)
|
|
384
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
385
|
+
[1],
|
|
386
|
+
Finite quadratic module over Integer Ring with invariants (2,)
|
|
387
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
388
|
+
[1],
|
|
389
|
+
Finite quadratic module over Integer Ring with invariants (2,)
|
|
390
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
391
|
+
[1],
|
|
392
|
+
Finite quadratic module over Integer Ring with invariants (2, 2)
|
|
393
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
394
|
+
[ 1 1/2]
|
|
395
|
+
[1/2 1]]
|
|
396
|
+
"""
|
|
397
|
+
from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
|
|
398
|
+
invs = self.invariants()
|
|
399
|
+
# knows how to compute all subgroups
|
|
400
|
+
A = AbelianGroupGap(invs)
|
|
401
|
+
S = A.all_subgroups()
|
|
402
|
+
# over ZZ submodules and subgroups are the same thing.
|
|
403
|
+
submodules = []
|
|
404
|
+
for sub in S:
|
|
405
|
+
gen = [A(g).exponents() for g in sub.gens()]
|
|
406
|
+
gen = [self.linear_combination_of_smith_form_gens(g) for g in gen]
|
|
407
|
+
submodules.append(self.submodule(gen))
|
|
408
|
+
return submodules
|
|
409
|
+
|
|
410
|
+
@cached_method
|
|
411
|
+
def brown_invariant(self):
|
|
412
|
+
r"""
|
|
413
|
+
Return the Brown invariant of this torsion quadratic form.
|
|
414
|
+
|
|
415
|
+
Let `(D,q)` be a torsion quadratic module with values in `\QQ / 2 \ZZ`.
|
|
416
|
+
The Brown invariant `Br(D,q) \in \Zmod{8}` is defined by the equation
|
|
417
|
+
|
|
418
|
+
.. MATH::
|
|
419
|
+
|
|
420
|
+
\exp \left( \frac{2 \pi i }{8} Br(q)\right) =
|
|
421
|
+
\frac{1}{\sqrt{D}} \sum_{x \in D} \exp(i \pi q(x)).
|
|
422
|
+
|
|
423
|
+
The Brown invariant is additive with respect to direct sums of
|
|
424
|
+
torsion quadratic modules.
|
|
425
|
+
|
|
426
|
+
OUTPUT: an element of `\Zmod{8}`
|
|
427
|
+
|
|
428
|
+
EXAMPLES::
|
|
429
|
+
|
|
430
|
+
sage: L = IntegralLattice("D4") # needs sage.combinat sage.graphs
|
|
431
|
+
sage: D = L.discriminant_group() # needs sage.combinat sage.graphs
|
|
432
|
+
sage: D.brown_invariant() # needs sage.combinat sage.graphs
|
|
433
|
+
4
|
|
434
|
+
|
|
435
|
+
We require the quadratic form to be defined modulo `2 \ZZ`::
|
|
436
|
+
|
|
437
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
438
|
+
sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3))
|
|
439
|
+
sage: T = TorsionQuadraticModule((1/10)*V, V)
|
|
440
|
+
sage: T.brown_invariant()
|
|
441
|
+
Traceback (most recent call last):
|
|
442
|
+
...
|
|
443
|
+
ValueError: the torsion quadratic form must have values in QQ / 2 ZZ
|
|
444
|
+
"""
|
|
445
|
+
if self._modulus_qf != 2:
|
|
446
|
+
raise ValueError("the torsion quadratic form must have values in "
|
|
447
|
+
"QQ / 2 ZZ")
|
|
448
|
+
from sage.quadratic_forms.genera.normal_form import collect_small_blocks
|
|
449
|
+
brown = IntegerModRing(8).zero()
|
|
450
|
+
for p in self.annihilator().gen().prime_divisors():
|
|
451
|
+
q = self.primary_part(p).normal_form()
|
|
452
|
+
q = q.gram_matrix_quadratic()
|
|
453
|
+
L = collect_small_blocks(q)
|
|
454
|
+
for qi in L:
|
|
455
|
+
brown += _brown_indecomposable(qi, p)
|
|
456
|
+
return brown
|
|
457
|
+
|
|
458
|
+
@cached_method
|
|
459
|
+
def gram_matrix_bilinear(self):
|
|
460
|
+
r"""
|
|
461
|
+
Return the Gram matrix with respect to the generators.
|
|
462
|
+
|
|
463
|
+
OUTPUT:
|
|
464
|
+
|
|
465
|
+
A rational matrix ``G`` with ``G[i,j]`` given by the inner product
|
|
466
|
+
of the `i`-th and `j`-th generator. Its entries are only well
|
|
467
|
+
defined `\mod (V, W)`.
|
|
468
|
+
|
|
469
|
+
EXAMPLES::
|
|
470
|
+
|
|
471
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
472
|
+
sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)*5)
|
|
473
|
+
sage: T = TorsionQuadraticModule((1/5)*V, V)
|
|
474
|
+
sage: T.gram_matrix_bilinear()
|
|
475
|
+
[1/5 0 0]
|
|
476
|
+
[ 0 1/5 0]
|
|
477
|
+
[ 0 0 1/5]
|
|
478
|
+
"""
|
|
479
|
+
gens = self.gens()
|
|
480
|
+
n = len(gens)
|
|
481
|
+
Q = self.base_ring().fraction_field()
|
|
482
|
+
G = matrix.zero(Q, n)
|
|
483
|
+
for i in range(n):
|
|
484
|
+
for j in range(i + 1):
|
|
485
|
+
G[i, j] = G[j, i] = (gens[i] * gens[j]).lift()
|
|
486
|
+
return G
|
|
487
|
+
|
|
488
|
+
@cached_method
|
|
489
|
+
def gram_matrix_quadratic(self):
|
|
490
|
+
r"""
|
|
491
|
+
The Gram matrix of the quadratic form with respect to the generators.
|
|
492
|
+
|
|
493
|
+
OUTPUT:
|
|
494
|
+
|
|
495
|
+
- a rational matrix ``Gq`` with ``Gq[i,j] = gens[i]*gens[j]``
|
|
496
|
+
and ``G[i,i] = gens[i].q()``
|
|
497
|
+
|
|
498
|
+
EXAMPLES::
|
|
499
|
+
|
|
500
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
501
|
+
sage: D4_gram = Matrix(ZZ, [[2,0,0,-1],[0,2,0,-1],[0,0,2,-1],[-1,-1,-1,2]])
|
|
502
|
+
sage: D4 = FreeQuadraticModule(ZZ, 4, D4_gram)
|
|
503
|
+
sage: D4dual = D4.span(D4_gram.inverse())
|
|
504
|
+
sage: discrForm = TorsionQuadraticModule(D4dual, D4)
|
|
505
|
+
sage: discrForm.gram_matrix_quadratic()
|
|
506
|
+
[ 1 1/2]
|
|
507
|
+
[1/2 1]
|
|
508
|
+
sage: discrForm.gram_matrix_bilinear()
|
|
509
|
+
[ 0 1/2]
|
|
510
|
+
[1/2 0]
|
|
511
|
+
"""
|
|
512
|
+
gens = self.gens()
|
|
513
|
+
n = len(gens)
|
|
514
|
+
Q = self.base_ring().fraction_field()
|
|
515
|
+
G = matrix.zero(Q, n)
|
|
516
|
+
for i in range(n):
|
|
517
|
+
for j in range(i):
|
|
518
|
+
G[i, j] = G[j, i] = (gens[i] * gens[j]).lift()
|
|
519
|
+
G[i, i] = gens[i].q().lift()
|
|
520
|
+
return G
|
|
521
|
+
|
|
522
|
+
def gens(self) -> tuple:
|
|
523
|
+
r"""
|
|
524
|
+
Return generators of ``self``.
|
|
525
|
+
|
|
526
|
+
There is no assumption on the generators except that they
|
|
527
|
+
generate the module.
|
|
528
|
+
|
|
529
|
+
EXAMPLES::
|
|
530
|
+
|
|
531
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
532
|
+
sage: V = FreeModule(ZZ, 3)
|
|
533
|
+
sage: T = TorsionQuadraticModule(V, 5*V)
|
|
534
|
+
sage: T.gens()
|
|
535
|
+
((1, 0, 0), (0, 1, 0), (0, 0, 1))
|
|
536
|
+
"""
|
|
537
|
+
if self._gens_user is None:
|
|
538
|
+
return self.smith_form_gens()
|
|
539
|
+
return self._gens_user
|
|
540
|
+
|
|
541
|
+
def genus(self, signature_pair):
|
|
542
|
+
r"""
|
|
543
|
+
Return the genus defined by ``self`` and the ``signature_pair``.
|
|
544
|
+
|
|
545
|
+
If no such genus exists, raise a :exc:`ValueError`.
|
|
546
|
+
|
|
547
|
+
REFERENCES:
|
|
548
|
+
|
|
549
|
+
[Nik1977]_ Corollary 1.9.4 and 1.16.3.
|
|
550
|
+
|
|
551
|
+
EXAMPLES::
|
|
552
|
+
|
|
553
|
+
sage: # needs sage.combinat sage.graphs
|
|
554
|
+
sage: L = IntegralLattice("D4").direct_sum(IntegralLattice("A2"))
|
|
555
|
+
sage: D = L.discriminant_group()
|
|
556
|
+
sage: genus = D.genus(L.signature_pair()) # needs sage.libs.pari
|
|
557
|
+
sage: genus # needs sage.libs.pari
|
|
558
|
+
Genus of
|
|
559
|
+
None
|
|
560
|
+
Signature: (6, 0)
|
|
561
|
+
Genus symbol at 2: 1^4:2^-2
|
|
562
|
+
Genus symbol at 3: 1^-5 3^-1
|
|
563
|
+
sage: genus == L.genus() # needs sage.libs.pari
|
|
564
|
+
True
|
|
565
|
+
|
|
566
|
+
Let `H` be an even unimodular lattice of signature `(9, 1)`.
|
|
567
|
+
Then `L = D_4 + A_2` is primitively embedded in `H`. We compute the discriminant
|
|
568
|
+
form of the orthogonal complement of `L` in `H`::
|
|
569
|
+
|
|
570
|
+
sage: DK = D.twist(-1) # needs sage.combinat sage.graphs sage.libs.pari
|
|
571
|
+
sage: DK # needs sage.combinat sage.graphs sage.libs.pari
|
|
572
|
+
Finite quadratic module over Integer Ring with invariants (2, 6)
|
|
573
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
574
|
+
[ 1 1/2]
|
|
575
|
+
[1/2 1/3]
|
|
576
|
+
|
|
577
|
+
We know that `K` has signature `(5, 1)` and thus we can compute
|
|
578
|
+
the genus of `K` as::
|
|
579
|
+
|
|
580
|
+
sage: DK.genus((3,1)) # needs sage.combinat sage.graphs sage.libs.pari
|
|
581
|
+
Genus of
|
|
582
|
+
None
|
|
583
|
+
Signature: (3, 1)
|
|
584
|
+
Genus symbol at 2: 1^2:2^-2
|
|
585
|
+
Genus symbol at 3: 1^-3 3^1
|
|
586
|
+
|
|
587
|
+
We can also compute the genus of an odd lattice
|
|
588
|
+
from its discriminant form::
|
|
589
|
+
|
|
590
|
+
sage: L = IntegralLattice(matrix.diagonal(range(1, 5)))
|
|
591
|
+
sage: D = L.discriminant_group()
|
|
592
|
+
sage: D.genus((4,0)) # needs sage.libs.pari
|
|
593
|
+
Genus of
|
|
594
|
+
None
|
|
595
|
+
Signature: (4, 0)
|
|
596
|
+
Genus symbol at 2: [1^-2 2^1 4^1]_6
|
|
597
|
+
Genus symbol at 3: 1^-3 3^1
|
|
598
|
+
|
|
599
|
+
TESTS::
|
|
600
|
+
|
|
601
|
+
sage: L.genus() == D.genus((4,0)) # needs sage.libs.pari
|
|
602
|
+
True
|
|
603
|
+
sage: D.genus((1,0)) # needs sage.libs.pari
|
|
604
|
+
Traceback (most recent call last):
|
|
605
|
+
...
|
|
606
|
+
ValueError: this discriminant form and signature do not define a genus
|
|
607
|
+
|
|
608
|
+
A systematic test of lattices of small ranks and determinants::
|
|
609
|
+
|
|
610
|
+
sage: # needs sage.libs.pari
|
|
611
|
+
sage: from sage.quadratic_forms.genera.genus import genera
|
|
612
|
+
sage: signatures = [(1,0), (1,1), (1,2), (3,0), (0,4)]
|
|
613
|
+
sage: dets = range(1, 33)
|
|
614
|
+
sage: genera = flatten([genera(s, d, even=False) for d in dets for s in signatures]) # long time
|
|
615
|
+
sage: all(g == g.discriminant_form().genus(g.signature_pair()) for g in genera) # long time
|
|
616
|
+
True
|
|
617
|
+
"""
|
|
618
|
+
from sage.quadratic_forms.genera.genus import (Genus_Symbol_p_adic_ring,
|
|
619
|
+
GenusSymbol_global_ring,
|
|
620
|
+
p_adic_symbol,
|
|
621
|
+
is_GlobalGenus,
|
|
622
|
+
_blocks)
|
|
623
|
+
from sage.misc.misc_c import prod
|
|
624
|
+
s_plus = signature_pair[0]
|
|
625
|
+
s_minus = signature_pair[1]
|
|
626
|
+
rank = s_plus + s_minus
|
|
627
|
+
if len(self.invariants()) > rank:
|
|
628
|
+
raise ValueError("this discriminant form and " +
|
|
629
|
+
"signature do not define a genus")
|
|
630
|
+
disc = self.cardinality()
|
|
631
|
+
determinant = (-1)**s_minus * disc
|
|
632
|
+
local_symbols = []
|
|
633
|
+
for p in (2 * disc).prime_divisors():
|
|
634
|
+
D = self.primary_part(p)
|
|
635
|
+
if len(D.invariants()) != 0:
|
|
636
|
+
G_p = D.gram_matrix_quadratic().inverse()
|
|
637
|
+
# get rid of denominators without changing the local equivalence class
|
|
638
|
+
G_p *= G_p.denominator()**2
|
|
639
|
+
G_p = G_p.change_ring(ZZ)
|
|
640
|
+
local_symbol = p_adic_symbol(G_p, p, D.invariants()[-1].valuation(p))
|
|
641
|
+
else:
|
|
642
|
+
local_symbol = []
|
|
643
|
+
|
|
644
|
+
rk = rank - len(D.invariants())
|
|
645
|
+
if rk > 0:
|
|
646
|
+
if p == 2:
|
|
647
|
+
det = determinant.prime_to_m_part(2)
|
|
648
|
+
det *= prod([di[2] for di in local_symbol])
|
|
649
|
+
det = det % 8
|
|
650
|
+
local_symbol.append([ZZ(0), rk, det, ZZ(0), ZZ(0)])
|
|
651
|
+
else:
|
|
652
|
+
det = legendre_symbol(determinant.prime_to_m_part(p), p)
|
|
653
|
+
det = (det * prod([di[2] for di in local_symbol]))
|
|
654
|
+
local_symbol.append([ZZ(0), rk, det])
|
|
655
|
+
local_symbol.sort()
|
|
656
|
+
local_symbol = Genus_Symbol_p_adic_ring(p, local_symbol)
|
|
657
|
+
local_symbols.append(local_symbol)
|
|
658
|
+
|
|
659
|
+
# This genus has the right discriminant group
|
|
660
|
+
# but it may be empty
|
|
661
|
+
genus = GenusSymbol_global_ring(signature_pair, local_symbols)
|
|
662
|
+
sym2 = local_symbols[0].symbol_tuple_list()
|
|
663
|
+
|
|
664
|
+
if sym2[0][0] != 0:
|
|
665
|
+
sym2 = [[ZZ(0), ZZ(0), ZZ(1), ZZ(0), ZZ(0)]] + sym2
|
|
666
|
+
if len(sym2) <= 1 or sym2[1][0] != 1:
|
|
667
|
+
sym2 = sym2[:1] + [[ZZ(1), ZZ(0), ZZ(1), ZZ(0), ZZ(0)]] + sym2[1:]
|
|
668
|
+
if len(sym2) <= 2 or sym2[2][0] != 2:
|
|
669
|
+
sym2 = sym2[:2] + [[ZZ(2), ZZ(0), ZZ(1), ZZ(0), ZZ(0)]] + sym2[2:]
|
|
670
|
+
|
|
671
|
+
if self.value_module_qf().n == 1:
|
|
672
|
+
# in this case the blocks of scales 1, 2, 4 are under determined
|
|
673
|
+
# make sure the first 3 symbols are of scales 1, 2, 4
|
|
674
|
+
# i.e. their valuations are 0, 1, 2
|
|
675
|
+
|
|
676
|
+
# the form is odd
|
|
677
|
+
block0 = [b for b in _blocks(sym2[0]) if b[3] == 1]
|
|
678
|
+
|
|
679
|
+
o = sym2[1][3]
|
|
680
|
+
# no restrictions on determinant and
|
|
681
|
+
# oddity beyond existence
|
|
682
|
+
# but we know if even or odd
|
|
683
|
+
block1 = [b for b in _blocks(sym2[1]) if b[3] == o]
|
|
684
|
+
|
|
685
|
+
d = sym2[2][2]
|
|
686
|
+
o = sym2[2][3]
|
|
687
|
+
t = sym2[2][4]
|
|
688
|
+
# if the jordan block of scale 2 is even we know it
|
|
689
|
+
if o == 0:
|
|
690
|
+
block2 = [sym2[2]]
|
|
691
|
+
# if it is odd we know det and oddity mod 4 at least
|
|
692
|
+
else:
|
|
693
|
+
block2 = [b for b in _blocks(sym2[2]) if b[3] == o
|
|
694
|
+
and (b[2] - d) % 4 == 0
|
|
695
|
+
and (b[4] - t) % 4 == 0
|
|
696
|
+
and (b[2] - d) % 8 == (b[4] - t) % 8 # if the oddity is altered by 4 then so is the determinant
|
|
697
|
+
]
|
|
698
|
+
elif self.value_module_qf().n == 2:
|
|
699
|
+
# the form is even
|
|
700
|
+
block0 = [b for b in _blocks(sym2[0]) if b[3] == 0]
|
|
701
|
+
|
|
702
|
+
# if the jordan block of scale 2 is even we know it
|
|
703
|
+
d = sym2[1][2]
|
|
704
|
+
o = sym2[1][3]
|
|
705
|
+
t = sym2[1][4]
|
|
706
|
+
if o == 0:
|
|
707
|
+
block1 = [sym2[1]]
|
|
708
|
+
else:
|
|
709
|
+
# the block is odd and we know det and oddity mod 4
|
|
710
|
+
block1 = [b for b in _blocks(sym2[1])
|
|
711
|
+
if b[3] == o
|
|
712
|
+
and (b[2] - d) % 4 == 0
|
|
713
|
+
and (b[4] - t) % 4 == 0
|
|
714
|
+
and (b[2] - d) % 8 == (b[4] - t) % 8
|
|
715
|
+
# if the oddity is altered by 4
|
|
716
|
+
# then so is the determinant
|
|
717
|
+
]
|
|
718
|
+
# this is completely determined
|
|
719
|
+
block2 = [sym2[2]]
|
|
720
|
+
else:
|
|
721
|
+
raise ValueError("this is not a discriminant form")
|
|
722
|
+
|
|
723
|
+
# figure out which symbol defines a genus and return that
|
|
724
|
+
for b0 in block0:
|
|
725
|
+
for b1 in block1:
|
|
726
|
+
for b2 in block2:
|
|
727
|
+
sym2[:3] = [b0, b1, b2]
|
|
728
|
+
local_symbols[0] = Genus_Symbol_p_adic_ring(2, sym2)
|
|
729
|
+
genus = GenusSymbol_global_ring(signature_pair, local_symbols)
|
|
730
|
+
if is_GlobalGenus(genus):
|
|
731
|
+
# make the symbol sparse again.
|
|
732
|
+
i = 0
|
|
733
|
+
k = 0
|
|
734
|
+
while i < 3:
|
|
735
|
+
if sym2[k][1] == 0:
|
|
736
|
+
sym2.pop(k)
|
|
737
|
+
else:
|
|
738
|
+
k = k + 1
|
|
739
|
+
i = i + 1
|
|
740
|
+
local_symbols[0] = Genus_Symbol_p_adic_ring(2, sym2)
|
|
741
|
+
genus = GenusSymbol_global_ring(signature_pair, local_symbols)
|
|
742
|
+
return genus
|
|
743
|
+
raise ValueError("this discriminant form and signature do not define a genus")
|
|
744
|
+
|
|
745
|
+
def is_genus(self, signature_pair, even=True) -> bool:
|
|
746
|
+
r"""
|
|
747
|
+
Return ``True`` if there is a lattice with this signature and discriminant form.
|
|
748
|
+
|
|
749
|
+
.. TODO::
|
|
750
|
+
|
|
751
|
+
implement the same for odd lattices
|
|
752
|
+
|
|
753
|
+
INPUT:
|
|
754
|
+
|
|
755
|
+
- ``signature_pair`` -- tuple of nonnegative integers ``(s_plus, s_minus)``
|
|
756
|
+
- ``even`` -- boolean (default: ``True``)
|
|
757
|
+
|
|
758
|
+
EXAMPLES::
|
|
759
|
+
|
|
760
|
+
sage: L3 = IntegralLattice(3 * Matrix(ZZ, 2, [2,1,1,2]))
|
|
761
|
+
sage: L = IntegralLattice("D4").direct_sum(L3) # needs sage.combinat sage.graphs
|
|
762
|
+
sage: D = L.discriminant_group() # needs sage.combinat sage.graphs
|
|
763
|
+
sage: D.is_genus((6,0)) # needs sage.combinat sage.graphs
|
|
764
|
+
True
|
|
765
|
+
|
|
766
|
+
Let us see if there is a lattice in the genus defined by the same discriminant form
|
|
767
|
+
but with a different signature::
|
|
768
|
+
|
|
769
|
+
sage: D.is_genus((4,2)) # needs sage.combinat sage.graphs
|
|
770
|
+
False
|
|
771
|
+
sage: D.is_genus((16,2)) # needs sage.combinat sage.graphs
|
|
772
|
+
True
|
|
773
|
+
"""
|
|
774
|
+
s_plus = ZZ(signature_pair[0])
|
|
775
|
+
s_minus = ZZ(signature_pair[1])
|
|
776
|
+
if s_plus < 0 or s_minus < 0:
|
|
777
|
+
raise ValueError("signature invariants must be nonnegative")
|
|
778
|
+
rank = s_plus + s_minus
|
|
779
|
+
signature = s_plus - s_minus
|
|
780
|
+
D = self.cardinality()
|
|
781
|
+
det = (-1)**s_minus * D
|
|
782
|
+
if rank < len(self.invariants()):
|
|
783
|
+
return False
|
|
784
|
+
if even and self._modulus_qf != 2:
|
|
785
|
+
raise ValueError("the discriminant form of an even lattice has"
|
|
786
|
+
"values modulo 2.")
|
|
787
|
+
if (not even) and not (self._modulus == self._modulus_qf == 1):
|
|
788
|
+
raise ValueError("the discriminant form of an odd lattice has"
|
|
789
|
+
"values modulo 1.")
|
|
790
|
+
if not even:
|
|
791
|
+
raise NotImplementedError("at the moment sage knows how to do this only for even genera. " +
|
|
792
|
+
" Help us to implement this for odd genera.")
|
|
793
|
+
for p in D.prime_divisors():
|
|
794
|
+
# check the determinant conditions
|
|
795
|
+
Q_p = self.primary_part(p)
|
|
796
|
+
gram_p = Q_p.gram_matrix_quadratic()
|
|
797
|
+
length_p = len(Q_p.invariants())
|
|
798
|
+
u = det.prime_to_m_part(p)
|
|
799
|
+
up = gram_p.det().numerator().prime_to_m_part(p)
|
|
800
|
+
if p != 2 and length_p == rank:
|
|
801
|
+
if legendre_symbol(u, p) != legendre_symbol(up, p):
|
|
802
|
+
return False
|
|
803
|
+
if p == 2:
|
|
804
|
+
if rank % 2 != length_p % 2:
|
|
805
|
+
return False
|
|
806
|
+
n = (rank - length_p) / 2
|
|
807
|
+
if u % 4 != (-1)**(n % 2) * up % 4:
|
|
808
|
+
return False
|
|
809
|
+
if rank == length_p:
|
|
810
|
+
a = QQ(1) / QQ(2)
|
|
811
|
+
b = QQ(3) / QQ(2)
|
|
812
|
+
diag = gram_p.diagonal()
|
|
813
|
+
if not (a in diag or b in diag):
|
|
814
|
+
if u % 8 != up % 8:
|
|
815
|
+
return False
|
|
816
|
+
if self.brown_invariant() != signature:
|
|
817
|
+
return False
|
|
818
|
+
return True
|
|
819
|
+
|
|
820
|
+
def orthogonal_group(self, gens=None, check=False):
|
|
821
|
+
r"""
|
|
822
|
+
Orthogonal group of the associated torsion quadratic form.
|
|
823
|
+
|
|
824
|
+
.. WARNING::
|
|
825
|
+
|
|
826
|
+
This is can be smaller than the orthogonal group of the bilinear form.
|
|
827
|
+
|
|
828
|
+
INPUT:
|
|
829
|
+
|
|
830
|
+
- ``gens`` -- a list of generators, for instance square matrices,
|
|
831
|
+
something that acts on ``self``, or an automorphism
|
|
832
|
+
of the underlying abelian group
|
|
833
|
+
- ``check`` -- perform additional checks on the generators
|
|
834
|
+
|
|
835
|
+
EXAMPLES:
|
|
836
|
+
|
|
837
|
+
You can provide generators to obtain a subgroup of the full orthogonal group::
|
|
838
|
+
|
|
839
|
+
sage: D = TorsionQuadraticForm(matrix.identity(2)/2)
|
|
840
|
+
sage: f = matrix(2, [0,1,1,0])
|
|
841
|
+
sage: D.orthogonal_group(gens=[f]).order() # needs sage.groups
|
|
842
|
+
2
|
|
843
|
+
|
|
844
|
+
If no generators are given a slow brute force approach is used to calculate the full orthogonal group::
|
|
845
|
+
|
|
846
|
+
sage: D = TorsionQuadraticForm(matrix.identity(3)/2)
|
|
847
|
+
sage: OD = D.orthogonal_group() # needs sage.groups
|
|
848
|
+
sage: OD.order() # needs sage.groups
|
|
849
|
+
6
|
|
850
|
+
sage: fd = D.hom([D.1, D.0, D.2]) # needs sage.symbolic
|
|
851
|
+
sage: OD(fd) # needs sage.groups sage.symbolic
|
|
852
|
+
[0 1 0]
|
|
853
|
+
[1 0 0]
|
|
854
|
+
[0 0 1]
|
|
855
|
+
|
|
856
|
+
We compute the kernel of the action of the orthogonal group of `L` on the discriminant group::
|
|
857
|
+
|
|
858
|
+
sage: # needs sage.combinat sage.groups
|
|
859
|
+
sage: L = IntegralLattice('A4')
|
|
860
|
+
sage: O = L.orthogonal_group()
|
|
861
|
+
sage: D = L.discriminant_group()
|
|
862
|
+
sage: Obar = D.orthogonal_group(O.gens())
|
|
863
|
+
sage: O.order()
|
|
864
|
+
240
|
|
865
|
+
sage: Obar.order()
|
|
866
|
+
2
|
|
867
|
+
sage: phi = O.hom(Obar.gens())
|
|
868
|
+
sage: phi.kernel().order()
|
|
869
|
+
120
|
|
870
|
+
"""
|
|
871
|
+
from sage.groups.fqf_orthogonal import FqfOrthogonalGroup, _isom_fqf
|
|
872
|
+
from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap
|
|
873
|
+
|
|
874
|
+
ambient = AbelianGroupGap(self.invariants()).aut()
|
|
875
|
+
# slow brute force implementation
|
|
876
|
+
if gens is None:
|
|
877
|
+
try:
|
|
878
|
+
gens = self._orthogonal_group_gens
|
|
879
|
+
except AttributeError:
|
|
880
|
+
gens = _isom_fqf(self)
|
|
881
|
+
gens = tuple(ambient(g) for g in gens)
|
|
882
|
+
self._orthogonal_group_gens = gens
|
|
883
|
+
else:
|
|
884
|
+
# see if there is an action
|
|
885
|
+
try:
|
|
886
|
+
gens = [matrix(x*g for x in self.smith_form_gens()) for g in gens]
|
|
887
|
+
except TypeError:
|
|
888
|
+
pass
|
|
889
|
+
# the ambient knows what to do with the generators
|
|
890
|
+
gens = tuple(ambient(g) for g in gens)
|
|
891
|
+
Oq = FqfOrthogonalGroup(ambient, gens, self, check=check)
|
|
892
|
+
return Oq
|
|
893
|
+
|
|
894
|
+
def orthogonal_submodule_to(self, S):
|
|
895
|
+
r"""
|
|
896
|
+
Return the submodule orthogonal to ``S``.
|
|
897
|
+
|
|
898
|
+
INPUT:
|
|
899
|
+
|
|
900
|
+
- ``S`` -- a submodule, list, or tuple of generators
|
|
901
|
+
|
|
902
|
+
EXAMPLES::
|
|
903
|
+
|
|
904
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
905
|
+
sage: V = FreeModule(ZZ, 10)
|
|
906
|
+
sage: T = TorsionQuadraticModule(V, 3*V)
|
|
907
|
+
sage: S = T.submodule(T.gens()[:5])
|
|
908
|
+
sage: O = T.orthogonal_submodule_to(S)
|
|
909
|
+
sage: O
|
|
910
|
+
Finite quadratic module over Integer Ring with invariants (3, 3, 3, 3, 3)
|
|
911
|
+
Gram matrix of the quadratic form with values in Q/3Z:
|
|
912
|
+
[1 0 0 0 0]
|
|
913
|
+
[0 1 0 0 0]
|
|
914
|
+
[0 0 1 0 0]
|
|
915
|
+
[0 0 0 1 0]
|
|
916
|
+
[0 0 0 0 1]
|
|
917
|
+
sage: O.V() + S.V() == T.V()
|
|
918
|
+
True
|
|
919
|
+
"""
|
|
920
|
+
if not isinstance(S, TorsionQuadraticModule):
|
|
921
|
+
S = self.submodule(S)
|
|
922
|
+
else:
|
|
923
|
+
if not S.is_submodule(self):
|
|
924
|
+
raise ValueError("S must be a submodule of this module")
|
|
925
|
+
|
|
926
|
+
G = self.V().inner_product_matrix()
|
|
927
|
+
T = self.V().basis_matrix()
|
|
928
|
+
S = S.V().basis_matrix()
|
|
929
|
+
m = self._modulus
|
|
930
|
+
|
|
931
|
+
Y = T * G * S.transpose()
|
|
932
|
+
# Elements of the ambient module which pair integrally with self.V()
|
|
933
|
+
integral = Y.inverse() * T
|
|
934
|
+
# Element of the ambient module which pair in mZZ with self.V()
|
|
935
|
+
orthogonal = m * integral
|
|
936
|
+
orthogonal = self.V().span(orthogonal.rows())
|
|
937
|
+
# We have to make sure we get a submodule
|
|
938
|
+
orthogonal = orthogonal.intersection(self.V())
|
|
939
|
+
orthogonal = self.submodule(orthogonal.gens())
|
|
940
|
+
return orthogonal
|
|
941
|
+
|
|
942
|
+
@cached_method
|
|
943
|
+
def normal_form(self, partial=False):
|
|
944
|
+
r"""
|
|
945
|
+
Return the normal form of this torsion quadratic module.
|
|
946
|
+
|
|
947
|
+
Two torsion quadratic modules are isomorphic if and only if they have
|
|
948
|
+
the same value modules and the same normal form.
|
|
949
|
+
|
|
950
|
+
A torsion quadratic module `(T,q)` with values in `\QQ/n\ZZ` is
|
|
951
|
+
in normal form if the rescaled quadratic module `(T, q/n)`
|
|
952
|
+
with values in `\QQ/\ZZ` is in normal form.
|
|
953
|
+
|
|
954
|
+
For the definition of normal form see [MirMor2009]_ IV Definition 4.6.
|
|
955
|
+
Below are some of its properties.
|
|
956
|
+
Let `p` be odd and `u` be the smallest non-square modulo `p`.
|
|
957
|
+
The normal form is a diagonal matrix with diagonal entries either `p^n`
|
|
958
|
+
or `u p^n`.
|
|
959
|
+
|
|
960
|
+
If `p = 2` is even, then the normal form consists of
|
|
961
|
+
`1 \times 1` blocks of the form
|
|
962
|
+
|
|
963
|
+
.. MATH::
|
|
964
|
+
|
|
965
|
+
(0), \quad 2^n(1),\quad 2^n(3),\quad 2^n(5) ,\quad 2^n(7)
|
|
966
|
+
|
|
967
|
+
or of `2 \times 2` blocks of the form
|
|
968
|
+
|
|
969
|
+
.. MATH::
|
|
970
|
+
|
|
971
|
+
2^n
|
|
972
|
+
\left(\begin{matrix}
|
|
973
|
+
2 & 1\\
|
|
974
|
+
1 & 2
|
|
975
|
+
\end{matrix}\right), \quad
|
|
976
|
+
2^n
|
|
977
|
+
\left(\begin{matrix}
|
|
978
|
+
0 & 1\\
|
|
979
|
+
1 & 0
|
|
980
|
+
\end{matrix}\right).
|
|
981
|
+
|
|
982
|
+
The blocks are ordered by their valuation.
|
|
983
|
+
|
|
984
|
+
INPUT:
|
|
985
|
+
|
|
986
|
+
- ``partial`` -- boolean (default: ``False``); return only a partial
|
|
987
|
+
normal form. It is not unique but still useful to extract invariants.
|
|
988
|
+
|
|
989
|
+
OUTPUT: a torsion quadratic module
|
|
990
|
+
|
|
991
|
+
EXAMPLES::
|
|
992
|
+
|
|
993
|
+
sage: L1 = IntegralLattice(matrix([[-2,0,0], [0,1,0], [0,0,4]]))
|
|
994
|
+
sage: L1.discriminant_group().normal_form() # needs sage.rings.padics
|
|
995
|
+
Finite quadratic module over Integer Ring with invariants (2, 4)
|
|
996
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
997
|
+
[1/2 0]
|
|
998
|
+
[ 0 1/4]
|
|
999
|
+
sage: L2 = IntegralLattice(matrix([[-2,0,0], [0,1,0], [0,0,-4]]))
|
|
1000
|
+
sage: L2.discriminant_group().normal_form() # needs sage.rings.padics
|
|
1001
|
+
Finite quadratic module over Integer Ring with invariants (2, 4)
|
|
1002
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
1003
|
+
[1/2 0]
|
|
1004
|
+
[ 0 1/4]
|
|
1005
|
+
|
|
1006
|
+
We check that :issue:`24864` is fixed::
|
|
1007
|
+
|
|
1008
|
+
sage: L1 = IntegralLattice(matrix([[-4,0,0], [0,4,0], [0,0,-2]]))
|
|
1009
|
+
sage: AL1 = L1.discriminant_group()
|
|
1010
|
+
sage: L2 = IntegralLattice(matrix([[-4,0,0], [0,-4,0], [0,0,2]]))
|
|
1011
|
+
sage: AL2 = L2.discriminant_group()
|
|
1012
|
+
sage: AL1.normal_form() # needs sage.rings.padics
|
|
1013
|
+
Finite quadratic module over Integer Ring with invariants (2, 4, 4)
|
|
1014
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
1015
|
+
[1/2 0 0]
|
|
1016
|
+
[ 0 1/4 0]
|
|
1017
|
+
[ 0 0 5/4]
|
|
1018
|
+
sage: AL2.normal_form() # needs sage.libs.pari sage.rings.padics
|
|
1019
|
+
Finite quadratic module over Integer Ring with invariants (2, 4, 4)
|
|
1020
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
1021
|
+
[1/2 0 0]
|
|
1022
|
+
[ 0 1/4 0]
|
|
1023
|
+
[ 0 0 5/4]
|
|
1024
|
+
|
|
1025
|
+
Some exotic cases::
|
|
1026
|
+
|
|
1027
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
1028
|
+
sage: D4_gram = Matrix(ZZ, 4, 4,[2,0,0,-1, 0,2,0,-1, 0,0,2,-1, -1,-1,-1,2])
|
|
1029
|
+
sage: D4 = FreeQuadraticModule(ZZ, 4, D4_gram)
|
|
1030
|
+
sage: D4dual = D4.span(D4_gram.inverse())
|
|
1031
|
+
sage: T = TorsionQuadraticModule((1/6)*D4dual, D4); T
|
|
1032
|
+
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
|
|
1033
|
+
Gram matrix of the quadratic form with values in Q/(1/3)Z:
|
|
1034
|
+
[ 1/18 1/12 5/36 1/36]
|
|
1035
|
+
[ 1/12 1/6 1/36 1/9]
|
|
1036
|
+
[ 5/36 1/36 1/36 11/72]
|
|
1037
|
+
[ 1/36 1/9 11/72 1/36]
|
|
1038
|
+
sage: T.normal_form() # needs sage.libs.pari sage.rings.padics
|
|
1039
|
+
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
|
|
1040
|
+
Gram matrix of the quadratic form with values in Q/(1/3)Z:
|
|
1041
|
+
[ 1/6 1/12 0 0 0 0 0 0]
|
|
1042
|
+
[1/12 1/6 0 0 0 0 0 0]
|
|
1043
|
+
[ 0 0 1/12 1/24 0 0 0 0]
|
|
1044
|
+
[ 0 0 1/24 1/12 0 0 0 0]
|
|
1045
|
+
[ 0 0 0 0 1/9 0 0 0]
|
|
1046
|
+
[ 0 0 0 0 0 1/9 0 0]
|
|
1047
|
+
[ 0 0 0 0 0 0 1/9 0]
|
|
1048
|
+
[ 0 0 0 0 0 0 0 1/9]
|
|
1049
|
+
|
|
1050
|
+
TESTS:
|
|
1051
|
+
|
|
1052
|
+
A degenerate case::
|
|
1053
|
+
|
|
1054
|
+
sage: T = TorsionQuadraticModule((1/6)*D4dual, D4, modulus=1/36)
|
|
1055
|
+
sage: T.normal_form() # needs sage.libs.pari sage.rings.padics
|
|
1056
|
+
Finite quadratic module over Integer Ring with invariants (6, 6, 12, 12)
|
|
1057
|
+
Gram matrix of the quadratic form with values in Q/(1/18)Z:
|
|
1058
|
+
[1/36 1/72 0 0 0 0 0 0]
|
|
1059
|
+
[1/72 1/36 0 0 0 0 0 0]
|
|
1060
|
+
[ 0 0 0 0 0 0 0 0]
|
|
1061
|
+
[ 0 0 0 0 0 0 0 0]
|
|
1062
|
+
[ 0 0 0 0 0 0 0 0]
|
|
1063
|
+
[ 0 0 0 0 0 0 0 0]
|
|
1064
|
+
[ 0 0 0 0 0 0 0 0]
|
|
1065
|
+
[ 0 0 0 0 0 0 0 0]
|
|
1066
|
+
"""
|
|
1067
|
+
from sage.quadratic_forms.genera.normal_form import p_adic_normal_form, _normalize
|
|
1068
|
+
from sage.rings.padics.factory import Zp
|
|
1069
|
+
|
|
1070
|
+
gens = []
|
|
1071
|
+
for p in self.annihilator().gen().prime_divisors():
|
|
1072
|
+
D_p = self.primary_part(p)
|
|
1073
|
+
q_p = D_p.gram_matrix_quadratic()
|
|
1074
|
+
q_p = q_p / D_p._modulus_qf
|
|
1075
|
+
|
|
1076
|
+
# continue with the non-degenerate part
|
|
1077
|
+
r = q_p.rank()
|
|
1078
|
+
if r != q_p.ncols():
|
|
1079
|
+
U = q_p._clear_denom()[0].hermite_form(transformation=True)[1]
|
|
1080
|
+
else:
|
|
1081
|
+
U = q_p.parent().identity_matrix()
|
|
1082
|
+
kernel = U[r:, :]
|
|
1083
|
+
nondeg = U[:r, :]
|
|
1084
|
+
q_p = nondeg * q_p * nondeg.T
|
|
1085
|
+
|
|
1086
|
+
# the normal form is implemented for p-adic lattices
|
|
1087
|
+
# so we should work with the lattice q_p --> q_p^-1
|
|
1088
|
+
q_p1 = q_p.inverse()
|
|
1089
|
+
prec = self.annihilator().gen().valuation(p) + 5
|
|
1090
|
+
D, U = p_adic_normal_form(q_p1, p, precision=prec + 5, partial=partial)
|
|
1091
|
+
# if we compute the inverse in the p-adics everything explodes --> go to ZZ
|
|
1092
|
+
U = U.change_ring(ZZ).inverse().transpose()
|
|
1093
|
+
|
|
1094
|
+
# the inverse is in normal form - so to get a normal form for the original one
|
|
1095
|
+
# it is enough to massage each 1x1 resp. 2x2 block.
|
|
1096
|
+
U = U.change_ring(Zp(p, type='fixed-mod', prec=prec)).change_ring(ZZ)
|
|
1097
|
+
D = U * q_p * U.T * p**q_p.denominator().valuation(p)
|
|
1098
|
+
D = D.change_ring(Zp(p, type='fixed-mod', prec=prec))
|
|
1099
|
+
_, U1 = _normalize(D, normal_odd=False)
|
|
1100
|
+
U = U1.change_ring(ZZ) * U
|
|
1101
|
+
|
|
1102
|
+
# reattach the degenerate part
|
|
1103
|
+
nondeg = U * nondeg
|
|
1104
|
+
U = nondeg.stack(kernel)
|
|
1105
|
+
|
|
1106
|
+
# apply U to the generators
|
|
1107
|
+
n = U.ncols()
|
|
1108
|
+
gens_p = []
|
|
1109
|
+
for i in range(n):
|
|
1110
|
+
g = self.V().zero()
|
|
1111
|
+
for j in range(n):
|
|
1112
|
+
g += D_p.gens()[j].lift() * U[i, j]
|
|
1113
|
+
gens_p.append(g)
|
|
1114
|
+
gens += gens_p
|
|
1115
|
+
return self.submodule_with_gens(gens)
|
|
1116
|
+
|
|
1117
|
+
def primary_part(self, m):
|
|
1118
|
+
r"""
|
|
1119
|
+
Return the ``m``-primary part of this torsion quadratic module
|
|
1120
|
+
as a submodule.
|
|
1121
|
+
|
|
1122
|
+
INPUT:
|
|
1123
|
+
|
|
1124
|
+
- ``m`` -- integer
|
|
1125
|
+
|
|
1126
|
+
OUTPUT: a submodule
|
|
1127
|
+
|
|
1128
|
+
EXAMPLES::
|
|
1129
|
+
|
|
1130
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
1131
|
+
sage: T = TorsionQuadraticModule((1/6)*ZZ^3, ZZ^3); T
|
|
1132
|
+
Finite quadratic module over Integer Ring with invariants (6, 6, 6)
|
|
1133
|
+
Gram matrix of the quadratic form with values in Q/(1/3)Z:
|
|
1134
|
+
[1/36 0 0]
|
|
1135
|
+
[ 0 1/36 0]
|
|
1136
|
+
[ 0 0 1/36]
|
|
1137
|
+
sage: T.primary_part(2)
|
|
1138
|
+
Finite quadratic module over Integer Ring with invariants (2, 2, 2)
|
|
1139
|
+
Gram matrix of the quadratic form with values in Q/(1/3)Z:
|
|
1140
|
+
[1/4 0 0]
|
|
1141
|
+
[ 0 1/4 0]
|
|
1142
|
+
[ 0 0 1/4]
|
|
1143
|
+
|
|
1144
|
+
TESTS::
|
|
1145
|
+
|
|
1146
|
+
sage: T == T.primary_part(T.annihilator().gen())
|
|
1147
|
+
True
|
|
1148
|
+
"""
|
|
1149
|
+
annihilator = self.annihilator().gen()
|
|
1150
|
+
a = annihilator.prime_to_m_part(m)
|
|
1151
|
+
return self.submodule((a * self.V()).gens())
|
|
1152
|
+
|
|
1153
|
+
def submodule_with_gens(self, gens):
|
|
1154
|
+
r"""
|
|
1155
|
+
Return a submodule with generators given by ``gens``.
|
|
1156
|
+
|
|
1157
|
+
INPUT:
|
|
1158
|
+
|
|
1159
|
+
- ``gens`` -- list of generators that convert into ``self``
|
|
1160
|
+
|
|
1161
|
+
OUTPUT: a submodule with the specified generators
|
|
1162
|
+
|
|
1163
|
+
EXAMPLES::
|
|
1164
|
+
|
|
1165
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
1166
|
+
sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)*10)
|
|
1167
|
+
sage: T = TorsionQuadraticModule((1/10)*V, V)
|
|
1168
|
+
sage: g = T.gens()
|
|
1169
|
+
sage: new_gens = [2*g[0], 5*g[0]]
|
|
1170
|
+
sage: T.submodule_with_gens(new_gens)
|
|
1171
|
+
Finite quadratic module over Integer Ring with invariants (10,)
|
|
1172
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
1173
|
+
[2/5 0]
|
|
1174
|
+
[ 0 1/2]
|
|
1175
|
+
|
|
1176
|
+
The generators do not need to be independent::
|
|
1177
|
+
|
|
1178
|
+
sage: new_gens = [g[0], 2*g[1], g[0], g[1]]
|
|
1179
|
+
sage: T.submodule_with_gens(new_gens)
|
|
1180
|
+
Finite quadratic module over Integer Ring with invariants (10, 10)
|
|
1181
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
1182
|
+
[1/10 0 1/10 0]
|
|
1183
|
+
[ 0 2/5 0 1/5]
|
|
1184
|
+
[1/10 0 1/10 0]
|
|
1185
|
+
[ 0 1/5 0 1/10]
|
|
1186
|
+
|
|
1187
|
+
TESTS:
|
|
1188
|
+
|
|
1189
|
+
Test that things work without specified gens too::
|
|
1190
|
+
|
|
1191
|
+
sage: from sage.modules.torsion_quadratic_module import TorsionQuadraticModule
|
|
1192
|
+
sage: V = FreeQuadraticModule(ZZ, 3, matrix.identity(3)*5)
|
|
1193
|
+
sage: T = TorsionQuadraticModule((1/5)*V, V); T
|
|
1194
|
+
Finite quadratic module over Integer Ring with invariants (5, 5, 5)
|
|
1195
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
1196
|
+
[1/5 0 0]
|
|
1197
|
+
[ 0 1/5 0]
|
|
1198
|
+
[ 0 0 1/5]
|
|
1199
|
+
sage: T.submodule(T.gens()[:2])
|
|
1200
|
+
Finite quadratic module over Integer Ring with invariants (5, 5)
|
|
1201
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
1202
|
+
[1/5 0]
|
|
1203
|
+
[ 0 1/5]
|
|
1204
|
+
"""
|
|
1205
|
+
gens = tuple(self(v) for v in gens)
|
|
1206
|
+
V = self.V().submodule([v.lift() for v in gens]) + self._W
|
|
1207
|
+
W = self.W()
|
|
1208
|
+
return TorsionQuadraticModule(V, W, gens=gens, modulus=self._modulus,
|
|
1209
|
+
modulus_qf=self._modulus_qf, check=False)
|
|
1210
|
+
|
|
1211
|
+
def twist(self, s):
|
|
1212
|
+
r"""
|
|
1213
|
+
Return the torsion quadratic module with quadratic form scaled by ``s``.
|
|
1214
|
+
|
|
1215
|
+
If the old form was defined modulo `n`, then the new form is defined
|
|
1216
|
+
modulo `n s`.
|
|
1217
|
+
|
|
1218
|
+
INPUT:
|
|
1219
|
+
|
|
1220
|
+
- ``s`` -- a rational number
|
|
1221
|
+
|
|
1222
|
+
EXAMPLES::
|
|
1223
|
+
|
|
1224
|
+
sage: q = TorsionQuadraticForm(matrix.diagonal([3/9, 1/9]))
|
|
1225
|
+
sage: q.twist(-1)
|
|
1226
|
+
Finite quadratic module over Integer Ring with invariants (3, 9)
|
|
1227
|
+
Gram matrix of the quadratic form with values in Q/Z:
|
|
1228
|
+
[2/3 0]
|
|
1229
|
+
[ 0 8/9]
|
|
1230
|
+
|
|
1231
|
+
This form is defined modulo `3`::
|
|
1232
|
+
|
|
1233
|
+
sage: q.twist(3)
|
|
1234
|
+
Finite quadratic module over Integer Ring with invariants (3, 9)
|
|
1235
|
+
Gram matrix of the quadratic form with values in Q/3Z:
|
|
1236
|
+
[ 1 0]
|
|
1237
|
+
[ 0 1/3]
|
|
1238
|
+
|
|
1239
|
+
The next form is defined modulo `4`::
|
|
1240
|
+
|
|
1241
|
+
sage: q.twist(4)
|
|
1242
|
+
Finite quadratic module over Integer Ring with invariants (3, 9)
|
|
1243
|
+
Gram matrix of the quadratic form with values in Q/4Z:
|
|
1244
|
+
[4/3 0]
|
|
1245
|
+
[ 0 4/9]
|
|
1246
|
+
"""
|
|
1247
|
+
s = self.base_ring().fraction_field()(s)
|
|
1248
|
+
n = self.V().degree()
|
|
1249
|
+
inner_product_matrix = s * self.V().inner_product_matrix()
|
|
1250
|
+
ambient = FreeQuadraticModule(self.base_ring(), n, inner_product_matrix)
|
|
1251
|
+
V = ambient.span(self.V().basis())
|
|
1252
|
+
W = ambient.span(self.W().basis())
|
|
1253
|
+
return TorsionQuadraticModule(V, W)
|
|
1254
|
+
|
|
1255
|
+
def value_module(self):
|
|
1256
|
+
r"""
|
|
1257
|
+
Return `\QQ / m\ZZ` with `m = (V, W)`.
|
|
1258
|
+
|
|
1259
|
+
This is where the inner product takes values.
|
|
1260
|
+
|
|
1261
|
+
EXAMPLES::
|
|
1262
|
+
|
|
1263
|
+
sage: A2 = Matrix(ZZ, 2, 2, [2,-1,-1,2])
|
|
1264
|
+
sage: L = IntegralLattice(2*A2)
|
|
1265
|
+
sage: D = L.discriminant_group(); D
|
|
1266
|
+
Finite quadratic module over Integer Ring with invariants (2, 6)
|
|
1267
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
1268
|
+
[ 1 1/2]
|
|
1269
|
+
[1/2 1/3]
|
|
1270
|
+
sage: D.value_module()
|
|
1271
|
+
Q/Z
|
|
1272
|
+
"""
|
|
1273
|
+
return QmodnZ(self._modulus)
|
|
1274
|
+
|
|
1275
|
+
def value_module_qf(self):
|
|
1276
|
+
r"""
|
|
1277
|
+
Return `\QQ / n\ZZ` with `n\ZZ = (V,W) + \ZZ \{ (w,w) | w \in W \}`.
|
|
1278
|
+
|
|
1279
|
+
This is where the torsion quadratic form takes values.
|
|
1280
|
+
|
|
1281
|
+
EXAMPLES::
|
|
1282
|
+
|
|
1283
|
+
sage: A2 = Matrix(ZZ, 2, 2, [2,-1,-1,2])
|
|
1284
|
+
sage: L = IntegralLattice(2 * A2)
|
|
1285
|
+
sage: D = L.discriminant_group(); D
|
|
1286
|
+
Finite quadratic module over Integer Ring with invariants (2, 6)
|
|
1287
|
+
Gram matrix of the quadratic form with values in Q/2Z:
|
|
1288
|
+
[ 1 1/2]
|
|
1289
|
+
[1/2 1/3]
|
|
1290
|
+
sage: D.value_module_qf()
|
|
1291
|
+
Q/2Z
|
|
1292
|
+
"""
|
|
1293
|
+
return QmodnZ(self._modulus_qf)
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
def _brown_indecomposable(q, p):
|
|
1297
|
+
r"""
|
|
1298
|
+
Return the Brown invariant of the indecomposable form ``q``.
|
|
1299
|
+
|
|
1300
|
+
The values are taken from Table 2.1 in [Shim2016]_.
|
|
1301
|
+
|
|
1302
|
+
INPUT:
|
|
1303
|
+
|
|
1304
|
+
- ``q`` -- an indecomposable quadratic form represented by a
|
|
1305
|
+
rational `1 \times 1` or `2 \times 2` matrix
|
|
1306
|
+
- ``p`` -- a prime number
|
|
1307
|
+
|
|
1308
|
+
EXAMPLES::
|
|
1309
|
+
|
|
1310
|
+
sage: from sage.modules.torsion_quadratic_module import _brown_indecomposable
|
|
1311
|
+
sage: q = Matrix(QQ, [1/3])
|
|
1312
|
+
sage: _brown_indecomposable(q,3)
|
|
1313
|
+
6
|
|
1314
|
+
sage: q = Matrix(QQ, [2/3])
|
|
1315
|
+
sage: _brown_indecomposable(q,3)
|
|
1316
|
+
2
|
|
1317
|
+
sage: q = Matrix(QQ, [5/4])
|
|
1318
|
+
sage: _brown_indecomposable(q,2)
|
|
1319
|
+
5
|
|
1320
|
+
sage: q = Matrix(QQ, [7/4])
|
|
1321
|
+
sage: _brown_indecomposable(q,2)
|
|
1322
|
+
7
|
|
1323
|
+
sage: q = Matrix(QQ, 2, [0,1,1,0])/2
|
|
1324
|
+
sage: _brown_indecomposable(q,2)
|
|
1325
|
+
0
|
|
1326
|
+
sage: q = Matrix(QQ, 2, [2,1,1,2])/2
|
|
1327
|
+
sage: _brown_indecomposable(q,2)
|
|
1328
|
+
4
|
|
1329
|
+
"""
|
|
1330
|
+
v = q.denominator().valuation(p)
|
|
1331
|
+
if p == 2:
|
|
1332
|
+
# brown(U) = 0
|
|
1333
|
+
if q.ncols() == 2:
|
|
1334
|
+
if q[0, 0].valuation(2) > v + 1 and q[1, 1].valuation(2) > v + 1:
|
|
1335
|
+
# type U
|
|
1336
|
+
return mod(0, 8)
|
|
1337
|
+
else:
|
|
1338
|
+
# type V
|
|
1339
|
+
return mod(4 * v, 8)
|
|
1340
|
+
u = q[0, 0].numerator()
|
|
1341
|
+
return mod(u + v * (u**2 - 1) / 2, 8)
|
|
1342
|
+
if p % 4 == 1:
|
|
1343
|
+
e = -1
|
|
1344
|
+
if p % 4 == 3:
|
|
1345
|
+
e = 1
|
|
1346
|
+
if v % 2 == 1:
|
|
1347
|
+
u = q[0, 0].numerator() // 2
|
|
1348
|
+
if legendre_symbol(u, p) == 1:
|
|
1349
|
+
return mod(1 + e, 8)
|
|
1350
|
+
else:
|
|
1351
|
+
return mod(-3 + e, 8)
|
|
1352
|
+
return mod(0, 8)
|