passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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.
- passagemath_categories-10.6.32.dist-info/METADATA +156 -0
- passagemath_categories-10.6.32.dist-info/RECORD +719 -0
- passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
- passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
- passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
- passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
- passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
- sage/all__sagemath_categories.py +28 -0
- sage/arith/all.py +38 -0
- sage/arith/constants.pxd +27 -0
- sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/functions.pxd +4 -0
- sage/arith/functions.pyx +221 -0
- sage/arith/misc.py +6552 -0
- sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/multi_modular.pxd +39 -0
- sage/arith/multi_modular.pyx +994 -0
- sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/rational_reconstruction.pxd +4 -0
- sage/arith/rational_reconstruction.pyx +115 -0
- sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/arith/srange.pyx +571 -0
- sage/calculus/all__sagemath_categories.py +2 -0
- sage/calculus/functional.py +481 -0
- sage/calculus/functions.py +151 -0
- sage/categories/additive_groups.py +73 -0
- sage/categories/additive_magmas.py +1044 -0
- sage/categories/additive_monoids.py +114 -0
- sage/categories/additive_semigroups.py +184 -0
- sage/categories/affine_weyl_groups.py +238 -0
- sage/categories/algebra_ideals.py +95 -0
- sage/categories/algebra_modules.py +96 -0
- sage/categories/algebras.py +349 -0
- sage/categories/algebras_with_basis.py +377 -0
- sage/categories/all.py +160 -0
- sage/categories/aperiodic_semigroups.py +29 -0
- sage/categories/associative_algebras.py +47 -0
- sage/categories/bialgebras.py +101 -0
- sage/categories/bialgebras_with_basis.py +414 -0
- sage/categories/bimodules.py +206 -0
- sage/categories/chain_complexes.py +268 -0
- sage/categories/classical_crystals.py +480 -0
- sage/categories/coalgebras.py +405 -0
- sage/categories/coalgebras_with_basis.py +232 -0
- sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/coercion_methods.pyx +52 -0
- sage/categories/commutative_additive_groups.py +104 -0
- sage/categories/commutative_additive_monoids.py +45 -0
- sage/categories/commutative_additive_semigroups.py +48 -0
- sage/categories/commutative_algebra_ideals.py +87 -0
- sage/categories/commutative_algebras.py +94 -0
- sage/categories/commutative_ring_ideals.py +58 -0
- sage/categories/commutative_rings.py +736 -0
- sage/categories/complete_discrete_valuation.py +293 -0
- sage/categories/complex_reflection_groups.py +145 -0
- sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
- sage/categories/coxeter_group_algebras.py +186 -0
- sage/categories/coxeter_groups.py +3402 -0
- sage/categories/crystals.py +2628 -0
- sage/categories/cw_complexes.py +216 -0
- sage/categories/dedekind_domains.py +137 -0
- sage/categories/discrete_valuation.py +325 -0
- sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
- sage/categories/division_rings.py +114 -0
- sage/categories/domains.py +95 -0
- sage/categories/drinfeld_modules.py +789 -0
- sage/categories/dual.py +42 -0
- sage/categories/enumerated_sets.py +1146 -0
- sage/categories/euclidean_domains.py +271 -0
- sage/categories/examples/algebras_with_basis.py +102 -0
- sage/categories/examples/all.py +1 -0
- sage/categories/examples/commutative_additive_monoids.py +130 -0
- sage/categories/examples/commutative_additive_semigroups.py +199 -0
- sage/categories/examples/coxeter_groups.py +8 -0
- sage/categories/examples/crystals.py +236 -0
- sage/categories/examples/cw_complexes.py +163 -0
- sage/categories/examples/facade_sets.py +187 -0
- sage/categories/examples/filtered_algebras_with_basis.py +204 -0
- sage/categories/examples/filtered_modules_with_basis.py +154 -0
- sage/categories/examples/finite_coxeter_groups.py +252 -0
- sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
- sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
- sage/categories/examples/finite_enumerated_sets.py +208 -0
- sage/categories/examples/finite_monoids.py +150 -0
- sage/categories/examples/finite_semigroups.py +190 -0
- sage/categories/examples/finite_weyl_groups.py +191 -0
- sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
- sage/categories/examples/graded_modules_with_basis.py +168 -0
- sage/categories/examples/graphs.py +122 -0
- sage/categories/examples/hopf_algebras_with_basis.py +145 -0
- sage/categories/examples/infinite_enumerated_sets.py +190 -0
- sage/categories/examples/lie_algebras.py +352 -0
- sage/categories/examples/lie_algebras_with_basis.py +196 -0
- sage/categories/examples/magmas.py +162 -0
- sage/categories/examples/manifolds.py +94 -0
- sage/categories/examples/monoids.py +144 -0
- sage/categories/examples/posets.py +178 -0
- sage/categories/examples/semigroups.py +580 -0
- sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/categories/examples/semigroups_cython.pyx +221 -0
- sage/categories/examples/semirings.py +249 -0
- sage/categories/examples/sets_cat.py +706 -0
- sage/categories/examples/sets_with_grading.py +101 -0
- sage/categories/examples/with_realizations.py +542 -0
- sage/categories/fields.py +991 -0
- sage/categories/filtered_algebras.py +63 -0
- sage/categories/filtered_algebras_with_basis.py +548 -0
- sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
- sage/categories/filtered_modules.py +210 -0
- sage/categories/filtered_modules_with_basis.py +1209 -0
- sage/categories/finite_complex_reflection_groups.py +1506 -0
- sage/categories/finite_coxeter_groups.py +1138 -0
- sage/categories/finite_crystals.py +103 -0
- sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
- sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
- sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
- sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
- sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
- sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
- sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
- sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
- sage/categories/finite_enumerated_sets.py +769 -0
- sage/categories/finite_fields.py +252 -0
- sage/categories/finite_groups.py +256 -0
- sage/categories/finite_lattice_posets.py +242 -0
- sage/categories/finite_monoids.py +316 -0
- sage/categories/finite_permutation_groups.py +339 -0
- sage/categories/finite_posets.py +1994 -0
- sage/categories/finite_semigroups.py +136 -0
- sage/categories/finite_sets.py +93 -0
- sage/categories/finite_weyl_groups.py +39 -0
- sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
- sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
- sage/categories/finitely_generated_magmas.py +57 -0
- sage/categories/finitely_generated_semigroups.py +214 -0
- sage/categories/function_fields.py +76 -0
- sage/categories/g_sets.py +77 -0
- sage/categories/gcd_domains.py +65 -0
- sage/categories/generalized_coxeter_groups.py +94 -0
- sage/categories/graded_algebras.py +85 -0
- sage/categories/graded_algebras_with_basis.py +258 -0
- sage/categories/graded_bialgebras.py +32 -0
- sage/categories/graded_bialgebras_with_basis.py +32 -0
- sage/categories/graded_coalgebras.py +65 -0
- sage/categories/graded_coalgebras_with_basis.py +51 -0
- sage/categories/graded_hopf_algebras.py +41 -0
- sage/categories/graded_hopf_algebras_with_basis.py +169 -0
- sage/categories/graded_lie_algebras.py +91 -0
- sage/categories/graded_lie_algebras_with_basis.py +44 -0
- sage/categories/graded_lie_conformal_algebras.py +74 -0
- sage/categories/graded_modules.py +133 -0
- sage/categories/graded_modules_with_basis.py +329 -0
- sage/categories/graphs.py +138 -0
- sage/categories/group_algebras.py +430 -0
- sage/categories/groupoid.py +94 -0
- sage/categories/groups.py +667 -0
- sage/categories/h_trivial_semigroups.py +64 -0
- sage/categories/hecke_modules.py +185 -0
- sage/categories/highest_weight_crystals.py +980 -0
- sage/categories/hopf_algebras.py +219 -0
- sage/categories/hopf_algebras_with_basis.py +309 -0
- sage/categories/infinite_enumerated_sets.py +115 -0
- sage/categories/integral_domains.py +203 -0
- sage/categories/j_trivial_semigroups.py +29 -0
- sage/categories/kac_moody_algebras.py +82 -0
- sage/categories/kahler_algebras.py +203 -0
- sage/categories/l_trivial_semigroups.py +63 -0
- sage/categories/lambda_bracket_algebras.py +280 -0
- sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
- sage/categories/lattice_posets.py +89 -0
- sage/categories/left_modules.py +49 -0
- sage/categories/lie_algebras.py +1070 -0
- sage/categories/lie_algebras_with_basis.py +261 -0
- sage/categories/lie_conformal_algebras.py +350 -0
- sage/categories/lie_conformal_algebras_with_basis.py +147 -0
- sage/categories/lie_groups.py +73 -0
- sage/categories/loop_crystals.py +1290 -0
- sage/categories/magmas.py +1189 -0
- sage/categories/magmas_and_additive_magmas.py +149 -0
- sage/categories/magmatic_algebras.py +365 -0
- sage/categories/manifolds.py +352 -0
- sage/categories/matrix_algebras.py +40 -0
- sage/categories/metric_spaces.py +387 -0
- sage/categories/modular_abelian_varieties.py +78 -0
- sage/categories/modules.py +989 -0
- sage/categories/modules_with_basis.py +2794 -0
- sage/categories/monoid_algebras.py +38 -0
- sage/categories/monoids.py +739 -0
- sage/categories/noetherian_rings.py +87 -0
- sage/categories/number_fields.py +242 -0
- sage/categories/ore_modules.py +189 -0
- sage/categories/partially_ordered_monoids.py +49 -0
- sage/categories/permutation_groups.py +63 -0
- sage/categories/pointed_sets.py +42 -0
- sage/categories/polyhedra.py +74 -0
- sage/categories/poor_man_map.py +270 -0
- sage/categories/posets.py +722 -0
- sage/categories/principal_ideal_domains.py +270 -0
- sage/categories/quantum_group_representations.py +543 -0
- sage/categories/quotient_fields.py +728 -0
- sage/categories/r_trivial_semigroups.py +45 -0
- sage/categories/regular_crystals.py +898 -0
- sage/categories/regular_supercrystals.py +170 -0
- sage/categories/right_modules.py +49 -0
- sage/categories/ring_ideals.py +74 -0
- sage/categories/rings.py +1904 -0
- sage/categories/rngs.py +175 -0
- sage/categories/schemes.py +393 -0
- sage/categories/semigroups.py +1060 -0
- sage/categories/semirings.py +71 -0
- sage/categories/semisimple_algebras.py +114 -0
- sage/categories/sets_with_grading.py +235 -0
- sage/categories/shephard_groups.py +43 -0
- sage/categories/signed_tensor.py +120 -0
- sage/categories/simplicial_complexes.py +134 -0
- sage/categories/simplicial_sets.py +1206 -0
- sage/categories/super_algebras.py +149 -0
- sage/categories/super_algebras_with_basis.py +144 -0
- sage/categories/super_hopf_algebras_with_basis.py +126 -0
- sage/categories/super_lie_conformal_algebras.py +193 -0
- sage/categories/super_modules.py +229 -0
- sage/categories/super_modules_with_basis.py +193 -0
- sage/categories/supercommutative_algebras.py +99 -0
- sage/categories/supercrystals.py +406 -0
- sage/categories/tensor.py +110 -0
- sage/categories/topological_spaces.py +170 -0
- sage/categories/triangular_kac_moody_algebras.py +439 -0
- sage/categories/tutorial.py +58 -0
- sage/categories/unique_factorization_domains.py +318 -0
- sage/categories/unital_algebras.py +426 -0
- sage/categories/vector_bundles.py +159 -0
- sage/categories/vector_spaces.py +357 -0
- sage/categories/weyl_groups.py +853 -0
- sage/combinat/all__sagemath_categories.py +34 -0
- sage/combinat/backtrack.py +180 -0
- sage/combinat/combinat.py +2269 -0
- sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/combinat_cython.pxd +6 -0
- sage/combinat/combinat_cython.pyx +390 -0
- sage/combinat/combination.py +796 -0
- sage/combinat/combinatorial_map.py +416 -0
- sage/combinat/composition.py +2192 -0
- sage/combinat/dlx.py +510 -0
- sage/combinat/integer_lists/__init__.py +7 -0
- sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/base.pxd +16 -0
- sage/combinat/integer_lists/base.pyx +713 -0
- sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/integer_lists/invlex.pxd +4 -0
- sage/combinat/integer_lists/invlex.pyx +1650 -0
- sage/combinat/integer_lists/lists.py +328 -0
- sage/combinat/integer_lists/nn.py +48 -0
- sage/combinat/integer_vector.py +1818 -0
- sage/combinat/integer_vector_weighted.py +413 -0
- sage/combinat/matrices/all__sagemath_categories.py +5 -0
- sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/matrices/dancing_links.pyx +1159 -0
- sage/combinat/matrices/dancing_links_c.h +380 -0
- sage/combinat/matrices/dlxcpp.py +136 -0
- sage/combinat/partition.py +10070 -0
- sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/partitions.pyx +743 -0
- sage/combinat/permutation.py +10168 -0
- sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/combinat/permutation_cython.pxd +11 -0
- sage/combinat/permutation_cython.pyx +407 -0
- sage/combinat/q_analogues.py +1090 -0
- sage/combinat/ranker.py +268 -0
- sage/combinat/subset.py +1561 -0
- sage/combinat/subsets_hereditary.py +202 -0
- sage/combinat/subsets_pairwise.py +184 -0
- sage/combinat/tools.py +63 -0
- sage/combinat/tuple.py +348 -0
- sage/data_structures/all.py +2 -0
- sage/data_structures/all__sagemath_categories.py +2 -0
- sage/data_structures/binary_matrix.pxd +138 -0
- sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/binary_search.pxd +3 -0
- sage/data_structures/binary_search.pyx +66 -0
- sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset.pxd +40 -0
- sage/data_structures/bitset.pyx +2385 -0
- sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/bitset_base.pxd +926 -0
- sage/data_structures/bitset_base.pyx +117 -0
- sage/data_structures/bitset_intrinsics.h +487 -0
- sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/blas_dict.pxd +12 -0
- sage/data_structures/blas_dict.pyx +469 -0
- sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/list_of_pairs.pxd +16 -0
- sage/data_structures/list_of_pairs.pyx +122 -0
- sage/data_structures/mutable_poset.py +3312 -0
- sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/data_structures/pairing_heap.h +346 -0
- sage/data_structures/pairing_heap.pxd +88 -0
- sage/data_structures/pairing_heap.pyx +1464 -0
- sage/data_structures/sparse_bitset.pxd +62 -0
- sage/data_structures/stream.py +5070 -0
- sage/databases/all__sagemath_categories.py +7 -0
- sage/databases/sql_db.py +2236 -0
- sage/ext/all__sagemath_categories.py +3 -0
- sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_callable.pxd +4 -0
- sage/ext/fast_callable.pyx +2746 -0
- sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/fast_eval.pxd +1 -0
- sage/ext/fast_eval.pyx +102 -0
- sage/ext/interpreters/__init__.py +1 -0
- sage/ext/interpreters/all__sagemath_categories.py +2 -0
- sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_el.pxd +18 -0
- sage/ext/interpreters/wrapper_el.pyx +148 -0
- sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/ext/interpreters/wrapper_py.pxd +17 -0
- sage/ext/interpreters/wrapper_py.pyx +133 -0
- sage/functions/airy.py +937 -0
- sage/functions/all.py +97 -0
- sage/functions/bessel.py +2102 -0
- sage/functions/error.py +784 -0
- sage/functions/exp_integral.py +1529 -0
- sage/functions/gamma.py +1087 -0
- sage/functions/generalized.py +672 -0
- sage/functions/hyperbolic.py +747 -0
- sage/functions/hypergeometric.py +1156 -0
- sage/functions/jacobi.py +1705 -0
- sage/functions/log.py +1402 -0
- sage/functions/min_max.py +338 -0
- sage/functions/orthogonal_polys.py +3106 -0
- sage/functions/other.py +2303 -0
- sage/functions/piecewise.py +1505 -0
- sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/functions/prime_pi.pyx +262 -0
- sage/functions/special.py +1212 -0
- sage/functions/spike_function.py +278 -0
- sage/functions/transcendental.py +690 -0
- sage/functions/trig.py +1062 -0
- sage/functions/wigner.py +726 -0
- sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/geometry/abc.pyx +82 -0
- sage/geometry/all__sagemath_categories.py +1 -0
- sage/groups/all__sagemath_categories.py +11 -0
- sage/groups/generic.py +1733 -0
- sage/groups/groups_catalog.py +113 -0
- sage/groups/perm_gps/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/all.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
- sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
- sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
- sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
- sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
- sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
- sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
- sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
- sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
- sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
- sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
- sage/interfaces/abc.py +140 -0
- sage/interfaces/all.py +58 -0
- sage/interfaces/all__sagemath_categories.py +1 -0
- sage/interfaces/expect.py +1643 -0
- sage/interfaces/interface.py +1682 -0
- sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/process.pxd +5 -0
- sage/interfaces/process.pyx +288 -0
- sage/interfaces/quit.py +167 -0
- sage/interfaces/sage0.py +604 -0
- sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/interfaces/sagespawn.pyx +308 -0
- sage/interfaces/tab_completion.py +101 -0
- sage/misc/all__sagemath_categories.py +78 -0
- sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/allocator.pxd +6 -0
- sage/misc/allocator.pyx +47 -0
- sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/binary_tree.pxd +29 -0
- sage/misc/binary_tree.pyx +537 -0
- sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/callable_dict.pyx +89 -0
- sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/citation.pyx +159 -0
- sage/misc/converting_dict.py +293 -0
- sage/misc/defaults.py +129 -0
- sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/derivative.pyx +223 -0
- sage/misc/functional.py +2005 -0
- sage/misc/html.py +589 -0
- sage/misc/latex.py +2673 -0
- sage/misc/latex_macros.py +236 -0
- sage/misc/latex_standalone.py +1833 -0
- sage/misc/map_threaded.py +38 -0
- sage/misc/mathml.py +76 -0
- sage/misc/method_decorator.py +88 -0
- sage/misc/mrange.py +755 -0
- sage/misc/multireplace.py +41 -0
- sage/misc/object_multiplexer.py +92 -0
- sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/parser.pyx +1107 -0
- sage/misc/random_testing.py +264 -0
- sage/misc/rest_index_of_methods.py +377 -0
- sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/search.pxd +2 -0
- sage/misc/search.pyx +68 -0
- sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/misc/stopgap.pyx +95 -0
- sage/misc/table.py +853 -0
- sage/monoids/all__sagemath_categories.py +1 -0
- sage/monoids/indexed_free_monoid.py +1071 -0
- sage/monoids/monoid.py +82 -0
- sage/numerical/all__sagemath_categories.py +1 -0
- sage/numerical/backends/all__sagemath_categories.py +1 -0
- sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_backend.pxd +61 -0
- sage/numerical/backends/generic_backend.pyx +1893 -0
- sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/numerical/backends/generic_sdp_backend.pxd +38 -0
- sage/numerical/backends/generic_sdp_backend.pyx +755 -0
- sage/parallel/all.py +6 -0
- sage/parallel/decorate.py +575 -0
- sage/parallel/map_reduce.py +1997 -0
- sage/parallel/multiprocessing_sage.py +76 -0
- sage/parallel/ncpus.py +35 -0
- sage/parallel/parallelism.py +364 -0
- sage/parallel/reference.py +47 -0
- sage/parallel/use_fork.py +333 -0
- sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/abc.pxd +31 -0
- sage/rings/abc.pyx +526 -0
- sage/rings/algebraic_closure_finite_field.py +1154 -0
- sage/rings/all__sagemath_categories.py +91 -0
- sage/rings/big_oh.py +227 -0
- sage/rings/continued_fraction.py +2754 -0
- sage/rings/continued_fraction_gosper.py +220 -0
- sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/factorint.pyx +295 -0
- sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fast_arith.pxd +21 -0
- sage/rings/fast_arith.pyx +535 -0
- sage/rings/finite_rings/all__sagemath_categories.py +9 -0
- sage/rings/finite_rings/conway_polynomials.py +542 -0
- sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_base.pxd +12 -0
- sage/rings/finite_rings/element_base.pyx +1176 -0
- sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/finite_field_base.pxd +7 -0
- sage/rings/finite_rings/finite_field_base.pyx +2171 -0
- sage/rings/finite_rings/finite_field_constructor.py +827 -0
- sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
- sage/rings/finite_rings/galois_group.py +154 -0
- sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field.pxd +23 -0
- sage/rings/finite_rings/hom_finite_field.pyx +856 -0
- sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
- sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
- sage/rings/finite_rings/homset.py +357 -0
- sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/integer_mod.pxd +56 -0
- sage/rings/finite_rings/integer_mod.pyx +4586 -0
- sage/rings/finite_rings/integer_mod_limits.h +11 -0
- sage/rings/finite_rings/integer_mod_ring.py +2044 -0
- sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field.pxd +30 -0
- sage/rings/finite_rings/residue_field.pyx +1811 -0
- sage/rings/finite_rings/stdint.pxd +19 -0
- sage/rings/fraction_field.py +1452 -0
- sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/fraction_field_element.pyx +1357 -0
- sage/rings/function_field/all.py +7 -0
- sage/rings/function_field/all__sagemath_categories.py +2 -0
- sage/rings/function_field/constructor.py +218 -0
- sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element.pxd +11 -0
- sage/rings/function_field/element.pyx +1008 -0
- sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/function_field/element_rational.pyx +513 -0
- sage/rings/function_field/extensions.py +230 -0
- sage/rings/function_field/function_field.py +1468 -0
- sage/rings/function_field/function_field_rational.py +1005 -0
- sage/rings/function_field/ideal.py +1155 -0
- sage/rings/function_field/ideal_rational.py +629 -0
- sage/rings/function_field/jacobian_base.py +826 -0
- sage/rings/function_field/jacobian_hess.py +1053 -0
- sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
- sage/rings/function_field/maps.py +1039 -0
- sage/rings/function_field/order.py +281 -0
- sage/rings/function_field/order_basis.py +586 -0
- sage/rings/function_field/order_rational.py +576 -0
- sage/rings/function_field/place.py +426 -0
- sage/rings/function_field/place_rational.py +181 -0
- sage/rings/generic.py +320 -0
- sage/rings/homset.py +332 -0
- sage/rings/ideal.py +1885 -0
- sage/rings/ideal_monoid.py +215 -0
- sage/rings/infinity.py +1890 -0
- sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer.pxd +45 -0
- sage/rings/integer.pyx +7874 -0
- sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/integer_ring.pxd +8 -0
- sage/rings/integer_ring.pyx +1693 -0
- sage/rings/laurent_series_ring.py +931 -0
- sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/laurent_series_ring_element.pxd +11 -0
- sage/rings/laurent_series_ring_element.pyx +1927 -0
- sage/rings/lazy_series.py +7815 -0
- sage/rings/lazy_series_ring.py +4356 -0
- sage/rings/localization.py +1043 -0
- sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/morphism.pxd +39 -0
- sage/rings/morphism.pyx +3299 -0
- sage/rings/multi_power_series_ring.py +1145 -0
- sage/rings/multi_power_series_ring_element.py +2184 -0
- sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/noncommutative_ideals.pyx +423 -0
- sage/rings/number_field/all__sagemath_categories.py +1 -0
- sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_base.pxd +8 -0
- sage/rings/number_field/number_field_base.pyx +507 -0
- sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/number_field/number_field_element_base.pxd +6 -0
- sage/rings/number_field/number_field_element_base.pyx +36 -0
- sage/rings/number_field/number_field_ideal.py +3550 -0
- sage/rings/padics/all__sagemath_categories.py +4 -0
- sage/rings/padics/local_generic.py +1670 -0
- sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/local_generic_element.pxd +5 -0
- sage/rings/padics/local_generic_element.pyx +1017 -0
- sage/rings/padics/misc.py +256 -0
- sage/rings/padics/padic_generic.py +1911 -0
- sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer.pxd +38 -0
- sage/rings/padics/pow_computer.pyx +671 -0
- sage/rings/padics/precision_error.py +24 -0
- sage/rings/polynomial/all__sagemath_categories.py +25 -0
- sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/commutative_polynomial.pxd +6 -0
- sage/rings/polynomial/commutative_polynomial.pyx +24 -0
- sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/cyclotomic.pyx +404 -0
- sage/rings/polynomial/flatten.py +711 -0
- sage/rings/polynomial/ideal.py +102 -0
- sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
- sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
- sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/laurent_polynomial.pxd +18 -0
- sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
- sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
- sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
- sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
- sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial.pxd +12 -0
- sage/rings/polynomial/multi_polynomial.pyx +3082 -0
- sage/rings/polynomial/multi_polynomial_element.py +2570 -0
- sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
- sage/rings/polynomial/multi_polynomial_ring.py +947 -0
- sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
- sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
- sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
- sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polydict.pxd +45 -0
- sage/rings/polynomial/polydict.pyx +2701 -0
- sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_compiled.pxd +59 -0
- sage/rings/polynomial/polynomial_compiled.pyx +509 -0
- sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_element.pxd +64 -0
- sage/rings/polynomial/polynomial_element.pyx +13255 -0
- sage/rings/polynomial/polynomial_element_generic.py +1637 -0
- sage/rings/polynomial/polynomial_fateman.py +97 -0
- sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
- sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
- sage/rings/polynomial/polynomial_ring.py +3784 -0
- sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
- sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
- sage/rings/polynomial/polynomial_singular_interface.py +549 -0
- sage/rings/polynomial/symmetric_ideal.py +989 -0
- sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/polynomial/symmetric_reduction.pxd +8 -0
- sage/rings/polynomial/symmetric_reduction.pyx +669 -0
- sage/rings/polynomial/term_order.py +2279 -0
- sage/rings/polynomial/toy_buchberger.py +449 -0
- sage/rings/polynomial/toy_d_basis.py +387 -0
- sage/rings/polynomial/toy_variety.py +362 -0
- sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_mpoly.pxd +9 -0
- sage/rings/power_series_mpoly.pyx +161 -0
- sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_poly.pxd +10 -0
- sage/rings/power_series_poly.pyx +1317 -0
- sage/rings/power_series_ring.py +1441 -0
- sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/power_series_ring_element.pxd +12 -0
- sage/rings/power_series_ring_element.pyx +3028 -0
- sage/rings/puiseux_series_ring.py +487 -0
- sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/puiseux_series_ring_element.pxd +7 -0
- sage/rings/puiseux_series_ring_element.pyx +1055 -0
- sage/rings/qqbar_decorators.py +167 -0
- sage/rings/quotient_ring.py +1598 -0
- sage/rings/quotient_ring_element.py +979 -0
- sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/rational.pxd +20 -0
- sage/rings/rational.pyx +4284 -0
- sage/rings/rational_field.py +1730 -0
- sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_double.pxd +16 -0
- sage/rings/real_double.pyx +2218 -0
- sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/real_lazy.pxd +30 -0
- sage/rings/real_lazy.pyx +1773 -0
- sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/ring.pxd +30 -0
- sage/rings/ring.pyx +850 -0
- sage/rings/semirings/all.py +3 -0
- sage/rings/semirings/non_negative_integer_semiring.py +107 -0
- sage/rings/semirings/tropical_mpolynomial.py +972 -0
- sage/rings/semirings/tropical_polynomial.py +997 -0
- sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/semirings/tropical_semiring.pyx +676 -0
- sage/rings/semirings/tropical_variety.py +1701 -0
- sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/rings/sum_of_squares.pxd +3 -0
- sage/rings/sum_of_squares.pyx +336 -0
- sage/rings/tests.py +504 -0
- sage/schemes/affine/affine_homset.py +508 -0
- sage/schemes/affine/affine_morphism.py +1574 -0
- sage/schemes/affine/affine_point.py +460 -0
- sage/schemes/affine/affine_rational_point.py +308 -0
- sage/schemes/affine/affine_space.py +1264 -0
- sage/schemes/affine/affine_subscheme.py +592 -0
- sage/schemes/affine/all.py +25 -0
- sage/schemes/all__sagemath_categories.py +5 -0
- sage/schemes/generic/algebraic_scheme.py +2092 -0
- sage/schemes/generic/all.py +5 -0
- sage/schemes/generic/ambient_space.py +400 -0
- sage/schemes/generic/divisor.py +465 -0
- sage/schemes/generic/divisor_group.py +313 -0
- sage/schemes/generic/glue.py +84 -0
- sage/schemes/generic/homset.py +820 -0
- sage/schemes/generic/hypersurface.py +234 -0
- sage/schemes/generic/morphism.py +2107 -0
- sage/schemes/generic/point.py +237 -0
- sage/schemes/generic/scheme.py +1190 -0
- sage/schemes/generic/spec.py +199 -0
- sage/schemes/product_projective/all.py +6 -0
- sage/schemes/product_projective/homset.py +236 -0
- sage/schemes/product_projective/morphism.py +517 -0
- sage/schemes/product_projective/point.py +568 -0
- sage/schemes/product_projective/rational_point.py +550 -0
- sage/schemes/product_projective/space.py +1301 -0
- sage/schemes/product_projective/subscheme.py +466 -0
- sage/schemes/projective/all.py +24 -0
- sage/schemes/projective/proj_bdd_height.py +453 -0
- sage/schemes/projective/projective_homset.py +718 -0
- sage/schemes/projective/projective_morphism.py +2792 -0
- sage/schemes/projective/projective_point.py +1484 -0
- sage/schemes/projective/projective_rational_point.py +569 -0
- sage/schemes/projective/projective_space.py +2571 -0
- sage/schemes/projective/projective_subscheme.py +1574 -0
- sage/sets/all.py +17 -0
- sage/sets/cartesian_product.py +376 -0
- sage/sets/condition_set.py +525 -0
- sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/disjoint_set.pxd +36 -0
- sage/sets/disjoint_set.pyx +998 -0
- sage/sets/disjoint_union_enumerated_sets.py +625 -0
- sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/family.pxd +12 -0
- sage/sets/family.pyx +1556 -0
- sage/sets/finite_enumerated_set.py +406 -0
- sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/finite_set_map_cy.pxd +34 -0
- sage/sets/finite_set_map_cy.pyx +708 -0
- sage/sets/finite_set_maps.py +591 -0
- sage/sets/image_set.py +448 -0
- sage/sets/integer_range.py +829 -0
- sage/sets/non_negative_integers.py +241 -0
- sage/sets/positive_integers.py +93 -0
- sage/sets/primes.py +188 -0
- sage/sets/real_set.py +2760 -0
- sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/sets/recursively_enumerated_set.pxd +31 -0
- sage/sets/recursively_enumerated_set.pyx +2082 -0
- sage/sets/set.py +2083 -0
- sage/sets/set_from_iterator.py +1021 -0
- sage/sets/totally_ordered_finite_set.py +329 -0
- sage/symbolic/all__sagemath_categories.py +1 -0
- sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/function.pxd +29 -0
- sage/symbolic/function.pyx +1488 -0
- sage/symbolic/symbols.py +56 -0
- sage/tests/all__sagemath_categories.py +1 -0
- sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/cython.pyx +37 -0
- sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/tests/stl_vector.pyx +171 -0
- sage/typeset/all.py +6 -0
- sage/typeset/ascii_art.py +295 -0
- sage/typeset/character_art.py +789 -0
- sage/typeset/character_art_factory.py +572 -0
- sage/typeset/symbols.py +334 -0
- sage/typeset/unicode_art.py +183 -0
- sage/typeset/unicode_characters.py +101 -0
|
@@ -0,0 +1,1811 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Finite residue fields
|
|
4
|
+
|
|
5
|
+
We can take the residue field of maximal ideals in the ring of integers
|
|
6
|
+
of number fields. We can also take the residue field of irreducible
|
|
7
|
+
polynomials over `\GF{p}`.
|
|
8
|
+
|
|
9
|
+
EXAMPLES::
|
|
10
|
+
|
|
11
|
+
sage: # needs sage.rings.number_field
|
|
12
|
+
sage: x = polygen(ZZ, 'x')
|
|
13
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
14
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
15
|
+
sage: k = K.residue_field(P); k
|
|
16
|
+
Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
|
|
17
|
+
sage: k.order()
|
|
18
|
+
841
|
|
19
|
+
|
|
20
|
+
We reduce mod a prime for which the ring of integers is not
|
|
21
|
+
monogenic (i.e., 2 is an essential discriminant divisor)::
|
|
22
|
+
|
|
23
|
+
sage: # needs sage.rings.number_field
|
|
24
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
|
25
|
+
sage: F = K.factor(2); F
|
|
26
|
+
(Fractional ideal (-1/2*a^2 + 1/2*a - 1)) * (Fractional ideal (a^2 - 2*a + 3)) * (Fractional ideal (-3/2*a^2 + 5/2*a - 4))
|
|
27
|
+
sage: F[0][0].residue_field()
|
|
28
|
+
Residue field of Fractional ideal (-1/2*a^2 + 1/2*a - 1)
|
|
29
|
+
sage: F[1][0].residue_field()
|
|
30
|
+
Residue field of Fractional ideal (a^2 - 2*a + 3)
|
|
31
|
+
sage: F[2][0].residue_field()
|
|
32
|
+
Residue field of Fractional ideal (-3/2*a^2 + 5/2*a - 4)
|
|
33
|
+
|
|
34
|
+
We can also form residue fields from `\ZZ`::
|
|
35
|
+
|
|
36
|
+
sage: ZZ.residue_field(17)
|
|
37
|
+
Residue field of Integers modulo 17
|
|
38
|
+
|
|
39
|
+
And for polynomial rings over finite fields::
|
|
40
|
+
|
|
41
|
+
sage: # needs sage.rings.finite_rings
|
|
42
|
+
sage: R.<t> = GF(5)[]
|
|
43
|
+
sage: I = R.ideal(t^2 + 2)
|
|
44
|
+
sage: k = ResidueField(I); k
|
|
45
|
+
Residue field in tbar of Principal ideal (t^2 + 2) of
|
|
46
|
+
Univariate Polynomial Ring in t over Finite Field of size 5
|
|
47
|
+
|
|
48
|
+
AUTHORS:
|
|
49
|
+
|
|
50
|
+
- David Roe (2007-10-3): initial version
|
|
51
|
+
- William Stein (2007-12): bug fixes
|
|
52
|
+
- John Cremona (2008-9): extend reduction maps to the whole valuation ring
|
|
53
|
+
add support for residue fields of ZZ
|
|
54
|
+
- David Roe (2009-12): added support for `GF(p)(t)` and moved to new coercion
|
|
55
|
+
framework.
|
|
56
|
+
|
|
57
|
+
TESTS::
|
|
58
|
+
|
|
59
|
+
sage: # needs sage.rings.number_field
|
|
60
|
+
sage: K.<z> = CyclotomicField(7)
|
|
61
|
+
sage: P = K.factor(17)[0][0]
|
|
62
|
+
sage: ff = K.residue_field(P)
|
|
63
|
+
sage: loads(dumps(ff)) is ff
|
|
64
|
+
True
|
|
65
|
+
sage: a = ff(z)
|
|
66
|
+
sage: parent(a*a)
|
|
67
|
+
Residue field in zbar of Fractional ideal (17)
|
|
68
|
+
sage: TestSuite(ff).run()
|
|
69
|
+
|
|
70
|
+
Verify that :issue:`15192` has been resolved::
|
|
71
|
+
|
|
72
|
+
sage: a.is_unit() # needs sage.rings.number_field
|
|
73
|
+
True
|
|
74
|
+
|
|
75
|
+
sage: # needs sage.rings.finite_rings
|
|
76
|
+
sage: R.<t> = GF(11)[]; P = R.ideal(t^3 + t + 4)
|
|
77
|
+
sage: ff.<a> = ResidueField(P)
|
|
78
|
+
sage: a == ff(t)
|
|
79
|
+
True
|
|
80
|
+
sage: parent(a*a)
|
|
81
|
+
Residue field in a of Principal ideal (t^3 + t + 4) of
|
|
82
|
+
Univariate Polynomial Ring in t over Finite Field of size 11
|
|
83
|
+
|
|
84
|
+
Verify that :issue:`7475` is fixed::
|
|
85
|
+
|
|
86
|
+
sage: K = ZZ.residue_field(2)
|
|
87
|
+
sage: loads(dumps(K)) is K
|
|
88
|
+
True
|
|
89
|
+
|
|
90
|
+
Reducing a curve modulo a prime::
|
|
91
|
+
|
|
92
|
+
sage: # needs sage.rings.number_field sage.schemes
|
|
93
|
+
sage: K.<s> = NumberField(x^2 + 23)
|
|
94
|
+
sage: OK = K.ring_of_integers()
|
|
95
|
+
sage: E = EllipticCurve([0,0,0,K(1),K(5)])
|
|
96
|
+
sage: pp = K.factor(13)[0][0]
|
|
97
|
+
sage: Fpp = OK.residue_field(pp)
|
|
98
|
+
sage: E.base_extend(Fpp)
|
|
99
|
+
Elliptic Curve defined by y^2 = x^3 + x + 5 over
|
|
100
|
+
Residue field of Fractional ideal (13, 1/2*s + 9/2)
|
|
101
|
+
|
|
102
|
+
sage: # needs sage.libs.pari sage.schemes
|
|
103
|
+
sage: R.<t> = GF(11)[]
|
|
104
|
+
sage: P = R.ideal(t^3 + t + 4)
|
|
105
|
+
sage: ff.<a> = R.residue_field(P)
|
|
106
|
+
sage: E = EllipticCurve([0,0,0,R(1),R(t)])
|
|
107
|
+
sage: E.base_extend(ff)
|
|
108
|
+
Elliptic Curve defined by y^2 = x^3 + x + a over
|
|
109
|
+
Residue field in a of Principal ideal (t^3 + t + 4) of
|
|
110
|
+
Univariate Polynomial Ring in t over Finite Field of size 11
|
|
111
|
+
|
|
112
|
+
Calculating Groebner bases over various residue fields.
|
|
113
|
+
First over a small non-prime field::
|
|
114
|
+
|
|
115
|
+
sage: # needs sage.rings.number_field
|
|
116
|
+
sage: F1.<u> = NumberField(x^6 + 6*x^5 + 124*x^4
|
|
117
|
+
....: + 452*x^3 + 4336*x^2 + 8200*x + 42316)
|
|
118
|
+
sage: reduct_id = F1.factor(47)[0][0]
|
|
119
|
+
sage: Rf = F1.residue_field(reduct_id)
|
|
120
|
+
sage: type(Rf)
|
|
121
|
+
<class 'sage.rings.finite_rings.residue_field_pari_ffelt.ResidueFiniteField_pari_ffelt_with_category'>
|
|
122
|
+
sage: Rf.cardinality().factor()
|
|
123
|
+
47^3
|
|
124
|
+
sage: R.<X, Y> = PolynomialRing(Rf)
|
|
125
|
+
sage: ubar = Rf(u)
|
|
126
|
+
sage: I = ideal([ubar*X + Y]); I
|
|
127
|
+
Ideal (ubar*X + Y) of Multivariate Polynomial Ring in X, Y over
|
|
128
|
+
Residue field in ubar of Fractional ideal
|
|
129
|
+
(47, 4841/93100*u^5 + 34451/139650*u^4 + 303697/69825*u^3
|
|
130
|
+
+ 297893/27930*u^2 + 1649764/23275*u + 2633506/69825)
|
|
131
|
+
sage: I.groebner_basis() # needs sage.libs.singular
|
|
132
|
+
[X + (-15*ubar^2 + 3*ubar - 2)*Y]
|
|
133
|
+
|
|
134
|
+
And now over a large prime field::
|
|
135
|
+
|
|
136
|
+
sage: # needs sage.rings.number_field
|
|
137
|
+
sage: x = ZZ['x'].0
|
|
138
|
+
sage: F1.<u> = NumberField(x^2 + 6*x + 324)
|
|
139
|
+
sage: reduct_id = F1.prime_above(next_prime(2^42))
|
|
140
|
+
sage: Rf = F1.residue_field(reduct_id)
|
|
141
|
+
sage: type(Rf)
|
|
142
|
+
<class 'sage.rings.finite_rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
|
|
143
|
+
sage: Rf.cardinality().factor()
|
|
144
|
+
4398046511119
|
|
145
|
+
sage: S.<X, Y, Z> = PolynomialRing(Rf, order='lex')
|
|
146
|
+
sage: I = ideal([2*X - Y^2, Y + Z])
|
|
147
|
+
sage: I.groebner_basis() # needs sage.libs.singular
|
|
148
|
+
[X + 2199023255559*Z^2, Y + Z]
|
|
149
|
+
sage: S.<X, Y, Z> = PolynomialRing(Rf, order='deglex')
|
|
150
|
+
sage: I = ideal([2*X - Y^2, Y + Z])
|
|
151
|
+
sage: I.groebner_basis() # needs sage.libs.singular
|
|
152
|
+
[Z^2 + 4398046511117*X, Y + Z]
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
# *****************************************************************************
|
|
156
|
+
# Copyright (C) 2007-2019 David Roe <roed@math.harvard.edu>
|
|
157
|
+
# 2007 William Stein <wstein@gmail.com>
|
|
158
|
+
# 2008 John Cremona
|
|
159
|
+
# 2008 Robert Bradshaw
|
|
160
|
+
# 2009 Nick Alexander
|
|
161
|
+
# 2010 Robert L. Miller
|
|
162
|
+
# 2010-2013 Simon King
|
|
163
|
+
# 2010-2017 Jeroen Demeyer
|
|
164
|
+
# 2012 Travis Scrimshaw
|
|
165
|
+
# 2016-2021 Frédéric Chapoton
|
|
166
|
+
# 2021-2022 Antonio Rojas
|
|
167
|
+
#
|
|
168
|
+
# This program is free software: you can redistribute it and/or modify
|
|
169
|
+
# it under the terms of the GNU General Public License as published by
|
|
170
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
171
|
+
# (at your option) any later version.
|
|
172
|
+
# https://www.gnu.org/licenses/
|
|
173
|
+
# *****************************************************************************
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
from sage.rings.ring cimport Field
|
|
177
|
+
from sage.rings.integer cimport Integer
|
|
178
|
+
from sage.rings.rational cimport Rational
|
|
179
|
+
from sage.categories.homset import Hom
|
|
180
|
+
from sage.categories.pushout import AlgebraicExtensionFunctor
|
|
181
|
+
from sage.rings.integer_ring import ZZ
|
|
182
|
+
from sage.rings.rational_field import QQ
|
|
183
|
+
from sage.rings.finite_rings.finite_field_constructor import zech_log_bound, FiniteField as GF
|
|
184
|
+
from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn
|
|
185
|
+
from sage.rings.ideal import Ideal_generic
|
|
186
|
+
from sage.rings.number_field.number_field_element_base import NumberFieldElement_base
|
|
187
|
+
from sage.rings.number_field.number_field_ideal import NumberFieldIdeal
|
|
188
|
+
|
|
189
|
+
from sage.rings.fraction_field import FractionField_generic
|
|
190
|
+
|
|
191
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
192
|
+
from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
|
|
193
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
194
|
+
|
|
195
|
+
from sage.structure.element cimport Element, parent, Vector
|
|
196
|
+
from sage.structure.factory import UniqueFactory
|
|
197
|
+
from sage.structure.richcmp cimport richcmp, richcmp_not_equal
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class ResidueFieldFactory(UniqueFactory):
|
|
201
|
+
"""
|
|
202
|
+
A factory that returns the residue class field of a prime ideal `p`
|
|
203
|
+
of the ring of integers of a number field, or of a polynomial ring
|
|
204
|
+
over a finite field.
|
|
205
|
+
|
|
206
|
+
INPUT:
|
|
207
|
+
|
|
208
|
+
- ``p`` -- a prime ideal of an order in a number field
|
|
209
|
+
|
|
210
|
+
- ``names`` -- the variable name for the finite field created;
|
|
211
|
+
defaults to the name of the number field variable but with
|
|
212
|
+
bar placed after it
|
|
213
|
+
|
|
214
|
+
- ``check`` -- whether or not to check if `p` is prime
|
|
215
|
+
|
|
216
|
+
OUTPUT: the residue field at the prime `p`
|
|
217
|
+
|
|
218
|
+
EXAMPLES::
|
|
219
|
+
|
|
220
|
+
sage: x = polygen(ZZ, 'x')
|
|
221
|
+
sage: K.<a> = NumberField(x^3 - 7) # needs sage.rings.number_field
|
|
222
|
+
sage: P = K.ideal(29).factor()[0][0] # needs sage.rings.number_field
|
|
223
|
+
sage: ResidueField(P) # needs sage.rings.number_field
|
|
224
|
+
Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
|
|
225
|
+
|
|
226
|
+
The result is cached::
|
|
227
|
+
|
|
228
|
+
sage: ResidueField(P) is ResidueField(P) # needs sage.rings.number_field
|
|
229
|
+
True
|
|
230
|
+
sage: k = K.residue_field(P); k # needs sage.rings.number_field
|
|
231
|
+
Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
|
|
232
|
+
sage: k.order() # needs sage.rings.number_field
|
|
233
|
+
841
|
|
234
|
+
|
|
235
|
+
It also works for polynomial rings::
|
|
236
|
+
|
|
237
|
+
sage: R.<t> = GF(31)[]
|
|
238
|
+
sage: P = R.ideal(t^5 + 2*t + 11)
|
|
239
|
+
sage: ResidueField(P) # needs sage.rings.finite_rings
|
|
240
|
+
Residue field in tbar of Principal ideal (t^5 + 2*t + 11) of
|
|
241
|
+
Univariate Polynomial Ring in t over Finite Field of size 31
|
|
242
|
+
|
|
243
|
+
sage: ResidueField(P) is ResidueField(P) # needs sage.rings.finite_rings
|
|
244
|
+
True
|
|
245
|
+
sage: k = ResidueField(P); k.order() # needs sage.rings.finite_rings
|
|
246
|
+
28629151
|
|
247
|
+
|
|
248
|
+
An example where the generator of the number field doesn't
|
|
249
|
+
generate the residue class field::
|
|
250
|
+
|
|
251
|
+
sage: # needs sage.rings.number_field
|
|
252
|
+
sage: K.<a> = NumberField(x^3 - 875)
|
|
253
|
+
sage: P = K.ideal(5).factor()[0][0]; k = K.residue_field(P); k
|
|
254
|
+
Residue field in abar of Fractional ideal (5, 1/25*a^2 - 2/5*a - 1)
|
|
255
|
+
sage: k.polynomial()
|
|
256
|
+
abar^2 + 3*abar + 4
|
|
257
|
+
sage: k.0^3 - 875
|
|
258
|
+
2
|
|
259
|
+
|
|
260
|
+
An example where the residue class field is large but of degree 1::
|
|
261
|
+
|
|
262
|
+
sage: # needs sage.rings.number_field
|
|
263
|
+
sage: K.<a> = NumberField(x^3 - 875)
|
|
264
|
+
sage: P = K.ideal(2007).factor()[2][0]; k = K.residue_field(P); k
|
|
265
|
+
Residue field of Fractional ideal (223, 1/5*a + 11)
|
|
266
|
+
sage: k(a)
|
|
267
|
+
168
|
|
268
|
+
sage: k(a)^3 - 875
|
|
269
|
+
0
|
|
270
|
+
|
|
271
|
+
And for polynomial rings::
|
|
272
|
+
|
|
273
|
+
sage: # needs sage.rings.finite_rings
|
|
274
|
+
sage: R.<t> = GF(next_prime(2^18))[]
|
|
275
|
+
sage: P = R.ideal(t - 5)
|
|
276
|
+
sage: k = ResidueField(P); k
|
|
277
|
+
Residue field of Principal ideal (t + 262142) of
|
|
278
|
+
Univariate Polynomial Ring in t over Finite Field of size 262147
|
|
279
|
+
sage: k(t)
|
|
280
|
+
5
|
|
281
|
+
|
|
282
|
+
In this example, 2 is an inessential discriminant divisor, so divides
|
|
283
|
+
the index of ``ZZ[a]`` in the maximal order for all ``a``::
|
|
284
|
+
|
|
285
|
+
sage: # needs sage.rings.number_field
|
|
286
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
|
287
|
+
sage: P = K.ideal(2).factor()[0][0]; P
|
|
288
|
+
Fractional ideal (-1/2*a^2 + 1/2*a - 1)
|
|
289
|
+
sage: F = K.residue_field(P); F
|
|
290
|
+
Residue field of Fractional ideal (-1/2*a^2 + 1/2*a - 1)
|
|
291
|
+
sage: F(a)
|
|
292
|
+
0
|
|
293
|
+
sage: B = K.maximal_order().basis(); B
|
|
294
|
+
[1, 1/2*a^2 + 1/2*a, a^2]
|
|
295
|
+
sage: F(B[1])
|
|
296
|
+
1
|
|
297
|
+
sage: F(B[2])
|
|
298
|
+
0
|
|
299
|
+
sage: F
|
|
300
|
+
Residue field of Fractional ideal (-1/2*a^2 + 1/2*a - 1)
|
|
301
|
+
sage: F.degree()
|
|
302
|
+
1
|
|
303
|
+
|
|
304
|
+
TESTS::
|
|
305
|
+
|
|
306
|
+
sage: K.<a> = NumberField(polygen(QQ)) # needs sage.rings.number_field
|
|
307
|
+
sage: K.residue_field(K.ideal(3)) # needs sage.rings.number_field
|
|
308
|
+
Residue field of Fractional ideal (3)
|
|
309
|
+
"""
|
|
310
|
+
def create_key_and_extra_args(self, p, names=None, check=True, impl=None, **kwds):
|
|
311
|
+
"""
|
|
312
|
+
Return a tuple containing the key (uniquely defining data)
|
|
313
|
+
and any extra arguments.
|
|
314
|
+
|
|
315
|
+
EXAMPLES::
|
|
316
|
+
|
|
317
|
+
sage: x = polygen(ZZ, 'x')
|
|
318
|
+
sage: K.<a> = NumberField(x^3 - 7) # needs sage.rings.number_field
|
|
319
|
+
sage: ResidueField(K.ideal(29).factor()[0][0]) # indirect doctest # needs sage.rings.number_field
|
|
320
|
+
Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
|
|
321
|
+
"""
|
|
322
|
+
if check:
|
|
323
|
+
if not isinstance(p, Ideal_generic):
|
|
324
|
+
if isinstance(p, (int, Integer, Rational)):
|
|
325
|
+
p = ZZ.ideal(p)
|
|
326
|
+
elif isinstance(p, NumberFieldElement_base):
|
|
327
|
+
if p.parent().is_field():
|
|
328
|
+
p = p.parent().ring_of_integers().ideal(p)
|
|
329
|
+
else:
|
|
330
|
+
p = p.parent().ideal(p)
|
|
331
|
+
elif isinstance(p, Polynomial):
|
|
332
|
+
p = p.parent().ideal(p)
|
|
333
|
+
#elif isinstance(p.parent(), FractionField_1poly_field):
|
|
334
|
+
# p = p.parent().ring_of_integers().ideal(p)
|
|
335
|
+
# will eventually support other function fields here.
|
|
336
|
+
else:
|
|
337
|
+
raise ValueError("p must be an ideal or element of a number field or function field.")
|
|
338
|
+
if not p.is_prime():
|
|
339
|
+
raise ValueError("p (%s) must be prime" % p)
|
|
340
|
+
if isinstance(p.ring(), PolynomialRing_generic):
|
|
341
|
+
if not p.ring().base_ring().is_finite():
|
|
342
|
+
raise ValueError("residue fields only supported for polynomial rings over finite fields")
|
|
343
|
+
if not p.ring().base_ring().is_prime_field():
|
|
344
|
+
# neither of these will work over non-prime fields quite yet. We should use relative finite field extensions.
|
|
345
|
+
raise NotImplementedError
|
|
346
|
+
elif not (isinstance(p, NumberFieldIdeal) or p.ring() is ZZ):
|
|
347
|
+
raise NotImplementedError
|
|
348
|
+
if isinstance(names, tuple):
|
|
349
|
+
if names:
|
|
350
|
+
names = str(names[0])
|
|
351
|
+
else:
|
|
352
|
+
names = None
|
|
353
|
+
if names is None and p.ring() is not ZZ:
|
|
354
|
+
names = '%sbar' % p.ring().fraction_field().variable_name()
|
|
355
|
+
key = (p, names, impl)
|
|
356
|
+
return key, kwds
|
|
357
|
+
|
|
358
|
+
def create_object(self, version, key, **kwds):
|
|
359
|
+
"""
|
|
360
|
+
Create the object from the key and extra arguments. This is only
|
|
361
|
+
called if the object was not found in the cache.
|
|
362
|
+
|
|
363
|
+
EXAMPLES::
|
|
364
|
+
|
|
365
|
+
sage: x = polygen(ZZ, 'x')
|
|
366
|
+
sage: K.<a> = NumberField(x^3 - 7) # needs sage.rings.number_field
|
|
367
|
+
sage: P = K.ideal(29).factor()[0][0] # needs sage.rings.number_field
|
|
368
|
+
sage: ResidueField(P) is ResidueField(P) # indirect doctest # needs sage.rings.number_field
|
|
369
|
+
True
|
|
370
|
+
"""
|
|
371
|
+
p, names, impl = key
|
|
372
|
+
pring = p.ring()
|
|
373
|
+
|
|
374
|
+
if pring is ZZ:
|
|
375
|
+
return ResidueFiniteField_prime_modn(p, names, p.gen(), None, None, None)
|
|
376
|
+
if isinstance(pring, PolynomialRing_generic):
|
|
377
|
+
K = pring.fraction_field()
|
|
378
|
+
Kbase = pring.base_ring()
|
|
379
|
+
f = p.gen()
|
|
380
|
+
characteristic = Kbase.order()
|
|
381
|
+
if f.degree() == 1 and Kbase.is_prime_field() and (impl is None or impl == 'modn'):
|
|
382
|
+
return ResidueFiniteField_prime_modn(p, None, Kbase.order(), None, None, None)
|
|
383
|
+
else:
|
|
384
|
+
q = characteristic**(f.degree())
|
|
385
|
+
if q < zech_log_bound and (impl is None or impl == 'givaro'):
|
|
386
|
+
try:
|
|
387
|
+
from sage.rings.finite_rings.residue_field_givaro import ResidueFiniteField_givaro
|
|
388
|
+
except ImportError:
|
|
389
|
+
if impl is not None:
|
|
390
|
+
raise
|
|
391
|
+
else:
|
|
392
|
+
return ResidueFiniteField_givaro(p, q, names, f, None, None, None)
|
|
393
|
+
if q % 2 == 0 and (impl is None or impl == 'ntl'):
|
|
394
|
+
try:
|
|
395
|
+
from sage.rings.finite_rings.residue_field_ntl_gf2e import ResidueFiniteField_ntl_gf2e
|
|
396
|
+
except ImportError:
|
|
397
|
+
if impl is not None:
|
|
398
|
+
raise
|
|
399
|
+
else:
|
|
400
|
+
return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, None, None, None)
|
|
401
|
+
if impl is None or impl == 'pari':
|
|
402
|
+
try:
|
|
403
|
+
from sage.rings.finite_rings.residue_field_pari_ffelt import ResidueFiniteField_pari_ffelt
|
|
404
|
+
except ImportError:
|
|
405
|
+
if impl is not None:
|
|
406
|
+
raise
|
|
407
|
+
else:
|
|
408
|
+
return ResidueFiniteField_pari_ffelt(p, characteristic, names, f, None, None, None)
|
|
409
|
+
raise ValueError("unrecognized finite field type")
|
|
410
|
+
|
|
411
|
+
# Should generalize to allowing residue fields of relative extensions to be extensions of finite fields.
|
|
412
|
+
if isinstance(p, NumberFieldIdeal):
|
|
413
|
+
characteristic = p.smallest_integer()
|
|
414
|
+
else: # ideal of a function field
|
|
415
|
+
characteristic = pring.base_ring().characteristic()
|
|
416
|
+
# Once we have function fields, we should probably have an if statement here.
|
|
417
|
+
K = pring.fraction_field()
|
|
418
|
+
#OK = K.maximal_order() # Need to change to p.order inside the __init__s for the residue fields.
|
|
419
|
+
|
|
420
|
+
U, to_vs, to_order = p._p_quotient(characteristic)
|
|
421
|
+
k = U.base_ring()
|
|
422
|
+
R = PolynomialRing(k, names)
|
|
423
|
+
n = p.residue_class_degree()
|
|
424
|
+
gen_ok = False
|
|
425
|
+
from sage.matrix.constructor import matrix
|
|
426
|
+
try:
|
|
427
|
+
x = K.gen()
|
|
428
|
+
if not x:
|
|
429
|
+
LL = [to_vs(1).list()] + [to_vs(x**i).list() for i in range(1,n+1)]
|
|
430
|
+
M = matrix(k, n+1, n, LL)
|
|
431
|
+
else:
|
|
432
|
+
M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
|
|
433
|
+
|
|
434
|
+
W = M.transpose().echelon_form()
|
|
435
|
+
if M.rank() == n:
|
|
436
|
+
PB = M.matrix_from_rows(range(n))
|
|
437
|
+
gen_ok = True
|
|
438
|
+
f = R((-W.column(n)).list() + [1])
|
|
439
|
+
except (TypeError, ZeroDivisionError):
|
|
440
|
+
pass
|
|
441
|
+
if not gen_ok:
|
|
442
|
+
bad = True
|
|
443
|
+
for u in U: # using this iterator may not be optimal, we may get a long string of non-generators
|
|
444
|
+
if u:
|
|
445
|
+
x = to_order(u)
|
|
446
|
+
M = matrix(k, n+1, n, [to_vs(x**i).list() for i in range(n+1)])
|
|
447
|
+
W = M.transpose().echelon_form()
|
|
448
|
+
if W.rank() == n:
|
|
449
|
+
f = R((-W.column(n)).list() + [1])
|
|
450
|
+
PB = M.matrix_from_rows(range(n))
|
|
451
|
+
bad = False
|
|
452
|
+
break
|
|
453
|
+
assert not bad, "error -- didn't find a generator."
|
|
454
|
+
# The reduction map is just x |--> k(to_vs(x) * (PB**(-1)))
|
|
455
|
+
# The lifting map is just x |--> to_order(x * PB)
|
|
456
|
+
# These are constructed inside the field __init__
|
|
457
|
+
if n == 1:
|
|
458
|
+
return ResidueFiniteField_prime_modn(p, names, p.smallest_integer(), to_vs, to_order, PB)
|
|
459
|
+
else:
|
|
460
|
+
q = characteristic**(f.degree())
|
|
461
|
+
if q < zech_log_bound and (impl is None or impl == 'givaro'):
|
|
462
|
+
try:
|
|
463
|
+
from sage.rings.finite_rings.residue_field_givaro import ResidueFiniteField_givaro
|
|
464
|
+
except ImportError:
|
|
465
|
+
if impl is not None:
|
|
466
|
+
raise
|
|
467
|
+
else:
|
|
468
|
+
return ResidueFiniteField_givaro(p, q, names, f, to_vs, to_order, PB)
|
|
469
|
+
elif q % 2 == 0 and (impl is None or impl == 'ntl'):
|
|
470
|
+
try:
|
|
471
|
+
from sage.rings.finite_rings.residue_field_ntl_gf2e import ResidueFiniteField_ntl_gf2e
|
|
472
|
+
except ImportError:
|
|
473
|
+
if impl is not None:
|
|
474
|
+
raise
|
|
475
|
+
else:
|
|
476
|
+
return ResidueFiniteField_ntl_gf2e(q, names, f, "poly", p, to_vs, to_order, PB)
|
|
477
|
+
if impl is None or impl == 'pari':
|
|
478
|
+
try:
|
|
479
|
+
from sage.rings.finite_rings.residue_field_pari_ffelt import ResidueFiniteField_pari_ffelt
|
|
480
|
+
except ImportError:
|
|
481
|
+
if impl is not None:
|
|
482
|
+
raise
|
|
483
|
+
else:
|
|
484
|
+
return ResidueFiniteField_pari_ffelt(p, characteristic, names, f, to_vs, to_order, PB)
|
|
485
|
+
raise ValueError("unrecognized finite field type")
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
ResidueField = ResidueFieldFactory("ResidueField")
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class ResidueField_generic(Field):
|
|
492
|
+
"""
|
|
493
|
+
The class representing a generic residue field.
|
|
494
|
+
|
|
495
|
+
EXAMPLES::
|
|
496
|
+
|
|
497
|
+
sage: # needs sage.rings.number_field
|
|
498
|
+
sage: I = QQ[i].factor(2)[0][0]; I
|
|
499
|
+
Fractional ideal (I - 1)
|
|
500
|
+
sage: k = I.residue_field(); k
|
|
501
|
+
Residue field of Fractional ideal (I - 1)
|
|
502
|
+
sage: type(k)
|
|
503
|
+
<class 'sage.rings.finite_rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
|
|
504
|
+
|
|
505
|
+
sage: # needs sage.rings.finite_rings
|
|
506
|
+
sage: R.<t> = GF(29)[]; P = R.ideal(t^2 + 2); k.<a> = ResidueField(P); k
|
|
507
|
+
Residue field in a of Principal ideal (t^2 + 2) of
|
|
508
|
+
Univariate Polynomial Ring in t over Finite Field of size 29
|
|
509
|
+
sage: type(k) # needs sage.libs.linbox
|
|
510
|
+
<class 'sage.rings.finite_rings.residue_field_givaro.ResidueFiniteField_givaro_with_category'>
|
|
511
|
+
"""
|
|
512
|
+
def __init__(self, p):
|
|
513
|
+
"""
|
|
514
|
+
.. WARNING::
|
|
515
|
+
|
|
516
|
+
This function does not call up the ``__init__`` chain, since many
|
|
517
|
+
residue fields use multiple inheritance and will be calling
|
|
518
|
+
``__init__`` via their other superclass.
|
|
519
|
+
|
|
520
|
+
If this is not the case, one should call ``Parent.__init__``
|
|
521
|
+
manually for any subclass.
|
|
522
|
+
|
|
523
|
+
INPUT:
|
|
524
|
+
|
|
525
|
+
- ``p`` -- the prime (ideal) defining this residue field
|
|
526
|
+
|
|
527
|
+
EXAMPLES::
|
|
528
|
+
|
|
529
|
+
sage: # needs sage.rings.number_field
|
|
530
|
+
sage: x = polygen(ZZ, 'x')
|
|
531
|
+
sage: K.<a> = NumberField(x^3 - 17)
|
|
532
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
533
|
+
sage: k = K.residue_field(P) # indirect doctest
|
|
534
|
+
|
|
535
|
+
sage: F = ZZ.residue_field(17) # indirect doctest
|
|
536
|
+
sage: F.category()
|
|
537
|
+
Join of Category of finite enumerated fields
|
|
538
|
+
and Category of subquotients of monoids
|
|
539
|
+
and Category of quotients of semigroups
|
|
540
|
+
|
|
541
|
+
sage: # needs sage.rings.finite_rings
|
|
542
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
543
|
+
sage: k.<a> = P.residue_field() # indirect doctest
|
|
544
|
+
sage: k.category()
|
|
545
|
+
Category of finite enumerated fields
|
|
546
|
+
|
|
547
|
+
TESTS::
|
|
548
|
+
|
|
549
|
+
sage: TestSuite(F).run()
|
|
550
|
+
|
|
551
|
+
sage: # needs sage.modules sage.rings.finite_rings
|
|
552
|
+
sage: TestSuite(k).run()
|
|
553
|
+
"""
|
|
554
|
+
self.p = p
|
|
555
|
+
# Note: we don't call Parent.__init__ since many residue fields use multiple inheritance and will be calling __init__ via their other superclass.
|
|
556
|
+
|
|
557
|
+
def construction(self):
|
|
558
|
+
"""
|
|
559
|
+
Construction of this residue field.
|
|
560
|
+
|
|
561
|
+
OUTPUT:
|
|
562
|
+
|
|
563
|
+
An :class:`~sage.categories.pushout.AlgebraicExtensionFunctor` and the
|
|
564
|
+
number field that this residue field has been obtained from.
|
|
565
|
+
|
|
566
|
+
The residue field is determined by a prime (fractional) ideal in a
|
|
567
|
+
number field. If this ideal can be coerced into a different number
|
|
568
|
+
field, then the construction functor applied to this number field will
|
|
569
|
+
return the corresponding residue field. See :issue:`15223`.
|
|
570
|
+
|
|
571
|
+
EXAMPLES::
|
|
572
|
+
|
|
573
|
+
sage: # needs sage.rings.number_field
|
|
574
|
+
sage: K.<z> = CyclotomicField(7)
|
|
575
|
+
sage: P = K.factor(17)[0][0]
|
|
576
|
+
sage: k = K.residue_field(P); k
|
|
577
|
+
Residue field in zbar of Fractional ideal (17)
|
|
578
|
+
sage: F, R = k.construction()
|
|
579
|
+
sage: F
|
|
580
|
+
AlgebraicExtensionFunctor
|
|
581
|
+
sage: R
|
|
582
|
+
Cyclotomic Field of order 7 and degree 6
|
|
583
|
+
sage: F(R) is k
|
|
584
|
+
True
|
|
585
|
+
sage: F(ZZ)
|
|
586
|
+
Residue field of Integers modulo 17
|
|
587
|
+
sage: F(CyclotomicField(49))
|
|
588
|
+
Residue field in zbar of Fractional ideal (17)
|
|
589
|
+
"""
|
|
590
|
+
return AlgebraicExtensionFunctor([self.polynomial()], [self.variable_name()], [None], residue=self.p), self.p.ring()
|
|
591
|
+
|
|
592
|
+
def ideal(self):
|
|
593
|
+
r"""
|
|
594
|
+
Return the maximal ideal that this residue field is the quotient by.
|
|
595
|
+
|
|
596
|
+
EXAMPLES::
|
|
597
|
+
|
|
598
|
+
sage: # needs sage.rings.number_field
|
|
599
|
+
sage: x = polygen(ZZ, 'x')
|
|
600
|
+
sage: K.<a> = NumberField(x^3 + x + 1)
|
|
601
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
602
|
+
sage: k = K.residue_field(P) # indirect doctest
|
|
603
|
+
sage: k.ideal() is P
|
|
604
|
+
True
|
|
605
|
+
sage: p = next_prime(2^40); p
|
|
606
|
+
1099511627791
|
|
607
|
+
sage: k = K.residue_field(K.prime_above(p))
|
|
608
|
+
sage: k.ideal().norm() == p
|
|
609
|
+
True
|
|
610
|
+
|
|
611
|
+
sage: # needs sage.rings.finite_rings
|
|
612
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
613
|
+
sage: k.<a> = R.residue_field(P)
|
|
614
|
+
sage: k.ideal()
|
|
615
|
+
Principal ideal (t^3 + t^2 + 7) of
|
|
616
|
+
Univariate Polynomial Ring in t over Finite Field of size 17
|
|
617
|
+
"""
|
|
618
|
+
return self.p
|
|
619
|
+
|
|
620
|
+
def _element_constructor_(self, x):
|
|
621
|
+
"""
|
|
622
|
+
This is called after ``x`` fails to convert into ``self`` as
|
|
623
|
+
abstract finite field (without considering the underlying
|
|
624
|
+
number field).
|
|
625
|
+
|
|
626
|
+
So the strategy is to try to convert into the number field,
|
|
627
|
+
and then proceed to the residue field.
|
|
628
|
+
|
|
629
|
+
.. NOTE::
|
|
630
|
+
|
|
631
|
+
The behaviour of this method was changed in :issue:`8800`.
|
|
632
|
+
Before, an error was raised if there was no coercion. Now,
|
|
633
|
+
a conversion is possible even when there is no coercion.
|
|
634
|
+
This is like for different finite fields.
|
|
635
|
+
|
|
636
|
+
EXAMPLES::
|
|
637
|
+
|
|
638
|
+
sage: # needs sage.rings.number_field
|
|
639
|
+
sage: from sage.rings.finite_rings.residue_field import ResidueField_generic
|
|
640
|
+
sage: x = polygen(ZZ, 'x')
|
|
641
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
|
642
|
+
sage: P = K.ideal(-3*i - 2)
|
|
643
|
+
sage: OK = K.maximal_order()
|
|
644
|
+
sage: F = OK.residue_field(P)
|
|
645
|
+
sage: ResidueField_generic._element_constructor_(F, i)
|
|
646
|
+
8
|
|
647
|
+
|
|
648
|
+
With :issue:`8800`, we also have::
|
|
649
|
+
|
|
650
|
+
sage: ResidueField_generic._element_constructor_(F, GF(13)(8)) # needs sage.rings.number_field
|
|
651
|
+
8
|
|
652
|
+
|
|
653
|
+
Here is a test that was temporarily removed, but newly introduced
|
|
654
|
+
in :issue:`8800`::
|
|
655
|
+
|
|
656
|
+
sage: # needs sage.rings.finite_rings
|
|
657
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
658
|
+
sage: k.<a> = P.residue_field()
|
|
659
|
+
sage: k(t)
|
|
660
|
+
a
|
|
661
|
+
sage: k(GF(17)(4))
|
|
662
|
+
4
|
|
663
|
+
"""
|
|
664
|
+
K = OK = self.p.ring()
|
|
665
|
+
R = parent(x)
|
|
666
|
+
if OK.is_field():
|
|
667
|
+
OK = OK.ring_of_integers()
|
|
668
|
+
else:
|
|
669
|
+
K = K.fraction_field()
|
|
670
|
+
if OK.has_coerce_map_from(R):
|
|
671
|
+
x = OK(x)
|
|
672
|
+
elif K.has_coerce_map_from(R):
|
|
673
|
+
x = K(x)
|
|
674
|
+
else:
|
|
675
|
+
try:
|
|
676
|
+
x = K(x)
|
|
677
|
+
except (TypeError, ValueError):
|
|
678
|
+
raise TypeError("cannot coerce %s" % type(x))
|
|
679
|
+
return self(x)
|
|
680
|
+
|
|
681
|
+
def _coerce_map_from_(self, R):
|
|
682
|
+
"""
|
|
683
|
+
Return ``True`` if there is a coercion map from ``R`` to ``self``.
|
|
684
|
+
|
|
685
|
+
EXAMPLES::
|
|
686
|
+
|
|
687
|
+
sage: # needs sage.rings.number_field
|
|
688
|
+
sage: x = polygen(ZZ, 'x')
|
|
689
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
|
690
|
+
sage: P = K.ideal(-3*i - 2)
|
|
691
|
+
sage: OK = K.maximal_order()
|
|
692
|
+
sage: F = OK.residue_field(P)
|
|
693
|
+
sage: F.has_coerce_map_from(GF(13)) # indirect doctest
|
|
694
|
+
True
|
|
695
|
+
|
|
696
|
+
TESTS:
|
|
697
|
+
|
|
698
|
+
Check that :issue:`11319` is fixed::
|
|
699
|
+
|
|
700
|
+
sage: GF(13).has_coerce_map_from(F) # needs sage.rings.number_field
|
|
701
|
+
True
|
|
702
|
+
|
|
703
|
+
sage: # needs sage.rings.number_field
|
|
704
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
705
|
+
sage: k.<a> = P.residue_field()
|
|
706
|
+
sage: k.has_coerce_map_from(Qp(17)) # indirect doctest # needs sage.rings.padics
|
|
707
|
+
False
|
|
708
|
+
"""
|
|
709
|
+
OK = self.p.ring()
|
|
710
|
+
if OK.is_field():
|
|
711
|
+
OK = OK.ring_of_integers()
|
|
712
|
+
return self.base_ring().has_coerce_map_from(R) or OK.has_coerce_map_from(R)
|
|
713
|
+
|
|
714
|
+
def __repr__(self) -> str:
|
|
715
|
+
"""
|
|
716
|
+
Return a string describing this residue field.
|
|
717
|
+
|
|
718
|
+
EXAMPLES::
|
|
719
|
+
|
|
720
|
+
sage: # needs sage.rings.number_field
|
|
721
|
+
sage: x = polygen(ZZ, 'x')
|
|
722
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
723
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
724
|
+
sage: k = K.residue_field(P); k
|
|
725
|
+
Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
|
|
726
|
+
|
|
727
|
+
sage: F = ZZ.residue_field(17); F
|
|
728
|
+
Residue field of Integers modulo 17
|
|
729
|
+
|
|
730
|
+
sage: # needs sage.rings.finite_rings
|
|
731
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
732
|
+
sage: k.<a> = P.residue_field(); k # indirect doctest
|
|
733
|
+
Residue field in a of Principal ideal (t^3 + t^2 + 7) of
|
|
734
|
+
Univariate Polynomial Ring in t over Finite Field of size 17
|
|
735
|
+
"""
|
|
736
|
+
if self.p.ring() is ZZ:
|
|
737
|
+
return "Residue field of Integers modulo %s" % self.p.gen()
|
|
738
|
+
return "Residue field %sof %s" % ('in %s ' % self.gen() if self.degree() > 1 else '', self.p)
|
|
739
|
+
|
|
740
|
+
def lift(self, x):
|
|
741
|
+
"""
|
|
742
|
+
Return a lift of ``x`` to the Order, returning a "polynomial" in the
|
|
743
|
+
generator with coefficients between 0 and `p-1`.
|
|
744
|
+
|
|
745
|
+
EXAMPLES::
|
|
746
|
+
|
|
747
|
+
sage: # needs sage.rings.number_field
|
|
748
|
+
sage: x = polygen(ZZ, 'x')
|
|
749
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
750
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
751
|
+
sage: k = K.residue_field(P)
|
|
752
|
+
sage: OK = K.maximal_order()
|
|
753
|
+
sage: c = OK(a)
|
|
754
|
+
sage: b = k(a)
|
|
755
|
+
sage: k.lift(13*b + 5)
|
|
756
|
+
13*a + 5
|
|
757
|
+
sage: k.lift(12821*b + 918)
|
|
758
|
+
3*a + 19
|
|
759
|
+
|
|
760
|
+
sage: # needs sage.rings.finite_rings
|
|
761
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
762
|
+
sage: k.<a> = P.residue_field()
|
|
763
|
+
sage: k.lift(a^2 + 5)
|
|
764
|
+
t^2 + 5
|
|
765
|
+
"""
|
|
766
|
+
if hasattr(self.p, "ring"):
|
|
767
|
+
R = self.p.ring()
|
|
768
|
+
if R.is_field():
|
|
769
|
+
R = R.ring_of_integers()
|
|
770
|
+
return R(x)
|
|
771
|
+
else:
|
|
772
|
+
return x.lift()
|
|
773
|
+
|
|
774
|
+
def reduction_map(self):
|
|
775
|
+
"""
|
|
776
|
+
Return the partially defined reduction map from the number
|
|
777
|
+
field to this residue class field.
|
|
778
|
+
|
|
779
|
+
EXAMPLES::
|
|
780
|
+
|
|
781
|
+
sage: # needs fpylll sage.rings.number_field sage.symbolic
|
|
782
|
+
sage: I = QQ[2^(1/3)].factor(2)[0][0]; I
|
|
783
|
+
Fractional ideal (a)
|
|
784
|
+
sage: k = I.residue_field(); k
|
|
785
|
+
Residue field of Fractional ideal (a)
|
|
786
|
+
sage: pi = k.reduction_map(); pi
|
|
787
|
+
Partially defined reduction map:
|
|
788
|
+
From: Number Field in a with defining polynomial x^3 - 2
|
|
789
|
+
with a = 1.259921049894873?
|
|
790
|
+
To: Residue field of Fractional ideal (a)
|
|
791
|
+
sage: pi.domain()
|
|
792
|
+
Number Field in a with defining polynomial x^3 - 2 with a = 1.259921049894873?
|
|
793
|
+
sage: pi.codomain()
|
|
794
|
+
Residue field of Fractional ideal (a)
|
|
795
|
+
|
|
796
|
+
sage: # needs sage.rings.number_field
|
|
797
|
+
sage: x = polygen(ZZ, 'x')
|
|
798
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 32)
|
|
799
|
+
sage: F = K.factor(2)[0][0].residue_field()
|
|
800
|
+
sage: F.reduction_map().domain()
|
|
801
|
+
Number Field in a with defining polynomial x^3 + x^2 - 2*x + 32
|
|
802
|
+
sage: K.<a> = NumberField(x^3 + 128)
|
|
803
|
+
sage: F = K.factor(2)[0][0].residue_field()
|
|
804
|
+
sage: F.reduction_map().codomain()
|
|
805
|
+
Residue field of Fractional ideal (1/4*a)
|
|
806
|
+
|
|
807
|
+
sage: # needs sage.rings.finite_rings
|
|
808
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
809
|
+
sage: k.<a> = P.residue_field(); f = k.reduction_map(); f
|
|
810
|
+
Partially defined reduction map:
|
|
811
|
+
From: Fraction Field of Univariate Polynomial Ring in t
|
|
812
|
+
over Finite Field of size 17
|
|
813
|
+
To: Residue field in a of Principal ideal (t^3 + t^2 + 7) of
|
|
814
|
+
Univariate Polynomial Ring in t over Finite Field of size 17
|
|
815
|
+
sage: f(1/t)
|
|
816
|
+
12*a^2 + 12*a
|
|
817
|
+
"""
|
|
818
|
+
return self.convert_map_from(self.p.ring().fraction_field())
|
|
819
|
+
|
|
820
|
+
def lift_map(self):
|
|
821
|
+
"""
|
|
822
|
+
Return the standard map from this residue field up to the ring of
|
|
823
|
+
integers lifting the canonical projection.
|
|
824
|
+
|
|
825
|
+
EXAMPLES::
|
|
826
|
+
|
|
827
|
+
sage: # needs fpylll sage.rings.number_field sage.symbolic
|
|
828
|
+
sage: I = QQ[3^(1/3)].factor(5)[1][0]; I
|
|
829
|
+
Fractional ideal (a - 2)
|
|
830
|
+
sage: k = I.residue_field(); k
|
|
831
|
+
Residue field of Fractional ideal (a - 2)
|
|
832
|
+
sage: f = k.lift_map(); f
|
|
833
|
+
Lifting map:
|
|
834
|
+
From: Residue field of Fractional ideal (a - 2)
|
|
835
|
+
To: Maximal Order generated by a in Number Field in a
|
|
836
|
+
with defining polynomial x^3 - 3 with a = 1.442249570307409?
|
|
837
|
+
sage: f.domain()
|
|
838
|
+
Residue field of Fractional ideal (a - 2)
|
|
839
|
+
sage: f.codomain()
|
|
840
|
+
Maximal Order generated by a in Number Field in a
|
|
841
|
+
with defining polynomial x^3 - 3 with a = 1.442249570307409?
|
|
842
|
+
sage: f(k.0)
|
|
843
|
+
1
|
|
844
|
+
|
|
845
|
+
sage: # needs sage.rings.finite_rings
|
|
846
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
847
|
+
sage: k.<a> = P.residue_field()
|
|
848
|
+
sage: f = k.lift_map(); f
|
|
849
|
+
(map internal to coercion system -- copy before use)
|
|
850
|
+
Lifting map:
|
|
851
|
+
From: Residue field in a of Principal ideal (t^3 + t^2 + 7) of
|
|
852
|
+
Univariate Polynomial Ring in t over Finite Field of size 17
|
|
853
|
+
To: Univariate Polynomial Ring in t over Finite Field of size 17
|
|
854
|
+
sage: f(a^2 + 5)
|
|
855
|
+
t^2 + 5
|
|
856
|
+
"""
|
|
857
|
+
OK = self.p.ring()
|
|
858
|
+
if OK.is_field():
|
|
859
|
+
OK = OK.ring_of_integers()
|
|
860
|
+
return self._internal_coerce_map_from(OK).section()
|
|
861
|
+
|
|
862
|
+
def _richcmp_(self, x, op):
|
|
863
|
+
"""
|
|
864
|
+
Compare two residue fields: they are equal iff the primes
|
|
865
|
+
defining them are equal and they have the same variable name.
|
|
866
|
+
|
|
867
|
+
EXAMPLES::
|
|
868
|
+
|
|
869
|
+
sage: # needs sage.rings.number_field
|
|
870
|
+
sage: x = polygen(ZZ, 'x')
|
|
871
|
+
sage: K.<a> = NumberField(x^3 - 11)
|
|
872
|
+
sage: F = K.ideal(37).factor(); F
|
|
873
|
+
(Fractional ideal (37, a + 9)) * (Fractional ideal (37, a + 12)) * (Fractional ideal (-2*a + 5))
|
|
874
|
+
sage: k = K.residue_field(F[0][0])
|
|
875
|
+
sage: l = K.residue_field(F[1][0])
|
|
876
|
+
sage: k == l
|
|
877
|
+
False
|
|
878
|
+
|
|
879
|
+
sage: # needs sage.rings.finite_rings
|
|
880
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
881
|
+
sage: k.<a> = P.residue_field()
|
|
882
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 11)
|
|
883
|
+
sage: l.<b> = P.residue_field()
|
|
884
|
+
sage: k == l
|
|
885
|
+
False
|
|
886
|
+
sage: ll.<c> = P.residue_field()
|
|
887
|
+
sage: ll == l
|
|
888
|
+
False
|
|
889
|
+
"""
|
|
890
|
+
if not isinstance(x, ResidueField_generic):
|
|
891
|
+
return NotImplemented
|
|
892
|
+
lp = self.p
|
|
893
|
+
rp = x.p
|
|
894
|
+
if lp != rp:
|
|
895
|
+
return richcmp_not_equal(lp, rp, op)
|
|
896
|
+
return richcmp(self.variable_name(), x.variable_name(), op)
|
|
897
|
+
|
|
898
|
+
def __hash__(self):
|
|
899
|
+
r"""
|
|
900
|
+
Return the hash of ``self``.
|
|
901
|
+
|
|
902
|
+
EXAMPLES::
|
|
903
|
+
|
|
904
|
+
sage: # needs sage.rings.number_field
|
|
905
|
+
sage: x = polygen(ZZ, 'x')
|
|
906
|
+
sage: K.<a> = NumberField(x^3 + x + 1)
|
|
907
|
+
sage: hash(K.residue_field(K.prime_above(17))) # random
|
|
908
|
+
-6463132282686559142
|
|
909
|
+
sage: hash(K.residue_field(K.prime_above(2^60))) # random
|
|
910
|
+
-6939519969600666586
|
|
911
|
+
|
|
912
|
+
sage: # needs sage.rings.finite_rings
|
|
913
|
+
sage: R.<t> = GF(13)[]
|
|
914
|
+
sage: hash(R.residue_field(t + 2)) # random
|
|
915
|
+
3521289879659800254
|
|
916
|
+
"""
|
|
917
|
+
return 1 + hash(self.ideal())
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
cdef class ReductionMap(Map):
|
|
921
|
+
"""
|
|
922
|
+
A reduction map from a (subset) of a number field or function field to
|
|
923
|
+
this residue class field.
|
|
924
|
+
|
|
925
|
+
It will be defined on those elements of the field with nonnegative
|
|
926
|
+
valuation at the specified prime.
|
|
927
|
+
|
|
928
|
+
EXAMPLES::
|
|
929
|
+
|
|
930
|
+
sage: # needs fpylll sage.rings.number_field sage.symbolic
|
|
931
|
+
sage: I = QQ[sqrt(17)].factor(5)[0][0]; I
|
|
932
|
+
Fractional ideal (5)
|
|
933
|
+
sage: k = I.residue_field(); k
|
|
934
|
+
Residue field in sqrt17bar of Fractional ideal (5)
|
|
935
|
+
sage: R = k.reduction_map(); R
|
|
936
|
+
Partially defined reduction map:
|
|
937
|
+
From: Number Field in sqrt17 with defining polynomial x^2 - 17
|
|
938
|
+
with sqrt17 = 4.123105625617660?
|
|
939
|
+
To: Residue field in sqrt17bar of Fractional ideal (5)
|
|
940
|
+
|
|
941
|
+
sage: # needs sage.rings.finite_rings
|
|
942
|
+
sage: R.<t> = GF(next_prime(2^20))[]; P = R.ideal(t^2 + t + 1)
|
|
943
|
+
sage: k = P.residue_field()
|
|
944
|
+
sage: k.reduction_map()
|
|
945
|
+
Partially defined reduction map:
|
|
946
|
+
From: Fraction Field of
|
|
947
|
+
Univariate Polynomial Ring in t over Finite Field of size 1048583
|
|
948
|
+
To: Residue field in tbar of Principal ideal (t^2 + t + 1) of
|
|
949
|
+
Univariate Polynomial Ring in t over Finite Field of size 1048583
|
|
950
|
+
"""
|
|
951
|
+
def __init__(self, K, F, to_vs, to_order, PB, PBinv):
|
|
952
|
+
"""
|
|
953
|
+
Create a reduction map.
|
|
954
|
+
|
|
955
|
+
EXAMPLES::
|
|
956
|
+
|
|
957
|
+
sage: # needs sage.rings.number_field
|
|
958
|
+
sage: x = polygen(ZZ, 'x')
|
|
959
|
+
sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
|
|
960
|
+
sage: F = K.factor(2)[0][0].residue_field()
|
|
961
|
+
sage: F.reduction_map()
|
|
962
|
+
Partially defined reduction map:
|
|
963
|
+
From: Number Field in a with defining polynomial x^3 + x^2 - 2*x + 8
|
|
964
|
+
To: Residue field of Fractional ideal (-1/2*a^2 + 1/2*a - 1)
|
|
965
|
+
|
|
966
|
+
sage: # needs sage.rings.number_field
|
|
967
|
+
sage: K.<theta_5> = CyclotomicField(5)
|
|
968
|
+
sage: F = K.factor(7)[0][0].residue_field()
|
|
969
|
+
sage: F.reduction_map()
|
|
970
|
+
Partially defined reduction map:
|
|
971
|
+
From: Cyclotomic Field of order 5 and degree 4
|
|
972
|
+
To: Residue field in theta_5bar of Fractional ideal (7)
|
|
973
|
+
|
|
974
|
+
sage: # needs sage.rings.finite_rings
|
|
975
|
+
sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
|
|
976
|
+
sage: k = P.residue_field()
|
|
977
|
+
sage: k.reduction_map() # needs sage.libs.ntl
|
|
978
|
+
Partially defined reduction map:
|
|
979
|
+
From: Fraction Field of
|
|
980
|
+
Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X)
|
|
981
|
+
To: Residue field in tbar of Principal ideal (t^7 + t^6 + t^5 + t^4 + 1) of
|
|
982
|
+
Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X)
|
|
983
|
+
sage: type(k) # needs sage.libs.linbox
|
|
984
|
+
<class 'sage.rings.finite_rings.residue_field_givaro.ResidueFiniteField_givaro_with_category'>
|
|
985
|
+
"""
|
|
986
|
+
self._K = K
|
|
987
|
+
self._F = F # finite field
|
|
988
|
+
self._to_vs = to_vs
|
|
989
|
+
self._PBinv = PBinv
|
|
990
|
+
self._to_order = to_order # used for lift
|
|
991
|
+
self._PB = PB # used for lift
|
|
992
|
+
from sage.categories.sets_with_partial_maps import SetsWithPartialMaps
|
|
993
|
+
self._repr_type_str = "Partially defined reduction"
|
|
994
|
+
Map.__init__(self, Hom(K, F, SetsWithPartialMaps()))
|
|
995
|
+
|
|
996
|
+
cdef dict _extra_slots(self):
|
|
997
|
+
"""
|
|
998
|
+
Helper for copying and pickling.
|
|
999
|
+
|
|
1000
|
+
EXAMPLES::
|
|
1001
|
+
|
|
1002
|
+
sage: # needs sage.rings.number_field
|
|
1003
|
+
sage: x = polygen(ZZ, 'x')
|
|
1004
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
|
1005
|
+
sage: F = K.factor(2)[0][0].residue_field()
|
|
1006
|
+
sage: r = F.reduction_map()
|
|
1007
|
+
sage: cr = copy(r) # indirect doctest
|
|
1008
|
+
sage: cr
|
|
1009
|
+
Partially defined reduction map:
|
|
1010
|
+
From: Number Field in a with defining polynomial x^2 + 1
|
|
1011
|
+
To: Residue field of Fractional ideal (a - 1)
|
|
1012
|
+
sage: cr == r # not implemented
|
|
1013
|
+
True
|
|
1014
|
+
sage: r(2 + a) == cr(2 + a)
|
|
1015
|
+
True
|
|
1016
|
+
"""
|
|
1017
|
+
slots = Map._extra_slots(self)
|
|
1018
|
+
slots['_K'] = self._K
|
|
1019
|
+
slots['_F'] = self._F
|
|
1020
|
+
slots['_to_vs'] = self._to_vs
|
|
1021
|
+
slots['_PBinv'] = self._PBinv
|
|
1022
|
+
slots['_to_order'] = self._to_order
|
|
1023
|
+
slots['_PB'] = self._PB
|
|
1024
|
+
slots['_section'] = self._section
|
|
1025
|
+
return slots
|
|
1026
|
+
|
|
1027
|
+
cdef _update_slots(self, dict _slots):
|
|
1028
|
+
"""
|
|
1029
|
+
Helper for copying and pickling.
|
|
1030
|
+
|
|
1031
|
+
EXAMPLES::
|
|
1032
|
+
|
|
1033
|
+
sage: # needs sage.rings.number_field
|
|
1034
|
+
sage: x = polygen(ZZ, 'x')
|
|
1035
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
|
1036
|
+
sage: F = K.factor(2)[0][0].residue_field()
|
|
1037
|
+
sage: r = F.reduction_map()
|
|
1038
|
+
sage: cr = copy(r) # indirect doctest
|
|
1039
|
+
sage: cr
|
|
1040
|
+
Partially defined reduction map:
|
|
1041
|
+
From: Number Field in a with defining polynomial x^2 + 1
|
|
1042
|
+
To: Residue field of Fractional ideal (a - 1)
|
|
1043
|
+
sage: cr == r # not implemented
|
|
1044
|
+
True
|
|
1045
|
+
sage: r(2 + a) == cr(2 + a)
|
|
1046
|
+
True
|
|
1047
|
+
"""
|
|
1048
|
+
Map._update_slots(self, _slots)
|
|
1049
|
+
self._K = _slots['_K']
|
|
1050
|
+
self._F = _slots['_F']
|
|
1051
|
+
self._to_vs = _slots['_to_vs']
|
|
1052
|
+
self._PBinv = _slots['_PBinv']
|
|
1053
|
+
self._to_order = _slots['_to_order']
|
|
1054
|
+
self._PB = _slots['_PB']
|
|
1055
|
+
self._section = _slots['_section']
|
|
1056
|
+
|
|
1057
|
+
cpdef Element _call_(self, x):
|
|
1058
|
+
"""
|
|
1059
|
+
Apply this reduction map to an element that coerces into the global
|
|
1060
|
+
field.
|
|
1061
|
+
|
|
1062
|
+
If ``x`` doesn't map because it has negative valuation, then a
|
|
1063
|
+
:exc:`ZeroDivisionError` exception is raised.
|
|
1064
|
+
|
|
1065
|
+
EXAMPLES::
|
|
1066
|
+
|
|
1067
|
+
sage: # needs sage.rings.number_field
|
|
1068
|
+
sage: x = polygen(ZZ, 'x')
|
|
1069
|
+
sage: K.<a> = NumberField(x^2 + 1)
|
|
1070
|
+
sage: F = K.factor(2)[0][0].residue_field()
|
|
1071
|
+
sage: r = F.reduction_map(); r
|
|
1072
|
+
Partially defined reduction map:
|
|
1073
|
+
From: Number Field in a with defining polynomial x^2 + 1
|
|
1074
|
+
To: Residue field of Fractional ideal (a - 1)
|
|
1075
|
+
|
|
1076
|
+
We test that calling the function also works after copying::
|
|
1077
|
+
|
|
1078
|
+
sage: # needs sage.rings.number_field
|
|
1079
|
+
sage: r = copy(r)
|
|
1080
|
+
sage: r(2 + a) # indirect doctest
|
|
1081
|
+
1
|
|
1082
|
+
sage: r(a/2)
|
|
1083
|
+
Traceback (most recent call last):
|
|
1084
|
+
...
|
|
1085
|
+
ZeroDivisionError: Cannot reduce field element 1/2*a
|
|
1086
|
+
modulo Fractional ideal (a - 1): it has negative valuation
|
|
1087
|
+
|
|
1088
|
+
sage: # needs sage.rings.finite_rings
|
|
1089
|
+
sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
|
|
1090
|
+
sage: k.<a> = R.residue_field(h)
|
|
1091
|
+
sage: K = R.fraction_field()
|
|
1092
|
+
sage: f = k.convert_map_from(K)
|
|
1093
|
+
sage: type(f)
|
|
1094
|
+
<class 'sage.rings.finite_rings.residue_field.ReductionMap'>
|
|
1095
|
+
sage: f(1/t)
|
|
1096
|
+
a^4 + a
|
|
1097
|
+
sage: f(1/h)
|
|
1098
|
+
Traceback (most recent call last):
|
|
1099
|
+
...
|
|
1100
|
+
ZeroDivisionError...
|
|
1101
|
+
|
|
1102
|
+
An example to show that the issue raised in :issue:`1951`
|
|
1103
|
+
has been fixed::
|
|
1104
|
+
|
|
1105
|
+
sage: # needs sage.rings.number_field
|
|
1106
|
+
sage: K.<i> = NumberField(x^2 + 1)
|
|
1107
|
+
sage: P1, P2 = [g[0] for g in K.factor(5)]; P1, P2
|
|
1108
|
+
(Fractional ideal (2*i - 1), Fractional ideal (-2*i - 1))
|
|
1109
|
+
sage: a = 1/(1+2*i)
|
|
1110
|
+
sage: F1, F2 = [g.residue_field() for g in [P1,P2]]; F1, F2
|
|
1111
|
+
(Residue field of Fractional ideal (2*i - 1),
|
|
1112
|
+
Residue field of Fractional ideal (-2*i - 1))
|
|
1113
|
+
sage: a.valuation(P1)
|
|
1114
|
+
0
|
|
1115
|
+
sage: F1(i/7)
|
|
1116
|
+
4
|
|
1117
|
+
sage: F1(a)
|
|
1118
|
+
3
|
|
1119
|
+
sage: a.valuation(P2)
|
|
1120
|
+
-1
|
|
1121
|
+
sage: F2(a)
|
|
1122
|
+
Traceback (most recent call last):
|
|
1123
|
+
...
|
|
1124
|
+
ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5
|
|
1125
|
+
modulo Fractional ideal (-2*i - 1): it has negative valuation
|
|
1126
|
+
"""
|
|
1127
|
+
# The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
|
|
1128
|
+
# either x is integral or the denominator of x is coprime to
|
|
1129
|
+
# p; otherwise we work harder.
|
|
1130
|
+
p = self._F.p
|
|
1131
|
+
|
|
1132
|
+
# Special code for residue fields of Q:
|
|
1133
|
+
if self._K is QQ:
|
|
1134
|
+
try:
|
|
1135
|
+
return FiniteField_prime_modn._element_constructor_(self._F, x)
|
|
1136
|
+
except ZeroDivisionError:
|
|
1137
|
+
raise ZeroDivisionError("Cannot reduce rational %s modulo %s: it has negative valuation" % (x, p.gen()))
|
|
1138
|
+
elif isinstance(self._K, FractionField_generic):
|
|
1139
|
+
p = p.gen()
|
|
1140
|
+
if p.degree() == 1:
|
|
1141
|
+
return self._F((x.numerator() % p)[0] / (x.denominator() % p)[0])
|
|
1142
|
+
else:
|
|
1143
|
+
return self._F((x.numerator() % p).list()) / self._F((x.denominator() % p).list())
|
|
1144
|
+
|
|
1145
|
+
try:
|
|
1146
|
+
return self._F(self._to_vs(x) * self._PBinv)
|
|
1147
|
+
except Exception:
|
|
1148
|
+
pass
|
|
1149
|
+
|
|
1150
|
+
# Now we do have to work harder...below this point we handle
|
|
1151
|
+
# cases which failed before trac 1951 was fixed.
|
|
1152
|
+
R = self._K.ring_of_integers()
|
|
1153
|
+
dx = R(x.denominator())
|
|
1154
|
+
nx = R(dx*x)
|
|
1155
|
+
vnx = nx.valuation(p)
|
|
1156
|
+
vdx = dx.valuation(p)
|
|
1157
|
+
if vnx > vdx:
|
|
1158
|
+
return self(0)
|
|
1159
|
+
if vnx < vdx:
|
|
1160
|
+
raise ZeroDivisionError("Cannot reduce field element %s modulo %s: it has negative valuation" % (x, p))
|
|
1161
|
+
|
|
1162
|
+
a = self._K.uniformizer(p,'negative') ** vnx
|
|
1163
|
+
nx /= a
|
|
1164
|
+
dx /= a
|
|
1165
|
+
# Assertions for debugging!
|
|
1166
|
+
# assert nx.valuation(p) == 0 and dx.valuation(p) == 0 and x == nx/dx
|
|
1167
|
+
# assert nx.is_integral() and dx.is_integral()
|
|
1168
|
+
# print("nx = ",nx,"; dx = ",dx, ": recursing")
|
|
1169
|
+
|
|
1170
|
+
# NB at this point nx and dx are in the ring of integers and
|
|
1171
|
+
# both are p-units. Recursion is now safe, since integral
|
|
1172
|
+
# elements will not cause further recursion; and neither
|
|
1173
|
+
# self(nx) nor self(dx) will be 0 since nx, dx are p-units.
|
|
1174
|
+
return self(nx)/self(dx)
|
|
1175
|
+
|
|
1176
|
+
def section(self):
|
|
1177
|
+
"""
|
|
1178
|
+
Compute a section of the map, namely a map that lifts elements of the
|
|
1179
|
+
residue field to elements of the field.
|
|
1180
|
+
|
|
1181
|
+
EXAMPLES::
|
|
1182
|
+
|
|
1183
|
+
sage: # needs sage.rings.number_field
|
|
1184
|
+
sage: x = polygen(ZZ, 'x')
|
|
1185
|
+
sage: K.<a> = NumberField(x^5 - 5*x + 2)
|
|
1186
|
+
sage: P = K.ideal(47).factor()[0][0]
|
|
1187
|
+
sage: k = K.residue_field(P)
|
|
1188
|
+
sage: f = k.convert_map_from(K)
|
|
1189
|
+
sage: s = f.section(); s
|
|
1190
|
+
Lifting map:
|
|
1191
|
+
From: Residue field in abar of Fractional ideal (14*a^4 - 24*a^3 - 26*a^2 + 58*a - 15)
|
|
1192
|
+
To: Number Field in a with defining polynomial x^5 - 5*x + 2
|
|
1193
|
+
sage: s(k.gen())
|
|
1194
|
+
a
|
|
1195
|
+
sage: L.<b> = NumberField(x^5 + 17*x + 1)
|
|
1196
|
+
sage: P = L.factor(53)[0][0]
|
|
1197
|
+
sage: l = L.residue_field(P)
|
|
1198
|
+
sage: g = l.convert_map_from(L)
|
|
1199
|
+
sage: s = g.section(); s
|
|
1200
|
+
Lifting map:
|
|
1201
|
+
From: Residue field in bbar of Fractional ideal (53, b^2 + 23*b + 8)
|
|
1202
|
+
To: Number Field in b with defining polynomial x^5 + 17*x + 1
|
|
1203
|
+
sage: s(l.gen()).parent()
|
|
1204
|
+
Number Field in b with defining polynomial x^5 + 17*x + 1
|
|
1205
|
+
|
|
1206
|
+
sage: # needs sage.rings.finite_rings
|
|
1207
|
+
sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
|
|
1208
|
+
sage: k.<a> = R.residue_field(h)
|
|
1209
|
+
sage: K = R.fraction_field()
|
|
1210
|
+
sage: f = k.convert_map_from(K)
|
|
1211
|
+
sage: f.section() # needs sage.libs.ntl
|
|
1212
|
+
Lifting map:
|
|
1213
|
+
From: Residue field in a of Principal ideal (t^5 + t^2 + 1) of
|
|
1214
|
+
Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X)
|
|
1215
|
+
To: Fraction Field of
|
|
1216
|
+
Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X)
|
|
1217
|
+
"""
|
|
1218
|
+
if self._section is None:
|
|
1219
|
+
self._section = LiftingMap(self, self._to_order, self._PB)
|
|
1220
|
+
return self._section
|
|
1221
|
+
|
|
1222
|
+
|
|
1223
|
+
cdef class ResidueFieldHomomorphism_global(RingHomomorphism):
|
|
1224
|
+
"""
|
|
1225
|
+
The class representing a homomorphism from the order of a number
|
|
1226
|
+
field or function field to the residue field at a given prime.
|
|
1227
|
+
|
|
1228
|
+
EXAMPLES::
|
|
1229
|
+
|
|
1230
|
+
sage: # needs sage.rings.number_field
|
|
1231
|
+
sage: x = polygen(ZZ, 'x')
|
|
1232
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
1233
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
1234
|
+
sage: k = K.residue_field(P)
|
|
1235
|
+
sage: OK = K.maximal_order()
|
|
1236
|
+
sage: abar = k(OK.1); abar
|
|
1237
|
+
abar
|
|
1238
|
+
sage: (1+abar)^179
|
|
1239
|
+
24*abar + 12
|
|
1240
|
+
|
|
1241
|
+
sage: # needs sage.rings.number_field
|
|
1242
|
+
sage: phi = k.coerce_map_from(OK); phi
|
|
1243
|
+
Ring morphism:
|
|
1244
|
+
From: Maximal Order generated by a in Number Field in a with defining polynomial x^3 - 7
|
|
1245
|
+
To: Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
|
|
1246
|
+
sage: phi in Hom(OK,k)
|
|
1247
|
+
True
|
|
1248
|
+
sage: phi(OK.1)
|
|
1249
|
+
abar
|
|
1250
|
+
|
|
1251
|
+
sage: # needs sage.rings.finite_rings
|
|
1252
|
+
sage: R.<t> = GF(19)[]; P = R.ideal(t^2 + 5)
|
|
1253
|
+
sage: k.<a> = R.residue_field(P)
|
|
1254
|
+
sage: f = k.coerce_map_from(R); f
|
|
1255
|
+
Ring morphism:
|
|
1256
|
+
From: Univariate Polynomial Ring in t over Finite Field of size 19
|
|
1257
|
+
To: Residue field in a of Principal ideal (t^2 + 5) of
|
|
1258
|
+
Univariate Polynomial Ring in t over Finite Field of size 19
|
|
1259
|
+
"""
|
|
1260
|
+
def __init__(self, K, F, to_vs, to_order, PB, PBinv):
|
|
1261
|
+
"""
|
|
1262
|
+
Initialize ``self``.
|
|
1263
|
+
|
|
1264
|
+
INPUT:
|
|
1265
|
+
|
|
1266
|
+
- ``k`` -- the residue field that is the codomain of this morphism
|
|
1267
|
+
|
|
1268
|
+
- ``p`` -- the prime ideal defining this residue field
|
|
1269
|
+
|
|
1270
|
+
- ``im_gen`` -- the image of the generator of the number field
|
|
1271
|
+
|
|
1272
|
+
EXAMPLES:
|
|
1273
|
+
|
|
1274
|
+
We create a residue field homomorphism::
|
|
1275
|
+
|
|
1276
|
+
sage: # needs sage.rings.number_field
|
|
1277
|
+
sage: K.<theta> = CyclotomicField(5)
|
|
1278
|
+
sage: P = K.factor(7)[0][0]
|
|
1279
|
+
sage: P.residue_class_degree()
|
|
1280
|
+
4
|
|
1281
|
+
sage: kk.<a> = P.residue_field(); kk
|
|
1282
|
+
Residue field in a of Fractional ideal (7)
|
|
1283
|
+
sage: phi = kk.coerce_map_from(K.maximal_order()); phi
|
|
1284
|
+
Ring morphism:
|
|
1285
|
+
From: Maximal Order generated by theta in Cyclotomic Field of order 5 and degree 4
|
|
1286
|
+
To: Residue field in a of Fractional ideal (7)
|
|
1287
|
+
sage: type(phi)
|
|
1288
|
+
<class 'sage.rings.finite_rings.residue_field.ResidueFieldHomomorphism_global'>
|
|
1289
|
+
|
|
1290
|
+
sage: # needs sage.rings.finite_rings
|
|
1291
|
+
sage: R.<t> = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1)
|
|
1292
|
+
sage: k = P.residue_field(); f = k.coerce_map_from(R)
|
|
1293
|
+
sage: f(t^10) # needs sage.modules
|
|
1294
|
+
tbar^6 + tbar^3 + tbar^2
|
|
1295
|
+
"""
|
|
1296
|
+
self._K = K
|
|
1297
|
+
self._F = F # finite field
|
|
1298
|
+
self._to_vs = to_vs
|
|
1299
|
+
self._PBinv = PBinv
|
|
1300
|
+
self._PB = PB # used for lift
|
|
1301
|
+
self._to_order = to_order # used for lift
|
|
1302
|
+
self._repr_type_str = "Reduction"
|
|
1303
|
+
RingHomomorphism.__init__(self, Hom(K,F))
|
|
1304
|
+
|
|
1305
|
+
cdef dict _extra_slots(self):
|
|
1306
|
+
"""
|
|
1307
|
+
Helper for copying and pickling.
|
|
1308
|
+
|
|
1309
|
+
EXAMPLES::
|
|
1310
|
+
|
|
1311
|
+
sage: # needs sage.rings.number_field
|
|
1312
|
+
sage: x = polygen(ZZ, 'x')
|
|
1313
|
+
sage: K.<a> = NumberField(x^3 - x + 8)
|
|
1314
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
1315
|
+
sage: k = K.residue_field(P)
|
|
1316
|
+
sage: OK = K.maximal_order()
|
|
1317
|
+
sage: phi = k.coerce_map_from(OK)
|
|
1318
|
+
sage: psi = copy(phi); psi # indirect doctest
|
|
1319
|
+
Ring morphism:
|
|
1320
|
+
From: Maximal Order generated by [1/2*a^2 + 1/2*a, a^2]
|
|
1321
|
+
in Number Field in a with defining polynomial x^3 - x + 8
|
|
1322
|
+
To: Residue field in abar of Fractional ideal (29)
|
|
1323
|
+
sage: psi == phi # not implemented
|
|
1324
|
+
True
|
|
1325
|
+
sage: psi(OK.an_element()) == phi(OK.an_element())
|
|
1326
|
+
True
|
|
1327
|
+
"""
|
|
1328
|
+
slots = RingHomomorphism._extra_slots(self)
|
|
1329
|
+
slots['_K'] = self._K
|
|
1330
|
+
slots['_F'] = self._F
|
|
1331
|
+
slots['_to_vs'] = self._to_vs
|
|
1332
|
+
slots['_PBinv'] = self._PBinv
|
|
1333
|
+
slots['_to_order'] = self._to_order
|
|
1334
|
+
slots['_PB'] = self._PB
|
|
1335
|
+
slots['_section'] = self._section
|
|
1336
|
+
return slots
|
|
1337
|
+
|
|
1338
|
+
cdef _update_slots(self, dict _slots):
|
|
1339
|
+
"""
|
|
1340
|
+
Helper for copying and pickling.
|
|
1341
|
+
|
|
1342
|
+
EXAMPLES::
|
|
1343
|
+
|
|
1344
|
+
sage: # needs sage.rings.number_field
|
|
1345
|
+
sage: x = polygen(ZZ, 'x')
|
|
1346
|
+
sage: K.<a> = NumberField(x^3 - x + 8)
|
|
1347
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
1348
|
+
sage: k = K.residue_field(P)
|
|
1349
|
+
sage: OK = K.maximal_order()
|
|
1350
|
+
sage: phi = k.coerce_map_from(OK)
|
|
1351
|
+
sage: psi = copy(phi); psi # indirect doctest
|
|
1352
|
+
Ring morphism:
|
|
1353
|
+
From: Maximal Order generated by [1/2*a^2 + 1/2*a, a^2]
|
|
1354
|
+
in Number Field in a with defining polynomial x^3 - x + 8
|
|
1355
|
+
To: Residue field in abar of Fractional ideal (29)
|
|
1356
|
+
sage: psi == phi # not implemented
|
|
1357
|
+
True
|
|
1358
|
+
sage: psi(OK.an_element()) == phi(OK.an_element())
|
|
1359
|
+
True
|
|
1360
|
+
"""
|
|
1361
|
+
RingHomomorphism._update_slots(self, _slots)
|
|
1362
|
+
self._K = _slots['_K']
|
|
1363
|
+
self._F = _slots['_F']
|
|
1364
|
+
self._to_vs = _slots['_to_vs']
|
|
1365
|
+
self._PBinv = _slots['_PBinv']
|
|
1366
|
+
self._to_order = _slots['_to_order']
|
|
1367
|
+
self._PB = _slots['_PB']
|
|
1368
|
+
self._section = _slots['_section']
|
|
1369
|
+
|
|
1370
|
+
cpdef Element _call_(self, x):
|
|
1371
|
+
"""
|
|
1372
|
+
Applies this morphism to an element.
|
|
1373
|
+
|
|
1374
|
+
EXAMPLES::
|
|
1375
|
+
|
|
1376
|
+
sage: # needs sage.rings.number_field
|
|
1377
|
+
sage: x = polygen(ZZ, 'x')
|
|
1378
|
+
sage: K.<a> = NumberField(x^3 - x + 8)
|
|
1379
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
1380
|
+
sage: k = K.residue_field(P)
|
|
1381
|
+
sage: OK = K.maximal_order()
|
|
1382
|
+
sage: k.coerce_map_from(OK)(OK(a)^7) # indirect doctest
|
|
1383
|
+
13*abar^2 + 7*abar + 21
|
|
1384
|
+
|
|
1385
|
+
sage: # needs sage.rings.finite_rings
|
|
1386
|
+
sage: R.<t> = GF(next_prime(2^18))[]; P = R.ideal(t - 71)
|
|
1387
|
+
sage: k = ResidueField(P); f = k.coerce_map_from(R); f
|
|
1388
|
+
Ring morphism:
|
|
1389
|
+
From: Univariate Polynomial Ring in t over Finite Field of size 262147
|
|
1390
|
+
To: Residue field of Principal ideal (t + 262076) of
|
|
1391
|
+
Univariate Polynomial Ring in t over Finite Field of size 262147
|
|
1392
|
+
sage: f(t^2)
|
|
1393
|
+
5041
|
|
1394
|
+
"""
|
|
1395
|
+
# The reduction map is just x |--> F(to_vs(x) * (PB**(-1))) if
|
|
1396
|
+
# either x is integral or the denominator of x is coprime to
|
|
1397
|
+
# p; otherwise we work harder.
|
|
1398
|
+
|
|
1399
|
+
# No special code for residue fields of Z, since we just use the normal reduction map to GF(p)
|
|
1400
|
+
if self._K is ZZ:
|
|
1401
|
+
return self._F(x)
|
|
1402
|
+
if isinstance(self._K, PolynomialRing_generic):
|
|
1403
|
+
p = self._F.p.gen()
|
|
1404
|
+
if p.degree() == 1:
|
|
1405
|
+
return self._F((x % p)[0])
|
|
1406
|
+
else:
|
|
1407
|
+
return self._F((x % p).list())
|
|
1408
|
+
return self._F(self._to_vs(x) * self._PBinv)
|
|
1409
|
+
#return self._F(self._to_vs(x.parent().fraction_field()(x)) * self._PBinv)
|
|
1410
|
+
|
|
1411
|
+
def section(self):
|
|
1412
|
+
"""
|
|
1413
|
+
Compute a section of the map, namely a map that lifts elements of
|
|
1414
|
+
the residue field to elements of the ring of integers.
|
|
1415
|
+
|
|
1416
|
+
EXAMPLES::
|
|
1417
|
+
|
|
1418
|
+
sage: # needs sage.rings.number_field
|
|
1419
|
+
sage: x = polygen(ZZ, 'x')
|
|
1420
|
+
sage: K.<a> = NumberField(x^5 - 5*x + 2)
|
|
1421
|
+
sage: P = K.ideal(47).factor()[0][0]
|
|
1422
|
+
sage: k = K.residue_field(P)
|
|
1423
|
+
sage: f = k.coerce_map_from(K.ring_of_integers())
|
|
1424
|
+
sage: s = f.section(); s
|
|
1425
|
+
Lifting map:
|
|
1426
|
+
From: Residue field in abar of Fractional ideal (14*a^4 - 24*a^3 - 26*a^2 + 58*a - 15)
|
|
1427
|
+
To: Maximal Order generated by a in Number Field in a with defining polynomial x^5 - 5*x + 2
|
|
1428
|
+
sage: s(k.gen())
|
|
1429
|
+
a
|
|
1430
|
+
sage: L.<b> = NumberField(x^5 + 17*x + 1)
|
|
1431
|
+
sage: P = L.factor(53)[0][0]
|
|
1432
|
+
sage: l = L.residue_field(P)
|
|
1433
|
+
sage: g = l.coerce_map_from(L.ring_of_integers())
|
|
1434
|
+
sage: s = g.section(); s
|
|
1435
|
+
Lifting map:
|
|
1436
|
+
From: Residue field in bbar of Fractional ideal (53, b^2 + 23*b + 8)
|
|
1437
|
+
To: Maximal Order generated by b in Number Field in b
|
|
1438
|
+
with defining polynomial x^5 + 17*x + 1
|
|
1439
|
+
sage: s(l.gen()).parent()
|
|
1440
|
+
Maximal Order generated by b in Number Field in b with defining polynomial x^5 + 17*x + 1
|
|
1441
|
+
|
|
1442
|
+
sage: # needs sage.rings.finite_rings
|
|
1443
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
1444
|
+
sage: k.<a> = P.residue_field()
|
|
1445
|
+
sage: f = k.coerce_map_from(R)
|
|
1446
|
+
sage: f.section()
|
|
1447
|
+
(map internal to coercion system -- copy before use)
|
|
1448
|
+
Lifting map:
|
|
1449
|
+
From: Residue field in a of Principal ideal (t^3 + t^2 + 7) of
|
|
1450
|
+
Univariate Polynomial Ring in t over Finite Field of size 17
|
|
1451
|
+
To: Univariate Polynomial Ring in t over Finite Field of size 17
|
|
1452
|
+
"""
|
|
1453
|
+
if self._section is None:
|
|
1454
|
+
self._section = LiftingMap(self, self._to_order, self._PB)
|
|
1455
|
+
return self._section
|
|
1456
|
+
|
|
1457
|
+
def lift(self, x):
|
|
1458
|
+
"""
|
|
1459
|
+
Return a lift of ``x`` to the Order, returning a "polynomial" in
|
|
1460
|
+
the generator with coefficients between 0 and `p-1`.
|
|
1461
|
+
|
|
1462
|
+
EXAMPLES::
|
|
1463
|
+
|
|
1464
|
+
sage: # needs sage.rings.number_field
|
|
1465
|
+
sage: x = polygen(ZZ, 'x')
|
|
1466
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
1467
|
+
sage: P = K.ideal(29).factor()[0][0]
|
|
1468
|
+
sage: k = K.residue_field(P)
|
|
1469
|
+
sage: OK = K.maximal_order()
|
|
1470
|
+
sage: f = k.coerce_map_from(OK)
|
|
1471
|
+
sage: c = OK(a)
|
|
1472
|
+
sage: b = k(a)
|
|
1473
|
+
sage: f.lift(13*b + 5)
|
|
1474
|
+
13*a + 5
|
|
1475
|
+
sage: f.lift(12821*b + 918)
|
|
1476
|
+
3*a + 19
|
|
1477
|
+
|
|
1478
|
+
sage: # needs sage.rings.finite_rings
|
|
1479
|
+
sage: R.<t> = GF(17)[]; P = R.ideal(t^3 + t^2 + 7)
|
|
1480
|
+
sage: k.<a> = P.residue_field(); f = k.coerce_map_from(R)
|
|
1481
|
+
sage: f.lift(a^2 + 5*a + 1)
|
|
1482
|
+
t^2 + 5*t + 1
|
|
1483
|
+
sage: f(f.lift(a^2 + 5*a + 1)) == a^2 + 5*a + 1 # needs sage.modules
|
|
1484
|
+
True
|
|
1485
|
+
"""
|
|
1486
|
+
if self.domain() is ZZ:
|
|
1487
|
+
return x.lift()
|
|
1488
|
+
else:
|
|
1489
|
+
return self.section()(x)
|
|
1490
|
+
|
|
1491
|
+
cdef class LiftingMap(Section):
|
|
1492
|
+
"""
|
|
1493
|
+
Lifting map from residue class field to number field.
|
|
1494
|
+
|
|
1495
|
+
EXAMPLES::
|
|
1496
|
+
|
|
1497
|
+
sage: # needs sage.rings.number_field
|
|
1498
|
+
sage: x = polygen(ZZ, 'x')
|
|
1499
|
+
sage: K.<a> = NumberField(x^3 + 2)
|
|
1500
|
+
sage: F = K.factor(5)[0][0].residue_field()
|
|
1501
|
+
sage: F.degree()
|
|
1502
|
+
2
|
|
1503
|
+
sage: L = F.lift_map(); L
|
|
1504
|
+
Lifting map:
|
|
1505
|
+
From: Residue field in abar of Fractional ideal (a^2 + 2*a - 1)
|
|
1506
|
+
To: Maximal Order generated by a in Number Field in a with defining polynomial x^3 + 2
|
|
1507
|
+
sage: L(F.0^2)
|
|
1508
|
+
3*a + 1
|
|
1509
|
+
sage: L(3*a + 1) == F.0^2
|
|
1510
|
+
True
|
|
1511
|
+
|
|
1512
|
+
sage: # needs sage.rings.finite_rings
|
|
1513
|
+
sage: R.<t> = GF(13)[]
|
|
1514
|
+
sage: P = R.ideal(8*t^12 + 9*t^11 + 11*t^10 + 2*t^9 + 11*t^8
|
|
1515
|
+
....: + 3*t^7 + 12*t^6 + t^4 + 7*t^3 + 5*t^2 + 12*t + 1)
|
|
1516
|
+
sage: k.<a> = P.residue_field()
|
|
1517
|
+
sage: k.lift_map()
|
|
1518
|
+
Lifting map:
|
|
1519
|
+
From: Residue field in a of Principal ideal (t^12 + 6*t^11 + 3*t^10
|
|
1520
|
+
+ 10*t^9 + 3*t^8 + 2*t^7 + 8*t^6 + 5*t^4 + 9*t^3 + 12*t^2 + 8*t + 5) of
|
|
1521
|
+
Univariate Polynomial Ring in t over Finite Field of size 13
|
|
1522
|
+
To: Univariate Polynomial Ring in t over Finite Field of size 13
|
|
1523
|
+
"""
|
|
1524
|
+
def __init__(self, reduction, to_order, PB):
|
|
1525
|
+
"""
|
|
1526
|
+
Create a lifting map.
|
|
1527
|
+
|
|
1528
|
+
EXAMPLES::
|
|
1529
|
+
|
|
1530
|
+
sage: # needs sage.rings.number_field
|
|
1531
|
+
sage: K.<theta_5> = CyclotomicField(5)
|
|
1532
|
+
sage: F = K.factor(7)[0][0].residue_field()
|
|
1533
|
+
sage: F.lift_map()
|
|
1534
|
+
Lifting map:
|
|
1535
|
+
From: Residue field in theta_5bar of Fractional ideal (7)
|
|
1536
|
+
To: Maximal Order generated by theta_5 in Cyclotomic Field of order 5 and degree 4
|
|
1537
|
+
|
|
1538
|
+
sage: # needs sage.rings.number_field
|
|
1539
|
+
sage: x = polygen(ZZ, 'x')
|
|
1540
|
+
sage: K.<a> = NumberField(x^5 + 2)
|
|
1541
|
+
sage: F = K.factor(7)[0][0].residue_field()
|
|
1542
|
+
sage: L = F.lift_map(); L
|
|
1543
|
+
Lifting map:
|
|
1544
|
+
From: Residue field in abar of Fractional ideal (2*a^4 - a^3 + 4*a^2 - 2*a + 1)
|
|
1545
|
+
To: Maximal Order generated by a in Number Field in a
|
|
1546
|
+
with defining polynomial x^5 + 2
|
|
1547
|
+
sage: L.domain()
|
|
1548
|
+
Residue field in abar of Fractional ideal (2*a^4 - a^3 + 4*a^2 - 2*a + 1)
|
|
1549
|
+
|
|
1550
|
+
sage: # needs sage.rings.number_field
|
|
1551
|
+
sage: K.<a> = CyclotomicField(7)
|
|
1552
|
+
sage: F = K.factor(5)[0][0].residue_field()
|
|
1553
|
+
sage: L = F.lift_map(); L
|
|
1554
|
+
Lifting map:
|
|
1555
|
+
From: Residue field in abar of Fractional ideal (5)
|
|
1556
|
+
To: Maximal Order generated by a in Cyclotomic Field of order 7 and degree 6
|
|
1557
|
+
sage: L.codomain()
|
|
1558
|
+
Maximal Order generated by a in Cyclotomic Field of order 7 and degree 6
|
|
1559
|
+
|
|
1560
|
+
sage: # needs sage.rings.finite_rings
|
|
1561
|
+
sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
|
|
1562
|
+
sage: k.<a> = R.residue_field(h)
|
|
1563
|
+
sage: K = R.fraction_field()
|
|
1564
|
+
sage: L = k.lift_map(); L.codomain()
|
|
1565
|
+
Univariate Polynomial Ring in t over Finite Field of size 2...
|
|
1566
|
+
"""
|
|
1567
|
+
self._K = reduction._K
|
|
1568
|
+
self._F = reduction._F # finite field
|
|
1569
|
+
self._to_order = to_order
|
|
1570
|
+
self._PB = PB
|
|
1571
|
+
Section.__init__(self, reduction)
|
|
1572
|
+
|
|
1573
|
+
cdef dict _extra_slots(self):
|
|
1574
|
+
"""
|
|
1575
|
+
Helper for copying and pickling.
|
|
1576
|
+
|
|
1577
|
+
EXAMPLES::
|
|
1578
|
+
|
|
1579
|
+
sage: # needs sage.rings.number_field
|
|
1580
|
+
sage: K.<a> = CyclotomicField(7)
|
|
1581
|
+
sage: F = K.factor(5)[0][0].residue_field()
|
|
1582
|
+
sage: phi = F.lift_map()
|
|
1583
|
+
sage: psi = copy(phi); psi # indirect doctest
|
|
1584
|
+
Lifting map:
|
|
1585
|
+
From: Residue field in abar of Fractional ideal (5)
|
|
1586
|
+
To: Maximal Order generated by a in Cyclotomic Field of order 7 and degree 6
|
|
1587
|
+
sage: psi == phi # not implemented
|
|
1588
|
+
False
|
|
1589
|
+
sage: phi(F.0) == psi(F.0)
|
|
1590
|
+
True
|
|
1591
|
+
"""
|
|
1592
|
+
slots = Section._extra_slots(self)
|
|
1593
|
+
slots['_K'] = self._K
|
|
1594
|
+
slots['_F'] = self._F
|
|
1595
|
+
slots['_to_order'] = self._to_order
|
|
1596
|
+
slots['_PB'] = self._PB
|
|
1597
|
+
return slots
|
|
1598
|
+
|
|
1599
|
+
cdef _update_slots(self, dict _slots):
|
|
1600
|
+
"""
|
|
1601
|
+
Helper for copying and pickling.
|
|
1602
|
+
|
|
1603
|
+
EXAMPLES::
|
|
1604
|
+
|
|
1605
|
+
sage: # needs sage.rings.number_field
|
|
1606
|
+
sage: K.<a> = CyclotomicField(7)
|
|
1607
|
+
sage: F = K.factor(5)[0][0].residue_field()
|
|
1608
|
+
sage: phi = F.lift_map()
|
|
1609
|
+
sage: psi = copy(phi); psi # indirect doctest
|
|
1610
|
+
Lifting map:
|
|
1611
|
+
From: Residue field in abar of Fractional ideal (5)
|
|
1612
|
+
To: Maximal Order generated by a in Cyclotomic Field of order 7 and degree 6
|
|
1613
|
+
sage: psi == phi # not implemented
|
|
1614
|
+
False
|
|
1615
|
+
sage: phi(F.0) == psi(F.0)
|
|
1616
|
+
True
|
|
1617
|
+
"""
|
|
1618
|
+
Section._update_slots(self, _slots)
|
|
1619
|
+
self._K = _slots['_K']
|
|
1620
|
+
self._F = _slots['_F']
|
|
1621
|
+
self._to_order = _slots['_to_order']
|
|
1622
|
+
self._PB = _slots['_PB']
|
|
1623
|
+
|
|
1624
|
+
cpdef Element _call_(self, x):
|
|
1625
|
+
"""
|
|
1626
|
+
Lift from this residue class field to the number field.
|
|
1627
|
+
|
|
1628
|
+
EXAMPLES::
|
|
1629
|
+
|
|
1630
|
+
sage: # needs sage.rings.number_field
|
|
1631
|
+
sage: K.<a> = CyclotomicField(7)
|
|
1632
|
+
sage: F = K.factor(5)[0][0].residue_field()
|
|
1633
|
+
sage: L = F.lift_map(); L
|
|
1634
|
+
Lifting map:
|
|
1635
|
+
From: Residue field in abar of Fractional ideal (5)
|
|
1636
|
+
To: Maximal Order generated by a in Cyclotomic Field of order 7 and degree 6
|
|
1637
|
+
sage: L(F.0) # indirect doctest
|
|
1638
|
+
a
|
|
1639
|
+
sage: F(a)
|
|
1640
|
+
abar
|
|
1641
|
+
|
|
1642
|
+
sage: # needs sage.rings.finite_rings
|
|
1643
|
+
sage: R.<t> = GF(2)[]; h = t^5 + t^2 + 1
|
|
1644
|
+
sage: k.<a> = R.residue_field(h)
|
|
1645
|
+
sage: K = R.fraction_field()
|
|
1646
|
+
sage: f = k.lift_map()
|
|
1647
|
+
sage: f(a^2)
|
|
1648
|
+
t^2
|
|
1649
|
+
sage: f(a^6)
|
|
1650
|
+
t^3 + t
|
|
1651
|
+
"""
|
|
1652
|
+
if self._K is QQ or self._K is ZZ:
|
|
1653
|
+
return self._K(x.lift()) # x.lift() is in ZZ
|
|
1654
|
+
elif isinstance(self._K, FractionField_generic):
|
|
1655
|
+
if self._F.p.degree() == 1:
|
|
1656
|
+
return self._K(self._K.ring_of_integers()(x))
|
|
1657
|
+
else:
|
|
1658
|
+
return self._K(self._K.ring_of_integers()(x.polynomial().list()))
|
|
1659
|
+
elif isinstance(self._K, PolynomialRing_generic):
|
|
1660
|
+
return self._K(x.polynomial().list())
|
|
1661
|
+
# Else the lifting map is just x |--> to_order(x * PB)
|
|
1662
|
+
x = self._F(x)
|
|
1663
|
+
v = x.polynomial().padded_list(self._F.degree())
|
|
1664
|
+
ans = self._to_order(self._PB.linear_combination_of_rows(v))
|
|
1665
|
+
if ans.parent() is self._K:
|
|
1666
|
+
return ans
|
|
1667
|
+
else:
|
|
1668
|
+
return self._K(ans)
|
|
1669
|
+
|
|
1670
|
+
def _repr_type(self):
|
|
1671
|
+
"""
|
|
1672
|
+
EXAMPLES::
|
|
1673
|
+
|
|
1674
|
+
sage: # needs sage.rings.number_field
|
|
1675
|
+
sage: K.<theta_12> = CyclotomicField(12)
|
|
1676
|
+
sage: F.<tmod> = K.factor(7)[0][0].residue_field()
|
|
1677
|
+
sage: F.lift_map() #indirect doctest
|
|
1678
|
+
Lifting map:
|
|
1679
|
+
From: Residue field in tmod of Fractional ideal (2*theta_12^3 + theta_12)
|
|
1680
|
+
To: Maximal Order generated by theta_12 in Cyclotomic Field of order 12 and degree 4
|
|
1681
|
+
"""
|
|
1682
|
+
return "Lifting"
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn):
|
|
1686
|
+
"""
|
|
1687
|
+
The class representing residue fields of number fields that have
|
|
1688
|
+
prime order.
|
|
1689
|
+
|
|
1690
|
+
EXAMPLES::
|
|
1691
|
+
|
|
1692
|
+
sage: # needs sage.rings.number_field
|
|
1693
|
+
sage: R.<x> = QQ[]
|
|
1694
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
1695
|
+
sage: P = K.ideal(29).factor()[1][0]
|
|
1696
|
+
sage: k = ResidueField(P); k
|
|
1697
|
+
Residue field of Fractional ideal (-a^2 - 2*a - 2)
|
|
1698
|
+
sage: k.order()
|
|
1699
|
+
29
|
|
1700
|
+
sage: OK = K.maximal_order()
|
|
1701
|
+
sage: c = OK(a)
|
|
1702
|
+
sage: b = k(a)
|
|
1703
|
+
sage: k.coerce_map_from(OK)(c)
|
|
1704
|
+
16
|
|
1705
|
+
sage: k(4)
|
|
1706
|
+
4
|
|
1707
|
+
sage: k(c + 5)
|
|
1708
|
+
21
|
|
1709
|
+
sage: b + c
|
|
1710
|
+
3
|
|
1711
|
+
|
|
1712
|
+
sage: # needs sage.rings.finite_rings
|
|
1713
|
+
sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
|
|
1714
|
+
sage: k = P.residue_field(); k
|
|
1715
|
+
Residue field of Principal ideal (t + 5) of
|
|
1716
|
+
Univariate Polynomial Ring in t over Finite Field of size 7
|
|
1717
|
+
sage: k(t^2)
|
|
1718
|
+
4
|
|
1719
|
+
sage: k.order()
|
|
1720
|
+
7
|
|
1721
|
+
"""
|
|
1722
|
+
def __init__(self, p, name, intp, to_vs, to_order, PB):
|
|
1723
|
+
"""
|
|
1724
|
+
Initialize ``self``.
|
|
1725
|
+
|
|
1726
|
+
INPUT:
|
|
1727
|
+
|
|
1728
|
+
- ``p`` -- a prime ideal of a number field
|
|
1729
|
+
|
|
1730
|
+
- ``name`` -- the name of the generator of this extension
|
|
1731
|
+
|
|
1732
|
+
- ``intp`` -- the rational prime that ``p`` lies over
|
|
1733
|
+
|
|
1734
|
+
EXAMPLES::
|
|
1735
|
+
|
|
1736
|
+
sage: # needs sage.rings.number_field
|
|
1737
|
+
sage: K.<i> = QuadraticField(-1)
|
|
1738
|
+
sage: kk = ResidueField(K.factor(5)[0][0])
|
|
1739
|
+
sage: type(kk)
|
|
1740
|
+
<class 'sage.rings.finite_rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
|
|
1741
|
+
|
|
1742
|
+
sage: # needs sage.rings.finite_rings
|
|
1743
|
+
sage: R.<t> = GF(7)[]; P = R.ideal(2*t + 3)
|
|
1744
|
+
sage: k = P.residue_field(); type(k)
|
|
1745
|
+
<class 'sage.rings.finite_rings.residue_field.ResidueFiniteField_prime_modn_with_category'>
|
|
1746
|
+
"""
|
|
1747
|
+
ResidueField_generic.__init__(self, p)
|
|
1748
|
+
FiniteField_prime_modn.__init__(self, intp)
|
|
1749
|
+
from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod, Integer_to_IntegerMod, Int_to_IntegerMod
|
|
1750
|
+
K = OK = p.ring()
|
|
1751
|
+
if OK.is_field():
|
|
1752
|
+
OK = OK.ring_of_integers()
|
|
1753
|
+
else:
|
|
1754
|
+
K = K.fraction_field()
|
|
1755
|
+
if PB is None:
|
|
1756
|
+
if OK is ZZ:
|
|
1757
|
+
# integer case
|
|
1758
|
+
coerce_list = [IntegerMod_to_IntegerMod(GF(intp), self), Integer_to_IntegerMod(self), Int_to_IntegerMod(self)]
|
|
1759
|
+
else:
|
|
1760
|
+
# polynomial ring case.
|
|
1761
|
+
coerce_list = [ResidueFieldHomomorphism_global(OK, self, None, None, None, None), OK.base_ring()]
|
|
1762
|
+
self._populate_coercion_lists_(coerce_list=coerce_list,
|
|
1763
|
+
convert_list=[ReductionMap(K, self, None, None, None, None)]) # could be special-cased a bit more.
|
|
1764
|
+
else:
|
|
1765
|
+
PBinv = PB**(-1)
|
|
1766
|
+
self._populate_coercion_lists_(coerce_list=[IntegerMod_to_IntegerMod(GF(intp), self),
|
|
1767
|
+
Integer_to_IntegerMod(self),
|
|
1768
|
+
Int_to_IntegerMod(self),
|
|
1769
|
+
ResidueFieldHomomorphism_global(OK, self, to_vs, to_order, PB, PBinv)],
|
|
1770
|
+
convert_list=[ReductionMap(K, self, to_vs, to_order, PB, PBinv)])
|
|
1771
|
+
|
|
1772
|
+
def _element_constructor_(self, x):
|
|
1773
|
+
"""
|
|
1774
|
+
Construct and/or coerce ``x`` into an element of ``self``.
|
|
1775
|
+
|
|
1776
|
+
INPUT:
|
|
1777
|
+
|
|
1778
|
+
- ``x`` -- something to cast in to ``self``
|
|
1779
|
+
|
|
1780
|
+
EXAMPLES::
|
|
1781
|
+
|
|
1782
|
+
sage: # needs sage.modules sage.rings.number_field
|
|
1783
|
+
sage: R.<x> = QQ[]
|
|
1784
|
+
sage: K.<a> = NumberField(x^3 - 7)
|
|
1785
|
+
sage: P = K.ideal(29).factor()[1][0]
|
|
1786
|
+
sage: k = ResidueField(P); k
|
|
1787
|
+
Residue field of Fractional ideal (-a^2 - 2*a - 2)
|
|
1788
|
+
sage: OK = K.maximal_order()
|
|
1789
|
+
sage: c = OK(a)
|
|
1790
|
+
sage: b = k(a); b
|
|
1791
|
+
16
|
|
1792
|
+
sage: k(2r)
|
|
1793
|
+
2
|
|
1794
|
+
sage: V = k.vector_space(map=False); v = V([3])
|
|
1795
|
+
sage: type(k.convert_map_from(V))
|
|
1796
|
+
<class 'sage.structure.coerce_maps.DefaultConvertMap_unique'>
|
|
1797
|
+
sage: k(v) # indirect doctest
|
|
1798
|
+
3
|
|
1799
|
+
|
|
1800
|
+
sage: # needs sage.modules sage.rings.finite_rings
|
|
1801
|
+
sage: R.<t> = GF(2)[]; P = R.ideal(t + 1); k.<a> = P.residue_field()
|
|
1802
|
+
sage: V = k.vector_space(map=False); v = V([1])
|
|
1803
|
+
sage: k(v)
|
|
1804
|
+
1
|
|
1805
|
+
"""
|
|
1806
|
+
if isinstance(x, Vector) and len(x) == 1:
|
|
1807
|
+
x = x[0]
|
|
1808
|
+
try:
|
|
1809
|
+
return FiniteField_prime_modn._element_constructor_(self, x)
|
|
1810
|
+
except TypeError:
|
|
1811
|
+
return ResidueField_generic._element_constructor_(self, x)
|