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,2171 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
# sage.doctest: needs sage.rings.finite_rings
|
|
3
|
+
"""
|
|
4
|
+
Base class for finite fields
|
|
5
|
+
|
|
6
|
+
TESTS::
|
|
7
|
+
|
|
8
|
+
sage: x = polygen(ZZ)
|
|
9
|
+
sage: K.<a> = NumberField(x^2 + 1) # needs sage.rings.number_field
|
|
10
|
+
sage: F = K.factor(3)[0][0].residue_field() # needs sage.rings.number_field
|
|
11
|
+
sage: loads(dumps(F)) == F # needs sage.rings.number_field
|
|
12
|
+
True
|
|
13
|
+
|
|
14
|
+
AUTHORS:
|
|
15
|
+
|
|
16
|
+
- Adrien Brochard, David Roe, Jeroen Demeyer, Julian Rueth, Niles Johnson,
|
|
17
|
+
Peter Bruin, Travis Scrimshaw, Xavier Caruso: initial version
|
|
18
|
+
"""
|
|
19
|
+
#*****************************************************************************
|
|
20
|
+
# Copyright (C) 2009 David Roe <roed@math.harvard.edu>
|
|
21
|
+
# Copyright (C) 2010 Niles Johnson <nilesj@gmail.com>
|
|
22
|
+
# Copyright (C) 2011 Jeroen Demeyer <jdemeyer@cage.ugent.be>
|
|
23
|
+
# Copyright (C) 2012 Adrien Brochard <aaa.brochard@gmail.com>
|
|
24
|
+
# Copyright (C) 2012 Travis Scrimshaw <tscrim@ucdavis.edu>
|
|
25
|
+
# Copyright (C) 2012 Xavier Caruso <xavier.caruso@normalesup.org>
|
|
26
|
+
# Copyright (C) 2013 Peter Bruin <P.Bruin@warwick.ac.uk>
|
|
27
|
+
# Copyright (C) 2014 Julian Rueth <julian.rueth@fsfe.org>
|
|
28
|
+
#
|
|
29
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
30
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
31
|
+
# the License, or (at your option) any later version.
|
|
32
|
+
# https://www.gnu.org/licenses/
|
|
33
|
+
#*****************************************************************************
|
|
34
|
+
|
|
35
|
+
cimport cython
|
|
36
|
+
from cysignals.signals cimport sig_check
|
|
37
|
+
from cpython.array cimport array
|
|
38
|
+
|
|
39
|
+
from sage.categories.finite_fields import FiniteFields
|
|
40
|
+
from sage.misc.persist import register_unpickle_override
|
|
41
|
+
from sage.misc.cachefunc import cached_method
|
|
42
|
+
from sage.misc.prandom import randrange
|
|
43
|
+
from sage.rings.integer cimport Integer
|
|
44
|
+
import sage.rings.abc
|
|
45
|
+
|
|
46
|
+
# Copied from sage.misc.fast_methods, used in __hash__() below.
|
|
47
|
+
cdef int SIZEOF_VOID_P_SHIFT = 8*sizeof(void *) - 4
|
|
48
|
+
|
|
49
|
+
cdef class FiniteField(Field):
|
|
50
|
+
"""
|
|
51
|
+
Abstract base class for finite fields.
|
|
52
|
+
|
|
53
|
+
TESTS::
|
|
54
|
+
|
|
55
|
+
sage: GF(997).is_finite()
|
|
56
|
+
True
|
|
57
|
+
"""
|
|
58
|
+
def __init__(self, base, names, normalize, category=None):
|
|
59
|
+
"""
|
|
60
|
+
Initialize ``self``.
|
|
61
|
+
|
|
62
|
+
EXAMPLES::
|
|
63
|
+
|
|
64
|
+
sage: K = GF(7); K
|
|
65
|
+
Finite Field of size 7
|
|
66
|
+
sage: loads(K.dumps()) == K
|
|
67
|
+
True
|
|
68
|
+
sage: GF(7^10, 'a')
|
|
69
|
+
Finite Field in a of size 7^10
|
|
70
|
+
sage: K = GF(7^10, 'a'); K
|
|
71
|
+
Finite Field in a of size 7^10
|
|
72
|
+
sage: loads(K.dumps()) == K
|
|
73
|
+
True
|
|
74
|
+
"""
|
|
75
|
+
if category is None:
|
|
76
|
+
category = FiniteFields()
|
|
77
|
+
Field.__init__(self, base, names, normalize, category)
|
|
78
|
+
|
|
79
|
+
# The methods __hash__ and __richcmp__ below were copied from
|
|
80
|
+
# sage.misc.fast_methods.WithEqualityById; we cannot inherit from
|
|
81
|
+
# this since Cython does not support multiple inheritance.
|
|
82
|
+
|
|
83
|
+
def __hash__(self):
|
|
84
|
+
"""
|
|
85
|
+
The hash provided by this class coincides with that of ``<class 'object'>``.
|
|
86
|
+
|
|
87
|
+
TESTS::
|
|
88
|
+
|
|
89
|
+
sage: F.<a> = FiniteField(2^3)
|
|
90
|
+
sage: hash(F) == hash(F)
|
|
91
|
+
True
|
|
92
|
+
sage: hash(F) == object.__hash__(F)
|
|
93
|
+
True
|
|
94
|
+
"""
|
|
95
|
+
# This is the default hash function in Python's object.c:
|
|
96
|
+
cdef long x
|
|
97
|
+
cdef size_t y = <size_t><void *>self
|
|
98
|
+
y = (y >> 4) | (y << SIZEOF_VOID_P_SHIFT)
|
|
99
|
+
x = <long>y
|
|
100
|
+
if x==-1:
|
|
101
|
+
x = -2
|
|
102
|
+
return x
|
|
103
|
+
|
|
104
|
+
def __richcmp__(self, other, int m):
|
|
105
|
+
"""
|
|
106
|
+
Compare ``self`` with ``other``.
|
|
107
|
+
|
|
108
|
+
Finite fields compare equal if and only if they are identical.
|
|
109
|
+
In particular, they are not equal unless they have the same
|
|
110
|
+
cardinality, modulus, variable name and implementation.
|
|
111
|
+
|
|
112
|
+
EXAMPLES::
|
|
113
|
+
|
|
114
|
+
sage: x = polygen(GF(3))
|
|
115
|
+
sage: F = FiniteField(3^2, 'c', modulus=x^2+1)
|
|
116
|
+
sage: F == F
|
|
117
|
+
True
|
|
118
|
+
sage: F == FiniteField(3^3, 'c')
|
|
119
|
+
False
|
|
120
|
+
sage: F == FiniteField(3^2, 'c', modulus=x^2+x+2)
|
|
121
|
+
False
|
|
122
|
+
sage: F == FiniteField(3^2, 'd')
|
|
123
|
+
False
|
|
124
|
+
sage: F == FiniteField(3^2, 'c', impl='pari_ffelt')
|
|
125
|
+
False
|
|
126
|
+
"""
|
|
127
|
+
if self is other:
|
|
128
|
+
if m == 2: # ==
|
|
129
|
+
return True
|
|
130
|
+
elif m == 3: # !=
|
|
131
|
+
return False
|
|
132
|
+
else:
|
|
133
|
+
# <= or >= or NotImplemented
|
|
134
|
+
return m==1 or m==5 or NotImplemented
|
|
135
|
+
else:
|
|
136
|
+
if m == 2:
|
|
137
|
+
return False
|
|
138
|
+
elif m == 3:
|
|
139
|
+
return True
|
|
140
|
+
else:
|
|
141
|
+
return NotImplemented
|
|
142
|
+
|
|
143
|
+
def __repr__(self) -> str:
|
|
144
|
+
"""
|
|
145
|
+
String representation of this finite field.
|
|
146
|
+
|
|
147
|
+
EXAMPLES::
|
|
148
|
+
|
|
149
|
+
sage: k = GF(127)
|
|
150
|
+
sage: k # indirect doctest
|
|
151
|
+
Finite Field of size 127
|
|
152
|
+
|
|
153
|
+
sage: k.<b> = GF(2^8)
|
|
154
|
+
sage: k
|
|
155
|
+
Finite Field in b of size 2^8
|
|
156
|
+
|
|
157
|
+
sage: k.<c> = GF(2^20)
|
|
158
|
+
sage: k
|
|
159
|
+
Finite Field in c of size 2^20
|
|
160
|
+
|
|
161
|
+
sage: k.<d> = GF(7^20)
|
|
162
|
+
sage: k
|
|
163
|
+
Finite Field in d of size 7^20
|
|
164
|
+
"""
|
|
165
|
+
if self.degree()>1:
|
|
166
|
+
return "Finite Field in %s of size %s^%s" % (self.variable_name(),
|
|
167
|
+
self.characteristic(),
|
|
168
|
+
self.degree())
|
|
169
|
+
else:
|
|
170
|
+
return "Finite Field of size %s" % (self.characteristic())
|
|
171
|
+
|
|
172
|
+
def _latex_(self) -> str:
|
|
173
|
+
r"""
|
|
174
|
+
Return a string denoting the name of the field in LaTeX.
|
|
175
|
+
|
|
176
|
+
The :func:`~sage.misc.latex.latex` function calls the
|
|
177
|
+
``_latex_`` attribute when available.
|
|
178
|
+
|
|
179
|
+
EXAMPLES:
|
|
180
|
+
|
|
181
|
+
The ``latex`` command parses the string::
|
|
182
|
+
|
|
183
|
+
sage: GF(81, 'a')._latex_()
|
|
184
|
+
'\\Bold{F}_{3^{4}}'
|
|
185
|
+
sage: latex(GF(81, 'a'))
|
|
186
|
+
\Bold{F}_{3^{4}}
|
|
187
|
+
sage: GF(3)._latex_()
|
|
188
|
+
'\\Bold{F}_{3}'
|
|
189
|
+
sage: latex(GF(3))
|
|
190
|
+
\Bold{F}_{3}
|
|
191
|
+
"""
|
|
192
|
+
if self.degree() > 1:
|
|
193
|
+
e = "^{%s}" % self.degree()
|
|
194
|
+
else:
|
|
195
|
+
e = ""
|
|
196
|
+
return "\\Bold{F}_{%s%s}" % (self.characteristic(), e)
|
|
197
|
+
|
|
198
|
+
def _gap_init_(self) -> str:
|
|
199
|
+
"""
|
|
200
|
+
Return string that initializes the GAP version of
|
|
201
|
+
this finite field.
|
|
202
|
+
|
|
203
|
+
EXAMPLES::
|
|
204
|
+
|
|
205
|
+
sage: GF(9,'a')._gap_init_()
|
|
206
|
+
'GF(9)'
|
|
207
|
+
"""
|
|
208
|
+
return 'GF(%s)' % self.order()
|
|
209
|
+
|
|
210
|
+
def _magma_init_(self, magma):
|
|
211
|
+
"""
|
|
212
|
+
Return string representation of ``self`` that Magma can
|
|
213
|
+
understand.
|
|
214
|
+
|
|
215
|
+
EXAMPLES::
|
|
216
|
+
|
|
217
|
+
sage: # optional - magma
|
|
218
|
+
sage: GF(97,'a')._magma_init_(magma)
|
|
219
|
+
'GF(97)'
|
|
220
|
+
sage: GF(9,'a')._magma_init_(magma)
|
|
221
|
+
'SageCreateWithNames(ext<GF(3)|_sage_[...]![GF(3)!2,GF(3)!2,GF(3)!1]>,["a"])'
|
|
222
|
+
sage: magma(GF(9,'a'))
|
|
223
|
+
Finite field of size 3^2
|
|
224
|
+
sage: magma(GF(9,'a')).1
|
|
225
|
+
a
|
|
226
|
+
"""
|
|
227
|
+
if self.degree() == 1:
|
|
228
|
+
return 'GF(%s)' % self.order()
|
|
229
|
+
B = self.base_ring()
|
|
230
|
+
p = self.polynomial()
|
|
231
|
+
s = "ext<%s|%s>" % (B._magma_init_(magma),p._magma_init_(magma))
|
|
232
|
+
return magma._with_names(s, self.variable_names())
|
|
233
|
+
|
|
234
|
+
def _macaulay2_init_(self, macaulay2=None):
|
|
235
|
+
"""
|
|
236
|
+
Return the string representation of this finite field that Macaulay2
|
|
237
|
+
can understand.
|
|
238
|
+
|
|
239
|
+
Note that, in the case of a prime field, this returns ``ZZ/p`` instead
|
|
240
|
+
of the Galois field ``GF p``, since computations in polynomial rings
|
|
241
|
+
over ``ZZ/p`` are faster in Macaulay2 (as of 2019).
|
|
242
|
+
|
|
243
|
+
EXAMPLES::
|
|
244
|
+
|
|
245
|
+
sage: macaulay2(GF(97, 'a')) # indirect doctest, optional - macaulay2
|
|
246
|
+
ZZ
|
|
247
|
+
--
|
|
248
|
+
97
|
|
249
|
+
sage: macaulay2(GF(49, 'a')) # indirect doctest, optional - macaulay2
|
|
250
|
+
GF 49
|
|
251
|
+
|
|
252
|
+
TESTS:
|
|
253
|
+
|
|
254
|
+
The variable name is preserved (:issue:`28566`)::
|
|
255
|
+
|
|
256
|
+
sage: K = macaulay2(GF(49, 'b')) # optional - macaulay2
|
|
257
|
+
sage: K.gens() # optional - macaulay2
|
|
258
|
+
{b}
|
|
259
|
+
sage: K._sage_() # optional - macaulay2
|
|
260
|
+
Finite Field in b of size 7^2
|
|
261
|
+
"""
|
|
262
|
+
if self.is_prime_field():
|
|
263
|
+
return "ZZ/%s" % self.order()
|
|
264
|
+
return "GF(%s,Variable=>symbol %s)" % (self.order(),
|
|
265
|
+
self.variable_name())
|
|
266
|
+
|
|
267
|
+
def _sage_input_(self, sib, coerced):
|
|
268
|
+
r"""
|
|
269
|
+
Produce an expression which will reproduce this value when evaluated.
|
|
270
|
+
|
|
271
|
+
EXAMPLES::
|
|
272
|
+
|
|
273
|
+
sage: sage_input(GF(5), verify=True)
|
|
274
|
+
# Verified
|
|
275
|
+
GF(5)
|
|
276
|
+
sage: sage_input(GF(32, 'a'), verify=True)
|
|
277
|
+
# Verified
|
|
278
|
+
R.<x> = GF(2)[]
|
|
279
|
+
GF(2^5, 'a', x^5 + x^2 + 1)
|
|
280
|
+
sage: K = GF(125, 'b')
|
|
281
|
+
sage: sage_input((K, K), verify=True)
|
|
282
|
+
# Verified
|
|
283
|
+
R.<x> = GF(5)[]
|
|
284
|
+
GF_5_3 = GF(5^3, 'b', x^3 + 3*x + 3)
|
|
285
|
+
(GF_5_3, GF_5_3)
|
|
286
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
|
287
|
+
sage: GF(81, 'a')._sage_input_(SageInputBuilder(), False)
|
|
288
|
+
{call: {atomic:GF}({binop:** {atomic:3} {atomic:4}}, {atomic:'a'}, {binop:+ {binop:+ {binop:** {gen:x {constr_parent: {subscr: {call: {atomic:GF}({atomic:3})}[{atomic:'x'}]} with gens: ('x',)}} {atomic:4}} {binop:* {atomic:2} {binop:** {gen:x {constr_parent: {subscr: {call: {atomic:GF}({atomic:3})}[{atomic:'x'}]} with gens: ('x',)}} {atomic:3}}}} {atomic:2}})}
|
|
289
|
+
"""
|
|
290
|
+
if self.degree() == 1:
|
|
291
|
+
v = sib.name('GF')(sib.int(self.characteristic()))
|
|
292
|
+
name = 'GF_%d' % self.characteristic()
|
|
293
|
+
else:
|
|
294
|
+
v = sib.name('GF')(sib.int(self.characteristic()) ** sib.int(self.degree()),
|
|
295
|
+
self.variable_name(),
|
|
296
|
+
self.modulus())
|
|
297
|
+
name = 'GF_%d_%d' % (self.characteristic(), self.degree())
|
|
298
|
+
sib.cache(self, v, name)
|
|
299
|
+
return v
|
|
300
|
+
|
|
301
|
+
@cython.boundscheck(False)
|
|
302
|
+
@cython.wraparound(False)
|
|
303
|
+
def __iter__(self):
|
|
304
|
+
"""
|
|
305
|
+
Iterate over all elements of this finite field.
|
|
306
|
+
|
|
307
|
+
EXAMPLES::
|
|
308
|
+
|
|
309
|
+
sage: k.<a> = FiniteField(9, impl='pari')
|
|
310
|
+
sage: list(k)
|
|
311
|
+
[0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2]
|
|
312
|
+
|
|
313
|
+
Partial iteration of a very large finite field::
|
|
314
|
+
|
|
315
|
+
sage: p = next_prime(2^64)
|
|
316
|
+
sage: k.<a> = FiniteField(p^2, impl='pari')
|
|
317
|
+
sage: it = iter(k); it
|
|
318
|
+
<...generator object at ...>
|
|
319
|
+
sage: [next(it) for i in range(10)]
|
|
320
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
321
|
+
|
|
322
|
+
TESTS:
|
|
323
|
+
|
|
324
|
+
Check that the generic implementation works in all cases::
|
|
325
|
+
|
|
326
|
+
sage: L = []
|
|
327
|
+
sage: from sage.rings.finite_rings.finite_field_base import FiniteField
|
|
328
|
+
sage: print(list(FiniteField.__iter__(GF(8, impl='givaro', names='z')))) # needs sage.libs.linbox
|
|
329
|
+
[0, 1, z, z + 1, z^2, z^2 + 1, z^2 + z, z^2 + z + 1]
|
|
330
|
+
sage: print(list(FiniteField.__iter__(GF(8, impl='pari', names='z'))))
|
|
331
|
+
[0, 1, z, z + 1, z^2, z^2 + 1, z^2 + z, z^2 + z + 1]
|
|
332
|
+
sage: print(list(FiniteField.__iter__(GF(8, impl='ntl', names='z')))) # needs sage.libs.ntl
|
|
333
|
+
[0, 1, z, z + 1, z^2, z^2 + 1, z^2 + z, z^2 + z + 1]
|
|
334
|
+
"""
|
|
335
|
+
cdef Py_ssize_t n = self.degree()
|
|
336
|
+
cdef unsigned long lim # maximum value for coefficients
|
|
337
|
+
try:
|
|
338
|
+
lim = (<unsigned long>self.characteristic()) - 1
|
|
339
|
+
except OverflowError:
|
|
340
|
+
# If the characteristic is too large to represent in an
|
|
341
|
+
# "unsigned long", it is reasonable to assume that we won't
|
|
342
|
+
# be able to iterate over all elements. Typically n >= 2,
|
|
343
|
+
# so that would mean >= 2^64 elements on a 32-bit system.
|
|
344
|
+
# Just in case that we iterate to the end anyway, we raise
|
|
345
|
+
# an exception at the end.
|
|
346
|
+
lim = <unsigned long>(-1)
|
|
347
|
+
|
|
348
|
+
elt = self.zero()
|
|
349
|
+
one = self.one()
|
|
350
|
+
x = self.gen()
|
|
351
|
+
|
|
352
|
+
# coeffs[] is an array of coefficients of the current finite
|
|
353
|
+
# field element (as unsigned longs)
|
|
354
|
+
#
|
|
355
|
+
# Stack represents an element
|
|
356
|
+
# sum_{i=0}^{n-1} coeffs[i] x^i
|
|
357
|
+
# as follows:
|
|
358
|
+
# stack[k] = sum_{i=k}^{n-1} coeffs[i] x^(i-k)
|
|
359
|
+
#
|
|
360
|
+
# This satisfies the recursion
|
|
361
|
+
# stack[k-1] = x * stack[k] + coeffs[k-1]
|
|
362
|
+
#
|
|
363
|
+
# Finally, elt is a shortcut for stack[k]
|
|
364
|
+
#
|
|
365
|
+
cdef list stack = [elt] * n
|
|
366
|
+
cdef array coeffsarr = array('L', [0] * n)
|
|
367
|
+
cdef unsigned long* coeffs = coeffsarr.data.as_ulongs
|
|
368
|
+
|
|
369
|
+
yield elt # zero
|
|
370
|
+
cdef Py_ssize_t k = 0
|
|
371
|
+
while k < n:
|
|
372
|
+
# Find coefficients of next element
|
|
373
|
+
coeff = coeffs[k]
|
|
374
|
+
if coeff >= lim:
|
|
375
|
+
# We cannot increase coeffs[k], so we wrap around to 0
|
|
376
|
+
# and try to increase the next coefficient
|
|
377
|
+
coeffs[k] = 0
|
|
378
|
+
k += 1
|
|
379
|
+
continue
|
|
380
|
+
coeffs[k] = coeff + 1
|
|
381
|
+
|
|
382
|
+
# Now compute and yield the finite field element
|
|
383
|
+
sig_check()
|
|
384
|
+
elt = stack[k] + one
|
|
385
|
+
stack[k] = elt
|
|
386
|
+
# Fix lower elements of stack, until k == 0
|
|
387
|
+
while k > 0:
|
|
388
|
+
elt *= x
|
|
389
|
+
k -= 1
|
|
390
|
+
stack[k] = elt
|
|
391
|
+
|
|
392
|
+
yield elt
|
|
393
|
+
|
|
394
|
+
if lim == <unsigned long>(-1):
|
|
395
|
+
raise NotImplementedError("iterating over all elements of a large finite field is not supported")
|
|
396
|
+
|
|
397
|
+
def from_integer(self, n, reverse=False):
|
|
398
|
+
r"""
|
|
399
|
+
Return the finite field element obtained by reinterpreting the base-`p`
|
|
400
|
+
expansion of `n` as a polynomial and evaluating it at the generator of
|
|
401
|
+
this finite field.
|
|
402
|
+
|
|
403
|
+
If ``reverse`` is set to ``True`` (default: ``False``),
|
|
404
|
+
the list of digits is reversed prior to evaluation.
|
|
405
|
+
|
|
406
|
+
Inverse of :meth:`sage.rings.finite_rings.element_base.FinitePolyExtElement.to_integer`.
|
|
407
|
+
|
|
408
|
+
INPUT:
|
|
409
|
+
|
|
410
|
+
- ``n`` -- integer between `0` and the cardinality of this field minus `1`
|
|
411
|
+
|
|
412
|
+
EXAMPLES::
|
|
413
|
+
|
|
414
|
+
sage: p = 4091
|
|
415
|
+
sage: F = GF(p^4, 'a')
|
|
416
|
+
sage: n = 100*p^3 + 37*p^2 + 12*p + 6
|
|
417
|
+
sage: F.from_integer(n)
|
|
418
|
+
100*a^3 + 37*a^2 + 12*a + 6
|
|
419
|
+
sage: F.from_integer(n) in F
|
|
420
|
+
True
|
|
421
|
+
sage: F.from_integer(n, reverse=True)
|
|
422
|
+
6*a^3 + 12*a^2 + 37*a + 100
|
|
423
|
+
|
|
424
|
+
TESTS::
|
|
425
|
+
|
|
426
|
+
sage: F = GF(19^5)
|
|
427
|
+
sage: F.from_integer(0)
|
|
428
|
+
0
|
|
429
|
+
sage: _.parent()
|
|
430
|
+
Finite Field in ... of size 19^5
|
|
431
|
+
sage: F.from_integer(-5)
|
|
432
|
+
Traceback (most recent call last):
|
|
433
|
+
...
|
|
434
|
+
ValueError: n must be between 0 and self.order()
|
|
435
|
+
sage: F.from_integer(F.cardinality())
|
|
436
|
+
Traceback (most recent call last):
|
|
437
|
+
...
|
|
438
|
+
ValueError: n must be between 0 and self.order()
|
|
439
|
+
"""
|
|
440
|
+
n = Integer(n)
|
|
441
|
+
if not 0 <= n < self.order():
|
|
442
|
+
raise ValueError("n must be between 0 and self.order()")
|
|
443
|
+
cdef list digs = n.digits(self.characteristic())
|
|
444
|
+
g = self.gen()
|
|
445
|
+
r = self.zero()
|
|
446
|
+
for d in (digs if reverse else digs[::-1]):
|
|
447
|
+
r = r * g + self(d)
|
|
448
|
+
return r
|
|
449
|
+
|
|
450
|
+
def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None):
|
|
451
|
+
"""
|
|
452
|
+
Return ``True`` if the map from ``self`` to codomain sending
|
|
453
|
+
``self.0`` to the unique element of ``im_gens`` is a valid field
|
|
454
|
+
homomorphism. Otherwise, return ``False``.
|
|
455
|
+
|
|
456
|
+
EXAMPLES:
|
|
457
|
+
|
|
458
|
+
Between prime fields::
|
|
459
|
+
|
|
460
|
+
sage: k0 = FiniteField(73, modulus='primitive')
|
|
461
|
+
sage: k1 = FiniteField(73)
|
|
462
|
+
sage: k0._is_valid_homomorphism_(k1, (k1(5),) )
|
|
463
|
+
True
|
|
464
|
+
sage: k1._is_valid_homomorphism_(k0, (k0(1),) )
|
|
465
|
+
True
|
|
466
|
+
|
|
467
|
+
Now for extension fields::
|
|
468
|
+
|
|
469
|
+
sage: k.<a> = FiniteField(73^2)
|
|
470
|
+
sage: K.<b> = FiniteField(73^3)
|
|
471
|
+
sage: L.<c> = FiniteField(73^4)
|
|
472
|
+
sage: k0._is_valid_homomorphism_(k, (k(5),) )
|
|
473
|
+
True
|
|
474
|
+
sage: k.hom([c]) # indirect doctest
|
|
475
|
+
Traceback (most recent call last):
|
|
476
|
+
...
|
|
477
|
+
TypeError: images do not define a valid homomorphism
|
|
478
|
+
|
|
479
|
+
sage: k.hom([c^(73*73+1)])
|
|
480
|
+
Ring morphism:
|
|
481
|
+
From: Finite Field in a of size 73^2
|
|
482
|
+
To: Finite Field in c of size 73^4
|
|
483
|
+
Defn: a |--> 7*c^3 + 13*c^2 + 65*c + 71
|
|
484
|
+
|
|
485
|
+
sage: k.hom([b])
|
|
486
|
+
Traceback (most recent call last):
|
|
487
|
+
...
|
|
488
|
+
TypeError: images do not define a valid homomorphism
|
|
489
|
+
"""
|
|
490
|
+
#if self.characteristic() != codomain.characteristic():
|
|
491
|
+
# raise ValueError("no map from %s to %s" % (self, codomain))
|
|
492
|
+
# When the base is not just Fp, we want to ensure that there's a
|
|
493
|
+
# coercion map from the base rather than just checking the characteristic
|
|
494
|
+
if base_map is None and not codomain.has_coerce_map_from(self.base_ring()):
|
|
495
|
+
return False
|
|
496
|
+
if len(im_gens) != 1:
|
|
497
|
+
raise ValueError("only one generator for finite fields")
|
|
498
|
+
|
|
499
|
+
f = self.modulus()
|
|
500
|
+
if base_map is not None:
|
|
501
|
+
f = f.map_coefficients(base_map)
|
|
502
|
+
return f(im_gens[0]).is_zero()
|
|
503
|
+
|
|
504
|
+
def _Hom_(self, codomain, category=None):
|
|
505
|
+
"""
|
|
506
|
+
Return the set of homomorphisms from ``self`` to ``codomain``
|
|
507
|
+
in ``category``.
|
|
508
|
+
|
|
509
|
+
This function is implicitly called by the ``Hom`` method or
|
|
510
|
+
function.
|
|
511
|
+
|
|
512
|
+
EXAMPLES::
|
|
513
|
+
|
|
514
|
+
sage: K.<a> = GF(25); K
|
|
515
|
+
Finite Field in a of size 5^2
|
|
516
|
+
sage: K.Hom(K) # indirect doctest
|
|
517
|
+
Automorphism group of Finite Field in a of size 5^2
|
|
518
|
+
"""
|
|
519
|
+
from sage.rings.finite_rings.homset import FiniteFieldHomset
|
|
520
|
+
if category.is_subcategory(FiniteFields()):
|
|
521
|
+
return FiniteFieldHomset(self, codomain, category)
|
|
522
|
+
return super()._Hom_(codomain, category)
|
|
523
|
+
|
|
524
|
+
def _squarefree_decomposition_univariate_polynomial(self, f):
|
|
525
|
+
"""
|
|
526
|
+
Return the square-free decomposition of this polynomial.
|
|
527
|
+
|
|
528
|
+
This is a partial factorization into square-free, coprime polynomials.
|
|
529
|
+
|
|
530
|
+
This is a helper method for
|
|
531
|
+
:meth:`sage.rings.polynomial.squarefree_decomposition`.
|
|
532
|
+
|
|
533
|
+
INPUT:
|
|
534
|
+
|
|
535
|
+
- ``f`` -- a univariate nonzero polynomial over this field
|
|
536
|
+
|
|
537
|
+
ALGORITHM: [Coh1993]_, Algorithm 3.4.2 which is basically the algorithm
|
|
538
|
+
in [Yun1976]_ with special treatment for powers divisible by `p`.
|
|
539
|
+
|
|
540
|
+
EXAMPLES::
|
|
541
|
+
|
|
542
|
+
sage: K.<a> = GF(3^2)
|
|
543
|
+
sage: R.<x> = K[]
|
|
544
|
+
sage: f = x^243+2*x^81+x^9+1
|
|
545
|
+
sage: f.squarefree_decomposition()
|
|
546
|
+
(x^27 + 2*x^9 + x + 1)^9
|
|
547
|
+
sage: f = x^243+a*x^27+1
|
|
548
|
+
sage: f.squarefree_decomposition()
|
|
549
|
+
(x^9 + (2*a + 1)*x + 1)^27
|
|
550
|
+
|
|
551
|
+
TESTS::
|
|
552
|
+
|
|
553
|
+
sage: for K in [GF(2^18,'a'), GF(3^2,'a'), GF(47^3,'a')]: # needs sage.modules
|
|
554
|
+
....: R.<x> = K[]
|
|
555
|
+
....: if K.characteristic() < 5: m = 4
|
|
556
|
+
....: else: m = 1
|
|
557
|
+
....: for _ in range(m):
|
|
558
|
+
....: f = (R.random_element(4)^3*R.random_element(m)^(m+1))(x^6)
|
|
559
|
+
....: F = f.squarefree_decomposition()
|
|
560
|
+
....: assert F.prod() == f
|
|
561
|
+
....: for i in range(len(F)):
|
|
562
|
+
....: assert gcd(F[i][0], F[i][0].derivative()) == 1
|
|
563
|
+
....: for j in range(len(F)):
|
|
564
|
+
....: if i == j: continue
|
|
565
|
+
....: assert gcd(F[i][0], F[j][0]) == 1
|
|
566
|
+
|
|
567
|
+
Check that :issue:`35323` is fixed::
|
|
568
|
+
|
|
569
|
+
sage: R.<x> = GF(2)[]
|
|
570
|
+
sage: (x^2 + 1).squarefree_decomposition()
|
|
571
|
+
(x + 1)^2
|
|
572
|
+
sage: R.<x> = PolynomialRing(GF(65537), sparse=True)
|
|
573
|
+
sage: (x^65537 + 2).squarefree_decomposition()
|
|
574
|
+
(x + 2)^65537
|
|
575
|
+
"""
|
|
576
|
+
from sage.structure.factorization import Factorization
|
|
577
|
+
if f.degree() == 0:
|
|
578
|
+
return Factorization([], unit=f[0])
|
|
579
|
+
|
|
580
|
+
cdef Py_ssize_t i, k
|
|
581
|
+
cdef list factors = []
|
|
582
|
+
cdef Integer p = Integer(self.characteristic())
|
|
583
|
+
unit = f.leading_coefficient()
|
|
584
|
+
T0 = f.monic()
|
|
585
|
+
cdef Integer e = Integer(1)
|
|
586
|
+
cdef Integer T0_deg = T0.degree()
|
|
587
|
+
if T0_deg > 0:
|
|
588
|
+
P = T0.parent()
|
|
589
|
+
der = T0.derivative()
|
|
590
|
+
pth_root = self.frobenius_endomorphism(-1)
|
|
591
|
+
while der.is_zero():
|
|
592
|
+
T0 = P([pth_root(T0[p*i]) for i in range(T0_deg//p + 1)])
|
|
593
|
+
T0_deg //= p
|
|
594
|
+
if T0 == 1:
|
|
595
|
+
raise RuntimeError
|
|
596
|
+
der = T0.derivative()
|
|
597
|
+
e *= p
|
|
598
|
+
T = T0.gcd(der)
|
|
599
|
+
V = T0 // T
|
|
600
|
+
k = 0
|
|
601
|
+
while T0_deg > 0:
|
|
602
|
+
k += 1
|
|
603
|
+
if p.divides(k):
|
|
604
|
+
T = T // V
|
|
605
|
+
k += 1
|
|
606
|
+
W = V.gcd(T)
|
|
607
|
+
if W.degree() < V.degree():
|
|
608
|
+
factors.append((V // W, e * k))
|
|
609
|
+
V = W
|
|
610
|
+
T = T // V
|
|
611
|
+
if V.degree() == 0:
|
|
612
|
+
if T.degree() == 0:
|
|
613
|
+
break
|
|
614
|
+
# T is of the form sum_{i=0}^n t_i X^{pi}
|
|
615
|
+
T0 = P([pth_root(T[p*i]) for i in range(T.degree()//p + 1)])
|
|
616
|
+
T0_deg //= p
|
|
617
|
+
der = T0.derivative()
|
|
618
|
+
e *= p
|
|
619
|
+
while der.is_zero():
|
|
620
|
+
T0 = P([pth_root(T0[p*i]) for i in range(T0_deg//p + 1)])
|
|
621
|
+
T0_deg //= p
|
|
622
|
+
der = T0.derivative()
|
|
623
|
+
e *= p
|
|
624
|
+
T = T0.gcd(der)
|
|
625
|
+
V = T0 // T
|
|
626
|
+
k = 0
|
|
627
|
+
else:
|
|
628
|
+
T = T // V
|
|
629
|
+
|
|
630
|
+
return Factorization(factors, unit=unit, sort=False)
|
|
631
|
+
|
|
632
|
+
def gen(self):
|
|
633
|
+
r"""
|
|
634
|
+
Return a generator of this field (over its prime field). As this is an
|
|
635
|
+
abstract base class, this just raises a :exc:`NotImplementedError`.
|
|
636
|
+
|
|
637
|
+
EXAMPLES::
|
|
638
|
+
|
|
639
|
+
sage: K = GF(17)
|
|
640
|
+
sage: sage.rings.finite_rings.finite_field_base.FiniteField.gen(K)
|
|
641
|
+
Traceback (most recent call last):
|
|
642
|
+
...
|
|
643
|
+
NotImplementedError
|
|
644
|
+
"""
|
|
645
|
+
raise NotImplementedError
|
|
646
|
+
|
|
647
|
+
@cached_method
|
|
648
|
+
def multiplicative_generator(self):
|
|
649
|
+
"""
|
|
650
|
+
Return a primitive element of this finite field, i.e. a
|
|
651
|
+
generator of the multiplicative group.
|
|
652
|
+
|
|
653
|
+
You can use :meth:`multiplicative_generator()` or
|
|
654
|
+
:meth:`primitive_element()`, these mean the same thing.
|
|
655
|
+
|
|
656
|
+
.. WARNING::
|
|
657
|
+
|
|
658
|
+
This generator might change from one version of Sage to another.
|
|
659
|
+
|
|
660
|
+
EXAMPLES::
|
|
661
|
+
|
|
662
|
+
sage: k = GF(997)
|
|
663
|
+
sage: k.multiplicative_generator()
|
|
664
|
+
7
|
|
665
|
+
sage: k.<a> = GF(11^3)
|
|
666
|
+
sage: k.primitive_element()
|
|
667
|
+
a
|
|
668
|
+
sage: k.<b> = GF(19^32)
|
|
669
|
+
sage: k.multiplicative_generator()
|
|
670
|
+
b + 4
|
|
671
|
+
|
|
672
|
+
TESTS:
|
|
673
|
+
|
|
674
|
+
Check that large characteristics work (:issue:`11946`)::
|
|
675
|
+
|
|
676
|
+
sage: p = 10^20 + 39
|
|
677
|
+
sage: x = polygen(GF(p))
|
|
678
|
+
sage: K.<a> = GF(p^2, modulus=x^2+1)
|
|
679
|
+
sage: K.multiplicative_generator()
|
|
680
|
+
a + 12
|
|
681
|
+
"""
|
|
682
|
+
if self.degree() == 1:
|
|
683
|
+
from sage.arith.misc import primitive_root
|
|
684
|
+
return self(primitive_root(self.order()))
|
|
685
|
+
F, = self.factored_unit_order()
|
|
686
|
+
return self._element_of_factored_order(F)
|
|
687
|
+
|
|
688
|
+
primitive_element = multiplicative_generator
|
|
689
|
+
|
|
690
|
+
def _element_of_factored_order(self, F):
|
|
691
|
+
"""
|
|
692
|
+
Return an element of ``self`` of order ``n`` where ``n`` is
|
|
693
|
+
given in factored form.
|
|
694
|
+
|
|
695
|
+
INPUT:
|
|
696
|
+
|
|
697
|
+
- ``F`` -- the factorization of the required order. The order
|
|
698
|
+
must be a divisor of ``self.order() - 1`` but this is not
|
|
699
|
+
checked.
|
|
700
|
+
|
|
701
|
+
EXAMPLES::
|
|
702
|
+
|
|
703
|
+
sage: k.<a> = GF(16, modulus=cyclotomic_polynomial(5))
|
|
704
|
+
sage: k._element_of_factored_order(factor(15))
|
|
705
|
+
a^2 + a + 1
|
|
706
|
+
sage: k._element_of_factored_order(factor(5))
|
|
707
|
+
a^3
|
|
708
|
+
sage: k._element_of_factored_order(factor(3))
|
|
709
|
+
a^3 + a^2 + 1
|
|
710
|
+
sage: k._element_of_factored_order(factor(30))
|
|
711
|
+
Traceback (most recent call last):
|
|
712
|
+
...
|
|
713
|
+
AssertionError: no element found
|
|
714
|
+
"""
|
|
715
|
+
n = Integer(1)
|
|
716
|
+
cdef list primes = []
|
|
717
|
+
for p, e in F:
|
|
718
|
+
primes.append(p)
|
|
719
|
+
n *= p ** e
|
|
720
|
+
|
|
721
|
+
N = self.order() - 1
|
|
722
|
+
c = N // n
|
|
723
|
+
|
|
724
|
+
# We check whether (x + g)^c has the required order, where
|
|
725
|
+
# x runs through the finite field.
|
|
726
|
+
# This has the advantage that g is the first element we try,
|
|
727
|
+
# so if that was a chosen to be a multiplicative generator,
|
|
728
|
+
# we are done immediately. Second, the PARI finite field
|
|
729
|
+
# iterator gives all the constant elements first, so we try
|
|
730
|
+
# (g+(constant))^c before anything else.
|
|
731
|
+
g = self.gen(0)
|
|
732
|
+
for x in self:
|
|
733
|
+
a = (g + x) ** c
|
|
734
|
+
if not a:
|
|
735
|
+
continue
|
|
736
|
+
if all(a ** (n // p) != 1 for p in primes):
|
|
737
|
+
return a
|
|
738
|
+
raise AssertionError("no element found")
|
|
739
|
+
|
|
740
|
+
def ngens(self):
|
|
741
|
+
"""
|
|
742
|
+
The number of generators of the finite field. Always 1.
|
|
743
|
+
|
|
744
|
+
EXAMPLES::
|
|
745
|
+
|
|
746
|
+
sage: k = FiniteField(3^4, 'b')
|
|
747
|
+
sage: k.ngens()
|
|
748
|
+
1
|
|
749
|
+
"""
|
|
750
|
+
return 1
|
|
751
|
+
|
|
752
|
+
def order(self):
|
|
753
|
+
"""
|
|
754
|
+
Return the order of this finite field.
|
|
755
|
+
|
|
756
|
+
EXAMPLES::
|
|
757
|
+
|
|
758
|
+
sage: GF(997).order()
|
|
759
|
+
997
|
|
760
|
+
"""
|
|
761
|
+
return self.characteristic()**self.degree()
|
|
762
|
+
|
|
763
|
+
# cached because constructing the Factorization is slow;
|
|
764
|
+
# see Issue #11628.
|
|
765
|
+
@cached_method
|
|
766
|
+
def factored_order(self):
|
|
767
|
+
"""
|
|
768
|
+
Return the factored order of this field. For compatibility with
|
|
769
|
+
:mod:`~sage.rings.finite_rings.integer_mod_ring`.
|
|
770
|
+
|
|
771
|
+
EXAMPLES::
|
|
772
|
+
|
|
773
|
+
sage: GF(7^2,'a').factored_order()
|
|
774
|
+
7^2
|
|
775
|
+
"""
|
|
776
|
+
from sage.structure.factorization import Factorization
|
|
777
|
+
return Factorization([(self.characteristic(), self.degree())])
|
|
778
|
+
|
|
779
|
+
@cached_method
|
|
780
|
+
def factored_unit_order(self):
|
|
781
|
+
"""
|
|
782
|
+
Return the factorization of ``self.order()-1``, as a 1-tuple.
|
|
783
|
+
|
|
784
|
+
The format is for compatibility with
|
|
785
|
+
:mod:`~sage.rings.finite_rings.integer_mod_ring`.
|
|
786
|
+
|
|
787
|
+
EXAMPLES::
|
|
788
|
+
|
|
789
|
+
sage: GF(7^2,'a').factored_unit_order()
|
|
790
|
+
(2^4 * 3,)
|
|
791
|
+
|
|
792
|
+
TESTS:
|
|
793
|
+
|
|
794
|
+
Check that :issue:`31686` is fixed::
|
|
795
|
+
|
|
796
|
+
sage: p = 1100585370631
|
|
797
|
+
sage: F = GF(p^24, 'a')
|
|
798
|
+
sage: F.factored_unit_order()
|
|
799
|
+
(2^6 * 3^2 * 5 * 7 * 11 * 13 * 17 * 53 * 97 * 229 * 337 * 421
|
|
800
|
+
* 3929 * 215417 * 249737 * 262519 * 397897 * 59825761 * 692192057
|
|
801
|
+
* 12506651939 * 37553789761 * 46950147799 * 172462808473 * 434045140817
|
|
802
|
+
* 81866093016401 * 617237859576697 * 659156729361017707
|
|
803
|
+
* 268083135725348991493995910983015600019336657
|
|
804
|
+
* 90433843562394341719266736354746485652016132372842876085423636587989263202299569913,)
|
|
805
|
+
"""
|
|
806
|
+
from sage.structure.factorization import Factorization
|
|
807
|
+
from sage.rings.polynomial.cyclotomic import cyclotomic_value as cv
|
|
808
|
+
p, d = self.characteristic(), self.degree()
|
|
809
|
+
F = Factorization(f for n in d.divisors() for f in cv(n, p).factor())
|
|
810
|
+
return (F,)
|
|
811
|
+
|
|
812
|
+
def cardinality(self):
|
|
813
|
+
"""
|
|
814
|
+
Return the cardinality of ``self``.
|
|
815
|
+
|
|
816
|
+
Same as :meth:`order`.
|
|
817
|
+
|
|
818
|
+
EXAMPLES::
|
|
819
|
+
|
|
820
|
+
sage: GF(997).cardinality()
|
|
821
|
+
997
|
|
822
|
+
"""
|
|
823
|
+
return self.order()
|
|
824
|
+
|
|
825
|
+
__len__ = cardinality
|
|
826
|
+
|
|
827
|
+
def is_prime_field(self):
|
|
828
|
+
"""
|
|
829
|
+
Return ``True`` if ``self`` is a prime field, i.e., has degree 1.
|
|
830
|
+
|
|
831
|
+
EXAMPLES::
|
|
832
|
+
|
|
833
|
+
sage: GF(3^7, 'a').is_prime_field()
|
|
834
|
+
False
|
|
835
|
+
sage: GF(3, 'a').is_prime_field()
|
|
836
|
+
True
|
|
837
|
+
"""
|
|
838
|
+
return self.degree() == 1
|
|
839
|
+
|
|
840
|
+
def modulus(self):
|
|
841
|
+
r"""
|
|
842
|
+
Return the minimal polynomial of the generator of ``self`` over
|
|
843
|
+
the prime finite field.
|
|
844
|
+
|
|
845
|
+
The minimal polynomial of an element `a` in a field is the
|
|
846
|
+
unique monic irreducible polynomial of smallest degree with
|
|
847
|
+
coefficients in the base field that has `a` as a root. In
|
|
848
|
+
finite field extensions, `\GF{p^n}`, the base field is `\GF{p}`.
|
|
849
|
+
|
|
850
|
+
OUTPUT: a monic polynomial over `\GF{p}` in the variable `x`
|
|
851
|
+
|
|
852
|
+
EXAMPLES::
|
|
853
|
+
|
|
854
|
+
sage: F.<a> = GF(7^2); F
|
|
855
|
+
Finite Field in a of size 7^2
|
|
856
|
+
sage: F.polynomial_ring()
|
|
857
|
+
Univariate Polynomial Ring in a over Finite Field of size 7
|
|
858
|
+
sage: f = F.modulus(); f
|
|
859
|
+
x^2 + 6*x + 3
|
|
860
|
+
sage: f(a)
|
|
861
|
+
0
|
|
862
|
+
|
|
863
|
+
Although `f` is irreducible over the base field, we can double-check
|
|
864
|
+
whether or not `f` factors in `F` as follows. The command
|
|
865
|
+
``F['x'](f)`` coerces `f` as a polynomial with coefficients in `F`.
|
|
866
|
+
(Instead of a polynomial with coefficients over the base field.)
|
|
867
|
+
|
|
868
|
+
::
|
|
869
|
+
|
|
870
|
+
sage: f.factor()
|
|
871
|
+
x^2 + 6*x + 3
|
|
872
|
+
sage: F['x'](f).factor()
|
|
873
|
+
(x + a + 6) * (x + 6*a)
|
|
874
|
+
|
|
875
|
+
Here is an example with a degree 3 extension::
|
|
876
|
+
|
|
877
|
+
sage: G.<b> = GF(7^3); G
|
|
878
|
+
Finite Field in b of size 7^3
|
|
879
|
+
sage: g = G.modulus(); g
|
|
880
|
+
x^3 + 6*x^2 + 4
|
|
881
|
+
sage: g.degree(); G.degree()
|
|
882
|
+
3
|
|
883
|
+
3
|
|
884
|
+
|
|
885
|
+
For prime fields, this returns `x - 1` unless a custom modulus
|
|
886
|
+
was given when constructing this field::
|
|
887
|
+
|
|
888
|
+
sage: k = GF(199)
|
|
889
|
+
sage: k.modulus()
|
|
890
|
+
x + 198
|
|
891
|
+
sage: var('x') # needs sage.symbolic
|
|
892
|
+
x
|
|
893
|
+
sage: k = GF(199, modulus=x+1) # needs sage.symbolic
|
|
894
|
+
sage: k.modulus() # needs sage.symbolic
|
|
895
|
+
x + 1
|
|
896
|
+
|
|
897
|
+
The given modulus is always made monic::
|
|
898
|
+
|
|
899
|
+
sage: k.<a> = GF(7^2, modulus=2*x^2 - 3, impl='pari_ffelt') # needs sage.symbolic
|
|
900
|
+
sage: k.modulus() # needs sage.symbolic
|
|
901
|
+
x^2 + 2
|
|
902
|
+
|
|
903
|
+
TESTS:
|
|
904
|
+
|
|
905
|
+
We test the various finite field implementations::
|
|
906
|
+
|
|
907
|
+
sage: GF(2, impl='modn').modulus()
|
|
908
|
+
x + 1
|
|
909
|
+
sage: GF(2, impl='givaro').modulus() # needs sage.libs.linbox
|
|
910
|
+
x + 1
|
|
911
|
+
sage: GF(2, impl='ntl').modulus() # needs sage.libs.ntl
|
|
912
|
+
x + 1
|
|
913
|
+
sage: GF(2, impl='modn', modulus=x).modulus() # needs sage.symbolics
|
|
914
|
+
x
|
|
915
|
+
sage: GF(2, impl='givaro', modulus=x).modulus() # needs sage.libs.linbox sage.symbolics
|
|
916
|
+
x
|
|
917
|
+
sage: GF(2, impl='ntl', modulus=x).modulus() # needs sage.libs.ntl sage.symbolics
|
|
918
|
+
x
|
|
919
|
+
sage: GF(13^2, 'a', impl='givaro', modulus=x^2 + 2).modulus() # needs sage.libs.linbox sage.symbolics
|
|
920
|
+
x^2 + 2
|
|
921
|
+
sage: GF(13^2, 'a', impl='pari_ffelt', modulus=x^2 + 2).modulus() # needs sage.libs.pari sage.symbolics
|
|
922
|
+
x^2 + 2
|
|
923
|
+
"""
|
|
924
|
+
# Normally, this is set by the constructor of the implementation
|
|
925
|
+
try:
|
|
926
|
+
return self._modulus
|
|
927
|
+
except AttributeError:
|
|
928
|
+
pass
|
|
929
|
+
|
|
930
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
931
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
932
|
+
R = PolynomialRing(GF(self.characteristic()), 'x')
|
|
933
|
+
self._modulus = R((-1,1)) # Polynomial x - 1
|
|
934
|
+
return self._modulus
|
|
935
|
+
|
|
936
|
+
def polynomial(self, name=None):
|
|
937
|
+
r"""
|
|
938
|
+
Return the minimal polynomial of the generator of ``self`` over
|
|
939
|
+
the prime finite field.
|
|
940
|
+
|
|
941
|
+
INPUT:
|
|
942
|
+
|
|
943
|
+
- ``name`` -- a variable name to use for the polynomial. By
|
|
944
|
+
default, use the name given when constructing this field.
|
|
945
|
+
|
|
946
|
+
OUTPUT: a monic polynomial over `\GF{p}` in the variable ``name``
|
|
947
|
+
|
|
948
|
+
.. SEEALSO::
|
|
949
|
+
|
|
950
|
+
Except for the ``name`` argument, this is identical to the
|
|
951
|
+
:meth:`modulus` method.
|
|
952
|
+
|
|
953
|
+
EXAMPLES::
|
|
954
|
+
|
|
955
|
+
sage: k.<a> = FiniteField(9)
|
|
956
|
+
sage: k.polynomial('x')
|
|
957
|
+
x^2 + 2*x + 2
|
|
958
|
+
sage: k.polynomial()
|
|
959
|
+
a^2 + 2*a + 2
|
|
960
|
+
|
|
961
|
+
sage: F = FiniteField(9, 'a', impl='pari_ffelt')
|
|
962
|
+
sage: F.polynomial()
|
|
963
|
+
a^2 + 2*a + 2
|
|
964
|
+
|
|
965
|
+
sage: F = FiniteField(7^20, 'a', impl='pari_ffelt')
|
|
966
|
+
sage: f = F.polynomial(); f
|
|
967
|
+
a^20 + a^12 + 6*a^11 + 2*a^10 + 5*a^9 + 2*a^8 + 3*a^7 + a^6 + 3*a^5 + 3*a^3 + a + 3
|
|
968
|
+
sage: f(F.gen())
|
|
969
|
+
0
|
|
970
|
+
|
|
971
|
+
sage: # needs sage.libs.ntl
|
|
972
|
+
sage: k.<a> = GF(2^20, impl='ntl')
|
|
973
|
+
sage: k.polynomial()
|
|
974
|
+
a^20 + a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1
|
|
975
|
+
sage: k.polynomial('FOO')
|
|
976
|
+
FOO^20 + FOO^10 + FOO^9 + FOO^7 + FOO^6 + FOO^5 + FOO^4 + FOO + 1
|
|
977
|
+
sage: a^20
|
|
978
|
+
a^10 + a^9 + a^7 + a^6 + a^5 + a^4 + a + 1
|
|
979
|
+
"""
|
|
980
|
+
if name is None:
|
|
981
|
+
name = self.variable_name()
|
|
982
|
+
return self.modulus().change_variable_name(name)
|
|
983
|
+
|
|
984
|
+
def unit_group_exponent(self):
|
|
985
|
+
"""
|
|
986
|
+
The exponent of the unit group of the finite field. For a
|
|
987
|
+
finite field, this is always the order minus 1.
|
|
988
|
+
|
|
989
|
+
EXAMPLES::
|
|
990
|
+
|
|
991
|
+
sage: k = GF(2^10, 'a')
|
|
992
|
+
sage: k.order()
|
|
993
|
+
1024
|
|
994
|
+
sage: k.unit_group_exponent()
|
|
995
|
+
1023
|
|
996
|
+
"""
|
|
997
|
+
return self.order() - 1
|
|
998
|
+
|
|
999
|
+
def random_element(self, *args, **kwds):
|
|
1000
|
+
r"""
|
|
1001
|
+
A random element of the finite field. Passes arguments to
|
|
1002
|
+
``random_element()`` function of underlying vector space.
|
|
1003
|
+
|
|
1004
|
+
EXAMPLES::
|
|
1005
|
+
|
|
1006
|
+
sage: k = GF(19^4, 'a')
|
|
1007
|
+
sage: k.random_element().parent() is k # needs sage.modules
|
|
1008
|
+
True
|
|
1009
|
+
|
|
1010
|
+
Passes extra positional or keyword arguments through::
|
|
1011
|
+
|
|
1012
|
+
sage: k.random_element(prob=0) # needs sage.modules
|
|
1013
|
+
0
|
|
1014
|
+
"""
|
|
1015
|
+
if self.degree() == 1:
|
|
1016
|
+
return self(randrange(self.order()))
|
|
1017
|
+
v = self.vector_space(map=False).random_element(*args, **kwds)
|
|
1018
|
+
return self(v)
|
|
1019
|
+
|
|
1020
|
+
def some_elements(self):
|
|
1021
|
+
"""
|
|
1022
|
+
Return a collection of elements of this finite field for use in unit
|
|
1023
|
+
testing.
|
|
1024
|
+
|
|
1025
|
+
EXAMPLES::
|
|
1026
|
+
|
|
1027
|
+
sage: k = GF(2^8,'a')
|
|
1028
|
+
sage: k.some_elements() # random output # needs sage.modules
|
|
1029
|
+
[a^4 + a^3 + 1, a^6 + a^4 + a^3, a^5 + a^4 + a, a^2 + a]
|
|
1030
|
+
"""
|
|
1031
|
+
return [self.random_element() for i in range(4)]
|
|
1032
|
+
|
|
1033
|
+
def polynomial_ring(self, variable_name=None):
|
|
1034
|
+
"""
|
|
1035
|
+
Return the polynomial ring over the prime subfield in the
|
|
1036
|
+
same variable as this finite field.
|
|
1037
|
+
|
|
1038
|
+
EXAMPLES::
|
|
1039
|
+
|
|
1040
|
+
sage: k.<alpha> = FiniteField(3^4)
|
|
1041
|
+
sage: k.polynomial_ring()
|
|
1042
|
+
Univariate Polynomial Ring in alpha over Finite Field of size 3
|
|
1043
|
+
"""
|
|
1044
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
1045
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
1046
|
+
|
|
1047
|
+
if variable_name is None and self.__polynomial_ring is not None:
|
|
1048
|
+
return self.__polynomial_ring
|
|
1049
|
+
else:
|
|
1050
|
+
if variable_name is None:
|
|
1051
|
+
self.__polynomial_ring = PolynomialRing(GF(self.characteristic()), self.variable_name())
|
|
1052
|
+
return self.__polynomial_ring
|
|
1053
|
+
else:
|
|
1054
|
+
return PolynomialRing(GF(self.characteristic()), variable_name)
|
|
1055
|
+
|
|
1056
|
+
def free_module(self, base=None, basis=None, map=True):
|
|
1057
|
+
"""
|
|
1058
|
+
Return the vector space over the subfield isomorphic to this
|
|
1059
|
+
finite field as a vector space, along with the isomorphisms.
|
|
1060
|
+
|
|
1061
|
+
INPUT:
|
|
1062
|
+
|
|
1063
|
+
- ``base`` -- a subfield of or a morphism into this finite field.
|
|
1064
|
+
If not given, the prime subfield is assumed. A subfield means
|
|
1065
|
+
a finite field with coercion to this finite field.
|
|
1066
|
+
|
|
1067
|
+
- ``basis`` -- a basis of the finite field as a vector space
|
|
1068
|
+
over the subfield. If not given, one is chosen automatically.
|
|
1069
|
+
|
|
1070
|
+
- ``map`` -- boolean (default: ``True``); if ``True``, isomorphisms
|
|
1071
|
+
from and to the vector space are also returned
|
|
1072
|
+
|
|
1073
|
+
The ``basis`` maps to the standard basis of the vector space
|
|
1074
|
+
by the isomorphisms.
|
|
1075
|
+
|
|
1076
|
+
OUTPUT: if ``map`` is ``False``,
|
|
1077
|
+
|
|
1078
|
+
- vector space over the subfield or the domain of the morphism,
|
|
1079
|
+
isomorphic to this finite field.
|
|
1080
|
+
|
|
1081
|
+
and if ``map`` is ``True``, then also
|
|
1082
|
+
|
|
1083
|
+
- an isomorphism from the vector space to the finite field.
|
|
1084
|
+
|
|
1085
|
+
- the inverse isomorphism to the vector space from the finite field.
|
|
1086
|
+
|
|
1087
|
+
EXAMPLES::
|
|
1088
|
+
|
|
1089
|
+
sage: GF(27,'a').vector_space(map=False) # needs sage.modules
|
|
1090
|
+
Vector space of dimension 3 over Finite Field of size 3
|
|
1091
|
+
|
|
1092
|
+
sage: # needs sage.modules
|
|
1093
|
+
sage: F = GF(8)
|
|
1094
|
+
sage: E = GF(64)
|
|
1095
|
+
sage: V, from_V, to_V = E.vector_space(F, map=True)
|
|
1096
|
+
sage: V
|
|
1097
|
+
Vector space of dimension 2 over Finite Field in z3 of size 2^3
|
|
1098
|
+
sage: to_V(E.gen())
|
|
1099
|
+
(0, 1)
|
|
1100
|
+
sage: all(from_V(to_V(e)) == e for e in E)
|
|
1101
|
+
True
|
|
1102
|
+
sage: all(to_V(e1 + e2) == to_V(e1) + to_V(e2) for e1 in E for e2 in E)
|
|
1103
|
+
True
|
|
1104
|
+
sage: all(to_V(c * e) == c * to_V(e) for e in E for c in F)
|
|
1105
|
+
True
|
|
1106
|
+
|
|
1107
|
+
sage: # needs sage.modules
|
|
1108
|
+
sage: basis = [E.gen(), E.gen() + 1]
|
|
1109
|
+
sage: W, from_W, to_W = E.vector_space(F, basis, map=True)
|
|
1110
|
+
sage: all(from_W(to_W(e)) == e for e in E)
|
|
1111
|
+
True
|
|
1112
|
+
sage: all(to_W(c * e) == c * to_W(e) for e in E for c in F)
|
|
1113
|
+
True
|
|
1114
|
+
sage: all(to_W(e1 + e2) == to_W(e1) + to_W(e2) for e1 in E for e2 in E) # long time
|
|
1115
|
+
True
|
|
1116
|
+
sage: to_W(basis[0]); to_W(basis[1])
|
|
1117
|
+
(1, 0)
|
|
1118
|
+
(0, 1)
|
|
1119
|
+
|
|
1120
|
+
sage: # needs sage.modules
|
|
1121
|
+
sage: x = polygen(ZZ)
|
|
1122
|
+
sage: F = GF(9, 't', modulus=x^2 + x - 1)
|
|
1123
|
+
sage: E = GF(81)
|
|
1124
|
+
sage: h = Hom(F,E).an_element()
|
|
1125
|
+
sage: V, from_V, to_V = E.vector_space(h, map=True)
|
|
1126
|
+
sage: V
|
|
1127
|
+
Vector space of dimension 2 over Finite Field in t of size 3^2
|
|
1128
|
+
sage: V.base_ring() is F
|
|
1129
|
+
True
|
|
1130
|
+
sage: all(from_V(to_V(e)) == e for e in E)
|
|
1131
|
+
True
|
|
1132
|
+
sage: all(to_V(e1 + e2) == to_V(e1) + to_V(e2) for e1 in E for e2 in E)
|
|
1133
|
+
True
|
|
1134
|
+
sage: all(to_V(h(c) * e) == c * to_V(e) for e in E for c in F)
|
|
1135
|
+
True
|
|
1136
|
+
"""
|
|
1137
|
+
if base is None and self.__vector_space is not None and not map:
|
|
1138
|
+
# A very common case: return as early as possible.
|
|
1139
|
+
return self.__vector_space
|
|
1140
|
+
|
|
1141
|
+
from sage.modules.free_module import VectorSpace
|
|
1142
|
+
from sage.categories.morphism import Morphism
|
|
1143
|
+
|
|
1144
|
+
if base is None:
|
|
1145
|
+
base = self.prime_subfield()
|
|
1146
|
+
s = self.degree()
|
|
1147
|
+
if self.__vector_space is None:
|
|
1148
|
+
self.__vector_space = VectorSpace(base, s)
|
|
1149
|
+
V = self.__vector_space
|
|
1150
|
+
inclusion_map = None
|
|
1151
|
+
elif isinstance(base, Morphism):
|
|
1152
|
+
inclusion_map = base
|
|
1153
|
+
base = inclusion_map.domain()
|
|
1154
|
+
s = self.degree() // base.degree()
|
|
1155
|
+
V = VectorSpace(base, s)
|
|
1156
|
+
elif base.is_subring(self):
|
|
1157
|
+
s = self.degree() // base.degree()
|
|
1158
|
+
V = VectorSpace(base, s)
|
|
1159
|
+
inclusion_map = None
|
|
1160
|
+
else:
|
|
1161
|
+
raise ValueError("{} is not a subfield".format(base))
|
|
1162
|
+
|
|
1163
|
+
if map is False: # shortcut
|
|
1164
|
+
return V
|
|
1165
|
+
|
|
1166
|
+
if inclusion_map is None:
|
|
1167
|
+
inclusion_map = self.coerce_map_from(base)
|
|
1168
|
+
|
|
1169
|
+
from sage.matrix.constructor import matrix
|
|
1170
|
+
from sage.rings.finite_rings.maps_finite_field import (
|
|
1171
|
+
MorphismVectorSpaceToFiniteField, MorphismFiniteFieldToVectorSpace)
|
|
1172
|
+
|
|
1173
|
+
E = self
|
|
1174
|
+
F = base
|
|
1175
|
+
|
|
1176
|
+
alpha = E.gen()
|
|
1177
|
+
beta = F.gen()
|
|
1178
|
+
|
|
1179
|
+
if basis is None:
|
|
1180
|
+
basis = [alpha**i for i in range(s)] # of E over F
|
|
1181
|
+
|
|
1182
|
+
F_basis = [beta**i for i in range(F.degree())]
|
|
1183
|
+
|
|
1184
|
+
# E_basis_alpha is the implicit basis of E over the prime subfield
|
|
1185
|
+
E_basis_beta = [inclusion_map(F_basis[i]) * basis[j]
|
|
1186
|
+
for j in range(s)
|
|
1187
|
+
for i in range(F.degree())]
|
|
1188
|
+
|
|
1189
|
+
C = matrix(E.prime_subfield(), E.degree(), E.degree(),
|
|
1190
|
+
[E_basis_beta[i]._vector_() for i in range(E.degree())])
|
|
1191
|
+
C.set_immutable()
|
|
1192
|
+
Cinv = C.inverse()
|
|
1193
|
+
Cinv.set_immutable()
|
|
1194
|
+
|
|
1195
|
+
phi = MorphismVectorSpaceToFiniteField(V, self, C)
|
|
1196
|
+
psi = MorphismFiniteFieldToVectorSpace(self, V, Cinv)
|
|
1197
|
+
|
|
1198
|
+
return V, phi, psi
|
|
1199
|
+
|
|
1200
|
+
cpdef _coerce_map_from_(self, R):
|
|
1201
|
+
r"""
|
|
1202
|
+
Canonical coercion to ``self``.
|
|
1203
|
+
|
|
1204
|
+
TESTS::
|
|
1205
|
+
|
|
1206
|
+
sage: k.<a> = GF(2^8)
|
|
1207
|
+
sage: a + 1
|
|
1208
|
+
a + 1
|
|
1209
|
+
sage: a + int(1)
|
|
1210
|
+
a + 1
|
|
1211
|
+
sage: a + GF(2)(1)
|
|
1212
|
+
a + 1
|
|
1213
|
+
|
|
1214
|
+
sage: k.<a> = GF(3^8)
|
|
1215
|
+
sage: a + 1
|
|
1216
|
+
a + 1
|
|
1217
|
+
sage: a + int(1)
|
|
1218
|
+
a + 1
|
|
1219
|
+
sage: a + GF(3)(1)
|
|
1220
|
+
a + 1
|
|
1221
|
+
|
|
1222
|
+
sage: k = GF(4, 'a')
|
|
1223
|
+
sage: k.coerce(GF(2)(1))
|
|
1224
|
+
1
|
|
1225
|
+
sage: k.coerce(k.0)
|
|
1226
|
+
a
|
|
1227
|
+
sage: k.coerce(3)
|
|
1228
|
+
1
|
|
1229
|
+
sage: k.coerce(2/3)
|
|
1230
|
+
Traceback (most recent call last):
|
|
1231
|
+
...
|
|
1232
|
+
TypeError: no canonical coercion from Rational Field to Finite Field in a of size 2^2
|
|
1233
|
+
|
|
1234
|
+
sage: FiniteField(16).coerce(FiniteField(4).0)
|
|
1235
|
+
z4^2 + z4
|
|
1236
|
+
|
|
1237
|
+
sage: FiniteField(8, 'a').coerce(FiniteField(4, 'a').0)
|
|
1238
|
+
Traceback (most recent call last):
|
|
1239
|
+
...
|
|
1240
|
+
TypeError: no canonical coercion from Finite Field in a of size 2^2 to Finite Field in a of size 2^3
|
|
1241
|
+
|
|
1242
|
+
sage: FiniteField(8, 'a').coerce(FiniteField(7, 'a')(2))
|
|
1243
|
+
Traceback (most recent call last):
|
|
1244
|
+
...
|
|
1245
|
+
TypeError: no canonical coercion from Finite Field of size 7 to Finite Field in a of size 2^3
|
|
1246
|
+
|
|
1247
|
+
There is no coercion from a `p`-adic ring to its residue field::
|
|
1248
|
+
|
|
1249
|
+
sage: # needs sage.libs.ntl sage.rings.padics
|
|
1250
|
+
sage: R.<a> = Zq(81); k = R.residue_field()
|
|
1251
|
+
sage: k.has_coerce_map_from(R)
|
|
1252
|
+
False
|
|
1253
|
+
"""
|
|
1254
|
+
from sage.rings.integer_ring import ZZ
|
|
1255
|
+
if R is int or R is ZZ:
|
|
1256
|
+
return True
|
|
1257
|
+
if isinstance(R, sage.rings.abc.IntegerModRing) and self.characteristic().divides(R.characteristic()):
|
|
1258
|
+
return R.hom((self.one(),), check=False)
|
|
1259
|
+
if isinstance(R, FiniteField):
|
|
1260
|
+
if R is self:
|
|
1261
|
+
return True
|
|
1262
|
+
from sage.rings.finite_rings.residue_field import ResidueField_generic
|
|
1263
|
+
if isinstance(R, ResidueField_generic):
|
|
1264
|
+
return False
|
|
1265
|
+
if R.characteristic() == self.characteristic():
|
|
1266
|
+
if R.degree() == 1:
|
|
1267
|
+
return R.hom((self.one(),), check=False)
|
|
1268
|
+
elif (R.degree().divides(self.degree())
|
|
1269
|
+
and hasattr(self, '_prefix') and hasattr(R, '_prefix')):
|
|
1270
|
+
return R.hom((self.gen() ** ((self.order() - 1)//(R.order() - 1)),))
|
|
1271
|
+
|
|
1272
|
+
cpdef _convert_map_from_(self, R):
|
|
1273
|
+
"""
|
|
1274
|
+
Conversion from `p`-adic fields.
|
|
1275
|
+
|
|
1276
|
+
EXAMPLES::
|
|
1277
|
+
|
|
1278
|
+
sage: K.<a> = Qq(49); k = K.residue_field() # needs sage.rings.padics
|
|
1279
|
+
sage: k.convert_map_from(K) # needs sage.rings.padics
|
|
1280
|
+
Reduction morphism:
|
|
1281
|
+
From: 7-adic Unramified Extension Field in a defined by x^2 + 6*x + 3
|
|
1282
|
+
To: Finite Field in a0 of size 7^2
|
|
1283
|
+
|
|
1284
|
+
Check that :issue:`8240 is resolved::
|
|
1285
|
+
|
|
1286
|
+
sage: R.<a> = Zq(81); k = R.residue_field() # needs sage.rings.padics
|
|
1287
|
+
sage: k.convert_map_from(R) # needs sage.rings.padics
|
|
1288
|
+
Reduction morphism:
|
|
1289
|
+
From: 3-adic Unramified Extension Ring in a defined by x^4 + 2*x^3 + 2
|
|
1290
|
+
To: Finite Field in a0 of size 3^4
|
|
1291
|
+
"""
|
|
1292
|
+
from sage.rings.padics.padic_generic import pAdicGeneric, ResidueReductionMap
|
|
1293
|
+
if isinstance(R, pAdicGeneric) and R.residue_field() is self:
|
|
1294
|
+
return ResidueReductionMap._create_(R, self)
|
|
1295
|
+
|
|
1296
|
+
def construction(self):
|
|
1297
|
+
"""
|
|
1298
|
+
Return the construction of this finite field, as a ``ConstructionFunctor``
|
|
1299
|
+
and the base field.
|
|
1300
|
+
|
|
1301
|
+
EXAMPLES::
|
|
1302
|
+
|
|
1303
|
+
sage: v = GF(3^3).construction(); v
|
|
1304
|
+
(AlgebraicExtensionFunctor, Finite Field of size 3)
|
|
1305
|
+
sage: v[0].polys[0]
|
|
1306
|
+
3
|
|
1307
|
+
sage: v = GF(2^1000, 'a').construction(); v[0].polys[0]
|
|
1308
|
+
a^1000 + a^5 + a^4 + a^3 + 1
|
|
1309
|
+
|
|
1310
|
+
The implementation is taken into account, by :issue:`15223`::
|
|
1311
|
+
|
|
1312
|
+
sage: k = FiniteField(9, 'a', impl='pari_ffelt')
|
|
1313
|
+
sage: F, R = k.construction()
|
|
1314
|
+
sage: F(R) is k
|
|
1315
|
+
True
|
|
1316
|
+
"""
|
|
1317
|
+
from sage.categories.pushout import AlgebraicExtensionFunctor
|
|
1318
|
+
try:
|
|
1319
|
+
kwds = {'impl': self._factory_data[2][3]}
|
|
1320
|
+
except (AttributeError, IndexError, TypeError):
|
|
1321
|
+
kwds = {}
|
|
1322
|
+
if self.degree() == 1:
|
|
1323
|
+
# this is not of type FiniteField_prime_modn
|
|
1324
|
+
from sage.rings.integer import Integer
|
|
1325
|
+
return AlgebraicExtensionFunctor([self.polynomial()], [None], [None], **kwds), self.base_ring()
|
|
1326
|
+
elif hasattr(self, '_prefix'):
|
|
1327
|
+
return (AlgebraicExtensionFunctor([self.degree()], [self.variable_name()], [None],
|
|
1328
|
+
prefix=self._prefix, **kwds),
|
|
1329
|
+
self.base_ring())
|
|
1330
|
+
else:
|
|
1331
|
+
return (AlgebraicExtensionFunctor([self.polynomial()],
|
|
1332
|
+
[self.variable_name()], [None],
|
|
1333
|
+
**kwds),
|
|
1334
|
+
self.base_ring())
|
|
1335
|
+
|
|
1336
|
+
def extension(self, modulus, name=None, names=None, map=False, embedding=None,
|
|
1337
|
+
*, latex_name=None, latex_names=None, **kwds):
|
|
1338
|
+
"""
|
|
1339
|
+
Return an extension of this finite field.
|
|
1340
|
+
|
|
1341
|
+
INPUT:
|
|
1342
|
+
|
|
1343
|
+
- ``modulus`` -- a polynomial with coefficients in ``self``,
|
|
1344
|
+
or an integer
|
|
1345
|
+
|
|
1346
|
+
- ``name`` or ``names`` -- string; the name of the generator
|
|
1347
|
+
in the new extension
|
|
1348
|
+
|
|
1349
|
+
- ``latex_name`` or ``latex_names`` -- string; latex name of
|
|
1350
|
+
the generator in the new extension
|
|
1351
|
+
|
|
1352
|
+
- ``map`` -- boolean (default: ``False``); if ``False``,
|
|
1353
|
+
return just the extension `E`. If ``True``, return a pair
|
|
1354
|
+
`(E, f)`, where `f` is an embedding of ``self`` into `E`.
|
|
1355
|
+
|
|
1356
|
+
- ``embedding`` -- currently not used; for compatibility with
|
|
1357
|
+
other ``AlgebraicExtensionFunctor`` calls
|
|
1358
|
+
|
|
1359
|
+
- ``**kwds`` -- further keywords, passed to the finite field
|
|
1360
|
+
constructor.
|
|
1361
|
+
|
|
1362
|
+
OUTPUT:
|
|
1363
|
+
|
|
1364
|
+
An extension of the given modulus, or pseudo-Conway of the
|
|
1365
|
+
given degree if ``modulus`` is an integer.
|
|
1366
|
+
|
|
1367
|
+
EXAMPLES::
|
|
1368
|
+
|
|
1369
|
+
sage: k = GF(2)
|
|
1370
|
+
sage: R.<x> = k[]
|
|
1371
|
+
sage: k.extension(x^1000 + x^5 + x^4 + x^3 + 1, 'a')
|
|
1372
|
+
Finite Field in a of size 2^1000
|
|
1373
|
+
sage: k = GF(3^4)
|
|
1374
|
+
sage: R.<x> = k[]
|
|
1375
|
+
sage: k.extension(3)
|
|
1376
|
+
Finite Field in z12 of size 3^12
|
|
1377
|
+
sage: K = k.extension(2, 'a')
|
|
1378
|
+
sage: k.is_subring(K)
|
|
1379
|
+
True
|
|
1380
|
+
|
|
1381
|
+
An example using the ``map`` argument::
|
|
1382
|
+
|
|
1383
|
+
sage: F = GF(5)
|
|
1384
|
+
sage: E, f = F.extension(2, 'b', map=True)
|
|
1385
|
+
sage: E
|
|
1386
|
+
Finite Field in b of size 5^2
|
|
1387
|
+
sage: f
|
|
1388
|
+
Ring morphism:
|
|
1389
|
+
From: Finite Field of size 5
|
|
1390
|
+
To: Finite Field in b of size 5^2
|
|
1391
|
+
Defn: 1 |--> 1
|
|
1392
|
+
sage: f.parent()
|
|
1393
|
+
Set of field embeddings
|
|
1394
|
+
from Finite Field of size 5
|
|
1395
|
+
to Finite Field in b of size 5^2
|
|
1396
|
+
|
|
1397
|
+
Extensions of non-prime finite fields by polynomials are not yet
|
|
1398
|
+
supported: we fall back to generic code::
|
|
1399
|
+
|
|
1400
|
+
sage: k.extension(x^5 + x^2 + x - 1)
|
|
1401
|
+
Univariate Quotient Polynomial Ring in x over Finite Field in z4 of size 3^4
|
|
1402
|
+
with modulus x^5 + x^2 + x + 2
|
|
1403
|
+
|
|
1404
|
+
TESTS:
|
|
1405
|
+
|
|
1406
|
+
We check that :issue:`18915` is fixed::
|
|
1407
|
+
|
|
1408
|
+
sage: F = GF(2)
|
|
1409
|
+
sage: F.extension(int(3), 'a')
|
|
1410
|
+
Finite Field in a of size 2^3
|
|
1411
|
+
|
|
1412
|
+
sage: F = GF((2,4), 'a')
|
|
1413
|
+
sage: F.extension(int(3), 'aa')
|
|
1414
|
+
Finite Field in aa of size 2^12
|
|
1415
|
+
|
|
1416
|
+
Randomized test for :issue:`33937`::
|
|
1417
|
+
|
|
1418
|
+
sage: p = random_prime(100)
|
|
1419
|
+
sage: a,b = (randrange(1,10) for _ in 'ab')
|
|
1420
|
+
sage: K.<u> = GF((p,a))
|
|
1421
|
+
sage: L.<v> = K.extension(b)
|
|
1422
|
+
sage: L(u).minpoly() == u.minpoly()
|
|
1423
|
+
True
|
|
1424
|
+
"""
|
|
1425
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
1426
|
+
from sage.rings.polynomial.polynomial_element import Polynomial
|
|
1427
|
+
from sage.rings.integer import Integer
|
|
1428
|
+
if name is None and names is not None:
|
|
1429
|
+
name = names
|
|
1430
|
+
if latex_name is None and latex_names is not None:
|
|
1431
|
+
latex_name = latex_names
|
|
1432
|
+
if self.degree() == 1:
|
|
1433
|
+
if isinstance(modulus, (int, Integer)):
|
|
1434
|
+
E = GF((self.characteristic(), modulus), name=name, **kwds)
|
|
1435
|
+
elif isinstance(modulus, (list, tuple)):
|
|
1436
|
+
E = GF((self.characteristic(), len(modulus) - 1), name=name, modulus=modulus, **kwds)
|
|
1437
|
+
elif isinstance(modulus, Polynomial):
|
|
1438
|
+
if modulus.change_ring(self).is_irreducible():
|
|
1439
|
+
E = GF((self.characteristic(), modulus.degree()), name=name, modulus=modulus, **kwds)
|
|
1440
|
+
else:
|
|
1441
|
+
E = Field.extension(self, modulus, name=name, embedding=embedding, **kwds)
|
|
1442
|
+
elif isinstance(modulus, (int, Integer)):
|
|
1443
|
+
E = GF((self.characteristic(), self.degree() * modulus), name=name, **kwds)
|
|
1444
|
+
if E is self:
|
|
1445
|
+
pass # coercion map (identity map) is automatically found
|
|
1446
|
+
elif hasattr(E, '_prefix') and hasattr(self, '_prefix'):
|
|
1447
|
+
pass # coercion map is automatically found
|
|
1448
|
+
else:
|
|
1449
|
+
if self.is_conway() and E.is_conway():
|
|
1450
|
+
alpha = E.gen()**((E.order()-1)//(self.order()-1))
|
|
1451
|
+
else:
|
|
1452
|
+
alpha = self.modulus().any_root(E)
|
|
1453
|
+
try: # to register a coercion map (embedding of self to E)
|
|
1454
|
+
E.register_coercion(self.hom([alpha], codomain=E, check=False))
|
|
1455
|
+
except AssertionError: # coercion already exists
|
|
1456
|
+
pass
|
|
1457
|
+
else:
|
|
1458
|
+
E = Field.extension(self, modulus, name=name, embedding=embedding, latex_name=latex_name, **kwds)
|
|
1459
|
+
if map:
|
|
1460
|
+
return (E, E.coerce_map_from(self))
|
|
1461
|
+
else:
|
|
1462
|
+
return E
|
|
1463
|
+
|
|
1464
|
+
@cached_method
|
|
1465
|
+
def _compatible_family(self):
|
|
1466
|
+
"""
|
|
1467
|
+
Return a family of elements of this field that generate each subfield in a compatible way.
|
|
1468
|
+
|
|
1469
|
+
OUTPUT:
|
|
1470
|
+
|
|
1471
|
+
- A dictionary `D` so that if `n` is a positive integer dividing the degree of this field then
|
|
1472
|
+
``D[n] = (a, f)`` where `a` generates the subfield of order `p^n` and `f` is the minimal polynomial of `a`.
|
|
1473
|
+
Moreover, if `a` and `b` are elements in this family of degree `m` and `n` respectively and `m` divides `n`
|
|
1474
|
+
then `a = b^{(p^n-1)/(p^m-1)}`.
|
|
1475
|
+
|
|
1476
|
+
EXAMPLES::
|
|
1477
|
+
|
|
1478
|
+
sage: k.<a> = GF(3^72)
|
|
1479
|
+
sage: F = k._compatible_family()
|
|
1480
|
+
sage: all(f(b) == 0 for (b, f) in F.values())
|
|
1481
|
+
True
|
|
1482
|
+
sage: all(f.degree() == n for (n, (b, f)) in F.items())
|
|
1483
|
+
True
|
|
1484
|
+
sage: D = 72.divisors()
|
|
1485
|
+
sage: for (m,n) in zip(D, D):
|
|
1486
|
+
....: if (n/m) in [2,3]:
|
|
1487
|
+
....: b, c = F[m][0], F[n][0]
|
|
1488
|
+
....: assert c^((3^n-1)//(3^m-1)) == b
|
|
1489
|
+
"""
|
|
1490
|
+
p = self.characteristic()
|
|
1491
|
+
# We try to use the appropriate power of the generator,
|
|
1492
|
+
# as in the definition of Conway polynomials.
|
|
1493
|
+
# this can fail if the generator is not a primitive element,
|
|
1494
|
+
# but it can succeed sometimes even
|
|
1495
|
+
# if the generator is not primitive.
|
|
1496
|
+
g = self.gen()
|
|
1497
|
+
f = self.modulus()
|
|
1498
|
+
d = self.degree()
|
|
1499
|
+
D = list(reversed(d.divisors()[:-1]))
|
|
1500
|
+
P = d.support()
|
|
1501
|
+
|
|
1502
|
+
def make_family(gen, poly):
|
|
1503
|
+
if poly.degree() != d:
|
|
1504
|
+
return False, {}
|
|
1505
|
+
fam = {d: (gen, poly)}
|
|
1506
|
+
for n in D:
|
|
1507
|
+
for l in P:
|
|
1508
|
+
if l*n in fam:
|
|
1509
|
+
a, _ = fam[l*n]
|
|
1510
|
+
b = a**((p**(l*n) - 1)//(p**n - 1))
|
|
1511
|
+
bpoly = b.minimal_polynomial()
|
|
1512
|
+
if bpoly.degree() != n:
|
|
1513
|
+
return False, fam
|
|
1514
|
+
fam[n] = (b, bpoly)
|
|
1515
|
+
return True, fam
|
|
1516
|
+
while True:
|
|
1517
|
+
ok, fam = make_family(g, f)
|
|
1518
|
+
if ok:
|
|
1519
|
+
return fam
|
|
1520
|
+
g = self.random_element()
|
|
1521
|
+
f = g.minimal_polynomial()
|
|
1522
|
+
|
|
1523
|
+
def subfield(self, degree, name=None, map=False):
|
|
1524
|
+
"""
|
|
1525
|
+
Return the subfield of the field of ``degree``.
|
|
1526
|
+
|
|
1527
|
+
The inclusion maps between these subfields will always commute, but they are only added as coercion maps
|
|
1528
|
+
if the following condition holds for the generator `g` of the field, where `d` is the degree of this field
|
|
1529
|
+
over the prime field:
|
|
1530
|
+
|
|
1531
|
+
The element `g^{(p^d - 1)/(p^n - 1)}` generates the subfield of degree `n` for all divisors `n` of `d`.
|
|
1532
|
+
|
|
1533
|
+
INPUT:
|
|
1534
|
+
|
|
1535
|
+
- ``degree`` -- integer; degree of the subfield
|
|
1536
|
+
|
|
1537
|
+
- ``name`` -- string; name of the generator of the subfield
|
|
1538
|
+
|
|
1539
|
+
- ``map`` -- boolean (default: ``False``); whether to also return the inclusion map
|
|
1540
|
+
|
|
1541
|
+
EXAMPLES::
|
|
1542
|
+
|
|
1543
|
+
sage: k = GF(2^21)
|
|
1544
|
+
sage: k.subfield(3)
|
|
1545
|
+
Finite Field in z3 of size 2^3
|
|
1546
|
+
sage: k.subfield(7, 'a')
|
|
1547
|
+
Finite Field in a of size 2^7
|
|
1548
|
+
sage: k.coerce_map_from(_)
|
|
1549
|
+
Ring morphism:
|
|
1550
|
+
From: Finite Field in a of size 2^7
|
|
1551
|
+
To: Finite Field in z21 of size 2^21
|
|
1552
|
+
Defn: a |--> z21^20 + z21^19 + z21^17 + z21^15 + z21^14 + z21^6 + z21^4 + z21^3 + z21
|
|
1553
|
+
sage: k.subfield(8)
|
|
1554
|
+
Traceback (most recent call last):
|
|
1555
|
+
...
|
|
1556
|
+
ValueError: no subfield of order 2^8
|
|
1557
|
+
|
|
1558
|
+
TESTS:
|
|
1559
|
+
|
|
1560
|
+
We check that :issue:`23801` is resolved::
|
|
1561
|
+
|
|
1562
|
+
sage: k.<a> = GF(5^240)
|
|
1563
|
+
sage: l, inc = k.subfield(3, 'z', map=True); l # needs sage.modules
|
|
1564
|
+
Finite Field in z of size 5^3
|
|
1565
|
+
sage: inc # needs sage.modules
|
|
1566
|
+
Ring morphism:
|
|
1567
|
+
From: Finite Field in z of size 5^3
|
|
1568
|
+
To: Finite Field in a of size 5^240
|
|
1569
|
+
Defn: z |--> ...
|
|
1570
|
+
|
|
1571
|
+
There is no coercion since we can't ensure compatibility with larger
|
|
1572
|
+
fields in this case::
|
|
1573
|
+
|
|
1574
|
+
sage: k.has_coerce_map_from(l) # needs sage.modules
|
|
1575
|
+
False
|
|
1576
|
+
|
|
1577
|
+
But there is still a compatibility among the generators chosen for the subfields::
|
|
1578
|
+
|
|
1579
|
+
sage: # needs sage.modules
|
|
1580
|
+
sage: ll, iinc = k.subfield(12, 'w', map=True)
|
|
1581
|
+
sage: x = iinc(ll.gen())^((5^12-1)/(5^3-1))
|
|
1582
|
+
sage: x.minimal_polynomial() == l.modulus()
|
|
1583
|
+
True
|
|
1584
|
+
|
|
1585
|
+
sage: S = GF(37^16).subfields()
|
|
1586
|
+
sage: len(S) == len(16.divisors())
|
|
1587
|
+
True
|
|
1588
|
+
sage: all(f is not None for (l, f) in S)
|
|
1589
|
+
True
|
|
1590
|
+
|
|
1591
|
+
sage: S = GF(2^93).subfields()
|
|
1592
|
+
sage: len(S) == len(93.divisors())
|
|
1593
|
+
True
|
|
1594
|
+
sage: all(f is not None for (l, f) in S)
|
|
1595
|
+
True
|
|
1596
|
+
|
|
1597
|
+
We choose a default variable name::
|
|
1598
|
+
|
|
1599
|
+
sage: GF(3^8, 'a').subfield(4)
|
|
1600
|
+
Finite Field in a4 of size 3^4
|
|
1601
|
+
"""
|
|
1602
|
+
from sage.rings.finite_rings.finite_field_constructor import GF
|
|
1603
|
+
p = self.characteristic()
|
|
1604
|
+
n = self.degree()
|
|
1605
|
+
if not n % degree == 0:
|
|
1606
|
+
raise ValueError("no subfield of order {}^{}".format(p, degree))
|
|
1607
|
+
|
|
1608
|
+
if name is None:
|
|
1609
|
+
if hasattr(self, '_prefix'):
|
|
1610
|
+
name = self._prefix + str(degree)
|
|
1611
|
+
else:
|
|
1612
|
+
name = self.variable_name() + str(degree)
|
|
1613
|
+
|
|
1614
|
+
if degree == 1:
|
|
1615
|
+
K = self.prime_subfield()
|
|
1616
|
+
inc = self.coerce_map_from(K)
|
|
1617
|
+
elif degree == n:
|
|
1618
|
+
K = self
|
|
1619
|
+
inc = self.coerce_map_from(self)
|
|
1620
|
+
elif hasattr(self, '_prefix'):
|
|
1621
|
+
modulus = self.prime_subfield().algebraic_closure(self._prefix)._get_polynomial(degree)
|
|
1622
|
+
K = GF((p, degree), name=name, prefix=self._prefix, modulus=modulus, check_irreducible=False)
|
|
1623
|
+
a = self.gen()**((p**n-1)//(p**degree - 1))
|
|
1624
|
+
inc = K.hom([a], codomain=self, check=False)
|
|
1625
|
+
else:
|
|
1626
|
+
fam = self._compatible_family()
|
|
1627
|
+
a, modulus = fam[degree]
|
|
1628
|
+
K = GF((p, degree), modulus=modulus, name=name)
|
|
1629
|
+
inc = K.hom([a], codomain=self, check=False)
|
|
1630
|
+
if fam[n][0] == self.gen():
|
|
1631
|
+
try: # to register a coercion map, embedding of K to self
|
|
1632
|
+
self.register_coercion(inc)
|
|
1633
|
+
except AssertionError: # coercion already exists
|
|
1634
|
+
pass
|
|
1635
|
+
if map:
|
|
1636
|
+
return K, inc
|
|
1637
|
+
else:
|
|
1638
|
+
return K
|
|
1639
|
+
|
|
1640
|
+
def subfields(self, degree=0, name=None):
|
|
1641
|
+
"""
|
|
1642
|
+
Return all subfields of ``self`` of the given ``degree``,
|
|
1643
|
+
or all possible degrees if ``degree`` is `0`.
|
|
1644
|
+
|
|
1645
|
+
The subfields are returned as absolute fields together with
|
|
1646
|
+
an embedding into ``self``.
|
|
1647
|
+
|
|
1648
|
+
INPUT:
|
|
1649
|
+
|
|
1650
|
+
- ``degree`` -- integer (default: `0`)
|
|
1651
|
+
|
|
1652
|
+
- ``name`` -- string; a dictionary or ``None``:
|
|
1653
|
+
|
|
1654
|
+
- If ``degree`` is nonzero, then ``name`` must be a string
|
|
1655
|
+
(or ``None``, if this is a pseudo-Conway extension),
|
|
1656
|
+
and will be the variable name of the returned field.
|
|
1657
|
+
- If ``degree`` is zero, the dictionary should have keys the divisors
|
|
1658
|
+
of the degree of this field, with the desired variable name for the
|
|
1659
|
+
field of that degree as an entry.
|
|
1660
|
+
- As a shortcut, you can provide a string and the degree of each
|
|
1661
|
+
subfield will be appended for the variable name of that subfield.
|
|
1662
|
+
- If ``None``, uses the prefix of this field.
|
|
1663
|
+
|
|
1664
|
+
OUTPUT:
|
|
1665
|
+
|
|
1666
|
+
A list of pairs ``(K, e)``, where ``K`` ranges over the subfields of
|
|
1667
|
+
this field and ``e`` gives an embedding of ``K`` into ``self``.
|
|
1668
|
+
|
|
1669
|
+
EXAMPLES::
|
|
1670
|
+
|
|
1671
|
+
sage: k = GF(2^21)
|
|
1672
|
+
sage: k.subfields()
|
|
1673
|
+
[(Finite Field of size 2,
|
|
1674
|
+
Ring morphism:
|
|
1675
|
+
From: Finite Field of size 2
|
|
1676
|
+
To: Finite Field in z21 of size 2^21
|
|
1677
|
+
Defn: 1 |--> 1),
|
|
1678
|
+
(Finite Field in z3 of size 2^3,
|
|
1679
|
+
Ring morphism:
|
|
1680
|
+
From: Finite Field in z3 of size 2^3
|
|
1681
|
+
To: Finite Field in z21 of size 2^21
|
|
1682
|
+
Defn: z3 |--> z21^20 + z21^19 + z21^17 + z21^15 + z21^11
|
|
1683
|
+
+ z21^9 + z21^8 + z21^6 + z21^2),
|
|
1684
|
+
(Finite Field in z7 of size 2^7,
|
|
1685
|
+
Ring morphism:
|
|
1686
|
+
From: Finite Field in z7 of size 2^7
|
|
1687
|
+
To: Finite Field in z21 of size 2^21
|
|
1688
|
+
Defn: z7 |--> z21^20 + z21^19 + z21^17 + z21^15 + z21^14
|
|
1689
|
+
+ z21^6 + z21^4 + z21^3 + z21),
|
|
1690
|
+
(Finite Field in z21 of size 2^21,
|
|
1691
|
+
Identity endomorphism of Finite Field in z21 of size 2^21)]
|
|
1692
|
+
"""
|
|
1693
|
+
n = self.degree()
|
|
1694
|
+
|
|
1695
|
+
if degree != 0:
|
|
1696
|
+
if not n % degree == 0:
|
|
1697
|
+
return []
|
|
1698
|
+
else:
|
|
1699
|
+
K, inc = self.subfield(degree, name=name, map=True)
|
|
1700
|
+
return [(K, inc)]
|
|
1701
|
+
|
|
1702
|
+
divisors = n.divisors()
|
|
1703
|
+
|
|
1704
|
+
if name is None:
|
|
1705
|
+
if hasattr(self, '_prefix'):
|
|
1706
|
+
name = self._prefix
|
|
1707
|
+
else:
|
|
1708
|
+
name = self.variable_name()
|
|
1709
|
+
if isinstance(name, str):
|
|
1710
|
+
name = {m: name + str(m) for m in divisors}
|
|
1711
|
+
elif not isinstance(name, dict):
|
|
1712
|
+
raise ValueError("name must be None, a string or a dictionary indexed by divisors of the degree")
|
|
1713
|
+
|
|
1714
|
+
pairs = []
|
|
1715
|
+
for m in divisors:
|
|
1716
|
+
K, inc = self.subfield(m, name=name[m], map=True)
|
|
1717
|
+
pairs.append((K, inc))
|
|
1718
|
+
return pairs
|
|
1719
|
+
|
|
1720
|
+
@cached_method
|
|
1721
|
+
def algebraic_closure(self, name='z', **kwds):
|
|
1722
|
+
"""
|
|
1723
|
+
Return an algebraic closure of ``self``.
|
|
1724
|
+
|
|
1725
|
+
INPUT:
|
|
1726
|
+
|
|
1727
|
+
- ``name`` -- string (default: ``'z'``); prefix to use for
|
|
1728
|
+
variable names of subfields
|
|
1729
|
+
|
|
1730
|
+
- ``implementation`` -- string (optional); specifies how to
|
|
1731
|
+
construct the algebraic closure. The only value supported
|
|
1732
|
+
at the moment is ``'pseudo_conway'``. For more details, see
|
|
1733
|
+
:mod:`~sage.rings.algebraic_closure_finite_field`.
|
|
1734
|
+
|
|
1735
|
+
OUTPUT:
|
|
1736
|
+
|
|
1737
|
+
An algebraic closure of ``self``. Note that mathematically
|
|
1738
|
+
speaking, this is only unique up to *non-unique* isomorphism.
|
|
1739
|
+
To obtain canonically defined algebraic closures, one needs an
|
|
1740
|
+
algorithm that also provides a canonical isomorphism between
|
|
1741
|
+
any two algebraic closures constructed using the algorithm.
|
|
1742
|
+
|
|
1743
|
+
This non-uniqueness problem can in principle be solved by
|
|
1744
|
+
using *Conway polynomials*; see for example
|
|
1745
|
+
:wikipedia:`Conway_polynomial_(finite_fields)`. These have
|
|
1746
|
+
the drawback that computing them takes a long time. Therefore
|
|
1747
|
+
Sage implements a variant called *pseudo-Conway polynomials*,
|
|
1748
|
+
which are easier to compute but do not determine an algebraic
|
|
1749
|
+
closure up to unique isomorphism.
|
|
1750
|
+
|
|
1751
|
+
The output of this method is cached, so that within the same
|
|
1752
|
+
Sage session, calling it multiple times will return the same
|
|
1753
|
+
algebraic closure (i.e. the same Sage object). Despite this,
|
|
1754
|
+
the non-uniqueness of the current implementation means that
|
|
1755
|
+
coercion and pickling cannot work as one might expect. See
|
|
1756
|
+
below for an example.
|
|
1757
|
+
|
|
1758
|
+
EXAMPLES::
|
|
1759
|
+
|
|
1760
|
+
sage: F = GF(5).algebraic_closure()
|
|
1761
|
+
sage: F
|
|
1762
|
+
Algebraic closure of Finite Field of size 5
|
|
1763
|
+
sage: F.gen(3)
|
|
1764
|
+
z3
|
|
1765
|
+
|
|
1766
|
+
For finite fields, the algebraic closure is always (isomorphic
|
|
1767
|
+
to) the algebraic closure of the prime field::
|
|
1768
|
+
|
|
1769
|
+
sage: GF(5^2).algebraic_closure() == F
|
|
1770
|
+
True
|
|
1771
|
+
|
|
1772
|
+
The default name is 'z' but you can change it through the option
|
|
1773
|
+
``name``::
|
|
1774
|
+
|
|
1775
|
+
sage: Ft = GF(5).algebraic_closure('t')
|
|
1776
|
+
sage: Ft.gen(3)
|
|
1777
|
+
t3
|
|
1778
|
+
|
|
1779
|
+
Because Sage currently only implements algebraic closures
|
|
1780
|
+
using a non-unique definition (see above), it is currently
|
|
1781
|
+
impossible to implement pickling in such a way that a pickled
|
|
1782
|
+
and unpickled element compares equal to the original::
|
|
1783
|
+
|
|
1784
|
+
sage: F = GF(7).algebraic_closure()
|
|
1785
|
+
sage: x = F.gen(2)
|
|
1786
|
+
sage: loads(dumps(x)) == x
|
|
1787
|
+
False
|
|
1788
|
+
|
|
1789
|
+
.. NOTE::
|
|
1790
|
+
|
|
1791
|
+
For non-prime finite fields, this method currently simply
|
|
1792
|
+
returns the algebraic closure of the prime field. This may
|
|
1793
|
+
or may not change in the future when extension towers are
|
|
1794
|
+
supported properly.
|
|
1795
|
+
|
|
1796
|
+
TESTS::
|
|
1797
|
+
|
|
1798
|
+
sage: GF(5).algebraic_closure() is GF(5).algebraic_closure()
|
|
1799
|
+
True
|
|
1800
|
+
"""
|
|
1801
|
+
if not self.is_prime_field():
|
|
1802
|
+
return self.prime_subfield().algebraic_closure()
|
|
1803
|
+
from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField
|
|
1804
|
+
return AlgebraicClosureFiniteField(self, name, **kwds)
|
|
1805
|
+
|
|
1806
|
+
@cached_method
|
|
1807
|
+
def is_conway(self):
|
|
1808
|
+
"""
|
|
1809
|
+
Return ``True`` if ``self`` is defined by a Conway polynomial.
|
|
1810
|
+
|
|
1811
|
+
EXAMPLES::
|
|
1812
|
+
|
|
1813
|
+
sage: GF(5^3, 'a').is_conway()
|
|
1814
|
+
True
|
|
1815
|
+
sage: GF(5^3, 'a', modulus='adleman-lenstra').is_conway()
|
|
1816
|
+
False
|
|
1817
|
+
sage: GF(next_prime(2^16, 2), 'a').is_conway()
|
|
1818
|
+
False
|
|
1819
|
+
"""
|
|
1820
|
+
from sage.rings.finite_rings.conway_polynomials import conway_polynomial, exists_conway_polynomial
|
|
1821
|
+
p = self.characteristic()
|
|
1822
|
+
n = self.degree()
|
|
1823
|
+
return (exists_conway_polynomial(p, n)
|
|
1824
|
+
and self.polynomial() == self.polynomial_ring()(conway_polynomial(p, n)))
|
|
1825
|
+
|
|
1826
|
+
def an_embedding(self, K):
|
|
1827
|
+
r"""
|
|
1828
|
+
Return some embedding of this field into another field `K`,
|
|
1829
|
+
and raise a :class:`ValueError` if none exists.
|
|
1830
|
+
|
|
1831
|
+
.. SEEALSO::
|
|
1832
|
+
|
|
1833
|
+
:meth:`sage.rings.ring.Field.an_embedding`
|
|
1834
|
+
|
|
1835
|
+
EXAMPLES::
|
|
1836
|
+
|
|
1837
|
+
sage: GF(4,'a').an_embedding(GF(2).algebraic_closure())
|
|
1838
|
+
Ring morphism:
|
|
1839
|
+
From: Finite Field in a of size 2^2
|
|
1840
|
+
To: Algebraic closure of Finite Field of size 2
|
|
1841
|
+
Defn: a |--> ...
|
|
1842
|
+
"""
|
|
1843
|
+
if self.characteristic() != K.characteristic():
|
|
1844
|
+
raise ValueError(f'no embedding from {self} to {K}: incompatible characteristics')
|
|
1845
|
+
try:
|
|
1846
|
+
return super().an_embedding(K)
|
|
1847
|
+
except (NotImplementedError, ValueError):
|
|
1848
|
+
pass
|
|
1849
|
+
if K not in FiniteFields():
|
|
1850
|
+
from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic
|
|
1851
|
+
if not isinstance(K, AlgebraicClosureFiniteField_generic):
|
|
1852
|
+
raise NotImplementedError('computing embeddings into this ring not implemented')
|
|
1853
|
+
g = self.gen()
|
|
1854
|
+
if (emb := K.coerce_map_from(self)) is not None:
|
|
1855
|
+
return self.hom([emb(g)])
|
|
1856
|
+
try:
|
|
1857
|
+
r = g.minpoly().change_ring(K).any_root()
|
|
1858
|
+
except ValueError:
|
|
1859
|
+
raise ValueError(f'no embedding from {self} to {K}')
|
|
1860
|
+
return self.hom([r])
|
|
1861
|
+
|
|
1862
|
+
def embeddings(self, K):
|
|
1863
|
+
r"""
|
|
1864
|
+
Return a list of all embeddings of this field in another field `K`.
|
|
1865
|
+
|
|
1866
|
+
EXAMPLES::
|
|
1867
|
+
|
|
1868
|
+
sage: GF(2).embeddings(GF(4))
|
|
1869
|
+
[Ring morphism:
|
|
1870
|
+
From: Finite Field of size 2
|
|
1871
|
+
To: Finite Field in z2 of size 2^2
|
|
1872
|
+
Defn: 1 |--> 1]
|
|
1873
|
+
sage: GF(4).embeddings(GF(2).algebraic_closure())
|
|
1874
|
+
[Ring morphism:
|
|
1875
|
+
From: Finite Field in z2 of size 2^2
|
|
1876
|
+
To: Algebraic closure of Finite Field of size 2
|
|
1877
|
+
Defn: z2 |--> z2,
|
|
1878
|
+
Ring morphism:
|
|
1879
|
+
From: Finite Field in z2 of size 2^2
|
|
1880
|
+
To: Algebraic closure of Finite Field of size 2
|
|
1881
|
+
Defn: z2 |--> z2 + 1]
|
|
1882
|
+
"""
|
|
1883
|
+
if self.characteristic() != K.characteristic():
|
|
1884
|
+
return []
|
|
1885
|
+
if K not in FiniteFields():
|
|
1886
|
+
from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic
|
|
1887
|
+
if not isinstance(K, AlgebraicClosureFiniteField_generic):
|
|
1888
|
+
raise NotImplementedError('computing embeddings into this ring not implemented')
|
|
1889
|
+
g = self.gen()
|
|
1890
|
+
rs = []
|
|
1891
|
+
if (emb := K.coerce_map_from(self)) is not None:
|
|
1892
|
+
rs.append(emb(g))
|
|
1893
|
+
rs += [r for r,_ in g.minpoly().roots(ring=K) if r not in rs]
|
|
1894
|
+
return [self.hom([r]) for r in rs]
|
|
1895
|
+
|
|
1896
|
+
def frobenius_endomorphism(self, n=1):
|
|
1897
|
+
"""
|
|
1898
|
+
INPUT:
|
|
1899
|
+
|
|
1900
|
+
- ``n`` -- integer (default: 1)
|
|
1901
|
+
|
|
1902
|
+
OUTPUT:
|
|
1903
|
+
|
|
1904
|
+
The `n`-th power of the absolute arithmetic Frobenius
|
|
1905
|
+
endomorphism on this finite field.
|
|
1906
|
+
|
|
1907
|
+
EXAMPLES::
|
|
1908
|
+
|
|
1909
|
+
sage: k.<t> = GF(3^5)
|
|
1910
|
+
sage: Frob = k.frobenius_endomorphism(); Frob
|
|
1911
|
+
Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
|
|
1912
|
+
|
|
1913
|
+
sage: a = k.random_element() # needs sage.modules
|
|
1914
|
+
sage: Frob(a) == a^3 # needs sage.modules
|
|
1915
|
+
True
|
|
1916
|
+
|
|
1917
|
+
We can specify a power::
|
|
1918
|
+
|
|
1919
|
+
sage: k.frobenius_endomorphism(2)
|
|
1920
|
+
Frobenius endomorphism t |--> t^(3^2) on Finite Field in t of size 3^5
|
|
1921
|
+
|
|
1922
|
+
The result is simplified if possible::
|
|
1923
|
+
|
|
1924
|
+
sage: k.frobenius_endomorphism(6)
|
|
1925
|
+
Frobenius endomorphism t |--> t^3 on Finite Field in t of size 3^5
|
|
1926
|
+
sage: k.frobenius_endomorphism(5)
|
|
1927
|
+
Identity endomorphism of Finite Field in t of size 3^5
|
|
1928
|
+
|
|
1929
|
+
Comparisons work::
|
|
1930
|
+
|
|
1931
|
+
sage: k.frobenius_endomorphism(6) == Frob
|
|
1932
|
+
True
|
|
1933
|
+
sage: from sage.categories.morphism import IdentityMorphism
|
|
1934
|
+
sage: k.frobenius_endomorphism(5) == IdentityMorphism(k)
|
|
1935
|
+
True
|
|
1936
|
+
|
|
1937
|
+
AUTHOR:
|
|
1938
|
+
|
|
1939
|
+
- Xavier Caruso (2012-06-29)
|
|
1940
|
+
"""
|
|
1941
|
+
from sage.rings.finite_rings.hom_finite_field import FrobeniusEndomorphism_finite_field
|
|
1942
|
+
return FrobeniusEndomorphism_finite_field(self, n)
|
|
1943
|
+
|
|
1944
|
+
def galois_group(self):
|
|
1945
|
+
r"""
|
|
1946
|
+
Return the Galois group of this finite field, a cyclic group generated by Frobenius.
|
|
1947
|
+
|
|
1948
|
+
EXAMPLES::
|
|
1949
|
+
|
|
1950
|
+
sage: # needs sage.groups
|
|
1951
|
+
sage: G = GF(3^6).galois_group(); G
|
|
1952
|
+
Galois group C6 of GF(3^6)
|
|
1953
|
+
sage: F = G.gen()
|
|
1954
|
+
sage: F^2
|
|
1955
|
+
Frob^2
|
|
1956
|
+
sage: F^6
|
|
1957
|
+
1
|
|
1958
|
+
"""
|
|
1959
|
+
from sage.rings.finite_rings.galois_group import GaloisGroup_GF
|
|
1960
|
+
return GaloisGroup_GF(self)
|
|
1961
|
+
|
|
1962
|
+
def dual_basis(self, basis=None, check=True):
|
|
1963
|
+
r"""
|
|
1964
|
+
Return the dual basis of ``basis``, or the dual basis of the power
|
|
1965
|
+
basis if no basis is supplied.
|
|
1966
|
+
|
|
1967
|
+
If `e = \{e_0, e_1, ..., e_{n-1}\}` is a basis of
|
|
1968
|
+
`\GF{p^n}` as a vector space over `\GF{p}`, then the dual basis of `e`,
|
|
1969
|
+
`d = \{d_0, d_1, ..., d_{n-1}\}`, is the unique basis such that
|
|
1970
|
+
`\mathrm{Tr}(e_i d_j) = \delta_{i,j}, 0 \leq i,j \leq n-1`, where
|
|
1971
|
+
`\mathrm{Tr}` is the trace function.
|
|
1972
|
+
|
|
1973
|
+
INPUT:
|
|
1974
|
+
|
|
1975
|
+
- ``basis`` -- (default: ``None``); a basis of the finite field
|
|
1976
|
+
``self``, `\GF{p^n}`, as a vector space over the base field
|
|
1977
|
+
`\GF{p}`. Uses the power basis `\{x^i : 0 \leq i \leq n-1\}` as
|
|
1978
|
+
input if no basis is supplied, where `x` is the generator of
|
|
1979
|
+
``self``.
|
|
1980
|
+
|
|
1981
|
+
- ``check`` -- (default: ``True``); verifies that ``basis`` is
|
|
1982
|
+
a valid basis of ``self``
|
|
1983
|
+
|
|
1984
|
+
ALGORITHM:
|
|
1985
|
+
|
|
1986
|
+
The algorithm used to calculate the dual basis comes from pages
|
|
1987
|
+
110--111 of [McE1987]_.
|
|
1988
|
+
|
|
1989
|
+
Let `e = \{e_0, e_1, ..., e_{n-1}\}` be a basis of `\GF{p^n}` as a
|
|
1990
|
+
vector space over `\GF{p}` and `d = \{d_0, d_1, ..., d_{n-1}\}` be the
|
|
1991
|
+
dual basis of `e`. Since `e` is a basis, we can rewrite any
|
|
1992
|
+
`d_c, 0 \leq c \leq n-1`, as
|
|
1993
|
+
`d_c = \beta_0 e_0 + \beta_1 e_1 + ... + \beta_{n-1} e_{n-1}`, for some
|
|
1994
|
+
`\beta_0, \beta_1, ..., \beta_{n-1} \in \GF{p}`. Using properties of
|
|
1995
|
+
the trace function, we can rewrite the `n` equations of the form
|
|
1996
|
+
`\mathrm{Tr}(e_i d_c) = \delta_{i,c}` and express the result as the
|
|
1997
|
+
matrix vector product:
|
|
1998
|
+
`A [\beta_0, \beta_1, ..., \beta_{n-1}] = i_c`, where the `i,j`-th
|
|
1999
|
+
element of `A` is `\mathrm{Tr(e_i e_j)}` and `i_c` is the `i`-th
|
|
2000
|
+
column of the `n \times n` identity matrix. Since `A` is an invertible
|
|
2001
|
+
matrix, `[\beta_0, \beta_1, ..., \beta_{n-1}] = A^{-1} i_c`, from
|
|
2002
|
+
which we can easily calculate `d_c`.
|
|
2003
|
+
|
|
2004
|
+
EXAMPLES::
|
|
2005
|
+
|
|
2006
|
+
sage: F.<a> = GF(2^4)
|
|
2007
|
+
sage: F.dual_basis(basis=None, check=False) # needs sage.modules
|
|
2008
|
+
[a^3 + 1, a^2, a, 1]
|
|
2009
|
+
|
|
2010
|
+
We can test that the dual basis returned satisfies the defining
|
|
2011
|
+
property of a dual basis:
|
|
2012
|
+
`\mathrm{Tr}(e_i d_j) = \delta_{i,j}, 0 \leq i,j \leq n-1` ::
|
|
2013
|
+
|
|
2014
|
+
sage: # needs sage.modules
|
|
2015
|
+
sage: F.<a> = GF(7^4)
|
|
2016
|
+
sage: e = [4*a^3, 2*a^3 + a^2 + 3*a + 5,
|
|
2017
|
+
....: 3*a^3 + 5*a^2 + 4*a + 2, 2*a^3 + 2*a^2 + 2]
|
|
2018
|
+
sage: d = F.dual_basis(e, check=True); d
|
|
2019
|
+
[3*a^3 + 4*a^2 + 6*a + 2, a^3 + 6*a + 5,
|
|
2020
|
+
3*a^3 + 6*a^2 + 2*a + 5, 5*a^2 + 4*a + 3]
|
|
2021
|
+
sage: vals = [[(x * y).trace() for x in e] for y in d]
|
|
2022
|
+
sage: matrix(vals) == matrix.identity(4)
|
|
2023
|
+
True
|
|
2024
|
+
|
|
2025
|
+
We can test that if `d` is the dual basis of `e`, then `e` is the dual
|
|
2026
|
+
basis of `d`::
|
|
2027
|
+
|
|
2028
|
+
sage: # needs sage.modules
|
|
2029
|
+
sage: F.<a> = GF(7^8)
|
|
2030
|
+
sage: e = [a^0, a^1, a^2, a^3, a^4, a^5, a^6, a^7]
|
|
2031
|
+
sage: d = F.dual_basis(e, check=False); d
|
|
2032
|
+
[6*a^6 + 4*a^5 + 4*a^4 + a^3 + 6*a^2 + 3,
|
|
2033
|
+
6*a^7 + 4*a^6 + 4*a^5 + 2*a^4 + a^2,
|
|
2034
|
+
4*a^6 + 5*a^5 + 5*a^4 + 4*a^3 + 5*a^2 + a + 6,
|
|
2035
|
+
5*a^7 + a^6 + a^4 + 4*a^3 + 4*a^2 + 1,
|
|
2036
|
+
2*a^7 + 5*a^6 + a^5 + a^3 + 5*a^2 + 2*a + 4,
|
|
2037
|
+
a^7 + 2*a^6 + 5*a^5 + a^4 + 5*a^2 + 4*a + 4,
|
|
2038
|
+
a^7 + a^6 + 2*a^5 + 5*a^4 + a^3 + 4*a^2 + 4*a + 6,
|
|
2039
|
+
5*a^7 + a^6 + a^5 + 2*a^4 + 5*a^3 + 6*a]
|
|
2040
|
+
sage: F.dual_basis(d)
|
|
2041
|
+
[1, a, a^2, a^3, a^4, a^5, a^6, a^7]
|
|
2042
|
+
|
|
2043
|
+
We cannot calculate the dual basis if ``basis`` is not a valid basis.
|
|
2044
|
+
::
|
|
2045
|
+
|
|
2046
|
+
sage: F.<a> = GF(2^3)
|
|
2047
|
+
sage: F.dual_basis([a], check=True) # needs sage.modules
|
|
2048
|
+
Traceback (most recent call last):
|
|
2049
|
+
...
|
|
2050
|
+
ValueError: basis length should be 3, not 1
|
|
2051
|
+
|
|
2052
|
+
sage: F.dual_basis([a^0, a, a^0 + a], check=True) # needs sage.modules
|
|
2053
|
+
Traceback (most recent call last):
|
|
2054
|
+
...
|
|
2055
|
+
ValueError: value of 'basis' keyword is not a basis
|
|
2056
|
+
|
|
2057
|
+
AUTHOR:
|
|
2058
|
+
|
|
2059
|
+
- Thomas Gagne (2015-06-16)
|
|
2060
|
+
"""
|
|
2061
|
+
from sage.matrix.constructor import matrix
|
|
2062
|
+
|
|
2063
|
+
if basis is None:
|
|
2064
|
+
basis = [self.gen() ** i for i in range(self.degree())]
|
|
2065
|
+
check = False
|
|
2066
|
+
|
|
2067
|
+
if check:
|
|
2068
|
+
if len(basis) != self.degree():
|
|
2069
|
+
msg = 'basis length should be {0}, not {1}'
|
|
2070
|
+
raise ValueError(msg.format(self.degree(), len(basis)))
|
|
2071
|
+
V = self.vector_space(map=False)
|
|
2072
|
+
vec_reps = [V(b) for b in basis]
|
|
2073
|
+
if matrix(vec_reps).is_singular():
|
|
2074
|
+
raise ValueError("value of 'basis' keyword is not a basis")
|
|
2075
|
+
|
|
2076
|
+
entries = [(bi * bj).trace() for bi in basis for bj in basis]
|
|
2077
|
+
B = matrix(self.base_ring(), self.degree(), entries).inverse()
|
|
2078
|
+
return [sum(x * y for x, y in zip(col, basis))
|
|
2079
|
+
for col in B.columns()]
|
|
2080
|
+
|
|
2081
|
+
def from_bytes(self, input_bytes, byteorder='big'):
|
|
2082
|
+
r"""
|
|
2083
|
+
Return the integer represented by the given array of bytes.
|
|
2084
|
+
|
|
2085
|
+
Internally relies on the python ``int.from_bytes()`` method.
|
|
2086
|
+
|
|
2087
|
+
INPUT:
|
|
2088
|
+
|
|
2089
|
+
- ``input_bytes`` -- a bytes-like object or iterable producing bytes
|
|
2090
|
+
- ``byteorder`` -- string (default: ``'big'``); determines the byte order of
|
|
2091
|
+
``input_bytes`` (can only be ``'big'`` or ``'little'``)
|
|
2092
|
+
|
|
2093
|
+
EXAMPLES::
|
|
2094
|
+
|
|
2095
|
+
sage: input_bytes = b"some_bytes"
|
|
2096
|
+
sage: F = GF(2**127 - 1)
|
|
2097
|
+
sage: F.from_bytes(input_bytes)
|
|
2098
|
+
545127616933790290830707
|
|
2099
|
+
sage: a = F.from_bytes(input_bytes, byteorder='little'); a
|
|
2100
|
+
544943659528996309004147
|
|
2101
|
+
sage: type(a)
|
|
2102
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
2103
|
+
|
|
2104
|
+
::
|
|
2105
|
+
|
|
2106
|
+
sage: input_bytes = b"some_bytes"
|
|
2107
|
+
sage: F_ext = GF(65537**5)
|
|
2108
|
+
sage: F_ext.from_bytes(input_bytes)
|
|
2109
|
+
29549*z5^4 + 40876*z5^3 + 52171*z5^2 + 13604*z5 + 20843
|
|
2110
|
+
sage: F_ext.from_bytes(input_bytes, byteorder='little')
|
|
2111
|
+
29539*z5^4 + 42728*z5^3 + 47440*z5^2 + 12423*z5 + 27473
|
|
2112
|
+
|
|
2113
|
+
TESTS::
|
|
2114
|
+
|
|
2115
|
+
sage: fields = [GF(2), GF(3), GF(65537), GF(2^10), GF(163^5)]
|
|
2116
|
+
sage: for F in fields: # needs sage.modules
|
|
2117
|
+
....: for _ in range(1000):
|
|
2118
|
+
....: a = F.random_element()
|
|
2119
|
+
....: order = choice(["little", "big"])
|
|
2120
|
+
....: a_bytes = a.to_bytes(byteorder=order)
|
|
2121
|
+
....: assert F.from_bytes(a_bytes, byteorder=order) == a
|
|
2122
|
+
"""
|
|
2123
|
+
python_int = int.from_bytes(input_bytes, byteorder=byteorder)
|
|
2124
|
+
return self.from_integer(python_int)
|
|
2125
|
+
|
|
2126
|
+
|
|
2127
|
+
def unpickle_FiniteField_ext(_type, order, variable_name, modulus, kwargs):
|
|
2128
|
+
r"""
|
|
2129
|
+
Used to unpickle extensions of finite fields. Now superseded (hence no
|
|
2130
|
+
doctest), but kept around for backward compatibility.
|
|
2131
|
+
"""
|
|
2132
|
+
return _type(order, variable_name, modulus, **kwargs)
|
|
2133
|
+
|
|
2134
|
+
|
|
2135
|
+
def unpickle_FiniteField_prm(_type, order, variable_name, kwargs):
|
|
2136
|
+
r"""
|
|
2137
|
+
Used to unpickle finite prime fields. Now superseded (hence no doctest),
|
|
2138
|
+
but kept around for backward compatibility.
|
|
2139
|
+
"""
|
|
2140
|
+
return _type(order, variable_name, **kwargs)
|
|
2141
|
+
|
|
2142
|
+
|
|
2143
|
+
register_unpickle_override(
|
|
2144
|
+
'sage.rings.ring', 'unpickle_FiniteField_prm', unpickle_FiniteField_prm)
|
|
2145
|
+
|
|
2146
|
+
|
|
2147
|
+
def is_FiniteField(R):
|
|
2148
|
+
r"""
|
|
2149
|
+
Return whether the implementation of ``R`` has the interface provided by
|
|
2150
|
+
the standard finite field implementation.
|
|
2151
|
+
|
|
2152
|
+
This function is deprecated.
|
|
2153
|
+
|
|
2154
|
+
EXAMPLES::
|
|
2155
|
+
|
|
2156
|
+
sage: from sage.rings.finite_rings.finite_field_base import is_FiniteField
|
|
2157
|
+
sage: is_FiniteField(GF(9,'a'))
|
|
2158
|
+
doctest:...: DeprecationWarning: the function is_FiniteField is deprecated; use isinstance(x, sage.rings.finite_rings.finite_field_base.FiniteField) instead
|
|
2159
|
+
See https://github.com/sagemath/sage/issues/32664 for details.
|
|
2160
|
+
True
|
|
2161
|
+
sage: is_FiniteField(GF(next_prime(10^10)))
|
|
2162
|
+
True
|
|
2163
|
+
|
|
2164
|
+
Note that the integers modulo n are not backed by the finite field type::
|
|
2165
|
+
|
|
2166
|
+
sage: is_FiniteField(Integers(7))
|
|
2167
|
+
False
|
|
2168
|
+
"""
|
|
2169
|
+
from sage.misc.superseded import deprecation
|
|
2170
|
+
deprecation(32664, "the function is_FiniteField is deprecated; use isinstance(x, sage.rings.finite_rings.finite_field_base.FiniteField) instead")
|
|
2171
|
+
return isinstance(R, FiniteField)
|