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,2027 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
r"""
|
|
3
|
+
Ternary quadratic form with integer coefficients
|
|
4
|
+
|
|
5
|
+
AUTHOR:
|
|
6
|
+
|
|
7
|
+
- Gustavo Rama
|
|
8
|
+
|
|
9
|
+
Based in code of Gonzalo Tornaria
|
|
10
|
+
|
|
11
|
+
The form `a\cdot x^2 + b\cdot y^2 + c\cdot z^2 + r\cdot yz + s\cdot xz + t\cdot xy` is stored as a tuple ``(a, b, c, r, s, t)`` of integers.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# ****************************************************************************
|
|
15
|
+
# Copyright (C) 2012 Gustavo Rama
|
|
16
|
+
#
|
|
17
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
18
|
+
#
|
|
19
|
+
# This code is distributed in the hope that it will be useful,
|
|
20
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
21
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
22
|
+
# General Public License for more details.
|
|
23
|
+
#
|
|
24
|
+
# The full text of the GPL is available at:
|
|
25
|
+
#
|
|
26
|
+
# https://www.gnu.org/licenses/
|
|
27
|
+
# ****************************************************************************
|
|
28
|
+
|
|
29
|
+
from sage.arith.misc import gcd, kronecker as kronecker_symbol
|
|
30
|
+
from sage.categories.rings import Rings
|
|
31
|
+
from sage.matrix.constructor import matrix, identity_matrix
|
|
32
|
+
from sage.misc.prandom import randint
|
|
33
|
+
from sage.quadratic_forms.quadratic_form import QuadraticForm
|
|
34
|
+
from sage.quadratic_forms.ternary import (_basic_lemma,
|
|
35
|
+
_find_a_ternary_qf_by_level_disc,
|
|
36
|
+
_find_all_ternary_qf_by_level_disc,
|
|
37
|
+
_find_p_neighbor_from_vec,
|
|
38
|
+
_find_zeros_mod_p_2,
|
|
39
|
+
_find_zeros_mod_p_odd,
|
|
40
|
+
_reduced_ternary_form_eisenstein_with_matrix,
|
|
41
|
+
_reduced_ternary_form_eisenstein_without_matrix)
|
|
42
|
+
|
|
43
|
+
from sage.rings.finite_rings.integer_mod import mod
|
|
44
|
+
from sage.rings.integer_ring import ZZ
|
|
45
|
+
from sage.rings.polynomial.polynomial_ring import polygens
|
|
46
|
+
from sage.structure.element import Vector, Matrix
|
|
47
|
+
from sage.structure.sage_object import SageObject
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class TernaryQF(SageObject):
|
|
51
|
+
r"""
|
|
52
|
+
The ``TernaryQF`` class represents a quadratic form in 3 variables with coefficients in `\ZZ`.
|
|
53
|
+
|
|
54
|
+
INPUT:
|
|
55
|
+
|
|
56
|
+
- ``v`` -- list or tuple of 6 entries: ``[a,b,c,r,s,t]``
|
|
57
|
+
|
|
58
|
+
OUTPUT: the ternary quadratic form `a\cdot x^2 + b\cdot y^2 + c\cdot z^2 + r\cdot y\cdot z + s\cdot x\cdot z + t\cdot x\cdot y`
|
|
59
|
+
|
|
60
|
+
EXAMPLES::
|
|
61
|
+
|
|
62
|
+
sage: Q = TernaryQF([1, 2, 3, 4, 5, 6]); Q
|
|
63
|
+
Ternary quadratic form with integer coefficients:
|
|
64
|
+
[1 2 3]
|
|
65
|
+
[4 5 6]
|
|
66
|
+
sage: A = matrix(ZZ, 3, [1, -7, 1, 0, -2, 1, 0, -1, 0])
|
|
67
|
+
sage: Q(A)
|
|
68
|
+
Ternary quadratic form with integer coefficients:
|
|
69
|
+
[1 187 9]
|
|
70
|
+
[-85 8 -31]
|
|
71
|
+
sage: TestSuite(TernaryQF).run()
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
__slots__ = ['_a', '_b', '_c', '_r', '_s', '_t',
|
|
75
|
+
'_automorphisms', '_number_of_automorphisms']
|
|
76
|
+
|
|
77
|
+
possible_automorphisms = None
|
|
78
|
+
|
|
79
|
+
def __init__(self, v):
|
|
80
|
+
r"""
|
|
81
|
+
Create the ternary quadratic form `a\cdot x^2 + b\cdot y^2 + c\cdot z^2 + r\cdot y\cdot z + s\cdot x\cdot z + t\cdot x\cdot y` from the
|
|
82
|
+
tuple ``v=[a,b,c,r,s,t]`` over `\ZZ`.
|
|
83
|
+
|
|
84
|
+
INPUT:
|
|
85
|
+
|
|
86
|
+
- ``v`` -- 6-tuple of integers
|
|
87
|
+
|
|
88
|
+
EXAMPLES::
|
|
89
|
+
|
|
90
|
+
sage: Q = TernaryQF([1, 2, 3, 4, 5, 6]); Q
|
|
91
|
+
Ternary quadratic form with integer coefficients:
|
|
92
|
+
[1 2 3]
|
|
93
|
+
[4 5 6]
|
|
94
|
+
"""
|
|
95
|
+
if len(v) != 6:
|
|
96
|
+
# Check we have six coefficients
|
|
97
|
+
raise ValueError("Ternary quadratic form must be given by a list of six coefficients")
|
|
98
|
+
self._a, self._b, self._c, self._r, self._s, self._t = (ZZ(x) for x in v)
|
|
99
|
+
self._automorphisms = None
|
|
100
|
+
self._number_of_automorphisms = None
|
|
101
|
+
|
|
102
|
+
def coefficients(self) -> tuple:
|
|
103
|
+
r"""
|
|
104
|
+
Return the tuple of coefficients of the ternary quadratic form.
|
|
105
|
+
|
|
106
|
+
EXAMPLES::
|
|
107
|
+
|
|
108
|
+
sage: Q = TernaryQF([1, 2, 3, 4, 5, 6]); Q
|
|
109
|
+
Ternary quadratic form with integer coefficients:
|
|
110
|
+
[1 2 3]
|
|
111
|
+
[4 5 6]
|
|
112
|
+
sage: Q.coefficients()
|
|
113
|
+
(1, 2, 3, 4, 5, 6)
|
|
114
|
+
"""
|
|
115
|
+
return self._a, self._b, self._c, self._r, self._s, self._t
|
|
116
|
+
|
|
117
|
+
def __hash__(self) -> int:
|
|
118
|
+
"""
|
|
119
|
+
Return a hash for ``self``.
|
|
120
|
+
|
|
121
|
+
EXAMPLES::
|
|
122
|
+
|
|
123
|
+
sage: Q = TernaryQF([1, 2, 3, 4, 5, 6])
|
|
124
|
+
sage: Q.__hash__()
|
|
125
|
+
5881802312257552497 # 64-bit
|
|
126
|
+
1770036893 # 32-bit
|
|
127
|
+
"""
|
|
128
|
+
return hash(self.coefficients())
|
|
129
|
+
|
|
130
|
+
def coefficient(self, n):
|
|
131
|
+
r"""
|
|
132
|
+
Return the `n`-th coefficient of the ternary quadratic form.
|
|
133
|
+
|
|
134
|
+
INPUT:
|
|
135
|
+
|
|
136
|
+
- ``n`` -- integer with `0 \leq n \leq 5`
|
|
137
|
+
|
|
138
|
+
EXAMPLES::
|
|
139
|
+
|
|
140
|
+
sage: Q = TernaryQF([1, 2, 3, 4, 5, 6]); Q
|
|
141
|
+
Ternary quadratic form with integer coefficients:
|
|
142
|
+
[1 2 3]
|
|
143
|
+
[4 5 6]
|
|
144
|
+
sage: Q.coefficient(2)
|
|
145
|
+
3
|
|
146
|
+
sage: Q.coefficient(5)
|
|
147
|
+
6
|
|
148
|
+
"""
|
|
149
|
+
return self.coefficients()[n]
|
|
150
|
+
|
|
151
|
+
def polynomial(self, names='x,y,z'):
|
|
152
|
+
r"""
|
|
153
|
+
Return the polynomial associated to the ternary quadratic form.
|
|
154
|
+
|
|
155
|
+
EXAMPLES::
|
|
156
|
+
|
|
157
|
+
sage: Q = TernaryQF([1, 1, 0, 2, -3, -1]); Q
|
|
158
|
+
Ternary quadratic form with integer coefficients:
|
|
159
|
+
[1 1 0]
|
|
160
|
+
[2 -3 -1]
|
|
161
|
+
sage: p = Q.polynomial(); p
|
|
162
|
+
x^2 - x*y + y^2 - 3*x*z + 2*y*z
|
|
163
|
+
sage: p.parent()
|
|
164
|
+
Multivariate Polynomial Ring in x, y, z over Integer Ring
|
|
165
|
+
"""
|
|
166
|
+
x, y, z = polygens(ZZ, names)
|
|
167
|
+
return self._a * x**2 + self._b * y**2 + self._c * z**2 + self._t * x*y + self._s * x*z + self._r * y*z
|
|
168
|
+
|
|
169
|
+
def _repr_(self) -> str:
|
|
170
|
+
r"""
|
|
171
|
+
Display the quadratic form.
|
|
172
|
+
|
|
173
|
+
EXAMPLES::
|
|
174
|
+
|
|
175
|
+
sage: Q = TernaryQF([1, 1, 0, 2, -3, -1])
|
|
176
|
+
sage: print(Q._repr_())
|
|
177
|
+
Ternary quadratic form with integer coefficients:
|
|
178
|
+
[1 1 0]
|
|
179
|
+
[2 -3 -1]
|
|
180
|
+
sage: Q = TernaryQF([0, 0, 0, 0, 0, 0]); Q
|
|
181
|
+
Ternary quadratic form with integer coefficients:
|
|
182
|
+
[0 0 0]
|
|
183
|
+
[0 0 0]
|
|
184
|
+
"""
|
|
185
|
+
rep = 'Ternary quadratic form with integer coefficients:\n'
|
|
186
|
+
rep += '[' + str(self._a) + ' ' + str(self._b) + ' ' + str(self._c) + ']\n'
|
|
187
|
+
rep += '[' + str(self._r) + ' ' + str(self._s) + ' ' + str(self._t) + ']'
|
|
188
|
+
return rep
|
|
189
|
+
|
|
190
|
+
def __call__(self, v):
|
|
191
|
+
r"""
|
|
192
|
+
Evaluate this ternary quadratic form `Q` on a vector of 3 elements,
|
|
193
|
+
or matrix of elements in Z, with 3 rows.
|
|
194
|
+
|
|
195
|
+
OUTPUT:
|
|
196
|
+
|
|
197
|
+
If a vector is given, then the output will be an integer `Q(v)`,
|
|
198
|
+
but if a matrix is given, the output will be a ternary quadratic form
|
|
199
|
+
if the matrix has 3 columns, or a quadratic form if not.
|
|
200
|
+
The quadratic form in matrix notation will be:
|
|
201
|
+
|
|
202
|
+
.. MATH::
|
|
203
|
+
|
|
204
|
+
Q' = v^t\cdot Q\cdot v.
|
|
205
|
+
|
|
206
|
+
EXAMPLES::
|
|
207
|
+
|
|
208
|
+
sage: Q = TernaryQF([1, 1, 1, -1, -2, -3])
|
|
209
|
+
sage: Q((1, 1, 1))
|
|
210
|
+
-3
|
|
211
|
+
sage: M = matrix(ZZ, 3, 2, [358, 6, 2, 0, 0, 4])
|
|
212
|
+
sage: Q(M)
|
|
213
|
+
Quadratic form in 2 variables over Integer Ring with coefficients:
|
|
214
|
+
[ 126020 1388 ]
|
|
215
|
+
[ * 4 ]
|
|
216
|
+
sage: M = matrix(ZZ, 3, 3, [1, 3, 0, -1, 4, 2, 1, -1, -1])
|
|
217
|
+
sage: M
|
|
218
|
+
[ 1 3 0]
|
|
219
|
+
[-1 4 2]
|
|
220
|
+
[ 1 -1 -1]
|
|
221
|
+
sage: Q(M)
|
|
222
|
+
Ternary quadratic form with integer coefficients:
|
|
223
|
+
[5 0 7]
|
|
224
|
+
[12 -13 -16]
|
|
225
|
+
"""
|
|
226
|
+
if isinstance(v, Matrix):
|
|
227
|
+
# Check that v has 3 rows
|
|
228
|
+
if v.nrows() != 3:
|
|
229
|
+
raise TypeError("the matrix must have 3 rows")
|
|
230
|
+
# Check if v has 3 cols
|
|
231
|
+
if v.ncols() == 3:
|
|
232
|
+
M = v.transpose() * self.matrix() * v
|
|
233
|
+
return TernaryQF([M[0, 0] // 2, M[1, 1] // 2, M[2, 2] // 2,
|
|
234
|
+
M[1, 2], M[0, 2], M[0, 1]])
|
|
235
|
+
|
|
236
|
+
return QuadraticForm(ZZ, v.transpose() * self.matrix() * v)
|
|
237
|
+
if isinstance(v, (Vector, list, tuple)):
|
|
238
|
+
# Check that v has length 3
|
|
239
|
+
if len(v) != 3:
|
|
240
|
+
raise TypeError("your vector needs to have length 3")
|
|
241
|
+
v0, v1, v2 = v
|
|
242
|
+
a, b, c, r, s, t = self.coefficients()
|
|
243
|
+
return a*v0**2 + b*v1**2 + c*v2**2 + r*v1*v2 + s*v0*v2 + t*v0*v1
|
|
244
|
+
|
|
245
|
+
raise TypeError("presently we can only evaluate a quadratic form on a list, tuple, vector or matrix")
|
|
246
|
+
|
|
247
|
+
def quadratic_form(self):
|
|
248
|
+
r"""
|
|
249
|
+
Return a :class:`QuadraticForm` with the same coefficients as ``self`` over `\ZZ`.
|
|
250
|
+
|
|
251
|
+
EXAMPLES::
|
|
252
|
+
|
|
253
|
+
sage: Q = TernaryQF([1, 2, 3, 1, 1, 1])
|
|
254
|
+
sage: QF1 = Q.quadratic_form(); QF1
|
|
255
|
+
Quadratic form in 3 variables over Integer Ring with coefficients:
|
|
256
|
+
[ 1 1 1 ]
|
|
257
|
+
[ * 2 1 ]
|
|
258
|
+
[ * * 3 ]
|
|
259
|
+
sage: QF2 = QuadraticForm(ZZ, 3, [1, 1, 1, 2, 1, 3])
|
|
260
|
+
sage: bool(QF1 == QF2)
|
|
261
|
+
True
|
|
262
|
+
"""
|
|
263
|
+
return QuadraticForm(ZZ, 3, [self._a, self._t, self._s,
|
|
264
|
+
self._b, self._r, self._c])
|
|
265
|
+
|
|
266
|
+
def matrix(self):
|
|
267
|
+
r"""
|
|
268
|
+
Return the Hessian matrix associated to the ternary quadratic form.
|
|
269
|
+
|
|
270
|
+
That is, if `Q` is a ternary quadratic form, `Q(x,y,z) = a\cdot x^2 + b\cdot y^2 + c\cdot z^2 + r\cdot y\cdot z + s\cdot x\cdot z + t\cdot x\cdot y`,
|
|
271
|
+
then the Hessian matrix associated to `Q` is
|
|
272
|
+
::
|
|
273
|
+
|
|
274
|
+
[2\cdot a t s]
|
|
275
|
+
[t 2\cdot b r]
|
|
276
|
+
[s r 2\cdot c]
|
|
277
|
+
|
|
278
|
+
EXAMPLES::
|
|
279
|
+
|
|
280
|
+
sage: Q = TernaryQF([1,1,2,0,-1,4]); Q
|
|
281
|
+
Ternary quadratic form with integer coefficients:
|
|
282
|
+
[1 1 2]
|
|
283
|
+
[0 -1 4]
|
|
284
|
+
sage: M = Q.matrix(); M
|
|
285
|
+
[ 2 4 -1]
|
|
286
|
+
[ 4 2 0]
|
|
287
|
+
[-1 0 4]
|
|
288
|
+
sage: v = vector((1, 2, 3))
|
|
289
|
+
sage: Q(v)
|
|
290
|
+
28
|
|
291
|
+
sage: (v*M*v.column())[0]//2
|
|
292
|
+
28
|
|
293
|
+
"""
|
|
294
|
+
return matrix(ZZ, 3, 3, [2 * self._a, self._t, self._s,
|
|
295
|
+
self._t, 2 * self._b, self._r,
|
|
296
|
+
self._s, self._r, 2 * self._c])
|
|
297
|
+
|
|
298
|
+
def disc(self):
|
|
299
|
+
r"""
|
|
300
|
+
Return the discriminant of the ternary quadratic form.
|
|
301
|
+
|
|
302
|
+
This is the determinant of the matrix divided by 2.
|
|
303
|
+
|
|
304
|
+
EXAMPLES::
|
|
305
|
+
|
|
306
|
+
sage: Q = TernaryQF([1, 1, 2, 0, -1, 4])
|
|
307
|
+
sage: Q.disc()
|
|
308
|
+
-25
|
|
309
|
+
sage: Q.matrix().det()
|
|
310
|
+
-50
|
|
311
|
+
"""
|
|
312
|
+
return (4*self._a*self._b*self._c + self._r*self._s*self._t
|
|
313
|
+
- self._a*self._r**2 - self._b*self._s**2 - self._c*self._t**2)
|
|
314
|
+
|
|
315
|
+
def is_definite(self) -> bool:
|
|
316
|
+
"""
|
|
317
|
+
Determine if the ternary quadratic form is definite.
|
|
318
|
+
|
|
319
|
+
EXAMPLES::
|
|
320
|
+
|
|
321
|
+
sage: Q = TernaryQF([10, 10, 1, -1, 2, 3])
|
|
322
|
+
sage: Q.is_definite()
|
|
323
|
+
True
|
|
324
|
+
sage: (-Q).is_definite()
|
|
325
|
+
True
|
|
326
|
+
sage: Q = TernaryQF([1, 1, 2, -3, 0, -1])
|
|
327
|
+
sage: Q.is_definite()
|
|
328
|
+
False
|
|
329
|
+
"""
|
|
330
|
+
d1 = self._a
|
|
331
|
+
if d1 == 0:
|
|
332
|
+
return False
|
|
333
|
+
d2 = 4 * self._a * self._b - self._t**2
|
|
334
|
+
if d2 <= 0:
|
|
335
|
+
return False
|
|
336
|
+
d3 = self.disc()
|
|
337
|
+
if d3 == 0:
|
|
338
|
+
return False
|
|
339
|
+
return (d1 > 0) == (d3 > 0)
|
|
340
|
+
|
|
341
|
+
def is_positive_definite(self) -> bool:
|
|
342
|
+
"""
|
|
343
|
+
Determine if the ternary quadratic form is positive definite.
|
|
344
|
+
|
|
345
|
+
EXAMPLES::
|
|
346
|
+
|
|
347
|
+
sage: Q = TernaryQF([10, 10, 1, -1, 2, 3])
|
|
348
|
+
sage: Q.is_positive_definite()
|
|
349
|
+
True
|
|
350
|
+
sage: (-Q).is_positive_definite()
|
|
351
|
+
False
|
|
352
|
+
sage: Q = TernaryQF([1, 1, 0, 0, 0, 0])
|
|
353
|
+
sage: Q.is_positive_definite()
|
|
354
|
+
False
|
|
355
|
+
sage: Q = TernaryQF([1, 1, 1, -1, -2, -3])
|
|
356
|
+
sage: Q((1,1,1))
|
|
357
|
+
-3
|
|
358
|
+
sage: Q.is_positive_definite()
|
|
359
|
+
False
|
|
360
|
+
"""
|
|
361
|
+
d1 = self._a
|
|
362
|
+
if d1 == 0:
|
|
363
|
+
return False
|
|
364
|
+
d2 = 4 * self._a * self._b - self._t**2
|
|
365
|
+
if d2 <= 0:
|
|
366
|
+
return False
|
|
367
|
+
d3 = self.disc()
|
|
368
|
+
if d3 == 0:
|
|
369
|
+
return False
|
|
370
|
+
return d1 > 0 and d3 > 0
|
|
371
|
+
|
|
372
|
+
def is_negative_definite(self) -> bool:
|
|
373
|
+
"""
|
|
374
|
+
Determine if the ternary quadratic form is negative definite.
|
|
375
|
+
|
|
376
|
+
EXAMPLES::
|
|
377
|
+
|
|
378
|
+
sage: Q = TernaryQF([-8, -9, -10, 1, 9, -3])
|
|
379
|
+
sage: Q.is_negative_definite()
|
|
380
|
+
True
|
|
381
|
+
sage: Q = TernaryQF([-4, -1, 6, -5, 1, -5])
|
|
382
|
+
sage: Q((0, 0, 1))
|
|
383
|
+
6
|
|
384
|
+
sage: Q.is_negative_definite()
|
|
385
|
+
False
|
|
386
|
+
"""
|
|
387
|
+
d1 = self._a
|
|
388
|
+
if d1 == 0:
|
|
389
|
+
return False
|
|
390
|
+
d2 = 4 * self._a * self._b - self._t**2
|
|
391
|
+
if d2 <= 0:
|
|
392
|
+
return False
|
|
393
|
+
d3 = self.disc()
|
|
394
|
+
if d3 == 0:
|
|
395
|
+
return False
|
|
396
|
+
return d1 < 0 and d3 < 0
|
|
397
|
+
|
|
398
|
+
def __neg__(self):
|
|
399
|
+
"""
|
|
400
|
+
Return the ternary quadratic form with coefficients negatives of ``self``.
|
|
401
|
+
|
|
402
|
+
EXAMPLES::
|
|
403
|
+
|
|
404
|
+
sage: Q = TernaryQF([1, 1, 2, -2, 0, -1]); Q
|
|
405
|
+
Ternary quadratic form with integer coefficients:
|
|
406
|
+
[1 1 2]
|
|
407
|
+
[-2 0 -1]
|
|
408
|
+
sage: -Q
|
|
409
|
+
Ternary quadratic form with integer coefficients:
|
|
410
|
+
[-1 -1 -2]
|
|
411
|
+
[2 0 1]
|
|
412
|
+
sage: Q = TernaryQF([0, 0, 0, 0, 0, 0])
|
|
413
|
+
sage: Q == -Q
|
|
414
|
+
True
|
|
415
|
+
"""
|
|
416
|
+
return TernaryQF([-a for a in self.coefficients()])
|
|
417
|
+
|
|
418
|
+
def is_primitive(self) -> bool:
|
|
419
|
+
"""
|
|
420
|
+
Determine if the ternary quadratic form is primitive.
|
|
421
|
+
|
|
422
|
+
This means that the greatest common divisor of the coefficients
|
|
423
|
+
of the form is 1.
|
|
424
|
+
|
|
425
|
+
EXAMPLES::
|
|
426
|
+
|
|
427
|
+
sage: Q = TernaryQF([1, 2, 3, 4, 5, 6])
|
|
428
|
+
sage: Q.is_primitive()
|
|
429
|
+
True
|
|
430
|
+
sage: Q.content()
|
|
431
|
+
1
|
|
432
|
+
sage: Q = TernaryQF([10, 10, 10, 5, 5, 5])
|
|
433
|
+
sage: Q.content()
|
|
434
|
+
5
|
|
435
|
+
sage: Q.is_primitive()
|
|
436
|
+
False
|
|
437
|
+
"""
|
|
438
|
+
return self.content() == 1
|
|
439
|
+
|
|
440
|
+
def primitive(self):
|
|
441
|
+
"""
|
|
442
|
+
Return the primitive version of the ternary quadratic form.
|
|
443
|
+
|
|
444
|
+
EXAMPLES::
|
|
445
|
+
|
|
446
|
+
sage: Q = TernaryQF([2, 2, 2, 1, 1, 1])
|
|
447
|
+
sage: Q.is_primitive()
|
|
448
|
+
True
|
|
449
|
+
sage: Q.primitive()
|
|
450
|
+
Ternary quadratic form with integer coefficients:
|
|
451
|
+
[2 2 2]
|
|
452
|
+
[1 1 1]
|
|
453
|
+
sage: Q.primitive() == Q
|
|
454
|
+
True
|
|
455
|
+
sage: Q = TernaryQF([10, 10, 10, 5, 5, 5])
|
|
456
|
+
sage: Q.primitive()
|
|
457
|
+
Ternary quadratic form with integer coefficients:
|
|
458
|
+
[2 2 2]
|
|
459
|
+
[1 1 1]
|
|
460
|
+
"""
|
|
461
|
+
l = self.coefficients()
|
|
462
|
+
g = gcd(l)
|
|
463
|
+
return TernaryQF([a // g for a in l])
|
|
464
|
+
|
|
465
|
+
def scale_by_factor(self, k):
|
|
466
|
+
"""
|
|
467
|
+
Scale the values of the ternary quadratic form by the number ``k``.
|
|
468
|
+
|
|
469
|
+
OUTPUT:
|
|
470
|
+
|
|
471
|
+
If ``k`` times the content of the ternary quadratic form is an integer, return a ternary quadratic form;
|
|
472
|
+
otherwise, return a quadratic form of dimension 3.
|
|
473
|
+
|
|
474
|
+
EXAMPLES::
|
|
475
|
+
|
|
476
|
+
sage: Q = TernaryQF([2, 2, 4, 0, -2, 8])
|
|
477
|
+
sage: Q
|
|
478
|
+
Ternary quadratic form with integer coefficients:
|
|
479
|
+
[2 2 4]
|
|
480
|
+
[0 -2 8]
|
|
481
|
+
sage: Q.scale_by_factor(5)
|
|
482
|
+
Ternary quadratic form with integer coefficients:
|
|
483
|
+
[10 10 20]
|
|
484
|
+
[0 -10 40]
|
|
485
|
+
sage: Q.scale_by_factor(1/2)
|
|
486
|
+
Ternary quadratic form with integer coefficients:
|
|
487
|
+
[1 1 2]
|
|
488
|
+
[0 -1 4]
|
|
489
|
+
sage: Q.scale_by_factor(1/3)
|
|
490
|
+
Quadratic form in 3 variables over Rational Field with coefficients:
|
|
491
|
+
[ 2/3 8/3 -2/3 ]
|
|
492
|
+
[ * 2/3 0 ]
|
|
493
|
+
[ * * 4/3 ]
|
|
494
|
+
"""
|
|
495
|
+
if k * self.content() in ZZ:
|
|
496
|
+
return TernaryQF([ZZ(k*self._a), ZZ(k*self._b), ZZ(k*self._c),
|
|
497
|
+
ZZ(k*self._r), ZZ(k*self._s), ZZ(k*self._t)])
|
|
498
|
+
|
|
499
|
+
R = k.parent()
|
|
500
|
+
if R not in Rings():
|
|
501
|
+
raise TypeError(f"{k} does not belong to a ring")
|
|
502
|
+
|
|
503
|
+
return QuadraticForm(R, 3, [k * self._a, k * self._t, k * self._s,
|
|
504
|
+
k * self._b, k * self._r, k * self._c])
|
|
505
|
+
|
|
506
|
+
def reciprocal(self):
|
|
507
|
+
"""
|
|
508
|
+
Return the reciprocal quadratic form associated to the given form.
|
|
509
|
+
|
|
510
|
+
This is defined as the multiple of the primitive adjoint with the same
|
|
511
|
+
content as the given form.
|
|
512
|
+
|
|
513
|
+
EXAMPLES::
|
|
514
|
+
|
|
515
|
+
sage: Q = TernaryQF([2, 2, 14, 0, 0, 0])
|
|
516
|
+
sage: Q.reciprocal()
|
|
517
|
+
Ternary quadratic form with integer coefficients:
|
|
518
|
+
[14 14 2]
|
|
519
|
+
[0 0 0]
|
|
520
|
+
sage: Q.content()
|
|
521
|
+
2
|
|
522
|
+
sage: Q.reciprocal().content()
|
|
523
|
+
2
|
|
524
|
+
sage: Q.adjoint().content()
|
|
525
|
+
16
|
|
526
|
+
"""
|
|
527
|
+
return self.adjoint().primitive().scale_by_factor(self.content())
|
|
528
|
+
|
|
529
|
+
def reciprocal_reduced(self):
|
|
530
|
+
"""
|
|
531
|
+
Return the reduced form of the reciprocal form of the given ternary quadratic form.
|
|
532
|
+
|
|
533
|
+
EXAMPLES::
|
|
534
|
+
|
|
535
|
+
sage: Q = TernaryQF([1, 1, 3, 0, -1, 0])
|
|
536
|
+
sage: Qrr = Q.reciprocal_reduced(); Qrr
|
|
537
|
+
Ternary quadratic form with integer coefficients:
|
|
538
|
+
[4 11 12]
|
|
539
|
+
[0 -4 0]
|
|
540
|
+
sage: Q.is_eisenstein_reduced()
|
|
541
|
+
True
|
|
542
|
+
sage: Qr = Q.reciprocal()
|
|
543
|
+
sage: Qr.reduced_form_eisenstein(matrix=False) == Qrr
|
|
544
|
+
True
|
|
545
|
+
"""
|
|
546
|
+
return self.reciprocal().reduced_form_eisenstein(matrix=False)
|
|
547
|
+
|
|
548
|
+
def divisor(self):
|
|
549
|
+
"""
|
|
550
|
+
Return the content of the adjoint form associated to the given form.
|
|
551
|
+
|
|
552
|
+
EXAMPLES::
|
|
553
|
+
|
|
554
|
+
sage: Q = TernaryQF([1, 1, 17, 0, 0, 0])
|
|
555
|
+
sage: Q.divisor()
|
|
556
|
+
4
|
|
557
|
+
"""
|
|
558
|
+
A11 = 4*self._b*self._c - self._r**2
|
|
559
|
+
A22 = 4*self._a*self._c - self._s**2
|
|
560
|
+
A33 = 4*self._a*self._b - self._t**2
|
|
561
|
+
A23 = self._s*self._t - 2*self._a*self._r
|
|
562
|
+
A13 = self._r*self._t - 2*self._b*self._s
|
|
563
|
+
A12 = self._r*self._s - 2*self._c*self._t
|
|
564
|
+
m = gcd([A11, A22, A33, 2*A12, 2*A13, 2*A23])
|
|
565
|
+
return m
|
|
566
|
+
|
|
567
|
+
def __eq__(self, right) -> bool:
|
|
568
|
+
"""
|
|
569
|
+
Determine if two ternary quadratic forms are equal.
|
|
570
|
+
|
|
571
|
+
EXAMPLES::
|
|
572
|
+
|
|
573
|
+
sage: Q = TernaryQF([1, 2, 3, 1, 2, 3])
|
|
574
|
+
sage: Q == Q
|
|
575
|
+
True
|
|
576
|
+
sage: Q1 = TernaryQF([1, 2, 3, 1, 2, 2])
|
|
577
|
+
sage: Q == Q1
|
|
578
|
+
False
|
|
579
|
+
"""
|
|
580
|
+
if not isinstance(right, TernaryQF):
|
|
581
|
+
return False
|
|
582
|
+
return self.coefficients() == right.coefficients()
|
|
583
|
+
|
|
584
|
+
def adjoint(self):
|
|
585
|
+
"""
|
|
586
|
+
Return the adjoint form associated to the given ternary quadratic
|
|
587
|
+
form.
|
|
588
|
+
|
|
589
|
+
That is, the Hessian matrix of the adjoint form is twice the
|
|
590
|
+
classical adjoint matrix of the Hessian matrix of the given form.
|
|
591
|
+
|
|
592
|
+
EXAMPLES::
|
|
593
|
+
|
|
594
|
+
sage: Q = TernaryQF([1, 1, 17, 0, 0, 1])
|
|
595
|
+
sage: Q.adjoint()
|
|
596
|
+
Ternary quadratic form with integer coefficients:
|
|
597
|
+
[68 68 3]
|
|
598
|
+
[0 0 -68]
|
|
599
|
+
sage: Q.adjoint().matrix() == 2*Q.matrix().adjoint_classical() # needs sage.libs.pari
|
|
600
|
+
True
|
|
601
|
+
"""
|
|
602
|
+
A11 = 4*self._b*self._c - self._r**2
|
|
603
|
+
A22 = 4*self._a*self._c - self._s**2
|
|
604
|
+
A33 = 4*self._a*self._b - self._t**2
|
|
605
|
+
A23 = self._s*self._t - 2*self._a*self._r
|
|
606
|
+
A13 = self._r*self._t - 2*self._b*self._s
|
|
607
|
+
A12 = self._r*self._s - 2*self._c*self._t
|
|
608
|
+
return TernaryQF([A11, A22, A33, 2*A23, 2*A13, 2*A12])
|
|
609
|
+
|
|
610
|
+
def content(self):
|
|
611
|
+
"""
|
|
612
|
+
Return the greatest common divisor of the coefficients of the given ternary quadratic form.
|
|
613
|
+
|
|
614
|
+
EXAMPLES::
|
|
615
|
+
|
|
616
|
+
sage: Q = TernaryQF([1, 1, 2, 0, 0, 0])
|
|
617
|
+
sage: Q.content()
|
|
618
|
+
1
|
|
619
|
+
sage: Q = TernaryQF([2, 4, 6, 0, 0, 0])
|
|
620
|
+
sage: Q.content()
|
|
621
|
+
2
|
|
622
|
+
sage: Q.scale_by_factor(100).content()
|
|
623
|
+
200
|
|
624
|
+
"""
|
|
625
|
+
return gcd(self.coefficients())
|
|
626
|
+
|
|
627
|
+
def omega(self):
|
|
628
|
+
"""
|
|
629
|
+
Return the content of the adjoint of the primitive associated
|
|
630
|
+
ternary quadratic form.
|
|
631
|
+
|
|
632
|
+
EXAMPLES::
|
|
633
|
+
|
|
634
|
+
sage: Q = TernaryQF([4, 11, 12, 0, -4, 0])
|
|
635
|
+
sage: Q.omega()
|
|
636
|
+
176
|
|
637
|
+
sage: Q.primitive().adjoint().content()
|
|
638
|
+
176
|
|
639
|
+
"""
|
|
640
|
+
return self.primitive().adjoint().content()
|
|
641
|
+
|
|
642
|
+
def delta(self):
|
|
643
|
+
"""
|
|
644
|
+
Return the omega of the adjoint of the given ternary quadratic form,
|
|
645
|
+
which is the same as the omega of the reciprocal form.
|
|
646
|
+
|
|
647
|
+
EXAMPLES::
|
|
648
|
+
|
|
649
|
+
sage: Q = TernaryQF([1, 2, 2, -1, 0, -1])
|
|
650
|
+
sage: Q.delta()
|
|
651
|
+
208
|
|
652
|
+
sage: Q.adjoint().omega()
|
|
653
|
+
208
|
|
654
|
+
sage: Q = TernaryQF([1, -1, 1, 0, 0, 0])
|
|
655
|
+
sage: Q.delta()
|
|
656
|
+
4
|
|
657
|
+
sage: Q.omega()
|
|
658
|
+
4
|
|
659
|
+
"""
|
|
660
|
+
return self.adjoint().omega()
|
|
661
|
+
|
|
662
|
+
def level(self):
|
|
663
|
+
"""
|
|
664
|
+
Return the level of the ternary quadratic form, which is 4 times the discriminant divided by the divisor.
|
|
665
|
+
|
|
666
|
+
EXAMPLES::
|
|
667
|
+
|
|
668
|
+
sage: Q = TernaryQF([1, 2, 2, -1, 0, -1])
|
|
669
|
+
sage: Q.level()
|
|
670
|
+
52
|
|
671
|
+
sage: 4*Q.disc()/Q.divisor()
|
|
672
|
+
52
|
|
673
|
+
"""
|
|
674
|
+
return 4 * self.disc() // self.divisor()
|
|
675
|
+
|
|
676
|
+
def is_eisenstein_reduced(self) -> bool:
|
|
677
|
+
r"""
|
|
678
|
+
Determine if the ternary quadratic form is Eisenstein reduced.
|
|
679
|
+
|
|
680
|
+
That is, if we have a ternary quadratic form:
|
|
681
|
+
::
|
|
682
|
+
|
|
683
|
+
[a b c]
|
|
684
|
+
[r s t]
|
|
685
|
+
|
|
686
|
+
then
|
|
687
|
+
|
|
688
|
+
1. `a \leq b \leq c`;
|
|
689
|
+
2. `r`, `s`, and `t` are all positive or all nonpositive;
|
|
690
|
+
3. `a \geq |t|`; `a \geq |s|`; `b \geq |r|`;
|
|
691
|
+
4. `a+b+r+s+t \geq 0`;
|
|
692
|
+
5. `a=t` implies `s \leq 2\cdot r`; `a=s` implies `t \leq 2\cdot r`; `b=r` implies `t \leq 2\cdot s`;
|
|
693
|
+
6. `a=-t` implies `s=0`; `a=-s` implies `t=0`; `b=-r` implies `t=0`;
|
|
694
|
+
7. `a+b+r+s+t = 0` implies `2\cdot a+2\cdot s+t \leq 0`;
|
|
695
|
+
8. `a=b` implies `|r| \leq |s|`; `b=c` implies `|s| \leq |t|`.
|
|
696
|
+
|
|
697
|
+
EXAMPLES::
|
|
698
|
+
|
|
699
|
+
sage: Q = TernaryQF([1, 1, 1, 0, 0, 0])
|
|
700
|
+
sage: Q.is_eisenstein_reduced()
|
|
701
|
+
True
|
|
702
|
+
sage: Q = TernaryQF([34, 14, 44, 12, 25, -22])
|
|
703
|
+
sage: Q.is_eisenstein_reduced()
|
|
704
|
+
False
|
|
705
|
+
"""
|
|
706
|
+
a, b, c, r, s, t = [self._a, self._b, self._c,
|
|
707
|
+
self._r, self._s, self._t]
|
|
708
|
+
|
|
709
|
+
# cond 2
|
|
710
|
+
if not (r > 0 and t > 0 and s > 0):
|
|
711
|
+
if not (r <= 0 and s <= 0 and t <= 0):
|
|
712
|
+
return False
|
|
713
|
+
|
|
714
|
+
# cond 1 & 4
|
|
715
|
+
if not (a <= b <= c and 0 <= a+b+r+s+t):
|
|
716
|
+
return False
|
|
717
|
+
|
|
718
|
+
# cond 3
|
|
719
|
+
if not (a >= abs(s) and a >= abs(t) and b >= abs(r)):
|
|
720
|
+
return False
|
|
721
|
+
|
|
722
|
+
# cond 8
|
|
723
|
+
if a == b and abs(r) > abs(s):
|
|
724
|
+
return False
|
|
725
|
+
if b == c and abs(s) > abs(t):
|
|
726
|
+
return False
|
|
727
|
+
if a+b+r+s+t == 0 and 2*a+2*s+t > 0:
|
|
728
|
+
return False
|
|
729
|
+
|
|
730
|
+
# cond 6
|
|
731
|
+
# r, s, t <= 0
|
|
732
|
+
if r <= 0:
|
|
733
|
+
if a == -t and s != 0:
|
|
734
|
+
return False
|
|
735
|
+
if a == -s and t != 0:
|
|
736
|
+
return False
|
|
737
|
+
if b == -r and t != 0:
|
|
738
|
+
return False
|
|
739
|
+
|
|
740
|
+
# cond 7
|
|
741
|
+
# r, s, t > 0
|
|
742
|
+
if a == t and s > 2*r:
|
|
743
|
+
return False
|
|
744
|
+
if a == s and t > 2*r:
|
|
745
|
+
return False
|
|
746
|
+
if b == r and t > 2*s:
|
|
747
|
+
return False
|
|
748
|
+
|
|
749
|
+
return True
|
|
750
|
+
|
|
751
|
+
def reduced_form_eisenstein(self, matrix=True):
|
|
752
|
+
r"""
|
|
753
|
+
Return the Eisenstein reduced form equivalent to the given positive ternary quadratic form,
|
|
754
|
+
which is unique.
|
|
755
|
+
|
|
756
|
+
EXAMPLES::
|
|
757
|
+
|
|
758
|
+
sage: Q = TernaryQF([293, 315, 756, 908, 929, 522])
|
|
759
|
+
sage: Qr, m = Q.reduced_form_eisenstein()
|
|
760
|
+
sage: Qr
|
|
761
|
+
Ternary quadratic form with integer coefficients:
|
|
762
|
+
[1 2 2]
|
|
763
|
+
[-1 0 -1]
|
|
764
|
+
sage: Qr.is_eisenstein_reduced()
|
|
765
|
+
True
|
|
766
|
+
sage: m
|
|
767
|
+
[ -54 137 -38]
|
|
768
|
+
[ -23 58 -16]
|
|
769
|
+
[ 47 -119 33]
|
|
770
|
+
sage: m.det()
|
|
771
|
+
1
|
|
772
|
+
sage: Q(m) == Qr
|
|
773
|
+
True
|
|
774
|
+
sage: Q = TernaryQF([12,36,3,14,-7,-19])
|
|
775
|
+
sage: Q.reduced_form_eisenstein(matrix = False)
|
|
776
|
+
Ternary quadratic form with integer coefficients:
|
|
777
|
+
[3 8 20]
|
|
778
|
+
[3 2 1]
|
|
779
|
+
"""
|
|
780
|
+
if matrix:
|
|
781
|
+
v, M = _reduced_ternary_form_eisenstein_with_matrix(self._a, self._b, self._c, self._r, self._s, self._t)
|
|
782
|
+
return TernaryQF(v), M
|
|
783
|
+
|
|
784
|
+
v = _reduced_ternary_form_eisenstein_without_matrix(self._a, self._b, self._c, self._r, self._s, self._t)
|
|
785
|
+
return TernaryQF(v)
|
|
786
|
+
|
|
787
|
+
def pseudorandom_primitive_zero_mod_p(self, p):
|
|
788
|
+
"""
|
|
789
|
+
Return a tuple of the form `v = (a, b, 1)` such that is a zero of the given ternary quadratic
|
|
790
|
+
positive definite form modulo an odd prime `p`, where `p` doesn't divides the discriminant of the form.
|
|
791
|
+
|
|
792
|
+
EXAMPLES::
|
|
793
|
+
|
|
794
|
+
sage: Q = TernaryQF([1, 1, 11, 0, -1, 0])
|
|
795
|
+
sage: Q.disc()
|
|
796
|
+
43
|
|
797
|
+
sage: Q.pseudorandom_primitive_zero_mod_p(3) # random
|
|
798
|
+
(1, 2, 1)
|
|
799
|
+
sage: Q((1, 2, 1))
|
|
800
|
+
15
|
|
801
|
+
sage: v = Q.pseudorandom_primitive_zero_mod_p(1009) # needs sage.libs.pari
|
|
802
|
+
sage: Q(v) % 1009 # needs sage.libs.pari
|
|
803
|
+
0
|
|
804
|
+
sage: v[2] # needs sage.libs.pari
|
|
805
|
+
1
|
|
806
|
+
"""
|
|
807
|
+
a, b, c, r, s, t = self.coefficients()
|
|
808
|
+
while True:
|
|
809
|
+
|
|
810
|
+
r1 = randint(0, p-1)
|
|
811
|
+
r2 = randint(0, p-1)
|
|
812
|
+
alpha = (b*r1**2+t*r1+a) % p
|
|
813
|
+
if alpha != 0:
|
|
814
|
+
|
|
815
|
+
beta = (2*b*r1*r2+t*r2+r*r1+s) % p
|
|
816
|
+
gamma = (b*r2**2+r*r2+c) % p
|
|
817
|
+
disc = beta**2-4*alpha*gamma
|
|
818
|
+
if mod(disc, p).is_square():
|
|
819
|
+
|
|
820
|
+
z = (-beta+mod(disc, p).sqrt().lift())*(2*alpha).inverse_mod(p)
|
|
821
|
+
# return vector((z,r1*z+r2,1))%p
|
|
822
|
+
return z % p, (r1*z+r2) % p, 1
|
|
823
|
+
|
|
824
|
+
def find_zeros_mod_p(self, p):
|
|
825
|
+
"""
|
|
826
|
+
Find the zeros of the given ternary quadratic positive definite form modulo a prime `p`, where `p` doesn't divide the discriminant of the form.
|
|
827
|
+
|
|
828
|
+
EXAMPLES::
|
|
829
|
+
|
|
830
|
+
sage: Q = TernaryQF([4, 7, 8, -4, -1, -3])
|
|
831
|
+
sage: Q.is_positive_definite()
|
|
832
|
+
True
|
|
833
|
+
sage: Q.disc().factor()
|
|
834
|
+
3 * 13 * 19
|
|
835
|
+
sage: Q.find_zeros_mod_p(2)
|
|
836
|
+
[(1, 0, 0), (1, 1, 0), (0, 0, 1)]
|
|
837
|
+
sage: zeros_17 = Q.find_zeros_mod_p(17) # needs sage.libs.pari
|
|
838
|
+
sage: len(zeros_17) # needs sage.libs.pari
|
|
839
|
+
18
|
|
840
|
+
sage: [Q(v)%17 for v in zeros_17] # needs sage.libs.pari
|
|
841
|
+
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
842
|
+
"""
|
|
843
|
+
if p == 2:
|
|
844
|
+
return _find_zeros_mod_p_2(self._a, self._b, self._c,
|
|
845
|
+
self._r, self._s, self._t)
|
|
846
|
+
|
|
847
|
+
v = self.pseudorandom_primitive_zero_mod_p(p)
|
|
848
|
+
a, b, c, r, s, t = self.coefficients()
|
|
849
|
+
return _find_zeros_mod_p_odd(a, b, c, r, s, t, p, v)
|
|
850
|
+
|
|
851
|
+
def find_p_neighbor_from_vec(self, p, v, mat=False):
|
|
852
|
+
r"""
|
|
853
|
+
Finds the reduced equivalent of the `p`-neighbor of this ternary quadratic form associated to a given
|
|
854
|
+
vector `v` satisfying:
|
|
855
|
+
|
|
856
|
+
1. `Q(v) = 0` (mod `p`)
|
|
857
|
+
|
|
858
|
+
2. `v` is a non-singular point of the conic `Q(v) = 0` (mod `p`).
|
|
859
|
+
|
|
860
|
+
REFERENCES:
|
|
861
|
+
|
|
862
|
+
Gonzalo Tornaria's Thesis, Thrm 3.5, p34.
|
|
863
|
+
|
|
864
|
+
EXAMPLES::
|
|
865
|
+
|
|
866
|
+
sage: # needs sage.libs.pari
|
|
867
|
+
sage: Q = TernaryQF([1, 3, 3, -2, 0, -1]); Q
|
|
868
|
+
Ternary quadratic form with integer coefficients:
|
|
869
|
+
[1 3 3]
|
|
870
|
+
[-2 0 -1]
|
|
871
|
+
sage: Q.disc()
|
|
872
|
+
29
|
|
873
|
+
sage: v = (9, 7, 1)
|
|
874
|
+
sage: v in Q.find_zeros_mod_p(11)
|
|
875
|
+
True
|
|
876
|
+
sage: Q11, M = Q.find_p_neighbor_from_vec(11, v, mat=True)
|
|
877
|
+
sage: Q11
|
|
878
|
+
Ternary quadratic form with integer coefficients:
|
|
879
|
+
[1 2 4]
|
|
880
|
+
[-1 -1 0]
|
|
881
|
+
sage: M
|
|
882
|
+
[ -1 -5/11 7/11]
|
|
883
|
+
[ 0 -10/11 3/11]
|
|
884
|
+
[ 0 -3/11 13/11]
|
|
885
|
+
sage: Q(M) == Q11
|
|
886
|
+
True
|
|
887
|
+
|
|
888
|
+
Test that it works with (0, 0, 1)::
|
|
889
|
+
|
|
890
|
+
sage: Q.find_p_neighbor_from_vec(3, (0,0,1)) # needs sage.libs.pari
|
|
891
|
+
Ternary quadratic form with integer coefficients:
|
|
892
|
+
[1 3 3]
|
|
893
|
+
[-2 0 -1]
|
|
894
|
+
"""
|
|
895
|
+
if mat:
|
|
896
|
+
q, M = _find_p_neighbor_from_vec(self._a, self._b, self._c, self._r, self._s, self._t, p, v, mat)
|
|
897
|
+
M = matrix(3, M)
|
|
898
|
+
return TernaryQF(q), M*M.det()
|
|
899
|
+
else:
|
|
900
|
+
return TernaryQF(_find_p_neighbor_from_vec(self._a, self._b, self._c, self._r, self._s, self._t, p, v, mat))
|
|
901
|
+
|
|
902
|
+
def find_p_neighbors(self, p, mat=False):
|
|
903
|
+
"""
|
|
904
|
+
Find a list with all the reduced equivalent of the `p`-neighbors of this ternary quadratic form, given by the zeros mod `p` of the form.
|
|
905
|
+
See :meth:`find_p_neighbor_from_vec` for more information.
|
|
906
|
+
|
|
907
|
+
EXAMPLES::
|
|
908
|
+
|
|
909
|
+
sage: # needs sage.libs.pari
|
|
910
|
+
sage: Q0 = TernaryQF([1, 3, 3, -2, 0, -1]); Q0
|
|
911
|
+
Ternary quadratic form with integer coefficients:
|
|
912
|
+
[1 3 3]
|
|
913
|
+
[-2 0 -1]
|
|
914
|
+
sage: neig = Q0.find_p_neighbors(5)
|
|
915
|
+
sage: len(neig)
|
|
916
|
+
6
|
|
917
|
+
sage: Q1 = TernaryQF([1, 1, 10, 1, 1, 1])
|
|
918
|
+
sage: Q2 = TernaryQF([1, 2, 4, -1, -1, 0])
|
|
919
|
+
sage: neig.count(Q0)
|
|
920
|
+
2
|
|
921
|
+
sage: neig.count(Q1)
|
|
922
|
+
1
|
|
923
|
+
sage: neig.count(Q2)
|
|
924
|
+
3
|
|
925
|
+
"""
|
|
926
|
+
z = self.find_zeros_mod_p(p)
|
|
927
|
+
return [self.find_p_neighbor_from_vec(p, v, mat) for v in z]
|
|
928
|
+
|
|
929
|
+
def basic_lemma(self, p):
|
|
930
|
+
"""
|
|
931
|
+
Find a number represented by ``self`` and coprime to the prime `p`.
|
|
932
|
+
|
|
933
|
+
EXAMPLES::
|
|
934
|
+
|
|
935
|
+
sage: Q = TernaryQF([3, 3, 3, -2, 0, -1])
|
|
936
|
+
sage: Q.basic_lemma(3)
|
|
937
|
+
4
|
|
938
|
+
"""
|
|
939
|
+
return _basic_lemma(self._a, self._b, self._c, self._r, self._s, self._t, p)
|
|
940
|
+
|
|
941
|
+
def xi(self, p):
|
|
942
|
+
"""
|
|
943
|
+
Return the value of the genus characters Xi_p... which may be
|
|
944
|
+
missing one character. We allow `-1` as a prime.
|
|
945
|
+
|
|
946
|
+
REFERENCES:
|
|
947
|
+
|
|
948
|
+
Dickson's "Studies in the Theory of Numbers"
|
|
949
|
+
|
|
950
|
+
EXAMPLES::
|
|
951
|
+
|
|
952
|
+
sage: Q1 = TernaryQF([26, 42, 53, -36, -17, -3])
|
|
953
|
+
sage: Q2 = Q1.find_p_neighbors(2)[1]
|
|
954
|
+
sage: Q1.omega()
|
|
955
|
+
3
|
|
956
|
+
sage: Q1.xi(3), Q2.xi(3)
|
|
957
|
+
(-1, -1)
|
|
958
|
+
"""
|
|
959
|
+
if p == 4:
|
|
960
|
+
p = -1
|
|
961
|
+
if p == 8:
|
|
962
|
+
p = 2
|
|
963
|
+
|
|
964
|
+
if self.omega() % p != 0:
|
|
965
|
+
raise ValueError("not a valid character")
|
|
966
|
+
|
|
967
|
+
if p == -1 and self.omega() % 2**4 != 0:
|
|
968
|
+
raise ValueError("not a valid character")
|
|
969
|
+
|
|
970
|
+
if p == 2 and self.omega() % 2**5 != 0:
|
|
971
|
+
raise ValueError("not a valid character")
|
|
972
|
+
|
|
973
|
+
if (p == -1) or (p == 2):
|
|
974
|
+
return kronecker_symbol(p, self.basic_lemma(2))
|
|
975
|
+
|
|
976
|
+
return kronecker_symbol(self.basic_lemma(p), p)
|
|
977
|
+
|
|
978
|
+
def xi_rec(self, p):
|
|
979
|
+
"""
|
|
980
|
+
Return Xi(p) for the reciprocal form.
|
|
981
|
+
|
|
982
|
+
EXAMPLES::
|
|
983
|
+
|
|
984
|
+
sage: Q1 = TernaryQF([1, 1, 7, 0, 0, 0])
|
|
985
|
+
sage: Q2 = Q1.find_p_neighbors(3)[0]
|
|
986
|
+
sage: Q1.delta()
|
|
987
|
+
28
|
|
988
|
+
sage: Q1.xi_rec(7), Q2.xi_rec(7)
|
|
989
|
+
(1, 1)
|
|
990
|
+
"""
|
|
991
|
+
return self.reciprocal().xi(p)
|
|
992
|
+
|
|
993
|
+
def symmetry(self, v):
|
|
994
|
+
"""
|
|
995
|
+
Return `A`, the automorphism of the ternary quadratic form such that:
|
|
996
|
+
|
|
997
|
+
- `Av = -v`,
|
|
998
|
+
- `Au = 0`, if `u` is orthogonal to `v`,
|
|
999
|
+
|
|
1000
|
+
where `v` is a given vector.
|
|
1001
|
+
|
|
1002
|
+
EXAMPLES::
|
|
1003
|
+
|
|
1004
|
+
sage: Q = TernaryQF([4, 5, 8, 5, 2, 2])
|
|
1005
|
+
sage: v = vector((1,1,1))
|
|
1006
|
+
sage: M = Q.symmetry(v)
|
|
1007
|
+
sage: M
|
|
1008
|
+
[ 7/13 -17/26 -23/26]
|
|
1009
|
+
[ -6/13 9/26 -23/26]
|
|
1010
|
+
[ -6/13 -17/26 3/26]
|
|
1011
|
+
sage: M.det()
|
|
1012
|
+
-1
|
|
1013
|
+
sage: M*v
|
|
1014
|
+
(-1, -1, -1)
|
|
1015
|
+
sage: v1 = vector((23, 0, -12))
|
|
1016
|
+
sage: v2 = vector((0, 23, -17))
|
|
1017
|
+
sage: v1*Q.matrix()*v
|
|
1018
|
+
0
|
|
1019
|
+
sage: v2*Q.matrix()*v
|
|
1020
|
+
0
|
|
1021
|
+
sage: M*v1 == v1
|
|
1022
|
+
True
|
|
1023
|
+
sage: M*v2 == v2
|
|
1024
|
+
True
|
|
1025
|
+
"""
|
|
1026
|
+
|
|
1027
|
+
return identity_matrix(3) - v.column()*matrix(v)*self.matrix()/self(v)
|
|
1028
|
+
|
|
1029
|
+
def automorphism_symmetries(self, A) -> list:
|
|
1030
|
+
"""
|
|
1031
|
+
Given the automorphism `A`, if `A` is the identity, return the empty list.
|
|
1032
|
+
Otherwise, return a list of two vectors `v_1`, `v_2` such that the product of
|
|
1033
|
+
the symmetries of the ternary quadratic form given by the two vectors is `A`.
|
|
1034
|
+
|
|
1035
|
+
EXAMPLES::
|
|
1036
|
+
|
|
1037
|
+
sage: Q = TernaryQF([9, 12, 30, -26, -28, 20])
|
|
1038
|
+
sage: A = matrix(ZZ, 3, [9, 10, -10, -6, -7, 6, 2, 2, -3])
|
|
1039
|
+
sage: Q(A) == Q
|
|
1040
|
+
True
|
|
1041
|
+
sage: v1, v2 = Q.automorphism_symmetries(A)
|
|
1042
|
+
sage: v1, v2
|
|
1043
|
+
((8, -6, 2), (1, -5/4, -1/4))
|
|
1044
|
+
sage: A1 = Q.symmetry(v1)
|
|
1045
|
+
sage: A1
|
|
1046
|
+
[ 9 9 -13]
|
|
1047
|
+
[ -6 -23/4 39/4]
|
|
1048
|
+
[ 2 9/4 -9/4]
|
|
1049
|
+
sage: A2 = Q.symmetry(v2)
|
|
1050
|
+
sage: A2
|
|
1051
|
+
[ 1 1 3]
|
|
1052
|
+
[ 0 -1/4 -15/4]
|
|
1053
|
+
[ 0 -1/4 1/4]
|
|
1054
|
+
sage: A1*A2 == A
|
|
1055
|
+
True
|
|
1056
|
+
sage: Q.automorphism_symmetries(identity_matrix(ZZ,3))
|
|
1057
|
+
[]
|
|
1058
|
+
"""
|
|
1059
|
+
if A == identity_matrix(3):
|
|
1060
|
+
return []
|
|
1061
|
+
|
|
1062
|
+
bs = (A - 1).columns()
|
|
1063
|
+
b1 = next(v for v in bs if v)
|
|
1064
|
+
A1 = self.symmetry(b1) * A
|
|
1065
|
+
bs = (A1 - 1).columns()
|
|
1066
|
+
b2 = next(v for v in bs if v)
|
|
1067
|
+
return [b1, b2]
|
|
1068
|
+
|
|
1069
|
+
def automorphism_spin_norm(self, A):
|
|
1070
|
+
"""
|
|
1071
|
+
Return the spin norm of the automorphism `A`.
|
|
1072
|
+
|
|
1073
|
+
EXAMPLES::
|
|
1074
|
+
|
|
1075
|
+
sage: Q = TernaryQF([9, 12, 30, -26, -28, 20])
|
|
1076
|
+
sage: A = matrix(ZZ, 3, [9, 10, -10, -6, -7, 6, 2, 2, -3])
|
|
1077
|
+
sage: A.det()
|
|
1078
|
+
1
|
|
1079
|
+
sage: Q(A) == Q
|
|
1080
|
+
True
|
|
1081
|
+
sage: Q.automorphism_spin_norm(A)
|
|
1082
|
+
7
|
|
1083
|
+
"""
|
|
1084
|
+
if A == identity_matrix(ZZ, 3):
|
|
1085
|
+
return 1
|
|
1086
|
+
b1, b2 = self.automorphism_symmetries(A)
|
|
1087
|
+
s = self(b1) * self(b2)
|
|
1088
|
+
return s.squarefree_part()
|
|
1089
|
+
|
|
1090
|
+
def _border(self, n) -> bool:
|
|
1091
|
+
"""
|
|
1092
|
+
Auxiliary function to find the automorphisms of a positive definite ternary quadratic form.
|
|
1093
|
+
|
|
1094
|
+
It returns a boolean whether the n-condition is true.
|
|
1095
|
+
|
|
1096
|
+
If ``Q = TernaryQF([a,b,c,r,s,t])``, the conditions are:
|
|
1097
|
+
|
|
1098
|
+
1. a = t, s = 2r.
|
|
1099
|
+
2. a = s, t = 2r.
|
|
1100
|
+
3. b = r, t = 2s.
|
|
1101
|
+
4. a = -t.
|
|
1102
|
+
5. a = -s.
|
|
1103
|
+
6. b = -r.
|
|
1104
|
+
7. a + b + r + s + t = 0, 2a + 2s + t = 0.
|
|
1105
|
+
8. a = b, r = s.
|
|
1106
|
+
9. b = c, s = t.
|
|
1107
|
+
10. r = s, r = 0.
|
|
1108
|
+
11. r = t, r = 0.
|
|
1109
|
+
12. s = t, s = 0.
|
|
1110
|
+
13. r = s, s = t, t = a.
|
|
1111
|
+
14. a = s, a = t.
|
|
1112
|
+
15. a = b, a + b + r + s + t = 0.
|
|
1113
|
+
16. a = b, b = c, a + b + r + s + t = 0.
|
|
1114
|
+
|
|
1115
|
+
EXAMPLES::
|
|
1116
|
+
|
|
1117
|
+
sage: Q01 = TernaryQF([5, 5, 9, 2, 4, 5])
|
|
1118
|
+
sage: Q01._border(1)
|
|
1119
|
+
True
|
|
1120
|
+
sage: Q02 = TernaryQF([6, 7, 8, 2, 6, 4])
|
|
1121
|
+
sage: Q02._border(2)
|
|
1122
|
+
True
|
|
1123
|
+
sage: Q03 = TernaryQF([6, 9, 9, 9, 3, 6])
|
|
1124
|
+
sage: Q03._border(3)
|
|
1125
|
+
True
|
|
1126
|
+
sage: Q04 = TernaryQF([1, 2, 3, -1, 0, -1])
|
|
1127
|
+
sage: Q04._border(4)
|
|
1128
|
+
True
|
|
1129
|
+
sage: Q05 = TernaryQF([2, 3, 5, -1, -2, 0])
|
|
1130
|
+
sage: Q05._border(5)
|
|
1131
|
+
True
|
|
1132
|
+
sage: Q06 = TernaryQF([1, 5, 7, -5, 0, 0])
|
|
1133
|
+
sage: Q06._border(6)
|
|
1134
|
+
True
|
|
1135
|
+
sage: Q07 = TernaryQF([1, 1, 7, -1, -1, 0])
|
|
1136
|
+
sage: Q07._border(7)
|
|
1137
|
+
True
|
|
1138
|
+
sage: Q08 = TernaryQF([2, 2, 5, -1, -1, -1])
|
|
1139
|
+
sage: Q08._border(8)
|
|
1140
|
+
True
|
|
1141
|
+
sage: Q09 = TernaryQF([3, 8, 8, 6, 2, 2])
|
|
1142
|
+
sage: Q09._border(9)
|
|
1143
|
+
True
|
|
1144
|
+
sage: Q10 = TernaryQF([1, 3, 4, 0, 0, 0])
|
|
1145
|
+
sage: Q10._border(10)
|
|
1146
|
+
True
|
|
1147
|
+
sage: Q11 = TernaryQF([3, 5, 8, 0, -1, 0])
|
|
1148
|
+
sage: Q11._border(11)
|
|
1149
|
+
True
|
|
1150
|
+
sage: Q12 = TernaryQF([2, 6, 7, -5, 0, 0])
|
|
1151
|
+
sage: Q12._border(12)
|
|
1152
|
+
True
|
|
1153
|
+
sage: Q13 = TernaryQF([1, 1, 2, 1, 1, 1])
|
|
1154
|
+
sage: Q13._border(13)
|
|
1155
|
+
True
|
|
1156
|
+
sage: Q14 = TernaryQF([1, 3, 4, 3, 1, 1])
|
|
1157
|
+
sage: Q14._border(14)
|
|
1158
|
+
True
|
|
1159
|
+
sage: Q15 = TernaryQF([3, 3, 6, -3, -3, 0])
|
|
1160
|
+
sage: Q15._border(15)
|
|
1161
|
+
True
|
|
1162
|
+
sage: Q16 = TernaryQF([4, 4, 4, -2, -3, -3])
|
|
1163
|
+
sage: Q16._border(16)
|
|
1164
|
+
True
|
|
1165
|
+
"""
|
|
1166
|
+
a, b, c, r, s, t = self.coefficients()
|
|
1167
|
+
if n == 1:
|
|
1168
|
+
return (a == t) and (s == 2*r)
|
|
1169
|
+
elif n == 2:
|
|
1170
|
+
return (a == s) and (t == 2*r)
|
|
1171
|
+
elif n == 3:
|
|
1172
|
+
return (b == r) and (t == 2*s)
|
|
1173
|
+
elif n == 4:
|
|
1174
|
+
return (a == -t)
|
|
1175
|
+
elif n == 5:
|
|
1176
|
+
return (a == -s)
|
|
1177
|
+
elif n == 6:
|
|
1178
|
+
return (b == -r)
|
|
1179
|
+
elif n == 7:
|
|
1180
|
+
return (a + b + r + s + t == 0) and (2*a + 2*s + t == 0)
|
|
1181
|
+
elif n == 8:
|
|
1182
|
+
return (a == b) and (r == s)
|
|
1183
|
+
elif n == 9:
|
|
1184
|
+
return (b == c) and (s == t)
|
|
1185
|
+
elif n == 10:
|
|
1186
|
+
return (r == s) and (r == 0)
|
|
1187
|
+
elif n == 11:
|
|
1188
|
+
return (r == t) and (r == 0)
|
|
1189
|
+
elif n == 12:
|
|
1190
|
+
return (s == t) and (s == 0)
|
|
1191
|
+
elif n == 13:
|
|
1192
|
+
return (r == s) and (s == t) and (t == a)
|
|
1193
|
+
elif n == 14:
|
|
1194
|
+
return (a == s) and (a == t)
|
|
1195
|
+
elif n == 15:
|
|
1196
|
+
return (a == b) and (a + b + r + s + t == 0)
|
|
1197
|
+
elif n == 16:
|
|
1198
|
+
return (a == b) and (b == c) and (a + b + r + s + t == 0)
|
|
1199
|
+
|
|
1200
|
+
def _borders(self):
|
|
1201
|
+
"""
|
|
1202
|
+
Return the borders that the ternary quadratic form meet.
|
|
1203
|
+
|
|
1204
|
+
See: TernaryQF._border
|
|
1205
|
+
|
|
1206
|
+
EXAMPLES::
|
|
1207
|
+
|
|
1208
|
+
sage: Q01 = TernaryQF([5, 5, 9, 2, 4, 5])
|
|
1209
|
+
sage: Q01._borders()
|
|
1210
|
+
(1,)
|
|
1211
|
+
sage: Q02 = TernaryQF([6, 7, 8, 2, 6, 4])
|
|
1212
|
+
sage: Q02._borders()
|
|
1213
|
+
(2,)
|
|
1214
|
+
sage: Q03 = TernaryQF([6, 9, 9, 9, 3, 6])
|
|
1215
|
+
sage: Q03._borders()
|
|
1216
|
+
(3,)
|
|
1217
|
+
sage: Q04 = TernaryQF([1, 2, 3, -1, 0, -1])
|
|
1218
|
+
sage: Q04._borders()
|
|
1219
|
+
(4,)
|
|
1220
|
+
sage: Q05 = TernaryQF([2, 3, 5, -1, -2, 0])
|
|
1221
|
+
sage: Q05._borders()
|
|
1222
|
+
(5,)
|
|
1223
|
+
sage: Q06 = TernaryQF([1, 5, 7, -5, 0, 0])
|
|
1224
|
+
sage: Q06._borders()
|
|
1225
|
+
(6, 12)
|
|
1226
|
+
sage: Q07 = TernaryQF([1, 1, 7, -1, -1, 0])
|
|
1227
|
+
sage: Q07._borders()
|
|
1228
|
+
(5, 6, 7, 8, 15)
|
|
1229
|
+
sage: Q08 = TernaryQF([2, 2, 5, -1, -1, -1])
|
|
1230
|
+
sage: Q08._borders()
|
|
1231
|
+
(8,)
|
|
1232
|
+
sage: Q09 = TernaryQF([3, 8, 8, 6, 2, 2])
|
|
1233
|
+
sage: Q09._borders()
|
|
1234
|
+
(9,)
|
|
1235
|
+
sage: Q10 = TernaryQF([1, 3, 4, 0, 0, 0])
|
|
1236
|
+
sage: Q10._borders()
|
|
1237
|
+
(10, 11, 12)
|
|
1238
|
+
sage: Q11 = TernaryQF([3, 5, 8, 0, -1, 0])
|
|
1239
|
+
sage: Q11._borders()
|
|
1240
|
+
(11,)
|
|
1241
|
+
sage: Q12 = TernaryQF([2, 6, 7, -5, 0, 0])
|
|
1242
|
+
sage: Q12._borders()
|
|
1243
|
+
(12,)
|
|
1244
|
+
sage: Q13 = TernaryQF([1, 1, 2, 1, 1, 1])
|
|
1245
|
+
sage: Q13._borders()
|
|
1246
|
+
(8, 13, 14)
|
|
1247
|
+
sage: Q14 = TernaryQF([1, 3, 4, 3, 1, 1])
|
|
1248
|
+
sage: Q14._borders()
|
|
1249
|
+
(14,)
|
|
1250
|
+
sage: Q15 = TernaryQF([3, 3, 6, -3, -3, 0])
|
|
1251
|
+
sage: Q15._borders()
|
|
1252
|
+
(5, 6, 7, 8, 15)
|
|
1253
|
+
sage: Q16 = TernaryQF([4, 4, 4, -2, -3, -3])
|
|
1254
|
+
sage: Q16._borders()
|
|
1255
|
+
(9, 15, 16)
|
|
1256
|
+
"""
|
|
1257
|
+
return tuple(n for n in range(1, 17) if self._border(n))
|
|
1258
|
+
|
|
1259
|
+
def _automorphisms_reduced_fast(self):
|
|
1260
|
+
"""
|
|
1261
|
+
Return the coefficients of the matrices of the automorphisms of the reduced ternary quadratic form.
|
|
1262
|
+
|
|
1263
|
+
EXAMPLES::
|
|
1264
|
+
|
|
1265
|
+
sage: Q = TernaryQF([1, 1, 7, 0, 0, 0])
|
|
1266
|
+
sage: Q.is_eisenstein_reduced()
|
|
1267
|
+
True
|
|
1268
|
+
sage: auts = Q._automorphisms_reduced_fast()
|
|
1269
|
+
sage: len(auts)
|
|
1270
|
+
8
|
|
1271
|
+
sage: A = matrix(3, auts[randint(0,7)])
|
|
1272
|
+
sage: Q(A) == Q
|
|
1273
|
+
True
|
|
1274
|
+
sage: Q = TernaryQF([3, 4, 5, 3, 3, 2])
|
|
1275
|
+
sage: Q._automorphisms_reduced_fast()
|
|
1276
|
+
[(1, 0, 0, 0, 1, 0, 0, 0, 1)]
|
|
1277
|
+
"""
|
|
1278
|
+
if self._border(1):
|
|
1279
|
+
if self._border(2):
|
|
1280
|
+
if self._border(14):
|
|
1281
|
+
if self._border(9):
|
|
1282
|
+
# borders 1, 2, 9, 14
|
|
1283
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1284
|
+
(-1, -1, -1, 0, 0, 1, 0, 1, 0),
|
|
1285
|
+
(-1, -1, 0, 0, 1, 0, 0, 0, -1),
|
|
1286
|
+
(-1, 0, -1, 0, -1, 0, 0, 0, 1),
|
|
1287
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1288
|
+
(1, 0, 1, 0, 0, -1, 0, 1, 0),
|
|
1289
|
+
(1, 1, 0, 0, 0, 1, 0, -1, 0),
|
|
1290
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1291
|
+
else:
|
|
1292
|
+
# borders 1, 2, 14
|
|
1293
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1294
|
+
(-1, -1, 0, 0, 1, 0, 0, 0, -1),
|
|
1295
|
+
(-1, 0, -1, 0, -1, 0, 0, 0, 1),
|
|
1296
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1297
|
+
else:
|
|
1298
|
+
# borders 1
|
|
1299
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1300
|
+
(-1, -1, 0, 0, 1, 0, 0, 0, -1)]
|
|
1301
|
+
|
|
1302
|
+
if self._border(2):
|
|
1303
|
+
# borders 2
|
|
1304
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1305
|
+
(-1, 0, -1, 0, -1, 0, 0, 0, 1)]
|
|
1306
|
+
|
|
1307
|
+
if self._border(3):
|
|
1308
|
+
# borders 3
|
|
1309
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1310
|
+
(-1, 0, 0, 0, -1, -1, 0, 0, 1)]
|
|
1311
|
+
|
|
1312
|
+
if self._border(4):
|
|
1313
|
+
if self._border(10):
|
|
1314
|
+
if self._border(8):
|
|
1315
|
+
# borders 4, 8, 10
|
|
1316
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1317
|
+
(-1, 0, 0, -1, 1, 0, 0, 0, -1),
|
|
1318
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1319
|
+
(-1, 1, 0, -1, 0, 0, 0, 0, 1),
|
|
1320
|
+
(-1, 1, 0, 0, 1, 0, 0, 0, -1),
|
|
1321
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1322
|
+
(0, -1, 0, 1, -1, 0, 0, 0, 1),
|
|
1323
|
+
(0, 1, 0, -1, 1, 0, 0, 0, 1),
|
|
1324
|
+
(0, 1, 0, 1, 0, 0, 0, 0, -1),
|
|
1325
|
+
(1, -1, 0, 0, -1, 0, 0, 0, -1),
|
|
1326
|
+
(1, -1, 0, 1, 0, 0, 0, 0, 1),
|
|
1327
|
+
(1, 0, 0, 1, -1, 0, 0, 0, -1)]
|
|
1328
|
+
else:
|
|
1329
|
+
# borders 4, 10
|
|
1330
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1331
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1332
|
+
(-1, 1, 0, 0, 1, 0, 0, 0, -1),
|
|
1333
|
+
(1, -1, 0, 0, -1, 0, 0, 0, -1)]
|
|
1334
|
+
else:
|
|
1335
|
+
# borders 4
|
|
1336
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1337
|
+
(1, -1, 0, 0, -1, 0, 0, 0, -1)]
|
|
1338
|
+
|
|
1339
|
+
if self._border(5):
|
|
1340
|
+
if self._border(6):
|
|
1341
|
+
if self._border(7):
|
|
1342
|
+
if self._border(8):
|
|
1343
|
+
if self._border(15):
|
|
1344
|
+
# borders 5, 6, 7, 8, 15
|
|
1345
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1346
|
+
(-1, 0, 0, 0, 1, -1, 0, 0, -1),
|
|
1347
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1),
|
|
1348
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1349
|
+
(0, -1, 1, 1, 0, 0, 0, 0, 1),
|
|
1350
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1),
|
|
1351
|
+
(0, 1, 0, -1, 0, 1, 0, 0, 1),
|
|
1352
|
+
(1, 0, -1, 0, -1, 0, 0, 0, -1)]
|
|
1353
|
+
else:
|
|
1354
|
+
# borders 5, 6, 7
|
|
1355
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1356
|
+
(-1, 0, 0, 0, 1, -1, 0, 0, -1),
|
|
1357
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1),
|
|
1358
|
+
(1, 0, -1, 0, -1, 0, 0, 0, -1)]
|
|
1359
|
+
elif self._border(11):
|
|
1360
|
+
# borders 5, 11
|
|
1361
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1362
|
+
(-1, 0, 0, 0, 1, 0, 0, 0, -1),
|
|
1363
|
+
(-1, 0, 1, 0, -1, 0, 0, 0, 1),
|
|
1364
|
+
(1, 0, -1, 0, -1, 0, 0, 0, -1)]
|
|
1365
|
+
else:
|
|
1366
|
+
# borders 5
|
|
1367
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1368
|
+
(1, 0, -1, 0, -1, 0, 0, 0, -1)]
|
|
1369
|
+
|
|
1370
|
+
if self._border(6):
|
|
1371
|
+
if self._border(12):
|
|
1372
|
+
if self._border(9):
|
|
1373
|
+
# borders 6, 9, 12
|
|
1374
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1375
|
+
(-1, 0, 0, 0, -1, 0, 0, -1, 1),
|
|
1376
|
+
(-1, 0, 0, 0, -1, 1, 0, 0, 1),
|
|
1377
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1378
|
+
(-1, 0, 0, 0, 0, 1, 0, 1, 0),
|
|
1379
|
+
(-1, 0, 0, 0, 1, -1, 0, 0, -1),
|
|
1380
|
+
(-1, 0, 0, 0, 1, 0, 0, 1, -1),
|
|
1381
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1),
|
|
1382
|
+
(1, 0, 0, 0, -1, 1, 0, -1, 0),
|
|
1383
|
+
(1, 0, 0, 0, 0, -1, 0, 1, -1),
|
|
1384
|
+
(1, 0, 0, 0, 0, 1, 0, -1, 1),
|
|
1385
|
+
(1, 0, 0, 0, 1, -1, 0, 1, 0)]
|
|
1386
|
+
else:
|
|
1387
|
+
# borders 6, 12
|
|
1388
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1389
|
+
(-1, 0, 0, 0, -1, 1, 0, 0, 1),
|
|
1390
|
+
(-1, 0, 0, 0, 1, -1, 0, 0, -1),
|
|
1391
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1)]
|
|
1392
|
+
else:
|
|
1393
|
+
# borders 6
|
|
1394
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1395
|
+
(-1, 0, 0, 0, 1, -1, 0, 0, -1)]
|
|
1396
|
+
|
|
1397
|
+
if self._border(7):
|
|
1398
|
+
if self._border(8) and self._border(15):
|
|
1399
|
+
if self._border(16):
|
|
1400
|
+
if self._border(9):
|
|
1401
|
+
# borders 7, 8, 9, 15, 16
|
|
1402
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1403
|
+
(-1, 0, 0, -1, 0, 1, -1, 1, 0),
|
|
1404
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1405
|
+
(-1, 0, 1, -1, 1, 0, -1, 0, 0),
|
|
1406
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1),
|
|
1407
|
+
(-1, 1, 0, -1, 0, 0, -1, 0, 1),
|
|
1408
|
+
(-1, 1, 0, 0, 1, 0, 0, 1, -1),
|
|
1409
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1410
|
+
(0, -1, 0, 1, -1, 0, 0, -1, 1),
|
|
1411
|
+
(0, -1, 1, 0, -1, 0, 1, -1, 0),
|
|
1412
|
+
(0, -1, 1, 0, 0, 1, -1, 0, 1),
|
|
1413
|
+
(0, 0, -1, 0, -1, 0, -1, 0, 0),
|
|
1414
|
+
(0, 0, -1, 0, 1, -1, 1, 0, -1),
|
|
1415
|
+
(0, 0, 1, -1, 0, 1, 0, -1, 1),
|
|
1416
|
+
(0, 0, 1, 1, 0, 0, 0, 1, 0),
|
|
1417
|
+
(0, 1, -1, -1, 1, 0, 0, 1, 0),
|
|
1418
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1),
|
|
1419
|
+
(0, 1, 0, 0, 0, 1, 1, 0, 0),
|
|
1420
|
+
(0, 1, 0, 0, 1, -1, -1, 1, 0),
|
|
1421
|
+
(1, -1, 0, 0, -1, 1, 0, -1, 0),
|
|
1422
|
+
(1, -1, 0, 1, 0, -1, 1, 0, 0),
|
|
1423
|
+
(1, 0, -1, 0, 0, -1, 0, 1, -1),
|
|
1424
|
+
(1, 0, -1, 1, 0, 0, 1, -1, 0),
|
|
1425
|
+
(1, 0, 0, 1, -1, 0, 1, 0, -1)]
|
|
1426
|
+
else:
|
|
1427
|
+
# borders 7, 8, 15, 16
|
|
1428
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1429
|
+
(-1, 0, 0, -1, 0, 1, -1, 1, 0),
|
|
1430
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1),
|
|
1431
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1432
|
+
(0, -1, 1, 0, -1, 0, 1, -1, 0),
|
|
1433
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1),
|
|
1434
|
+
(0, 1, 0, 0, 1, -1, -1, 1, 0),
|
|
1435
|
+
(1, 0, -1, 1, 0, 0, 1, -1, 0)]
|
|
1436
|
+
else:
|
|
1437
|
+
# borders 7, 8, 15
|
|
1438
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1439
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1),
|
|
1440
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1441
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1)]
|
|
1442
|
+
elif self._border(9):
|
|
1443
|
+
# borders 7, 9
|
|
1444
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1445
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1446
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1),
|
|
1447
|
+
(-1, 1, 0, 0, 1, 0, 0, 1, -1),
|
|
1448
|
+
(1, -1, 0, 0, -1, 1, 0, -1, 0),
|
|
1449
|
+
(1, 0, -1, 0, 0, -1, 0, 1, -1)]
|
|
1450
|
+
else:
|
|
1451
|
+
# borders 7
|
|
1452
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1453
|
+
(-1, 0, 1, 0, -1, 1, 0, 0, 1)]
|
|
1454
|
+
|
|
1455
|
+
if self._border(8):
|
|
1456
|
+
if self._border(9):
|
|
1457
|
+
if self._border(10) and self._border(11) and self._border(12):
|
|
1458
|
+
# borders 8, 9, 10, 11, 12
|
|
1459
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1460
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1461
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1462
|
+
(-1, 0, 0, 0, 0, 1, 0, 1, 0),
|
|
1463
|
+
(-1, 0, 0, 0, 1, 0, 0, 0, -1),
|
|
1464
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1465
|
+
(0, -1, 0, 0, 0, -1, 1, 0, 0),
|
|
1466
|
+
(0, -1, 0, 0, 0, 1, -1, 0, 0),
|
|
1467
|
+
(0, -1, 0, 1, 0, 0, 0, 0, 1),
|
|
1468
|
+
(0, 0, -1, -1, 0, 0, 0, 1, 0),
|
|
1469
|
+
(0, 0, -1, 0, -1, 0, -1, 0, 0),
|
|
1470
|
+
(0, 0, -1, 0, 1, 0, 1, 0, 0),
|
|
1471
|
+
(0, 0, -1, 1, 0, 0, 0, -1, 0),
|
|
1472
|
+
(0, 0, 1, -1, 0, 0, 0, -1, 0),
|
|
1473
|
+
(0, 0, 1, 0, -1, 0, 1, 0, 0),
|
|
1474
|
+
(0, 0, 1, 0, 1, 0, -1, 0, 0),
|
|
1475
|
+
(0, 0, 1, 1, 0, 0, 0, 1, 0),
|
|
1476
|
+
(0, 1, 0, -1, 0, 0, 0, 0, 1),
|
|
1477
|
+
(0, 1, 0, 0, 0, -1, -1, 0, 0),
|
|
1478
|
+
(0, 1, 0, 0, 0, 1, 1, 0, 0),
|
|
1479
|
+
(0, 1, 0, 1, 0, 0, 0, 0, -1),
|
|
1480
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1),
|
|
1481
|
+
(1, 0, 0, 0, 0, -1, 0, 1, 0),
|
|
1482
|
+
(1, 0, 0, 0, 0, 1, 0, -1, 0)]
|
|
1483
|
+
elif self._border(13) and self._border(14):
|
|
1484
|
+
# borders 8, 9, 13, 14
|
|
1485
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1486
|
+
(-1, -1, -1, 0, 0, 1, 0, 1, 0),
|
|
1487
|
+
(-1, -1, -1, 0, 1, 0, 1, 0, 0),
|
|
1488
|
+
(-1, -1, -1, 1, 0, 0, 0, 0, 1),
|
|
1489
|
+
(-1, 0, 0, 0, -1, 0, 1, 1, 1),
|
|
1490
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1491
|
+
(-1, 0, 0, 1, 1, 1, 0, 0, -1),
|
|
1492
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1493
|
+
(0, -1, 0, 0, 0, -1, 1, 1, 1),
|
|
1494
|
+
(0, -1, 0, 1, 1, 1, -1, 0, 0),
|
|
1495
|
+
(0, 0, -1, -1, 0, 0, 1, 1, 1),
|
|
1496
|
+
(0, 0, -1, 0, -1, 0, -1, 0, 0),
|
|
1497
|
+
(0, 0, -1, 1, 1, 1, 0, -1, 0),
|
|
1498
|
+
(0, 0, 1, -1, -1, -1, 1, 0, 0),
|
|
1499
|
+
(0, 0, 1, 0, 1, 0, -1, -1, -1),
|
|
1500
|
+
(0, 0, 1, 1, 0, 0, 0, 1, 0),
|
|
1501
|
+
(0, 1, 0, -1, -1, -1, 0, 0, 1),
|
|
1502
|
+
(0, 1, 0, 0, 0, 1, 1, 0, 0),
|
|
1503
|
+
(0, 1, 0, 1, 0, 0, -1, -1, -1),
|
|
1504
|
+
(1, 0, 0, -1, -1, -1, 0, 1, 0),
|
|
1505
|
+
(1, 0, 0, 0, 0, 1, -1, -1, -1),
|
|
1506
|
+
(1, 1, 1, -1, 0, 0, 0, -1, 0),
|
|
1507
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1),
|
|
1508
|
+
(1, 1, 1, 0, 0, -1, -1, 0, 0)]
|
|
1509
|
+
else:
|
|
1510
|
+
# borders 8, 9
|
|
1511
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1512
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1513
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1514
|
+
(0, 0, -1, 0, -1, 0, -1, 0, 0),
|
|
1515
|
+
(0, 0, 1, 1, 0, 0, 0, 1, 0),
|
|
1516
|
+
(0, 1, 0, 0, 0, 1, 1, 0, 0)]
|
|
1517
|
+
elif self._border(10):
|
|
1518
|
+
if self._border(11) and self._border(12):
|
|
1519
|
+
# borders 8, 10, 11, 12
|
|
1520
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1521
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1522
|
+
(-1, 0, 0, 0, 1, 0, 0, 0, -1),
|
|
1523
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1524
|
+
(0, -1, 0, 1, 0, 0, 0, 0, 1),
|
|
1525
|
+
(0, 1, 0, -1, 0, 0, 0, 0, 1),
|
|
1526
|
+
(0, 1, 0, 1, 0, 0, 0, 0, -1),
|
|
1527
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1)]
|
|
1528
|
+
else:
|
|
1529
|
+
# borders 8, 10
|
|
1530
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1531
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1532
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1533
|
+
(0, 1, 0, 1, 0, 0, 0, 0, -1)]
|
|
1534
|
+
elif self._border(14):
|
|
1535
|
+
# borders 8, 13, 14
|
|
1536
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1537
|
+
(-1, -1, -1, 1, 0, 0, 0, 0, 1),
|
|
1538
|
+
(-1, 0, 0, 1, 1, 1, 0, 0, -1),
|
|
1539
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1),
|
|
1540
|
+
(0, 1, 0, -1, -1, -1, 0, 0, 1),
|
|
1541
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1542
|
+
else:
|
|
1543
|
+
# borders 8
|
|
1544
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1545
|
+
(0, -1, 0, -1, 0, 0, 0, 0, -1)]
|
|
1546
|
+
|
|
1547
|
+
if self._border(9):
|
|
1548
|
+
if self._border(12):
|
|
1549
|
+
if self._border(10) and self._border(11):
|
|
1550
|
+
# borders 9, 10, 11, 12
|
|
1551
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1552
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1553
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1554
|
+
(-1, 0, 0, 0, 0, 1, 0, 1, 0),
|
|
1555
|
+
(-1, 0, 0, 0, 1, 0, 0, 0, -1),
|
|
1556
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1),
|
|
1557
|
+
(1, 0, 0, 0, 0, -1, 0, 1, 0),
|
|
1558
|
+
(1, 0, 0, 0, 0, 1, 0, -1, 0)]
|
|
1559
|
+
else:
|
|
1560
|
+
# borders 9, 12
|
|
1561
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1562
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1563
|
+
(-1, 0, 0, 0, 0, 1, 0, 1, 0),
|
|
1564
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1)]
|
|
1565
|
+
elif self._border(14):
|
|
1566
|
+
if self._border(13):
|
|
1567
|
+
# borders 9, 13, 14
|
|
1568
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1569
|
+
(-1, -1, -1, 0, 0, 1, 0, 1, 0),
|
|
1570
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1571
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1572
|
+
else:
|
|
1573
|
+
# borders 9, 14
|
|
1574
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1575
|
+
(-1, -1, -1, 0, 0, 1, 0, 1, 0),
|
|
1576
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1577
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1578
|
+
elif self._border(15):
|
|
1579
|
+
# borders 9, 15, 16
|
|
1580
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1581
|
+
(-1, 0, 0, -1, 0, 1, -1, 1, 0),
|
|
1582
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0),
|
|
1583
|
+
(0, -1, 1, 0, -1, 0, 1, -1, 0),
|
|
1584
|
+
(0, -1, 1, 0, 0, 1, -1, 0, 1),
|
|
1585
|
+
(0, 1, -1, -1, 1, 0, 0, 1, 0),
|
|
1586
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1),
|
|
1587
|
+
(1, 0, 0, 1, -1, 0, 1, 0, -1)]
|
|
1588
|
+
else:
|
|
1589
|
+
# borders 9
|
|
1590
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1591
|
+
(-1, 0, 0, 0, 0, -1, 0, -1, 0)]
|
|
1592
|
+
|
|
1593
|
+
if self._border(10):
|
|
1594
|
+
if self._border(11) and self._border(12):
|
|
1595
|
+
# borders 10, 11, 12
|
|
1596
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1597
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1),
|
|
1598
|
+
(-1, 0, 0, 0, 1, 0, 0, 0, -1),
|
|
1599
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1)]
|
|
1600
|
+
else:
|
|
1601
|
+
# borders 10
|
|
1602
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1603
|
+
(-1, 0, 0, 0, -1, 0, 0, 0, 1)]
|
|
1604
|
+
|
|
1605
|
+
if self._border(11):
|
|
1606
|
+
# borders 11
|
|
1607
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1608
|
+
(-1, 0, 0, 0, 1, 0, 0, 0, -1)]
|
|
1609
|
+
|
|
1610
|
+
if self._border(12):
|
|
1611
|
+
# border 12
|
|
1612
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1613
|
+
(1, 0, 0, 0, -1, 0, 0, 0, -1)]
|
|
1614
|
+
|
|
1615
|
+
if self._border(13) and self._border(14):
|
|
1616
|
+
# border 13, 14
|
|
1617
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1618
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1619
|
+
|
|
1620
|
+
if self._border(14):
|
|
1621
|
+
# border 14
|
|
1622
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1623
|
+
(1, 1, 1, 0, -1, 0, 0, 0, -1)]
|
|
1624
|
+
|
|
1625
|
+
if self._border(15):
|
|
1626
|
+
if self._border(16):
|
|
1627
|
+
# borders 15, 16
|
|
1628
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1629
|
+
(-1, 0, 0, -1, 0, 1, -1, 1, 0),
|
|
1630
|
+
(0, -1, 1, 0, -1, 0, 1, -1, 0),
|
|
1631
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1)]
|
|
1632
|
+
else:
|
|
1633
|
+
# borders 15
|
|
1634
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
1635
|
+
(0, 1, -1, 1, 0, -1, 0, 0, -1)]
|
|
1636
|
+
|
|
1637
|
+
return [(1, 0, 0, 0, 1, 0, 0, 0, 1)]
|
|
1638
|
+
|
|
1639
|
+
def _automorphisms_reduced_slow(self):
|
|
1640
|
+
"""
|
|
1641
|
+
Return the automorphisms of the reduced ternary quadratic form.
|
|
1642
|
+
|
|
1643
|
+
It searches over all 3x3 matrices with coefficients -1, 0, 1,
|
|
1644
|
+
determinant 1 and finite order, because Eisenstein reduced forms
|
|
1645
|
+
are Minkowski reduced. See Cassels.
|
|
1646
|
+
|
|
1647
|
+
EXAMPLES::
|
|
1648
|
+
|
|
1649
|
+
sage: Q = TernaryQF([1, 1, 7, 0, 0, 0])
|
|
1650
|
+
sage: Q.is_eisenstein_reduced()
|
|
1651
|
+
True
|
|
1652
|
+
|
|
1653
|
+
sage: # long time
|
|
1654
|
+
sage: auts = Q._automorphisms_reduced_slow() # 3s on sage.math, 2014
|
|
1655
|
+
sage: len(auts)
|
|
1656
|
+
8
|
|
1657
|
+
sage: A = auts[randint(0,7)]
|
|
1658
|
+
sage: Q(A) == Q
|
|
1659
|
+
True
|
|
1660
|
+
sage: Q = TernaryQF([3, 4, 5, 3, 3, 2])
|
|
1661
|
+
sage: Q._automorphisms_reduced_slow()
|
|
1662
|
+
[
|
|
1663
|
+
[1 0 0]
|
|
1664
|
+
[0 1 0]
|
|
1665
|
+
[0 0 1]
|
|
1666
|
+
]
|
|
1667
|
+
"""
|
|
1668
|
+
from itertools import product
|
|
1669
|
+
if TernaryQF.possible_automorphisms is None:
|
|
1670
|
+
auts = (matrix(ZZ, 3, 3, m) for m in product([-1, 0, 1], repeat=9))
|
|
1671
|
+
auts = [m for m in auts if m.det() == 1]
|
|
1672
|
+
auts = [m for m in auts if m**2 in auts]
|
|
1673
|
+
auts = [m for m in auts if m**2 in auts]
|
|
1674
|
+
auts = [m for m in auts if m**2 in auts]
|
|
1675
|
+
TernaryQF.possible_automorphisms = auts
|
|
1676
|
+
return [m for m in TernaryQF.possible_automorphisms if self(m) == self]
|
|
1677
|
+
|
|
1678
|
+
def automorphisms(self, slow=True):
|
|
1679
|
+
"""
|
|
1680
|
+
Return a list with the automorphisms of the definite ternary quadratic form.
|
|
1681
|
+
|
|
1682
|
+
EXAMPLES::
|
|
1683
|
+
|
|
1684
|
+
sage: Q = TernaryQF([1, 1, 7, 0, 0, 0])
|
|
1685
|
+
sage: auts = Q.automorphisms(); auts
|
|
1686
|
+
[
|
|
1687
|
+
[-1 0 0] [-1 0 0] [ 0 -1 0] [ 0 -1 0] [ 0 1 0] [ 0 1 0]
|
|
1688
|
+
[ 0 -1 0] [ 0 1 0] [-1 0 0] [ 1 0 0] [-1 0 0] [ 1 0 0]
|
|
1689
|
+
[ 0 0 1], [ 0 0 -1], [ 0 0 -1], [ 0 0 1], [ 0 0 1], [ 0 0 -1],
|
|
1690
|
+
[ 1 0 0] [1 0 0]
|
|
1691
|
+
[ 0 -1 0] [0 1 0]
|
|
1692
|
+
[ 0 0 -1], [0 0 1]
|
|
1693
|
+
]
|
|
1694
|
+
sage: all(Q == Q(A) for A in auts)
|
|
1695
|
+
True
|
|
1696
|
+
sage: Q = TernaryQF([3, 4, 5, 3, 3, 2])
|
|
1697
|
+
sage: Q.automorphisms(slow=False)
|
|
1698
|
+
[
|
|
1699
|
+
[1 0 0]
|
|
1700
|
+
[0 1 0]
|
|
1701
|
+
[0 0 1]
|
|
1702
|
+
]
|
|
1703
|
+
sage: Q = TernaryQF([4, 2, 4, 3, -4, -5])
|
|
1704
|
+
sage: auts = Q.automorphisms(slow=False)
|
|
1705
|
+
sage: auts
|
|
1706
|
+
[
|
|
1707
|
+
[1 0 0] [ 2 -1 -1]
|
|
1708
|
+
[0 1 0] [ 3 -2 -1]
|
|
1709
|
+
[0 0 1], [ 0 0 -1]
|
|
1710
|
+
]
|
|
1711
|
+
sage: A = auts[1]
|
|
1712
|
+
sage: Q(A) == Q
|
|
1713
|
+
True
|
|
1714
|
+
sage: Qr, M_red = Q.reduced_form_eisenstein()
|
|
1715
|
+
sage: Qr
|
|
1716
|
+
Ternary quadratic form with integer coefficients:
|
|
1717
|
+
[1 2 3]
|
|
1718
|
+
[-1 0 -1]
|
|
1719
|
+
sage: Q(A*M_red) == Qr
|
|
1720
|
+
True
|
|
1721
|
+
"""
|
|
1722
|
+
if not self.is_definite():
|
|
1723
|
+
raise ValueError("only implemented for definite forms")
|
|
1724
|
+
|
|
1725
|
+
if self._automorphisms is not None:
|
|
1726
|
+
return self._automorphisms
|
|
1727
|
+
|
|
1728
|
+
if self.is_positive_definite():
|
|
1729
|
+
if self.is_eisenstein_reduced():
|
|
1730
|
+
if slow:
|
|
1731
|
+
self._automorphisms = self._automorphisms_reduced_slow()
|
|
1732
|
+
else:
|
|
1733
|
+
auts = self._automorphisms_reduced_fast()
|
|
1734
|
+
self._automorphisms = [matrix(ZZ, 3, A) for A in auts]
|
|
1735
|
+
else:
|
|
1736
|
+
Qr, M = self.reduced_form_eisenstein()
|
|
1737
|
+
auts = Qr.automorphisms(slow)
|
|
1738
|
+
M_inv = M.inverse()
|
|
1739
|
+
self._automorphisms = [M*m*M_inv for m in auts]
|
|
1740
|
+
else:
|
|
1741
|
+
self._automorphisms = (-self).automorphisms()
|
|
1742
|
+
return self._automorphisms
|
|
1743
|
+
|
|
1744
|
+
def _number_of_automorphisms_reduced(self):
|
|
1745
|
+
"""
|
|
1746
|
+
Return the number of automorphisms of the reduced definite ternary quadratic form.
|
|
1747
|
+
|
|
1748
|
+
EXAMPLES::
|
|
1749
|
+
|
|
1750
|
+
sage: Q = TernaryQF([1, 1, 7, 0, 0, 0])
|
|
1751
|
+
sage: Q._number_of_automorphisms_reduced()
|
|
1752
|
+
8
|
|
1753
|
+
sage: len(Q.automorphisms(slow=False))
|
|
1754
|
+
8
|
|
1755
|
+
sage: Q = TernaryQF([3, 4, 5, 3, 3, 2])
|
|
1756
|
+
sage: Q._number_of_automorphisms_reduced()
|
|
1757
|
+
1
|
|
1758
|
+
"""
|
|
1759
|
+
if self._border(1):
|
|
1760
|
+
if self._border(2):
|
|
1761
|
+
if self._border(14):
|
|
1762
|
+
if self._border(9):
|
|
1763
|
+
# borders 1, 2, 9, 14
|
|
1764
|
+
return 8
|
|
1765
|
+
else:
|
|
1766
|
+
# borders 1, 2, 14
|
|
1767
|
+
return 4
|
|
1768
|
+
else:
|
|
1769
|
+
# borders 1
|
|
1770
|
+
return 2
|
|
1771
|
+
|
|
1772
|
+
if self._border(2):
|
|
1773
|
+
# borders 2
|
|
1774
|
+
return 2
|
|
1775
|
+
|
|
1776
|
+
if self._border(3):
|
|
1777
|
+
# borders 3
|
|
1778
|
+
return 2
|
|
1779
|
+
|
|
1780
|
+
if self._border(4):
|
|
1781
|
+
if self._border(10):
|
|
1782
|
+
if self._border(8):
|
|
1783
|
+
# borders 4, 8, 10
|
|
1784
|
+
return 12
|
|
1785
|
+
else:
|
|
1786
|
+
# borders 4, 10
|
|
1787
|
+
return 4
|
|
1788
|
+
else:
|
|
1789
|
+
# borders 4
|
|
1790
|
+
return 2
|
|
1791
|
+
|
|
1792
|
+
if self._border(5):
|
|
1793
|
+
if self._border(6):
|
|
1794
|
+
if self._border(7):
|
|
1795
|
+
if self._border(8):
|
|
1796
|
+
if self._border(15):
|
|
1797
|
+
# borders 5, 6, 7, 8, 15
|
|
1798
|
+
return 8
|
|
1799
|
+
else:
|
|
1800
|
+
# borders 5, 6, 7
|
|
1801
|
+
return 4
|
|
1802
|
+
elif self._border(11):
|
|
1803
|
+
# borders 5, 11
|
|
1804
|
+
return 4
|
|
1805
|
+
else:
|
|
1806
|
+
# borders 5
|
|
1807
|
+
return 2
|
|
1808
|
+
|
|
1809
|
+
if self._border(6):
|
|
1810
|
+
if self._border(12):
|
|
1811
|
+
if self._border(9):
|
|
1812
|
+
# borders 6, 9, 12
|
|
1813
|
+
return 12
|
|
1814
|
+
else:
|
|
1815
|
+
# borders 6, 12
|
|
1816
|
+
return 4
|
|
1817
|
+
else:
|
|
1818
|
+
# borders 6
|
|
1819
|
+
return 2
|
|
1820
|
+
|
|
1821
|
+
if self._border(7):
|
|
1822
|
+
if self._border(8) and self._border(15):
|
|
1823
|
+
if self._border(16):
|
|
1824
|
+
if self._border(9):
|
|
1825
|
+
# borders 7, 8, 9, 15, 16
|
|
1826
|
+
return 24
|
|
1827
|
+
else:
|
|
1828
|
+
# borders 7, 8, 15, 16
|
|
1829
|
+
return 8
|
|
1830
|
+
else:
|
|
1831
|
+
# borders 7, 8, 15
|
|
1832
|
+
return 4
|
|
1833
|
+
elif self._border(9):
|
|
1834
|
+
# borders 7, 9
|
|
1835
|
+
return 6
|
|
1836
|
+
else:
|
|
1837
|
+
# borders 7
|
|
1838
|
+
return 2
|
|
1839
|
+
|
|
1840
|
+
if self._border(8):
|
|
1841
|
+
if self._border(9):
|
|
1842
|
+
if self._border(10) and self._border(11) and self._border(12):
|
|
1843
|
+
# borders 8, 9, 10, 11, 12
|
|
1844
|
+
return 24
|
|
1845
|
+
elif self._border(13) and self._border(14):
|
|
1846
|
+
# borders 8, 9, 13, 14
|
|
1847
|
+
return 24
|
|
1848
|
+
else:
|
|
1849
|
+
# borders 8, 9
|
|
1850
|
+
return 6
|
|
1851
|
+
elif self._border(10):
|
|
1852
|
+
if self._border(11) and self._border(12):
|
|
1853
|
+
# borders 8, 10, 11, 12
|
|
1854
|
+
return 8
|
|
1855
|
+
else:
|
|
1856
|
+
# borders 8, 10
|
|
1857
|
+
return 4
|
|
1858
|
+
elif self._border(14):
|
|
1859
|
+
# borders 8, 13, 14
|
|
1860
|
+
return 6
|
|
1861
|
+
else:
|
|
1862
|
+
# borders 8
|
|
1863
|
+
return 2
|
|
1864
|
+
|
|
1865
|
+
if self._border(9):
|
|
1866
|
+
if self._border(12):
|
|
1867
|
+
if self._border(10) and self._border(11):
|
|
1868
|
+
# borders 9, 10, 11, 12
|
|
1869
|
+
return 8
|
|
1870
|
+
else:
|
|
1871
|
+
# borders 9, 12
|
|
1872
|
+
return 4
|
|
1873
|
+
elif self._border(14):
|
|
1874
|
+
if self._border(13):
|
|
1875
|
+
# borders 9, 13, 14
|
|
1876
|
+
return 4
|
|
1877
|
+
else:
|
|
1878
|
+
# borders 9, 14
|
|
1879
|
+
return 4
|
|
1880
|
+
elif self._border(15):
|
|
1881
|
+
# borders 9, 15, 16
|
|
1882
|
+
return 8
|
|
1883
|
+
else:
|
|
1884
|
+
# borders 9
|
|
1885
|
+
return 2
|
|
1886
|
+
|
|
1887
|
+
if self._border(10):
|
|
1888
|
+
if self._border(11) and self._border(12):
|
|
1889
|
+
# borders 10, 11, 12
|
|
1890
|
+
return 4
|
|
1891
|
+
else:
|
|
1892
|
+
# borders 10
|
|
1893
|
+
return 2
|
|
1894
|
+
|
|
1895
|
+
if self._border(11):
|
|
1896
|
+
# borders 11
|
|
1897
|
+
return 2
|
|
1898
|
+
|
|
1899
|
+
if self._border(12):
|
|
1900
|
+
# border 12
|
|
1901
|
+
return 2
|
|
1902
|
+
|
|
1903
|
+
if self._border(13) and self._border(14):
|
|
1904
|
+
# border 13, 14
|
|
1905
|
+
return 2
|
|
1906
|
+
|
|
1907
|
+
if self._border(14):
|
|
1908
|
+
# border 14
|
|
1909
|
+
return 2
|
|
1910
|
+
|
|
1911
|
+
if self._border(15):
|
|
1912
|
+
if self._border(16):
|
|
1913
|
+
# borders 15, 16
|
|
1914
|
+
return 4
|
|
1915
|
+
else:
|
|
1916
|
+
# borders 15
|
|
1917
|
+
return 2
|
|
1918
|
+
|
|
1919
|
+
return 1
|
|
1920
|
+
|
|
1921
|
+
def number_of_automorphisms(self, slow=True):
|
|
1922
|
+
"""
|
|
1923
|
+
Return the number of automorphisms of the definite ternary quadratic form.
|
|
1924
|
+
|
|
1925
|
+
EXAMPLES::
|
|
1926
|
+
|
|
1927
|
+
sage: Q = TernaryQF([1, 1, 7, 0, 0, 0])
|
|
1928
|
+
sage: A = matrix(ZZ, 3, [0, 1, 0, -1, 5, 0, -8, -1, 1])
|
|
1929
|
+
sage: A.det()
|
|
1930
|
+
1
|
|
1931
|
+
sage: Q1 = Q(A); Q1
|
|
1932
|
+
Ternary quadratic form with integer coefficients:
|
|
1933
|
+
[449 33 7]
|
|
1934
|
+
[-14 -112 102]
|
|
1935
|
+
sage: Q1.number_of_automorphisms()
|
|
1936
|
+
8
|
|
1937
|
+
sage: Q = TernaryQF([-19, -7, -6, -12, 20, 23])
|
|
1938
|
+
sage: Q.is_negative_definite()
|
|
1939
|
+
True
|
|
1940
|
+
sage: Q.number_of_automorphisms(slow=False)
|
|
1941
|
+
24
|
|
1942
|
+
"""
|
|
1943
|
+
if not self.is_definite():
|
|
1944
|
+
raise ValueError("only implemented for definite forms")
|
|
1945
|
+
|
|
1946
|
+
if self._number_of_automorphisms is not None:
|
|
1947
|
+
return self._number_of_automorphisms
|
|
1948
|
+
|
|
1949
|
+
if slow:
|
|
1950
|
+
self._number_of_automorphisms = len(self.automorphisms())
|
|
1951
|
+
else:
|
|
1952
|
+
if self.is_negative_definite():
|
|
1953
|
+
self._number_of_automorphisms = (-self).reduced_form_eisenstein(False)._number_of_automorphisms_reduced()
|
|
1954
|
+
else:
|
|
1955
|
+
self._number_of_automorphisms = self.reduced_form_eisenstein(False)._number_of_automorphisms_reduced()
|
|
1956
|
+
|
|
1957
|
+
return self._number_of_automorphisms
|
|
1958
|
+
|
|
1959
|
+
|
|
1960
|
+
def find_all_ternary_qf_by_level_disc(N, d):
|
|
1961
|
+
"""
|
|
1962
|
+
Find the coefficients of all the reduced ternary quadratic forms given its discriminant `d` and level `N`.
|
|
1963
|
+
|
|
1964
|
+
If `N|4d` and `d|N^2`, then it may be some forms with that discriminant and level.
|
|
1965
|
+
|
|
1966
|
+
EXAMPLES::
|
|
1967
|
+
|
|
1968
|
+
sage: find_all_ternary_qf_by_level_disc(44, 11)
|
|
1969
|
+
[Ternary quadratic form with integer coefficients:
|
|
1970
|
+
[1 1 3]
|
|
1971
|
+
[0 -1 0], Ternary quadratic form with integer coefficients:
|
|
1972
|
+
[1 1 4]
|
|
1973
|
+
[1 1 1]]
|
|
1974
|
+
sage: find_all_ternary_qf_by_level_disc(44, 11^2 * 16)
|
|
1975
|
+
[Ternary quadratic form with integer coefficients:
|
|
1976
|
+
[3 15 15]
|
|
1977
|
+
[-14 -2 -2], Ternary quadratic form with integer coefficients:
|
|
1978
|
+
[4 11 12]
|
|
1979
|
+
[0 -4 0]]
|
|
1980
|
+
sage: Q = TernaryQF([1, 1, 3, 0, -1, 0])
|
|
1981
|
+
sage: Q.is_eisenstein_reduced()
|
|
1982
|
+
True
|
|
1983
|
+
sage: Q.reciprocal_reduced()
|
|
1984
|
+
Ternary quadratic form with integer coefficients:
|
|
1985
|
+
[4 11 12]
|
|
1986
|
+
[0 -4 0]
|
|
1987
|
+
sage: find_all_ternary_qf_by_level_disc(44, 22)
|
|
1988
|
+
[]
|
|
1989
|
+
sage: find_all_ternary_qf_by_level_disc(44, 33)
|
|
1990
|
+
Traceback (most recent call last):
|
|
1991
|
+
...
|
|
1992
|
+
ValueError: There are no ternary forms of this level and discriminant
|
|
1993
|
+
"""
|
|
1994
|
+
return [TernaryQF(qf) for qf in _find_all_ternary_qf_by_level_disc(N, d)]
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
def find_a_ternary_qf_by_level_disc(N, d):
|
|
1998
|
+
"""
|
|
1999
|
+
Find a reduced ternary quadratic form given its discriminant `d` and level `N`.
|
|
2000
|
+
If `N|4d` and `d|N^2`, then it may be a form with that discriminant and level.
|
|
2001
|
+
|
|
2002
|
+
EXAMPLES::
|
|
2003
|
+
|
|
2004
|
+
sage: Q1 = find_a_ternary_qf_by_level_disc(44, 11); Q1
|
|
2005
|
+
Ternary quadratic form with integer coefficients:
|
|
2006
|
+
[1 1 3]
|
|
2007
|
+
[0 -1 0]
|
|
2008
|
+
sage: Q2 = find_a_ternary_qf_by_level_disc(44, 11^2 * 16)
|
|
2009
|
+
sage: Q2
|
|
2010
|
+
Ternary quadratic form with integer coefficients:
|
|
2011
|
+
[3 15 15]
|
|
2012
|
+
[-14 -2 -2]
|
|
2013
|
+
sage: Q1.is_eisenstein_reduced()
|
|
2014
|
+
True
|
|
2015
|
+
sage: Q1.level()
|
|
2016
|
+
44
|
|
2017
|
+
sage: Q1.disc()
|
|
2018
|
+
11
|
|
2019
|
+
sage: find_a_ternary_qf_by_level_disc(44, 22)
|
|
2020
|
+
sage: find_a_ternary_qf_by_level_disc(44, 33)
|
|
2021
|
+
Traceback (most recent call last):
|
|
2022
|
+
...
|
|
2023
|
+
ValueError: There are no ternary forms of this level and discriminant
|
|
2024
|
+
"""
|
|
2025
|
+
q = _find_a_ternary_qf_by_level_disc(N, d)
|
|
2026
|
+
if q is not None:
|
|
2027
|
+
return TernaryQF(q)
|