passagemath-modules 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-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 +808 -0
- passagemath_modules-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_modules-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_modules.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_modules.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_modules.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_modules.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_modules.libs/libmpc-d8ebe4b5.so.3.3.1 +0 -0
- passagemath_modules.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_modules.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_modules.libs/libquadmath-bb76a5fc.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/calculus/integration.pyx +698 -0
- sage/calculus/interpolation.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/interpolation.pxd +13 -0
- sage/calculus/interpolation.pyx +387 -0
- sage/calculus/interpolators.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/interpolators.pyx +326 -0
- sage/calculus/ode.cpython-314-x86_64-linux-musl.so +0 -0
- sage/calculus/ode.pxd +5 -0
- sage/calculus/ode.pyx +610 -0
- sage/calculus/riemann.cpython-314-x86_64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/matrix/constructor.pyx +750 -0
- sage/matrix/docs.py +430 -0
- sage/matrix/echelon_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/echelon_matrix.pyx +155 -0
- sage/matrix/matrix.pxd +2 -0
- sage/matrix/matrix0.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix0.pxd +68 -0
- sage/matrix/matrix0.pyx +6324 -0
- sage/matrix/matrix1.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix1.pxd +8 -0
- sage/matrix/matrix1.pyx +2851 -0
- sage/matrix/matrix2.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix2.pxd +25 -0
- sage/matrix/matrix2.pyx +20181 -0
- sage/matrix/matrix_cdv.cpython-314-x86_64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/matroids/extension.pxd +34 -0
- sage/matroids/extension.pyx +519 -0
- sage/matroids/flats_matroid.cpython-314-x86_64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/rings/function_field/hermite_form_polynomial.pyx +188 -0
- sage/rings/function_field/khuri_makdisi.cpython-314-x86_64-linux-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.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-musl.so +0 -0
- sage/stats/hmm/chmm.pyx +1595 -0
- sage/stats/hmm/distributions.cpython-314-x86_64-linux-musl.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-musl.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-musl.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-musl.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-musl.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,2779 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-modules
|
|
2
|
+
r"""
|
|
3
|
+
Extension of rings
|
|
4
|
+
|
|
5
|
+
Sage offers the possibility to work with ring extensions `L/K` as
|
|
6
|
+
actual parents and perform meaningful operations on them and their
|
|
7
|
+
elements.
|
|
8
|
+
|
|
9
|
+
The simplest way to build an extension is to use the method
|
|
10
|
+
:meth:`sage.categories.commutative_rings.CommutativeRings.ParentMethods.over` on the top ring,
|
|
11
|
+
that is `L`.
|
|
12
|
+
For example, the following line constructs the extension of
|
|
13
|
+
finite fields `\mathbf{F}_{5^4}/\mathbf{F}_{5^2}`::
|
|
14
|
+
|
|
15
|
+
sage: GF(5^4).over(GF(5^2)) # needs sage.rings.finite_rings
|
|
16
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
17
|
+
|
|
18
|
+
By default, Sage reuses the canonical generator of the top ring
|
|
19
|
+
(here `z_4 \in \mathbf{F}_{5^4}`), together with its name. However,
|
|
20
|
+
the user can customize them by passing in appropriate arguments::
|
|
21
|
+
|
|
22
|
+
sage: # needs sage.rings.finite_rings
|
|
23
|
+
sage: F = GF(5^2)
|
|
24
|
+
sage: k = GF(5^4)
|
|
25
|
+
sage: z4 = k.gen()
|
|
26
|
+
sage: K.<a> = k.over(F, gen=1-z4); K
|
|
27
|
+
Field in a with defining polynomial x^2 + z2*x + 4 over its base
|
|
28
|
+
|
|
29
|
+
The base of the extension is available via the method :meth:`base` (or
|
|
30
|
+
equivalently :meth:`base_ring`)::
|
|
31
|
+
|
|
32
|
+
sage: K.base() # needs sage.rings.finite_rings
|
|
33
|
+
Finite Field in z2 of size 5^2
|
|
34
|
+
|
|
35
|
+
It is also possible to build an extension on top of another extension,
|
|
36
|
+
obtaining this way a tower of extensions::
|
|
37
|
+
|
|
38
|
+
sage: L.<b> = GF(5^8).over(K); L # needs sage.rings.finite_rings
|
|
39
|
+
Field in b with defining polynomial x^2 + (4*z2 + 3*a)*x + 1 - a over its base
|
|
40
|
+
sage: L.base() # needs sage.rings.finite_rings
|
|
41
|
+
Field in a with defining polynomial x^2 + z2*x + 4 over its base
|
|
42
|
+
sage: L.base().base() # needs sage.rings.finite_rings
|
|
43
|
+
Finite Field in z2 of size 5^2
|
|
44
|
+
|
|
45
|
+
The method :meth:`bases` gives access to the complete list of rings in
|
|
46
|
+
a tower::
|
|
47
|
+
|
|
48
|
+
sage: L.bases() # needs sage.rings.finite_rings
|
|
49
|
+
[Field in b with defining polynomial x^2 + (4*z2 + 3*a)*x + 1 - a over its base,
|
|
50
|
+
Field in a with defining polynomial x^2 + z2*x + 4 over its base,
|
|
51
|
+
Finite Field in z2 of size 5^2]
|
|
52
|
+
|
|
53
|
+
Once we have constructed an extension (or a tower of extensions), we
|
|
54
|
+
have interesting methods attached to it. As a basic example, one can
|
|
55
|
+
compute a basis of the top ring over any base in the tower::
|
|
56
|
+
|
|
57
|
+
sage: L.basis_over(K) # needs sage.rings.finite_rings
|
|
58
|
+
[1, b]
|
|
59
|
+
sage: L.basis_over(F) # needs sage.rings.finite_rings
|
|
60
|
+
[1, a, b, a*b]
|
|
61
|
+
|
|
62
|
+
When the base is omitted, the default is the natural base of the extension::
|
|
63
|
+
|
|
64
|
+
sage: L.basis_over() # needs sage.rings.finite_rings
|
|
65
|
+
[1, b]
|
|
66
|
+
|
|
67
|
+
The method :meth:`sage.rings.ring_extension_element.RingExtensionWithBasis.vector`
|
|
68
|
+
computes the coordinates of an element according to the above basis::
|
|
69
|
+
|
|
70
|
+
sage: u = a + 2*b + 3*a*b # needs sage.rings.finite_rings
|
|
71
|
+
sage: u.vector() # over K # needs sage.rings.finite_rings
|
|
72
|
+
(a, 2 + 3*a)
|
|
73
|
+
sage: u.vector(F) # needs sage.rings.finite_rings
|
|
74
|
+
(0, 1, 2, 3)
|
|
75
|
+
|
|
76
|
+
One can also compute traces and norms with respect to any base of the tower::
|
|
77
|
+
|
|
78
|
+
sage: # needs sage.rings.finite_rings
|
|
79
|
+
sage: u.trace() # over K
|
|
80
|
+
(2*z2 + 1) + (2*z2 + 1)*a
|
|
81
|
+
sage: u.trace(F)
|
|
82
|
+
z2 + 1
|
|
83
|
+
sage: u.trace().trace() # over K, then over F
|
|
84
|
+
z2 + 1
|
|
85
|
+
sage: u.norm() # over K
|
|
86
|
+
(z2 + 1) + (4*z2 + 2)*a
|
|
87
|
+
sage: u.norm(F)
|
|
88
|
+
2*z2 + 2
|
|
89
|
+
|
|
90
|
+
And minimal polynomials::
|
|
91
|
+
|
|
92
|
+
sage: u.minpoly() # needs sage.rings.finite_rings sage.libs.singular
|
|
93
|
+
x^2 + ((3*z2 + 4) + (3*z2 + 4)*a)*x + (z2 + 1) + (4*z2 + 2)*a
|
|
94
|
+
sage: u.minpoly(F) # needs sage.rings.finite_rings sage.libs.singular
|
|
95
|
+
x^4 + (4*z2 + 4)*x^3 + x^2 + (z2 + 1)*x + 2*z2 + 2
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
AUTHOR:
|
|
99
|
+
|
|
100
|
+
- Xavier Caruso (2019)
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
# ###########################################################################
|
|
104
|
+
# Copyright (C) 2019 Xavier Caruso <xavier.caruso@normalesup.org>
|
|
105
|
+
#
|
|
106
|
+
# This program is free softwGare: you can redistribute it and/or modify
|
|
107
|
+
# it under the terms of the GNU General Public License as published by
|
|
108
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
109
|
+
# (at your option) any later version.
|
|
110
|
+
# https://www.gnu.org/licenses/
|
|
111
|
+
# ***************************************************************************
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
cimport cython
|
|
115
|
+
from sage.misc.fast_methods cimport hash_by_id
|
|
116
|
+
from sage.misc.cachefunc import cached_method
|
|
117
|
+
from sage.cpython.getattr cimport AttributeErrorMessage
|
|
118
|
+
from sage.cpython.getattr import dir_with_other_class
|
|
119
|
+
from sage.misc.latex import latex, latex_variable_name
|
|
120
|
+
|
|
121
|
+
from sage.structure.factory import UniqueFactory
|
|
122
|
+
from sage.structure.parent cimport Parent
|
|
123
|
+
from sage.structure.element cimport Element
|
|
124
|
+
from sage.structure.category_object import normalize_names
|
|
125
|
+
from sage.categories.map cimport Map
|
|
126
|
+
from sage.categories.commutative_rings import CommutativeRings
|
|
127
|
+
from sage.categories.fields import Fields
|
|
128
|
+
from sage.rings.integer_ring import ZZ
|
|
129
|
+
from sage.rings.infinity import Infinity
|
|
130
|
+
|
|
131
|
+
from sage.rings.ring_extension_element cimport (
|
|
132
|
+
RingExtensionElement, RingExtensionFractionFieldElement, RingExtensionWithBasisElement)
|
|
133
|
+
from sage.rings.ring_extension_morphism cimport (
|
|
134
|
+
RingExtensionHomomorphism, RingExtensionBackendIsomorphism, RingExtensionBackendReverseIsomorphism,
|
|
135
|
+
are_equal_morphisms, MapFreeModuleToRelativeRing, MapRelativeRingToFreeModule)
|
|
136
|
+
from sage.rings.ring_extension_conversion cimport (
|
|
137
|
+
backend_parent, backend_morphism, to_backend, from_backend)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Helper functions
|
|
141
|
+
##################
|
|
142
|
+
|
|
143
|
+
def tower_bases(ring, degree):
|
|
144
|
+
r"""
|
|
145
|
+
Return the list of bases of ``ring`` (including itself); if
|
|
146
|
+
degree is ``True``, restrict to finite extensions and return
|
|
147
|
+
in addition the degree of ``ring`` over each base.
|
|
148
|
+
|
|
149
|
+
INPUT:
|
|
150
|
+
|
|
151
|
+
- ``ring`` -- a commutative ring
|
|
152
|
+
|
|
153
|
+
- ``degree`` -- boolean
|
|
154
|
+
|
|
155
|
+
EXAMPLES::
|
|
156
|
+
|
|
157
|
+
sage: from sage.rings.ring_extension import tower_bases
|
|
158
|
+
sage: S.<x> = QQ[]
|
|
159
|
+
sage: T.<y> = S[]
|
|
160
|
+
sage: tower_bases(T, False)
|
|
161
|
+
([Univariate Polynomial Ring in y over
|
|
162
|
+
Univariate Polynomial Ring in x over Rational Field,
|
|
163
|
+
Univariate Polynomial Ring in x over Rational Field,
|
|
164
|
+
Rational Field],
|
|
165
|
+
[])
|
|
166
|
+
sage: tower_bases(T, True)
|
|
167
|
+
([Univariate Polynomial Ring in y over
|
|
168
|
+
Univariate Polynomial Ring in x over Rational Field],
|
|
169
|
+
[1])
|
|
170
|
+
|
|
171
|
+
sage: K.<a> = Qq(5^2) # needs sage.rings.padics
|
|
172
|
+
sage: L.<w> = K.extension(x^3 - 5) # needs sage.rings.padics
|
|
173
|
+
sage: tower_bases(L, True) # needs sage.rings.padics
|
|
174
|
+
([5-adic Eisenstein Extension Field in w defined by x^3 - 5 over its base field,
|
|
175
|
+
5-adic Unramified Extension Field in a defined by x^2 + 4*x + 2,
|
|
176
|
+
5-adic Field with capped relative precision 20],
|
|
177
|
+
[1, 3, 6])
|
|
178
|
+
"""
|
|
179
|
+
bases = []
|
|
180
|
+
degrees = []
|
|
181
|
+
base = ring
|
|
182
|
+
deg = 1
|
|
183
|
+
while True:
|
|
184
|
+
bases.append(base)
|
|
185
|
+
if degree:
|
|
186
|
+
degrees.append(deg)
|
|
187
|
+
try:
|
|
188
|
+
d = base.relative_degree()
|
|
189
|
+
except AttributeError:
|
|
190
|
+
try:
|
|
191
|
+
d = base.degree()
|
|
192
|
+
except AttributeError:
|
|
193
|
+
break
|
|
194
|
+
if d is Infinity: break
|
|
195
|
+
deg *= d
|
|
196
|
+
newbase = base._base
|
|
197
|
+
if newbase is base: break
|
|
198
|
+
base = newbase
|
|
199
|
+
return bases, degrees
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def common_base(K, L, degree):
|
|
203
|
+
"""
|
|
204
|
+
Return a common base on which ``K`` and ``L`` are defined.
|
|
205
|
+
|
|
206
|
+
INPUT:
|
|
207
|
+
|
|
208
|
+
- ``K`` -- a commutative ring
|
|
209
|
+
|
|
210
|
+
- ``L`` -- a commutative ring
|
|
211
|
+
|
|
212
|
+
- ``degree`` -- boolean; if ``True``, return the degree of
|
|
213
|
+
``K`` and ``L`` over their common base
|
|
214
|
+
|
|
215
|
+
EXAMPLES::
|
|
216
|
+
|
|
217
|
+
sage: from sage.rings.ring_extension import common_base
|
|
218
|
+
|
|
219
|
+
sage: common_base(GF(5^3), GF(5^7), False) # needs sage.rings.finite_rings
|
|
220
|
+
Finite Field of size 5
|
|
221
|
+
sage: common_base(GF(5^3), GF(5^7), True) # needs sage.rings.finite_rings
|
|
222
|
+
(Finite Field of size 5, 3, 7)
|
|
223
|
+
|
|
224
|
+
sage: common_base(GF(5^3), GF(7^5), False) # needs sage.rings.finite_rings
|
|
225
|
+
Traceback (most recent call last):
|
|
226
|
+
...
|
|
227
|
+
NotImplementedError: unable to find a common base
|
|
228
|
+
|
|
229
|
+
When ``degree`` is set to ``True``, we only look up for bases on
|
|
230
|
+
which both ``K`` and ``L`` are finite::
|
|
231
|
+
|
|
232
|
+
sage: S.<x> = QQ[]
|
|
233
|
+
sage: common_base(S, QQ, False)
|
|
234
|
+
Rational Field
|
|
235
|
+
sage: common_base(S, QQ, True)
|
|
236
|
+
Traceback (most recent call last):
|
|
237
|
+
...
|
|
238
|
+
NotImplementedError: unable to find a common base
|
|
239
|
+
"""
|
|
240
|
+
bases_K, degrees_K = tower_bases(K, degree)
|
|
241
|
+
bases_L, degrees_L = tower_bases(L, degree)
|
|
242
|
+
base = None
|
|
243
|
+
for iL in range(len(bases_L)):
|
|
244
|
+
try:
|
|
245
|
+
iK = bases_K.index(bases_L[iL])
|
|
246
|
+
base = bases_L[iL]
|
|
247
|
+
break
|
|
248
|
+
except ValueError:
|
|
249
|
+
pass
|
|
250
|
+
if base is None:
|
|
251
|
+
raise NotImplementedError("unable to find a common base")
|
|
252
|
+
if degree:
|
|
253
|
+
return base, degrees_K[iK], degrees_L[iL]
|
|
254
|
+
else:
|
|
255
|
+
return base
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def generators(ring, base):
|
|
259
|
+
r"""
|
|
260
|
+
Return the generators of ``ring`` over ``base``.
|
|
261
|
+
|
|
262
|
+
INPUT:
|
|
263
|
+
|
|
264
|
+
- ``ring`` -- a commutative ring
|
|
265
|
+
|
|
266
|
+
- ``base`` -- a commutative ring
|
|
267
|
+
|
|
268
|
+
EXAMPLES::
|
|
269
|
+
|
|
270
|
+
sage: from sage.rings.ring_extension import generators
|
|
271
|
+
sage: S.<x> = QQ[]
|
|
272
|
+
sage: T.<y> = S[]
|
|
273
|
+
|
|
274
|
+
sage: generators(T, S)
|
|
275
|
+
(y,)
|
|
276
|
+
sage: generators(T, QQ)
|
|
277
|
+
(y, x)
|
|
278
|
+
"""
|
|
279
|
+
gens = tuple()
|
|
280
|
+
while ring is not ring.base_ring() and (base is None or not base.has_coerce_map_from(ring)):
|
|
281
|
+
gens += tuple(ring.gens())
|
|
282
|
+
ring = ring.base_ring()
|
|
283
|
+
if base is None:
|
|
284
|
+
return gens
|
|
285
|
+
else:
|
|
286
|
+
return tuple([x for x in gens if x not in base])
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def variable_names(ring, base):
|
|
290
|
+
r"""
|
|
291
|
+
Return the variable names of the generators of ``ring``
|
|
292
|
+
over ``base``.
|
|
293
|
+
|
|
294
|
+
INPUT:
|
|
295
|
+
|
|
296
|
+
- ``ring`` -- a commutative ring
|
|
297
|
+
|
|
298
|
+
- ``base`` -- a commutative ring
|
|
299
|
+
|
|
300
|
+
EXAMPLES::
|
|
301
|
+
|
|
302
|
+
sage: from sage.rings.ring_extension import variable_names
|
|
303
|
+
sage: S.<x> = QQ[]
|
|
304
|
+
sage: T.<y> = S[]
|
|
305
|
+
|
|
306
|
+
sage: variable_names(T, S)
|
|
307
|
+
('y',)
|
|
308
|
+
sage: variable_names(T, QQ)
|
|
309
|
+
('y', 'x')
|
|
310
|
+
"""
|
|
311
|
+
names = tuple()
|
|
312
|
+
while ring is not ring.base_ring() and (base is None or not base.has_coerce_map_from(ring)):
|
|
313
|
+
gens = ring.gens()
|
|
314
|
+
vars = ring.variable_names()
|
|
315
|
+
if len(gens) != len(vars):
|
|
316
|
+
raise NotImplementedError("cannot figure out the variable names")
|
|
317
|
+
if base is None:
|
|
318
|
+
names += tuple(vars)
|
|
319
|
+
else:
|
|
320
|
+
for gen, var in zip(gens, vars):
|
|
321
|
+
if gen not in base:
|
|
322
|
+
names += (var,)
|
|
323
|
+
ring = ring.base_ring()
|
|
324
|
+
return names
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# Factory
|
|
328
|
+
#########
|
|
329
|
+
|
|
330
|
+
class RingExtensionFactory(UniqueFactory):
|
|
331
|
+
"""
|
|
332
|
+
Factory for ring extensions.
|
|
333
|
+
|
|
334
|
+
TESTS::
|
|
335
|
+
|
|
336
|
+
sage: E = QQ.over(ZZ)
|
|
337
|
+
sage: QQ.over(ZZ) is E
|
|
338
|
+
True
|
|
339
|
+
|
|
340
|
+
sage: x = polygen(ZZ, 'x')
|
|
341
|
+
sage: K.<a> = QQ.extension(x^2 - 2) # needs sage.rings.number_field
|
|
342
|
+
sage: E = K.over(QQ); E # needs sage.rings.number_field
|
|
343
|
+
Field in a with defining polynomial x^2 - 2 over its base
|
|
344
|
+
|
|
345
|
+
sage: E2.<b> = K.over(QQ) # needs sage.rings.number_field
|
|
346
|
+
sage: E2 is E # needs sage.rings.number_field
|
|
347
|
+
False
|
|
348
|
+
"""
|
|
349
|
+
def create_key_and_extra_args(self, ring, defining_morphism=None, gens=None, names=None, constructors=None):
|
|
350
|
+
"""
|
|
351
|
+
Create a key and return it together with a list of constructors
|
|
352
|
+
of the object.
|
|
353
|
+
|
|
354
|
+
INPUT:
|
|
355
|
+
|
|
356
|
+
- ``ring`` -- a commutative ring
|
|
357
|
+
|
|
358
|
+
- ``defining_morphism`` -- a ring homomorphism or a commutative
|
|
359
|
+
ring or ``None`` (default: ``None``); the defining morphism of
|
|
360
|
+
this extension or its base (if it coerces to ``ring``)
|
|
361
|
+
|
|
362
|
+
- ``gens`` -- list of generators of this extension (over its base)
|
|
363
|
+
or ``None`` (default: ``None``)
|
|
364
|
+
|
|
365
|
+
- ``names`` -- list or a tuple of variable names or ``None``
|
|
366
|
+
(default: ``None``)
|
|
367
|
+
|
|
368
|
+
- ``constructors`` -- list of constructors; each constructor
|
|
369
|
+
is a pair `(class, arguments)` where `class` is the class
|
|
370
|
+
implementing the extension and `arguments` is the dictionary
|
|
371
|
+
of arguments to pass in to init function
|
|
372
|
+
|
|
373
|
+
TESTS::
|
|
374
|
+
|
|
375
|
+
sage: from sage.rings.ring_extension import RingExtension
|
|
376
|
+
sage: RingExtension.create_key_and_extra_args(QQ, ZZ)
|
|
377
|
+
((Ring morphism:
|
|
378
|
+
From: Integer Ring
|
|
379
|
+
To: Rational Field
|
|
380
|
+
Defn: 1 |--> 1, (), ()),
|
|
381
|
+
{'constructors': [(<class 'sage.rings.ring_extension.RingExtension_generic'>,
|
|
382
|
+
{'is_backend_exposed': True,
|
|
383
|
+
'print_options': {'print_elements_as': None,
|
|
384
|
+
'print_parent_as': None}})]})
|
|
385
|
+
|
|
386
|
+
sage: RingExtension.create_key_and_extra_args(GF(5^4), GF(5^2), # needs sage.rings.finite_rings
|
|
387
|
+
....: names=('a',))
|
|
388
|
+
((Ring morphism:
|
|
389
|
+
From: Finite Field in z2 of size 5^2
|
|
390
|
+
To: Finite Field in z4 of size 5^4
|
|
391
|
+
Defn: z2 |--> z4^3 + z4^2 + z4 + 3, (z4,), ('a',)),
|
|
392
|
+
{'constructors': [(<class 'sage.rings.ring_extension.RingExtensionWithGen'>,
|
|
393
|
+
{'gen': z4, 'is_backend_exposed': True, 'names': ('a',)})]})
|
|
394
|
+
"""
|
|
395
|
+
use_generic_constructor = True
|
|
396
|
+
is_backend_exposed = True
|
|
397
|
+
print_as = None
|
|
398
|
+
|
|
399
|
+
if defining_morphism is None:
|
|
400
|
+
base = ring.base_ring()
|
|
401
|
+
elif isinstance(defining_morphism, Map):
|
|
402
|
+
base = defining_morphism.domain()
|
|
403
|
+
elif defining_morphism in CommutativeRings():
|
|
404
|
+
base = defining_morphism
|
|
405
|
+
defining_morphism = None
|
|
406
|
+
else:
|
|
407
|
+
raise TypeError("only commutative rings are accepted")
|
|
408
|
+
|
|
409
|
+
# We compute the defining morphism
|
|
410
|
+
if defining_morphism is None:
|
|
411
|
+
if isinstance(base, RingExtension_generic):
|
|
412
|
+
backend_base = (<RingExtension_generic>base)._backend
|
|
413
|
+
if ring.has_coerce_map_from(backend_base):
|
|
414
|
+
defining_morphism = RingExtensionHomomorphism(base.Hom(ring), ring.coerce_map_from(backend_base))
|
|
415
|
+
else:
|
|
416
|
+
if ring.has_coerce_map_from(base):
|
|
417
|
+
defining_morphism = ring.coerce_map_from(base)
|
|
418
|
+
if defining_morphism is None:
|
|
419
|
+
raise ValueError("No coercion map from %s to %s" % (base,ring))
|
|
420
|
+
else:
|
|
421
|
+
if defining_morphism.domain() is not base:
|
|
422
|
+
defining_morphism = defining_morphism.extend_domain(base)
|
|
423
|
+
if defining_morphism.codomain() is not ring:
|
|
424
|
+
defining_morphism = defining_morphism.extend_codomain(ring)
|
|
425
|
+
if not isinstance(defining_morphism, RingExtensionHomomorphism):
|
|
426
|
+
defining_morphism = RingExtensionHomomorphism(defining_morphism.parent(), defining_morphism)
|
|
427
|
+
if isinstance(ring, RingExtension_generic):
|
|
428
|
+
defining_morphism = backend_morphism(defining_morphism, forget='codomain')
|
|
429
|
+
if (<RingExtension_generic>ring)._is_backend_exposed:
|
|
430
|
+
print_as = (<RingExtension_generic>ring)._backend
|
|
431
|
+
else:
|
|
432
|
+
use_generic_constructor = False
|
|
433
|
+
is_backend_exposed = False
|
|
434
|
+
ring = (<RingExtension_generic>ring)._backend
|
|
435
|
+
|
|
436
|
+
# We normalize other attributes
|
|
437
|
+
if gens is not None:
|
|
438
|
+
if not isinstance(gens, (list, tuple)):
|
|
439
|
+
raise TypeError("gens must be a list or a tuple")
|
|
440
|
+
gens = tuple(ring(g) for g in gens )
|
|
441
|
+
if names is None:
|
|
442
|
+
raise TypeError("you must specify the names of the generators")
|
|
443
|
+
names = normalize_names(len(gens), names)
|
|
444
|
+
use_generic_constructor = False
|
|
445
|
+
else:
|
|
446
|
+
gens = generators(ring, base)
|
|
447
|
+
if names is None:
|
|
448
|
+
try:
|
|
449
|
+
names = variable_names(ring, base)
|
|
450
|
+
except NotImplementedError:
|
|
451
|
+
gens = names = None
|
|
452
|
+
else:
|
|
453
|
+
names = normalize_names(len(gens), names)
|
|
454
|
+
use_generic_constructor = False
|
|
455
|
+
|
|
456
|
+
# We figure out what are the best constructors
|
|
457
|
+
if constructors is None:
|
|
458
|
+
constructors = []
|
|
459
|
+
if gens is not None and len(gens) == 1:
|
|
460
|
+
constructors.append((RingExtensionWithGen,
|
|
461
|
+
{'gen': gens[0], 'names': names,
|
|
462
|
+
'is_backend_exposed': is_backend_exposed}))
|
|
463
|
+
if use_generic_constructor:
|
|
464
|
+
constructors.append((RingExtension_generic,
|
|
465
|
+
{'print_options': {'print_parent_as': print_as,
|
|
466
|
+
'print_elements_as': print_as},
|
|
467
|
+
'is_backend_exposed': is_backend_exposed}))
|
|
468
|
+
|
|
469
|
+
# We build the key and return it
|
|
470
|
+
return (defining_morphism, gens, names), {'constructors': constructors}
|
|
471
|
+
|
|
472
|
+
def create_object(self, version, key, **extra_args):
|
|
473
|
+
"""
|
|
474
|
+
Return the object associated to a given key.
|
|
475
|
+
|
|
476
|
+
TESTS::
|
|
477
|
+
|
|
478
|
+
sage: from sage.rings.ring_extension import RingExtension
|
|
479
|
+
sage: key, extra_args = RingExtension.create_key_and_extra_args(QQ, ZZ)
|
|
480
|
+
sage: RingExtension.create_object((8,9,0), key, **extra_args)
|
|
481
|
+
Rational Field over its base
|
|
482
|
+
"""
|
|
483
|
+
defining_morphism, gens, names = key
|
|
484
|
+
constructors = extra_args['constructors']
|
|
485
|
+
if len(constructors) == 0:
|
|
486
|
+
raise NotImplementedError("no constructor available for this extension")
|
|
487
|
+
for (constructor, kwargs) in constructors[:-1]:
|
|
488
|
+
try:
|
|
489
|
+
return constructor(defining_morphism, **kwargs)
|
|
490
|
+
except (NotImplementedError, ValueError, TypeError):
|
|
491
|
+
pass
|
|
492
|
+
(constructor, kwargs) = constructors[-1]
|
|
493
|
+
return constructor(defining_morphism, **kwargs)
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
RingExtension = RingExtensionFactory("sage.rings.ring_extension.RingExtension")
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
# General extensions
|
|
500
|
+
####################
|
|
501
|
+
|
|
502
|
+
cdef class RingExtension_generic(Parent):
|
|
503
|
+
r"""
|
|
504
|
+
A generic class for all ring extensions.
|
|
505
|
+
|
|
506
|
+
TESTS::
|
|
507
|
+
|
|
508
|
+
sage: Q = QQ.over(ZZ) # indirect doctest
|
|
509
|
+
sage: Q
|
|
510
|
+
Rational Field over its base
|
|
511
|
+
|
|
512
|
+
sage: type(Q)
|
|
513
|
+
<class 'sage.rings.ring_extension.RingExtension_generic'>
|
|
514
|
+
|
|
515
|
+
sage: TestSuite(Q).run()
|
|
516
|
+
"""
|
|
517
|
+
Element = RingExtensionElement
|
|
518
|
+
|
|
519
|
+
def __init__(self, defining_morphism, print_options={}, import_methods=True, is_backend_exposed=False, category=None):
|
|
520
|
+
r"""
|
|
521
|
+
Initialize this ring extension.
|
|
522
|
+
|
|
523
|
+
INPUT:
|
|
524
|
+
|
|
525
|
+
- ``defining_morphism`` -- a ring homomorphism
|
|
526
|
+
|
|
527
|
+
- ``print_options`` -- dictionary
|
|
528
|
+
|
|
529
|
+
- ``import_methods`` -- boolean (default: ``True``); whether this
|
|
530
|
+
parent (resp. its elements) import the methods of the backend
|
|
531
|
+
parent class (resp. element class)
|
|
532
|
+
|
|
533
|
+
- ``is_backend_exposed`` -- boolean (default: ``False``); whether
|
|
534
|
+
the backend ring can be exposed to the user
|
|
535
|
+
|
|
536
|
+
- ``category`` -- the category for the resulting parent
|
|
537
|
+
(default: ``CommutativeRings()``)
|
|
538
|
+
|
|
539
|
+
.. NOTE::
|
|
540
|
+
|
|
541
|
+
The attribute ``is_backend_exposed`` is only used for printing;
|
|
542
|
+
when it is ``False``, printing an element like its backend is
|
|
543
|
+
disabled (and a :exc:`RuntimeError` is raised when it would occur).
|
|
544
|
+
|
|
545
|
+
OUTPUT: the extension defined by ``defining_morphism``
|
|
546
|
+
|
|
547
|
+
EXAMPLES::
|
|
548
|
+
|
|
549
|
+
sage: QQ.over(ZZ)
|
|
550
|
+
Rational Field over its base
|
|
551
|
+
|
|
552
|
+
sage: S.<x> = QQ[]
|
|
553
|
+
sage: S.over() # over QQ
|
|
554
|
+
Univariate Polynomial Ring in x over Rational Field over its base
|
|
555
|
+
|
|
556
|
+
TESTS::
|
|
557
|
+
|
|
558
|
+
sage: ZZ.over(NN)
|
|
559
|
+
Traceback (most recent call last):
|
|
560
|
+
...
|
|
561
|
+
TypeError: only commutative rings are accepted
|
|
562
|
+
|
|
563
|
+
sage: K = GF(5^3) # needs sage.rings.finite_rings
|
|
564
|
+
sage: K.over(K.frobenius_endomorphism()) # needs sage.rings.finite_rings
|
|
565
|
+
Traceback (most recent call last):
|
|
566
|
+
...
|
|
567
|
+
ValueError: exotic defining morphism between two rings in the tower; consider using another variable name
|
|
568
|
+
"""
|
|
569
|
+
cdef Parent base, ring
|
|
570
|
+
cdef Parent b, backend
|
|
571
|
+
cdef Map f
|
|
572
|
+
|
|
573
|
+
base = defining_morphism.domain()
|
|
574
|
+
ring = defining_morphism.codomain()
|
|
575
|
+
if category is None:
|
|
576
|
+
# Another option would be to set category = CommutativeAlgebras(base)
|
|
577
|
+
# but CommutativeRings() seems safer, especially when dealing with
|
|
578
|
+
# morphisms which do not need to preserve the base
|
|
579
|
+
category = CommutativeRings()
|
|
580
|
+
Parent.__init__(self, base=ZZ, category=category)
|
|
581
|
+
self._base = base
|
|
582
|
+
self._backend = ring
|
|
583
|
+
self._backend_defining_morphism = defining_morphism
|
|
584
|
+
self._defining_morphism = RingExtensionHomomorphism(self._base.Hom(self), defining_morphism)
|
|
585
|
+
self._print_options = print_options.copy()
|
|
586
|
+
if 'over' not in self._print_options:
|
|
587
|
+
self._print_options['over'] = ZZ(0)
|
|
588
|
+
self._import_methods = import_methods
|
|
589
|
+
self._is_backend_exposed = is_backend_exposed
|
|
590
|
+
self._type = "Ring"
|
|
591
|
+
if self._backend in Fields():
|
|
592
|
+
self._type = "Field"
|
|
593
|
+
|
|
594
|
+
# Some checks
|
|
595
|
+
if (base not in CommutativeRings()
|
|
596
|
+
or ring not in CommutativeRings()
|
|
597
|
+
or not defining_morphism.category_for().is_subcategory(CommutativeRings())):
|
|
598
|
+
raise TypeError("only commutative rings are accepted")
|
|
599
|
+
f = ring.Hom(ring).identity()
|
|
600
|
+
b = self
|
|
601
|
+
while isinstance(b, RingExtension_generic):
|
|
602
|
+
f *= backend_morphism((<RingExtension_generic>b)._backend_defining_morphism)
|
|
603
|
+
b = b._base
|
|
604
|
+
if isinstance(b, RingExtension_generic):
|
|
605
|
+
backend = (<RingExtension_generic>b)._backend
|
|
606
|
+
else:
|
|
607
|
+
backend = b
|
|
608
|
+
if ring.has_coerce_map_from(backend) and not are_equal_morphisms(f, None):
|
|
609
|
+
# TODO: find a better message
|
|
610
|
+
raise ValueError("exotic defining morphism between two rings in the tower; consider using another variable name")
|
|
611
|
+
|
|
612
|
+
# We register coercion/conversion maps
|
|
613
|
+
self.register_coercion(self._defining_morphism.__copy__())
|
|
614
|
+
self.register_coercion(RingExtensionBackendIsomorphism(ring.Hom(self)))
|
|
615
|
+
ring.register_conversion(RingExtensionBackendReverseIsomorphism(self.Hom(ring)))
|
|
616
|
+
|
|
617
|
+
@cython.binding(True)
|
|
618
|
+
def __getattr__(self, name):
|
|
619
|
+
"""
|
|
620
|
+
If this extension was created with ``import_methods = True``,
|
|
621
|
+
return a wrapper to the corresponding method of the backend
|
|
622
|
+
parent (if it exists).
|
|
623
|
+
|
|
624
|
+
EXAMPLES::
|
|
625
|
+
|
|
626
|
+
sage: # needs sage.rings.number_field
|
|
627
|
+
sage: x = polygen(ZZ, 'x')
|
|
628
|
+
sage: K.<a> = QQ.extension(x^2 - 2)
|
|
629
|
+
sage: E = K.over() # over QQ
|
|
630
|
+
sage: hasattr(E, 'automorphisms')
|
|
631
|
+
True
|
|
632
|
+
sage: E.automorphisms()
|
|
633
|
+
[Ring endomorphism of Field in a with defining polynomial x^2 - 2 over its base
|
|
634
|
+
Defn: a |--> a,
|
|
635
|
+
Ring endomorphism of Field in a with defining polynomial x^2 - 2 over its base
|
|
636
|
+
Defn: a |--> -a]
|
|
637
|
+
"""
|
|
638
|
+
try:
|
|
639
|
+
return self.getattr_from_category(name)
|
|
640
|
+
except AttributeError:
|
|
641
|
+
pass
|
|
642
|
+
method = None
|
|
643
|
+
if self._import_methods and hasattr(self._backend, name):
|
|
644
|
+
method = getattr(self._backend, name)
|
|
645
|
+
if not callable(method):
|
|
646
|
+
raise AttributeError(AttributeErrorMessage(self, name))
|
|
647
|
+
|
|
648
|
+
def wrapper(*args, **kwargs):
|
|
649
|
+
output = method(*to_backend(args), **to_backend(kwargs))
|
|
650
|
+
return from_backend(output, self)
|
|
651
|
+
wrapper.__doc__ = method.__doc__
|
|
652
|
+
return wrapper
|
|
653
|
+
|
|
654
|
+
def __dir__(self):
|
|
655
|
+
"""
|
|
656
|
+
Return the list of all the attributes of this extension;
|
|
657
|
+
if the extension was created with ``import_methods = True``,
|
|
658
|
+
concatenate this list with the list of all the methods of
|
|
659
|
+
the backend parent.
|
|
660
|
+
|
|
661
|
+
EXAMPLES::
|
|
662
|
+
|
|
663
|
+
sage: x = polygen(ZZ, 'x')
|
|
664
|
+
sage: A.<a> = QQ.extension(x^2 - 2) # needs sage.rings.number_field
|
|
665
|
+
sage: K.<a> = A.over() # needs sage.rings.number_field
|
|
666
|
+
|
|
667
|
+
sage: dir(K) # needs sage.rings.number_field
|
|
668
|
+
['CartesianProduct',
|
|
669
|
+
'Element',
|
|
670
|
+
'Hom',
|
|
671
|
+
...
|
|
672
|
+
'zeta',
|
|
673
|
+
'zeta_coefficients',
|
|
674
|
+
'zeta_function',
|
|
675
|
+
'zeta_order']
|
|
676
|
+
"""
|
|
677
|
+
d = dir_with_other_class(self, self.category().parent_class)
|
|
678
|
+
if not self._import_methods:
|
|
679
|
+
return d
|
|
680
|
+
for name in dir(self._backend):
|
|
681
|
+
if name[0] == "_": continue
|
|
682
|
+
try:
|
|
683
|
+
attribute = getattr(self._backend, name)
|
|
684
|
+
if callable(attribute):
|
|
685
|
+
d.append(name)
|
|
686
|
+
except Exception:
|
|
687
|
+
pass
|
|
688
|
+
return sorted(set(d))
|
|
689
|
+
|
|
690
|
+
def __hash__(self):
|
|
691
|
+
"""
|
|
692
|
+
Return a hash of this extension.
|
|
693
|
+
|
|
694
|
+
EXAMPLES:
|
|
695
|
+
|
|
696
|
+
sage: E = GF(5^3).over() # needs sage.rings.finite_rings
|
|
697
|
+
sage: hash(E) # random # needs sage.rings.finite_rings
|
|
698
|
+
140257667982632
|
|
699
|
+
"""
|
|
700
|
+
return hash_by_id(<void *>self)
|
|
701
|
+
|
|
702
|
+
def __reduce__(self):
|
|
703
|
+
"""
|
|
704
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
705
|
+
extension.
|
|
706
|
+
|
|
707
|
+
TESTS::
|
|
708
|
+
|
|
709
|
+
sage: K = GF(7^3).over() # needs sage.rings.finite_rings
|
|
710
|
+
sage: type(K) # needs sage.rings.finite_rings
|
|
711
|
+
<class 'sage.rings.ring_extension.RingExtensionWithGen'>
|
|
712
|
+
sage: loads(dumps(K)) is K # needs sage.rings.finite_rings
|
|
713
|
+
True
|
|
714
|
+
"""
|
|
715
|
+
(defining_morphism, gens, names) = self._factory_data[2]
|
|
716
|
+
constructors = self._factory_data[3]['constructors']
|
|
717
|
+
return RingExtension, (self._backend, defining_morphism, gens, names, constructors)
|
|
718
|
+
|
|
719
|
+
def construction(self):
|
|
720
|
+
"""
|
|
721
|
+
Return the functorial construction of this extension, if defined.
|
|
722
|
+
|
|
723
|
+
EXAMPLES::
|
|
724
|
+
|
|
725
|
+
sage: E = GF(5^3).over() # needs sage.rings.finite_rings
|
|
726
|
+
sage: E.construction() # needs sage.rings.finite_rings
|
|
727
|
+
"""
|
|
728
|
+
# One could define a construction functor K' -> K' otimes_K L, but we leave this to another issue
|
|
729
|
+
pass
|
|
730
|
+
|
|
731
|
+
def backend(self, force=False):
|
|
732
|
+
"""
|
|
733
|
+
Return the backend of this extension.
|
|
734
|
+
|
|
735
|
+
INPUT:
|
|
736
|
+
|
|
737
|
+
- ``force`` -- boolean (default: ``False``); if ``False``,
|
|
738
|
+
raise an error if the backend is not exposed
|
|
739
|
+
|
|
740
|
+
EXAMPLES::
|
|
741
|
+
|
|
742
|
+
sage: # needs sage.rings.finite_rings
|
|
743
|
+
sage: K = GF(5^3)
|
|
744
|
+
sage: E = K.over()
|
|
745
|
+
sage: E
|
|
746
|
+
Field in z3 with defining polynomial x^3 + 3*x + 3 over its base
|
|
747
|
+
sage: E.backend()
|
|
748
|
+
Finite Field in z3 of size 5^3
|
|
749
|
+
sage: E.backend() is K
|
|
750
|
+
True
|
|
751
|
+
"""
|
|
752
|
+
if force or self._is_backend_exposed:
|
|
753
|
+
return self._backend
|
|
754
|
+
raise ValueError("backend is not exposed; try force=True")
|
|
755
|
+
|
|
756
|
+
def from_base_ring(self, r):
|
|
757
|
+
r"""
|
|
758
|
+
Return the canonical embedding of ``r`` into this extension.
|
|
759
|
+
|
|
760
|
+
INPUT:
|
|
761
|
+
|
|
762
|
+
- ``r`` -- an element of the base of the ring of this extension
|
|
763
|
+
|
|
764
|
+
EXAMPLES::
|
|
765
|
+
|
|
766
|
+
sage: # needs sage.rings.finite_rings
|
|
767
|
+
sage: k = GF(5)
|
|
768
|
+
sage: K.<u> = GF(5^2).over(k)
|
|
769
|
+
sage: L.<v> = GF(5^4).over(K)
|
|
770
|
+
sage: x = L.from_base_ring(k(2)); x
|
|
771
|
+
2
|
|
772
|
+
sage: x.parent()
|
|
773
|
+
Field in v with defining polynomial x^2 + (3 - u)*x + u over its base
|
|
774
|
+
sage: x = L.from_base_ring(u); x
|
|
775
|
+
u
|
|
776
|
+
sage: x.parent()
|
|
777
|
+
Field in v with defining polynomial x^2 + (3 - u)*x + u over its base
|
|
778
|
+
"""
|
|
779
|
+
if r not in self._base:
|
|
780
|
+
raise TypeError("%s is not an element of the base of %s (= %s)" % (r, self._backend, self._base))
|
|
781
|
+
return self.element_class(self, r)
|
|
782
|
+
|
|
783
|
+
def print_options(self, **options):
|
|
784
|
+
"""
|
|
785
|
+
Update the printing options of this extension.
|
|
786
|
+
|
|
787
|
+
INPUT:
|
|
788
|
+
|
|
789
|
+
- ``over`` -- integer or ``Infinity`` (default: ``0``); the maximum
|
|
790
|
+
number of bases included in the printing of this extension
|
|
791
|
+
|
|
792
|
+
- ``base`` -- a base over which this extension is finite free;
|
|
793
|
+
elements in this extension will be printed as a linear
|
|
794
|
+
combinaison of a basis of this extension over the given base
|
|
795
|
+
|
|
796
|
+
EXAMPLES::
|
|
797
|
+
|
|
798
|
+
sage: # needs sage.rings.finite_rings
|
|
799
|
+
sage: A.<a> = GF(5^2).over() # over GF(5)
|
|
800
|
+
sage: B.<b> = GF(5^4).over(A)
|
|
801
|
+
sage: C.<c> = GF(5^12).over(B)
|
|
802
|
+
sage: D.<d> = GF(5^24).over(C)
|
|
803
|
+
|
|
804
|
+
Observe what happens when we modify the option ``over``::
|
|
805
|
+
|
|
806
|
+
sage: # needs sage.rings.finite_rings
|
|
807
|
+
sage: D
|
|
808
|
+
Field in d with defining polynomial
|
|
809
|
+
x^2 + ((1 - a) + ((1 + 2*a) - b)*c + ((2 + a) + (1 - a)*b)*c^2)*x + c over its base
|
|
810
|
+
sage: D.print_options(over=2)
|
|
811
|
+
sage: D
|
|
812
|
+
Field in d with defining polynomial x^2 + ((1 - a) + ((1 + 2*a) - b)*c + ((2 + a) + (1 - a)*b)*c^2)*x + c over
|
|
813
|
+
Field in c with defining polynomial x^3 + (1 + (2 - a)*b)*x^2 + (2 + 2*b)*x - b over
|
|
814
|
+
Field in b with defining polynomial x^2 + (3 - a)*x + a over its base
|
|
815
|
+
sage: D.print_options(over=Infinity)
|
|
816
|
+
sage: D
|
|
817
|
+
Field in d with defining polynomial x^2 + ((1 - a) + ((1 + 2*a) - b)*c + ((2 + a) + (1 - a)*b)*c^2)*x + c over
|
|
818
|
+
Field in c with defining polynomial x^3 + (1 + (2 - a)*b)*x^2 + (2 + 2*b)*x - b over
|
|
819
|
+
Field in b with defining polynomial x^2 + (3 - a)*x + a over
|
|
820
|
+
Field in a with defining polynomial x^2 + 4*x + 2 over
|
|
821
|
+
Finite Field of size 5
|
|
822
|
+
|
|
823
|
+
Now the option ``base``::
|
|
824
|
+
|
|
825
|
+
sage: # needs sage.rings.finite_rings
|
|
826
|
+
sage: d^2
|
|
827
|
+
-c + ((-1 + a) + ((-1 + 3*a) + b)*c + ((3 - a) + (-1 + a)*b)*c^2)*d
|
|
828
|
+
sage: D.basis_over(B)
|
|
829
|
+
[1, c, c^2, d, c*d, c^2*d]
|
|
830
|
+
sage: D.print_options(base=B)
|
|
831
|
+
sage: d^2
|
|
832
|
+
-c + (-1 + a)*d + ((-1 + 3*a) + b)*c*d + ((3 - a) + (-1 + a)*b)*c^2*d
|
|
833
|
+
sage: D.basis_over(A)
|
|
834
|
+
[1, b, c, b*c, c^2, b*c^2, d, b*d, c*d, b*c*d, c^2*d, b*c^2*d]
|
|
835
|
+
sage: D.print_options(base=A)
|
|
836
|
+
sage: d^2
|
|
837
|
+
-c + (-1 + a)*d + (-1 + 3*a)*c*d + b*c*d + (3 - a)*c^2*d + (-1 + a)*b*c^2*d
|
|
838
|
+
"""
|
|
839
|
+
for (name, value) in options.items():
|
|
840
|
+
method = None
|
|
841
|
+
if hasattr(self, '_print_option_' + name):
|
|
842
|
+
method = getattr(self, '_print_option_' + name)
|
|
843
|
+
if not callable(method):
|
|
844
|
+
raise ValueError("option '%s' does not exist" % name)
|
|
845
|
+
self._print_options[name] = method(value)
|
|
846
|
+
|
|
847
|
+
def _print_option_over(self, over):
|
|
848
|
+
"""
|
|
849
|
+
Check and normalize the print option ``over``.
|
|
850
|
+
|
|
851
|
+
INPUT:
|
|
852
|
+
|
|
853
|
+
- ``over`` -- integer or ``Infinity``
|
|
854
|
+
|
|
855
|
+
OUTPUT: the normalized value of ``over``
|
|
856
|
+
|
|
857
|
+
TESTS::
|
|
858
|
+
|
|
859
|
+
sage: E = QQ.over(ZZ)
|
|
860
|
+
sage: E.print_options(over=-2)
|
|
861
|
+
Traceback (most recent call last):
|
|
862
|
+
...
|
|
863
|
+
ValueError: 'over' must be nonnegative
|
|
864
|
+
|
|
865
|
+
sage: E.print_options(over=ZZ)
|
|
866
|
+
Traceback (most recent call last):
|
|
867
|
+
...
|
|
868
|
+
TypeError: unable to coerce <class 'sage.rings.integer_ring.IntegerRing_class'> to an integer
|
|
869
|
+
"""
|
|
870
|
+
if over is not None and over is not Infinity:
|
|
871
|
+
over = ZZ(over)
|
|
872
|
+
if over < 0:
|
|
873
|
+
raise ValueError("'over' must be nonnegative")
|
|
874
|
+
return over
|
|
875
|
+
|
|
876
|
+
def _repr_(self, **options):
|
|
877
|
+
r"""
|
|
878
|
+
Return a string representation of this extension.
|
|
879
|
+
|
|
880
|
+
INPUT:
|
|
881
|
+
|
|
882
|
+
- ``over`` -- integer, ``Infinity`` or ``None``; the maximum
|
|
883
|
+
number of bases included in the print representation of
|
|
884
|
+
this extension. If ``None``, use the print options of this extension.
|
|
885
|
+
|
|
886
|
+
EXAMPLES::
|
|
887
|
+
|
|
888
|
+
sage: E = QQ.over(ZZ)
|
|
889
|
+
sage: E
|
|
890
|
+
Rational Field over its base
|
|
891
|
+
|
|
892
|
+
sage: E._repr_()
|
|
893
|
+
'Rational Field over its base'
|
|
894
|
+
sage: E._repr_(over=Infinity)
|
|
895
|
+
'Rational Field over Integer Ring'
|
|
896
|
+
"""
|
|
897
|
+
if 'print_parent_as' in options:
|
|
898
|
+
print_as = options.pop('print_parent_as')
|
|
899
|
+
else:
|
|
900
|
+
print_as = self._print_options.get('print_parent_as')
|
|
901
|
+
if print_as is not None:
|
|
902
|
+
if isinstance(print_as, RingExtension_generic):
|
|
903
|
+
return print_as._repr_(**options)
|
|
904
|
+
else:
|
|
905
|
+
return str(print_as)
|
|
906
|
+
print_options = self._print_options.copy()
|
|
907
|
+
for (name, value) in options.items():
|
|
908
|
+
method = None
|
|
909
|
+
if hasattr(self, '_print_option_' + name):
|
|
910
|
+
method = getattr(self, '_print_option_' + name)
|
|
911
|
+
if not callable(method):
|
|
912
|
+
raise ValueError("option '%s' does not exist" % name)
|
|
913
|
+
print_options[name] = method(value)
|
|
914
|
+
over = print_options.pop('over', None)
|
|
915
|
+
s = self._repr_topring(**print_options)
|
|
916
|
+
if over is None or over == 0:
|
|
917
|
+
s += " over its base"
|
|
918
|
+
else:
|
|
919
|
+
s += " over "
|
|
920
|
+
base = self._base
|
|
921
|
+
if isinstance(base, RingExtension_generic):
|
|
922
|
+
s += base._repr_(over=over-1)
|
|
923
|
+
else:
|
|
924
|
+
s += str(base)
|
|
925
|
+
return s
|
|
926
|
+
|
|
927
|
+
def _repr_topring(self, **options):
|
|
928
|
+
r"""
|
|
929
|
+
Return a string representation of top ring of this extension.
|
|
930
|
+
|
|
931
|
+
EXAMPLES::
|
|
932
|
+
|
|
933
|
+
sage: E = QQ.over(ZZ)
|
|
934
|
+
sage: E._repr_topring()
|
|
935
|
+
'Rational Field'
|
|
936
|
+
"""
|
|
937
|
+
if not self._is_backend_exposed:
|
|
938
|
+
raise RuntimeError("backend is not exposed to the user; cannot print")
|
|
939
|
+
return str(self._backend)
|
|
940
|
+
|
|
941
|
+
def _latex_(self, **options):
|
|
942
|
+
r"""
|
|
943
|
+
Return a LaTeX representation of this extension.
|
|
944
|
+
|
|
945
|
+
- ``over`` -- integer, ``Infinity`` or ``None``; the maximum
|
|
946
|
+
number of bases included in the LaTeX representation of
|
|
947
|
+
this extension. If ``None``, use the print options of this extension.
|
|
948
|
+
|
|
949
|
+
EXAMPLES::
|
|
950
|
+
|
|
951
|
+
sage: E = QQ.over(ZZ)
|
|
952
|
+
sage: latex(E)
|
|
953
|
+
\Bold{Q}
|
|
954
|
+
|
|
955
|
+
sage: E._latex_()
|
|
956
|
+
\Bold{Q}
|
|
957
|
+
sage: E._latex_(over=Infinity)
|
|
958
|
+
\Bold{Q} / \Bold{Z}
|
|
959
|
+
"""
|
|
960
|
+
if 'print_parent_as' in options:
|
|
961
|
+
print_as = options.pop('print_parent_as')
|
|
962
|
+
else:
|
|
963
|
+
print_as = self._print_options.get('print_parent_as')
|
|
964
|
+
if print_as is not None:
|
|
965
|
+
if isinstance(print_as, RingExtension_generic):
|
|
966
|
+
return print_as._latex_(**options)
|
|
967
|
+
else:
|
|
968
|
+
return latex(print_as)
|
|
969
|
+
print_options = self._print_options.copy()
|
|
970
|
+
for (name, value) in options.items():
|
|
971
|
+
method = None
|
|
972
|
+
if hasattr(self, '_print_option_' + name):
|
|
973
|
+
method = getattr(self, '_print_option_' + name)
|
|
974
|
+
if not callable(method):
|
|
975
|
+
raise ValueError("option '%s' does not exist" % name)
|
|
976
|
+
print_options[name] = method(value)
|
|
977
|
+
over = print_options.pop('over', None)
|
|
978
|
+
s = self._latex_topring(**print_options)
|
|
979
|
+
if over > 0:
|
|
980
|
+
s += " / "
|
|
981
|
+
base = self._base
|
|
982
|
+
if isinstance(base, RingExtension_generic):
|
|
983
|
+
s += base._latex_(over=over-1)
|
|
984
|
+
else:
|
|
985
|
+
s += latex(base)
|
|
986
|
+
return s
|
|
987
|
+
|
|
988
|
+
def _latex_topring(self, **options):
|
|
989
|
+
r"""
|
|
990
|
+
Return a string representation of top ring of this extension.
|
|
991
|
+
|
|
992
|
+
EXAMPLES::
|
|
993
|
+
|
|
994
|
+
sage: E = QQ.over(ZZ)
|
|
995
|
+
sage: E._latex_topring()
|
|
996
|
+
\Bold{Q}
|
|
997
|
+
"""
|
|
998
|
+
if not self._is_backend_exposed:
|
|
999
|
+
raise RuntimeError("backend is not exposed to the user; cannot print")
|
|
1000
|
+
return latex(self._backend)
|
|
1001
|
+
|
|
1002
|
+
cpdef _coerce_map_from_(self, other):
|
|
1003
|
+
r"""
|
|
1004
|
+
Return a coerce map from this extension to ``other`` if defined.
|
|
1005
|
+
|
|
1006
|
+
COERCION MODEL
|
|
1007
|
+
|
|
1008
|
+
If `L/K` is an extension, a coercion map `K \to (L/K)`
|
|
1009
|
+
(acting through the defining morphism of `L/K`) is set.
|
|
1010
|
+
|
|
1011
|
+
If `L_1/K_1` and `L_2/K_2` are two extensions, a coercion
|
|
1012
|
+
map `(L_1/K_1) \to (L_2/K_2)` is set when `L_1` coerces to
|
|
1013
|
+
`L_2` and `K_1` coerces to `K_2` in such a way that the
|
|
1014
|
+
appropriate diagram commutes.
|
|
1015
|
+
|
|
1016
|
+
These rules have the following consequence regarding iterated
|
|
1017
|
+
extensions.
|
|
1018
|
+
Given two iterated extensions `A = (A_n/\cdots/A_2/A_1)` and
|
|
1019
|
+
`B = (B_m/\cdots/B_2/B_1)`, there is a coercion map `A \to B`
|
|
1020
|
+
if there exists a strictly increasing function
|
|
1021
|
+
`sigma : \{1,\ldots,n\} \to \{1,\ldots,m\}` and coercion maps
|
|
1022
|
+
`A_i \to B_{\sigma(i)}` making all the appropriate diagrams
|
|
1023
|
+
commutative.
|
|
1024
|
+
|
|
1025
|
+
.. NOTE::
|
|
1026
|
+
|
|
1027
|
+
In order to avoid discrepancies, it is forbidden to create
|
|
1028
|
+
an extension with exotic defining morphisms:
|
|
1029
|
+
if (A_n/\cdots/A_2/A_1) is an iterated extension and `i
|
|
1030
|
+
\leq j` are two indices such that `A_i` coerces to `A_j`,
|
|
1031
|
+
then the composition defining morphism `A_i \to A_{i+1}
|
|
1032
|
+
\to \cdots \to A_j` must agree with the coercion map.
|
|
1033
|
+
|
|
1034
|
+
TESTS::
|
|
1035
|
+
|
|
1036
|
+
sage: # needs sage.rings.finite_rings
|
|
1037
|
+
sage: E1 = GF(3^6).over(GF(3^3))
|
|
1038
|
+
sage: E1.coerce_map_from(GF(3^3)) # indirect doctest
|
|
1039
|
+
Ring morphism:
|
|
1040
|
+
From: Finite Field in z3 of size 3^3
|
|
1041
|
+
To: Field in z6 with defining polynomial x^2 + (2*z3 + 1)*x + z3 over its base
|
|
1042
|
+
Defn: z3 |--> z3
|
|
1043
|
+
sage: E1.coerce_map_from(GF(3)) # indirect doctest
|
|
1044
|
+
Ring morphism:
|
|
1045
|
+
From: Finite Field of size 3
|
|
1046
|
+
To: Field in z6 with defining polynomial x^2 + (2*z3 + 1)*x + z3 over its base
|
|
1047
|
+
Defn: 1 |--> 1
|
|
1048
|
+
sage: E2 = GF(3^18).over(GF(3^9))
|
|
1049
|
+
sage: E2.coerce_map_from(E1) # indirect doctest
|
|
1050
|
+
Ring morphism:
|
|
1051
|
+
From: Field in z6 with defining polynomial x^2 + (2*z3 + 1)*x + z3 over its base
|
|
1052
|
+
To: Field in z18 with defining polynomial x^2 + (z9^8 + 2*z9^7 + z9^5 + 2*z9^4 + z9^2 + z9 + 1)*x + z9 over its base
|
|
1053
|
+
Defn: z6 |--> (2*z9^7 + z9^6 + 2*z9^2 + 2*z9) + (z9^8 + 2*z9^7 + 2*z9^6 + z9^5 + z9^3 + z9 + 1)*z18
|
|
1054
|
+
|
|
1055
|
+
A test with iterated extensions::
|
|
1056
|
+
|
|
1057
|
+
sage: # needs sage.rings.finite_rings
|
|
1058
|
+
sage: A = GF(3^18).over(GF(3^3)) # simple extension GF(3^3) -> GF(3^18)
|
|
1059
|
+
sage: B = GF(3^18).over(E1) # iterated extension GF(3^3) -> GF(3^6) -> GF(3^18)
|
|
1060
|
+
sage: A.has_coerce_map_from(B)
|
|
1061
|
+
False
|
|
1062
|
+
sage: B.has_coerce_map_from(A)
|
|
1063
|
+
True
|
|
1064
|
+
"""
|
|
1065
|
+
cdef RingExtension_generic right
|
|
1066
|
+
if isinstance(other, RingExtension_generic):
|
|
1067
|
+
right = <RingExtension_generic>other
|
|
1068
|
+
if self._backend.has_coerce_map_from(right._backend) and self._base.has_coerce_map_from(right._base):
|
|
1069
|
+
backend = self._backend.coerce_map_from(right._backend)
|
|
1070
|
+
f = backend * backend_morphism(right._defining_morphism)
|
|
1071
|
+
g = backend_morphism(self._defining_morphism * self._base.coerce_map_from(right._base))
|
|
1072
|
+
if are_equal_morphisms(f, g):
|
|
1073
|
+
return RingExtensionHomomorphism(right.Hom(self), backend)
|
|
1074
|
+
|
|
1075
|
+
def base(self):
|
|
1076
|
+
r"""
|
|
1077
|
+
Return the base of this extension.
|
|
1078
|
+
|
|
1079
|
+
EXAMPLES::
|
|
1080
|
+
|
|
1081
|
+
sage: F = GF(5^2) # needs sage.rings.finite_rings
|
|
1082
|
+
sage: K = GF(5^4).over(F) # needs sage.rings.finite_rings
|
|
1083
|
+
sage: K.base() # needs sage.rings.finite_rings
|
|
1084
|
+
Finite Field in z2 of size 5^2
|
|
1085
|
+
|
|
1086
|
+
In case of iterated extensions, the base is itself an extension::
|
|
1087
|
+
|
|
1088
|
+
sage: L = GF(5^8).over(K) # needs sage.rings.finite_rings
|
|
1089
|
+
sage: L.base() # needs sage.rings.finite_rings
|
|
1090
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1091
|
+
sage: L.base() is K # needs sage.rings.finite_rings
|
|
1092
|
+
True
|
|
1093
|
+
|
|
1094
|
+
.. SEEALSO::
|
|
1095
|
+
|
|
1096
|
+
:meth:`bases`, :meth:`absolute_base`, :meth:`is_defined_over`
|
|
1097
|
+
"""
|
|
1098
|
+
return self._base
|
|
1099
|
+
|
|
1100
|
+
def bases(self):
|
|
1101
|
+
r"""
|
|
1102
|
+
Return the list of successive bases of this extension
|
|
1103
|
+
(including itself).
|
|
1104
|
+
|
|
1105
|
+
EXAMPLES::
|
|
1106
|
+
|
|
1107
|
+
sage: # needs sage.rings.finite_rings
|
|
1108
|
+
sage: F = GF(5^2).over() # over GF(5)
|
|
1109
|
+
sage: K = GF(5^4).over(F)
|
|
1110
|
+
sage: L = GF(5^12).over(K)
|
|
1111
|
+
sage: F.bases()
|
|
1112
|
+
[Field in z2 with defining polynomial x^2 + 4*x + 2 over its base,
|
|
1113
|
+
Finite Field of size 5]
|
|
1114
|
+
sage: K.bases()
|
|
1115
|
+
[Field in z4 with defining polynomial x^2 + (3 - z2)*x + z2 over its base,
|
|
1116
|
+
Field in z2 with defining polynomial x^2 + 4*x + 2 over its base,
|
|
1117
|
+
Finite Field of size 5]
|
|
1118
|
+
sage: L.bases()
|
|
1119
|
+
[Field in z12 with defining polynomial
|
|
1120
|
+
x^3 + (1 + (2 - z2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base,
|
|
1121
|
+
Field in z4 with defining polynomial x^2 + (3 - z2)*x + z2 over its base,
|
|
1122
|
+
Field in z2 with defining polynomial x^2 + 4*x + 2 over its base,
|
|
1123
|
+
Finite Field of size 5]
|
|
1124
|
+
|
|
1125
|
+
.. SEEALSO::
|
|
1126
|
+
|
|
1127
|
+
:meth:`base`, :meth:`absolute_base`, :meth:`is_defined_over`
|
|
1128
|
+
"""
|
|
1129
|
+
L = [self]
|
|
1130
|
+
base = self
|
|
1131
|
+
while isinstance(base, RingExtension_generic):
|
|
1132
|
+
base = base.base_ring()
|
|
1133
|
+
L.append(base)
|
|
1134
|
+
return L
|
|
1135
|
+
|
|
1136
|
+
def absolute_base(self):
|
|
1137
|
+
r"""
|
|
1138
|
+
Return the absolute base of this extension.
|
|
1139
|
+
|
|
1140
|
+
By definition, the absolute base of an iterated extension
|
|
1141
|
+
`K_n/\cdots K_2/K_1` is the ring `K_1`.
|
|
1142
|
+
|
|
1143
|
+
EXAMPLES::
|
|
1144
|
+
|
|
1145
|
+
sage: # needs sage.rings.finite_rings
|
|
1146
|
+
sage: F = GF(5^2).over() # over GF(5)
|
|
1147
|
+
sage: K = GF(5^4).over(F)
|
|
1148
|
+
sage: L = GF(5^12).over(K)
|
|
1149
|
+
sage: F.absolute_base()
|
|
1150
|
+
Finite Field of size 5
|
|
1151
|
+
sage: K.absolute_base()
|
|
1152
|
+
Finite Field of size 5
|
|
1153
|
+
sage: L.absolute_base()
|
|
1154
|
+
Finite Field of size 5
|
|
1155
|
+
|
|
1156
|
+
.. SEEALSO::
|
|
1157
|
+
|
|
1158
|
+
:meth:`base`, :meth:`bases`, :meth:`is_defined_over`
|
|
1159
|
+
"""
|
|
1160
|
+
return self.bases()[-1]
|
|
1161
|
+
|
|
1162
|
+
cpdef is_defined_over(self, base):
|
|
1163
|
+
r"""
|
|
1164
|
+
Return whether or not ``base`` is one of the bases of this
|
|
1165
|
+
extension.
|
|
1166
|
+
|
|
1167
|
+
INPUT:
|
|
1168
|
+
|
|
1169
|
+
- ``base`` -- a commutative ring, which might be itself an
|
|
1170
|
+
extension
|
|
1171
|
+
|
|
1172
|
+
EXAMPLES::
|
|
1173
|
+
|
|
1174
|
+
sage: # needs sage.rings.finite_rings
|
|
1175
|
+
sage: A = GF(5^4).over(GF(5^2))
|
|
1176
|
+
sage: B = GF(5^12).over(A)
|
|
1177
|
+
sage: A.is_defined_over(GF(5^2))
|
|
1178
|
+
True
|
|
1179
|
+
sage: A.is_defined_over(GF(5))
|
|
1180
|
+
False
|
|
1181
|
+
|
|
1182
|
+
sage: # needs sage.rings.finite_rings
|
|
1183
|
+
sage: B.is_defined_over(A)
|
|
1184
|
+
True
|
|
1185
|
+
sage: B.is_defined_over(GF(5^4))
|
|
1186
|
+
True
|
|
1187
|
+
sage: B.is_defined_over(GF(5^2))
|
|
1188
|
+
True
|
|
1189
|
+
sage: B.is_defined_over(GF(5))
|
|
1190
|
+
False
|
|
1191
|
+
|
|
1192
|
+
Note that an extension is defined over itself::
|
|
1193
|
+
|
|
1194
|
+
sage: A.is_defined_over(A) # needs sage.rings.finite_rings
|
|
1195
|
+
True
|
|
1196
|
+
sage: A.is_defined_over(GF(5^4)) # needs sage.rings.finite_rings
|
|
1197
|
+
True
|
|
1198
|
+
|
|
1199
|
+
.. SEEALSO::
|
|
1200
|
+
|
|
1201
|
+
:meth:`base`, :meth:`bases`, :meth:`absolute_base`
|
|
1202
|
+
"""
|
|
1203
|
+
cdef Parent b
|
|
1204
|
+
b = self
|
|
1205
|
+
while isinstance(b, RingExtension_generic):
|
|
1206
|
+
if b is base or (<RingExtension_generic>b)._backend is base: return True
|
|
1207
|
+
b = (<RingExtension_generic>b)._base
|
|
1208
|
+
return b is base
|
|
1209
|
+
|
|
1210
|
+
cpdef Parent _check_base(self, Parent base):
|
|
1211
|
+
r"""
|
|
1212
|
+
Check if ``base`` is one of the successive bases of this
|
|
1213
|
+
extension and, if it is, normalize it.
|
|
1214
|
+
|
|
1215
|
+
INPUT:
|
|
1216
|
+
|
|
1217
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1218
|
+
extension) or ``None``
|
|
1219
|
+
|
|
1220
|
+
OUTPUT:
|
|
1221
|
+
|
|
1222
|
+
The base ``base`` normalized as a parent appearing in the
|
|
1223
|
+
list of bases of this extension as returned by :meth:`bases`.
|
|
1224
|
+
|
|
1225
|
+
EXAMPLES::
|
|
1226
|
+
|
|
1227
|
+
sage: # needs sage.rings.finite_rings
|
|
1228
|
+
sage: F = GF(5^2)
|
|
1229
|
+
sage: K = GF(5^4).over(F)
|
|
1230
|
+
sage: L = GF(5^12).over(K)
|
|
1231
|
+
sage: L.bases()
|
|
1232
|
+
[Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base,
|
|
1233
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base,
|
|
1234
|
+
Finite Field in z2 of size 5^2]
|
|
1235
|
+
sage: L._check_base(K)
|
|
1236
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1237
|
+
sage: L._check_base(GF(5^4))
|
|
1238
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1239
|
+
sage: L._check_base(GF(5^4)) is K
|
|
1240
|
+
True
|
|
1241
|
+
|
|
1242
|
+
When ``base`` is ``None``, the base of the extension is returned::
|
|
1243
|
+
|
|
1244
|
+
sage: L._check_base(None) # needs sage.rings.finite_rings
|
|
1245
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1246
|
+
sage: L._check_base(None) is L.base() # needs sage.rings.finite_rings
|
|
1247
|
+
True
|
|
1248
|
+
"""
|
|
1249
|
+
cdef Parent b
|
|
1250
|
+
if base is None:
|
|
1251
|
+
return self._base
|
|
1252
|
+
b = self
|
|
1253
|
+
while isinstance(b, RingExtension_generic):
|
|
1254
|
+
if b is base or (<RingExtension_generic>b)._backend is base: return b
|
|
1255
|
+
b = (<RingExtension_generic>b)._base
|
|
1256
|
+
if b is base:
|
|
1257
|
+
return b
|
|
1258
|
+
raise ValueError("not (explicitly) defined over %s" % base)
|
|
1259
|
+
|
|
1260
|
+
def defining_morphism(self, base=None):
|
|
1261
|
+
r"""
|
|
1262
|
+
Return the defining morphism of this extension over ``base``.
|
|
1263
|
+
|
|
1264
|
+
INPUT:
|
|
1265
|
+
|
|
1266
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1267
|
+
extension) or ``None`` (default: ``None``)
|
|
1268
|
+
|
|
1269
|
+
EXAMPLES::
|
|
1270
|
+
|
|
1271
|
+
sage: # needs sage.rings.finite_rings
|
|
1272
|
+
sage: F = GF(5^2)
|
|
1273
|
+
sage: K = GF(5^4).over(F)
|
|
1274
|
+
sage: L = GF(5^12).over(K)
|
|
1275
|
+
sage: K.defining_morphism()
|
|
1276
|
+
Ring morphism:
|
|
1277
|
+
From: Finite Field in z2 of size 5^2
|
|
1278
|
+
To: Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1279
|
+
Defn: z2 |--> z2
|
|
1280
|
+
sage: L.defining_morphism()
|
|
1281
|
+
Ring morphism:
|
|
1282
|
+
From: Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1283
|
+
To: Field in z12 with defining polynomial
|
|
1284
|
+
x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base
|
|
1285
|
+
Defn: z4 |--> z4
|
|
1286
|
+
|
|
1287
|
+
One can also pass in a base over which the extension is explicitly
|
|
1288
|
+
defined (see also :meth:`is_defined_over`)::
|
|
1289
|
+
|
|
1290
|
+
sage: L.defining_morphism(F) # needs sage.rings.finite_rings
|
|
1291
|
+
Ring morphism:
|
|
1292
|
+
From: Finite Field in z2 of size 5^2
|
|
1293
|
+
To: Field in z12 with defining polynomial
|
|
1294
|
+
x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base
|
|
1295
|
+
Defn: z2 |--> z2
|
|
1296
|
+
sage: L.defining_morphism(GF(5)) # needs sage.rings.finite_rings
|
|
1297
|
+
Traceback (most recent call last):
|
|
1298
|
+
...
|
|
1299
|
+
ValueError: not (explicitly) defined over Finite Field of size 5
|
|
1300
|
+
"""
|
|
1301
|
+
base = self._check_base(base)
|
|
1302
|
+
return self.coerce_map_from(base)
|
|
1303
|
+
|
|
1304
|
+
def _an_element_(self):
|
|
1305
|
+
r"""
|
|
1306
|
+
Return an element of this extension.
|
|
1307
|
+
|
|
1308
|
+
TESTS::
|
|
1309
|
+
|
|
1310
|
+
sage: E = QQ.over(ZZ)
|
|
1311
|
+
sage: x = E.an_element() # indirect doctest
|
|
1312
|
+
sage: x
|
|
1313
|
+
1/2
|
|
1314
|
+
sage: x.parent()
|
|
1315
|
+
Rational Field over its base
|
|
1316
|
+
"""
|
|
1317
|
+
elt = self._backend.an_element()
|
|
1318
|
+
return self.element_class(self, elt)
|
|
1319
|
+
|
|
1320
|
+
def gens(self, base=None) -> tuple:
|
|
1321
|
+
r"""
|
|
1322
|
+
Return the generators of this extension over ``base``.
|
|
1323
|
+
|
|
1324
|
+
INPUT:
|
|
1325
|
+
|
|
1326
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1327
|
+
extension) or ``None`` (default: ``None``); if omitted,
|
|
1328
|
+
use the base of this extension
|
|
1329
|
+
|
|
1330
|
+
EXAMPLES::
|
|
1331
|
+
|
|
1332
|
+
sage: # needs sage.rings.finite_rings
|
|
1333
|
+
sage: K.<a> = GF(5^2).over() # over GF(5)
|
|
1334
|
+
sage: K.gens()
|
|
1335
|
+
(a,)
|
|
1336
|
+
sage: L.<b> = GF(5^4).over(K)
|
|
1337
|
+
sage: L.gens()
|
|
1338
|
+
(b,)
|
|
1339
|
+
sage: L.gens(GF(5))
|
|
1340
|
+
(b, a)
|
|
1341
|
+
|
|
1342
|
+
sage: S.<x> = QQ[]
|
|
1343
|
+
sage: T.<y> = S[]
|
|
1344
|
+
sage: T.over(S).gens()
|
|
1345
|
+
(y,)
|
|
1346
|
+
sage: T.over(QQ).gens()
|
|
1347
|
+
(y, x)
|
|
1348
|
+
"""
|
|
1349
|
+
self._check_base(base)
|
|
1350
|
+
return tuple([self(x) for x in generators(self._backend,
|
|
1351
|
+
backend_parent(self._base))])
|
|
1352
|
+
|
|
1353
|
+
def ngens(self, base=None):
|
|
1354
|
+
r"""
|
|
1355
|
+
Return the number of generators of this extension over ``base``.
|
|
1356
|
+
|
|
1357
|
+
INPUT:
|
|
1358
|
+
|
|
1359
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1360
|
+
extension) or ``None`` (default: ``None``)
|
|
1361
|
+
|
|
1362
|
+
EXAMPLES::
|
|
1363
|
+
|
|
1364
|
+
sage: # needs sage.rings.finite_rings
|
|
1365
|
+
sage: K = GF(5^2).over() # over GF(5)
|
|
1366
|
+
sage: K.gens()
|
|
1367
|
+
(z2,)
|
|
1368
|
+
sage: K.ngens()
|
|
1369
|
+
1
|
|
1370
|
+
sage: L = GF(5^4).over(K)
|
|
1371
|
+
sage: L.gens(GF(5))
|
|
1372
|
+
(z4, z2)
|
|
1373
|
+
sage: L.ngens(GF(5))
|
|
1374
|
+
2
|
|
1375
|
+
"""
|
|
1376
|
+
return len(self.gens(base))
|
|
1377
|
+
|
|
1378
|
+
def gen(self):
|
|
1379
|
+
r"""
|
|
1380
|
+
Return the first generator of this extension.
|
|
1381
|
+
|
|
1382
|
+
EXAMPLES::
|
|
1383
|
+
|
|
1384
|
+
sage: K = GF(5^2).over() # over GF(5) # needs sage.rings.finite_rings
|
|
1385
|
+
sage: x = K.gen(); x # needs sage.rings.finite_rings
|
|
1386
|
+
z2
|
|
1387
|
+
|
|
1388
|
+
Observe that the generator lives in the extension::
|
|
1389
|
+
|
|
1390
|
+
sage: x.parent() # needs sage.rings.finite_rings
|
|
1391
|
+
Field in z2 with defining polynomial x^2 + 4*x + 2 over its base
|
|
1392
|
+
sage: x.parent() is K # needs sage.rings.finite_rings
|
|
1393
|
+
True
|
|
1394
|
+
"""
|
|
1395
|
+
return self.gens()[0]
|
|
1396
|
+
|
|
1397
|
+
def random_element(self):
|
|
1398
|
+
r"""
|
|
1399
|
+
Return a random element in this extension.
|
|
1400
|
+
|
|
1401
|
+
EXAMPLES::
|
|
1402
|
+
|
|
1403
|
+
sage: # needs sage.rings.finite_rings
|
|
1404
|
+
sage: K = GF(5^2).over() # over GF(5)
|
|
1405
|
+
sage: x = K.random_element(); x # random
|
|
1406
|
+
3 + z2
|
|
1407
|
+
sage: x.parent()
|
|
1408
|
+
Field in z2 with defining polynomial x^2 + 4*x + 2 over its base
|
|
1409
|
+
sage: x.parent() is K
|
|
1410
|
+
True
|
|
1411
|
+
"""
|
|
1412
|
+
elt = self._backend.random_element()
|
|
1413
|
+
return self.element_class(self, elt)
|
|
1414
|
+
|
|
1415
|
+
def degree_over(self, base=None):
|
|
1416
|
+
r"""
|
|
1417
|
+
Return the degree of this extension over ``base``.
|
|
1418
|
+
|
|
1419
|
+
INPUT:
|
|
1420
|
+
|
|
1421
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1422
|
+
extension) or ``None`` (default: ``None``)
|
|
1423
|
+
|
|
1424
|
+
EXAMPLES::
|
|
1425
|
+
|
|
1426
|
+
sage: # needs sage.rings.finite_rings
|
|
1427
|
+
sage: F = GF(5^2)
|
|
1428
|
+
sage: K = GF(5^4).over(F)
|
|
1429
|
+
sage: L = GF(5^12).over(K)
|
|
1430
|
+
sage: K.degree_over(F)
|
|
1431
|
+
2
|
|
1432
|
+
sage: L.degree_over(K)
|
|
1433
|
+
3
|
|
1434
|
+
sage: L.degree_over(F)
|
|
1435
|
+
6
|
|
1436
|
+
|
|
1437
|
+
If ``base`` is omitted, the degree is computed over the base
|
|
1438
|
+
of the extension::
|
|
1439
|
+
|
|
1440
|
+
sage: K.degree_over() # needs sage.rings.finite_rings
|
|
1441
|
+
2
|
|
1442
|
+
sage: L.degree_over() # needs sage.rings.finite_rings
|
|
1443
|
+
3
|
|
1444
|
+
|
|
1445
|
+
Note that ``base`` must be an explicit base over which the
|
|
1446
|
+
extension has been defined (as listed by the method :meth:`bases`)::
|
|
1447
|
+
|
|
1448
|
+
sage: K.degree_over(GF(5)) # needs sage.rings.finite_rings
|
|
1449
|
+
Traceback (most recent call last):
|
|
1450
|
+
...
|
|
1451
|
+
ValueError: not (explicitly) defined over Finite Field of size 5
|
|
1452
|
+
"""
|
|
1453
|
+
base = self._check_base(base)
|
|
1454
|
+
return self._degree_over(base)
|
|
1455
|
+
|
|
1456
|
+
cpdef _degree_over(self, Parent base):
|
|
1457
|
+
r"""
|
|
1458
|
+
Return the degree of this extension over ``base``.
|
|
1459
|
+
|
|
1460
|
+
Should be implemented in subclasses.
|
|
1461
|
+
|
|
1462
|
+
INPUT:
|
|
1463
|
+
|
|
1464
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1465
|
+
extension) or ``None`` (default: ``None``)
|
|
1466
|
+
|
|
1467
|
+
TESTS::
|
|
1468
|
+
|
|
1469
|
+
sage: # needs sage.rings.number_field
|
|
1470
|
+
sage: x = polygen(ZZ, 'x')
|
|
1471
|
+
sage: A.<a> = QQ.extension(x^2 - 2)
|
|
1472
|
+
sage: B.<b> = QQ.extension(x^6 - 2)
|
|
1473
|
+
sage: f = A.hom([b^3])
|
|
1474
|
+
sage: E = B.over(f)
|
|
1475
|
+
sage: E.degree_over() # indirect doctest
|
|
1476
|
+
3
|
|
1477
|
+
"""
|
|
1478
|
+
if base is self:
|
|
1479
|
+
return ZZ(1)
|
|
1480
|
+
raise NotImplementedError("degree is not implemented (and maybe not defined) for this extension")
|
|
1481
|
+
|
|
1482
|
+
def degree(self, base):
|
|
1483
|
+
r"""
|
|
1484
|
+
Return the degree of this extension over ``base``.
|
|
1485
|
+
|
|
1486
|
+
INPUT:
|
|
1487
|
+
|
|
1488
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1489
|
+
extension)
|
|
1490
|
+
|
|
1491
|
+
EXAMPLES::
|
|
1492
|
+
|
|
1493
|
+
sage: # needs sage.rings.finite_rings
|
|
1494
|
+
sage: A = GF(5^4).over(GF(5^2))
|
|
1495
|
+
sage: B = GF(5^12).over(A)
|
|
1496
|
+
sage: A.degree(GF(5^2))
|
|
1497
|
+
2
|
|
1498
|
+
sage: B.degree(A)
|
|
1499
|
+
3
|
|
1500
|
+
sage: B.degree(GF(5^2))
|
|
1501
|
+
6
|
|
1502
|
+
|
|
1503
|
+
Note that ``base`` must be an explicit base over which the
|
|
1504
|
+
extension has been defined (as listed by the method :meth:`bases`)::
|
|
1505
|
+
|
|
1506
|
+
sage: A.degree(GF(5)) # needs sage.rings.finite_rings
|
|
1507
|
+
Traceback (most recent call last):
|
|
1508
|
+
...
|
|
1509
|
+
ValueError: not (explicitly) defined over Finite Field of size 5
|
|
1510
|
+
|
|
1511
|
+
.. SEEALSO::
|
|
1512
|
+
|
|
1513
|
+
:meth:`relative_degree`, :meth:`absolute_degree`
|
|
1514
|
+
"""
|
|
1515
|
+
return self.degree_over(base)
|
|
1516
|
+
|
|
1517
|
+
def relative_degree(self):
|
|
1518
|
+
r"""
|
|
1519
|
+
Return the degree of this extension over its base.
|
|
1520
|
+
|
|
1521
|
+
EXAMPLES::
|
|
1522
|
+
|
|
1523
|
+
sage: A = GF(5^4).over(GF(5^2)) # needs sage.rings.finite_rings
|
|
1524
|
+
sage: A.relative_degree() # needs sage.rings.finite_rings
|
|
1525
|
+
2
|
|
1526
|
+
|
|
1527
|
+
.. SEEALSO::
|
|
1528
|
+
|
|
1529
|
+
:meth:`degree`, :meth:`absolute_degree`
|
|
1530
|
+
"""
|
|
1531
|
+
return self._degree_over(self._base)
|
|
1532
|
+
|
|
1533
|
+
def absolute_degree(self):
|
|
1534
|
+
r"""
|
|
1535
|
+
Return the degree of this extension over its absolute base.
|
|
1536
|
+
|
|
1537
|
+
EXAMPLES::
|
|
1538
|
+
|
|
1539
|
+
sage: # needs sage.rings.finite_rings
|
|
1540
|
+
sage: A = GF(5^4).over(GF(5^2))
|
|
1541
|
+
sage: B = GF(5^12).over(A)
|
|
1542
|
+
sage: A.absolute_degree()
|
|
1543
|
+
2
|
|
1544
|
+
sage: B.absolute_degree()
|
|
1545
|
+
6
|
|
1546
|
+
|
|
1547
|
+
.. SEEALSO::
|
|
1548
|
+
|
|
1549
|
+
:meth:`degree`, :meth:`relative_degree`
|
|
1550
|
+
"""
|
|
1551
|
+
return self._degree_over(self.absolute_base())
|
|
1552
|
+
|
|
1553
|
+
def is_finite_over(self, base=None):
|
|
1554
|
+
r"""
|
|
1555
|
+
Return whether or not this extension is finite over ``base`` (as a module).
|
|
1556
|
+
|
|
1557
|
+
INPUT:
|
|
1558
|
+
|
|
1559
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1560
|
+
extension) or ``None`` (default: ``None``)
|
|
1561
|
+
|
|
1562
|
+
EXAMPLES::
|
|
1563
|
+
|
|
1564
|
+
sage: # needs sage.rings.finite_rings
|
|
1565
|
+
sage: K = GF(5^2).over() # over GF(5)
|
|
1566
|
+
sage: L = GF(5^4).over(K)
|
|
1567
|
+
sage: L.is_finite_over(K)
|
|
1568
|
+
True
|
|
1569
|
+
sage: L.is_finite_over(GF(5))
|
|
1570
|
+
True
|
|
1571
|
+
|
|
1572
|
+
If ``base`` is omitted, it is set to its default which is the
|
|
1573
|
+
base of the extension::
|
|
1574
|
+
|
|
1575
|
+
sage: L.is_finite_over() # needs sage.rings.finite_rings
|
|
1576
|
+
True
|
|
1577
|
+
"""
|
|
1578
|
+
cdef Parent b
|
|
1579
|
+
base = self._check_base(base)
|
|
1580
|
+
if base is self:
|
|
1581
|
+
return True
|
|
1582
|
+
try:
|
|
1583
|
+
return self._is_finite_over(base)
|
|
1584
|
+
except NotImplementedError:
|
|
1585
|
+
pass
|
|
1586
|
+
b = self._base
|
|
1587
|
+
while b is not base:
|
|
1588
|
+
try:
|
|
1589
|
+
if self._is_finite_over(b) and b.is_finite_over(base):
|
|
1590
|
+
return True
|
|
1591
|
+
except NotImplementedError:
|
|
1592
|
+
pass
|
|
1593
|
+
b = (<RingExtension_generic?>b)._base
|
|
1594
|
+
raise NotImplementedError
|
|
1595
|
+
|
|
1596
|
+
cpdef _is_finite_over(self, Parent base):
|
|
1597
|
+
r"""
|
|
1598
|
+
Return whether or not this extension is finite over ``base``.
|
|
1599
|
+
|
|
1600
|
+
Should be implemented in subclasses.
|
|
1601
|
+
|
|
1602
|
+
INPUT:
|
|
1603
|
+
|
|
1604
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1605
|
+
extension)
|
|
1606
|
+
|
|
1607
|
+
TESTS::
|
|
1608
|
+
|
|
1609
|
+
sage: K = GF(5^2).over() # over GF(5) # needs sage.rings.finite_rings
|
|
1610
|
+
sage: K.is_finite_over() # indirect doctest # needs sage.rings.finite_rings
|
|
1611
|
+
True
|
|
1612
|
+
"""
|
|
1613
|
+
raise NotImplementedError
|
|
1614
|
+
|
|
1615
|
+
def is_free_over(self, base=None):
|
|
1616
|
+
r"""
|
|
1617
|
+
Return ``True`` if this extension is free (as a module)
|
|
1618
|
+
over ``base``
|
|
1619
|
+
|
|
1620
|
+
INPUT:
|
|
1621
|
+
|
|
1622
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1623
|
+
extension) or ``None`` (default: ``None``)
|
|
1624
|
+
|
|
1625
|
+
EXAMPLES::
|
|
1626
|
+
|
|
1627
|
+
sage: # needs sage.rings.finite_rings
|
|
1628
|
+
sage: K = GF(5^2).over() # over GF(5)
|
|
1629
|
+
sage: L = GF(5^4).over(K)
|
|
1630
|
+
sage: L.is_free_over(K)
|
|
1631
|
+
True
|
|
1632
|
+
sage: L.is_free_over(GF(5))
|
|
1633
|
+
True
|
|
1634
|
+
|
|
1635
|
+
If ``base`` is omitted, it is set to its default which is the
|
|
1636
|
+
base of the extension::
|
|
1637
|
+
|
|
1638
|
+
sage: L.is_free_over() # needs sage.rings.finite_rings
|
|
1639
|
+
True
|
|
1640
|
+
"""
|
|
1641
|
+
cdef Parent b
|
|
1642
|
+
base = self._check_base(base)
|
|
1643
|
+
if base is self or base.is_field():
|
|
1644
|
+
return True
|
|
1645
|
+
try:
|
|
1646
|
+
return self._is_free_over(base)
|
|
1647
|
+
except NotImplementedError:
|
|
1648
|
+
pass
|
|
1649
|
+
b = self._base
|
|
1650
|
+
while b is not base:
|
|
1651
|
+
try:
|
|
1652
|
+
if self._is_free_over(b) and b.is_free_over(base):
|
|
1653
|
+
return True
|
|
1654
|
+
except NotImplementedError:
|
|
1655
|
+
pass
|
|
1656
|
+
b = (<RingExtension_generic?>b)._base
|
|
1657
|
+
raise NotImplementedError
|
|
1658
|
+
|
|
1659
|
+
cpdef _is_free_over(self, Parent base):
|
|
1660
|
+
r"""
|
|
1661
|
+
Return whether or not this extension is finite over ``base``.
|
|
1662
|
+
|
|
1663
|
+
Should be implemented in subclasses.
|
|
1664
|
+
|
|
1665
|
+
INPUT:
|
|
1666
|
+
|
|
1667
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
1668
|
+
extension)
|
|
1669
|
+
|
|
1670
|
+
TESTS::
|
|
1671
|
+
|
|
1672
|
+
sage: K = GF(5^2).over() # over GF(5) # needs sage.rings.finite_rings
|
|
1673
|
+
sage: K.is_free_over() # indirect doctest # needs sage.rings.finite_rings
|
|
1674
|
+
True
|
|
1675
|
+
"""
|
|
1676
|
+
raise NotImplementedError
|
|
1677
|
+
|
|
1678
|
+
def is_field(self, proof=True):
|
|
1679
|
+
r"""
|
|
1680
|
+
Return whether or not this extension is a field.
|
|
1681
|
+
|
|
1682
|
+
INPUT:
|
|
1683
|
+
|
|
1684
|
+
- ``proof`` -- boolean (default: ``False``)
|
|
1685
|
+
|
|
1686
|
+
EXAMPLES::
|
|
1687
|
+
|
|
1688
|
+
sage: K = GF(5^5).over() # over GF(5) # needs sage.rings.finite_rings
|
|
1689
|
+
sage: K.is_field() # needs sage.rings.finite_rings
|
|
1690
|
+
True
|
|
1691
|
+
|
|
1692
|
+
sage: S.<x> = QQ[]
|
|
1693
|
+
sage: A = S.over(QQ)
|
|
1694
|
+
sage: A.is_field()
|
|
1695
|
+
False
|
|
1696
|
+
|
|
1697
|
+
sage: B = A.fraction_field()
|
|
1698
|
+
sage: B.is_field()
|
|
1699
|
+
True
|
|
1700
|
+
"""
|
|
1701
|
+
return self._backend.is_field(proof=proof)
|
|
1702
|
+
|
|
1703
|
+
@cached_method
|
|
1704
|
+
def fraction_field(self, extend_base=False):
|
|
1705
|
+
r"""
|
|
1706
|
+
Return the fraction field of this extension.
|
|
1707
|
+
|
|
1708
|
+
INPUT:
|
|
1709
|
+
|
|
1710
|
+
- ``extend_base`` -- boolean (default: ``False``)
|
|
1711
|
+
|
|
1712
|
+
If ``extend_base`` is ``False``, the fraction field of the
|
|
1713
|
+
extension `L/K` is defined as `\textrm{Frac}(L)/L/K`, except
|
|
1714
|
+
if `L` is already a field in which base the fraction field
|
|
1715
|
+
of `L/K` is `L/K` itself.
|
|
1716
|
+
|
|
1717
|
+
If ``extend_base`` is ``True``, the fraction field of the
|
|
1718
|
+
extension `L/K` is defined as `\textrm{Frac}(L)/\textrm{Frac}(K)`
|
|
1719
|
+
(provided that the defining morphism extends to the fraction
|
|
1720
|
+
fields, i.e. is injective).
|
|
1721
|
+
|
|
1722
|
+
EXAMPLES::
|
|
1723
|
+
|
|
1724
|
+
sage: # needs sage.rings.number_field
|
|
1725
|
+
sage: x = polygen(ZZ, 'x')
|
|
1726
|
+
sage: A.<a> = ZZ.extension(x^2 - 5)
|
|
1727
|
+
sage: OK = A.over() # over ZZ
|
|
1728
|
+
sage: OK
|
|
1729
|
+
Order of conductor 2 generated by a in Number Field in a
|
|
1730
|
+
with defining polynomial x^2 - 5 over its base
|
|
1731
|
+
sage: K1 = OK.fraction_field(); K1
|
|
1732
|
+
Fraction Field of Order of conductor 2 generated by a
|
|
1733
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base
|
|
1734
|
+
sage: K1.bases()
|
|
1735
|
+
[Fraction Field of Order of conductor 2 generated by a
|
|
1736
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base,
|
|
1737
|
+
Order of conductor 2 generated by a in Number Field in a
|
|
1738
|
+
with defining polynomial x^2 - 5 over its base,
|
|
1739
|
+
Integer Ring]
|
|
1740
|
+
sage: K2 = OK.fraction_field(extend_base=True); K2
|
|
1741
|
+
Fraction Field of Order of conductor 2 generated by a
|
|
1742
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base
|
|
1743
|
+
sage: K2.bases()
|
|
1744
|
+
[Fraction Field of Order of conductor 2 generated by a
|
|
1745
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base,
|
|
1746
|
+
Rational Field]
|
|
1747
|
+
|
|
1748
|
+
Note that there is no coercion between `K_1` and `K_2`::
|
|
1749
|
+
|
|
1750
|
+
sage: K1.has_coerce_map_from(K2) # needs sage.rings.number_field
|
|
1751
|
+
False
|
|
1752
|
+
sage: K2.has_coerce_map_from(K1) # needs sage.rings.number_field
|
|
1753
|
+
False
|
|
1754
|
+
|
|
1755
|
+
We check that when the extension is a field, its fraction field does not change::
|
|
1756
|
+
|
|
1757
|
+
sage: K1.fraction_field() is K1 # needs sage.rings.number_field
|
|
1758
|
+
True
|
|
1759
|
+
sage: K2.fraction_field() is K2 # needs sage.rings.number_field
|
|
1760
|
+
True
|
|
1761
|
+
|
|
1762
|
+
TESTS::
|
|
1763
|
+
|
|
1764
|
+
sage: A = GF(5).over(ZZ)
|
|
1765
|
+
sage: A.fraction_field(extend_base=True)
|
|
1766
|
+
Traceback (most recent call last):
|
|
1767
|
+
...
|
|
1768
|
+
ValueError: the morphism is not injective
|
|
1769
|
+
"""
|
|
1770
|
+
defining_morphism = self._defining_morphism_fraction_field(extend_base)
|
|
1771
|
+
if defining_morphism is None:
|
|
1772
|
+
return self
|
|
1773
|
+
ring = defining_morphism.codomain()
|
|
1774
|
+
constructor = RingExtensionFractionField, {'ring': self, 'is_backend_exposed': self._is_backend_exposed}
|
|
1775
|
+
return RingExtension(ring, defining_morphism, constructors=[constructor])
|
|
1776
|
+
|
|
1777
|
+
cdef Map _defining_morphism_fraction_field(self, bint extend_base):
|
|
1778
|
+
r"""
|
|
1779
|
+
Return the defining morphism of the fraction field of this extension.
|
|
1780
|
+
|
|
1781
|
+
This is a helper function.
|
|
1782
|
+
|
|
1783
|
+
INPUT:
|
|
1784
|
+
|
|
1785
|
+
- ``extend_base`` -- boolean (default: ``False``); see
|
|
1786
|
+
:meth:`fraction_field` for more informations
|
|
1787
|
+
|
|
1788
|
+
TESTS::
|
|
1789
|
+
|
|
1790
|
+
sage: K = GF(5^2).over() # needs sage.rings.finite_rings
|
|
1791
|
+
sage: K.fraction_field() # indirect doctest # needs sage.rings.finite_rings
|
|
1792
|
+
Field in z2 with defining polynomial x^2 + 4*x + 2 over its base
|
|
1793
|
+
|
|
1794
|
+
sage: K = QQ.over(ZZ)
|
|
1795
|
+
sage: K.fraction_field(extend_base=True) # indirect doctest
|
|
1796
|
+
Rational Field over its base
|
|
1797
|
+
"""
|
|
1798
|
+
if extend_base:
|
|
1799
|
+
defining_morphism = backend_morphism(self._backend_defining_morphism)
|
|
1800
|
+
defining_morphism = defining_morphism.extend_to_fraction_field()
|
|
1801
|
+
if isinstance(self._base, RingExtension_generic):
|
|
1802
|
+
base = self._base.fraction_field(extend_base)
|
|
1803
|
+
ring = defining_morphism.codomain()
|
|
1804
|
+
defining_morphism = RingExtensionHomomorphism(base.Hom(ring), defining_morphism)
|
|
1805
|
+
else:
|
|
1806
|
+
if self.is_field():
|
|
1807
|
+
defining_morphism = None
|
|
1808
|
+
else:
|
|
1809
|
+
ring = self._backend.fraction_field()
|
|
1810
|
+
defining_morphism = RingExtensionHomomorphism(self.Hom(ring), ring.coerce_map_from(self._backend))
|
|
1811
|
+
return defining_morphism
|
|
1812
|
+
|
|
1813
|
+
def _Hom_(self, codomain, category):
|
|
1814
|
+
r"""
|
|
1815
|
+
Return the homset from this extension of ``codomain`` is the category ``category``.
|
|
1816
|
+
|
|
1817
|
+
INPUT:
|
|
1818
|
+
|
|
1819
|
+
- ``codomain`` -- a parent
|
|
1820
|
+
|
|
1821
|
+
- ``category`` -- a subcategory of the category of rings
|
|
1822
|
+
|
|
1823
|
+
EXAMPLES::
|
|
1824
|
+
|
|
1825
|
+
sage: # needs sage.rings.finite_rings
|
|
1826
|
+
sage: F = GF(5^2)
|
|
1827
|
+
sage: K = GF(5^4).over(F)
|
|
1828
|
+
sage: L = GF(5^12).over(F)
|
|
1829
|
+
sage: K.Hom(L) # indirect doctest
|
|
1830
|
+
Set of Homomorphisms
|
|
1831
|
+
from Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1832
|
+
to Field in z12 with defining polynomial x^6 + (4*z2 + 3)*x^5 + x^4
|
|
1833
|
+
+ (3*z2 + 1)*x^3 + x^2 + (4*z2 + 1)*x + z2 over its base
|
|
1834
|
+
sage: K.Hom(L, category=Sets())
|
|
1835
|
+
Set of Morphisms
|
|
1836
|
+
from Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
1837
|
+
to Field in z12 with defining polynomial x^6 + (4*z2 + 3)*x^5 + x^4
|
|
1838
|
+
+ (3*z2 + 1)*x^3 + x^2 + (4*z2 + 1)*x + z2 over its base
|
|
1839
|
+
in Category of sets
|
|
1840
|
+
"""
|
|
1841
|
+
from sage.rings.ring_extension_homset import RingExtensionHomset
|
|
1842
|
+
if category.is_subcategory(CommutativeRings()):
|
|
1843
|
+
return RingExtensionHomset(self, codomain, category)
|
|
1844
|
+
raise TypeError("category must be a subcategory of rings")
|
|
1845
|
+
|
|
1846
|
+
def hom(self, im_gens, codomain=None, base_map=None, category=None, check=True):
|
|
1847
|
+
r"""
|
|
1848
|
+
Return the unique homomorphism from this extension to
|
|
1849
|
+
``codomain`` that sends ``self.gens()`` to the entries
|
|
1850
|
+
of ``im_gens`` and induces the map ``base_map`` on the
|
|
1851
|
+
base ring.
|
|
1852
|
+
|
|
1853
|
+
INPUT:
|
|
1854
|
+
|
|
1855
|
+
- ``im_gens`` -- the images of the generators of this extension
|
|
1856
|
+
|
|
1857
|
+
- ``codomain`` -- the codomain of the homomorphism; if omitted, it
|
|
1858
|
+
is set to the smallest parent containing all the entries of ``im_gens``
|
|
1859
|
+
|
|
1860
|
+
- ``base_map`` -- a map from one of the bases of this extension into
|
|
1861
|
+
something that coerces into the codomain; if omitted, coercion maps
|
|
1862
|
+
are used
|
|
1863
|
+
|
|
1864
|
+
- ``category`` -- the category of the resulting morphism
|
|
1865
|
+
|
|
1866
|
+
- ``check`` -- boolean (default: ``True``); whether to verify that the
|
|
1867
|
+
images of generators extend to define a map (using only canonical coercions)
|
|
1868
|
+
|
|
1869
|
+
EXAMPLES::
|
|
1870
|
+
|
|
1871
|
+
sage: K.<a> = GF(5^2).over() # over GF(5) # needs sage.rings.finite_rings
|
|
1872
|
+
sage: L.<b> = GF(5^6).over(K) # needs sage.rings.finite_rings
|
|
1873
|
+
|
|
1874
|
+
We define (by hand) the relative Frobenius endomorphism of the extension `L/K`::
|
|
1875
|
+
|
|
1876
|
+
sage: L.hom([b^25]) # needs sage.rings.finite_rings
|
|
1877
|
+
Ring endomorphism of
|
|
1878
|
+
Field in b with defining polynomial x^3 + (2 + 2*a)*x - a over its base
|
|
1879
|
+
Defn: b |--> 2 + 2*a*b + (2 - a)*b^2
|
|
1880
|
+
|
|
1881
|
+
Defining the absolute Frobenius of `L` is a bit more complicated
|
|
1882
|
+
because it is not a homomorphism of `K`-algebras.
|
|
1883
|
+
For this reason, the construction ``L.hom([b^5])`` fails::
|
|
1884
|
+
|
|
1885
|
+
sage: L.hom([b^5]) # needs sage.rings.finite_rings
|
|
1886
|
+
Traceback (most recent call last):
|
|
1887
|
+
...
|
|
1888
|
+
ValueError: images do not define a valid homomorphism
|
|
1889
|
+
|
|
1890
|
+
What we need is to specify a base map::
|
|
1891
|
+
|
|
1892
|
+
sage: FrobK = K.hom([a^5]) # needs sage.rings.finite_rings
|
|
1893
|
+
sage: FrobL = L.hom([b^5], base_map=FrobK); FrobL # needs sage.rings.finite_rings
|
|
1894
|
+
Ring endomorphism of
|
|
1895
|
+
Field in b with defining polynomial x^3 + (2 + 2*a)*x - a over its base
|
|
1896
|
+
Defn: b |--> (-1 + a) + (1 + 2*a)*b + a*b^2
|
|
1897
|
+
with map on base ring:
|
|
1898
|
+
a |--> 1 - a
|
|
1899
|
+
|
|
1900
|
+
As a shortcut, we may use the following construction::
|
|
1901
|
+
|
|
1902
|
+
sage: phi = L.hom([b^5, a^5]); phi # needs sage.rings.finite_rings
|
|
1903
|
+
Ring endomorphism of
|
|
1904
|
+
Field in b with defining polynomial x^3 + (2 + 2*a)*x - a over its base
|
|
1905
|
+
Defn: b |--> (-1 + a) + (1 + 2*a)*b + a*b^2
|
|
1906
|
+
with map on base ring:
|
|
1907
|
+
a |--> 1 - a
|
|
1908
|
+
sage: phi == FrobL # needs sage.rings.finite_rings
|
|
1909
|
+
True
|
|
1910
|
+
"""
|
|
1911
|
+
if codomain is None:
|
|
1912
|
+
from sage.structure.sequence import Sequence
|
|
1913
|
+
codomain = Sequence(im_gens).universe()
|
|
1914
|
+
parent = self.Hom(codomain, category=category)
|
|
1915
|
+
return RingExtensionHomomorphism(parent, im_gens, base_map, check)
|
|
1916
|
+
|
|
1917
|
+
def characteristic(self):
|
|
1918
|
+
r"""
|
|
1919
|
+
Return the characteristic of the extension as a ring.
|
|
1920
|
+
|
|
1921
|
+
OUTPUT: a prime number or zero
|
|
1922
|
+
|
|
1923
|
+
EXAMPLES::
|
|
1924
|
+
|
|
1925
|
+
sage: # needs sage.rings.finite_rings
|
|
1926
|
+
sage: F = GF(5^2).over() # over GF(5)
|
|
1927
|
+
sage: K = GF(5^4).over(F)
|
|
1928
|
+
sage: L = GF(5^12).over(K)
|
|
1929
|
+
sage: F.characteristic()
|
|
1930
|
+
5
|
|
1931
|
+
sage: K.characteristic()
|
|
1932
|
+
5
|
|
1933
|
+
sage: L.characteristic()
|
|
1934
|
+
5
|
|
1935
|
+
|
|
1936
|
+
::
|
|
1937
|
+
|
|
1938
|
+
sage: F = RR.over(ZZ)
|
|
1939
|
+
sage: F.characteristic()
|
|
1940
|
+
0
|
|
1941
|
+
|
|
1942
|
+
::
|
|
1943
|
+
|
|
1944
|
+
sage: F = GF(11)
|
|
1945
|
+
sage: A.<x> = F[]
|
|
1946
|
+
sage: K = Frac(F).over(F)
|
|
1947
|
+
sage: K.characteristic()
|
|
1948
|
+
11
|
|
1949
|
+
|
|
1950
|
+
::
|
|
1951
|
+
|
|
1952
|
+
sage: E = GF(7).over(ZZ)
|
|
1953
|
+
sage: E.characteristic()
|
|
1954
|
+
7
|
|
1955
|
+
|
|
1956
|
+
TESTS:
|
|
1957
|
+
|
|
1958
|
+
Ensure issue :issue:`34692` is fixed::
|
|
1959
|
+
|
|
1960
|
+
sage: Fq = GF(11)
|
|
1961
|
+
sage: FqX.<X> = Fq[]
|
|
1962
|
+
sage: k = Frac(FqX)
|
|
1963
|
+
sage: K = k.over(FqX)
|
|
1964
|
+
sage: K.frobenius_endomorphism()
|
|
1965
|
+
Frobenius endomorphism x |--> x^11 of
|
|
1966
|
+
Fraction Field of Univariate Polynomial Ring in X over
|
|
1967
|
+
Finite Field of size 11 over its base
|
|
1968
|
+
"""
|
|
1969
|
+
return self._backend.characteristic()
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
# Fraction fields
|
|
1973
|
+
#################
|
|
1974
|
+
|
|
1975
|
+
cdef class RingExtensionFractionField(RingExtension_generic):
|
|
1976
|
+
"""
|
|
1977
|
+
A class for ring extensions of the form `\textrm{Frac}(A)/A`.
|
|
1978
|
+
|
|
1979
|
+
TESTS::
|
|
1980
|
+
|
|
1981
|
+
sage: Z = ZZ.over() # over ZZ itself
|
|
1982
|
+
sage: Q = Z.fraction_field()
|
|
1983
|
+
sage: Q
|
|
1984
|
+
Fraction Field of Integer Ring over its base
|
|
1985
|
+
|
|
1986
|
+
sage: type(Q)
|
|
1987
|
+
<class 'sage.rings.ring_extension.RingExtensionFractionField'>
|
|
1988
|
+
|
|
1989
|
+
sage: TestSuite(Q).run()
|
|
1990
|
+
"""
|
|
1991
|
+
Element = RingExtensionFractionFieldElement
|
|
1992
|
+
|
|
1993
|
+
def __init__(self, defining_morphism, ring=None, **kwargs):
|
|
1994
|
+
r"""
|
|
1995
|
+
Initialize this ring extension.
|
|
1996
|
+
|
|
1997
|
+
INPUT:
|
|
1998
|
+
|
|
1999
|
+
- ``defining_morphism`` -- a ring homomorphism
|
|
2000
|
+
|
|
2001
|
+
- ``ring`` -- the commutative ring whose fraction field is this
|
|
2002
|
+
extension
|
|
2003
|
+
|
|
2004
|
+
TESTS::
|
|
2005
|
+
|
|
2006
|
+
sage: # needs sage.rings.number_field
|
|
2007
|
+
sage: x = polygen(ZZ, 'x')
|
|
2008
|
+
sage: A.<a> = ZZ.extension(x^2 - 2)
|
|
2009
|
+
sage: OK = A.over()
|
|
2010
|
+
sage: K = OK.fraction_field(); K
|
|
2011
|
+
Fraction Field of
|
|
2012
|
+
Maximal Order generated by a in Number Field in a
|
|
2013
|
+
with defining polynomial x^2 - 2 over its base
|
|
2014
|
+
sage: TestSuite(K).run()
|
|
2015
|
+
"""
|
|
2016
|
+
RingExtension_generic.__init__(self, defining_morphism, **kwargs)
|
|
2017
|
+
if ring is None:
|
|
2018
|
+
self._ring = self._base
|
|
2019
|
+
else:
|
|
2020
|
+
self._ring = ring
|
|
2021
|
+
|
|
2022
|
+
def ring(self):
|
|
2023
|
+
r"""
|
|
2024
|
+
Return the ring whose fraction field is this extension.
|
|
2025
|
+
|
|
2026
|
+
EXAMPLES::
|
|
2027
|
+
|
|
2028
|
+
sage: # needs sage.rings.number_field
|
|
2029
|
+
sage: x = polygen(ZZ, 'x')
|
|
2030
|
+
sage: A.<a> = ZZ.extension(x^2 - 2)
|
|
2031
|
+
sage: OK = A.over()
|
|
2032
|
+
sage: K = OK.fraction_field(); K
|
|
2033
|
+
Fraction Field of
|
|
2034
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^2 - 2 over its base
|
|
2035
|
+
sage: K.ring()
|
|
2036
|
+
Maximal Order generated by a in Number Field in a with defining polynomial x^2 - 2 over its base
|
|
2037
|
+
sage: K.ring() is OK
|
|
2038
|
+
True
|
|
2039
|
+
"""
|
|
2040
|
+
return self._ring
|
|
2041
|
+
|
|
2042
|
+
def _repr_topring(self, **options):
|
|
2043
|
+
r"""
|
|
2044
|
+
Return a string representation of top ring of this extension.
|
|
2045
|
+
|
|
2046
|
+
EXAMPLES::
|
|
2047
|
+
|
|
2048
|
+
sage: # needs sage.rings.number_field
|
|
2049
|
+
sage: x = polygen(ZZ, 'x')
|
|
2050
|
+
sage: A.<a> = ZZ.extension(x^2 - 2)
|
|
2051
|
+
sage: OK = A.over()
|
|
2052
|
+
sage: K = OK.fraction_field()
|
|
2053
|
+
sage: K._repr_topring()
|
|
2054
|
+
'Fraction Field of Maximal Order generated by a in Number Field in a with defining polynomial x^2 - 2'
|
|
2055
|
+
"""
|
|
2056
|
+
if isinstance(self._ring, RingExtension_generic):
|
|
2057
|
+
sr = self._ring._repr_topring(**options)
|
|
2058
|
+
else:
|
|
2059
|
+
sr = str(self._ring)
|
|
2060
|
+
if self._ring in Fields():
|
|
2061
|
+
return sr
|
|
2062
|
+
else:
|
|
2063
|
+
return "Fraction Field of %s" % sr
|
|
2064
|
+
|
|
2065
|
+
def _latex_topring(self, **options):
|
|
2066
|
+
r"""
|
|
2067
|
+
Return a LaTeX representation of top ring of this extension.
|
|
2068
|
+
|
|
2069
|
+
EXAMPLES::
|
|
2070
|
+
|
|
2071
|
+
sage: Z = ZZ.over()
|
|
2072
|
+
sage: Q = Z.fraction_field()
|
|
2073
|
+
|
|
2074
|
+
sage: Q._latex_topring()
|
|
2075
|
+
'\\mathrm{Frac}(\\Bold{Z})'
|
|
2076
|
+
"""
|
|
2077
|
+
if self._ring in Fields():
|
|
2078
|
+
return self._ring._latex_topring(**options)
|
|
2079
|
+
else:
|
|
2080
|
+
return "\\mathrm{Frac}(%s)" % latex(self._ring)
|
|
2081
|
+
|
|
2082
|
+
|
|
2083
|
+
# Finite free extensions
|
|
2084
|
+
########################
|
|
2085
|
+
|
|
2086
|
+
cdef class RingExtensionWithBasis(RingExtension_generic):
|
|
2087
|
+
"""
|
|
2088
|
+
A class for finite free ring extensions equipped
|
|
2089
|
+
with a basis.
|
|
2090
|
+
|
|
2091
|
+
TESTS::
|
|
2092
|
+
|
|
2093
|
+
sage: E = GF(5^4).over(GF(5^2)); E # needs sage.rings.finite_rings
|
|
2094
|
+
Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
|
|
2095
|
+
|
|
2096
|
+
sage: TestSuite(E).run() # needs sage.rings.finite_rings
|
|
2097
|
+
"""
|
|
2098
|
+
Element = RingExtensionWithBasisElement
|
|
2099
|
+
|
|
2100
|
+
def __init__(self, defining_morphism, basis, names=None, check=True, **kwargs):
|
|
2101
|
+
r"""
|
|
2102
|
+
Initialize this ring extension.
|
|
2103
|
+
|
|
2104
|
+
INPUT:
|
|
2105
|
+
|
|
2106
|
+
- ``defining_morphism`` -- a ring homomorphism
|
|
2107
|
+
|
|
2108
|
+
- ``basis`` -- tuple of elements in this extension
|
|
2109
|
+
|
|
2110
|
+
- ``names`` -- tuple of strings or ``None`` (default: ``None``);
|
|
2111
|
+
the way the elements of the basis are printed
|
|
2112
|
+
|
|
2113
|
+
- ``check`` -- boolean (default: ``True``); whether to check if
|
|
2114
|
+
``basis`` is indeed a basis
|
|
2115
|
+
|
|
2116
|
+
TESTS::
|
|
2117
|
+
|
|
2118
|
+
sage: x = polygen(ZZ, 'x')
|
|
2119
|
+
sage: K.<a> = QQ.extension(x^3 - 2) # needs sage.rings.number_field
|
|
2120
|
+
sage: E = K.over(); E # needs sage.rings.number_field
|
|
2121
|
+
Field in a with defining polynomial x^3 - 2 over its base
|
|
2122
|
+
|
|
2123
|
+
sage: TestSuite(E).run() # needs sage.rings.number_field
|
|
2124
|
+
"""
|
|
2125
|
+
RingExtension_generic.__init__(self, defining_morphism, **kwargs)
|
|
2126
|
+
self._basis = [self(b) for b in basis]
|
|
2127
|
+
if names is None:
|
|
2128
|
+
names = []
|
|
2129
|
+
for b in self._basis:
|
|
2130
|
+
b = b._backend
|
|
2131
|
+
if b == 1:
|
|
2132
|
+
names.append("")
|
|
2133
|
+
sb = str(b)
|
|
2134
|
+
if b._is_atomic() or (sb[0] == "(" and sb[-1] == ")"):
|
|
2135
|
+
names.append(sb)
|
|
2136
|
+
else:
|
|
2137
|
+
names.append("(" + sb + ")")
|
|
2138
|
+
else:
|
|
2139
|
+
if len(names) != len(self._basis):
|
|
2140
|
+
raise ValueError("the number of names does not match the cardinality of the basis")
|
|
2141
|
+
self._basis_names = names
|
|
2142
|
+
self._basis_latex_names = [latex_variable_name(name) for name in names]
|
|
2143
|
+
self._names = tuple(names)
|
|
2144
|
+
if check:
|
|
2145
|
+
try:
|
|
2146
|
+
_ = self.free_module(map=True)
|
|
2147
|
+
except (ZeroDivisionError, ArithmeticError):
|
|
2148
|
+
raise ValueError("the given family is not a basis")
|
|
2149
|
+
if 'base' not in self._print_options:
|
|
2150
|
+
self._print_options['base'] = self._base
|
|
2151
|
+
|
|
2152
|
+
def _print_option_base(self, base):
|
|
2153
|
+
r"""
|
|
2154
|
+
Return a normalized form of the print option ``base``.
|
|
2155
|
+
|
|
2156
|
+
INPUT:
|
|
2157
|
+
|
|
2158
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2159
|
+
extension) or ``None`` (default: ``None``)
|
|
2160
|
+
|
|
2161
|
+
TESTS::
|
|
2162
|
+
|
|
2163
|
+
sage: # needs sage.rings.finite_rings
|
|
2164
|
+
sage: F = GF(5)
|
|
2165
|
+
sage: K = GF(5^2).over(F)
|
|
2166
|
+
sage: L = GF(5^4).over(K)
|
|
2167
|
+
sage: L._print_option_base(F) is F
|
|
2168
|
+
True
|
|
2169
|
+
sage: L._print_option_base(K) is K
|
|
2170
|
+
True
|
|
2171
|
+
sage: L._print_option_base(GF(5^2)) is K
|
|
2172
|
+
True
|
|
2173
|
+
sage: L._print_option_base(None) is K
|
|
2174
|
+
True
|
|
2175
|
+
sage: L._print_option_base(L)
|
|
2176
|
+
Traceback (most recent call last):
|
|
2177
|
+
...
|
|
2178
|
+
ValueError: base must be strict
|
|
2179
|
+
sage: K._print_option_base(L)
|
|
2180
|
+
Traceback (most recent call last):
|
|
2181
|
+
...
|
|
2182
|
+
ValueError: not (explicitly) defined over Field in z4
|
|
2183
|
+
with defining polynomial x^2 + (3 - z2)*x + z2 over its base
|
|
2184
|
+
"""
|
|
2185
|
+
if 'print_elements_as' in self._print_options:
|
|
2186
|
+
raise NotImplementedError("printing is handled by an external function or another parent")
|
|
2187
|
+
base = self._check_base(base)
|
|
2188
|
+
if base is self:
|
|
2189
|
+
raise ValueError("base must be strict")
|
|
2190
|
+
b = self._base
|
|
2191
|
+
while b is not base:
|
|
2192
|
+
if not isinstance(b, RingExtensionWithBasis):
|
|
2193
|
+
raise NotImplementedError
|
|
2194
|
+
b = b.base_ring()
|
|
2195
|
+
return base
|
|
2196
|
+
|
|
2197
|
+
cpdef _degree_over(self, Parent base):
|
|
2198
|
+
r"""
|
|
2199
|
+
Return the degree of this extension over ``base``.
|
|
2200
|
+
|
|
2201
|
+
INPUT:
|
|
2202
|
+
|
|
2203
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2204
|
+
extension) or ``None`` (default: ``None``)
|
|
2205
|
+
|
|
2206
|
+
TESTS::
|
|
2207
|
+
|
|
2208
|
+
sage: # needs sage.rings.number_field
|
|
2209
|
+
sage: x = polygen(ZZ, 'x')
|
|
2210
|
+
sage: A.<a> = QQ.extension(x^2 - 2)
|
|
2211
|
+
sage: B.<b> = QQ.extension(x^6 - 2)
|
|
2212
|
+
sage: f = A.hom([b^3])
|
|
2213
|
+
sage: E = B.over(f)
|
|
2214
|
+
sage: E.degree_over() # indirect doctest
|
|
2215
|
+
3
|
|
2216
|
+
"""
|
|
2217
|
+
if base is self:
|
|
2218
|
+
return ZZ(1)
|
|
2219
|
+
elif base is self._base:
|
|
2220
|
+
return len(self._basis)
|
|
2221
|
+
else:
|
|
2222
|
+
return len(self._basis) * self._base._degree_over(base)
|
|
2223
|
+
|
|
2224
|
+
cpdef _is_finite_over(self, Parent base):
|
|
2225
|
+
r"""
|
|
2226
|
+
Return whether or not this extension is finite over ``base``.
|
|
2227
|
+
|
|
2228
|
+
INPUT:
|
|
2229
|
+
|
|
2230
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2231
|
+
extension)
|
|
2232
|
+
|
|
2233
|
+
TESTS::
|
|
2234
|
+
|
|
2235
|
+
sage: K = GF(5^2).over() # over GF(5) # needs sage.rings.finite_rings
|
|
2236
|
+
sage: K.is_finite_over() # indirect doctest # needs sage.rings.finite_rings
|
|
2237
|
+
True
|
|
2238
|
+
"""
|
|
2239
|
+
if base is self or base is self._base:
|
|
2240
|
+
return True
|
|
2241
|
+
return self._base._is_finite_over(base)
|
|
2242
|
+
|
|
2243
|
+
cpdef _is_free_over(self, Parent base):
|
|
2244
|
+
r"""
|
|
2245
|
+
Return whether or not this extension is free over ``base``.
|
|
2246
|
+
|
|
2247
|
+
INPUT:
|
|
2248
|
+
|
|
2249
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2250
|
+
extension)
|
|
2251
|
+
|
|
2252
|
+
TESTS::
|
|
2253
|
+
|
|
2254
|
+
sage: K = GF(5^2).over() # over GF(5) # needs sage.rings.finite_rings
|
|
2255
|
+
sage: K.is_free_over() # indirect doctest # needs sage.rings.finite_rings
|
|
2256
|
+
True
|
|
2257
|
+
"""
|
|
2258
|
+
if base is self or base is self._base:
|
|
2259
|
+
return True
|
|
2260
|
+
return self._base._is_free_over(base)
|
|
2261
|
+
|
|
2262
|
+
def basis_over(self, base=None):
|
|
2263
|
+
r"""
|
|
2264
|
+
Return a basis of this extension over ``base``.
|
|
2265
|
+
|
|
2266
|
+
INPUT:
|
|
2267
|
+
|
|
2268
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2269
|
+
extension)
|
|
2270
|
+
|
|
2271
|
+
EXAMPLES::
|
|
2272
|
+
|
|
2273
|
+
sage: # needs sage.rings.finite_rings
|
|
2274
|
+
sage: F.<a> = GF(5^2).over() # over GF(5)
|
|
2275
|
+
sage: K.<b> = GF(5^4).over(F)
|
|
2276
|
+
sage: L.<c> = GF(5^12).over(K)
|
|
2277
|
+
sage: L.basis_over(K)
|
|
2278
|
+
[1, c, c^2]
|
|
2279
|
+
sage: L.basis_over(F)
|
|
2280
|
+
[1, b, c, b*c, c^2, b*c^2]
|
|
2281
|
+
sage: L.basis_over(GF(5))
|
|
2282
|
+
[1, a, b, a*b, c, a*c, b*c, a*b*c, c^2, a*c^2, b*c^2, a*b*c^2]
|
|
2283
|
+
|
|
2284
|
+
If ``base`` is omitted, it is set to its default which is the
|
|
2285
|
+
base of the extension::
|
|
2286
|
+
|
|
2287
|
+
sage: L.basis_over() # needs sage.rings.finite_rings
|
|
2288
|
+
[1, c, c^2]
|
|
2289
|
+
|
|
2290
|
+
sage: K.basis_over() # needs sage.rings.finite_rings
|
|
2291
|
+
[1, b]
|
|
2292
|
+
|
|
2293
|
+
Note that ``base`` must be an explicit base over which the
|
|
2294
|
+
extension has been defined (as listed by the method :meth:`bases`)::
|
|
2295
|
+
|
|
2296
|
+
sage: L.degree_over(GF(5^6)) # needs sage.rings.finite_rings
|
|
2297
|
+
Traceback (most recent call last):
|
|
2298
|
+
...
|
|
2299
|
+
ValueError: not (explicitly) defined over Finite Field in z6 of size 5^6
|
|
2300
|
+
"""
|
|
2301
|
+
base = self._check_base(base)
|
|
2302
|
+
return self._basis_over(base)
|
|
2303
|
+
|
|
2304
|
+
cpdef _basis_over(self, Parent base):
|
|
2305
|
+
r"""
|
|
2306
|
+
Return a basis of this extension over ``base``.
|
|
2307
|
+
|
|
2308
|
+
INPUT:
|
|
2309
|
+
|
|
2310
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2311
|
+
extension)
|
|
2312
|
+
|
|
2313
|
+
TESTS::
|
|
2314
|
+
|
|
2315
|
+
sage: x = polygen(ZZ, 'x')
|
|
2316
|
+
sage: A.<a> = QQ.extension(x^3 - 2) # needs sage.rings.number_field
|
|
2317
|
+
sage: K.<u> = A.over() # needs sage.rings.number_field
|
|
2318
|
+
sage: K.basis_over() # needs sage.rings.number_field
|
|
2319
|
+
[1, u, u^2]
|
|
2320
|
+
"""
|
|
2321
|
+
if base is self:
|
|
2322
|
+
return [self.one()]
|
|
2323
|
+
if base is self._base:
|
|
2324
|
+
return self._basis[:]
|
|
2325
|
+
b = self._base._basis_over(base)
|
|
2326
|
+
return [x * y for x in self._basis for y in b]
|
|
2327
|
+
|
|
2328
|
+
def free_module(self, base=None, map=True):
|
|
2329
|
+
r"""
|
|
2330
|
+
Return a free module V over ``base`` which is isomorphic to
|
|
2331
|
+
this ring
|
|
2332
|
+
|
|
2333
|
+
INPUT:
|
|
2334
|
+
|
|
2335
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2336
|
+
extension) or ``None`` (default: ``None``)
|
|
2337
|
+
|
|
2338
|
+
- ``map`` -- boolean (default: ``True``); whether to return
|
|
2339
|
+
isomorphisms between this ring and V
|
|
2340
|
+
|
|
2341
|
+
OUTPUT:
|
|
2342
|
+
|
|
2343
|
+
- A finite-rank free module V over ``base``
|
|
2344
|
+
|
|
2345
|
+
- The isomorphism from V to this ring corresponding to the
|
|
2346
|
+
basis output by the method :meth:`basis_over`
|
|
2347
|
+
(only included if ``map`` is ``True``)
|
|
2348
|
+
|
|
2349
|
+
- The reverse isomorphism of the isomorphism above
|
|
2350
|
+
(only included if ``map`` is ``True``)
|
|
2351
|
+
|
|
2352
|
+
EXAMPLES::
|
|
2353
|
+
|
|
2354
|
+
sage: F = GF(11)
|
|
2355
|
+
sage: K.<a> = GF(11^2).over() # needs sage.rings.finite_rings
|
|
2356
|
+
sage: L.<b> = GF(11^6).over(K) # needs sage.rings.finite_rings
|
|
2357
|
+
|
|
2358
|
+
Forgetting a part of the multiplicative structure, the field L
|
|
2359
|
+
can be viewed as a vector space of dimension 3 over K, equipped
|
|
2360
|
+
with a distinguished basis, namely `(1, b, b^2)`::
|
|
2361
|
+
|
|
2362
|
+
sage: # needs sage.rings.finite_rings
|
|
2363
|
+
sage: V, i, j = L.free_module(K)
|
|
2364
|
+
sage: V
|
|
2365
|
+
Vector space of dimension 3 over
|
|
2366
|
+
Field in a with defining polynomial x^2 + 7*x + 2 over its base
|
|
2367
|
+
sage: i
|
|
2368
|
+
Generic map:
|
|
2369
|
+
From: Vector space of dimension 3 over
|
|
2370
|
+
Field in a with defining polynomial x^2 + 7*x + 2 over its base
|
|
2371
|
+
To: Field in b with defining polynomial
|
|
2372
|
+
x^3 + (7 + 2*a)*x^2 + (2 - a)*x - a over its base
|
|
2373
|
+
sage: j
|
|
2374
|
+
Generic map:
|
|
2375
|
+
From: Field in b with defining polynomial
|
|
2376
|
+
x^3 + (7 + 2*a)*x^2 + (2 - a)*x - a over its base
|
|
2377
|
+
To: Vector space of dimension 3 over
|
|
2378
|
+
Field in a with defining polynomial x^2 + 7*x + 2 over its base
|
|
2379
|
+
sage: j(b)
|
|
2380
|
+
(0, 1, 0)
|
|
2381
|
+
sage: i((1, a, a+1))
|
|
2382
|
+
1 + a*b + (1 + a)*b^2
|
|
2383
|
+
|
|
2384
|
+
Similarly, one can view L as a F-vector space of dimension 6::
|
|
2385
|
+
|
|
2386
|
+
sage: V, i, j, = L.free_module(F) # needs sage.rings.finite_rings
|
|
2387
|
+
sage: V # needs sage.rings.finite_rings
|
|
2388
|
+
Vector space of dimension 6 over Finite Field of size 11
|
|
2389
|
+
|
|
2390
|
+
In this case, the isomorphisms between `V` and `L` are given by the
|
|
2391
|
+
basis `(1, a, b, ab, b^2, ab^2)`:
|
|
2392
|
+
|
|
2393
|
+
sage: j(a*b) # needs sage.rings.finite_rings
|
|
2394
|
+
(0, 0, 0, 1, 0, 0)
|
|
2395
|
+
sage: i((1,2,3,4,5,6)) # needs sage.rings.finite_rings
|
|
2396
|
+
(1 + 2*a) + (3 + 4*a)*b + (5 + 6*a)*b^2
|
|
2397
|
+
|
|
2398
|
+
When ``base`` is omitted, the default is the base of this extension::
|
|
2399
|
+
|
|
2400
|
+
sage: L.free_module(map=False) # needs sage.rings.finite_rings
|
|
2401
|
+
Vector space of dimension 3 over
|
|
2402
|
+
Field in a with defining polynomial x^2 + 7*x + 2 over its base
|
|
2403
|
+
|
|
2404
|
+
Note that ``base`` must be an explicit base over which the
|
|
2405
|
+
extension has been defined (as listed by the method :meth:`bases`)::
|
|
2406
|
+
|
|
2407
|
+
sage: L.degree(GF(11^3)) # needs sage.rings.finite_rings
|
|
2408
|
+
Traceback (most recent call last):
|
|
2409
|
+
...
|
|
2410
|
+
ValueError: not (explicitly) defined over Finite Field in z3 of size 11^3
|
|
2411
|
+
"""
|
|
2412
|
+
base = self._check_base(base)
|
|
2413
|
+
return self._free_module(base, map)
|
|
2414
|
+
|
|
2415
|
+
@cached_method
|
|
2416
|
+
def _free_module(self, base, map):
|
|
2417
|
+
r"""
|
|
2418
|
+
Return a free module V over ``base`` which is isomorphic to
|
|
2419
|
+
this ring
|
|
2420
|
+
|
|
2421
|
+
INPUT:
|
|
2422
|
+
|
|
2423
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2424
|
+
extension) or ``None`` (default: ``None``)
|
|
2425
|
+
|
|
2426
|
+
- ``map`` -- boolean (default: ``True``); whether to return
|
|
2427
|
+
isomorphisms between this ring and V
|
|
2428
|
+
|
|
2429
|
+
OUTPUT:
|
|
2430
|
+
|
|
2431
|
+
- A finite-rank free module V over ``base``
|
|
2432
|
+
|
|
2433
|
+
- The isomorphism from V to this ring corresponding to the
|
|
2434
|
+
basis output by the method :meth:`basis_over`
|
|
2435
|
+
(only included if ``map`` is ``True``)
|
|
2436
|
+
|
|
2437
|
+
- The reverse isomorphism of the isomorphism above
|
|
2438
|
+
(only included if ``map`` is ``True``)
|
|
2439
|
+
|
|
2440
|
+
TESTS::
|
|
2441
|
+
|
|
2442
|
+
sage: K = GF(7^5).over() # needs sage.rings.finite_rings
|
|
2443
|
+
sage: L = GF(7^15).over(K) # needs sage.rings.finite_rings
|
|
2444
|
+
sage: for base in L.bases(): # needs sage.rings.finite_rings
|
|
2445
|
+
....: V, i, j = L.free_module(base)
|
|
2446
|
+
....: assert([i(v) for v in V.basis()] == L.basis_over(base))
|
|
2447
|
+
....: assert([j(x) for x in L.basis_over(base)] == V.basis())
|
|
2448
|
+
"""
|
|
2449
|
+
d = self._degree_over(base)
|
|
2450
|
+
if map:
|
|
2451
|
+
return base**d, MapFreeModuleToRelativeRing(self, base), MapRelativeRingToFreeModule(self, base)
|
|
2452
|
+
else:
|
|
2453
|
+
return base**d
|
|
2454
|
+
|
|
2455
|
+
@cached_method
|
|
2456
|
+
def fraction_field(self, extend_base=False):
|
|
2457
|
+
r"""
|
|
2458
|
+
Return the fraction field of this extension.
|
|
2459
|
+
|
|
2460
|
+
INPUT:
|
|
2461
|
+
|
|
2462
|
+
- ``extend_base`` -- boolean (default: ``False``)
|
|
2463
|
+
|
|
2464
|
+
If ``extend_base`` is ``False``, the fraction field of the
|
|
2465
|
+
extension `L/K` is defined as `\textrm{Frac}(L)/L/K`, except
|
|
2466
|
+
is `L` is already a field in which base the fraction field
|
|
2467
|
+
of `L/K` is `L/K` itself.
|
|
2468
|
+
|
|
2469
|
+
If ``extend_base`` is ``True``, the fraction field of the
|
|
2470
|
+
extension `L/K` is defined as `\textrm{Frac}(L)/\textrm{Frac}(K)`
|
|
2471
|
+
(provided that the defining morphism extends to the fraction
|
|
2472
|
+
fields, i.e. is injective).
|
|
2473
|
+
|
|
2474
|
+
EXAMPLES::
|
|
2475
|
+
|
|
2476
|
+
sage: # needs sage.rings.number_field
|
|
2477
|
+
sage: x = polygen(ZZ, 'x')
|
|
2478
|
+
sage: A.<a> = ZZ.extension(x^2 - 5)
|
|
2479
|
+
sage: OK = A.over() # over ZZ
|
|
2480
|
+
sage: OK
|
|
2481
|
+
Order of conductor 2 generated by a in Number Field in a with defining polynomial x^2 - 5 over its base
|
|
2482
|
+
sage: K1 = OK.fraction_field(); K1
|
|
2483
|
+
Fraction Field of Order of conductor 2 generated by a in Number Field in a
|
|
2484
|
+
with defining polynomial x^2 - 5 over its base
|
|
2485
|
+
sage: K1.bases()
|
|
2486
|
+
[Fraction Field of Order of conductor 2 generated by a in Number Field in a
|
|
2487
|
+
with defining polynomial x^2 - 5 over its base,
|
|
2488
|
+
Order of conductor 2 generated by a in Number Field in a
|
|
2489
|
+
with defining polynomial x^2 - 5 over its base,
|
|
2490
|
+
Integer Ring]
|
|
2491
|
+
sage: K2 = OK.fraction_field(extend_base=True); K2
|
|
2492
|
+
Fraction Field of Order of conductor 2 generated by a
|
|
2493
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base
|
|
2494
|
+
sage: K2.bases()
|
|
2495
|
+
[Fraction Field of Order of conductor 2 generated by a
|
|
2496
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base,
|
|
2497
|
+
Rational Field]
|
|
2498
|
+
|
|
2499
|
+
Note that there is no coercion map between `K_1` and `K_2`::
|
|
2500
|
+
|
|
2501
|
+
sage: K1.has_coerce_map_from(K2) # needs sage.rings.number_field
|
|
2502
|
+
False
|
|
2503
|
+
sage: K2.has_coerce_map_from(K1) # needs sage.rings.number_field
|
|
2504
|
+
False
|
|
2505
|
+
|
|
2506
|
+
We check that when the extension is a field, its fraction field does not change::
|
|
2507
|
+
|
|
2508
|
+
sage: K1.fraction_field() is K1 # needs sage.rings.number_field
|
|
2509
|
+
True
|
|
2510
|
+
sage: K2.fraction_field() is K2 # needs sage.rings.number_field
|
|
2511
|
+
True
|
|
2512
|
+
|
|
2513
|
+
TESTS::
|
|
2514
|
+
|
|
2515
|
+
sage: A = GF(5).over(ZZ)
|
|
2516
|
+
sage: A.fraction_field(extend_base=True)
|
|
2517
|
+
Traceback (most recent call last):
|
|
2518
|
+
...
|
|
2519
|
+
ValueError: the morphism is not injective
|
|
2520
|
+
"""
|
|
2521
|
+
defining_morphism = self._defining_morphism_fraction_field(extend_base)
|
|
2522
|
+
if defining_morphism is None:
|
|
2523
|
+
return self
|
|
2524
|
+
if extend_base:
|
|
2525
|
+
basis = self._basis
|
|
2526
|
+
names = self._basis_names
|
|
2527
|
+
constructor = RingExtensionWithBasis
|
|
2528
|
+
kwargs = { 'basis': basis, 'names': names, 'check': False }
|
|
2529
|
+
else:
|
|
2530
|
+
gen = names = None
|
|
2531
|
+
constructor = RingExtensionFractionField
|
|
2532
|
+
kwargs = { 'print_options': {'print_elements_as': self.fraction_field(extend_base=True)} }
|
|
2533
|
+
kwargs['is_backend_exposed'] = self._is_backend_exposed
|
|
2534
|
+
ring = defining_morphism.codomain()
|
|
2535
|
+
return RingExtension(ring, defining_morphism, gen=gen, names=names, constructors=[(constructor, kwargs)])
|
|
2536
|
+
|
|
2537
|
+
|
|
2538
|
+
cdef class RingExtensionWithGen(RingExtensionWithBasis):
|
|
2539
|
+
"""
|
|
2540
|
+
A class for finite free ring extensions generated by
|
|
2541
|
+
a single element
|
|
2542
|
+
|
|
2543
|
+
TESTS::
|
|
2544
|
+
|
|
2545
|
+
sage: # needs sage.rings.number_field
|
|
2546
|
+
sage: x = polygen(ZZ, 'x')
|
|
2547
|
+
sage: A.<a> = QQ.extension(x^3 - 7)
|
|
2548
|
+
sage: K = A.over()
|
|
2549
|
+
sage: type(K)
|
|
2550
|
+
<class 'sage.rings.ring_extension.RingExtensionWithGen'>
|
|
2551
|
+
sage: TestSuite(K).run()
|
|
2552
|
+
"""
|
|
2553
|
+
def __init__(self, defining_morphism, gen, names, check=True, **kwargs):
|
|
2554
|
+
r"""
|
|
2555
|
+
Initialize this ring extension.
|
|
2556
|
+
|
|
2557
|
+
INPUT:
|
|
2558
|
+
|
|
2559
|
+
- ``defining_morphism`` -- a ring homomorphism
|
|
2560
|
+
|
|
2561
|
+
- ``gen`` -- a generator of this extension
|
|
2562
|
+
|
|
2563
|
+
- ``names`` -- tuple of strings or ``None`` (default: ``None``);
|
|
2564
|
+
the way the elements of the basis are printed
|
|
2565
|
+
|
|
2566
|
+
- ``check`` -- boolean (default: ``True``); whether to check if
|
|
2567
|
+
``gen`` is indeed a generator
|
|
2568
|
+
|
|
2569
|
+
TESTS::
|
|
2570
|
+
|
|
2571
|
+
sage: x = polygen(ZZ, 'x')
|
|
2572
|
+
sage: K.<a> = QQ.extension(x^3 + 3*x + 1) # needs sage.rings.number_field
|
|
2573
|
+
sage: E = K.over(); E # needs sage.rings.number_field
|
|
2574
|
+
Field in a with defining polynomial x^3 + 3*x + 1 over its base
|
|
2575
|
+
|
|
2576
|
+
sage: TestSuite(E).run() # needs sage.rings.number_field
|
|
2577
|
+
"""
|
|
2578
|
+
self._name = names[0]
|
|
2579
|
+
backend_base = backend_parent(defining_morphism.domain())
|
|
2580
|
+
_, deg_domain, deg_codomain = common_base(backend_base, defining_morphism.codomain(), True)
|
|
2581
|
+
degree = deg_codomain // deg_domain
|
|
2582
|
+
basis_names = [""]
|
|
2583
|
+
basis_latex_names = [""]
|
|
2584
|
+
if degree == 1:
|
|
2585
|
+
self._name = None
|
|
2586
|
+
else:
|
|
2587
|
+
basis_names += [self._name] + ["%s^%s" % (self._name, i) for i in range(2, degree)]
|
|
2588
|
+
latex_name = latex_variable_name(self._name)
|
|
2589
|
+
basis_latex_names += [latex_name] + ["%s^{%s}" % (latex_name, i) for i in range(2, degree)]
|
|
2590
|
+
basis = [gen ** i for i in range(degree)]
|
|
2591
|
+
RingExtensionWithBasis.__init__(self, defining_morphism, basis, basis_names, check, **kwargs)
|
|
2592
|
+
self._gen = self._backend(gen)
|
|
2593
|
+
self._names = (self._name,)
|
|
2594
|
+
self._basis_latex_names = basis_latex_names
|
|
2595
|
+
|
|
2596
|
+
def _repr_topring(self, **options):
|
|
2597
|
+
r"""
|
|
2598
|
+
Return a string representation of top ring of this extension.
|
|
2599
|
+
|
|
2600
|
+
EXAMPLES::
|
|
2601
|
+
|
|
2602
|
+
sage: # needs sage.rings.finite_rings
|
|
2603
|
+
sage: K.<a> = GF(5^3).over()
|
|
2604
|
+
sage: K._repr_topring()
|
|
2605
|
+
'Field in a with defining polynomial x^3 + 3*x + 3'
|
|
2606
|
+
sage: L.<b> = GF(5^9).over(K)
|
|
2607
|
+
sage: L._repr_topring()
|
|
2608
|
+
'Field in b with defining polynomial x^3 + (1 + 3*a^2)*x^2 + (3 + 2*a + 2*a^2)*x - a'
|
|
2609
|
+
"""
|
|
2610
|
+
if self._name is None:
|
|
2611
|
+
return RingExtension_generic._repr_topring(self, **options)
|
|
2612
|
+
return "%s in %s with defining polynomial %s" % (self._type, self._name, self.modulus())
|
|
2613
|
+
|
|
2614
|
+
def _latex_topring(self):
|
|
2615
|
+
r"""
|
|
2616
|
+
Return a LaTeX representation of top ring of this extension.
|
|
2617
|
+
|
|
2618
|
+
EXAMPLES::
|
|
2619
|
+
|
|
2620
|
+
sage: # needs sage.rings.finite_rings
|
|
2621
|
+
sage: K.<a> = GF(5^3).over()
|
|
2622
|
+
sage: K._latex_topring()
|
|
2623
|
+
'\\Bold{F}_{5}[a]'
|
|
2624
|
+
sage: L.<b> = GF(5^9).over(K)
|
|
2625
|
+
sage: L._latex_topring()
|
|
2626
|
+
'\\Bold{F}_{5}[a][b]'
|
|
2627
|
+
"""
|
|
2628
|
+
if self._name is None:
|
|
2629
|
+
return RingExtension_generic._latex_topring(self)
|
|
2630
|
+
if isinstance(self._base, RingExtension_generic):
|
|
2631
|
+
return "%s[%s]" % (self._base._latex_topring(), self.latex_variable_names()[0])
|
|
2632
|
+
else:
|
|
2633
|
+
return "%s[%s]" % (latex(self._base), self.latex_variable_names()[0])
|
|
2634
|
+
|
|
2635
|
+
def modulus(self, var='x'):
|
|
2636
|
+
r"""
|
|
2637
|
+
Return the defining polynomial of this extension, that is the
|
|
2638
|
+
minimal polynomial of the given generator of this extension.
|
|
2639
|
+
|
|
2640
|
+
INPUT:
|
|
2641
|
+
|
|
2642
|
+
- ``var`` -- a variable name (default: ``x``)
|
|
2643
|
+
|
|
2644
|
+
EXAMPLES::
|
|
2645
|
+
|
|
2646
|
+
sage: # needs sage.rings.finite_rings
|
|
2647
|
+
sage: K.<u> = GF(7^10).over(GF(7^2)); K
|
|
2648
|
+
Field in u with defining polynomial x^5 + (6*z2 + 4)*x^4
|
|
2649
|
+
+ (3*z2 + 5)*x^3 + (2*z2 + 2)*x^2 + 4*x + 6*z2 over its base
|
|
2650
|
+
sage: P = K.modulus(); P
|
|
2651
|
+
x^5 + (6*z2 + 4)*x^4 + (3*z2 + 5)*x^3 + (2*z2 + 2)*x^2 + 4*x + 6*z2
|
|
2652
|
+
sage: P(u)
|
|
2653
|
+
0
|
|
2654
|
+
|
|
2655
|
+
We can use a different variable name::
|
|
2656
|
+
|
|
2657
|
+
sage: K.modulus('y') # needs sage.rings.finite_rings
|
|
2658
|
+
y^5 + (6*z2 + 4)*y^4 + (3*z2 + 5)*y^3 + (2*z2 + 2)*y^2 + 4*y + 6*z2
|
|
2659
|
+
"""
|
|
2660
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
2661
|
+
_, _, j = self.free_module(map=True)
|
|
2662
|
+
d = self.relative_degree()
|
|
2663
|
+
coeffs = [-c for c in j(self._gen**d)] + [1]
|
|
2664
|
+
S = PolynomialRing(self._base, name=var)
|
|
2665
|
+
return S(coeffs)
|
|
2666
|
+
|
|
2667
|
+
def gens(self, base=None) -> tuple:
|
|
2668
|
+
r"""
|
|
2669
|
+
Return the generators of this extension over ``base``.
|
|
2670
|
+
|
|
2671
|
+
INPUT:
|
|
2672
|
+
|
|
2673
|
+
- ``base`` -- a commutative ring (which might be itself an
|
|
2674
|
+
extension) or ``None`` (default: ``None``)
|
|
2675
|
+
|
|
2676
|
+
EXAMPLES::
|
|
2677
|
+
|
|
2678
|
+
sage: # needs sage.rings.finite_rings
|
|
2679
|
+
sage: K.<a> = GF(5^2).over() # over GF(5)
|
|
2680
|
+
sage: K.gens()
|
|
2681
|
+
(a,)
|
|
2682
|
+
sage: L.<b> = GF(5^4).over(K)
|
|
2683
|
+
sage: L.gens()
|
|
2684
|
+
(b,)
|
|
2685
|
+
sage: L.gens(GF(5))
|
|
2686
|
+
(b, a)
|
|
2687
|
+
"""
|
|
2688
|
+
if base is None:
|
|
2689
|
+
return (self(self._gen),)
|
|
2690
|
+
base = self._check_base(base)
|
|
2691
|
+
gens = tuple()
|
|
2692
|
+
b = self
|
|
2693
|
+
while b is not base:
|
|
2694
|
+
gens += b.gens()
|
|
2695
|
+
b = b.base()
|
|
2696
|
+
return gens
|
|
2697
|
+
|
|
2698
|
+
@cached_method
|
|
2699
|
+
def fraction_field(self, extend_base=False):
|
|
2700
|
+
r"""
|
|
2701
|
+
Return the fraction field of this extension.
|
|
2702
|
+
|
|
2703
|
+
INPUT:
|
|
2704
|
+
|
|
2705
|
+
- ``extend_base`` -- boolean (default: ``False``)
|
|
2706
|
+
|
|
2707
|
+
If ``extend_base`` is ``False``, the fraction field of the
|
|
2708
|
+
extension `L/K` is defined as `\textrm{Frac}(L)/L/K`, except
|
|
2709
|
+
is `L` is already a field in which base the fraction field
|
|
2710
|
+
of `L/K` is `L/K` itself.
|
|
2711
|
+
|
|
2712
|
+
If ``extend_base`` is ``True``, the fraction field of the
|
|
2713
|
+
extension `L/K` is defined as `\textrm{Frac}(L)/\textrm{Frac}(K)`
|
|
2714
|
+
(provided that the defining morphism extends to the fraction
|
|
2715
|
+
fields, i.e. is injective).
|
|
2716
|
+
|
|
2717
|
+
EXAMPLES::
|
|
2718
|
+
|
|
2719
|
+
sage: # needs sage.rings.number_field
|
|
2720
|
+
sage: x = polygen(ZZ, 'x')
|
|
2721
|
+
sage: A.<a> = ZZ.extension(x^2 - 5)
|
|
2722
|
+
sage: OK = A.over() # over ZZ
|
|
2723
|
+
sage: OK
|
|
2724
|
+
Order of conductor 2 generated by a in Number Field in a
|
|
2725
|
+
with defining polynomial x^2 - 5 over its base
|
|
2726
|
+
sage: K1 = OK.fraction_field(); K1
|
|
2727
|
+
Fraction Field of Order of conductor 2 generated by a
|
|
2728
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base
|
|
2729
|
+
sage: K1.bases()
|
|
2730
|
+
[Fraction Field of Order of conductor 2 generated by a
|
|
2731
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base,
|
|
2732
|
+
Order of conductor 2 generated by a in Number Field in a
|
|
2733
|
+
with defining polynomial x^2 - 5 over its base,
|
|
2734
|
+
Integer Ring]
|
|
2735
|
+
sage: K2 = OK.fraction_field(extend_base=True); K2
|
|
2736
|
+
Fraction Field of Order of conductor 2 generated by a
|
|
2737
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base
|
|
2738
|
+
sage: K2.bases()
|
|
2739
|
+
[Fraction Field of Order of conductor 2 generated by a
|
|
2740
|
+
in Number Field in a with defining polynomial x^2 - 5 over its base,
|
|
2741
|
+
Rational Field]
|
|
2742
|
+
|
|
2743
|
+
Note that there is no coercion map between `K_1` and `K_2`::
|
|
2744
|
+
|
|
2745
|
+
sage: K1.has_coerce_map_from(K2) # needs sage.rings.number_field
|
|
2746
|
+
False
|
|
2747
|
+
sage: K2.has_coerce_map_from(K1) # needs sage.rings.number_field
|
|
2748
|
+
False
|
|
2749
|
+
|
|
2750
|
+
We check that when the extension is a field, its fraction field does not change::
|
|
2751
|
+
|
|
2752
|
+
sage: K1.fraction_field() is K1 # needs sage.rings.number_field
|
|
2753
|
+
True
|
|
2754
|
+
sage: K2.fraction_field() is K2 # needs sage.rings.number_field
|
|
2755
|
+
True
|
|
2756
|
+
|
|
2757
|
+
TESTS::
|
|
2758
|
+
|
|
2759
|
+
sage: A = GF(5).over(ZZ)
|
|
2760
|
+
sage: A.fraction_field(extend_base=True)
|
|
2761
|
+
Traceback (most recent call last):
|
|
2762
|
+
...
|
|
2763
|
+
ValueError: the morphism is not injective
|
|
2764
|
+
"""
|
|
2765
|
+
defining_morphism = self._defining_morphism_fraction_field(extend_base)
|
|
2766
|
+
if defining_morphism is None:
|
|
2767
|
+
return self
|
|
2768
|
+
if extend_base:
|
|
2769
|
+
gen = self._gen
|
|
2770
|
+
names = self._names
|
|
2771
|
+
constructor = RingExtensionWithGen
|
|
2772
|
+
kwargs = { 'gen': gen, 'names': names, 'check': False }
|
|
2773
|
+
else:
|
|
2774
|
+
gen = names = None
|
|
2775
|
+
constructor = RingExtensionFractionField
|
|
2776
|
+
kwargs = { 'print_options': {'print_elements_as': self.fraction_field(extend_base=True)} }
|
|
2777
|
+
kwargs['is_backend_exposed'] = self._is_backend_exposed
|
|
2778
|
+
ring = defining_morphism.codomain()
|
|
2779
|
+
return RingExtension(ring, defining_morphism, gen=gen, names=names, constructors=[(constructor, kwargs)])
|