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,4586 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-categories
|
|
2
|
+
r"""
|
|
3
|
+
Elements of `\ZZ/n\ZZ`
|
|
4
|
+
|
|
5
|
+
An element of the integers modulo `n`.
|
|
6
|
+
|
|
7
|
+
There are three types of integer_mod classes, depending on the
|
|
8
|
+
size of the modulus.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
- ``IntegerMod_int`` stores its value in a
|
|
12
|
+
``int_fast32_t`` (typically an ``int``);
|
|
13
|
+
this is used if the modulus is less than
|
|
14
|
+
`\sqrt{2^{31}-1}`.
|
|
15
|
+
|
|
16
|
+
- ``IntegerMod_int64`` stores its value in a
|
|
17
|
+
``int_fast64_t`` (typically a ``long
|
|
18
|
+
long``); this is used if the modulus is less than
|
|
19
|
+
`2^{31}-1`. In many places, we assume that the values and the modulus
|
|
20
|
+
actually fit inside an ``unsigned long``.
|
|
21
|
+
|
|
22
|
+
- ``IntegerMod_gmp`` stores its value in a
|
|
23
|
+
``mpz_t``; this can be used for an arbitrarily large
|
|
24
|
+
modulus.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
All extend ``IntegerMod_abstract``.
|
|
28
|
+
|
|
29
|
+
For efficiency reasons, it stores the modulus (in all three forms,
|
|
30
|
+
if possible) in a common (cdef) class
|
|
31
|
+
``NativeIntStruct`` rather than in the parent.
|
|
32
|
+
|
|
33
|
+
AUTHORS:
|
|
34
|
+
|
|
35
|
+
- Robert Bradshaw: most of the work
|
|
36
|
+
|
|
37
|
+
- Didier Deshommes: bit shifting
|
|
38
|
+
|
|
39
|
+
- William Stein: editing and polishing; new arith architecture
|
|
40
|
+
|
|
41
|
+
- Robert Bradshaw: implement native is_square and square_root
|
|
42
|
+
|
|
43
|
+
- William Stein: sqrt
|
|
44
|
+
|
|
45
|
+
- Maarten Derickx: moved the valuation code from the global
|
|
46
|
+
valuation function to here
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
TESTS::
|
|
50
|
+
|
|
51
|
+
sage: R = Integers(101^3)
|
|
52
|
+
sage: a = R(824362); b = R(205942)
|
|
53
|
+
sage: a * b
|
|
54
|
+
851127
|
|
55
|
+
|
|
56
|
+
sage: type(IntegerModRing(2^31-1).an_element())
|
|
57
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>
|
|
58
|
+
sage: type(IntegerModRing(2^31).an_element())
|
|
59
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
60
|
+
"""
|
|
61
|
+
# ****************************************************************************
|
|
62
|
+
# Copyright (C) 2006 Robert Bradshaw <robertwb@math.washington.edu>
|
|
63
|
+
# 2006 William Stein <wstein@gmail.com>
|
|
64
|
+
#
|
|
65
|
+
# This program is free software: you can redistribute it and/or modify
|
|
66
|
+
# it under the terms of the GNU General Public License as published by
|
|
67
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
68
|
+
# (at your option) any later version.
|
|
69
|
+
# https://www.gnu.org/licenses/
|
|
70
|
+
# ****************************************************************************
|
|
71
|
+
|
|
72
|
+
from cysignals.signals cimport sig_on, sig_off, sig_check
|
|
73
|
+
|
|
74
|
+
from cpython.long cimport *
|
|
75
|
+
from cpython.list cimport *
|
|
76
|
+
from cpython.ref cimport *
|
|
77
|
+
|
|
78
|
+
from libc.math cimport log2, ceil
|
|
79
|
+
|
|
80
|
+
from sage.libs.gmp.all cimport *
|
|
81
|
+
|
|
82
|
+
cdef bint use_32bit_type(int_fast64_t modulus) noexcept:
|
|
83
|
+
return modulus <= INTEGER_MOD_INT32_LIMIT
|
|
84
|
+
|
|
85
|
+
from sage.arith.long cimport (
|
|
86
|
+
integer_check_long, integer_check_long_py, is_small_python_int)
|
|
87
|
+
|
|
88
|
+
import sage.rings.rational as rational
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
from sage.libs.pari import pari
|
|
92
|
+
from cypari2.handle_error import PariError
|
|
93
|
+
except ImportError:
|
|
94
|
+
class PariError(Exception):
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
import sage.rings.integer_ring as integer_ring
|
|
98
|
+
import sage.rings.rational_field
|
|
99
|
+
|
|
100
|
+
import sage.rings.integer
|
|
101
|
+
cimport sage.rings.integer
|
|
102
|
+
from sage.rings.integer cimport Integer
|
|
103
|
+
|
|
104
|
+
from sage.structure.coerce cimport py_scalar_to_element
|
|
105
|
+
from sage.structure.richcmp cimport rich_to_bool_sgn, rich_to_bool
|
|
106
|
+
import sage.structure.element
|
|
107
|
+
cimport sage.structure.element
|
|
108
|
+
coerce_binop = sage.structure.element.coerce_binop
|
|
109
|
+
from sage.structure.element cimport Element
|
|
110
|
+
from sage.categories.morphism cimport Morphism
|
|
111
|
+
from sage.categories.map cimport Map
|
|
112
|
+
|
|
113
|
+
from sage.misc.persist import register_unpickle_override
|
|
114
|
+
|
|
115
|
+
from sage.structure.parent cimport Parent
|
|
116
|
+
|
|
117
|
+
from sage.arith.misc import CRT as crt
|
|
118
|
+
from sage.arith.functions import lcm
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
cdef Integer one_Z = Integer(1)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def Mod(n, m, parent=None):
|
|
125
|
+
r"""
|
|
126
|
+
Return the equivalence class of `n` modulo `m` as
|
|
127
|
+
an element of `\ZZ/m\ZZ`.
|
|
128
|
+
|
|
129
|
+
EXAMPLES::
|
|
130
|
+
|
|
131
|
+
sage: x = Mod(12345678, 32098203845329048)
|
|
132
|
+
sage: x
|
|
133
|
+
12345678
|
|
134
|
+
sage: x^100
|
|
135
|
+
1017322209155072
|
|
136
|
+
|
|
137
|
+
You can also use the lowercase version::
|
|
138
|
+
|
|
139
|
+
sage: mod(12,5)
|
|
140
|
+
2
|
|
141
|
+
|
|
142
|
+
Illustrates that :issue:`5971` is fixed. Consider `n` modulo `m` when
|
|
143
|
+
`m = 0`. Then `\ZZ/0\ZZ` is isomorphic to `\ZZ` so `n` modulo `0`
|
|
144
|
+
is equivalent to `n` for any integer value of `n`::
|
|
145
|
+
|
|
146
|
+
sage: Mod(10, 0)
|
|
147
|
+
10
|
|
148
|
+
sage: a = randint(-100, 100)
|
|
149
|
+
sage: Mod(a, 0) == a
|
|
150
|
+
True
|
|
151
|
+
"""
|
|
152
|
+
# when m is zero, then ZZ/0ZZ is isomorphic to ZZ
|
|
153
|
+
if m == 0:
|
|
154
|
+
return n
|
|
155
|
+
|
|
156
|
+
# m is nonzero, so return n mod m
|
|
157
|
+
if parent is None:
|
|
158
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
159
|
+
parent = IntegerModRing(m)
|
|
160
|
+
return IntegerMod(parent, n)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
mod = Mod
|
|
164
|
+
|
|
165
|
+
register_unpickle_override('sage.rings.integer_mod', 'Mod', Mod)
|
|
166
|
+
register_unpickle_override('sage.rings.integer_mod', 'mod', mod)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def IntegerMod(parent, value):
|
|
170
|
+
"""
|
|
171
|
+
Create an integer modulo `n` with the given parent.
|
|
172
|
+
|
|
173
|
+
This is mainly for internal use.
|
|
174
|
+
|
|
175
|
+
EXAMPLES::
|
|
176
|
+
|
|
177
|
+
sage: from sage.rings.finite_rings.integer_mod import IntegerMod
|
|
178
|
+
sage: R = IntegerModRing(100)
|
|
179
|
+
sage: type(R._pyx_order.table)
|
|
180
|
+
<class 'list'>
|
|
181
|
+
sage: IntegerMod(R, 42)
|
|
182
|
+
42
|
|
183
|
+
sage: IntegerMod(R, 142)
|
|
184
|
+
42
|
|
185
|
+
sage: IntegerMod(R, 10^100 + 42)
|
|
186
|
+
42
|
|
187
|
+
sage: IntegerMod(R, -9158)
|
|
188
|
+
42
|
|
189
|
+
"""
|
|
190
|
+
cdef NativeIntStruct modulus = parent._pyx_order
|
|
191
|
+
|
|
192
|
+
cdef long val = 0
|
|
193
|
+
cdef int err
|
|
194
|
+
|
|
195
|
+
if modulus.table is not None:
|
|
196
|
+
# Try to return an element from the precomputed table
|
|
197
|
+
integer_check_long(value, &val, &err)
|
|
198
|
+
if not err:
|
|
199
|
+
val = (<int_fast64_t>val) % modulus.int64
|
|
200
|
+
if val < 0:
|
|
201
|
+
val += modulus.int64
|
|
202
|
+
a = <Element>modulus.table[val]
|
|
203
|
+
assert a._parent is parent
|
|
204
|
+
return a
|
|
205
|
+
t = modulus.element_class()
|
|
206
|
+
return t(parent, value)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def is_IntegerMod(x):
|
|
210
|
+
"""
|
|
211
|
+
Return ``True`` if and only if x is an integer modulo
|
|
212
|
+
`n`.
|
|
213
|
+
|
|
214
|
+
EXAMPLES::
|
|
215
|
+
|
|
216
|
+
sage: from sage.rings.finite_rings.integer_mod import is_IntegerMod
|
|
217
|
+
sage: is_IntegerMod(5)
|
|
218
|
+
doctest:warning...
|
|
219
|
+
DeprecationWarning: The function is_IntegerMod is deprecated;
|
|
220
|
+
use 'isinstance(..., IntegerMod_abstract)' instead.
|
|
221
|
+
See https://github.com/sagemath/sage/issues/38128 for details.
|
|
222
|
+
False
|
|
223
|
+
sage: is_IntegerMod(Mod(5,10))
|
|
224
|
+
True
|
|
225
|
+
"""
|
|
226
|
+
from sage.misc.superseded import deprecation_cython
|
|
227
|
+
deprecation_cython(38128,
|
|
228
|
+
"The function is_IntegerMod is deprecated; "
|
|
229
|
+
"use 'isinstance(..., IntegerMod_abstract)' instead.")
|
|
230
|
+
return isinstance(x, IntegerMod_abstract)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
cdef inline inverse_or_None(x):
|
|
234
|
+
try:
|
|
235
|
+
return ~x
|
|
236
|
+
except ArithmeticError:
|
|
237
|
+
return None
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
cdef class NativeIntStruct:
|
|
241
|
+
"""
|
|
242
|
+
We store the various forms of the modulus here rather than in the
|
|
243
|
+
parent for efficiency reasons.
|
|
244
|
+
|
|
245
|
+
We may also store a cached table of all elements of a given ring in
|
|
246
|
+
this class.
|
|
247
|
+
"""
|
|
248
|
+
def __cinit__(self):
|
|
249
|
+
self.int32 = -1
|
|
250
|
+
self.int64 = -1
|
|
251
|
+
|
|
252
|
+
def __init__(self, m):
|
|
253
|
+
self.sageInteger = Integer(m)
|
|
254
|
+
cdef mpz_srcptr z = self.sageInteger.value
|
|
255
|
+
if mpz_cmp_si(z, INTEGER_MOD_INT64_LIMIT) <= 0:
|
|
256
|
+
self.int64 = mpz_get_si(z)
|
|
257
|
+
if use_32bit_type(self.int64):
|
|
258
|
+
self.int32 = self.int64
|
|
259
|
+
|
|
260
|
+
def __repr__(self):
|
|
261
|
+
return f"{type(self).__name__}({self.sageInteger})"
|
|
262
|
+
|
|
263
|
+
def __reduce__(self):
|
|
264
|
+
"""
|
|
265
|
+
TESTS::
|
|
266
|
+
|
|
267
|
+
sage: from sage.rings.finite_rings.integer_mod import NativeIntStruct
|
|
268
|
+
sage: M = NativeIntStruct(12345); M
|
|
269
|
+
NativeIntStruct(12345)
|
|
270
|
+
sage: loads(dumps(M))
|
|
271
|
+
NativeIntStruct(12345)
|
|
272
|
+
"""
|
|
273
|
+
return type(self), (self.sageInteger, )
|
|
274
|
+
|
|
275
|
+
def precompute_table(self, parent):
|
|
276
|
+
"""
|
|
277
|
+
Function to compute and cache all elements of this class.
|
|
278
|
+
|
|
279
|
+
If ``inverses == True``, also computes and caches the inverses
|
|
280
|
+
of the invertible elements.
|
|
281
|
+
|
|
282
|
+
EXAMPLES::
|
|
283
|
+
|
|
284
|
+
sage: from sage.rings.finite_rings.integer_mod import NativeIntStruct
|
|
285
|
+
sage: R = IntegerModRing(10)
|
|
286
|
+
sage: M = NativeIntStruct(R.order())
|
|
287
|
+
sage: M.precompute_table(R)
|
|
288
|
+
sage: M.table
|
|
289
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
290
|
+
sage: M.inverses
|
|
291
|
+
[None, 1, None, 7, None, None, None, 3, None, 9]
|
|
292
|
+
|
|
293
|
+
This is used by the :class:`sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic` constructor::
|
|
294
|
+
|
|
295
|
+
sage: from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic
|
|
296
|
+
sage: R = IntegerModRing_generic(39, cache=False)
|
|
297
|
+
sage: R(5)^-1
|
|
298
|
+
8
|
|
299
|
+
sage: R(5)^-1 is R(8)
|
|
300
|
+
False
|
|
301
|
+
sage: R = IntegerModRing_generic(39, cache=True) # indirect doctest
|
|
302
|
+
sage: R(5)^-1 is R(8)
|
|
303
|
+
True
|
|
304
|
+
|
|
305
|
+
Check that the inverse of 0 modulo 1 works, see :issue:`13639`::
|
|
306
|
+
|
|
307
|
+
sage: R = IntegerModRing_generic(1, cache=True) # indirect doctest
|
|
308
|
+
sage: R(0)^-1 is R(0)
|
|
309
|
+
True
|
|
310
|
+
|
|
311
|
+
TESTS::
|
|
312
|
+
|
|
313
|
+
sage: R = IntegerModRing(10^50)
|
|
314
|
+
sage: M = NativeIntStruct(R.order())
|
|
315
|
+
sage: M.precompute_table(R)
|
|
316
|
+
Traceback (most recent call last):
|
|
317
|
+
...
|
|
318
|
+
OverflowError: precompute_table() is only supported for small moduli
|
|
319
|
+
"""
|
|
320
|
+
cdef Py_ssize_t i, m = self.int64
|
|
321
|
+
|
|
322
|
+
# Verify that the modulus m fits in a Py_ssize_t
|
|
323
|
+
if m <= 0 or (<int_fast64_t>m != self.int64):
|
|
324
|
+
raise OverflowError("precompute_table() is only supported for small moduli")
|
|
325
|
+
|
|
326
|
+
t = self.element_class()
|
|
327
|
+
self.table = [t(parent, i) for i in range(m)]
|
|
328
|
+
|
|
329
|
+
if m == 1:
|
|
330
|
+
# Special case for integers modulo 1
|
|
331
|
+
self.inverses = self.table
|
|
332
|
+
else:
|
|
333
|
+
self.inverses = [inverse_or_None(x) for x in self.table]
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
# For unpickling
|
|
337
|
+
makeNativeIntStruct = NativeIntStruct
|
|
338
|
+
register_unpickle_override('sage.rings.integer_mod', 'makeNativeIntStruct', NativeIntStruct)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
cdef class IntegerMod_abstract(FiniteRingElement):
|
|
342
|
+
|
|
343
|
+
def __init__(self, parent, value=None):
|
|
344
|
+
"""
|
|
345
|
+
EXAMPLES::
|
|
346
|
+
|
|
347
|
+
sage: a = Mod(10, 30^10); a
|
|
348
|
+
10
|
|
349
|
+
sage: type(a)
|
|
350
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
351
|
+
sage: loads(a.dumps()) == a
|
|
352
|
+
True
|
|
353
|
+
|
|
354
|
+
TESTS::
|
|
355
|
+
|
|
356
|
+
sage: TestSuite(Zmod(1)).run()
|
|
357
|
+
sage: TestSuite(Zmod(2)).run()
|
|
358
|
+
sage: TestSuite(Zmod(3)).run()
|
|
359
|
+
sage: TestSuite(Zmod(4)).run()
|
|
360
|
+
sage: TestSuite(Zmod(5)).run()
|
|
361
|
+
sage: TestSuite(Zmod(6)).run()
|
|
362
|
+
sage: TestSuite(Zmod(2^10 * 3^5)).run()
|
|
363
|
+
sage: TestSuite(Zmod(2^30 * 3^50 * 5^20)).run()
|
|
364
|
+
|
|
365
|
+
sage: GF(29)(SR(1/3)) # needs sage.rings.finite_rings sage.symbolic
|
|
366
|
+
10
|
|
367
|
+
sage: Integers(30)(QQ['x'](1/7))
|
|
368
|
+
13
|
|
369
|
+
sage: Integers(30)(SR(1/4)) # needs sage.symbolic
|
|
370
|
+
Traceback (most recent call last):
|
|
371
|
+
...
|
|
372
|
+
ZeroDivisionError: inverse of Mod(4, 30) does not exist
|
|
373
|
+
"""
|
|
374
|
+
self._parent = parent
|
|
375
|
+
self._modulus = parent._pyx_order
|
|
376
|
+
|
|
377
|
+
if value is None:
|
|
378
|
+
return
|
|
379
|
+
|
|
380
|
+
cdef long longval = 0
|
|
381
|
+
cdef int err = 0
|
|
382
|
+
cdef Integer z
|
|
383
|
+
|
|
384
|
+
if isinstance(value, Integer):
|
|
385
|
+
z = <Integer>value
|
|
386
|
+
elif isinstance(value, rational.Rational):
|
|
387
|
+
z = value % self._modulus.sageInteger
|
|
388
|
+
elif integer_check_long_py(value, &longval, &err) and not err:
|
|
389
|
+
self.set_from_long(longval)
|
|
390
|
+
return
|
|
391
|
+
else:
|
|
392
|
+
try:
|
|
393
|
+
z = integer_ring.Z(value)
|
|
394
|
+
except (TypeError, ValueError):
|
|
395
|
+
from sage.structure.element import Expression
|
|
396
|
+
if isinstance(value, Expression):
|
|
397
|
+
value = value.pyobject()
|
|
398
|
+
else:
|
|
399
|
+
value = py_scalar_to_element(value)
|
|
400
|
+
if isinstance(value, Element) and value.parent().is_exact():
|
|
401
|
+
value = sage.rings.rational_field.QQ(value)
|
|
402
|
+
z = value % self._modulus.sageInteger
|
|
403
|
+
else:
|
|
404
|
+
raise
|
|
405
|
+
self.set_from_mpz(z.value)
|
|
406
|
+
|
|
407
|
+
cdef IntegerMod_abstract _new_c_fast(self, unsigned long value):
|
|
408
|
+
cdef type t = type(self)
|
|
409
|
+
x = <IntegerMod_abstract>t.__new__(t)
|
|
410
|
+
x._parent = self._parent
|
|
411
|
+
x._modulus = self._modulus
|
|
412
|
+
x.set_from_ulong_fast(value)
|
|
413
|
+
return x
|
|
414
|
+
|
|
415
|
+
cdef _new_c_from_long(self, long value):
|
|
416
|
+
cdef type t = type(self)
|
|
417
|
+
cdef IntegerMod_abstract x = <IntegerMod_abstract>t.__new__(t)
|
|
418
|
+
x._parent = self._parent
|
|
419
|
+
x._modulus = self._modulus
|
|
420
|
+
x.set_from_long(value)
|
|
421
|
+
return x
|
|
422
|
+
|
|
423
|
+
cdef void set_from_mpz(self, mpz_t value) noexcept:
|
|
424
|
+
raise NotImplementedError("must be defined in child class")
|
|
425
|
+
|
|
426
|
+
cdef void set_from_long(self, long value) noexcept:
|
|
427
|
+
raise NotImplementedError("must be defined in child class")
|
|
428
|
+
|
|
429
|
+
cdef void set_from_ulong_fast(self, unsigned long value) noexcept:
|
|
430
|
+
"""
|
|
431
|
+
Set ``self`` to the value in ``value`` where ``value`` is
|
|
432
|
+
assumed to be less than the modulus
|
|
433
|
+
"""
|
|
434
|
+
raise NotImplementedError("must be defined in child class")
|
|
435
|
+
|
|
436
|
+
def __abs__(self):
|
|
437
|
+
"""
|
|
438
|
+
Raise an error message, since ``abs(x)`` makes no sense
|
|
439
|
+
when ``x`` is an integer modulo `n`.
|
|
440
|
+
|
|
441
|
+
EXAMPLES::
|
|
442
|
+
|
|
443
|
+
sage: abs(Mod(2,3))
|
|
444
|
+
Traceback (most recent call last):
|
|
445
|
+
...
|
|
446
|
+
ArithmeticError: absolute value not defined on integers modulo n.
|
|
447
|
+
"""
|
|
448
|
+
raise ArithmeticError("absolute value not defined on integers modulo n.")
|
|
449
|
+
|
|
450
|
+
def __reduce__(IntegerMod_abstract self):
|
|
451
|
+
"""
|
|
452
|
+
EXAMPLES::
|
|
453
|
+
|
|
454
|
+
sage: a = Mod(4,5); a
|
|
455
|
+
4
|
|
456
|
+
sage: loads(a.dumps()) == a
|
|
457
|
+
True
|
|
458
|
+
sage: a = Mod(-1,5^30)^25
|
|
459
|
+
sage: loads(a.dumps()) == a
|
|
460
|
+
True
|
|
461
|
+
"""
|
|
462
|
+
return sage.rings.finite_rings.integer_mod.mod, (self.lift(), self.modulus(), self.parent())
|
|
463
|
+
|
|
464
|
+
def _im_gens_(self, codomain, im_gens, base_map=None):
|
|
465
|
+
"""
|
|
466
|
+
Return the image of ``self`` under the map that sends the
|
|
467
|
+
generators of the parent to ``im_gens``.
|
|
468
|
+
|
|
469
|
+
EXAMPLES::
|
|
470
|
+
|
|
471
|
+
sage: a = Mod(7, 10)
|
|
472
|
+
sage: R = ZZ.quotient(5)
|
|
473
|
+
sage: a._im_gens_(R, (R(1),))
|
|
474
|
+
2
|
|
475
|
+
"""
|
|
476
|
+
# The generators are irrelevant (Zmod(n) is its own base), so we ignore base_map
|
|
477
|
+
return codomain.coerce(self)
|
|
478
|
+
|
|
479
|
+
def __mod__(self, modulus):
|
|
480
|
+
"""
|
|
481
|
+
Coerce this element to the ring `Z/(modulus)`.
|
|
482
|
+
|
|
483
|
+
If the new ``modulus`` does not divide the current modulus,
|
|
484
|
+
an :exc:`ArithmeticError` is raised.
|
|
485
|
+
|
|
486
|
+
EXAMPLES::
|
|
487
|
+
|
|
488
|
+
sage: a = Mod(14, 35)
|
|
489
|
+
sage: a % 5
|
|
490
|
+
4
|
|
491
|
+
sage: parent(a % 5)
|
|
492
|
+
Ring of integers modulo 5
|
|
493
|
+
sage: a % 350
|
|
494
|
+
Traceback (most recent call last):
|
|
495
|
+
...
|
|
496
|
+
ArithmeticError: reduction modulo 350 not defined
|
|
497
|
+
sage: a % 35
|
|
498
|
+
14
|
|
499
|
+
sage: int(1) % a
|
|
500
|
+
Traceback (most recent call last):
|
|
501
|
+
...
|
|
502
|
+
TypeError: unsupported operand type(s) for %: 'int' and 'sage.rings.finite_rings.integer_mod.IntegerMod_int'
|
|
503
|
+
"""
|
|
504
|
+
if not isinstance(self, IntegerMod_abstract):
|
|
505
|
+
# something % Mod(x,y) makes no sense
|
|
506
|
+
return NotImplemented
|
|
507
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
508
|
+
R = IntegerModRing(modulus)
|
|
509
|
+
if (<Element>self)._parent._IntegerModRing_generic__order % R.order():
|
|
510
|
+
raise ArithmeticError(f"reduction modulo {modulus!r} not defined")
|
|
511
|
+
return R(self)
|
|
512
|
+
|
|
513
|
+
def is_nilpotent(self):
|
|
514
|
+
r"""
|
|
515
|
+
Return ``True`` if ``self`` is nilpotent,
|
|
516
|
+
i.e., some power of ``self`` is zero.
|
|
517
|
+
|
|
518
|
+
EXAMPLES::
|
|
519
|
+
|
|
520
|
+
sage: a = Integers(90384098234^3)
|
|
521
|
+
sage: factor(a.order()) # needs sage.libs.pari
|
|
522
|
+
2^3 * 191^3 * 236607587^3
|
|
523
|
+
sage: b = a(2*191)
|
|
524
|
+
sage: b.is_nilpotent()
|
|
525
|
+
False
|
|
526
|
+
sage: b = a(2*191*236607587)
|
|
527
|
+
sage: b.is_nilpotent()
|
|
528
|
+
True
|
|
529
|
+
|
|
530
|
+
ALGORITHM: Let `m \geq \log_2(n)`, where `n` is
|
|
531
|
+
the modulus. Then `x \in \ZZ/n\ZZ` is
|
|
532
|
+
nilpotent if and only if `x^m = 0`.
|
|
533
|
+
|
|
534
|
+
PROOF: This is clear if you reduce to the prime power case, which
|
|
535
|
+
you can do via the Chinese Remainder Theorem.
|
|
536
|
+
|
|
537
|
+
We could alternatively factor `n` and check to see if the
|
|
538
|
+
prime divisors of `n` all divide `x`. This is
|
|
539
|
+
asymptotically slower :-).
|
|
540
|
+
"""
|
|
541
|
+
if self.is_zero():
|
|
542
|
+
return True
|
|
543
|
+
m = self._modulus.sageInteger.exact_log(2) + 1
|
|
544
|
+
return (self**m).is_zero()
|
|
545
|
+
|
|
546
|
+
#################################################################
|
|
547
|
+
# Interfaces
|
|
548
|
+
#################################################################
|
|
549
|
+
def _pari_init_(self):
|
|
550
|
+
return 'Mod(%s,%s)' % (str(self), self._modulus.sageInteger)
|
|
551
|
+
|
|
552
|
+
def __pari__(self):
|
|
553
|
+
return self.lift().__pari__().Mod(self._modulus.sageInteger)
|
|
554
|
+
|
|
555
|
+
def _gap_init_(self):
|
|
556
|
+
r"""
|
|
557
|
+
Return string representation of corresponding GAP object.
|
|
558
|
+
|
|
559
|
+
EXAMPLES::
|
|
560
|
+
|
|
561
|
+
sage: # needs sage.libs.gap
|
|
562
|
+
sage: a = Mod(2,19)
|
|
563
|
+
sage: gap(a)
|
|
564
|
+
Z(19)
|
|
565
|
+
sage: gap(Mod(3, next_prime(10000))) # needs sage.libs.pari
|
|
566
|
+
Z(10007)^6190
|
|
567
|
+
sage: gap(Mod(3, next_prime(100000))) # needs sage.libs.pari
|
|
568
|
+
ZmodpZObj( 3, 100003 )
|
|
569
|
+
sage: gap(Mod(4, 48))
|
|
570
|
+
ZmodnZObj( 4, 48 )
|
|
571
|
+
"""
|
|
572
|
+
return '%s*One(ZmodnZ(%s))' % (self, self._modulus.sageInteger)
|
|
573
|
+
|
|
574
|
+
def _magma_init_(self, magma):
|
|
575
|
+
"""
|
|
576
|
+
Coercion to Magma.
|
|
577
|
+
|
|
578
|
+
EXAMPLES::
|
|
579
|
+
|
|
580
|
+
sage: # optional - magma
|
|
581
|
+
sage: a = Integers(15)(4)
|
|
582
|
+
sage: b = magma(a)
|
|
583
|
+
sage: b.Type()
|
|
584
|
+
RngIntResElt
|
|
585
|
+
sage: b^2
|
|
586
|
+
1
|
|
587
|
+
"""
|
|
588
|
+
return '%s!%s' % (self.parent()._magma_init_(magma), self)
|
|
589
|
+
|
|
590
|
+
def _axiom_init_(self):
|
|
591
|
+
"""
|
|
592
|
+
Return a string representation of the corresponding to
|
|
593
|
+
(Pan)Axiom object.
|
|
594
|
+
|
|
595
|
+
EXAMPLES::
|
|
596
|
+
|
|
597
|
+
sage: a = Integers(15)(4)
|
|
598
|
+
sage: a._axiom_init_()
|
|
599
|
+
'4 :: IntegerMod(15)'
|
|
600
|
+
|
|
601
|
+
sage: aa = axiom(a); aa # optional - axiom
|
|
602
|
+
4
|
|
603
|
+
sage: aa.type() # optional - axiom
|
|
604
|
+
IntegerMod 15
|
|
605
|
+
|
|
606
|
+
sage: aa = fricas(a); aa # optional - fricas
|
|
607
|
+
4
|
|
608
|
+
sage: aa.typeOf() # optional - fricas
|
|
609
|
+
IntegerMod(15)
|
|
610
|
+
"""
|
|
611
|
+
return '%s :: %s' % (self, self.parent()._axiom_init_())
|
|
612
|
+
|
|
613
|
+
_fricas_init_ = _axiom_init_
|
|
614
|
+
|
|
615
|
+
def _sage_input_(self, sib, coerced):
|
|
616
|
+
r"""
|
|
617
|
+
Produce an expression which will reproduce this value when
|
|
618
|
+
evaluated.
|
|
619
|
+
|
|
620
|
+
EXAMPLES::
|
|
621
|
+
|
|
622
|
+
sage: K = GF(7)
|
|
623
|
+
sage: sage_input(K(5), verify=True)
|
|
624
|
+
# Verified
|
|
625
|
+
GF(7)(5)
|
|
626
|
+
sage: sage_input(K(5) * polygen(K), verify=True)
|
|
627
|
+
# Verified
|
|
628
|
+
R.<x> = GF(7)[]
|
|
629
|
+
5*x
|
|
630
|
+
sage: from sage.misc.sage_input import SageInputBuilder
|
|
631
|
+
sage: K(5)._sage_input_(SageInputBuilder(), False)
|
|
632
|
+
{call: {call: {atomic:GF}({atomic:7})}({atomic:5})}
|
|
633
|
+
sage: K(5)._sage_input_(SageInputBuilder(), True)
|
|
634
|
+
{atomic:5}
|
|
635
|
+
"""
|
|
636
|
+
v = sib.int(self.lift())
|
|
637
|
+
if coerced:
|
|
638
|
+
return v
|
|
639
|
+
else:
|
|
640
|
+
return sib(self.parent())(v)
|
|
641
|
+
|
|
642
|
+
def log(self, b=None, order=None, check=False):
|
|
643
|
+
r"""
|
|
644
|
+
Compute the discrete logarithm of this element to base `b`,
|
|
645
|
+
that is,
|
|
646
|
+
return an integer `x` such that `b^x = a`, where
|
|
647
|
+
`a` is ``self``.
|
|
648
|
+
|
|
649
|
+
INPUT:
|
|
650
|
+
|
|
651
|
+
- ``self`` -- unit modulo `n`
|
|
652
|
+
|
|
653
|
+
- ``b`` -- a unit modulo `n`. If ``b`` is not given,
|
|
654
|
+
``R.multiplicative_generator()`` is used, where
|
|
655
|
+
``R`` is the parent of ``self``.
|
|
656
|
+
|
|
657
|
+
- ``order`` -- integer (unused), the order of ``b``.
|
|
658
|
+
This argument is normally unused, only there for
|
|
659
|
+
coherence of apis with finite field elements.
|
|
660
|
+
|
|
661
|
+
- ``check`` -- boolean (default: ``False``); if set,
|
|
662
|
+
test whether the given ``order`` is correct
|
|
663
|
+
|
|
664
|
+
OUTPUT:
|
|
665
|
+
|
|
666
|
+
Integer `x` such that `b^x = a`, if this exists; a :exc:`ValueError`
|
|
667
|
+
otherwise.
|
|
668
|
+
|
|
669
|
+
.. NOTE::
|
|
670
|
+
|
|
671
|
+
The algorithm first factors the modulus, then invokes Pari's :pari:`znlog`
|
|
672
|
+
function for each odd prime power in the factorization of the modulus.
|
|
673
|
+
This method can be quite slow for large moduli.
|
|
674
|
+
|
|
675
|
+
EXAMPLES::
|
|
676
|
+
|
|
677
|
+
sage: # needs sage.libs.pari sage.modules
|
|
678
|
+
sage: r = Integers(125)
|
|
679
|
+
sage: b = r.multiplicative_generator()^3
|
|
680
|
+
sage: a = b^17
|
|
681
|
+
sage: a.log(b)
|
|
682
|
+
17
|
|
683
|
+
sage: a.log()
|
|
684
|
+
51
|
|
685
|
+
|
|
686
|
+
A bigger example::
|
|
687
|
+
|
|
688
|
+
sage: # needs sage.rings.finite_rings
|
|
689
|
+
sage: FF = FiniteField(2^32 + 61)
|
|
690
|
+
sage: c = FF(4294967356)
|
|
691
|
+
sage: x = FF(2)
|
|
692
|
+
sage: a = c.log(x)
|
|
693
|
+
sage: a
|
|
694
|
+
2147483678
|
|
695
|
+
sage: x^a
|
|
696
|
+
4294967356
|
|
697
|
+
|
|
698
|
+
An example with a highly composite modulus::
|
|
699
|
+
|
|
700
|
+
sage: m = 2^99 * 77^7 * 123456789 * 13712923537615486607^2
|
|
701
|
+
sage: (Mod(5,m)^5735816763073854953388147237921).log(5) # needs sage.libs.pari
|
|
702
|
+
5735816763073854953388147237921
|
|
703
|
+
|
|
704
|
+
Errors are generated if the logarithm doesn't exist
|
|
705
|
+
or the inputs are not units::
|
|
706
|
+
|
|
707
|
+
sage: Mod(3, 7).log(Mod(2, 7)) # needs sage.libs.pari
|
|
708
|
+
Traceback (most recent call last):
|
|
709
|
+
...
|
|
710
|
+
ValueError: no logarithm of 3 found to base 2 modulo 7
|
|
711
|
+
sage: a = Mod(16, 100); b = Mod(4, 100)
|
|
712
|
+
sage: a.log(b)
|
|
713
|
+
Traceback (most recent call last):
|
|
714
|
+
...
|
|
715
|
+
ValueError: logarithm of 16 is not defined since it is not a unit modulo 100
|
|
716
|
+
|
|
717
|
+
TESTS:
|
|
718
|
+
|
|
719
|
+
We check that :issue:`9205` is fixed::
|
|
720
|
+
|
|
721
|
+
sage: Mod(5, 9).log(Mod(2, 9)) # needs sage.libs.pari
|
|
722
|
+
5
|
|
723
|
+
|
|
724
|
+
We test against a bug (side effect on PARI) fixed in :issue:`9438`::
|
|
725
|
+
|
|
726
|
+
sage: # needs sage.libs.pari
|
|
727
|
+
sage: R.<a, b> = QQ[]
|
|
728
|
+
sage: pari(b)
|
|
729
|
+
b
|
|
730
|
+
sage: GF(7)(5).log()
|
|
731
|
+
5
|
|
732
|
+
sage: pari(b)
|
|
733
|
+
b
|
|
734
|
+
|
|
735
|
+
We test that :issue:`23927` is fixed::
|
|
736
|
+
|
|
737
|
+
sage: x = mod(48475563673907791151, 10^20 + 763)^2
|
|
738
|
+
sage: e = 25248843418589594761
|
|
739
|
+
sage: (x^e).log(x) == e # needs sage.libs.pari
|
|
740
|
+
True
|
|
741
|
+
|
|
742
|
+
Examples like this took extremely long before :issue:`32375`::
|
|
743
|
+
|
|
744
|
+
sage: (Mod(5, 123337052926643**4) ^ (10^50-1)).log(5) # needs sage.libs.pari
|
|
745
|
+
99999999999999999999999999999999999999999999999999
|
|
746
|
+
|
|
747
|
+
We check that non-existence of solutions is detected:
|
|
748
|
+
|
|
749
|
+
No local solutions::
|
|
750
|
+
|
|
751
|
+
sage: Mod(1111, 1234567).log(1111**3) # needs sage.libs.pari
|
|
752
|
+
Traceback (most recent call last):
|
|
753
|
+
...
|
|
754
|
+
ValueError: no logarithm of 1111 found to base 961261 modulo 1234567 (no solution modulo 9721)
|
|
755
|
+
|
|
756
|
+
Incompatible local solutions::
|
|
757
|
+
|
|
758
|
+
sage: Mod(230, 323).log(173) # needs sage.libs.pari
|
|
759
|
+
Traceback (most recent call last):
|
|
760
|
+
...
|
|
761
|
+
ValueError: no logarithm of 230 found to base 173 modulo 323 (incompatible local solutions)
|
|
762
|
+
|
|
763
|
+
We test that :issue:`12419` is fixed::
|
|
764
|
+
|
|
765
|
+
sage: R.<x,y> = GF(2)[]
|
|
766
|
+
sage: R(1).factor()
|
|
767
|
+
1
|
|
768
|
+
|
|
769
|
+
An example for ``check=True``::
|
|
770
|
+
|
|
771
|
+
sage: F = GF(127, impl='modn')
|
|
772
|
+
sage: t = F.primitive_element() # needs sage.libs.pari
|
|
773
|
+
sage: t.log(t, 57, check=True) # needs sage.libs.pari
|
|
774
|
+
Traceback (most recent call last):
|
|
775
|
+
...
|
|
776
|
+
ValueError: base does not have the provided order
|
|
777
|
+
|
|
778
|
+
AUTHORS:
|
|
779
|
+
|
|
780
|
+
- David Joyner and William Stein (2005-11)
|
|
781
|
+
|
|
782
|
+
- William Stein (2007-01-27): update to use PARI as requested
|
|
783
|
+
by David Kohel.
|
|
784
|
+
|
|
785
|
+
- Simon King (2010-07-07): fix a side effect on PARI
|
|
786
|
+
|
|
787
|
+
- Lorenz Panny (2021): speedups for composite moduli
|
|
788
|
+
"""
|
|
789
|
+
if not self.is_unit():
|
|
790
|
+
raise ValueError(f"logarithm of {self} is not defined since it is not a unit modulo {self.modulus()}")
|
|
791
|
+
|
|
792
|
+
if b is None:
|
|
793
|
+
b = self._parent.multiplicative_generator()
|
|
794
|
+
else:
|
|
795
|
+
b = self._parent(b)
|
|
796
|
+
if not b.is_unit():
|
|
797
|
+
raise ValueError(f"logarithm with base {b} is not defined since it is not a unit modulo {b.modulus()}")
|
|
798
|
+
|
|
799
|
+
if check:
|
|
800
|
+
from sage.groups.generic import has_order
|
|
801
|
+
if not has_order(b, order, '*'):
|
|
802
|
+
raise ValueError('base does not have the provided order')
|
|
803
|
+
|
|
804
|
+
cdef Integer n = Integer()
|
|
805
|
+
cdef Integer m = one_Z
|
|
806
|
+
cdef Integer q, na, nb
|
|
807
|
+
|
|
808
|
+
for p, e in self.modulus().factor():
|
|
809
|
+
q = p**e
|
|
810
|
+
a_red = Mod(self.lift(), q)
|
|
811
|
+
b_red = Mod(b.lift(), q)
|
|
812
|
+
|
|
813
|
+
na = a_red.multiplicative_order()
|
|
814
|
+
nb = b_red.multiplicative_order()
|
|
815
|
+
if not na.divides(nb): # cannot be a power
|
|
816
|
+
raise ValueError(f"no logarithm of {self} found to base {b} modulo {self.modulus()}"
|
|
817
|
+
+ (f" (no solution modulo {q})" if q != self.modulus() else ""))
|
|
818
|
+
|
|
819
|
+
if p == 2 and e >= 3: # (ZZ/2^e)* is not cyclic; must not give unsolvable DLPs to Pari
|
|
820
|
+
try:
|
|
821
|
+
from sage.groups.generic import discrete_log
|
|
822
|
+
v = discrete_log(a_red, b_red, nb)
|
|
823
|
+
except ValueError:
|
|
824
|
+
raise ValueError(f"no logarithm of {self} found to base {b} modulo {self.modulus()}"
|
|
825
|
+
+ (f" (no solution modulo {q})" if q != self.modulus() else ""))
|
|
826
|
+
else:
|
|
827
|
+
try:
|
|
828
|
+
v = pari(a_red).znlog(pari(b_red)).sage()
|
|
829
|
+
except PariError as msg:
|
|
830
|
+
raise RuntimeError(f"{msg}\nPARI failed to compute discrete log modulo {q} (perhaps base is not a generator or is too large)")
|
|
831
|
+
assert v != [] # if this happens, we've made a mistake above (or there is a Pari bug)
|
|
832
|
+
|
|
833
|
+
try:
|
|
834
|
+
n = crt(n, v, m, nb)
|
|
835
|
+
except ValueError:
|
|
836
|
+
raise ValueError(f"no logarithm of {self} found to base {b} modulo {self.modulus()} (incompatible local solutions)")
|
|
837
|
+
m = lcm(m, nb)
|
|
838
|
+
|
|
839
|
+
# assert b**n == self
|
|
840
|
+
return n
|
|
841
|
+
|
|
842
|
+
def generalised_log(self):
|
|
843
|
+
r"""
|
|
844
|
+
Return integers `[n_1, \ldots, n_d]` such that.
|
|
845
|
+
|
|
846
|
+
.. MATH::
|
|
847
|
+
|
|
848
|
+
\prod_{i=1}^d x_i^{n_i} = \text{self},
|
|
849
|
+
|
|
850
|
+
where `x_1, \dots, x_d` are the generators of the unit group
|
|
851
|
+
returned by ``self.parent().unit_gens()``.
|
|
852
|
+
|
|
853
|
+
EXAMPLES::
|
|
854
|
+
|
|
855
|
+
|
|
856
|
+
sage: m = Mod(3, 1568)
|
|
857
|
+
sage: v = m.generalised_log(); v # needs sage.libs.pari sage.modules
|
|
858
|
+
[1, 3, 1]
|
|
859
|
+
sage: prod([Zmod(1568).unit_gens()[i] ** v[i] for i in [0..2]]) # needs sage.libs.pari sage.modules
|
|
860
|
+
3
|
|
861
|
+
|
|
862
|
+
.. SEEALSO::
|
|
863
|
+
|
|
864
|
+
The method :meth:`log`.
|
|
865
|
+
|
|
866
|
+
.. warning::
|
|
867
|
+
|
|
868
|
+
The output is given relative to the set of generators
|
|
869
|
+
obtained by passing ``algorithm='sage'`` to the method
|
|
870
|
+
:meth:`~sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic.unit_gens`
|
|
871
|
+
of the parent (which is the default). Specifying
|
|
872
|
+
``algorithm='pari'`` usually yields a different set of
|
|
873
|
+
generators that is incompatible with this method.
|
|
874
|
+
"""
|
|
875
|
+
if not self.is_unit():
|
|
876
|
+
raise ZeroDivisionError
|
|
877
|
+
N = self.modulus()
|
|
878
|
+
h = []
|
|
879
|
+
for (p, c) in N.factor():
|
|
880
|
+
if p != 2 or (p == 2 and c == 2):
|
|
881
|
+
h.append((self % p**c).log())
|
|
882
|
+
elif c > 2:
|
|
883
|
+
m = self % p**c
|
|
884
|
+
if m % 4 == 1:
|
|
885
|
+
h.append(0)
|
|
886
|
+
else:
|
|
887
|
+
h.append(1)
|
|
888
|
+
m *= -1
|
|
889
|
+
h.append(m.log(5))
|
|
890
|
+
return h
|
|
891
|
+
|
|
892
|
+
def modulus(IntegerMod_abstract self):
|
|
893
|
+
"""
|
|
894
|
+
EXAMPLES::
|
|
895
|
+
|
|
896
|
+
sage: Mod(3,17).modulus()
|
|
897
|
+
17
|
|
898
|
+
"""
|
|
899
|
+
return self._modulus.sageInteger
|
|
900
|
+
|
|
901
|
+
def charpoly(self, var='x'):
|
|
902
|
+
"""
|
|
903
|
+
Return the characteristic polynomial of this element.
|
|
904
|
+
|
|
905
|
+
EXAMPLES::
|
|
906
|
+
|
|
907
|
+
sage: k = GF(3)
|
|
908
|
+
sage: a = k.gen()
|
|
909
|
+
sage: a.charpoly('x')
|
|
910
|
+
x + 2
|
|
911
|
+
sage: a + 2
|
|
912
|
+
0
|
|
913
|
+
|
|
914
|
+
AUTHORS:
|
|
915
|
+
|
|
916
|
+
- Craig Citro
|
|
917
|
+
"""
|
|
918
|
+
R = self.parent()[var]
|
|
919
|
+
return R([-self,1])
|
|
920
|
+
|
|
921
|
+
def minpoly(self, var='x'):
|
|
922
|
+
"""
|
|
923
|
+
Return the minimal polynomial of this element.
|
|
924
|
+
|
|
925
|
+
EXAMPLES::
|
|
926
|
+
|
|
927
|
+
sage: GF(241, 'a')(1).minpoly()
|
|
928
|
+
x + 240
|
|
929
|
+
"""
|
|
930
|
+
return self.charpoly(var)
|
|
931
|
+
|
|
932
|
+
def minimal_polynomial(self, var='x'):
|
|
933
|
+
"""
|
|
934
|
+
Return the minimal polynomial of this element.
|
|
935
|
+
|
|
936
|
+
EXAMPLES::
|
|
937
|
+
|
|
938
|
+
sage: GF(241, 'a')(1).minimal_polynomial(var = 'z')
|
|
939
|
+
z + 240
|
|
940
|
+
"""
|
|
941
|
+
return self.minpoly(var)
|
|
942
|
+
|
|
943
|
+
def polynomial(self, var='x'):
|
|
944
|
+
"""
|
|
945
|
+
Return a constant polynomial representing this value.
|
|
946
|
+
|
|
947
|
+
EXAMPLES::
|
|
948
|
+
|
|
949
|
+
sage: k = GF(7)
|
|
950
|
+
sage: a = k.gen(); a
|
|
951
|
+
1
|
|
952
|
+
sage: a.polynomial()
|
|
953
|
+
1
|
|
954
|
+
sage: type(a.polynomial()) # needs sage.libs.flint
|
|
955
|
+
<class 'sage.rings.polynomial.polynomial_zmod_flint.Polynomial_zmod_flint'>
|
|
956
|
+
"""
|
|
957
|
+
R = self.parent()[var]
|
|
958
|
+
return R(self)
|
|
959
|
+
|
|
960
|
+
def norm(self):
|
|
961
|
+
"""
|
|
962
|
+
Return the norm of this element, which is itself. (This is here
|
|
963
|
+
for compatibility with higher order finite fields.)
|
|
964
|
+
|
|
965
|
+
EXAMPLES::
|
|
966
|
+
|
|
967
|
+
sage: k = GF(691)
|
|
968
|
+
sage: a = k(389)
|
|
969
|
+
sage: a.norm()
|
|
970
|
+
389
|
|
971
|
+
|
|
972
|
+
AUTHORS:
|
|
973
|
+
|
|
974
|
+
- Craig Citro
|
|
975
|
+
"""
|
|
976
|
+
return self
|
|
977
|
+
|
|
978
|
+
def trace(self):
|
|
979
|
+
"""
|
|
980
|
+
Return the trace of this element, which is itself. (This is here
|
|
981
|
+
for compatibility with higher order finite fields.)
|
|
982
|
+
|
|
983
|
+
EXAMPLES::
|
|
984
|
+
|
|
985
|
+
sage: k = GF(691)
|
|
986
|
+
sage: a = k(389)
|
|
987
|
+
sage: a.trace()
|
|
988
|
+
389
|
|
989
|
+
|
|
990
|
+
AUTHORS:
|
|
991
|
+
|
|
992
|
+
- Craig Citro
|
|
993
|
+
"""
|
|
994
|
+
return self
|
|
995
|
+
|
|
996
|
+
def lift_centered(self):
|
|
997
|
+
r"""
|
|
998
|
+
Lift ``self`` to a centered congruent integer.
|
|
999
|
+
|
|
1000
|
+
OUTPUT:
|
|
1001
|
+
|
|
1002
|
+
The unique integer `i` such that `-n/2 < i \leq n/2` and `i = self \mod n`
|
|
1003
|
+
(where `n` denotes the modulus).
|
|
1004
|
+
|
|
1005
|
+
EXAMPLES::
|
|
1006
|
+
|
|
1007
|
+
sage: Mod(0,5).lift_centered()
|
|
1008
|
+
0
|
|
1009
|
+
sage: Mod(1,5).lift_centered()
|
|
1010
|
+
1
|
|
1011
|
+
sage: Mod(2,5).lift_centered()
|
|
1012
|
+
2
|
|
1013
|
+
sage: Mod(3,5).lift_centered()
|
|
1014
|
+
-2
|
|
1015
|
+
sage: Mod(4,5).lift_centered()
|
|
1016
|
+
-1
|
|
1017
|
+
sage: Mod(50,100).lift_centered()
|
|
1018
|
+
50
|
|
1019
|
+
sage: Mod(51,100).lift_centered()
|
|
1020
|
+
-49
|
|
1021
|
+
sage: Mod(-1,3^100).lift_centered()
|
|
1022
|
+
-1
|
|
1023
|
+
"""
|
|
1024
|
+
n = self.modulus()
|
|
1025
|
+
x = self.lift()
|
|
1026
|
+
if 2*x <= n:
|
|
1027
|
+
return x
|
|
1028
|
+
else:
|
|
1029
|
+
return x - n
|
|
1030
|
+
|
|
1031
|
+
cpdef bint is_one(self) noexcept:
|
|
1032
|
+
raise NotImplementedError
|
|
1033
|
+
|
|
1034
|
+
cpdef bint is_unit(self) noexcept:
|
|
1035
|
+
raise NotImplementedError
|
|
1036
|
+
|
|
1037
|
+
@coerce_binop
|
|
1038
|
+
def divides(self, other):
|
|
1039
|
+
r"""
|
|
1040
|
+
Test whether ``self`` divides ``other``.
|
|
1041
|
+
|
|
1042
|
+
EXAMPLES::
|
|
1043
|
+
|
|
1044
|
+
sage: R = Zmod(6)
|
|
1045
|
+
sage: R(2).divides(R(4))
|
|
1046
|
+
True
|
|
1047
|
+
sage: R(4).divides(R(2))
|
|
1048
|
+
True
|
|
1049
|
+
sage: R(2).divides(R(3))
|
|
1050
|
+
False
|
|
1051
|
+
"""
|
|
1052
|
+
if not other:
|
|
1053
|
+
return True
|
|
1054
|
+
elif not self:
|
|
1055
|
+
return False
|
|
1056
|
+
mod = self.modulus()
|
|
1057
|
+
sl = self.lift().gcd(mod)
|
|
1058
|
+
if sl.is_one():
|
|
1059
|
+
return True
|
|
1060
|
+
return sl.divides(other.lift().gcd(mod))
|
|
1061
|
+
|
|
1062
|
+
def is_square(self):
|
|
1063
|
+
r"""
|
|
1064
|
+
EXAMPLES::
|
|
1065
|
+
|
|
1066
|
+
sage: Mod(3, 17).is_square()
|
|
1067
|
+
False
|
|
1068
|
+
|
|
1069
|
+
sage: # needs sage.libs.pari
|
|
1070
|
+
sage: Mod(9, 17).is_square()
|
|
1071
|
+
True
|
|
1072
|
+
sage: Mod(9, 17*19^2).is_square()
|
|
1073
|
+
True
|
|
1074
|
+
sage: Mod(-1, 17^30).is_square()
|
|
1075
|
+
True
|
|
1076
|
+
sage: Mod(1/9, next_prime(2^40)).is_square()
|
|
1077
|
+
True
|
|
1078
|
+
sage: Mod(1/25, next_prime(2^90)).is_square()
|
|
1079
|
+
True
|
|
1080
|
+
|
|
1081
|
+
TESTS::
|
|
1082
|
+
|
|
1083
|
+
sage: Mod(1/25, 2^8).is_square() # needs sage.libs.pari
|
|
1084
|
+
True
|
|
1085
|
+
sage: Mod(1/25, 2^40).is_square() # needs sage.libs.pari
|
|
1086
|
+
True
|
|
1087
|
+
|
|
1088
|
+
sage: for p,q,r in cartesian_product_iterator([[3,5],[11,13],[17,19]]): # long time, needs sage.libs.pari
|
|
1089
|
+
....: for ep,eq,er in cartesian_product_iterator([[0,1,2,3],[0,1,2,3],[0,1,2,3]]):
|
|
1090
|
+
....: for e2 in [0, 1, 2, 3, 4]:
|
|
1091
|
+
....: n = p^ep * q^eq * r^er * 2^e2
|
|
1092
|
+
....: for _ in range(2):
|
|
1093
|
+
....: a = Zmod(n).random_element()
|
|
1094
|
+
....: if a.is_square().__xor__(a.__pari__().issquare()):
|
|
1095
|
+
....: print(a, n)
|
|
1096
|
+
|
|
1097
|
+
ALGORITHM: Calculate the Jacobi symbol
|
|
1098
|
+
`(\mathtt{self}/p)` at each prime `p`
|
|
1099
|
+
dividing `n`. It must be 1 or 0 for each prime, and if it
|
|
1100
|
+
is 0 mod `p`, where `p^k || n`, then
|
|
1101
|
+
`ord_p(\mathtt{self})` must be even or greater than
|
|
1102
|
+
`k`.
|
|
1103
|
+
|
|
1104
|
+
The case `p = 2` is handled separately.
|
|
1105
|
+
|
|
1106
|
+
AUTHORS:
|
|
1107
|
+
|
|
1108
|
+
- Robert Bradshaw
|
|
1109
|
+
"""
|
|
1110
|
+
return self.is_square_c()
|
|
1111
|
+
|
|
1112
|
+
cdef bint is_square_c(self) except -2:
|
|
1113
|
+
cdef int l2, m2
|
|
1114
|
+
if self.is_zero() or self.is_one():
|
|
1115
|
+
return 1
|
|
1116
|
+
# We first try to rule out self being a square without
|
|
1117
|
+
# factoring the modulus.
|
|
1118
|
+
lift = self.lift()
|
|
1119
|
+
m2, modd = self.modulus().val_unit(2)
|
|
1120
|
+
if m2 == 2:
|
|
1121
|
+
if lift & 2 == 2: # lift = 2 or 3 (mod 4)
|
|
1122
|
+
return 0
|
|
1123
|
+
elif m2 > 2:
|
|
1124
|
+
l2, lodd = lift.val_unit(2)
|
|
1125
|
+
if l2 < m2 and (l2 % 2 == 1 or lodd % (1 << min(3, m2 - l2)) != 1):
|
|
1126
|
+
return 0
|
|
1127
|
+
# self is a square modulo 2^m2. We compute the Jacobi symbol
|
|
1128
|
+
# modulo modd. If this is -1, then self is not a square.
|
|
1129
|
+
if lift.jacobi(modd) == -1:
|
|
1130
|
+
return 0
|
|
1131
|
+
# We need to factor the modulus. We do it here instead of
|
|
1132
|
+
# letting PARI do it, so that we can cache the factorisation.
|
|
1133
|
+
return lift.__pari__().Zn_issquare(self._parent.factored_order())
|
|
1134
|
+
|
|
1135
|
+
def sqrt(self, extend=True, all=False):
|
|
1136
|
+
r"""
|
|
1137
|
+
Return square root or square roots of ``self`` modulo `n`.
|
|
1138
|
+
|
|
1139
|
+
INPUT:
|
|
1140
|
+
|
|
1141
|
+
- ``extend`` -- boolean (default: ``True``); if ``True``, return a
|
|
1142
|
+
square root in an extension ring, if necessary. Otherwise, raise a
|
|
1143
|
+
:exc:`ValueError` if the square root is not in the base ring.
|
|
1144
|
+
|
|
1145
|
+
- ``all`` -- boolean (default: ``False``); if ``True``, return {all}
|
|
1146
|
+
square roots of self, instead of just one
|
|
1147
|
+
|
|
1148
|
+
ALGORITHM: Calculates the square roots mod `p` for each of
|
|
1149
|
+
the primes `p` dividing the order of the ring, then lifts
|
|
1150
|
+
them `p`-adically and uses the CRT to find a square root
|
|
1151
|
+
mod `n`.
|
|
1152
|
+
|
|
1153
|
+
See also :meth:`square_root_mod_prime_power` and
|
|
1154
|
+
:meth:`square_root_mod_prime` for more algorithmic details.
|
|
1155
|
+
|
|
1156
|
+
EXAMPLES::
|
|
1157
|
+
|
|
1158
|
+
sage: mod(-1, 17).sqrt()
|
|
1159
|
+
4
|
|
1160
|
+
sage: mod(5, 389).sqrt()
|
|
1161
|
+
86
|
|
1162
|
+
sage: mod(7, 18).sqrt()
|
|
1163
|
+
5
|
|
1164
|
+
|
|
1165
|
+
sage: # needs sage.libs.pari
|
|
1166
|
+
sage: a = mod(14, 5^60).sqrt()
|
|
1167
|
+
sage: a*a
|
|
1168
|
+
14
|
|
1169
|
+
sage: mod(15, 389).sqrt(extend=False)
|
|
1170
|
+
Traceback (most recent call last):
|
|
1171
|
+
...
|
|
1172
|
+
ValueError: self must be a square
|
|
1173
|
+
sage: Mod(1/9, next_prime(2^40)).sqrt()^(-2)
|
|
1174
|
+
9
|
|
1175
|
+
sage: Mod(1/25, next_prime(2^90)).sqrt()^(-2)
|
|
1176
|
+
25
|
|
1177
|
+
|
|
1178
|
+
Error message as requested in :issue:`38802`::
|
|
1179
|
+
|
|
1180
|
+
sage: sqrt(Mod(2, 101010), all=True) # needs sage.rings.finite_rings
|
|
1181
|
+
Traceback (most recent call last):
|
|
1182
|
+
...
|
|
1183
|
+
NotImplementedError: Finding all square roots in extensions is not implemented; try extend=False to find only roots in the base ring Zmod(n).
|
|
1184
|
+
|
|
1185
|
+
Using the suggested ``extend=False`` works and returns an empty list
|
|
1186
|
+
as expected::
|
|
1187
|
+
|
|
1188
|
+
sage: sqrt(Mod(2, 101010), all=True, extend=False) # needs sage.rings.finite_rings
|
|
1189
|
+
[]
|
|
1190
|
+
|
|
1191
|
+
::
|
|
1192
|
+
|
|
1193
|
+
sage: a = Mod(3, 5); a
|
|
1194
|
+
3
|
|
1195
|
+
sage: x = Mod(-1, 360)
|
|
1196
|
+
sage: x.sqrt(extend=False)
|
|
1197
|
+
Traceback (most recent call last):
|
|
1198
|
+
...
|
|
1199
|
+
ValueError: self must be a square
|
|
1200
|
+
sage: y = x.sqrt(); y
|
|
1201
|
+
sqrt359
|
|
1202
|
+
sage: y.parent()
|
|
1203
|
+
Univariate Quotient Polynomial Ring in sqrt359 over
|
|
1204
|
+
Ring of integers modulo 360 with modulus x^2 + 1
|
|
1205
|
+
sage: y^2
|
|
1206
|
+
359
|
|
1207
|
+
|
|
1208
|
+
We compute all square roots in several cases::
|
|
1209
|
+
|
|
1210
|
+
sage: R = Integers(5*2^3*3^2); R
|
|
1211
|
+
Ring of integers modulo 360
|
|
1212
|
+
sage: R(40).sqrt(all=True)
|
|
1213
|
+
[20, 160, 200, 340]
|
|
1214
|
+
sage: [x for x in R if x^2 == 40] # Brute force verification
|
|
1215
|
+
[20, 160, 200, 340]
|
|
1216
|
+
sage: R(1).sqrt(all=True)
|
|
1217
|
+
[1, 19, 71, 89, 91, 109, 161, 179, 181, 199, 251, 269, 271, 289, 341, 359]
|
|
1218
|
+
sage: R(0).sqrt(all=True)
|
|
1219
|
+
[0, 60, 120, 180, 240, 300]
|
|
1220
|
+
|
|
1221
|
+
::
|
|
1222
|
+
|
|
1223
|
+
sage: # needs sage.libs.pari
|
|
1224
|
+
sage: R = Integers(5*13^3*37); R
|
|
1225
|
+
Ring of integers modulo 406445
|
|
1226
|
+
sage: v = R(-1).sqrt(all=True); v
|
|
1227
|
+
[78853, 111808, 160142, 193097, 213348, 246303, 294637, 327592]
|
|
1228
|
+
sage: [x^2 for x in v]
|
|
1229
|
+
[406444, 406444, 406444, 406444, 406444, 406444, 406444, 406444]
|
|
1230
|
+
sage: v = R(169).sqrt(all=True); min(v), -max(v), len(v)
|
|
1231
|
+
(13, 13, 104)
|
|
1232
|
+
sage: all(x^2 == 169 for x in v)
|
|
1233
|
+
True
|
|
1234
|
+
|
|
1235
|
+
::
|
|
1236
|
+
|
|
1237
|
+
sage: # needs sage.rings.finite_rings
|
|
1238
|
+
sage: t = FiniteField(next_prime(2^100))(4)
|
|
1239
|
+
sage: t.sqrt(extend=False, all=True)
|
|
1240
|
+
[2, 1267650600228229401496703205651]
|
|
1241
|
+
sage: t = FiniteField(next_prime(2^100))(2)
|
|
1242
|
+
sage: t.sqrt(extend=False, all=True)
|
|
1243
|
+
[]
|
|
1244
|
+
|
|
1245
|
+
Modulo a power of 2::
|
|
1246
|
+
|
|
1247
|
+
sage: R = Integers(2^7); R
|
|
1248
|
+
Ring of integers modulo 128
|
|
1249
|
+
sage: a = R(17)
|
|
1250
|
+
sage: a.sqrt()
|
|
1251
|
+
23
|
|
1252
|
+
sage: a.sqrt(all=True)
|
|
1253
|
+
[23, 41, 87, 105]
|
|
1254
|
+
sage: [x for x in R if x^2==17]
|
|
1255
|
+
[23, 41, 87, 105]
|
|
1256
|
+
"""
|
|
1257
|
+
if self.is_one():
|
|
1258
|
+
if all:
|
|
1259
|
+
return list(self.parent().square_roots_of_one())
|
|
1260
|
+
else:
|
|
1261
|
+
return self
|
|
1262
|
+
|
|
1263
|
+
if not self.is_square_c():
|
|
1264
|
+
if extend:
|
|
1265
|
+
y = 'sqrt%s' % self
|
|
1266
|
+
R = self.parent()['x']
|
|
1267
|
+
modulus = R.gen()**2 - R(self)
|
|
1268
|
+
if self._parent.is_field():
|
|
1269
|
+
from sage.rings.finite_rings.finite_field_constructor import FiniteField
|
|
1270
|
+
Q = FiniteField(self._modulus.sageInteger**2, y, modulus)
|
|
1271
|
+
else:
|
|
1272
|
+
R = self.parent()['x']
|
|
1273
|
+
Q = R.quotient(modulus, names=(y,))
|
|
1274
|
+
z = Q.gen()
|
|
1275
|
+
if all:
|
|
1276
|
+
# TODO
|
|
1277
|
+
raise NotImplementedError("Finding all square roots in extensions is not implemented; try extend=False to find only roots in the base ring Zmod(n).")
|
|
1278
|
+
return z
|
|
1279
|
+
if all:
|
|
1280
|
+
return []
|
|
1281
|
+
raise ValueError("self must be a square")
|
|
1282
|
+
|
|
1283
|
+
F = self._parent.factored_order()
|
|
1284
|
+
cdef long e, exp, val
|
|
1285
|
+
if len(F) == 1:
|
|
1286
|
+
p, e = F[0]
|
|
1287
|
+
|
|
1288
|
+
if all and e > 1 and not self.is_unit():
|
|
1289
|
+
if self.is_zero():
|
|
1290
|
+
# All multiples of p^ciel(e/2) vanish
|
|
1291
|
+
return [self._parent(x) for x in range(0, self._modulus.sageInteger, p**((e+1)/2))]
|
|
1292
|
+
else:
|
|
1293
|
+
z = self.lift()
|
|
1294
|
+
val = z.valuation(p)/2 # square => valuation is even
|
|
1295
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
1296
|
+
# Find the unit part (mod the ring with appropriate precision)
|
|
1297
|
+
u = IntegerModRing(p**(e-val))(z // p**(2*val))
|
|
1298
|
+
# will add multiples of p^exp
|
|
1299
|
+
exp = e - val
|
|
1300
|
+
if p == 2:
|
|
1301
|
+
exp -= 1 # note the factor of 2 below
|
|
1302
|
+
if 2*exp < e:
|
|
1303
|
+
exp = (e+1)/2
|
|
1304
|
+
# For all a^2 = u and all integers b
|
|
1305
|
+
# (a*p^val + b*p^exp) ^ 2
|
|
1306
|
+
# = u*p^(2*val) + 2*a*b*p^(val+exp) + b^2*p^(2*exp)
|
|
1307
|
+
# = u*p^(2*val) mod p^e
|
|
1308
|
+
# whenever min(val+exp, 2*exp) > e
|
|
1309
|
+
p_val = p**val
|
|
1310
|
+
p_exp = p**exp
|
|
1311
|
+
w = [self._parent(a.lift() * p_val + b)
|
|
1312
|
+
for a in u.sqrt(all=True)
|
|
1313
|
+
for b in range(0, self._modulus.sageInteger, p_exp)]
|
|
1314
|
+
if p == 2:
|
|
1315
|
+
w = list(set(w))
|
|
1316
|
+
w.sort()
|
|
1317
|
+
return w
|
|
1318
|
+
|
|
1319
|
+
if e > 1:
|
|
1320
|
+
x = square_root_mod_prime_power(mod(self, p**e), p, e)
|
|
1321
|
+
else:
|
|
1322
|
+
x = square_root_mod_prime(self, p)
|
|
1323
|
+
x = x._balanced_abs()
|
|
1324
|
+
|
|
1325
|
+
if not all:
|
|
1326
|
+
return x
|
|
1327
|
+
|
|
1328
|
+
v = list(set([x*a for a in self._parent.square_roots_of_one()]))
|
|
1329
|
+
v.sort()
|
|
1330
|
+
return v
|
|
1331
|
+
|
|
1332
|
+
else:
|
|
1333
|
+
if not all:
|
|
1334
|
+
# Use CRT to combine together a square root modulo each prime power
|
|
1335
|
+
sqrts = [square_root_mod_prime(mod(self, p), p) for p, e in F if e == 1] + \
|
|
1336
|
+
[square_root_mod_prime_power(mod(self, p**e), p, e) for p, e in F if e != 1]
|
|
1337
|
+
|
|
1338
|
+
x = sqrts.pop()
|
|
1339
|
+
for y in sqrts:
|
|
1340
|
+
x = x.crt(y)
|
|
1341
|
+
return x._balanced_abs()
|
|
1342
|
+
else:
|
|
1343
|
+
# Use CRT to combine together all square roots modulo each prime power
|
|
1344
|
+
vmod = []
|
|
1345
|
+
moduli = []
|
|
1346
|
+
P = self.parent()
|
|
1347
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
1348
|
+
for p, e in F:
|
|
1349
|
+
k = p**e
|
|
1350
|
+
R = IntegerModRing(p**e)
|
|
1351
|
+
w = [P(x) for x in R(self).sqrt(all=True)]
|
|
1352
|
+
vmod.append(w)
|
|
1353
|
+
moduli.append(k)
|
|
1354
|
+
# Now combine in all possible ways using the CRT
|
|
1355
|
+
from sage.arith.misc import CRT_basis
|
|
1356
|
+
basis = CRT_basis(moduli)
|
|
1357
|
+
from sage.misc.mrange import cartesian_product_iterator
|
|
1358
|
+
v = []
|
|
1359
|
+
for x in cartesian_product_iterator(vmod):
|
|
1360
|
+
# x is a specific choice of roots modulo each prime power divisor
|
|
1361
|
+
a = sum([basis[i]*x[i] for i in range(len(x))])
|
|
1362
|
+
v.append(a)
|
|
1363
|
+
v.sort()
|
|
1364
|
+
return v
|
|
1365
|
+
|
|
1366
|
+
square_root = sqrt
|
|
1367
|
+
|
|
1368
|
+
def nth_root(self, n, extend=False, all=False, algorithm=None, cunningham=False):
|
|
1369
|
+
r"""
|
|
1370
|
+
Return an `n`-th root of ``self``.
|
|
1371
|
+
|
|
1372
|
+
INPUT:
|
|
1373
|
+
|
|
1374
|
+
- ``n`` -- integer `\geq 1`
|
|
1375
|
+
|
|
1376
|
+
- ``extend`` -- boolean (default: ``True``); if ``True``, return an
|
|
1377
|
+
`n`-th root in an extension ring, if necessary. Otherwise, raise a
|
|
1378
|
+
:exc:`ValueError` if the root is not in the base ring. Warning:
|
|
1379
|
+
this option is not implemented!
|
|
1380
|
+
|
|
1381
|
+
- ``all`` -- boolean (default: ``False``); if ``True``, return all
|
|
1382
|
+
`n`-th roots of ``self``, instead of just one
|
|
1383
|
+
|
|
1384
|
+
- ``algorithm`` -- string (default: ``None``); the algorithm for the
|
|
1385
|
+
prime modulus case. CRT and `p`-adic log techniques are used to reduce
|
|
1386
|
+
to this case. ``'Johnston'`` is the only currently supported option.
|
|
1387
|
+
|
|
1388
|
+
- ``cunningham`` -- boolean (default: ``False``); in some cases,
|
|
1389
|
+
factorization of `n` is computed. If cunningham is set to ``True``,
|
|
1390
|
+
the factorization of `n` is computed using trial division for all
|
|
1391
|
+
primes in the so called Cunningham table. Refer to
|
|
1392
|
+
``sage.rings.factorint.factor_cunningham`` for more information. You
|
|
1393
|
+
need to install an optional package to use this method, this can be
|
|
1394
|
+
done with the following command line: ``sage -i cunningham_tables``.
|
|
1395
|
+
|
|
1396
|
+
OUTPUT:
|
|
1397
|
+
|
|
1398
|
+
If ``self`` has an `n`-th root, returns one (if ``all`` is ``False``) or a
|
|
1399
|
+
list of all of them (if ``all`` is ``True``). Otherwise, raises a
|
|
1400
|
+
:exc:`ValueError` (if ``extend`` is ``False``) or a
|
|
1401
|
+
:exc:`NotImplementedError` (if ``extend`` is ``True``).
|
|
1402
|
+
|
|
1403
|
+
.. warning::
|
|
1404
|
+
|
|
1405
|
+
The 'extend' option is not implemented (yet).
|
|
1406
|
+
|
|
1407
|
+
NOTE:
|
|
1408
|
+
|
|
1409
|
+
- If `n = 0`:
|
|
1410
|
+
|
|
1411
|
+
- if ``all=True``:
|
|
1412
|
+
|
|
1413
|
+
- if ``self=1``: all nonzero elements of the parent are returned in
|
|
1414
|
+
a list. Note that this could be very expensive for large
|
|
1415
|
+
parents.
|
|
1416
|
+
|
|
1417
|
+
- otherwise: an empty list is returned
|
|
1418
|
+
|
|
1419
|
+
- if ``all=False``:
|
|
1420
|
+
|
|
1421
|
+
- if ``self=1``: ``self`` is returned
|
|
1422
|
+
|
|
1423
|
+
- otherwise; a :exc:`ValueError` is raised
|
|
1424
|
+
|
|
1425
|
+
- If `n < 0`:
|
|
1426
|
+
|
|
1427
|
+
- if ``self`` is invertible, the `(-n)`\th root of the inverse of ``self`` is returned
|
|
1428
|
+
|
|
1429
|
+
- otherwise a :exc:`ValueError` is raised or empty list returned.
|
|
1430
|
+
|
|
1431
|
+
EXAMPLES::
|
|
1432
|
+
|
|
1433
|
+
|
|
1434
|
+
sage: K = GF(31)
|
|
1435
|
+
sage: a = K(22)
|
|
1436
|
+
sage: K(22).nth_root(7)
|
|
1437
|
+
13
|
|
1438
|
+
sage: K(25).nth_root(5)
|
|
1439
|
+
5
|
|
1440
|
+
sage: K(23).nth_root(3)
|
|
1441
|
+
29
|
|
1442
|
+
|
|
1443
|
+
sage: # needs sage.rings.padics
|
|
1444
|
+
sage: mod(225, 2^5*3^2).nth_root(4, all=True)
|
|
1445
|
+
[225, 129, 33, 63, 255, 159, 9, 201, 105, 279, 183, 87, 81,
|
|
1446
|
+
273, 177, 207, 111, 15, 153, 57, 249, 135, 39, 231]
|
|
1447
|
+
sage: mod(275, 2^5*7^4).nth_root(7, all=True)
|
|
1448
|
+
[58235, 25307, 69211, 36283, 3355, 47259, 14331]
|
|
1449
|
+
sage: mod(1,8).nth_root(2, all=True)
|
|
1450
|
+
[1, 7, 5, 3]
|
|
1451
|
+
sage: mod(4,8).nth_root(2, all=True)
|
|
1452
|
+
[2, 6]
|
|
1453
|
+
sage: mod(1,16).nth_root(4, all=True)
|
|
1454
|
+
[1, 15, 13, 3, 9, 7, 5, 11]
|
|
1455
|
+
|
|
1456
|
+
sage: (mod(22,31)^200).nth_root(200)
|
|
1457
|
+
5
|
|
1458
|
+
sage: mod(3,6).nth_root(0, all=True)
|
|
1459
|
+
[]
|
|
1460
|
+
sage: mod(3,6).nth_root(0)
|
|
1461
|
+
Traceback (most recent call last):
|
|
1462
|
+
...
|
|
1463
|
+
ValueError
|
|
1464
|
+
sage: mod(1,6).nth_root(0, all=True)
|
|
1465
|
+
[1, 2, 3, 4, 5]
|
|
1466
|
+
|
|
1467
|
+
TESTS::
|
|
1468
|
+
|
|
1469
|
+
sage: for p in [1009,2003,10007,100003]: # needs sage.rings.finite_rings
|
|
1470
|
+
....: K = GF(p)
|
|
1471
|
+
....: for r in (p-1).divisors():
|
|
1472
|
+
....: if r == 1: continue
|
|
1473
|
+
....: x = K.random_element()
|
|
1474
|
+
....: y = x^r
|
|
1475
|
+
....: if y.nth_root(r)**r != y: raise RuntimeError
|
|
1476
|
+
....: if (y^41).nth_root(41*r)**(41*r) != y^41: raise RuntimeError
|
|
1477
|
+
....: if (y^307).nth_root(307*r)**(307*r) != y^307: raise RuntimeError
|
|
1478
|
+
|
|
1479
|
+
sage: for t in range(200): # needs sage.libs.pari sage.rings.padics
|
|
1480
|
+
....: n = randint(1,2^63)
|
|
1481
|
+
....: K = Integers(n)
|
|
1482
|
+
....: b = K.random_element()
|
|
1483
|
+
....: e = randint(-2^62, 2^63)
|
|
1484
|
+
....: try:
|
|
1485
|
+
....: a = b.nth_root(e)
|
|
1486
|
+
....: if a^e != b:
|
|
1487
|
+
....: print(n, b, e, a)
|
|
1488
|
+
....: raise NotImplementedError
|
|
1489
|
+
....: except ValueError:
|
|
1490
|
+
....: pass
|
|
1491
|
+
|
|
1492
|
+
We check that :issue:`13172` is resolved::
|
|
1493
|
+
|
|
1494
|
+
sage: mod(-1, 4489).nth_root(2, all=True) # needs sage.rings.padics
|
|
1495
|
+
[]
|
|
1496
|
+
|
|
1497
|
+
We check that :issue:`32084` is fixed::
|
|
1498
|
+
|
|
1499
|
+
sage: mod(24, 25).nth_root(50)^50 # needs sage.rings.padics
|
|
1500
|
+
24
|
|
1501
|
+
|
|
1502
|
+
Check that the code path cunningham might be used::
|
|
1503
|
+
|
|
1504
|
+
sage: a = Mod(9,11)
|
|
1505
|
+
sage: a.nth_root(2, False, True, 'Johnston', cunningham=True) # optional - cunningham_tables
|
|
1506
|
+
[3, 8]
|
|
1507
|
+
|
|
1508
|
+
ALGORITHM:
|
|
1509
|
+
|
|
1510
|
+
The default for prime modulus is currently an algorithm
|
|
1511
|
+
described in [Joh1999]_.
|
|
1512
|
+
|
|
1513
|
+
AUTHORS:
|
|
1514
|
+
|
|
1515
|
+
- David Roe (2010-02-13)
|
|
1516
|
+
"""
|
|
1517
|
+
if extend:
|
|
1518
|
+
raise NotImplementedError
|
|
1519
|
+
K = self.parent()
|
|
1520
|
+
n = Integer(n)
|
|
1521
|
+
if n == 0:
|
|
1522
|
+
if self == 1:
|
|
1523
|
+
if all:
|
|
1524
|
+
return [K(a) for a in range(1, K.order())]
|
|
1525
|
+
return self
|
|
1526
|
+
else:
|
|
1527
|
+
if all:
|
|
1528
|
+
return []
|
|
1529
|
+
raise ValueError
|
|
1530
|
+
F = K.factored_order()
|
|
1531
|
+
if len(F) == 0:
|
|
1532
|
+
if all:
|
|
1533
|
+
return [self]
|
|
1534
|
+
return self
|
|
1535
|
+
if len(F) != 1:
|
|
1536
|
+
if all:
|
|
1537
|
+
# we should probably do a first pass to see if there are any solutions so that we don't get giant intermediate lists and waste time...
|
|
1538
|
+
L = []
|
|
1539
|
+
for p, k in F:
|
|
1540
|
+
L.append(mod(self, p**k).nth_root(n, all=True, algorithm=algorithm))
|
|
1541
|
+
ans = L[0]
|
|
1542
|
+
for i in range(1, len(L)):
|
|
1543
|
+
ans = [a.crt(b) for a in ans for b in L[i]]
|
|
1544
|
+
else:
|
|
1545
|
+
ans = mod(0,1)
|
|
1546
|
+
for p, k in F:
|
|
1547
|
+
ans = ans.crt(mod(self, p**k).nth_root(n, algorithm=algorithm))
|
|
1548
|
+
return ans
|
|
1549
|
+
p, k = F[0]
|
|
1550
|
+
if self.is_zero():
|
|
1551
|
+
if n < 0:
|
|
1552
|
+
if all:
|
|
1553
|
+
return []
|
|
1554
|
+
raise ValueError
|
|
1555
|
+
if all:
|
|
1556
|
+
if k == 1:
|
|
1557
|
+
return [self]
|
|
1558
|
+
minval = max(1, (k/n).ceil())
|
|
1559
|
+
return [K(a*p**minval) for a in range(p**(k-minval))]
|
|
1560
|
+
return self
|
|
1561
|
+
if n < 0:
|
|
1562
|
+
try:
|
|
1563
|
+
self = ~self
|
|
1564
|
+
except ZeroDivisionError:
|
|
1565
|
+
if all:
|
|
1566
|
+
return []
|
|
1567
|
+
raise ValueError
|
|
1568
|
+
n = -n
|
|
1569
|
+
if p == 2 and k == 1:
|
|
1570
|
+
return [self] if all else self
|
|
1571
|
+
if k > 1:
|
|
1572
|
+
pval, upart = self.lift().val_unit(p)
|
|
1573
|
+
if not n.divides(pval):
|
|
1574
|
+
if all:
|
|
1575
|
+
return []
|
|
1576
|
+
raise ValueError("no nth root")
|
|
1577
|
+
if pval > 0:
|
|
1578
|
+
if all:
|
|
1579
|
+
return [K(a.lift()*p**(pval // n) + p**(k - (pval - pval//n)) * b) for a in mod(upart, p**(k-pval)).nth_root(n, all=True, algorithm=algorithm) for b in range(p**(pval - pval//n))]
|
|
1580
|
+
else:
|
|
1581
|
+
return K(p**(pval // n) * mod(upart, p**(k-pval)).nth_root(n, algorithm=algorithm).lift())
|
|
1582
|
+
from sage.rings.padics.factory import ZpFM
|
|
1583
|
+
R = ZpFM(p,k)
|
|
1584
|
+
if p == 2:
|
|
1585
|
+
sign = [1]
|
|
1586
|
+
if self % 4 == 3:
|
|
1587
|
+
if n % 2 == 0:
|
|
1588
|
+
if all:
|
|
1589
|
+
return []
|
|
1590
|
+
raise ValueError("no nth root")
|
|
1591
|
+
else:
|
|
1592
|
+
sign = [-1]
|
|
1593
|
+
self = -self
|
|
1594
|
+
elif n % 2 == 0:
|
|
1595
|
+
if k > 2 and self % 8 == 5:
|
|
1596
|
+
if all:
|
|
1597
|
+
return []
|
|
1598
|
+
raise ValueError("no nth root")
|
|
1599
|
+
sign = [1, -1]
|
|
1600
|
+
if k == 2:
|
|
1601
|
+
if all:
|
|
1602
|
+
return [K(s) for s in sign[:2]]
|
|
1603
|
+
return K(sign[0])
|
|
1604
|
+
modp = [mod(self, 8)] if all else mod(self, 8)
|
|
1605
|
+
else:
|
|
1606
|
+
sign = [1]
|
|
1607
|
+
modp = self % p
|
|
1608
|
+
self = self / K(R.teichmuller(modp))
|
|
1609
|
+
modp = modp.nth_root(n, all=all, algorithm=algorithm)
|
|
1610
|
+
# now self is congruent to 1 mod 4 or 1 mod p (for odd p),
|
|
1611
|
+
# so the power series for p-adic log converges.
|
|
1612
|
+
# Hensel lifting is probably better, but this is easier at the moment.
|
|
1613
|
+
plog = R(self).log()
|
|
1614
|
+
nval = n.valuation(p)
|
|
1615
|
+
if nval >= plog.valuation() + (-1 if p == 2 else 0):
|
|
1616
|
+
if self == 1:
|
|
1617
|
+
if all:
|
|
1618
|
+
return [s*K(p*a+m.lift()) for a in range(p**(k-(2 if p==2 else 1))) for m in modp for s in sign]
|
|
1619
|
+
return K(modp.lift())
|
|
1620
|
+
else:
|
|
1621
|
+
if all:
|
|
1622
|
+
return []
|
|
1623
|
+
raise ValueError("no nth root")
|
|
1624
|
+
if all:
|
|
1625
|
+
ans = [plog // n + p**(k - nval) * i for i in range(p**nval)]
|
|
1626
|
+
ans = [s*K(R.teichmuller(m) * a.exp()) for a in ans for m in modp for s in sign]
|
|
1627
|
+
return ans
|
|
1628
|
+
else:
|
|
1629
|
+
return sign[0] * K(R.teichmuller(modp) * (plog // n).exp())
|
|
1630
|
+
return self._nth_root_common(n, all, algorithm, cunningham)
|
|
1631
|
+
|
|
1632
|
+
def _nth_root_naive(self, n):
|
|
1633
|
+
"""
|
|
1634
|
+
Compute all `n`-th roots using brute force, for doc-testing.
|
|
1635
|
+
|
|
1636
|
+
TESTS::
|
|
1637
|
+
|
|
1638
|
+
sage: for n in range(2,100): # long time
|
|
1639
|
+
....: K = Integers(n)
|
|
1640
|
+
....: elist = list(range(1,min(2*n+2,100)))
|
|
1641
|
+
....: for e in random_sublist(elist, 5/len(elist)):
|
|
1642
|
+
....: for a in random_sublist(range(1,n), min((n+2)//2,10)/(n-1)):
|
|
1643
|
+
....: b = K(a)
|
|
1644
|
+
....: try:
|
|
1645
|
+
....: L = b.nth_root(e, all=True)
|
|
1646
|
+
....: if L:
|
|
1647
|
+
....: c = b.nth_root(e)
|
|
1648
|
+
....: except Exception:
|
|
1649
|
+
....: L = [-1]
|
|
1650
|
+
....: M = b._nth_root_naive(e)
|
|
1651
|
+
....: if sorted(L) != M:
|
|
1652
|
+
....: print("mod(%s, %s).nth_root(%s,all=True), mod(%s, %s)._nth_root_naive(%s)" % (a,n,e,a,n,e))
|
|
1653
|
+
....: if L and (c not in L):
|
|
1654
|
+
....: print("mod(%s, %s).nth_root(%s), mod(%s, %s).nth_root(%s,all=True)" % (a,n,e,a,n,e))
|
|
1655
|
+
"""
|
|
1656
|
+
return [a for a in self.parent() if a**n == self]
|
|
1657
|
+
|
|
1658
|
+
def _balanced_abs(self):
|
|
1659
|
+
r"""
|
|
1660
|
+
This function returns `x` or `-x`, whichever has a
|
|
1661
|
+
positive representative in `-n/2 < x \leq n/2`.
|
|
1662
|
+
|
|
1663
|
+
This is used so that the same square root is always returned,
|
|
1664
|
+
despite the possibly probabilistic nature of the underlying
|
|
1665
|
+
algorithm.
|
|
1666
|
+
"""
|
|
1667
|
+
if self.lift() > self._modulus.sageInteger >> 1:
|
|
1668
|
+
return -self
|
|
1669
|
+
return self
|
|
1670
|
+
|
|
1671
|
+
def rational_reconstruction(self):
|
|
1672
|
+
"""
|
|
1673
|
+
Use rational reconstruction to try to find a lift of this element to
|
|
1674
|
+
the rational numbers.
|
|
1675
|
+
|
|
1676
|
+
EXAMPLES::
|
|
1677
|
+
|
|
1678
|
+
sage: R = IntegerModRing(97)
|
|
1679
|
+
sage: a = R(2) / R(3)
|
|
1680
|
+
sage: a
|
|
1681
|
+
33
|
|
1682
|
+
sage: a.rational_reconstruction()
|
|
1683
|
+
2/3
|
|
1684
|
+
|
|
1685
|
+
This method is also inherited by prime finite fields elements::
|
|
1686
|
+
|
|
1687
|
+
sage: k = GF(97)
|
|
1688
|
+
sage: a = k(RationalField()('2/3'))
|
|
1689
|
+
sage: a
|
|
1690
|
+
33
|
|
1691
|
+
sage: a.rational_reconstruction()
|
|
1692
|
+
2/3
|
|
1693
|
+
"""
|
|
1694
|
+
return self.lift().rational_reconstruction(self.modulus())
|
|
1695
|
+
|
|
1696
|
+
def crt(IntegerMod_abstract self, IntegerMod_abstract other):
|
|
1697
|
+
r"""
|
|
1698
|
+
Use the Chinese Remainder Theorem to find an element of the
|
|
1699
|
+
integers modulo the product of the moduli that reduces to
|
|
1700
|
+
``self`` and to ``other``. The modulus of
|
|
1701
|
+
``other`` must be coprime to the modulus of
|
|
1702
|
+
``self``.
|
|
1703
|
+
|
|
1704
|
+
EXAMPLES::
|
|
1705
|
+
|
|
1706
|
+
sage: a = mod(3, 5)
|
|
1707
|
+
sage: b = mod(2, 7)
|
|
1708
|
+
sage: a.crt(b)
|
|
1709
|
+
23
|
|
1710
|
+
|
|
1711
|
+
::
|
|
1712
|
+
|
|
1713
|
+
sage: a = mod(37, 10^8)
|
|
1714
|
+
sage: b = mod(9, 3^8)
|
|
1715
|
+
sage: a.crt(b)
|
|
1716
|
+
125900000037
|
|
1717
|
+
|
|
1718
|
+
::
|
|
1719
|
+
|
|
1720
|
+
sage: b = mod(0, 1)
|
|
1721
|
+
sage: a.crt(b) == a
|
|
1722
|
+
True
|
|
1723
|
+
sage: a.crt(b).modulus()
|
|
1724
|
+
100000000
|
|
1725
|
+
|
|
1726
|
+
TESTS::
|
|
1727
|
+
|
|
1728
|
+
sage: mod(0, 1).crt(mod(4, 2^127))
|
|
1729
|
+
4
|
|
1730
|
+
sage: mod(4, 2^127).crt(mod(0, 1))
|
|
1731
|
+
4
|
|
1732
|
+
sage: mod(4, 2^30).crt(mod(0, 1))
|
|
1733
|
+
4
|
|
1734
|
+
sage: mod(0, 1).crt(mod(4, 2^30))
|
|
1735
|
+
4
|
|
1736
|
+
sage: mod(0, 1).crt(mod(4, 2^15))
|
|
1737
|
+
4
|
|
1738
|
+
sage: mod(4, 2^15).crt(mod(0, 1))
|
|
1739
|
+
4
|
|
1740
|
+
|
|
1741
|
+
AUTHORS:
|
|
1742
|
+
|
|
1743
|
+
- Robert Bradshaw
|
|
1744
|
+
"""
|
|
1745
|
+
cdef int_fast64_t new_modulus
|
|
1746
|
+
if not isinstance(self, IntegerMod_gmp) and not isinstance(other, IntegerMod_gmp):
|
|
1747
|
+
|
|
1748
|
+
if other._modulus.int64 == 1: return self
|
|
1749
|
+
new_modulus = self._modulus.int64 * other._modulus.int64
|
|
1750
|
+
if new_modulus < INTEGER_MOD_INT32_LIMIT:
|
|
1751
|
+
return self._crt(other)
|
|
1752
|
+
|
|
1753
|
+
elif new_modulus < INTEGER_MOD_INT64_LIMIT:
|
|
1754
|
+
if not isinstance(self, IntegerMod_int64):
|
|
1755
|
+
self = IntegerMod_int64(self._parent, self.lift())
|
|
1756
|
+
if not isinstance(other, IntegerMod_int64):
|
|
1757
|
+
other = IntegerMod_int64(other._parent, other.lift())
|
|
1758
|
+
return self._crt(other)
|
|
1759
|
+
|
|
1760
|
+
if not isinstance(self, IntegerMod_gmp):
|
|
1761
|
+
if self._modulus.int64 == 1: return other
|
|
1762
|
+
self = IntegerMod_gmp(self._parent, self.lift())
|
|
1763
|
+
|
|
1764
|
+
if not isinstance(other, IntegerMod_gmp):
|
|
1765
|
+
if other._modulus.int64 == 1: return self
|
|
1766
|
+
other = IntegerMod_gmp(other._parent, other.lift())
|
|
1767
|
+
|
|
1768
|
+
return self._crt(other)
|
|
1769
|
+
|
|
1770
|
+
def additive_order(self):
|
|
1771
|
+
r"""
|
|
1772
|
+
Return the additive order of ``self``.
|
|
1773
|
+
|
|
1774
|
+
This is the same as ``self.order()``.
|
|
1775
|
+
|
|
1776
|
+
EXAMPLES::
|
|
1777
|
+
|
|
1778
|
+
sage: Integers(20)(2).additive_order()
|
|
1779
|
+
10
|
|
1780
|
+
sage: Integers(20)(7).additive_order()
|
|
1781
|
+
20
|
|
1782
|
+
sage: Integers(90308402384902)(2).additive_order()
|
|
1783
|
+
45154201192451
|
|
1784
|
+
"""
|
|
1785
|
+
n = self._modulus.sageInteger
|
|
1786
|
+
return sage.rings.integer.Integer(n // self.lift().gcd(n))
|
|
1787
|
+
|
|
1788
|
+
def is_primitive_root(self) -> bool:
|
|
1789
|
+
"""
|
|
1790
|
+
Determine whether this element generates the group of units modulo n.
|
|
1791
|
+
|
|
1792
|
+
This is only possible if the group of units is cyclic, which occurs if
|
|
1793
|
+
n is 2, 4, a power of an odd prime or twice a power of an odd prime.
|
|
1794
|
+
|
|
1795
|
+
EXAMPLES::
|
|
1796
|
+
|
|
1797
|
+
sage: mod(1, 2).is_primitive_root()
|
|
1798
|
+
True
|
|
1799
|
+
sage: mod(3, 4).is_primitive_root()
|
|
1800
|
+
True
|
|
1801
|
+
sage: mod(2, 7).is_primitive_root()
|
|
1802
|
+
False
|
|
1803
|
+
sage: mod(3, 98).is_primitive_root() # needs sage.libs.pari
|
|
1804
|
+
True
|
|
1805
|
+
sage: mod(11, 1009^2).is_primitive_root() # needs sage.libs.pari
|
|
1806
|
+
True
|
|
1807
|
+
|
|
1808
|
+
TESTS::
|
|
1809
|
+
|
|
1810
|
+
sage: for p in prime_range(3,12): # needs sage.libs.pari
|
|
1811
|
+
....: for k in range(1,4):
|
|
1812
|
+
....: for even in [1,2]:
|
|
1813
|
+
....: n = even*p^k
|
|
1814
|
+
....: phin = euler_phi(n)
|
|
1815
|
+
....: for _ in range(6):
|
|
1816
|
+
....: a = Zmod(n).random_element()
|
|
1817
|
+
....: if not a.is_unit(): continue
|
|
1818
|
+
....: if a.is_primitive_root().__xor__(a.multiplicative_order()==phin):
|
|
1819
|
+
....: print("mod(%s,%s) incorrect" % (a, n))
|
|
1820
|
+
|
|
1821
|
+
`0` is not a primitive root mod `n` (:issue:`23624`) except for `n=0`::
|
|
1822
|
+
|
|
1823
|
+
sage: mod(0, 17).is_primitive_root()
|
|
1824
|
+
False
|
|
1825
|
+
sage: all(not mod(0, n).is_primitive_root() for n in srange(2, 20)) # needs sage.libs.pari
|
|
1826
|
+
True
|
|
1827
|
+
sage: mod(0, 1).is_primitive_root()
|
|
1828
|
+
True
|
|
1829
|
+
|
|
1830
|
+
sage: all(not mod(p^j, p^k).is_primitive_root() # needs sage.libs.pari
|
|
1831
|
+
....: for p in prime_range(3, 12)
|
|
1832
|
+
....: for k in srange(1, 4)
|
|
1833
|
+
....: for j in srange(0, k))
|
|
1834
|
+
True
|
|
1835
|
+
"""
|
|
1836
|
+
cdef Integer p1, q = Integer(2)
|
|
1837
|
+
m = self.modulus()
|
|
1838
|
+
if m == 1:
|
|
1839
|
+
return True
|
|
1840
|
+
if m == 2:
|
|
1841
|
+
return self == 1
|
|
1842
|
+
if m == 4:
|
|
1843
|
+
return self == 3
|
|
1844
|
+
pow2, odd = m.val_unit(2)
|
|
1845
|
+
if pow2 > 1:
|
|
1846
|
+
return False
|
|
1847
|
+
if pow2 == 1:
|
|
1848
|
+
if self % 2 == 0:
|
|
1849
|
+
return False
|
|
1850
|
+
self = self % odd
|
|
1851
|
+
p, k = odd.perfect_power()
|
|
1852
|
+
if not p.is_prime():
|
|
1853
|
+
return False
|
|
1854
|
+
if k > 1:
|
|
1855
|
+
if self**((p-1)*p**(k-2)) == 1:
|
|
1856
|
+
return False
|
|
1857
|
+
# self**(p**(k-1)*(p-1)//q) = 1 for some q
|
|
1858
|
+
# iff mod(self,p)**((p-1)//q) = 1 for some q
|
|
1859
|
+
self = self % p
|
|
1860
|
+
if self == 0:
|
|
1861
|
+
return False
|
|
1862
|
+
# Now self is modulo a prime and need the factorization of p-1.
|
|
1863
|
+
p1 = p - 1
|
|
1864
|
+
while mpz_cmpabs_ui(p1.value, 1):
|
|
1865
|
+
q = p1.trial_division(bound=1000, start=mpz_get_ui(q.value))
|
|
1866
|
+
if q == p1:
|
|
1867
|
+
break
|
|
1868
|
+
if self**((p-1)//q) == 1:
|
|
1869
|
+
return False
|
|
1870
|
+
mpz_remove(p1.value, p1.value, q.value)
|
|
1871
|
+
if q.is_prime():
|
|
1872
|
+
return self**((p-1)//q) != 1
|
|
1873
|
+
# No small factors remain: we need to do some real work.
|
|
1874
|
+
for qq, e in q.factor():
|
|
1875
|
+
if self**((p-1)//qq) == 1:
|
|
1876
|
+
return False
|
|
1877
|
+
return True
|
|
1878
|
+
|
|
1879
|
+
def multiplicative_order(self):
|
|
1880
|
+
"""
|
|
1881
|
+
Return the multiplicative order of ``self``.
|
|
1882
|
+
|
|
1883
|
+
EXAMPLES::
|
|
1884
|
+
|
|
1885
|
+
sage: Mod(-1, 5).multiplicative_order() # needs sage.libs.pari
|
|
1886
|
+
2
|
|
1887
|
+
sage: Mod(1, 5).multiplicative_order() # needs sage.libs.pari
|
|
1888
|
+
1
|
|
1889
|
+
sage: Mod(0, 5).multiplicative_order() # needs sage.libs.pari
|
|
1890
|
+
Traceback (most recent call last):
|
|
1891
|
+
...
|
|
1892
|
+
ArithmeticError: multiplicative order of 0 not defined
|
|
1893
|
+
since it is not a unit modulo 5
|
|
1894
|
+
"""
|
|
1895
|
+
try:
|
|
1896
|
+
return sage.rings.integer.Integer(self.__pari__().znorder())
|
|
1897
|
+
except PariError:
|
|
1898
|
+
raise ArithmeticError("multiplicative order of %s not defined since it is not a unit modulo %s" % (
|
|
1899
|
+
self, self._modulus.sageInteger))
|
|
1900
|
+
|
|
1901
|
+
def valuation(self, p):
|
|
1902
|
+
"""
|
|
1903
|
+
The largest power `r` such that `m` is in the ideal generated by `p^r` or infinity if there is not a largest such power.
|
|
1904
|
+
However it is an error to take the valuation with respect to a unit.
|
|
1905
|
+
|
|
1906
|
+
.. NOTE::
|
|
1907
|
+
|
|
1908
|
+
This is not a valuation in the mathematical sense. As shown with the examples below.
|
|
1909
|
+
|
|
1910
|
+
EXAMPLES:
|
|
1911
|
+
|
|
1912
|
+
This example shows that ``(a*b).valuation(n)`` is not always the same as ``a.valuation(n) + b.valuation(n)``
|
|
1913
|
+
|
|
1914
|
+
::
|
|
1915
|
+
|
|
1916
|
+
sage: R = ZZ.quo(9)
|
|
1917
|
+
sage: a = R(3)
|
|
1918
|
+
sage: b = R(6)
|
|
1919
|
+
sage: a.valuation(3)
|
|
1920
|
+
1
|
|
1921
|
+
sage: a.valuation(3) + b.valuation(3)
|
|
1922
|
+
2
|
|
1923
|
+
sage: (a*b).valuation(3)
|
|
1924
|
+
+Infinity
|
|
1925
|
+
|
|
1926
|
+
The valuation with respect to a unit is an error
|
|
1927
|
+
|
|
1928
|
+
::
|
|
1929
|
+
|
|
1930
|
+
sage: a.valuation(4)
|
|
1931
|
+
Traceback (most recent call last):
|
|
1932
|
+
...
|
|
1933
|
+
ValueError: Valuation with respect to a unit is not defined.
|
|
1934
|
+
|
|
1935
|
+
TESTS::
|
|
1936
|
+
|
|
1937
|
+
sage: R = ZZ.quo(12)
|
|
1938
|
+
sage: a = R(2)
|
|
1939
|
+
sage: b = R(4)
|
|
1940
|
+
sage: a.valuation(2)
|
|
1941
|
+
1
|
|
1942
|
+
sage: b.valuation(2)
|
|
1943
|
+
+Infinity
|
|
1944
|
+
sage: ZZ.quo(1024)(16).valuation(4)
|
|
1945
|
+
2
|
|
1946
|
+
"""
|
|
1947
|
+
p=self._modulus.sageInteger.gcd(p)
|
|
1948
|
+
if p==1:
|
|
1949
|
+
raise ValueError("Valuation with respect to a unit is not defined.")
|
|
1950
|
+
r = 0
|
|
1951
|
+
power = p
|
|
1952
|
+
while not (self % power): # self % power == 0
|
|
1953
|
+
r += 1
|
|
1954
|
+
power *= p
|
|
1955
|
+
if not power.divides(self._modulus.sageInteger):
|
|
1956
|
+
from sage.rings.infinity import infinity
|
|
1957
|
+
return infinity
|
|
1958
|
+
return r
|
|
1959
|
+
|
|
1960
|
+
cpdef _floordiv_(self, right):
|
|
1961
|
+
"""
|
|
1962
|
+
Exact division for prime moduli, for compatibility with other fields.
|
|
1963
|
+
|
|
1964
|
+
EXAMPLES::
|
|
1965
|
+
|
|
1966
|
+
sage: GF(7)(3) // 5
|
|
1967
|
+
2
|
|
1968
|
+
"""
|
|
1969
|
+
return self._mul_(~right)
|
|
1970
|
+
|
|
1971
|
+
def _repr_(self):
|
|
1972
|
+
return str(self.lift())
|
|
1973
|
+
|
|
1974
|
+
def _latex_(self):
|
|
1975
|
+
return str(self)
|
|
1976
|
+
|
|
1977
|
+
def _integer_(self, ZZ=None):
|
|
1978
|
+
return self.lift()
|
|
1979
|
+
|
|
1980
|
+
def _rational_(self):
|
|
1981
|
+
return rational.Rational(self.lift())
|
|
1982
|
+
|
|
1983
|
+
def _vector_(self):
|
|
1984
|
+
"""
|
|
1985
|
+
Return ``self`` as a vector of its parent viewed as a one-dimensional
|
|
1986
|
+
vector space.
|
|
1987
|
+
|
|
1988
|
+
This is to support prime finite fields, which are implemented as
|
|
1989
|
+
`IntegerMod` ring.
|
|
1990
|
+
|
|
1991
|
+
EXAMPLES::
|
|
1992
|
+
|
|
1993
|
+
sage: F.<a> = GF(13)
|
|
1994
|
+
sage: V = F.vector_space(map=False) # needs sage.modules
|
|
1995
|
+
sage: V(a) # needs sage.modules
|
|
1996
|
+
(1)
|
|
1997
|
+
"""
|
|
1998
|
+
return self.parent().vector_space(map=False)([self])
|
|
1999
|
+
|
|
2000
|
+
|
|
2001
|
+
######################################################################
|
|
2002
|
+
# class IntegerMod_gmp
|
|
2003
|
+
######################################################################
|
|
2004
|
+
|
|
2005
|
+
|
|
2006
|
+
cdef class IntegerMod_gmp(IntegerMod_abstract):
|
|
2007
|
+
r"""
|
|
2008
|
+
Elements of `\ZZ/n\ZZ` for n not small enough
|
|
2009
|
+
to be operated on in word size.
|
|
2010
|
+
|
|
2011
|
+
AUTHORS:
|
|
2012
|
+
|
|
2013
|
+
- Robert Bradshaw (2006-08-24)
|
|
2014
|
+
"""
|
|
2015
|
+
|
|
2016
|
+
def __cinit__(self):
|
|
2017
|
+
mpz_init(self.value)
|
|
2018
|
+
|
|
2019
|
+
cdef IntegerMod_gmp _new_c(self):
|
|
2020
|
+
cdef IntegerMod_gmp x
|
|
2021
|
+
x = IntegerMod_gmp.__new__(IntegerMod_gmp)
|
|
2022
|
+
x._modulus = self._modulus
|
|
2023
|
+
x._parent = self._parent
|
|
2024
|
+
return x
|
|
2025
|
+
|
|
2026
|
+
def __dealloc__(self):
|
|
2027
|
+
mpz_clear(self.value)
|
|
2028
|
+
|
|
2029
|
+
cdef void set_from_mpz(self, mpz_t value) noexcept:
|
|
2030
|
+
cdef sage.rings.integer.Integer modulus
|
|
2031
|
+
modulus = self._modulus.sageInteger
|
|
2032
|
+
mpz_mod(self.value, value, modulus.value)
|
|
2033
|
+
|
|
2034
|
+
cdef void set_from_long(self, long value) noexcept:
|
|
2035
|
+
r"""
|
|
2036
|
+
EXAMPLES::
|
|
2037
|
+
|
|
2038
|
+
sage: p = next_prime(2^32) # needs sage.libs.pari
|
|
2039
|
+
sage: GF(p)(int(p + 1)) # needs sage.libs.pari sage.rings.finite_rings
|
|
2040
|
+
1
|
|
2041
|
+
"""
|
|
2042
|
+
mpz_set_si(self.value, value)
|
|
2043
|
+
mpz_mod(self.value, self.value, self._modulus.sageInteger.value)
|
|
2044
|
+
|
|
2045
|
+
cdef void set_from_ulong_fast(self, unsigned long value) noexcept:
|
|
2046
|
+
mpz_set_ui(self.value, value)
|
|
2047
|
+
|
|
2048
|
+
def __lshift__(IntegerMod_gmp self, k):
|
|
2049
|
+
r"""
|
|
2050
|
+
Perform a left shift by ``k`` bits.
|
|
2051
|
+
|
|
2052
|
+
For details, see :meth:`shift`.
|
|
2053
|
+
|
|
2054
|
+
EXAMPLES::
|
|
2055
|
+
|
|
2056
|
+
sage: e = Mod(19, 10^10)
|
|
2057
|
+
sage: e << 102
|
|
2058
|
+
9443608576
|
|
2059
|
+
sage: e << (2^200)
|
|
2060
|
+
Traceback (most recent call last):
|
|
2061
|
+
...
|
|
2062
|
+
OverflowError: Python int too large to convert to C long
|
|
2063
|
+
"""
|
|
2064
|
+
return self.shift(k)
|
|
2065
|
+
|
|
2066
|
+
def __rshift__(IntegerMod_gmp self, k):
|
|
2067
|
+
r"""
|
|
2068
|
+
Perform a right shift by ``k`` bits.
|
|
2069
|
+
|
|
2070
|
+
For details, see :meth:`shift`.
|
|
2071
|
+
|
|
2072
|
+
EXAMPLES::
|
|
2073
|
+
|
|
2074
|
+
sage: e = Mod(19, 10^10)
|
|
2075
|
+
sage: e >> 1
|
|
2076
|
+
9
|
|
2077
|
+
sage: e << (2^200)
|
|
2078
|
+
Traceback (most recent call last):
|
|
2079
|
+
...
|
|
2080
|
+
OverflowError: Python int too large to convert to C long
|
|
2081
|
+
"""
|
|
2082
|
+
return self.shift(-k)
|
|
2083
|
+
|
|
2084
|
+
cdef shift(IntegerMod_gmp self, long k):
|
|
2085
|
+
r"""
|
|
2086
|
+
Perform a bit-shift specified by ``k`` on ``self``.
|
|
2087
|
+
|
|
2088
|
+
Suppose that ``self`` represents an integer `x` modulo `n`. If `k` is
|
|
2089
|
+
`k = 0`, returns `x`. If `k > 0`, shifts `x` to the left, that is,
|
|
2090
|
+
multiplies `x` by `2^k` and then returns the representative in the
|
|
2091
|
+
range `[0,n)`. If `k < 0`, shifts `x` to the right, that is, returns
|
|
2092
|
+
the integral part of `x` divided by `2^k`.
|
|
2093
|
+
|
|
2094
|
+
Note that, in any case, ``self`` remains unchanged.
|
|
2095
|
+
|
|
2096
|
+
INPUT:
|
|
2097
|
+
|
|
2098
|
+
- ``k`` -- integer of type ``long``
|
|
2099
|
+
|
|
2100
|
+
OUTPUT: result of type ``IntegerMod_gmp``
|
|
2101
|
+
|
|
2102
|
+
EXAMPLES::
|
|
2103
|
+
|
|
2104
|
+
sage: e = Mod(19, 10^10)
|
|
2105
|
+
sage: e << 102
|
|
2106
|
+
9443608576
|
|
2107
|
+
sage: e >> 1
|
|
2108
|
+
9
|
|
2109
|
+
sage: e >> 4
|
|
2110
|
+
1
|
|
2111
|
+
"""
|
|
2112
|
+
cdef IntegerMod_gmp x
|
|
2113
|
+
if k == 0:
|
|
2114
|
+
return self
|
|
2115
|
+
else:
|
|
2116
|
+
x = self._new_c()
|
|
2117
|
+
if k > 0:
|
|
2118
|
+
mpz_mul_2exp(x.value, self.value, k)
|
|
2119
|
+
mpz_fdiv_r(x.value, x.value, self._modulus.sageInteger.value)
|
|
2120
|
+
else:
|
|
2121
|
+
mpz_fdiv_q_2exp(x.value, self.value, -k)
|
|
2122
|
+
return x
|
|
2123
|
+
|
|
2124
|
+
cpdef _richcmp_(left, right, int op):
|
|
2125
|
+
"""
|
|
2126
|
+
EXAMPLES::
|
|
2127
|
+
|
|
2128
|
+
sage: mod(5,13^20) == mod(5,13^20)
|
|
2129
|
+
True
|
|
2130
|
+
sage: mod(5,13^20) == mod(-5,13^20)
|
|
2131
|
+
False
|
|
2132
|
+
sage: mod(5,13^20) == mod(-5,13)
|
|
2133
|
+
False
|
|
2134
|
+
"""
|
|
2135
|
+
cdef int i
|
|
2136
|
+
i = mpz_cmp((<IntegerMod_gmp>left).value, (<IntegerMod_gmp>right).value)
|
|
2137
|
+
return rich_to_bool_sgn(op, i)
|
|
2138
|
+
|
|
2139
|
+
cpdef bint is_one(IntegerMod_gmp self) noexcept:
|
|
2140
|
+
"""
|
|
2141
|
+
Return ``True`` if this is `1`, otherwise ``False``.
|
|
2142
|
+
|
|
2143
|
+
EXAMPLES::
|
|
2144
|
+
|
|
2145
|
+
sage: mod(1,5^23).is_one()
|
|
2146
|
+
True
|
|
2147
|
+
sage: mod(0,5^23).is_one()
|
|
2148
|
+
False
|
|
2149
|
+
"""
|
|
2150
|
+
return mpz_cmp_si(self.value, 1) == 0
|
|
2151
|
+
|
|
2152
|
+
def __bool__(IntegerMod_gmp self):
|
|
2153
|
+
"""
|
|
2154
|
+
Return ``True`` if this is not `0`, otherwise ``False``.
|
|
2155
|
+
|
|
2156
|
+
EXAMPLES::
|
|
2157
|
+
|
|
2158
|
+
sage: mod(13,5^23).is_zero()
|
|
2159
|
+
False
|
|
2160
|
+
sage: (mod(25,5^23)^23).is_zero()
|
|
2161
|
+
True
|
|
2162
|
+
"""
|
|
2163
|
+
return mpz_cmp_si(self.value, 0) != 0
|
|
2164
|
+
|
|
2165
|
+
cpdef bint is_unit(self) noexcept:
|
|
2166
|
+
"""
|
|
2167
|
+
Return ``True`` iff this element is a unit.
|
|
2168
|
+
|
|
2169
|
+
EXAMPLES::
|
|
2170
|
+
|
|
2171
|
+
sage: mod(13, 5^23).is_unit()
|
|
2172
|
+
True
|
|
2173
|
+
sage: mod(25, 5^23).is_unit()
|
|
2174
|
+
False
|
|
2175
|
+
"""
|
|
2176
|
+
return self.lift().gcd(self.modulus()) == 1
|
|
2177
|
+
|
|
2178
|
+
def _crt(IntegerMod_gmp self, IntegerMod_gmp other):
|
|
2179
|
+
cdef IntegerMod_gmp lift, x
|
|
2180
|
+
cdef sage.rings.integer.Integer modulus, other_modulus
|
|
2181
|
+
|
|
2182
|
+
modulus = self._modulus.sageInteger
|
|
2183
|
+
other_modulus = other._modulus.sageInteger
|
|
2184
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
2185
|
+
lift = IntegerMod_gmp(IntegerModRing(modulus*other_modulus))
|
|
2186
|
+
try:
|
|
2187
|
+
if mpz_cmp(self.value, other.value) > 0:
|
|
2188
|
+
x = (other - IntegerMod_gmp(other._parent, self.lift())) / IntegerMod_gmp(other._parent, modulus)
|
|
2189
|
+
mpz_mul(lift.value, x.value, modulus.value)
|
|
2190
|
+
mpz_add(lift.value, lift.value, self.value)
|
|
2191
|
+
else:
|
|
2192
|
+
x = (self - IntegerMod_gmp(self._parent, other.lift())) / IntegerMod_gmp(self._parent, other_modulus)
|
|
2193
|
+
mpz_mul(lift.value, x.value, other_modulus.value)
|
|
2194
|
+
mpz_add(lift.value, lift.value, other.value)
|
|
2195
|
+
return lift
|
|
2196
|
+
except ZeroDivisionError:
|
|
2197
|
+
raise ZeroDivisionError("moduli must be coprime")
|
|
2198
|
+
|
|
2199
|
+
def __copy__(IntegerMod_gmp self):
|
|
2200
|
+
"""
|
|
2201
|
+
EXAMPLES::
|
|
2202
|
+
|
|
2203
|
+
sage: R = Integers(10^10)
|
|
2204
|
+
sage: R7 = R(7)
|
|
2205
|
+
sage: copy(R7) is R7
|
|
2206
|
+
True
|
|
2207
|
+
"""
|
|
2208
|
+
# immutable
|
|
2209
|
+
return self
|
|
2210
|
+
|
|
2211
|
+
def __deepcopy__(IntegerMod_gmp self, memo):
|
|
2212
|
+
"""
|
|
2213
|
+
EXAMPLES::
|
|
2214
|
+
|
|
2215
|
+
sage: R = Integers(10^10)
|
|
2216
|
+
sage: R7 = R(7)
|
|
2217
|
+
sage: deepcopy(R7) is R7
|
|
2218
|
+
True
|
|
2219
|
+
"""
|
|
2220
|
+
# immutable
|
|
2221
|
+
return self
|
|
2222
|
+
|
|
2223
|
+
cpdef _add_(self, right):
|
|
2224
|
+
"""
|
|
2225
|
+
EXAMPLES::
|
|
2226
|
+
|
|
2227
|
+
sage: R = Integers(10^10)
|
|
2228
|
+
sage: R(7) + R(8)
|
|
2229
|
+
15
|
|
2230
|
+
"""
|
|
2231
|
+
cdef IntegerMod_gmp x
|
|
2232
|
+
x = self._new_c()
|
|
2233
|
+
mpz_add(x.value, self.value, (<IntegerMod_gmp>right).value)
|
|
2234
|
+
if mpz_cmp(x.value, self._modulus.sageInteger.value) >= 0:
|
|
2235
|
+
mpz_sub(x.value, x.value, self._modulus.sageInteger.value)
|
|
2236
|
+
return x
|
|
2237
|
+
|
|
2238
|
+
cpdef _sub_(self, right):
|
|
2239
|
+
"""
|
|
2240
|
+
EXAMPLES::
|
|
2241
|
+
|
|
2242
|
+
sage: R = Integers(10^10)
|
|
2243
|
+
sage: R(7) - R(8)
|
|
2244
|
+
9999999999
|
|
2245
|
+
"""
|
|
2246
|
+
cdef IntegerMod_gmp x
|
|
2247
|
+
x = self._new_c()
|
|
2248
|
+
mpz_sub(x.value, self.value, (<IntegerMod_gmp>right).value)
|
|
2249
|
+
if mpz_sgn(x.value) == -1:
|
|
2250
|
+
mpz_add(x.value, x.value, self._modulus.sageInteger.value)
|
|
2251
|
+
return x
|
|
2252
|
+
|
|
2253
|
+
cpdef _neg_(self):
|
|
2254
|
+
"""
|
|
2255
|
+
EXAMPLES::
|
|
2256
|
+
|
|
2257
|
+
sage: -mod(5,10^10)
|
|
2258
|
+
9999999995
|
|
2259
|
+
sage: -mod(0,10^10)
|
|
2260
|
+
0
|
|
2261
|
+
"""
|
|
2262
|
+
if mpz_cmp_si(self.value, 0) == 0:
|
|
2263
|
+
return self
|
|
2264
|
+
cdef IntegerMod_gmp x
|
|
2265
|
+
x = self._new_c()
|
|
2266
|
+
mpz_sub(x.value, self._modulus.sageInteger.value, self.value)
|
|
2267
|
+
return x
|
|
2268
|
+
|
|
2269
|
+
cpdef _mul_(self, right):
|
|
2270
|
+
"""
|
|
2271
|
+
EXAMPLES::
|
|
2272
|
+
|
|
2273
|
+
sage: R = Integers(10^11)
|
|
2274
|
+
sage: R(700000) * R(800000)
|
|
2275
|
+
60000000000
|
|
2276
|
+
"""
|
|
2277
|
+
cdef IntegerMod_gmp x
|
|
2278
|
+
x = self._new_c()
|
|
2279
|
+
mpz_mul(x.value, self.value, (<IntegerMod_gmp>right).value)
|
|
2280
|
+
mpz_fdiv_r(x.value, x.value, self._modulus.sageInteger.value)
|
|
2281
|
+
return x
|
|
2282
|
+
|
|
2283
|
+
cpdef _div_(self, right):
|
|
2284
|
+
"""
|
|
2285
|
+
EXAMPLES::
|
|
2286
|
+
|
|
2287
|
+
sage: R = Integers(10^11)
|
|
2288
|
+
sage: R(3) / R(7)
|
|
2289
|
+
71428571429
|
|
2290
|
+
"""
|
|
2291
|
+
return self._mul_(~right)
|
|
2292
|
+
|
|
2293
|
+
def __int__(self):
|
|
2294
|
+
return int(self.lift())
|
|
2295
|
+
|
|
2296
|
+
def __index__(self):
|
|
2297
|
+
"""
|
|
2298
|
+
Needed so integers modulo `n` can be used as list indices.
|
|
2299
|
+
|
|
2300
|
+
EXAMPLES::
|
|
2301
|
+
|
|
2302
|
+
sage: v = [1,2,3,4,5]
|
|
2303
|
+
sage: v[Mod(3,10^20)]
|
|
2304
|
+
4
|
|
2305
|
+
"""
|
|
2306
|
+
return int(self.lift())
|
|
2307
|
+
|
|
2308
|
+
def __pow__(IntegerMod_gmp self, exp, m): # NOTE: m ignored, always use modulus of parent ring
|
|
2309
|
+
"""
|
|
2310
|
+
EXAMPLES::
|
|
2311
|
+
|
|
2312
|
+
sage: R = Integers(10^10)
|
|
2313
|
+
sage: R(2)^1000
|
|
2314
|
+
5668069376
|
|
2315
|
+
sage: p = next_prime(11^10) # needs sage.libs.pari
|
|
2316
|
+
sage: R = Integers(p) # needs sage.libs.pari
|
|
2317
|
+
sage: R(9876)^(p-1) # needs sage.libs.pari
|
|
2318
|
+
1
|
|
2319
|
+
sage: mod(3, 10^100)^-2
|
|
2320
|
+
8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888889
|
|
2321
|
+
sage: mod(2, 10^100)^-2
|
|
2322
|
+
Traceback (most recent call last):
|
|
2323
|
+
...
|
|
2324
|
+
ZeroDivisionError: Inverse does not exist.
|
|
2325
|
+
|
|
2326
|
+
TESTS:
|
|
2327
|
+
|
|
2328
|
+
We define ``0^0`` to be unity, :issue:`13894`::
|
|
2329
|
+
|
|
2330
|
+
sage: p = next_prime(11^10) # needs sage.libs.pari
|
|
2331
|
+
sage: R = Integers(p) # needs sage.libs.pari
|
|
2332
|
+
sage: R(0)^0
|
|
2333
|
+
1
|
|
2334
|
+
|
|
2335
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
2336
|
+
|
|
2337
|
+
sage: type(R(0)^0) == type(R(0))
|
|
2338
|
+
True
|
|
2339
|
+
|
|
2340
|
+
When the modulus is ``1``, the only element in the ring is
|
|
2341
|
+
``0`` (and it is equivalent to ``1``), so we return that
|
|
2342
|
+
instead::
|
|
2343
|
+
|
|
2344
|
+
sage: from sage.rings.finite_rings.integer_mod \
|
|
2345
|
+
....: import IntegerMod_gmp
|
|
2346
|
+
sage: zero = IntegerMod_gmp(Integers(1),0)
|
|
2347
|
+
sage: type(zero)
|
|
2348
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
2349
|
+
sage: zero^0
|
|
2350
|
+
0
|
|
2351
|
+
"""
|
|
2352
|
+
cdef IntegerMod_gmp x = self._new_c()
|
|
2353
|
+
sig_on()
|
|
2354
|
+
try:
|
|
2355
|
+
mpz_pow_helper(x.value, self.value, exp, self._modulus.sageInteger.value)
|
|
2356
|
+
finally:
|
|
2357
|
+
sig_off()
|
|
2358
|
+
return x
|
|
2359
|
+
|
|
2360
|
+
def __invert__(IntegerMod_gmp self):
|
|
2361
|
+
"""
|
|
2362
|
+
Return the multiplicative inverse of ``self``.
|
|
2363
|
+
|
|
2364
|
+
EXAMPLES::
|
|
2365
|
+
|
|
2366
|
+
sage: a = mod(3,10^100); type(a)
|
|
2367
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
2368
|
+
sage: ~a
|
|
2369
|
+
6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667
|
|
2370
|
+
sage: ~mod(2,10^100)
|
|
2371
|
+
Traceback (most recent call last):
|
|
2372
|
+
...
|
|
2373
|
+
ZeroDivisionError: inverse of Mod(2, 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) does not exist
|
|
2374
|
+
"""
|
|
2375
|
+
if self.is_zero():
|
|
2376
|
+
raise ZeroDivisionError(f"inverse of Mod(0, {self._modulus.sageInteger}) does not exist")
|
|
2377
|
+
|
|
2378
|
+
cdef IntegerMod_gmp x
|
|
2379
|
+
x = self._new_c()
|
|
2380
|
+
if not mpz_invert(x.value, self.value, self._modulus.sageInteger.value):
|
|
2381
|
+
raise ZeroDivisionError(f"inverse of Mod({self}, {self._modulus.sageInteger}) does not exist")
|
|
2382
|
+
return x
|
|
2383
|
+
|
|
2384
|
+
def lift(IntegerMod_gmp self):
|
|
2385
|
+
"""
|
|
2386
|
+
Lift an integer modulo `n` to the integers.
|
|
2387
|
+
|
|
2388
|
+
EXAMPLES::
|
|
2389
|
+
|
|
2390
|
+
sage: a = Mod(8943, 2^70); type(a)
|
|
2391
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
2392
|
+
sage: lift(a)
|
|
2393
|
+
8943
|
|
2394
|
+
sage: a.lift()
|
|
2395
|
+
8943
|
|
2396
|
+
"""
|
|
2397
|
+
cdef sage.rings.integer.Integer z
|
|
2398
|
+
z = sage.rings.integer.Integer()
|
|
2399
|
+
z.set_from_mpz(self.value)
|
|
2400
|
+
return z
|
|
2401
|
+
|
|
2402
|
+
def __float__(self):
|
|
2403
|
+
return float(self.lift())
|
|
2404
|
+
|
|
2405
|
+
def __hash__(self):
|
|
2406
|
+
"""
|
|
2407
|
+
EXAMPLES::
|
|
2408
|
+
|
|
2409
|
+
sage: a = Mod(8943, 2^100)
|
|
2410
|
+
sage: hash(a)
|
|
2411
|
+
8943
|
|
2412
|
+
"""
|
|
2413
|
+
return mpz_pythonhash(self.value)
|
|
2414
|
+
|
|
2415
|
+
@coerce_binop
|
|
2416
|
+
def gcd(self, IntegerMod_gmp other):
|
|
2417
|
+
r"""
|
|
2418
|
+
Greatest common divisor.
|
|
2419
|
+
|
|
2420
|
+
Returns the "smallest" generator in `\ZZ / N\ZZ` of the ideal
|
|
2421
|
+
generated by ``self`` and ``other``.
|
|
2422
|
+
|
|
2423
|
+
INPUT:
|
|
2424
|
+
|
|
2425
|
+
- ``other`` -- an element of the same ring as this one
|
|
2426
|
+
|
|
2427
|
+
EXAMPLES::
|
|
2428
|
+
|
|
2429
|
+
sage: mod(2^3*3^2*5, 3^3*2^2*17^8).gcd(mod(2^4*3*17, 3^3*2^2*17^8))
|
|
2430
|
+
12
|
|
2431
|
+
sage: mod(0,17^8).gcd(mod(0,17^8))
|
|
2432
|
+
0
|
|
2433
|
+
"""
|
|
2434
|
+
cdef IntegerMod_gmp ans = self._new_c()
|
|
2435
|
+
sig_on()
|
|
2436
|
+
mpz_gcd(ans.value, self.value, self._modulus.sageInteger.value)
|
|
2437
|
+
mpz_gcd(ans.value, ans.value, other.value)
|
|
2438
|
+
sig_off()
|
|
2439
|
+
if mpz_cmp(ans.value, self._modulus.sageInteger.value) == 0:
|
|
2440
|
+
# self = other = 0
|
|
2441
|
+
mpz_set_ui(ans.value, 0)
|
|
2442
|
+
return ans
|
|
2443
|
+
|
|
2444
|
+
######################################################################
|
|
2445
|
+
# class IntegerMod_int
|
|
2446
|
+
######################################################################
|
|
2447
|
+
|
|
2448
|
+
|
|
2449
|
+
cdef class IntegerMod_int(IntegerMod_abstract):
|
|
2450
|
+
r"""
|
|
2451
|
+
Elements of `\ZZ/n\ZZ` for n small enough to
|
|
2452
|
+
be operated on in 32 bits
|
|
2453
|
+
|
|
2454
|
+
AUTHORS:
|
|
2455
|
+
|
|
2456
|
+
- Robert Bradshaw (2006-08-24)
|
|
2457
|
+
|
|
2458
|
+
EXAMPLES::
|
|
2459
|
+
|
|
2460
|
+
sage: a = Mod(10,30); a
|
|
2461
|
+
10
|
|
2462
|
+
sage: loads(a.dumps()) == a
|
|
2463
|
+
True
|
|
2464
|
+
"""
|
|
2465
|
+
|
|
2466
|
+
cdef IntegerMod_int _new_c(self, int_fast32_t value):
|
|
2467
|
+
if self._modulus.table is not None:
|
|
2468
|
+
return self._modulus.table[value]
|
|
2469
|
+
cdef IntegerMod_int x = IntegerMod_int.__new__(IntegerMod_int)
|
|
2470
|
+
x._parent = self._parent
|
|
2471
|
+
x._modulus = self._modulus
|
|
2472
|
+
x.ivalue = value
|
|
2473
|
+
return x
|
|
2474
|
+
|
|
2475
|
+
cdef void set_from_mpz(self, mpz_t value) noexcept:
|
|
2476
|
+
self.ivalue = mpz_fdiv_ui(value, self._modulus.int32)
|
|
2477
|
+
|
|
2478
|
+
cdef void set_from_long(self, long value) noexcept:
|
|
2479
|
+
self.ivalue = value % self._modulus.int32
|
|
2480
|
+
if self.ivalue < 0:
|
|
2481
|
+
self.ivalue += self._modulus.int32
|
|
2482
|
+
|
|
2483
|
+
cdef void set_from_ulong_fast(self, unsigned long value) noexcept:
|
|
2484
|
+
self.ivalue = value
|
|
2485
|
+
|
|
2486
|
+
cdef void set_from_int(IntegerMod_int self, int_fast32_t ivalue) noexcept:
|
|
2487
|
+
if ivalue < 0:
|
|
2488
|
+
self.ivalue = self._modulus.int32 + (ivalue % self._modulus.int32)
|
|
2489
|
+
elif ivalue >= self._modulus.int32:
|
|
2490
|
+
self.ivalue = ivalue % self._modulus.int32
|
|
2491
|
+
else:
|
|
2492
|
+
self.ivalue = ivalue
|
|
2493
|
+
|
|
2494
|
+
cdef int_fast32_t get_int_value(IntegerMod_int self) noexcept:
|
|
2495
|
+
return self.ivalue
|
|
2496
|
+
|
|
2497
|
+
cpdef _richcmp_(self, right, int op):
|
|
2498
|
+
"""
|
|
2499
|
+
EXAMPLES::
|
|
2500
|
+
|
|
2501
|
+
sage: mod(5,13) == mod(-8,13)
|
|
2502
|
+
True
|
|
2503
|
+
sage: mod(5,13) == mod(8,13)
|
|
2504
|
+
False
|
|
2505
|
+
sage: mod(5,13) == mod(5,24)
|
|
2506
|
+
False
|
|
2507
|
+
sage: mod(0, 13) == 0
|
|
2508
|
+
True
|
|
2509
|
+
sage: mod(0, 13) == int(0)
|
|
2510
|
+
True
|
|
2511
|
+
"""
|
|
2512
|
+
if self.ivalue == (<IntegerMod_int>right).ivalue:
|
|
2513
|
+
return rich_to_bool(op, 0)
|
|
2514
|
+
elif self.ivalue < (<IntegerMod_int>right).ivalue:
|
|
2515
|
+
return rich_to_bool(op, -1)
|
|
2516
|
+
else:
|
|
2517
|
+
return rich_to_bool(op, 1)
|
|
2518
|
+
|
|
2519
|
+
cpdef bint is_one(IntegerMod_int self) noexcept:
|
|
2520
|
+
"""
|
|
2521
|
+
Return ``True`` if this is `1`, otherwise ``False``.
|
|
2522
|
+
|
|
2523
|
+
EXAMPLES::
|
|
2524
|
+
|
|
2525
|
+
sage: mod(6,5).is_one()
|
|
2526
|
+
True
|
|
2527
|
+
sage: mod(0,5).is_one()
|
|
2528
|
+
False
|
|
2529
|
+
sage: mod(1, 1).is_one()
|
|
2530
|
+
True
|
|
2531
|
+
sage: Zmod(1).one().is_one()
|
|
2532
|
+
True
|
|
2533
|
+
"""
|
|
2534
|
+
return self.ivalue == 1 or self._modulus.int32 == 1
|
|
2535
|
+
|
|
2536
|
+
def __bool__(IntegerMod_int self):
|
|
2537
|
+
"""
|
|
2538
|
+
Return ``True`` if this is not `0`, otherwise ``False``.
|
|
2539
|
+
|
|
2540
|
+
EXAMPLES::
|
|
2541
|
+
|
|
2542
|
+
sage: mod(13,5).is_zero()
|
|
2543
|
+
False
|
|
2544
|
+
sage: mod(25,5).is_zero()
|
|
2545
|
+
True
|
|
2546
|
+
"""
|
|
2547
|
+
return self.ivalue != 0
|
|
2548
|
+
|
|
2549
|
+
cpdef bint is_unit(IntegerMod_int self) noexcept:
|
|
2550
|
+
"""
|
|
2551
|
+
Return ``True`` iff this element is a unit
|
|
2552
|
+
|
|
2553
|
+
EXAMPLES::
|
|
2554
|
+
|
|
2555
|
+
sage: a=Mod(23,100)
|
|
2556
|
+
sage: a.is_unit()
|
|
2557
|
+
True
|
|
2558
|
+
sage: a=Mod(24,100)
|
|
2559
|
+
sage: a.is_unit()
|
|
2560
|
+
False
|
|
2561
|
+
"""
|
|
2562
|
+
return gcd_int(self.ivalue, self._modulus.int32) == 1
|
|
2563
|
+
|
|
2564
|
+
def _crt(IntegerMod_int self, IntegerMod_int other):
|
|
2565
|
+
"""
|
|
2566
|
+
Use the Chinese Remainder Theorem to find an element of the
|
|
2567
|
+
integers modulo the product of the moduli that reduces to ``self`` and
|
|
2568
|
+
to ``other``. The modulus of ``other`` must be coprime to the modulus
|
|
2569
|
+
of ``self``.
|
|
2570
|
+
|
|
2571
|
+
EXAMPLES::
|
|
2572
|
+
|
|
2573
|
+
sage: a = mod(3,5)
|
|
2574
|
+
sage: b = mod(2,7)
|
|
2575
|
+
sage: a.crt(b)
|
|
2576
|
+
23
|
|
2577
|
+
|
|
2578
|
+
AUTHORS:
|
|
2579
|
+
|
|
2580
|
+
- Robert Bradshaw
|
|
2581
|
+
"""
|
|
2582
|
+
cdef IntegerMod_int lift
|
|
2583
|
+
cdef int_fast32_t x
|
|
2584
|
+
|
|
2585
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
2586
|
+
lift = IntegerMod_int(IntegerModRing(self._modulus.int32 * other._modulus.int32))
|
|
2587
|
+
|
|
2588
|
+
try:
|
|
2589
|
+
x = (other.ivalue - self.ivalue % other._modulus.int32) * mod_inverse_int(self._modulus.int32, other._modulus.int32)
|
|
2590
|
+
lift.set_from_int( x * self._modulus.int32 + self.ivalue )
|
|
2591
|
+
return lift
|
|
2592
|
+
except ZeroDivisionError:
|
|
2593
|
+
raise ZeroDivisionError("moduli must be coprime")
|
|
2594
|
+
|
|
2595
|
+
def __copy__(IntegerMod_int self):
|
|
2596
|
+
"""
|
|
2597
|
+
EXAMPLES::
|
|
2598
|
+
|
|
2599
|
+
sage: R = Integers(10)
|
|
2600
|
+
sage: R7 = R(7)
|
|
2601
|
+
sage: copy(R7) is R7
|
|
2602
|
+
True
|
|
2603
|
+
"""
|
|
2604
|
+
# immutable
|
|
2605
|
+
return self
|
|
2606
|
+
|
|
2607
|
+
def __deepcopy__(IntegerMod_int self, memo):
|
|
2608
|
+
"""
|
|
2609
|
+
EXAMPLES::
|
|
2610
|
+
|
|
2611
|
+
sage: R = Integers(10)
|
|
2612
|
+
sage: R7 = R(7)
|
|
2613
|
+
sage: deepcopy(R7) is R7
|
|
2614
|
+
True
|
|
2615
|
+
"""
|
|
2616
|
+
# immutable
|
|
2617
|
+
return self
|
|
2618
|
+
|
|
2619
|
+
cpdef _add_(self, right):
|
|
2620
|
+
"""
|
|
2621
|
+
EXAMPLES::
|
|
2622
|
+
|
|
2623
|
+
sage: R = Integers(10)
|
|
2624
|
+
sage: R(7) + R(8)
|
|
2625
|
+
5
|
|
2626
|
+
"""
|
|
2627
|
+
cdef int_fast32_t x
|
|
2628
|
+
x = self.ivalue + (<IntegerMod_int>right).ivalue
|
|
2629
|
+
if x >= self._modulus.int32:
|
|
2630
|
+
x = x - self._modulus.int32
|
|
2631
|
+
return self._new_c(x)
|
|
2632
|
+
|
|
2633
|
+
cpdef _sub_(self, right):
|
|
2634
|
+
"""
|
|
2635
|
+
EXAMPLES::
|
|
2636
|
+
|
|
2637
|
+
sage: R = Integers(10)
|
|
2638
|
+
sage: R(7) - R(8)
|
|
2639
|
+
9
|
|
2640
|
+
"""
|
|
2641
|
+
cdef int_fast32_t x
|
|
2642
|
+
x = self.ivalue - (<IntegerMod_int>right).ivalue
|
|
2643
|
+
if x < 0:
|
|
2644
|
+
x = x + self._modulus.int32
|
|
2645
|
+
return self._new_c(x)
|
|
2646
|
+
|
|
2647
|
+
cpdef _neg_(self):
|
|
2648
|
+
"""
|
|
2649
|
+
EXAMPLES::
|
|
2650
|
+
|
|
2651
|
+
sage: -mod(7,10)
|
|
2652
|
+
3
|
|
2653
|
+
sage: -mod(0,10)
|
|
2654
|
+
0
|
|
2655
|
+
"""
|
|
2656
|
+
if self.ivalue == 0:
|
|
2657
|
+
return self
|
|
2658
|
+
return self._new_c(self._modulus.int32 - self.ivalue)
|
|
2659
|
+
|
|
2660
|
+
cpdef _mul_(self, right):
|
|
2661
|
+
"""
|
|
2662
|
+
EXAMPLES::
|
|
2663
|
+
|
|
2664
|
+
sage: R = Integers(10)
|
|
2665
|
+
sage: R(7) * R(8)
|
|
2666
|
+
6
|
|
2667
|
+
"""
|
|
2668
|
+
return self._new_c((self.ivalue * (<IntegerMod_int>right).ivalue) % self._modulus.int32)
|
|
2669
|
+
|
|
2670
|
+
cpdef _div_(self, right):
|
|
2671
|
+
"""
|
|
2672
|
+
EXAMPLES::
|
|
2673
|
+
|
|
2674
|
+
sage: R = Integers(10)
|
|
2675
|
+
sage: R(2)/3
|
|
2676
|
+
4
|
|
2677
|
+
"""
|
|
2678
|
+
if self._modulus.inverses is not None:
|
|
2679
|
+
right_inverse = self._modulus.inverses[(<IntegerMod_int>right).ivalue]
|
|
2680
|
+
if right_inverse is None:
|
|
2681
|
+
raise ZeroDivisionError(f"inverse of Mod({right}, {self._modulus.sageInteger}) does not exist")
|
|
2682
|
+
else:
|
|
2683
|
+
return self._new_c((self.ivalue * (<IntegerMod_int>right_inverse).ivalue) % self._modulus.int32)
|
|
2684
|
+
|
|
2685
|
+
cdef int_fast32_t x
|
|
2686
|
+
x = self.ivalue * mod_inverse_int((<IntegerMod_int>right).ivalue, self._modulus.int32)
|
|
2687
|
+
return self._new_c(x% self._modulus.int32)
|
|
2688
|
+
|
|
2689
|
+
def __int__(IntegerMod_int self):
|
|
2690
|
+
"""
|
|
2691
|
+
TESTS::
|
|
2692
|
+
|
|
2693
|
+
sage: e = Mod(8, 31)
|
|
2694
|
+
sage: int(e)
|
|
2695
|
+
8
|
|
2696
|
+
"""
|
|
2697
|
+
return self.ivalue
|
|
2698
|
+
|
|
2699
|
+
def __index__(self):
|
|
2700
|
+
"""
|
|
2701
|
+
Needed so integers modulo `n` can be used as list indices.
|
|
2702
|
+
|
|
2703
|
+
EXAMPLES::
|
|
2704
|
+
|
|
2705
|
+
sage: v = [1,2,3,4,5]
|
|
2706
|
+
sage: v[Mod(10,7)]
|
|
2707
|
+
4
|
|
2708
|
+
"""
|
|
2709
|
+
return self.ivalue
|
|
2710
|
+
|
|
2711
|
+
def __lshift__(IntegerMod_int self, k):
|
|
2712
|
+
r"""
|
|
2713
|
+
Perform a left shift by ``k`` bits.
|
|
2714
|
+
|
|
2715
|
+
For details, see :meth:`shift`.
|
|
2716
|
+
|
|
2717
|
+
EXAMPLES::
|
|
2718
|
+
|
|
2719
|
+
sage: e = Mod(5, 2^10 - 1)
|
|
2720
|
+
sage: e << 5
|
|
2721
|
+
160
|
|
2722
|
+
sage: e * 2^5
|
|
2723
|
+
160
|
|
2724
|
+
"""
|
|
2725
|
+
return self.shift(int(k))
|
|
2726
|
+
|
|
2727
|
+
def __rshift__(IntegerMod_int self, k):
|
|
2728
|
+
r"""
|
|
2729
|
+
Perform a right shift by ``k`` bits.
|
|
2730
|
+
|
|
2731
|
+
For details, see :meth:`shift`.
|
|
2732
|
+
|
|
2733
|
+
EXAMPLES::
|
|
2734
|
+
|
|
2735
|
+
sage: e = Mod(5, 2^10 - 1)
|
|
2736
|
+
sage: e << 5
|
|
2737
|
+
160
|
|
2738
|
+
sage: e * 2^5
|
|
2739
|
+
160
|
|
2740
|
+
"""
|
|
2741
|
+
return self.shift(-int(k))
|
|
2742
|
+
|
|
2743
|
+
cdef shift(IntegerMod_int self, int k):
|
|
2744
|
+
"""
|
|
2745
|
+
Perform a bit-shift specified by ``k`` on ``self``.
|
|
2746
|
+
|
|
2747
|
+
Suppose that ``self`` represents an integer `x` modulo `n`. If `k` is
|
|
2748
|
+
`k = 0`, returns `x`. If `k > 0`, shifts `x` to the left, that is,
|
|
2749
|
+
multiplies `x` by `2^k` and then returns the representative in the
|
|
2750
|
+
range `[0,n)`. If `k < 0`, shifts `x` to the right, that is, returns
|
|
2751
|
+
the integral part of `x` divided by `2^k`.
|
|
2752
|
+
|
|
2753
|
+
Note that, in any case, ``self`` remains unchanged.
|
|
2754
|
+
|
|
2755
|
+
INPUT:
|
|
2756
|
+
|
|
2757
|
+
- ``k`` -- integer of type ``int``
|
|
2758
|
+
|
|
2759
|
+
OUTPUT: result of type ``IntegerMod_int``
|
|
2760
|
+
|
|
2761
|
+
WARNING:
|
|
2762
|
+
|
|
2763
|
+
For positive ``k``, if ``x << k`` overflows as a 32-bit integer, the
|
|
2764
|
+
result is meaningless.
|
|
2765
|
+
|
|
2766
|
+
EXAMPLES::
|
|
2767
|
+
|
|
2768
|
+
sage: e = Mod(5, 2^10 - 1)
|
|
2769
|
+
sage: e << 5
|
|
2770
|
+
160
|
|
2771
|
+
sage: e * 2^5
|
|
2772
|
+
160
|
|
2773
|
+
sage: e = Mod(8, 2^5 - 1)
|
|
2774
|
+
sage: e >> 3
|
|
2775
|
+
1
|
|
2776
|
+
"""
|
|
2777
|
+
if k == 0:
|
|
2778
|
+
return self
|
|
2779
|
+
elif k > 0:
|
|
2780
|
+
return self._new_c((self.ivalue << k) % self._modulus.int32)
|
|
2781
|
+
else:
|
|
2782
|
+
return self._new_c(self.ivalue >> (-k))
|
|
2783
|
+
|
|
2784
|
+
def __pow__(IntegerMod_int self, exp, m): # NOTE: m ignored, always use modulus of parent ring
|
|
2785
|
+
"""
|
|
2786
|
+
EXAMPLES::
|
|
2787
|
+
|
|
2788
|
+
sage: R = Integers(10)
|
|
2789
|
+
sage: R(2)^10
|
|
2790
|
+
4
|
|
2791
|
+
sage: R = Integers(389)
|
|
2792
|
+
sage: R(7)^388
|
|
2793
|
+
1
|
|
2794
|
+
|
|
2795
|
+
sage: mod(3, 100)^-1
|
|
2796
|
+
67
|
|
2797
|
+
sage: mod(3, 100)^-100000000
|
|
2798
|
+
1
|
|
2799
|
+
|
|
2800
|
+
sage: mod(2, 100)^-1
|
|
2801
|
+
Traceback (most recent call last):
|
|
2802
|
+
...
|
|
2803
|
+
ZeroDivisionError: inverse of Mod(2, 100) does not exist
|
|
2804
|
+
sage: mod(2, 100)^-100000000
|
|
2805
|
+
Traceback (most recent call last):
|
|
2806
|
+
...
|
|
2807
|
+
ZeroDivisionError: Inverse does not exist.
|
|
2808
|
+
|
|
2809
|
+
TESTS:
|
|
2810
|
+
|
|
2811
|
+
We define ``0^0`` to be unity, :issue:`13894`::
|
|
2812
|
+
|
|
2813
|
+
sage: R = Integers(100)
|
|
2814
|
+
sage: R(0)^0
|
|
2815
|
+
1
|
|
2816
|
+
|
|
2817
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
2818
|
+
|
|
2819
|
+
sage: type(R(0)^0) == type(R(0))
|
|
2820
|
+
True
|
|
2821
|
+
|
|
2822
|
+
When the modulus is ``1``, the only element in the ring is
|
|
2823
|
+
``0`` (and it is equivalent to ``1``), so we return that
|
|
2824
|
+
instead::
|
|
2825
|
+
|
|
2826
|
+
sage: R = Integers(1)
|
|
2827
|
+
sage: R(0)^0
|
|
2828
|
+
0
|
|
2829
|
+
"""
|
|
2830
|
+
cdef long long_exp
|
|
2831
|
+
cdef int_fast32_t res
|
|
2832
|
+
cdef mpz_t res_mpz
|
|
2833
|
+
if type(exp) is int and -100000 < PyLong_AsLong(exp) < 100000:
|
|
2834
|
+
long_exp = PyLong_AsLong(exp)
|
|
2835
|
+
elif type(exp) is Integer and mpz_cmpabs_ui((<Integer>exp).value, 100000) == -1:
|
|
2836
|
+
long_exp = mpz_get_si((<Integer>exp).value)
|
|
2837
|
+
else:
|
|
2838
|
+
base = self.lift()
|
|
2839
|
+
sig_on()
|
|
2840
|
+
try:
|
|
2841
|
+
mpz_init(res_mpz)
|
|
2842
|
+
mpz_pow_helper(res_mpz, (<Integer>base).value, exp, self._modulus.sageInteger.value)
|
|
2843
|
+
res = mpz_get_ui(res_mpz)
|
|
2844
|
+
mpz_clear(res_mpz)
|
|
2845
|
+
finally:
|
|
2846
|
+
sig_off()
|
|
2847
|
+
return self._new_c(res)
|
|
2848
|
+
|
|
2849
|
+
if long_exp == 0 and self.ivalue == 0:
|
|
2850
|
+
# Return 0 if the modulus is 1, otherwise return 1.
|
|
2851
|
+
return self._new_c(self._modulus.int32 != 1)
|
|
2852
|
+
cdef bint invert = False
|
|
2853
|
+
if long_exp < 0:
|
|
2854
|
+
invert = True
|
|
2855
|
+
long_exp = -long_exp
|
|
2856
|
+
res = mod_pow_int(self.ivalue, long_exp, self._modulus.int32)
|
|
2857
|
+
if invert:
|
|
2858
|
+
return ~self._new_c(res)
|
|
2859
|
+
else:
|
|
2860
|
+
return self._new_c(res)
|
|
2861
|
+
|
|
2862
|
+
def __invert__(IntegerMod_int self):
|
|
2863
|
+
"""
|
|
2864
|
+
Return the multiplicative inverse of ``self``.
|
|
2865
|
+
|
|
2866
|
+
EXAMPLES::
|
|
2867
|
+
|
|
2868
|
+
sage: ~mod(7,100)
|
|
2869
|
+
43
|
|
2870
|
+
sage: Mod(0,1)^-1
|
|
2871
|
+
0
|
|
2872
|
+
"""
|
|
2873
|
+
if self._modulus.inverses is not None:
|
|
2874
|
+
x = self._modulus.inverses[self.ivalue]
|
|
2875
|
+
if x is None:
|
|
2876
|
+
raise ZeroDivisionError(f"inverse of Mod({self}, {self._modulus.sageInteger}) does not exist")
|
|
2877
|
+
else:
|
|
2878
|
+
return x
|
|
2879
|
+
else:
|
|
2880
|
+
return self._new_c(mod_inverse_int(self.ivalue, self._modulus.int32))
|
|
2881
|
+
|
|
2882
|
+
def lift(IntegerMod_int self):
|
|
2883
|
+
"""
|
|
2884
|
+
Lift an integer modulo `n` to the integers.
|
|
2885
|
+
|
|
2886
|
+
EXAMPLES::
|
|
2887
|
+
|
|
2888
|
+
sage: a = Mod(8943, 2^10); type(a)
|
|
2889
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
|
|
2890
|
+
sage: lift(a)
|
|
2891
|
+
751
|
|
2892
|
+
sage: a.lift()
|
|
2893
|
+
751
|
|
2894
|
+
"""
|
|
2895
|
+
cdef sage.rings.integer.Integer z
|
|
2896
|
+
z = sage.rings.integer.Integer()
|
|
2897
|
+
mpz_set_si(z.value, self.ivalue)
|
|
2898
|
+
return z
|
|
2899
|
+
|
|
2900
|
+
def __float__(IntegerMod_int self):
|
|
2901
|
+
return <double>self.ivalue
|
|
2902
|
+
|
|
2903
|
+
def __hash__(self):
|
|
2904
|
+
"""
|
|
2905
|
+
EXAMPLES::
|
|
2906
|
+
|
|
2907
|
+
sage: a = Mod(89, 2^10)
|
|
2908
|
+
sage: hash(a)
|
|
2909
|
+
89
|
|
2910
|
+
"""
|
|
2911
|
+
return hash(self.ivalue)
|
|
2912
|
+
|
|
2913
|
+
cdef bint is_square_c(self) except -2:
|
|
2914
|
+
cdef int_fast32_t l2, lodd, m2, modd
|
|
2915
|
+
if self.ivalue <= 1:
|
|
2916
|
+
return 1
|
|
2917
|
+
# We first try to rule out self being a square without
|
|
2918
|
+
# factoring the modulus.
|
|
2919
|
+
lift = self.lift()
|
|
2920
|
+
m2, modd = self.modulus().val_unit(2)
|
|
2921
|
+
if m2 == 2:
|
|
2922
|
+
if self.ivalue & 2 == 2: # self.ivalue = 2 or 3 (mod 4)
|
|
2923
|
+
return 0
|
|
2924
|
+
elif m2 > 2:
|
|
2925
|
+
l2, lodd = lift.val_unit(2)
|
|
2926
|
+
if l2 < m2 and (l2 % 2 == 1 or lodd % (1 << min(3, m2 - l2)) != 1):
|
|
2927
|
+
return 0
|
|
2928
|
+
# self is a square modulo 2^m2. We compute the Jacobi symbol
|
|
2929
|
+
# modulo modd. If this is -1, then self is not a square.
|
|
2930
|
+
if jacobi_int(self.ivalue, modd) == -1:
|
|
2931
|
+
return 0
|
|
2932
|
+
# We need to factor the modulus. We do it here instead of
|
|
2933
|
+
# letting PARI do it, so that we can cache the factorisation.
|
|
2934
|
+
return lift.__pari__().Zn_issquare(self._parent.factored_order())
|
|
2935
|
+
|
|
2936
|
+
def sqrt(self, extend=True, all=False):
|
|
2937
|
+
r"""
|
|
2938
|
+
Return square root or square roots of ``self`` modulo `n`.
|
|
2939
|
+
|
|
2940
|
+
INPUT:
|
|
2941
|
+
|
|
2942
|
+
- ``extend`` -- boolean (default: ``True``);
|
|
2943
|
+
if ``True``, return a square root in an extension ring,
|
|
2944
|
+
if necessary. Otherwise, raise a :exc:`ValueError` if the
|
|
2945
|
+
square root is not in the base ring.
|
|
2946
|
+
|
|
2947
|
+
- ``all`` -- boolean (default: ``False``); if
|
|
2948
|
+
``True``, return {all} square roots of self, instead of
|
|
2949
|
+
just one.
|
|
2950
|
+
|
|
2951
|
+
ALGORITHM: Calculates the square roots mod `p` for each of
|
|
2952
|
+
the primes `p` dividing the order of the ring, then lifts
|
|
2953
|
+
them `p`-adically and uses the CRT to find a square root
|
|
2954
|
+
mod `n`.
|
|
2955
|
+
|
|
2956
|
+
See also :meth:`square_root_mod_prime_power` and
|
|
2957
|
+
:meth:`square_root_mod_prime` for more algorithmic details.
|
|
2958
|
+
|
|
2959
|
+
EXAMPLES::
|
|
2960
|
+
|
|
2961
|
+
sage: mod(-1, 17).sqrt()
|
|
2962
|
+
4
|
|
2963
|
+
sage: mod(5, 389).sqrt()
|
|
2964
|
+
86
|
|
2965
|
+
sage: mod(7, 18).sqrt()
|
|
2966
|
+
5
|
|
2967
|
+
|
|
2968
|
+
sage: # needs sage.libs.pari
|
|
2969
|
+
sage: a = mod(14, 5^60).sqrt()
|
|
2970
|
+
sage: a*a
|
|
2971
|
+
14
|
|
2972
|
+
sage: mod(15, 389).sqrt(extend=False)
|
|
2973
|
+
Traceback (most recent call last):
|
|
2974
|
+
...
|
|
2975
|
+
ValueError: self must be a square
|
|
2976
|
+
sage: Mod(1/9, next_prime(2^40)).sqrt()^(-2)
|
|
2977
|
+
9
|
|
2978
|
+
sage: Mod(1/25, next_prime(2^90)).sqrt()^(-2)
|
|
2979
|
+
25
|
|
2980
|
+
|
|
2981
|
+
::
|
|
2982
|
+
|
|
2983
|
+
sage: a = Mod(3,5); a
|
|
2984
|
+
3
|
|
2985
|
+
sage: x = Mod(-1, 360)
|
|
2986
|
+
sage: x.sqrt(extend=False)
|
|
2987
|
+
Traceback (most recent call last):
|
|
2988
|
+
...
|
|
2989
|
+
ValueError: self must be a square
|
|
2990
|
+
sage: y = x.sqrt(); y
|
|
2991
|
+
sqrt359
|
|
2992
|
+
sage: y.parent()
|
|
2993
|
+
Univariate Quotient Polynomial Ring in sqrt359
|
|
2994
|
+
over Ring of integers modulo 360 with modulus x^2 + 1
|
|
2995
|
+
sage: y^2
|
|
2996
|
+
359
|
|
2997
|
+
|
|
2998
|
+
We compute all square roots in several cases::
|
|
2999
|
+
|
|
3000
|
+
sage: R = Integers(5*2^3*3^2); R
|
|
3001
|
+
Ring of integers modulo 360
|
|
3002
|
+
sage: R(40).sqrt(all=True)
|
|
3003
|
+
[20, 160, 200, 340]
|
|
3004
|
+
sage: [x for x in R if x^2 == 40] # Brute force verification
|
|
3005
|
+
[20, 160, 200, 340]
|
|
3006
|
+
sage: R(1).sqrt(all=True)
|
|
3007
|
+
[1, 19, 71, 89, 91, 109, 161, 179, 181, 199, 251, 269, 271, 289, 341, 359]
|
|
3008
|
+
sage: R(0).sqrt(all=True)
|
|
3009
|
+
[0, 60, 120, 180, 240, 300]
|
|
3010
|
+
sage: GF(107)(0).sqrt(all=True)
|
|
3011
|
+
[0]
|
|
3012
|
+
|
|
3013
|
+
::
|
|
3014
|
+
|
|
3015
|
+
sage: # needs sage.libs.pari
|
|
3016
|
+
sage: R = Integers(5*13^3*37); R
|
|
3017
|
+
Ring of integers modulo 406445
|
|
3018
|
+
sage: v = R(-1).sqrt(all=True); v
|
|
3019
|
+
[78853, 111808, 160142, 193097, 213348, 246303, 294637, 327592]
|
|
3020
|
+
sage: [x^2 for x in v]
|
|
3021
|
+
[406444, 406444, 406444, 406444, 406444, 406444, 406444, 406444]
|
|
3022
|
+
sage: v = R(169).sqrt(all=True); min(v), -max(v), len(v)
|
|
3023
|
+
(13, 13, 104)
|
|
3024
|
+
sage: all(x^2 == 169 for x in v)
|
|
3025
|
+
True
|
|
3026
|
+
|
|
3027
|
+
Modulo a power of 2::
|
|
3028
|
+
|
|
3029
|
+
sage: R = Integers(2^7); R
|
|
3030
|
+
Ring of integers modulo 128
|
|
3031
|
+
sage: a = R(17)
|
|
3032
|
+
sage: a.sqrt()
|
|
3033
|
+
23
|
|
3034
|
+
sage: a.sqrt(all=True)
|
|
3035
|
+
[23, 41, 87, 105]
|
|
3036
|
+
sage: [x for x in R if x^2==17]
|
|
3037
|
+
[23, 41, 87, 105]
|
|
3038
|
+
|
|
3039
|
+
TESTS:
|
|
3040
|
+
|
|
3041
|
+
Check for :issue:`30797`::
|
|
3042
|
+
|
|
3043
|
+
sage: GF(103)(-1).sqrt(extend=False, all=True)
|
|
3044
|
+
[]
|
|
3045
|
+
"""
|
|
3046
|
+
cdef int_fast32_t i, n = self._modulus.int32
|
|
3047
|
+
if n > 100:
|
|
3048
|
+
moduli = self._parent.factored_order()
|
|
3049
|
+
# Unless the modulus is tiny, test to see if we're in the really
|
|
3050
|
+
# easy case of n prime, n = 3 mod 4.
|
|
3051
|
+
if n > 100 and n % 4 == 3 and len(moduli) == 1 and moduli[0][1] == 1:
|
|
3052
|
+
if jacobi_int(self.ivalue, self._modulus.int32) == 1:
|
|
3053
|
+
# it's a nonzero square, sqrt(a) = a^(p+1)/4
|
|
3054
|
+
i = mod_pow_int(self.ivalue, (self._modulus.int32+1)/4, n)
|
|
3055
|
+
if i > n / 2:
|
|
3056
|
+
i = n - i
|
|
3057
|
+
if all:
|
|
3058
|
+
return [self._new_c(i), self._new_c(n-i)]
|
|
3059
|
+
else:
|
|
3060
|
+
return self._new_c(i)
|
|
3061
|
+
elif self.ivalue == 0:
|
|
3062
|
+
return [self] if all else self
|
|
3063
|
+
elif not extend:
|
|
3064
|
+
if all:
|
|
3065
|
+
return []
|
|
3066
|
+
raise ValueError("self must be a square")
|
|
3067
|
+
# Now we use a heuristic to guess whether or not it will
|
|
3068
|
+
# be faster to just brute-force search for squares in a c loop...
|
|
3069
|
+
# TODO: more tuning?
|
|
3070
|
+
elif n <= 100 or n / (1 << len(moduli)) < 5000:
|
|
3071
|
+
if all:
|
|
3072
|
+
return [self._new_c(i) for i from 0 <= i < n if (i*i) % n == self.ivalue]
|
|
3073
|
+
else:
|
|
3074
|
+
for i from 0 <= i <= n/2:
|
|
3075
|
+
if (i*i) % n == self.ivalue:
|
|
3076
|
+
return self._new_c(i)
|
|
3077
|
+
if not extend:
|
|
3078
|
+
if all:
|
|
3079
|
+
return []
|
|
3080
|
+
raise ValueError("self must be a square")
|
|
3081
|
+
# Either it failed but extend was True, or the generic algorithm is better
|
|
3082
|
+
return IntegerMod_abstract.sqrt(self, extend=extend, all=all)
|
|
3083
|
+
|
|
3084
|
+
def _balanced_abs(self):
|
|
3085
|
+
r"""
|
|
3086
|
+
This function returns `x` or `-x`, whichever has a
|
|
3087
|
+
positive representative in `-n/2 < x \leq n/2`.
|
|
3088
|
+
"""
|
|
3089
|
+
if self.ivalue > self._modulus.int32 / 2:
|
|
3090
|
+
return -self
|
|
3091
|
+
return self
|
|
3092
|
+
|
|
3093
|
+
@coerce_binop
|
|
3094
|
+
def gcd(self, IntegerMod_int other):
|
|
3095
|
+
r"""
|
|
3096
|
+
Greatest common divisor.
|
|
3097
|
+
|
|
3098
|
+
Returns the "smallest" generator in `\ZZ / N\ZZ` of the ideal
|
|
3099
|
+
generated by ``self`` and ``other``.
|
|
3100
|
+
|
|
3101
|
+
INPUT:
|
|
3102
|
+
|
|
3103
|
+
- ``other`` -- an element of the same ring as this one
|
|
3104
|
+
|
|
3105
|
+
EXAMPLES::
|
|
3106
|
+
|
|
3107
|
+
sage: R = Zmod(60); S = Zmod(72)
|
|
3108
|
+
sage: a = R(40).gcd(S(30)); a
|
|
3109
|
+
2
|
|
3110
|
+
sage: a.parent()
|
|
3111
|
+
Ring of integers modulo 12
|
|
3112
|
+
sage: b = R(17).gcd(60); b
|
|
3113
|
+
1
|
|
3114
|
+
sage: b.parent()
|
|
3115
|
+
Ring of integers modulo 60
|
|
3116
|
+
|
|
3117
|
+
sage: mod(72*5, 3^3*2^2*17^2).gcd(mod(48*17, 3^3*2^2*17^2))
|
|
3118
|
+
12
|
|
3119
|
+
sage: mod(0,1).gcd(mod(0,1))
|
|
3120
|
+
0
|
|
3121
|
+
"""
|
|
3122
|
+
cdef int_fast32_t g = gcd_int(self.ivalue, self._modulus.int32)
|
|
3123
|
+
g = gcd_int(g, other.ivalue)
|
|
3124
|
+
if g == self._modulus.int32: # self = other = 0
|
|
3125
|
+
g = 0
|
|
3126
|
+
return self._new_c(g)
|
|
3127
|
+
|
|
3128
|
+
### End of class
|
|
3129
|
+
|
|
3130
|
+
|
|
3131
|
+
cdef int_fast32_t gcd_int(int_fast32_t a, int_fast32_t b) noexcept:
|
|
3132
|
+
"""
|
|
3133
|
+
Return the gcd of ``a`` and ``b``.
|
|
3134
|
+
|
|
3135
|
+
For use with ``IntegerMod_int``.
|
|
3136
|
+
|
|
3137
|
+
AUTHORS:
|
|
3138
|
+
|
|
3139
|
+
- Robert Bradshaw
|
|
3140
|
+
"""
|
|
3141
|
+
cdef int_fast32_t tmp
|
|
3142
|
+
if a < b:
|
|
3143
|
+
tmp = b
|
|
3144
|
+
b = a
|
|
3145
|
+
a = tmp
|
|
3146
|
+
while b:
|
|
3147
|
+
tmp = b
|
|
3148
|
+
b = a % b
|
|
3149
|
+
a = tmp
|
|
3150
|
+
return a
|
|
3151
|
+
|
|
3152
|
+
|
|
3153
|
+
cdef int_fast32_t mod_inverse_int(int_fast32_t x, int_fast32_t n) except 0:
|
|
3154
|
+
"""
|
|
3155
|
+
Return y such that xy=1 mod n.
|
|
3156
|
+
|
|
3157
|
+
For use in ``IntegerMod_int``.
|
|
3158
|
+
|
|
3159
|
+
AUTHORS:
|
|
3160
|
+
|
|
3161
|
+
- Robert Bradshaw
|
|
3162
|
+
"""
|
|
3163
|
+
cdef int_fast32_t tmp, a, b, last_t, t, next_t, q
|
|
3164
|
+
if n == 1:
|
|
3165
|
+
return 0
|
|
3166
|
+
a = n
|
|
3167
|
+
b = x
|
|
3168
|
+
t = 0
|
|
3169
|
+
next_t = 1
|
|
3170
|
+
while b:
|
|
3171
|
+
# a = s * n + t * x
|
|
3172
|
+
if b == 1:
|
|
3173
|
+
next_t = next_t % n
|
|
3174
|
+
if next_t < 0:
|
|
3175
|
+
next_t = next_t + n
|
|
3176
|
+
return next_t
|
|
3177
|
+
q = a / b
|
|
3178
|
+
tmp = b
|
|
3179
|
+
b = a % b
|
|
3180
|
+
a = tmp
|
|
3181
|
+
last_t = t
|
|
3182
|
+
t = next_t
|
|
3183
|
+
next_t = last_t - q * t
|
|
3184
|
+
raise ZeroDivisionError(f"inverse of Mod({x}, {n}) does not exist")
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
cdef int_fast32_t mod_pow_int(int_fast32_t base, int_fast32_t exp, int_fast32_t n) noexcept:
|
|
3188
|
+
"""
|
|
3189
|
+
Return base^exp mod n.
|
|
3190
|
+
|
|
3191
|
+
For use in ``IntegerMod_int``.
|
|
3192
|
+
|
|
3193
|
+
EXAMPLES::
|
|
3194
|
+
|
|
3195
|
+
sage: z = Mod(2, 256)
|
|
3196
|
+
sage: z^8
|
|
3197
|
+
0
|
|
3198
|
+
|
|
3199
|
+
AUTHORS:
|
|
3200
|
+
|
|
3201
|
+
- Robert Bradshaw
|
|
3202
|
+
"""
|
|
3203
|
+
cdef int_fast32_t prod, pow2
|
|
3204
|
+
if exp <= 5:
|
|
3205
|
+
if exp == 0: return 1
|
|
3206
|
+
if exp == 1: return base
|
|
3207
|
+
prod = base * base % n
|
|
3208
|
+
if exp == 2: return prod
|
|
3209
|
+
if exp == 3: return (prod * base) % n
|
|
3210
|
+
if exp == 4: return (prod * prod) % n
|
|
3211
|
+
|
|
3212
|
+
pow2 = base
|
|
3213
|
+
if exp % 2:
|
|
3214
|
+
prod = base
|
|
3215
|
+
else:
|
|
3216
|
+
prod = 1
|
|
3217
|
+
exp = exp >> 1
|
|
3218
|
+
while exp != 0:
|
|
3219
|
+
pow2 = pow2 * pow2
|
|
3220
|
+
if pow2 >= INTEGER_MOD_INT32_LIMIT: pow2 = pow2 % n
|
|
3221
|
+
if exp % 2:
|
|
3222
|
+
prod = prod * pow2
|
|
3223
|
+
if prod >= INTEGER_MOD_INT32_LIMIT: prod = prod % n
|
|
3224
|
+
exp = exp >> 1
|
|
3225
|
+
|
|
3226
|
+
if prod >= n:
|
|
3227
|
+
prod = prod % n
|
|
3228
|
+
return prod
|
|
3229
|
+
|
|
3230
|
+
|
|
3231
|
+
cdef int jacobi_int(int_fast32_t a, int_fast32_t m) except -2:
|
|
3232
|
+
"""
|
|
3233
|
+
Calculate the jacobi symbol (a/n).
|
|
3234
|
+
|
|
3235
|
+
For use in ``IntegerMod_int``.
|
|
3236
|
+
|
|
3237
|
+
AUTHORS:
|
|
3238
|
+
|
|
3239
|
+
- Robert Bradshaw
|
|
3240
|
+
"""
|
|
3241
|
+
cdef int s, jacobi = 1
|
|
3242
|
+
cdef int_fast32_t b
|
|
3243
|
+
|
|
3244
|
+
a = a % m
|
|
3245
|
+
|
|
3246
|
+
while True:
|
|
3247
|
+
if a == 0:
|
|
3248
|
+
return 0 # gcd was nontrivial
|
|
3249
|
+
elif a == 1:
|
|
3250
|
+
return jacobi
|
|
3251
|
+
s = 0
|
|
3252
|
+
while (1 << s) & a == 0:
|
|
3253
|
+
s += 1
|
|
3254
|
+
b = a >> s
|
|
3255
|
+
# Now a = 2^s * b
|
|
3256
|
+
|
|
3257
|
+
# factor out (2/m)^s term
|
|
3258
|
+
if s % 2 == 1 and (m % 8 == 3 or m % 8 == 5):
|
|
3259
|
+
jacobi = -jacobi
|
|
3260
|
+
|
|
3261
|
+
if b == 1:
|
|
3262
|
+
return jacobi
|
|
3263
|
+
|
|
3264
|
+
# quadratic reciprocity
|
|
3265
|
+
if b % 4 == 3 and m % 4 == 3:
|
|
3266
|
+
jacobi = -jacobi
|
|
3267
|
+
a = m % b
|
|
3268
|
+
m = b
|
|
3269
|
+
|
|
3270
|
+
######################################################################
|
|
3271
|
+
# class IntegerMod_int64
|
|
3272
|
+
######################################################################
|
|
3273
|
+
|
|
3274
|
+
cdef class IntegerMod_int64(IntegerMod_abstract):
|
|
3275
|
+
r"""
|
|
3276
|
+
Elements of `\ZZ/n\ZZ` for n small enough to
|
|
3277
|
+
be operated on in 64 bits
|
|
3278
|
+
|
|
3279
|
+
EXAMPLES::
|
|
3280
|
+
|
|
3281
|
+
sage: a = Mod(10,3^10); a
|
|
3282
|
+
10
|
|
3283
|
+
sage: type(a)
|
|
3284
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>
|
|
3285
|
+
sage: loads(a.dumps()) == a
|
|
3286
|
+
True
|
|
3287
|
+
sage: Mod(5, 2^31)
|
|
3288
|
+
5
|
|
3289
|
+
|
|
3290
|
+
AUTHORS:
|
|
3291
|
+
|
|
3292
|
+
- Robert Bradshaw (2006-09-14)
|
|
3293
|
+
"""
|
|
3294
|
+
|
|
3295
|
+
cdef IntegerMod_int64 _new_c(self, int_fast64_t value):
|
|
3296
|
+
cdef IntegerMod_int64 x
|
|
3297
|
+
x = IntegerMod_int64.__new__(IntegerMod_int64)
|
|
3298
|
+
x._modulus = self._modulus
|
|
3299
|
+
x._parent = self._parent
|
|
3300
|
+
x.ivalue = value
|
|
3301
|
+
return x
|
|
3302
|
+
|
|
3303
|
+
cdef void set_from_mpz(self, mpz_t value) noexcept:
|
|
3304
|
+
self.ivalue = mpz_fdiv_ui(value, self._modulus.int64)
|
|
3305
|
+
|
|
3306
|
+
cdef void set_from_long(self, long value) noexcept:
|
|
3307
|
+
self.ivalue = value % self._modulus.int64
|
|
3308
|
+
if self.ivalue < 0:
|
|
3309
|
+
self.ivalue += self._modulus.int64
|
|
3310
|
+
|
|
3311
|
+
cdef void set_from_ulong_fast(self, unsigned long value) noexcept:
|
|
3312
|
+
self.ivalue = value
|
|
3313
|
+
|
|
3314
|
+
cdef void set_from_int(IntegerMod_int64 self, int_fast64_t ivalue) noexcept:
|
|
3315
|
+
if ivalue < 0:
|
|
3316
|
+
self.ivalue = self._modulus.int64 + (ivalue % self._modulus.int64) # Is ivalue % self._modulus.int64 actually negative?
|
|
3317
|
+
elif ivalue >= self._modulus.int64:
|
|
3318
|
+
self.ivalue = ivalue % self._modulus.int64
|
|
3319
|
+
else:
|
|
3320
|
+
self.ivalue = ivalue
|
|
3321
|
+
|
|
3322
|
+
cdef int_fast64_t get_int_value(IntegerMod_int64 self) noexcept:
|
|
3323
|
+
return self.ivalue
|
|
3324
|
+
|
|
3325
|
+
cpdef _richcmp_(self, right, int op):
|
|
3326
|
+
"""
|
|
3327
|
+
EXAMPLES::
|
|
3328
|
+
|
|
3329
|
+
sage: mod(5,13^5) == mod(13^5+5,13^5)
|
|
3330
|
+
True
|
|
3331
|
+
sage: mod(5,13^5) == mod(8,13^5)
|
|
3332
|
+
False
|
|
3333
|
+
sage: mod(5,13^5) == mod(5,13)
|
|
3334
|
+
True
|
|
3335
|
+
sage: mod(0, 13^5) == 0
|
|
3336
|
+
True
|
|
3337
|
+
sage: mod(0, 13^5) == int(0)
|
|
3338
|
+
True
|
|
3339
|
+
"""
|
|
3340
|
+
if self.ivalue == (<IntegerMod_int64>right).ivalue:
|
|
3341
|
+
return rich_to_bool(op, 0)
|
|
3342
|
+
elif self.ivalue < (<IntegerMod_int64>right).ivalue:
|
|
3343
|
+
return rich_to_bool(op, -1)
|
|
3344
|
+
else:
|
|
3345
|
+
return rich_to_bool(op, 1)
|
|
3346
|
+
|
|
3347
|
+
cpdef bint is_one(IntegerMod_int64 self) noexcept:
|
|
3348
|
+
"""
|
|
3349
|
+
Return ``True`` if this is `1`, otherwise ``False``.
|
|
3350
|
+
|
|
3351
|
+
EXAMPLES::
|
|
3352
|
+
|
|
3353
|
+
sage: (mod(-1,5^10)^2).is_one()
|
|
3354
|
+
True
|
|
3355
|
+
sage: mod(0,5^10).is_one()
|
|
3356
|
+
False
|
|
3357
|
+
"""
|
|
3358
|
+
return self.ivalue == 1
|
|
3359
|
+
|
|
3360
|
+
def __bool__(IntegerMod_int64 self):
|
|
3361
|
+
"""
|
|
3362
|
+
Return ``True`` if this is not `0`, otherwise ``False``.
|
|
3363
|
+
|
|
3364
|
+
EXAMPLES::
|
|
3365
|
+
|
|
3366
|
+
sage: mod(13,5^10).is_zero()
|
|
3367
|
+
False
|
|
3368
|
+
sage: mod(5^12,5^10).is_zero()
|
|
3369
|
+
True
|
|
3370
|
+
"""
|
|
3371
|
+
return self.ivalue != 0
|
|
3372
|
+
|
|
3373
|
+
cpdef bint is_unit(IntegerMod_int64 self) noexcept:
|
|
3374
|
+
"""
|
|
3375
|
+
Return ``True`` iff this element is a unit.
|
|
3376
|
+
|
|
3377
|
+
EXAMPLES::
|
|
3378
|
+
|
|
3379
|
+
sage: mod(13, 5^10).is_unit()
|
|
3380
|
+
True
|
|
3381
|
+
sage: mod(25, 5^10).is_unit()
|
|
3382
|
+
False
|
|
3383
|
+
"""
|
|
3384
|
+
return gcd_int64(self.ivalue, self._modulus.int64) == 1
|
|
3385
|
+
|
|
3386
|
+
def _crt(IntegerMod_int64 self, IntegerMod_int64 other):
|
|
3387
|
+
"""
|
|
3388
|
+
Use the Chinese Remainder Theorem to find an element of the
|
|
3389
|
+
integers modulo the product of the moduli that reduces to ``self`` and
|
|
3390
|
+
to ``other``. The modulus of ``other`` must be coprime to the modulus
|
|
3391
|
+
of ``self``.
|
|
3392
|
+
|
|
3393
|
+
EXAMPLES::
|
|
3394
|
+
|
|
3395
|
+
sage: a = mod(3,5^10)
|
|
3396
|
+
sage: b = mod(2,7)
|
|
3397
|
+
sage: a.crt(b)
|
|
3398
|
+
29296878
|
|
3399
|
+
sage: type(a.crt(b)) == type(b.crt(a)) and type(a.crt(b)) == type(mod(1, 7 * 5^10))
|
|
3400
|
+
True
|
|
3401
|
+
|
|
3402
|
+
::
|
|
3403
|
+
|
|
3404
|
+
sage: a = mod(3,10^10)
|
|
3405
|
+
sage: b = mod(2,9)
|
|
3406
|
+
sage: a.crt(b)
|
|
3407
|
+
80000000003
|
|
3408
|
+
sage: type(a.crt(b)) == type(b.crt(a)) and type(a.crt(b)) == type(mod(1, 9 * 10^10))
|
|
3409
|
+
True
|
|
3410
|
+
|
|
3411
|
+
AUTHORS:
|
|
3412
|
+
|
|
3413
|
+
- Robert Bradshaw
|
|
3414
|
+
"""
|
|
3415
|
+
cdef IntegerMod_int64 lift
|
|
3416
|
+
cdef int_fast64_t x
|
|
3417
|
+
|
|
3418
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
3419
|
+
lift = IntegerMod_int64(IntegerModRing(self._modulus.int64 * other._modulus.int64))
|
|
3420
|
+
|
|
3421
|
+
try:
|
|
3422
|
+
x = (other.ivalue - self.ivalue % other._modulus.int64) * mod_inverse_int64(self._modulus.int64, other._modulus.int64)
|
|
3423
|
+
lift.set_from_int( x * self._modulus.int64 + self.ivalue )
|
|
3424
|
+
return lift
|
|
3425
|
+
except ZeroDivisionError:
|
|
3426
|
+
raise ZeroDivisionError("moduli must be coprime")
|
|
3427
|
+
|
|
3428
|
+
def __copy__(IntegerMod_int64 self):
|
|
3429
|
+
"""
|
|
3430
|
+
EXAMPLES::
|
|
3431
|
+
|
|
3432
|
+
sage: R = Integers(10^5)
|
|
3433
|
+
sage: R7 = R(7)
|
|
3434
|
+
sage: copy(R7) is R7
|
|
3435
|
+
True
|
|
3436
|
+
"""
|
|
3437
|
+
# immutable
|
|
3438
|
+
return self
|
|
3439
|
+
|
|
3440
|
+
def __deepcopy__(IntegerMod_int64 self, memo):
|
|
3441
|
+
"""
|
|
3442
|
+
EXAMPLES::
|
|
3443
|
+
|
|
3444
|
+
sage: R = Integers(10^5)
|
|
3445
|
+
sage: R7 = R(7)
|
|
3446
|
+
sage: deepcopy(R7) is R7
|
|
3447
|
+
True
|
|
3448
|
+
"""
|
|
3449
|
+
# immutable
|
|
3450
|
+
return self
|
|
3451
|
+
|
|
3452
|
+
cpdef _add_(self, right):
|
|
3453
|
+
"""
|
|
3454
|
+
EXAMPLES::
|
|
3455
|
+
|
|
3456
|
+
sage: R = Integers(10^5)
|
|
3457
|
+
sage: R(7) + R(8)
|
|
3458
|
+
15
|
|
3459
|
+
"""
|
|
3460
|
+
cdef int_fast64_t x
|
|
3461
|
+
x = self.ivalue + (<IntegerMod_int64>right).ivalue
|
|
3462
|
+
if x >= self._modulus.int64:
|
|
3463
|
+
x = x - self._modulus.int64
|
|
3464
|
+
return self._new_c(x)
|
|
3465
|
+
|
|
3466
|
+
cpdef _sub_(self, right):
|
|
3467
|
+
"""
|
|
3468
|
+
EXAMPLES::
|
|
3469
|
+
|
|
3470
|
+
sage: R = Integers(10^5)
|
|
3471
|
+
sage: R(7) - R(8)
|
|
3472
|
+
99999
|
|
3473
|
+
"""
|
|
3474
|
+
cdef int_fast64_t x
|
|
3475
|
+
x = self.ivalue - (<IntegerMod_int64>right).ivalue
|
|
3476
|
+
if x < 0:
|
|
3477
|
+
x = x + self._modulus.int64
|
|
3478
|
+
return self._new_c(x)
|
|
3479
|
+
|
|
3480
|
+
cpdef _neg_(self):
|
|
3481
|
+
"""
|
|
3482
|
+
EXAMPLES::
|
|
3483
|
+
|
|
3484
|
+
sage: -mod(7,10^5)
|
|
3485
|
+
99993
|
|
3486
|
+
sage: -mod(0,10^6)
|
|
3487
|
+
0
|
|
3488
|
+
"""
|
|
3489
|
+
if self.ivalue == 0:
|
|
3490
|
+
return self
|
|
3491
|
+
return self._new_c(self._modulus.int64 - self.ivalue)
|
|
3492
|
+
|
|
3493
|
+
cpdef _mul_(self, right):
|
|
3494
|
+
"""
|
|
3495
|
+
EXAMPLES::
|
|
3496
|
+
|
|
3497
|
+
sage: R = Integers(10^5)
|
|
3498
|
+
sage: R(700) * R(800)
|
|
3499
|
+
60000
|
|
3500
|
+
"""
|
|
3501
|
+
return self._new_c((self.ivalue * (<IntegerMod_int64>right).ivalue) % self._modulus.int64)
|
|
3502
|
+
|
|
3503
|
+
cpdef _div_(self, right):
|
|
3504
|
+
"""
|
|
3505
|
+
EXAMPLES::
|
|
3506
|
+
|
|
3507
|
+
sage: R = Integers(10^5)
|
|
3508
|
+
sage: R(2)/3
|
|
3509
|
+
33334
|
|
3510
|
+
"""
|
|
3511
|
+
return self._new_c((self.ivalue * mod_inverse_int64((<IntegerMod_int64>right).ivalue,
|
|
3512
|
+
self._modulus.int64) ) % self._modulus.int64)
|
|
3513
|
+
|
|
3514
|
+
def __int__(IntegerMod_int64 self):
|
|
3515
|
+
return self.ivalue
|
|
3516
|
+
|
|
3517
|
+
def __index__(self):
|
|
3518
|
+
"""
|
|
3519
|
+
Needed so integers modulo `n` can be used as list indices.
|
|
3520
|
+
|
|
3521
|
+
EXAMPLES::
|
|
3522
|
+
|
|
3523
|
+
sage: v = [1,2,3,4,5]
|
|
3524
|
+
sage: v[Mod(3, 2^20)]
|
|
3525
|
+
4
|
|
3526
|
+
"""
|
|
3527
|
+
return self.ivalue
|
|
3528
|
+
|
|
3529
|
+
def __lshift__(IntegerMod_int64 self, k):
|
|
3530
|
+
r"""
|
|
3531
|
+
Perform a left shift by ``k`` bits.
|
|
3532
|
+
|
|
3533
|
+
For details, see :meth:`shift`.
|
|
3534
|
+
|
|
3535
|
+
EXAMPLES::
|
|
3536
|
+
|
|
3537
|
+
sage: e = Mod(5, 2^31 - 1)
|
|
3538
|
+
sage: e << 32
|
|
3539
|
+
10
|
|
3540
|
+
sage: e * 2^32
|
|
3541
|
+
10
|
|
3542
|
+
"""
|
|
3543
|
+
return self.shift(int(k))
|
|
3544
|
+
|
|
3545
|
+
def __rshift__(IntegerMod_int64 self, k):
|
|
3546
|
+
r"""
|
|
3547
|
+
Perform a right shift by ``k`` bits.
|
|
3548
|
+
|
|
3549
|
+
For details, see :meth:`shift`.
|
|
3550
|
+
|
|
3551
|
+
EXAMPLES::
|
|
3552
|
+
|
|
3553
|
+
sage: e = Mod(5, 2^31 - 1)
|
|
3554
|
+
sage: e >> 1
|
|
3555
|
+
2
|
|
3556
|
+
"""
|
|
3557
|
+
return self.shift(-int(k))
|
|
3558
|
+
|
|
3559
|
+
cdef shift(IntegerMod_int64 self, int k):
|
|
3560
|
+
"""
|
|
3561
|
+
Perform a bit-shift specified by ``k`` on ``self``.
|
|
3562
|
+
|
|
3563
|
+
Suppose that ``self`` represents an integer `x` modulo `n`. If `k` is
|
|
3564
|
+
`k = 0`, returns `x`. If `k > 0`, shifts `x` to the left, that is,
|
|
3565
|
+
multiplies `x` by `2^k` and then returns the representative in the
|
|
3566
|
+
range `[0,n)`. If `k < 0`, shifts `x` to the right, that is, returns
|
|
3567
|
+
the integral part of `x` divided by `2^k`.
|
|
3568
|
+
|
|
3569
|
+
Note that, in any case, ``self`` remains unchanged.
|
|
3570
|
+
|
|
3571
|
+
INPUT:
|
|
3572
|
+
|
|
3573
|
+
- ``k`` -- integer of type ``int``
|
|
3574
|
+
|
|
3575
|
+
OUTPUT: result of type ``IntegerMod_int64``
|
|
3576
|
+
|
|
3577
|
+
WARNING:
|
|
3578
|
+
|
|
3579
|
+
For positive ``k``, if ``x << k`` overflows as a 64-bit integer, the
|
|
3580
|
+
result is meaningless.
|
|
3581
|
+
|
|
3582
|
+
EXAMPLES::
|
|
3583
|
+
|
|
3584
|
+
sage: e = Mod(5, 2^31 - 1)
|
|
3585
|
+
sage: e << 32
|
|
3586
|
+
10
|
|
3587
|
+
sage: e * 2^32
|
|
3588
|
+
10
|
|
3589
|
+
sage: e = Mod(5, 2^31 - 1)
|
|
3590
|
+
sage: e >> 1
|
|
3591
|
+
2
|
|
3592
|
+
"""
|
|
3593
|
+
if k == 0:
|
|
3594
|
+
return self
|
|
3595
|
+
elif k > 0:
|
|
3596
|
+
return self._new_c((self.ivalue << k) % self._modulus.int64)
|
|
3597
|
+
else:
|
|
3598
|
+
return self._new_c(self.ivalue >> (-k))
|
|
3599
|
+
|
|
3600
|
+
def __pow__(IntegerMod_int64 self, exp, m): # NOTE: m ignored, always use modulus of parent ring
|
|
3601
|
+
"""
|
|
3602
|
+
EXAMPLES::
|
|
3603
|
+
|
|
3604
|
+
sage: R = Integers(10)
|
|
3605
|
+
sage: R(2)^10
|
|
3606
|
+
4
|
|
3607
|
+
sage: p = next_prime(10^5) # needs sage.libs.pari
|
|
3608
|
+
sage: R = Integers(p) # needs sage.libs.pari
|
|
3609
|
+
sage: R(1234)^(p - 1) # needs sage.libs.pari
|
|
3610
|
+
1
|
|
3611
|
+
sage: R = Integers(17^5)
|
|
3612
|
+
sage: R(17)^5
|
|
3613
|
+
0
|
|
3614
|
+
|
|
3615
|
+
sage: R(2)^-1 * 2
|
|
3616
|
+
1
|
|
3617
|
+
sage: R(2)^-1000000 * 2^1000000
|
|
3618
|
+
1
|
|
3619
|
+
sage: R(17)^-1
|
|
3620
|
+
Traceback (most recent call last):
|
|
3621
|
+
...
|
|
3622
|
+
ZeroDivisionError: inverse of Mod(17, 1419857) does not exist
|
|
3623
|
+
sage: R(17)^-100000000
|
|
3624
|
+
Traceback (most recent call last):
|
|
3625
|
+
...
|
|
3626
|
+
ZeroDivisionError: Inverse does not exist.
|
|
3627
|
+
|
|
3628
|
+
TESTS::
|
|
3629
|
+
|
|
3630
|
+
sage: type(R(0))
|
|
3631
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>
|
|
3632
|
+
|
|
3633
|
+
We define ``0^0`` to be unity, :issue:`13894`::
|
|
3634
|
+
|
|
3635
|
+
sage: p = next_prime(10^5) # needs sage.libs.pari
|
|
3636
|
+
sage: R = Integers(p) # needs sage.libs.pari
|
|
3637
|
+
sage: R(0)^0
|
|
3638
|
+
1
|
|
3639
|
+
|
|
3640
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
3641
|
+
|
|
3642
|
+
sage: type(R(0)^0) == type(R(0))
|
|
3643
|
+
True
|
|
3644
|
+
|
|
3645
|
+
When the modulus is ``1``, the only element in the ring is
|
|
3646
|
+
``0`` (and it is equivalent to ``1``), so we return that
|
|
3647
|
+
instead::
|
|
3648
|
+
|
|
3649
|
+
sage: from sage.rings.finite_rings.integer_mod \
|
|
3650
|
+
....: import IntegerMod_int64
|
|
3651
|
+
sage: zero = IntegerMod_int64(Integers(1),0)
|
|
3652
|
+
sage: type(zero)
|
|
3653
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>
|
|
3654
|
+
sage: zero^0
|
|
3655
|
+
0
|
|
3656
|
+
"""
|
|
3657
|
+
cdef long long_exp
|
|
3658
|
+
cdef int_fast64_t res
|
|
3659
|
+
cdef mpz_t res_mpz
|
|
3660
|
+
if type(exp) is int and -100000 < PyLong_AsLong(exp) < 100000:
|
|
3661
|
+
long_exp = PyLong_AsLong(exp)
|
|
3662
|
+
elif type(exp) is Integer and mpz_cmpabs_ui((<Integer>exp).value, 100000) == -1:
|
|
3663
|
+
long_exp = mpz_get_si((<Integer>exp).value)
|
|
3664
|
+
else:
|
|
3665
|
+
base = self.lift()
|
|
3666
|
+
sig_on()
|
|
3667
|
+
try:
|
|
3668
|
+
mpz_init(res_mpz)
|
|
3669
|
+
mpz_pow_helper(res_mpz, (<Integer>base).value, exp, self._modulus.sageInteger.value)
|
|
3670
|
+
res = mpz_get_ui(res_mpz)
|
|
3671
|
+
mpz_clear(res_mpz)
|
|
3672
|
+
finally:
|
|
3673
|
+
sig_off()
|
|
3674
|
+
return self._new_c(res)
|
|
3675
|
+
|
|
3676
|
+
if long_exp == 0 and self.ivalue == 0:
|
|
3677
|
+
# Return 0 if the modulus is 1, otherwise return 1.
|
|
3678
|
+
return self._new_c(self._modulus.int64 != 1)
|
|
3679
|
+
cdef bint invert = False
|
|
3680
|
+
if long_exp < 0:
|
|
3681
|
+
invert = True
|
|
3682
|
+
long_exp = -long_exp
|
|
3683
|
+
res = mod_pow_int64(self.ivalue, long_exp, self._modulus.int64)
|
|
3684
|
+
if invert:
|
|
3685
|
+
return self._new_c(mod_inverse_int64(res, self._modulus.int64))
|
|
3686
|
+
else:
|
|
3687
|
+
return self._new_c(res)
|
|
3688
|
+
|
|
3689
|
+
def __invert__(IntegerMod_int64 self):
|
|
3690
|
+
"""
|
|
3691
|
+
Return the multiplicative inverse of ``self``.
|
|
3692
|
+
|
|
3693
|
+
EXAMPLES::
|
|
3694
|
+
|
|
3695
|
+
sage: a = mod(7,2^40); type(a)
|
|
3696
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>
|
|
3697
|
+
sage: ~a
|
|
3698
|
+
471219269047
|
|
3699
|
+
sage: a
|
|
3700
|
+
7
|
|
3701
|
+
"""
|
|
3702
|
+
return self._new_c(mod_inverse_int64(self.ivalue, self._modulus.int64))
|
|
3703
|
+
|
|
3704
|
+
def lift(IntegerMod_int64 self):
|
|
3705
|
+
"""
|
|
3706
|
+
Lift an integer modulo `n` to the integers.
|
|
3707
|
+
|
|
3708
|
+
EXAMPLES::
|
|
3709
|
+
|
|
3710
|
+
sage: a = Mod(8943, 2^25); type(a)
|
|
3711
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>
|
|
3712
|
+
sage: lift(a)
|
|
3713
|
+
8943
|
|
3714
|
+
sage: a.lift()
|
|
3715
|
+
8943
|
|
3716
|
+
"""
|
|
3717
|
+
cdef sage.rings.integer.Integer z
|
|
3718
|
+
z = sage.rings.integer.Integer()
|
|
3719
|
+
mpz_set_si(z.value, self.ivalue)
|
|
3720
|
+
return z
|
|
3721
|
+
|
|
3722
|
+
def __float__(IntegerMod_int64 self):
|
|
3723
|
+
"""
|
|
3724
|
+
Coerce ``self`` to a float.
|
|
3725
|
+
|
|
3726
|
+
EXAMPLES::
|
|
3727
|
+
|
|
3728
|
+
sage: a = Mod(8943, 2^35)
|
|
3729
|
+
sage: float(a)
|
|
3730
|
+
8943.0
|
|
3731
|
+
"""
|
|
3732
|
+
return <double>self.ivalue
|
|
3733
|
+
|
|
3734
|
+
def __hash__(self):
|
|
3735
|
+
"""
|
|
3736
|
+
Compute hash of ``self``.
|
|
3737
|
+
|
|
3738
|
+
EXAMPLES::
|
|
3739
|
+
|
|
3740
|
+
sage: a = Mod(8943, 2^35)
|
|
3741
|
+
sage: hash(a)
|
|
3742
|
+
8943
|
|
3743
|
+
"""
|
|
3744
|
+
return hash(self.ivalue)
|
|
3745
|
+
|
|
3746
|
+
def _balanced_abs(self):
|
|
3747
|
+
r"""
|
|
3748
|
+
This function returns `x` or `-x`, whichever has a
|
|
3749
|
+
positive representative in `-n/2 < x \leq n/2`.
|
|
3750
|
+
"""
|
|
3751
|
+
if self.ivalue > self._modulus.int64 / 2:
|
|
3752
|
+
return -self
|
|
3753
|
+
return self
|
|
3754
|
+
|
|
3755
|
+
@coerce_binop
|
|
3756
|
+
def gcd(self, IntegerMod_int64 other):
|
|
3757
|
+
r"""
|
|
3758
|
+
Greatest common divisor.
|
|
3759
|
+
|
|
3760
|
+
Returns the "smallest" generator in `\ZZ / N\ZZ` of the ideal
|
|
3761
|
+
generated by ``self`` and ``other``.
|
|
3762
|
+
|
|
3763
|
+
INPUT:
|
|
3764
|
+
|
|
3765
|
+
- ``other`` -- an element of the same ring as this one
|
|
3766
|
+
|
|
3767
|
+
EXAMPLES::
|
|
3768
|
+
|
|
3769
|
+
sage: mod(2^3*3^2*5, 3^3*2^2*17^5).gcd(mod(2^4*3*17, 3^3*2^2*17^5))
|
|
3770
|
+
12
|
|
3771
|
+
sage: mod(0,17^5).gcd(mod(0,17^5))
|
|
3772
|
+
0
|
|
3773
|
+
"""
|
|
3774
|
+
cdef int_fast64_t g = gcd_int64(self.ivalue, self._modulus.int64)
|
|
3775
|
+
g = gcd_int64(g, other.ivalue)
|
|
3776
|
+
if g == self._modulus.int64: # self = other = 0
|
|
3777
|
+
g = 0
|
|
3778
|
+
return self._new_c(g)
|
|
3779
|
+
|
|
3780
|
+
|
|
3781
|
+
### Helper functions
|
|
3782
|
+
|
|
3783
|
+
cdef int mpz_pow_helper(mpz_t res, mpz_t base, object exp, mpz_t modulus) except -1:
|
|
3784
|
+
cdef bint invert = False
|
|
3785
|
+
cdef long long_exp
|
|
3786
|
+
if is_small_python_int(exp):
|
|
3787
|
+
long_exp = exp
|
|
3788
|
+
if long_exp < 0:
|
|
3789
|
+
long_exp = -long_exp
|
|
3790
|
+
invert = True
|
|
3791
|
+
mpz_powm_ui(res, base, long_exp, modulus)
|
|
3792
|
+
else:
|
|
3793
|
+
if type(exp) is not Integer:
|
|
3794
|
+
exp = Integer(exp)
|
|
3795
|
+
if mpz_sgn((<Integer>exp).value) < 0:
|
|
3796
|
+
exp = -exp
|
|
3797
|
+
invert = True
|
|
3798
|
+
mpz_powm(res, base, (<Integer>exp).value, modulus)
|
|
3799
|
+
if invert:
|
|
3800
|
+
if not mpz_invert(res, res, modulus):
|
|
3801
|
+
raise ZeroDivisionError("Inverse does not exist.")
|
|
3802
|
+
|
|
3803
|
+
cdef int_fast64_t gcd_int64(int_fast64_t a, int_fast64_t b) noexcept:
|
|
3804
|
+
"""
|
|
3805
|
+
Return the gcd of ``a`` and ``b``.
|
|
3806
|
+
|
|
3807
|
+
For use with IntegerMod_int64.
|
|
3808
|
+
|
|
3809
|
+
AUTHORS:
|
|
3810
|
+
|
|
3811
|
+
- Robert Bradshaw
|
|
3812
|
+
"""
|
|
3813
|
+
cdef int_fast64_t tmp
|
|
3814
|
+
if a < b:
|
|
3815
|
+
tmp = b
|
|
3816
|
+
b = a
|
|
3817
|
+
a = tmp
|
|
3818
|
+
while b:
|
|
3819
|
+
tmp = b
|
|
3820
|
+
b = a % b
|
|
3821
|
+
a = tmp
|
|
3822
|
+
return a
|
|
3823
|
+
|
|
3824
|
+
|
|
3825
|
+
cdef int_fast64_t mod_inverse_int64(int_fast64_t x, int_fast64_t n) except 0:
|
|
3826
|
+
"""
|
|
3827
|
+
Return y such that xy=1 mod n.
|
|
3828
|
+
|
|
3829
|
+
For use in ``IntegerMod_int64``.
|
|
3830
|
+
|
|
3831
|
+
AUTHORS:
|
|
3832
|
+
|
|
3833
|
+
- Robert Bradshaw
|
|
3834
|
+
"""
|
|
3835
|
+
cdef int_fast64_t tmp, a, b, last_t, t, next_t, q
|
|
3836
|
+
a = n
|
|
3837
|
+
b = x
|
|
3838
|
+
t = 0
|
|
3839
|
+
next_t = 1
|
|
3840
|
+
while b:
|
|
3841
|
+
# a = s * n + t * x
|
|
3842
|
+
if b == 1:
|
|
3843
|
+
next_t = next_t % n
|
|
3844
|
+
if next_t < 0:
|
|
3845
|
+
next_t = next_t + n
|
|
3846
|
+
return next_t
|
|
3847
|
+
q = a / b
|
|
3848
|
+
tmp = b
|
|
3849
|
+
b = a % b
|
|
3850
|
+
a = tmp
|
|
3851
|
+
last_t = t
|
|
3852
|
+
t = next_t
|
|
3853
|
+
next_t = last_t - q * t
|
|
3854
|
+
raise ZeroDivisionError(f"inverse of Mod({x}, {n}) does not exist")
|
|
3855
|
+
|
|
3856
|
+
|
|
3857
|
+
cdef int_fast64_t mod_pow_int64(int_fast64_t base, int_fast64_t exp, int_fast64_t n) noexcept:
|
|
3858
|
+
"""
|
|
3859
|
+
Return base^exp mod n.
|
|
3860
|
+
|
|
3861
|
+
For use in ``IntegerMod_int64``.
|
|
3862
|
+
|
|
3863
|
+
AUTHORS:
|
|
3864
|
+
|
|
3865
|
+
- Robert Bradshaw
|
|
3866
|
+
"""
|
|
3867
|
+
cdef int_fast64_t prod, pow2
|
|
3868
|
+
if exp <= 5:
|
|
3869
|
+
if exp == 0: return 1
|
|
3870
|
+
if exp == 1: return base
|
|
3871
|
+
prod = base * base % n
|
|
3872
|
+
if exp == 2: return prod
|
|
3873
|
+
if exp == 3: return (prod * base) % n
|
|
3874
|
+
if exp == 4: return (prod * prod) % n
|
|
3875
|
+
|
|
3876
|
+
pow2 = base
|
|
3877
|
+
if exp % 2:
|
|
3878
|
+
prod = base
|
|
3879
|
+
else:
|
|
3880
|
+
prod = 1
|
|
3881
|
+
exp = exp >> 1
|
|
3882
|
+
while exp != 0:
|
|
3883
|
+
pow2 = pow2 * pow2
|
|
3884
|
+
if pow2 >= INTEGER_MOD_INT64_LIMIT: pow2 = pow2 % n
|
|
3885
|
+
if exp % 2:
|
|
3886
|
+
prod = prod * pow2
|
|
3887
|
+
if prod >= INTEGER_MOD_INT64_LIMIT: prod = prod % n
|
|
3888
|
+
exp = exp >> 1
|
|
3889
|
+
|
|
3890
|
+
if prod >= n:
|
|
3891
|
+
prod = prod % n
|
|
3892
|
+
return prod
|
|
3893
|
+
|
|
3894
|
+
|
|
3895
|
+
cdef int jacobi_int64(int_fast64_t a, int_fast64_t m) except -2:
|
|
3896
|
+
"""
|
|
3897
|
+
Calculate the jacobi symbol (a/n).
|
|
3898
|
+
|
|
3899
|
+
For use in ``IntegerMod_int64``.
|
|
3900
|
+
|
|
3901
|
+
AUTHORS:
|
|
3902
|
+
|
|
3903
|
+
- Robert Bradshaw
|
|
3904
|
+
"""
|
|
3905
|
+
cdef int s, jacobi = 1
|
|
3906
|
+
cdef int_fast64_t b
|
|
3907
|
+
|
|
3908
|
+
a = a % m
|
|
3909
|
+
|
|
3910
|
+
while True:
|
|
3911
|
+
if a == 0:
|
|
3912
|
+
return 0 # gcd was nontrivial
|
|
3913
|
+
elif a == 1:
|
|
3914
|
+
return jacobi
|
|
3915
|
+
s = 0
|
|
3916
|
+
while (1 << s) & a == 0:
|
|
3917
|
+
s += 1
|
|
3918
|
+
b = a >> s
|
|
3919
|
+
# Now a = 2^s * b
|
|
3920
|
+
|
|
3921
|
+
# factor out (2/m)^s term
|
|
3922
|
+
if s % 2 == 1 and (m % 8 == 3 or m % 8 == 5):
|
|
3923
|
+
jacobi = -jacobi
|
|
3924
|
+
|
|
3925
|
+
if b == 1:
|
|
3926
|
+
return jacobi
|
|
3927
|
+
|
|
3928
|
+
# quadratic reciprocity
|
|
3929
|
+
if b % 4 == 3 and m % 4 == 3:
|
|
3930
|
+
jacobi = -jacobi
|
|
3931
|
+
a = m % b
|
|
3932
|
+
m = b
|
|
3933
|
+
|
|
3934
|
+
|
|
3935
|
+
########################
|
|
3936
|
+
# Square root functions
|
|
3937
|
+
########################
|
|
3938
|
+
|
|
3939
|
+
def square_root_mod_prime_power(IntegerMod_abstract a, p, e):
|
|
3940
|
+
r"""
|
|
3941
|
+
Calculate the square root of `a`, where `a` is an
|
|
3942
|
+
integer mod `p^e`.
|
|
3943
|
+
|
|
3944
|
+
ALGORITHM: Compute `p`-adically by stripping off even powers of `p`
|
|
3945
|
+
to get a unit and lifting `\sqrt{unit} \bmod p` via Newton's method
|
|
3946
|
+
whenever `p` is odd and by a variant of Hensel lifting for `p = 2`.
|
|
3947
|
+
|
|
3948
|
+
AUTHORS:
|
|
3949
|
+
|
|
3950
|
+
- Robert Bradshaw
|
|
3951
|
+
- Lorenz Panny (2022): polynomial-time algorithm for `p = 2`
|
|
3952
|
+
|
|
3953
|
+
EXAMPLES::
|
|
3954
|
+
|
|
3955
|
+
sage: from sage.rings.finite_rings.integer_mod import square_root_mod_prime_power
|
|
3956
|
+
sage: a = Mod(17,2^20)
|
|
3957
|
+
sage: b = square_root_mod_prime_power(a,2,20)
|
|
3958
|
+
sage: b^2 == a
|
|
3959
|
+
True
|
|
3960
|
+
|
|
3961
|
+
::
|
|
3962
|
+
|
|
3963
|
+
sage: a = Mod(72, 97^10)
|
|
3964
|
+
sage: b = square_root_mod_prime_power(a, 97, 10) # needs sage.libs.pari
|
|
3965
|
+
sage: b^2 == a # needs sage.libs.pari
|
|
3966
|
+
True
|
|
3967
|
+
sage: mod(100, 5^7).sqrt()^2 # needs sage.libs.pari
|
|
3968
|
+
100
|
|
3969
|
+
|
|
3970
|
+
TESTS:
|
|
3971
|
+
|
|
3972
|
+
A big example for the binary case (:issue:`33961`)::
|
|
3973
|
+
|
|
3974
|
+
sage: y = Mod(-7, 2^777)
|
|
3975
|
+
sage: hex(y.sqrt()^2 - y) # needs sage.libs.pari
|
|
3976
|
+
'0x0'
|
|
3977
|
+
|
|
3978
|
+
Testing with random squares in random rings::
|
|
3979
|
+
|
|
3980
|
+
sage: p = random_prime(999)
|
|
3981
|
+
sage: e = randrange(1, 999)
|
|
3982
|
+
sage: x = Zmod(p^e).random_element()
|
|
3983
|
+
sage: (x^2).sqrt()^2 == x^2 # needs sage.libs.pari
|
|
3984
|
+
True
|
|
3985
|
+
"""
|
|
3986
|
+
if a.is_zero() or a.is_one():
|
|
3987
|
+
return a
|
|
3988
|
+
|
|
3989
|
+
# strip off even powers of p
|
|
3990
|
+
cdef int i, val = a.lift().valuation(p)
|
|
3991
|
+
if val % 2 == 1:
|
|
3992
|
+
raise ValueError("self must be a square")
|
|
3993
|
+
if val > 0:
|
|
3994
|
+
unit = a._parent(a.lift() // p**val)
|
|
3995
|
+
else:
|
|
3996
|
+
unit = a
|
|
3997
|
+
|
|
3998
|
+
cdef int n
|
|
3999
|
+
|
|
4000
|
+
if p == 2:
|
|
4001
|
+
# squares in Z/2^e are of the form 4^n*(1+8*m)
|
|
4002
|
+
if unit.lift() % 8 != 1:
|
|
4003
|
+
raise ValueError("self must be a square")
|
|
4004
|
+
|
|
4005
|
+
u = unit.lift()
|
|
4006
|
+
x = next(i for i in range(1,8,2) if i*i & 31 == u & 31)
|
|
4007
|
+
t = (x*x - u) >> 5
|
|
4008
|
+
for i in range(4, e-1 - val//2):
|
|
4009
|
+
if t & 1:
|
|
4010
|
+
x |= one_Z << i
|
|
4011
|
+
t += x - (one_Z << i-1)
|
|
4012
|
+
t >>= 1
|
|
4013
|
+
# assert t << i+2 == x*x - u
|
|
4014
|
+
x = a.parent()(x)
|
|
4015
|
+
|
|
4016
|
+
else:
|
|
4017
|
+
# find square root of unit mod p
|
|
4018
|
+
x = unit.parent()(square_root_mod_prime(mod(unit, p), p))
|
|
4019
|
+
|
|
4020
|
+
# lift p-adically using Newton iteration
|
|
4021
|
+
# this is done to higher precision than necessary except at the last step
|
|
4022
|
+
one_half = ~(a._new_c_from_long(2))
|
|
4023
|
+
# need at least (e - val//2) p-adic digits of precision, which doubles
|
|
4024
|
+
# at each step
|
|
4025
|
+
n = <int>ceil(log2(e - val//2))
|
|
4026
|
+
for i in range(n):
|
|
4027
|
+
x = (x + unit/x) * one_half
|
|
4028
|
+
|
|
4029
|
+
# multiply in powers of p (if any)
|
|
4030
|
+
if val > 0:
|
|
4031
|
+
x *= p**(val//2)
|
|
4032
|
+
return x
|
|
4033
|
+
|
|
4034
|
+
|
|
4035
|
+
cpdef square_root_mod_prime(IntegerMod_abstract a, p=None):
|
|
4036
|
+
r"""
|
|
4037
|
+
Calculate the square root of `a`, where `a` is an
|
|
4038
|
+
integer mod `p`; if `a` is not a perfect square,
|
|
4039
|
+
this returns an (incorrect) answer without checking.
|
|
4040
|
+
|
|
4041
|
+
ALGORITHM: Several cases based on residue class of
|
|
4042
|
+
`p \bmod 16`.
|
|
4043
|
+
|
|
4044
|
+
|
|
4045
|
+
- `p \bmod 2 = 0`: `p = 2` so `\sqrt{a} = a`.
|
|
4046
|
+
|
|
4047
|
+
- `p \bmod 4 = 3`: `\sqrt{a} = a^{(p+1)/4}`.
|
|
4048
|
+
|
|
4049
|
+
- `p \bmod 8 = 5`: `\sqrt{a} = \zeta i a` where `\zeta = (2a)^{(p-5)/8}`,
|
|
4050
|
+
`i=\sqrt{-1}`.
|
|
4051
|
+
|
|
4052
|
+
- `p \bmod 16 = 9`: Similar, work in a bi-quadratic extension of `\GF{p}`
|
|
4053
|
+
for small `p`, Tonelli and Shanks for large `p`.
|
|
4054
|
+
|
|
4055
|
+
- `p \bmod 16 = 1`: Tonelli and Shanks.
|
|
4056
|
+
|
|
4057
|
+
|
|
4058
|
+
REFERENCES:
|
|
4059
|
+
|
|
4060
|
+
- [Mul2004]_
|
|
4061
|
+
|
|
4062
|
+
- [Atk1992]_
|
|
4063
|
+
|
|
4064
|
+
- [Pos1988]_
|
|
4065
|
+
|
|
4066
|
+
AUTHORS:
|
|
4067
|
+
|
|
4068
|
+
- Robert Bradshaw
|
|
4069
|
+
|
|
4070
|
+
TESTS:
|
|
4071
|
+
|
|
4072
|
+
Every case appears in the first hundred primes.
|
|
4073
|
+
|
|
4074
|
+
::
|
|
4075
|
+
|
|
4076
|
+
sage: from sage.rings.finite_rings.integer_mod import square_root_mod_prime # sqrt() uses brute force for small p
|
|
4077
|
+
sage: all(square_root_mod_prime(a*a)^2 == a*a # needs sage.libs.pari
|
|
4078
|
+
....: for p in prime_range(100)
|
|
4079
|
+
....: for a in Integers(p))
|
|
4080
|
+
True
|
|
4081
|
+
"""
|
|
4082
|
+
if not a or a.is_one():
|
|
4083
|
+
return a
|
|
4084
|
+
|
|
4085
|
+
if p is None:
|
|
4086
|
+
p = a._parent.order()
|
|
4087
|
+
p = Integer(p)
|
|
4088
|
+
|
|
4089
|
+
cdef int p_mod_16 = p % 16
|
|
4090
|
+
cdef double bits = log2(float(p))
|
|
4091
|
+
cdef long r, m
|
|
4092
|
+
|
|
4093
|
+
if p_mod_16 % 2 == 0: # p == 2
|
|
4094
|
+
return a
|
|
4095
|
+
|
|
4096
|
+
elif p_mod_16 % 4 == 3:
|
|
4097
|
+
return a ** ((p+1)//4)
|
|
4098
|
+
|
|
4099
|
+
elif p_mod_16 % 8 == 5:
|
|
4100
|
+
two_a = a+a
|
|
4101
|
+
zeta = two_a ** ((p-5)//8)
|
|
4102
|
+
i = zeta**2 * two_a # = two_a ** ((p-1)//4)
|
|
4103
|
+
return zeta*a*(i-1)
|
|
4104
|
+
|
|
4105
|
+
elif p_mod_16 == 9 and bits < 500:
|
|
4106
|
+
two_a = a+a
|
|
4107
|
+
s = two_a ** ((p-1)//4)
|
|
4108
|
+
if s.is_one():
|
|
4109
|
+
d = a._parent.quadratic_nonresidue()
|
|
4110
|
+
d2 = d*d
|
|
4111
|
+
z = (two_a * d2) ** ((p-9)//16)
|
|
4112
|
+
i = two_a * d2 * z*z
|
|
4113
|
+
return z*d*a*(i-1)
|
|
4114
|
+
else:
|
|
4115
|
+
z = two_a ** ((p-9)//16)
|
|
4116
|
+
i = two_a * z*z
|
|
4117
|
+
return z*a*(i-1)
|
|
4118
|
+
|
|
4119
|
+
else:
|
|
4120
|
+
one = a._new_c_from_long(1)
|
|
4121
|
+
r, q = (p-one_Z).val_unit(2)
|
|
4122
|
+
v = a._parent.quadratic_nonresidue()**q
|
|
4123
|
+
|
|
4124
|
+
x = a ** ((q-1)//2)
|
|
4125
|
+
b = a*x*x # a ^ q
|
|
4126
|
+
res = a*x # a ^ ((q-1)/2)
|
|
4127
|
+
|
|
4128
|
+
while b != one:
|
|
4129
|
+
m = 1
|
|
4130
|
+
bpow = b*b
|
|
4131
|
+
while bpow != one:
|
|
4132
|
+
bpow *= bpow
|
|
4133
|
+
m += 1
|
|
4134
|
+
g = v**(one_Z << (r-m-1)) # v^(2^(r-m-1))
|
|
4135
|
+
res *= g
|
|
4136
|
+
b *= g*g
|
|
4137
|
+
return res
|
|
4138
|
+
|
|
4139
|
+
|
|
4140
|
+
def lucas_q1(mm, IntegerMod_abstract P):
|
|
4141
|
+
"""
|
|
4142
|
+
Return `V_k(P, 1)` where `V_k` is the Lucas
|
|
4143
|
+
function defined by the recursive relation.
|
|
4144
|
+
|
|
4145
|
+
`V_k(P, Q) = PV_{k-1}(P, Q) - QV_{k-2}(P, Q)`
|
|
4146
|
+
|
|
4147
|
+
with `V_0 = 2, V_1(P_Q) = P`.
|
|
4148
|
+
|
|
4149
|
+
REFERENCES:
|
|
4150
|
+
|
|
4151
|
+
- [Pos1988]_
|
|
4152
|
+
|
|
4153
|
+
AUTHORS:
|
|
4154
|
+
|
|
4155
|
+
- Robert Bradshaw
|
|
4156
|
+
|
|
4157
|
+
TESTS::
|
|
4158
|
+
|
|
4159
|
+
sage: from sage.rings.finite_rings.integer_mod import lucas_q1
|
|
4160
|
+
sage: all(lucas_q1(k, a) == BinaryRecurrenceSequence(a, -1, 2, a)(k) # needs sage.combinat sage.modules
|
|
4161
|
+
....: for a in Integers(23)
|
|
4162
|
+
....: for k in range(13))
|
|
4163
|
+
True
|
|
4164
|
+
"""
|
|
4165
|
+
if mm == 0:
|
|
4166
|
+
return 2
|
|
4167
|
+
elif mm == 1:
|
|
4168
|
+
return P
|
|
4169
|
+
|
|
4170
|
+
cdef sage.rings.integer.Integer m
|
|
4171
|
+
m = <sage.rings.integer.Integer>mm if isinstance(mm, sage.rings.integer.Integer) else sage.rings.integer.Integer(mm)
|
|
4172
|
+
two = P._new_c_from_long(2)
|
|
4173
|
+
d1 = P
|
|
4174
|
+
d2 = P*P - two
|
|
4175
|
+
|
|
4176
|
+
cdef int j
|
|
4177
|
+
for j from mpz_sizeinbase(m.value, 2)-1 > j > 0:
|
|
4178
|
+
sig_check()
|
|
4179
|
+
if mpz_tstbit(m.value, j):
|
|
4180
|
+
d1 = d1*d2 - P
|
|
4181
|
+
d2 = d2*d2 - two
|
|
4182
|
+
else:
|
|
4183
|
+
d2 = d1*d2 - P
|
|
4184
|
+
d1 = d1*d1 - two
|
|
4185
|
+
if mpz_odd_p(m.value):
|
|
4186
|
+
return d1*d2 - P
|
|
4187
|
+
else:
|
|
4188
|
+
return d1*d1 - two
|
|
4189
|
+
|
|
4190
|
+
|
|
4191
|
+
def lucas(k, P, Q=1, n=None):
|
|
4192
|
+
r"""
|
|
4193
|
+
Return `[V_k(P, Q) \mod n, Q^{\lfloor k/2 \rfloor} \mod n]` where `V_k`
|
|
4194
|
+
is the Lucas function defined by the recursive relation
|
|
4195
|
+
|
|
4196
|
+
.. MATH::
|
|
4197
|
+
|
|
4198
|
+
V_k(P, Q) = P V_{k-1}(P, Q) - Q V_{k-2}(P, Q)
|
|
4199
|
+
|
|
4200
|
+
with `V_0 = 2, V_1 = P`.
|
|
4201
|
+
|
|
4202
|
+
INPUT:
|
|
4203
|
+
|
|
4204
|
+
- ``k`` -- integer; index to compute
|
|
4205
|
+
|
|
4206
|
+
- ``P``, ``Q`` -- integers or modular integers; initial values
|
|
4207
|
+
|
|
4208
|
+
- ``n`` -- integer (optional); modulus to use if ``P`` is not a modular
|
|
4209
|
+
integer
|
|
4210
|
+
|
|
4211
|
+
REFERENCES:
|
|
4212
|
+
|
|
4213
|
+
- [IEEEP1363]_
|
|
4214
|
+
|
|
4215
|
+
AUTHORS:
|
|
4216
|
+
|
|
4217
|
+
- Somindu Chaya Ramanna, Shashank Singh and Srinivas Vivek Venkatesh
|
|
4218
|
+
(2011-09-15, ECC2011 summer school)
|
|
4219
|
+
|
|
4220
|
+
- Robert Bradshaw
|
|
4221
|
+
|
|
4222
|
+
TESTS::
|
|
4223
|
+
|
|
4224
|
+
sage: from sage.rings.finite_rings.integer_mod import lucas
|
|
4225
|
+
sage: p = randint(0,100000)
|
|
4226
|
+
sage: q = randint(0,100000)
|
|
4227
|
+
sage: n = randint(1,100)
|
|
4228
|
+
sage: all(lucas(k, p, q, n)[0] == Mod(lucas_number2(k, p, q), n) # needs sage.combinat sage.libs.gap
|
|
4229
|
+
....: for k in Integers(20))
|
|
4230
|
+
True
|
|
4231
|
+
sage: from sage.rings.finite_rings.integer_mod import lucas
|
|
4232
|
+
sage: p = randint(0,100000)
|
|
4233
|
+
sage: q = randint(0,100000)
|
|
4234
|
+
sage: n = randint(1,100)
|
|
4235
|
+
sage: k = randint(0,100)
|
|
4236
|
+
sage: lucas(k, p, q, n) == [Mod(lucas_number2(k, p, q), n), # needs sage.combinat sage.libs.gap
|
|
4237
|
+
....: Mod(q^(int(k/2)), n)]
|
|
4238
|
+
True
|
|
4239
|
+
|
|
4240
|
+
EXAMPLES::
|
|
4241
|
+
|
|
4242
|
+
sage: [lucas(k,4,5,11)[0] for k in range(30)]
|
|
4243
|
+
[2, 4, 6, 4, 8, 1, 8, 5, 2, 5, 10, 4, 10, 9, 8, 9, 7, 5, 7, 3, 10, 3, 6, 9, 6, 1, 7, 1, 2, 3]
|
|
4244
|
+
|
|
4245
|
+
sage: lucas(20,4,5,11)
|
|
4246
|
+
[10, 1]
|
|
4247
|
+
"""
|
|
4248
|
+
cdef IntegerMod_abstract p,q
|
|
4249
|
+
|
|
4250
|
+
if n is None and not isinstance(P, IntegerMod_abstract):
|
|
4251
|
+
raise ValueError
|
|
4252
|
+
|
|
4253
|
+
if n is None:
|
|
4254
|
+
n = P.modulus()
|
|
4255
|
+
|
|
4256
|
+
if not isinstance(P, IntegerMod_abstract):
|
|
4257
|
+
p = Mod(P,n)
|
|
4258
|
+
else:
|
|
4259
|
+
p = P
|
|
4260
|
+
|
|
4261
|
+
if not isinstance(Q, IntegerMod_abstract):
|
|
4262
|
+
q = Mod(Q,n)
|
|
4263
|
+
else:
|
|
4264
|
+
q = Q
|
|
4265
|
+
|
|
4266
|
+
if k == 0:
|
|
4267
|
+
return [2, 1]
|
|
4268
|
+
elif k == 1:
|
|
4269
|
+
return [p, 1]
|
|
4270
|
+
|
|
4271
|
+
cdef sage.rings.integer.Integer m
|
|
4272
|
+
m = <sage.rings.integer.Integer>k if isinstance(k, sage.rings.integer.Integer) else sage.rings.integer.Integer(k)
|
|
4273
|
+
two = p._new_c_from_long(2)
|
|
4274
|
+
|
|
4275
|
+
v0 = p._new_c_from_long(2)
|
|
4276
|
+
v1 = p
|
|
4277
|
+
q0 = p._new_c_from_long(1)
|
|
4278
|
+
q1 = p._new_c_from_long(1)
|
|
4279
|
+
|
|
4280
|
+
cdef int j
|
|
4281
|
+
for j from mpz_sizeinbase(m.value, 2)-1 >= j >= 0:
|
|
4282
|
+
sig_check()
|
|
4283
|
+
q0 = q0*q1
|
|
4284
|
+
if mpz_tstbit(m.value, j):
|
|
4285
|
+
q1 = q0*Q
|
|
4286
|
+
v0 = v0*v1 - p*q0
|
|
4287
|
+
v1 = v1*v1 - two*q1
|
|
4288
|
+
else:
|
|
4289
|
+
q1 = q0
|
|
4290
|
+
v1 = v0*v1 - p*q0
|
|
4291
|
+
v0 = v0*v0 - two*q0
|
|
4292
|
+
return [v0,q0]
|
|
4293
|
+
|
|
4294
|
+
|
|
4295
|
+
############# Homomorphisms ###############
|
|
4296
|
+
|
|
4297
|
+
cdef class IntegerMod_hom(Morphism):
|
|
4298
|
+
cdef IntegerMod_abstract zero
|
|
4299
|
+
cdef NativeIntStruct modulus
|
|
4300
|
+
|
|
4301
|
+
def __init__(self, parent):
|
|
4302
|
+
Morphism.__init__(self, parent)
|
|
4303
|
+
# we need to use element constructor so that we can register both coercions and conversions using these morphisms.
|
|
4304
|
+
cdef Parent C = self._codomain
|
|
4305
|
+
self.zero = C._element_constructor_(0)
|
|
4306
|
+
self.modulus = C._pyx_order
|
|
4307
|
+
|
|
4308
|
+
cdef dict _extra_slots(self):
|
|
4309
|
+
"""
|
|
4310
|
+
Helper for pickling and copying.
|
|
4311
|
+
|
|
4312
|
+
EXAMPLES::
|
|
4313
|
+
|
|
4314
|
+
sage: R5 = IntegerModRing(5)
|
|
4315
|
+
sage: R15 = IntegerModRing(15)
|
|
4316
|
+
sage: phi = R5.coerce_map_from(R15); phi
|
|
4317
|
+
Natural morphism:
|
|
4318
|
+
From: Ring of integers modulo 15
|
|
4319
|
+
To: Ring of integers modulo 5
|
|
4320
|
+
|
|
4321
|
+
This method helps to implement copying::
|
|
4322
|
+
|
|
4323
|
+
sage: psi = copy(phi); psi
|
|
4324
|
+
Natural morphism:
|
|
4325
|
+
From: Ring of integers modulo 15
|
|
4326
|
+
To: Ring of integers modulo 5
|
|
4327
|
+
sage: psi(R15(7))
|
|
4328
|
+
2
|
|
4329
|
+
"""
|
|
4330
|
+
slots = Morphism._extra_slots(self)
|
|
4331
|
+
slots['zero'] = self.zero
|
|
4332
|
+
slots['modulus'] = self.modulus
|
|
4333
|
+
return slots
|
|
4334
|
+
|
|
4335
|
+
cdef _update_slots(self, dict _slots):
|
|
4336
|
+
"""
|
|
4337
|
+
Helper for pickling and copying.
|
|
4338
|
+
|
|
4339
|
+
EXAMPLES::
|
|
4340
|
+
|
|
4341
|
+
sage: R5 = IntegerModRing(5)
|
|
4342
|
+
sage: R15 = IntegerModRing(15)
|
|
4343
|
+
sage: phi = R5.coerce_map_from(R15); phi
|
|
4344
|
+
Natural morphism:
|
|
4345
|
+
From: Ring of integers modulo 15
|
|
4346
|
+
To: Ring of integers modulo 5
|
|
4347
|
+
|
|
4348
|
+
This method helps to implement copying.
|
|
4349
|
+
::
|
|
4350
|
+
|
|
4351
|
+
sage: psi = copy(phi); psi
|
|
4352
|
+
Natural morphism:
|
|
4353
|
+
From: Ring of integers modulo 15
|
|
4354
|
+
To: Ring of integers modulo 5
|
|
4355
|
+
sage: psi(R15(7))
|
|
4356
|
+
2
|
|
4357
|
+
"""
|
|
4358
|
+
Morphism._update_slots(self, _slots)
|
|
4359
|
+
self.zero = _slots['zero']
|
|
4360
|
+
self.modulus = _slots['modulus']
|
|
4361
|
+
|
|
4362
|
+
cpdef Element _call_(self, x):
|
|
4363
|
+
return IntegerMod(self._codomain, x)
|
|
4364
|
+
|
|
4365
|
+
cdef class IntegerMod_to_IntegerMod(IntegerMod_hom):
|
|
4366
|
+
"""
|
|
4367
|
+
Very fast IntegerMod to IntegerMod homomorphism.
|
|
4368
|
+
|
|
4369
|
+
EXAMPLES::
|
|
4370
|
+
|
|
4371
|
+
sage: from sage.rings.finite_rings.integer_mod import IntegerMod_to_IntegerMod
|
|
4372
|
+
sage: Rs = [Integers(3**k) for k in range(1,30,5)]
|
|
4373
|
+
sage: [type(R(0)) for R in Rs]
|
|
4374
|
+
[<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>,
|
|
4375
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>,
|
|
4376
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>,
|
|
4377
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>,
|
|
4378
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>,
|
|
4379
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>]
|
|
4380
|
+
sage: fs = [IntegerMod_to_IntegerMod(S, R)
|
|
4381
|
+
....: for R in Rs for S in Rs if S is not R and S.order() > R.order()]
|
|
4382
|
+
sage: all(f(-1) == f.codomain()(-1) for f in fs)
|
|
4383
|
+
True
|
|
4384
|
+
sage: [f(-1) for f in fs]
|
|
4385
|
+
[2, 2, 2, 2, 2, 728, 728, 728, 728, 177146, 177146, 177146, 43046720, 43046720, 10460353202]
|
|
4386
|
+
"""
|
|
4387
|
+
def __init__(self, R, S):
|
|
4388
|
+
if not S.order().divides(R.order()):
|
|
4389
|
+
raise TypeError("No natural coercion from %s to %s" % (R, S))
|
|
4390
|
+
import sage.categories.homset
|
|
4391
|
+
IntegerMod_hom.__init__(self, sage.categories.homset.Hom(R, S))
|
|
4392
|
+
|
|
4393
|
+
cpdef Element _call_(self, x):
|
|
4394
|
+
cdef IntegerMod_abstract a
|
|
4395
|
+
zero = <IntegerMod_abstract>self.zero
|
|
4396
|
+
cdef unsigned long value
|
|
4397
|
+
if isinstance(x, IntegerMod_int):
|
|
4398
|
+
value = (<IntegerMod_int>x).ivalue
|
|
4399
|
+
value %= <unsigned long>self.modulus.int32
|
|
4400
|
+
return zero._new_c_fast(value)
|
|
4401
|
+
elif isinstance(x, IntegerMod_int64):
|
|
4402
|
+
value = (<IntegerMod_int64>x).ivalue
|
|
4403
|
+
value %= <unsigned long>self.modulus.int64
|
|
4404
|
+
return zero._new_c_fast(value)
|
|
4405
|
+
a = zero._new_c_fast(0)
|
|
4406
|
+
a.set_from_mpz((<IntegerMod_gmp?>x).value)
|
|
4407
|
+
return a
|
|
4408
|
+
|
|
4409
|
+
def _repr_type(self):
|
|
4410
|
+
return "Natural"
|
|
4411
|
+
|
|
4412
|
+
def is_surjective(self):
|
|
4413
|
+
r"""
|
|
4414
|
+
Return whether this morphism is surjective.
|
|
4415
|
+
|
|
4416
|
+
EXAMPLES::
|
|
4417
|
+
|
|
4418
|
+
sage: Zmod(4).hom(Zmod(2)).is_surjective()
|
|
4419
|
+
True
|
|
4420
|
+
"""
|
|
4421
|
+
return True
|
|
4422
|
+
|
|
4423
|
+
def is_injective(self):
|
|
4424
|
+
r"""
|
|
4425
|
+
Return whether this morphism is injective.
|
|
4426
|
+
|
|
4427
|
+
EXAMPLES::
|
|
4428
|
+
|
|
4429
|
+
sage: Zmod(4).hom(Zmod(2)).is_injective()
|
|
4430
|
+
False
|
|
4431
|
+
"""
|
|
4432
|
+
return self.domain().order() == self.codomain().order()
|
|
4433
|
+
|
|
4434
|
+
cdef class Integer_to_IntegerMod(IntegerMod_hom):
|
|
4435
|
+
r"""
|
|
4436
|
+
Fast `\ZZ \rightarrow \ZZ/n\ZZ` morphism.
|
|
4437
|
+
|
|
4438
|
+
EXAMPLES:
|
|
4439
|
+
|
|
4440
|
+
We make sure it works for every type.
|
|
4441
|
+
|
|
4442
|
+
::
|
|
4443
|
+
|
|
4444
|
+
sage: from sage.rings.finite_rings.integer_mod import Integer_to_IntegerMod
|
|
4445
|
+
sage: Rs = [Integers(10), Integers(10^5), Integers(10^10)]
|
|
4446
|
+
sage: [type(R(0)) for R in Rs]
|
|
4447
|
+
[<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>,
|
|
4448
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>,
|
|
4449
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>]
|
|
4450
|
+
sage: fs = [Integer_to_IntegerMod(R) for R in Rs]
|
|
4451
|
+
sage: [f(-1) for f in fs]
|
|
4452
|
+
[9, 99999, 9999999999]
|
|
4453
|
+
"""
|
|
4454
|
+
def __init__(self, R):
|
|
4455
|
+
import sage.categories.homset
|
|
4456
|
+
IntegerMod_hom.__init__(self, sage.categories.homset.Hom(integer_ring.ZZ, R))
|
|
4457
|
+
|
|
4458
|
+
cpdef Element _call_(self, x):
|
|
4459
|
+
cdef IntegerMod_abstract a
|
|
4460
|
+
cdef Py_ssize_t res
|
|
4461
|
+
if self.modulus.table is not None:
|
|
4462
|
+
res = x % self.modulus.int64
|
|
4463
|
+
if res < 0:
|
|
4464
|
+
res += self.modulus.int64
|
|
4465
|
+
a = self.modulus.table[res]
|
|
4466
|
+
# if a._parent is not self._codomain:
|
|
4467
|
+
a._parent = self._codomain
|
|
4468
|
+
return a
|
|
4469
|
+
else:
|
|
4470
|
+
a = self.zero._new_c_from_long(0)
|
|
4471
|
+
a.set_from_mpz((<Integer>x).value)
|
|
4472
|
+
return a
|
|
4473
|
+
|
|
4474
|
+
def _repr_type(self):
|
|
4475
|
+
return "Natural"
|
|
4476
|
+
|
|
4477
|
+
def section(self):
|
|
4478
|
+
return IntegerMod_to_Integer(self._codomain)
|
|
4479
|
+
|
|
4480
|
+
def is_surjective(self):
|
|
4481
|
+
r"""
|
|
4482
|
+
Return whether this morphism is surjective.
|
|
4483
|
+
|
|
4484
|
+
EXAMPLES::
|
|
4485
|
+
|
|
4486
|
+
sage: ZZ.hom(Zmod(2)).is_surjective()
|
|
4487
|
+
True
|
|
4488
|
+
"""
|
|
4489
|
+
return True
|
|
4490
|
+
|
|
4491
|
+
def is_injective(self):
|
|
4492
|
+
r"""
|
|
4493
|
+
Return whether this morphism is injective.
|
|
4494
|
+
|
|
4495
|
+
EXAMPLES::
|
|
4496
|
+
|
|
4497
|
+
sage: ZZ.hom(Zmod(2)).is_injective()
|
|
4498
|
+
False
|
|
4499
|
+
"""
|
|
4500
|
+
return False
|
|
4501
|
+
|
|
4502
|
+
|
|
4503
|
+
cdef class IntegerMod_to_Integer(Map):
|
|
4504
|
+
"""
|
|
4505
|
+
Map to lift elements to :class:`~sage.rings.integer.Integer`.
|
|
4506
|
+
|
|
4507
|
+
EXAMPLES::
|
|
4508
|
+
|
|
4509
|
+
sage: ZZ.convert_map_from(GF(2))
|
|
4510
|
+
Lifting map:
|
|
4511
|
+
From: Finite Field of size 2
|
|
4512
|
+
To: Integer Ring
|
|
4513
|
+
"""
|
|
4514
|
+
def __init__(self, R):
|
|
4515
|
+
"""
|
|
4516
|
+
TESTS:
|
|
4517
|
+
|
|
4518
|
+
Lifting maps are morphisms in the category of sets (see
|
|
4519
|
+
:issue:`15618`)::
|
|
4520
|
+
|
|
4521
|
+
sage: ZZ.convert_map_from(GF(2)).parent()
|
|
4522
|
+
Set of Morphisms from Finite Field of size 2 to Integer Ring in Category of sets
|
|
4523
|
+
"""
|
|
4524
|
+
import sage.categories.homset
|
|
4525
|
+
from sage.categories.sets_cat import Sets
|
|
4526
|
+
Morphism.__init__(self, sage.categories.homset.Hom(R, integer_ring.ZZ, Sets()))
|
|
4527
|
+
|
|
4528
|
+
cpdef Element _call_(self, x):
|
|
4529
|
+
cdef Integer ans = Integer.__new__(Integer)
|
|
4530
|
+
if isinstance(x, IntegerMod_gmp):
|
|
4531
|
+
mpz_set(ans.value, (<IntegerMod_gmp>x).value)
|
|
4532
|
+
elif isinstance(x, IntegerMod_int):
|
|
4533
|
+
mpz_set_ui(ans.value, (<IntegerMod_int>x).ivalue)
|
|
4534
|
+
elif isinstance(x, IntegerMod_int64):
|
|
4535
|
+
mpz_set_ui(ans.value, (<IntegerMod_int64>x).ivalue)
|
|
4536
|
+
return ans
|
|
4537
|
+
|
|
4538
|
+
def _repr_type(self):
|
|
4539
|
+
return "Lifting"
|
|
4540
|
+
|
|
4541
|
+
|
|
4542
|
+
cdef class Int_to_IntegerMod(IntegerMod_hom):
|
|
4543
|
+
"""
|
|
4544
|
+
EXAMPLES:
|
|
4545
|
+
|
|
4546
|
+
We make sure it works for every type.
|
|
4547
|
+
|
|
4548
|
+
::
|
|
4549
|
+
|
|
4550
|
+
sage: from sage.rings.finite_rings.integer_mod import Int_to_IntegerMod
|
|
4551
|
+
sage: Rs = [Integers(2**k) for k in range(1,50,10)]
|
|
4552
|
+
sage: [type(R(0)) for R in Rs]
|
|
4553
|
+
[<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>,
|
|
4554
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>,
|
|
4555
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_int64'>,
|
|
4556
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>,
|
|
4557
|
+
<class 'sage.rings.finite_rings.integer_mod.IntegerMod_gmp'>]
|
|
4558
|
+
sage: fs = [Int_to_IntegerMod(R) for R in Rs]
|
|
4559
|
+
sage: [f(-1) for f in fs]
|
|
4560
|
+
[1, 2047, 2097151, 2147483647, 2199023255551]
|
|
4561
|
+
"""
|
|
4562
|
+
def __init__(self, R):
|
|
4563
|
+
import sage.categories.homset
|
|
4564
|
+
from sage.sets.pythonclass import Set_PythonType
|
|
4565
|
+
IntegerMod_hom.__init__(self, sage.categories.homset.Hom(Set_PythonType(int), R))
|
|
4566
|
+
|
|
4567
|
+
cpdef Element _call_(self, x):
|
|
4568
|
+
cdef IntegerMod_abstract a
|
|
4569
|
+
zero = <IntegerMod_abstract>self.zero
|
|
4570
|
+
|
|
4571
|
+
cdef long res
|
|
4572
|
+
cdef int err
|
|
4573
|
+
|
|
4574
|
+
if not integer_check_long_py(x, &res, &err):
|
|
4575
|
+
raise TypeError(f"{x} is not an integer")
|
|
4576
|
+
|
|
4577
|
+
if not err:
|
|
4578
|
+
return zero._new_c_from_long(res)
|
|
4579
|
+
|
|
4580
|
+
cdef Integer z = Integer(x)
|
|
4581
|
+
a = zero._new_c_fast(0)
|
|
4582
|
+
a.set_from_mpz(z.value)
|
|
4583
|
+
return a
|
|
4584
|
+
|
|
4585
|
+
def _repr_type(self):
|
|
4586
|
+
return "Native"
|