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.
Files changed (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
sage/groups/generic.py ADDED
@@ -0,0 +1,1733 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ """
3
+ Miscellaneous generic functions
4
+
5
+ A collection of functions implementing generic algorithms in arbitrary
6
+ groups, including additive and multiplicative groups.
7
+
8
+ In all cases the group operation is specified by a parameter
9
+ ``operation``, which is a string either one of the set of
10
+ ``multiplication_names`` or ``addition_names`` specified below, or other.
11
+ In the latter case, the caller must provide an identity, ``inverse()`` and
12
+ ``op()`` functions.
13
+
14
+ ::
15
+
16
+ multiplication_names = ('multiplication', 'times', 'product', '*')
17
+ addition_names = ('addition', 'plus', 'sum', '+')
18
+
19
+ Also included are a generic function for computing multiples (or
20
+ powers), and an iterator for general multiples and powers.
21
+
22
+ EXAMPLES:
23
+
24
+ Some examples in the multiplicative group of a finite field:
25
+
26
+ - Discrete logs::
27
+
28
+ sage: # needs sage.rings.finite_rings
29
+ sage: K = GF(3^6,'b')
30
+ sage: b = K.gen()
31
+ sage: a = b^210
32
+ sage: discrete_log(a, b, K.order() - 1)
33
+ 210
34
+
35
+ - Linear relation finder::
36
+
37
+ sage: # needs sage.rings.finite_rings
38
+ sage: F.<a> = GF(3^6,'a')
39
+ sage: a.multiplicative_order().factor()
40
+ 2^3 * 7 * 13
41
+ sage: b = a^7
42
+ sage: c = a^13
43
+ sage: linear_relation(b,c,'*')
44
+ (13, 7)
45
+ sage: b^13 == c^7
46
+ True
47
+
48
+ - Orders of elements::
49
+
50
+ sage: # needs sage.rings.finite_rings
51
+ sage: from sage.groups.generic import order_from_multiple, order_from_bounds
52
+ sage: k.<a> = GF(5^5)
53
+ sage: b = a^4
54
+ sage: order_from_multiple(b, 5^5 - 1, operation='*')
55
+ 781
56
+ sage: order_from_bounds(b, (5^4, 5^5), operation='*')
57
+ 781
58
+
59
+ Some examples in the group of points of an elliptic curve over a finite field:
60
+
61
+ - Discrete logs::
62
+
63
+ sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
64
+ sage: F = GF(37^2,'a')
65
+ sage: E = EllipticCurve(F,[1,1])
66
+ sage: F.<a> = GF(37^2,'a')
67
+ sage: E = EllipticCurve(F,[1,1])
68
+ sage: P = E(25*a + 16 , 15*a + 7 )
69
+ sage: P.order()
70
+ 672
71
+ sage: Q = 39*P; Q
72
+ (36*a + 32 : 5*a + 12 : 1)
73
+ sage: discrete_log(Q, P, P.order(), operation='+')
74
+ 39
75
+
76
+ - Linear relation finder::
77
+
78
+ sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
79
+ sage: F.<a> = GF(3^6,'a')
80
+ sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1])
81
+ sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2 , 0)
82
+ sage: Q = E(2*a^3 + 2*a^2 + 2*a , a^3 + 2*a^2 + 1)
83
+ sage: linear_relation(P,Q,'+')
84
+ (1, 2)
85
+ sage: P == 2*Q
86
+ True
87
+
88
+ - Orders of elements::
89
+
90
+ sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
91
+ sage: from sage.groups.generic import order_from_multiple, order_from_bounds
92
+ sage: k.<a> = GF(5^5)
93
+ sage: E = EllipticCurve(k,[2,4])
94
+ sage: P = E(3*a^4 + 3*a, 2*a + 1)
95
+ sage: M = E.cardinality(); M
96
+ 3227
97
+ sage: plist = M.prime_factors()
98
+ sage: order_from_multiple(P, M, plist, operation='+')
99
+ 3227
100
+ sage: Q = E(0,2)
101
+ sage: order_from_multiple(Q, M, plist, operation='+')
102
+ 7
103
+ sage: order_from_bounds(Q, Hasse_bounds(5^5), operation='+')
104
+ 7
105
+ """
106
+
107
+ # ****************************************************************************
108
+ # Copyright (C) 2008 William Stein <wstein@gmail.com>
109
+ # John Cremona <john.cremona@gmail.com>
110
+ #
111
+ # This program is free software: you can redistribute it and/or modify
112
+ # it under the terms of the GNU General Public License as published by
113
+ # the Free Software Foundation, either version 2 of the License, or
114
+ # (at your option) any later version.
115
+ # https://www.gnu.org/licenses/
116
+ # ****************************************************************************
117
+
118
+ from copy import copy
119
+
120
+ from sage.arith.misc import integer_ceil, integer_floor, xlcm
121
+ from sage.arith.srange import xsrange
122
+ from sage.misc.misc_c import prod
123
+ import sage.rings.integer_ring as integer_ring
124
+ import sage.rings.integer
125
+
126
+ #
127
+ # Lists of names (as strings) which the user may use to identify one
128
+ # of the standard operations:
129
+ #
130
+ multiplication_names = ('multiplication', 'times', 'product', '*')
131
+ addition_names = ('addition', 'plus', 'sum', '+')
132
+
133
+
134
+ def multiple(a, n, operation='*', identity=None, inverse=None, op=None):
135
+ r"""
136
+ Return either `na` or `a^n`, where `n` is any integer and `a` is
137
+ a Python object on which a group operation such as addition or
138
+ multiplication is defined. Uses the standard binary algorithm.
139
+
140
+ INPUT: See the documentation for ``discrete_logarithm()``.
141
+
142
+ EXAMPLES::
143
+
144
+ sage: multiple(2, 5)
145
+ 32
146
+ sage: multiple(RealField()('2.5'), 4) # needs sage.rings.real_mpfr
147
+ 39.0625000000000
148
+ sage: multiple(2, -3)
149
+ 1/8
150
+ sage: multiple(2, 100, '+') == 100*2
151
+ True
152
+ sage: multiple(2, 100) == 2**100
153
+ True
154
+ sage: multiple(2, -100,) == 2**-100
155
+ True
156
+ sage: R.<x> = ZZ[]
157
+ sage: multiple(x, 100)
158
+ x^100
159
+ sage: multiple(x, 100, '+')
160
+ 100*x
161
+ sage: multiple(x, -10)
162
+ 1/x^10
163
+
164
+ Idempotence is detected, making the following fast::
165
+
166
+ sage: multiple(1, 10^1000)
167
+ 1
168
+
169
+ sage: # needs database_cremona_mini_ellcurve sage.schemes
170
+ sage: E = EllipticCurve('389a1')
171
+ sage: P = E(-1,1)
172
+ sage: multiple(P, 10, '+')
173
+ (645656132358737542773209599489/22817025904944891235367494656 :
174
+ 525532176124281192881231818644174845702936831/3446581505217248068297884384990762467229696 : 1)
175
+ sage: multiple(P, -10, '+')
176
+ (645656132358737542773209599489/22817025904944891235367494656 :
177
+ -528978757629498440949529703029165608170166527/3446581505217248068297884384990762467229696 : 1)
178
+ """
179
+ from operator import inv, mul, neg, add
180
+
181
+ if operation in multiplication_names:
182
+ identity = a.parent().one()
183
+ inverse = inv
184
+ op = mul
185
+ elif operation in addition_names:
186
+ identity = a.parent().zero()
187
+ inverse = neg
188
+ op = add
189
+ else:
190
+ if identity is None or inverse is None or op is None:
191
+ raise ValueError("identity, inverse and operation must all be specified")
192
+
193
+ if n == 0:
194
+ return identity
195
+
196
+ if n < 0:
197
+ n = -n
198
+ a = inverse(a)
199
+
200
+ if n == 1:
201
+ return a
202
+
203
+ # check for idempotence, and store the result otherwise
204
+ aa = op(a, a)
205
+ if aa == a:
206
+ return a
207
+
208
+ if n == 2:
209
+ return aa
210
+
211
+ if n == 3:
212
+ return op(aa, a)
213
+
214
+ if n == 4:
215
+ return op(aa, aa)
216
+
217
+ # since we've computed a^2, let's start squaring there
218
+ # so, let's keep the least-significant bit around, just
219
+ # in case.
220
+ m = n & 1
221
+ n = n >> 1
222
+
223
+ # One multiplication can be saved by starting with
224
+ # the second-smallest power needed rather than with 1
225
+ # we've already squared a, so let's start there.
226
+ apow = aa
227
+ while n & 1 == 0:
228
+ apow = op(apow, apow)
229
+ n = n >> 1
230
+ power = apow
231
+ n = n >> 1
232
+
233
+ # now multiply that least-significant bit in...
234
+ if m:
235
+ power = op(power, a)
236
+
237
+ # and this is straight from the book.
238
+ while n != 0:
239
+ apow = op(apow, apow)
240
+ if n & 1 != 0:
241
+ power = op(power, apow)
242
+ n = n >> 1
243
+
244
+ return power
245
+
246
+
247
+ #
248
+ # Generic iterator for looping through multiples or powers
249
+ #
250
+
251
+ class multiples:
252
+ r"""
253
+ Return an iterator which runs through ``P0+i*P`` for ``i`` in ``range(n)``.
254
+
255
+ ``P`` and ``P0`` must be Sage objects in some group; if the operation is
256
+ multiplication then the returned values are instead ``P0*P**i``.
257
+
258
+ EXAMPLES::
259
+
260
+ sage: list(multiples(1, 10))
261
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
262
+ sage: list(multiples(1, 10, 100))
263
+ [100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
264
+
265
+ sage: # needs database_cremona_mini_ellcurve sage.schemes
266
+ sage: E = EllipticCurve('389a1')
267
+ sage: P = E(-1,1)
268
+ sage: for Q in multiples(P, 5): print((Q, Q.height()/P.height()))
269
+ ((0 : 1 : 0), 0.000000000000000)
270
+ ((-1 : 1 : 1), 1.00000000000000)
271
+ ((10/9 : -35/27 : 1), 4.00000000000000)
272
+ ((26/361 : -5720/6859 : 1), 9.00000000000000)
273
+ ((47503/16641 : 9862190/2146689 : 1), 16.0000000000000)
274
+
275
+ sage: R.<x> = ZZ[]
276
+ sage: list(multiples(x, 5))
277
+ [0, x, 2*x, 3*x, 4*x]
278
+ sage: list(multiples(x, 5, operation='*'))
279
+ [1, x, x^2, x^3, x^4]
280
+ sage: list(multiples(x, 5, indexed=True))
281
+ [(0, 0), (1, x), (2, 2*x), (3, 3*x), (4, 4*x)]
282
+ sage: list(multiples(x, 5, indexed=True, operation='*'))
283
+ [(0, 1), (1, x), (2, x^2), (3, x^3), (4, x^4)]
284
+ sage: for i,y in multiples(x, 5, indexed=True): print("%s times %s = %s"%(i,x,y))
285
+ 0 times x = 0
286
+ 1 times x = x
287
+ 2 times x = 2*x
288
+ 3 times x = 3*x
289
+ 4 times x = 4*x
290
+
291
+ sage: for i,n in multiples(3, 5, indexed=True, operation='*'):
292
+ ....: print("3 to the power %s = %s" % (i,n))
293
+ 3 to the power 0 = 1
294
+ 3 to the power 1 = 3
295
+ 3 to the power 2 = 9
296
+ 3 to the power 3 = 27
297
+ 3 to the power 4 = 81
298
+ """
299
+ def __init__(self, P, n, P0=None, indexed=False, operation='+', op=None):
300
+ """
301
+ Create a multiples iterator.
302
+
303
+ INPUT:
304
+
305
+ - ``P`` -- step value; any Sage object on which a binary operation is defined
306
+ - ``n`` -- number of multiples; nonnegative integer
307
+ - ``P0`` -- offset (default: 0); Sage object which can be 'added' to P
308
+ - ``indexed`` -- boolean (default: ``False``)
309
+
310
+ If ``indexed==False``, then the iterator delivers ``P0+i*P``
311
+ (if ``operation=='+'``) or ``P0*P**i`` (if
312
+ ``operation=='*'``), for ``i`` in ``range(n)``.
313
+
314
+ If ``indexed==True`` then the iterator delivers tuples
315
+ ``(i, P0+i*P)`` or ``(i, P0*P**i)``.
316
+
317
+ - ``operation`` -- string: ``'+'`` (the default) or ``'*'`` or other.
318
+
319
+ If other, a function ``op()`` must be supplied (a function
320
+ of 2 arguments) defining the group binary operation; also
321
+ ``P0`` must be supplied.
322
+ """
323
+ if n < 0:
324
+ raise ValueError('n cannot be negative in multiples')
325
+
326
+ from operator import mul, add
327
+
328
+ if operation in multiplication_names:
329
+ if P0 is None:
330
+ P0 = P.parent().one()
331
+ self.op = mul
332
+ elif operation in addition_names:
333
+ if P0 is None:
334
+ P0 = P.parent().zero()
335
+ self.op = add
336
+ else:
337
+ if P0 is None:
338
+ raise ValueError("P0 must be supplied when operation is neither addition nor multiplication")
339
+ if op is None:
340
+ raise ValueError("op() must both be supplied when operation is neither addition nor multiplication")
341
+ self.op = op
342
+
343
+ self.P = copy(P)
344
+ self.Q = copy(P0)
345
+ if self.P is None or self.Q is None:
346
+ raise ValueError("P and Q must not be None")
347
+ self.i = 0
348
+ self.bound = n
349
+ self.indexed = indexed
350
+
351
+ def __next__(self):
352
+ """
353
+ Return the next item in this multiples iterator.
354
+ """
355
+ if self.i >= self.bound:
356
+ raise StopIteration
357
+ i = self.i
358
+ val = self.Q
359
+ self.i += 1
360
+ self.Q = self.op(self.Q, self.P)
361
+ if self.indexed:
362
+ return (i, val)
363
+ else:
364
+ return val
365
+
366
+ next = __next__
367
+
368
+ def __iter__(self):
369
+ """
370
+ Standard member function making this class an iterator.
371
+ """
372
+ return self
373
+
374
+
375
+ def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None):
376
+ r"""
377
+ Totally generic discrete baby-step giant-step function.
378
+
379
+ Solves `na=b` (or `a^n=b`) with `lb\le n\le ub` where ``bounds==(lb,ub)``,
380
+ raising an error if no such `n` exists.
381
+
382
+ `a` and `b` must be elements of some group with given identity,
383
+ inverse of ``x`` given by ``inverse(x)``, and group operation on
384
+ ``x``, ``y`` by ``op(x,y)``.
385
+
386
+ If operation is '*' or '+' then the other
387
+ arguments are provided automatically; otherwise they must be
388
+ provided by the caller.
389
+
390
+ INPUT:
391
+
392
+ - ``a`` -- group element
393
+ - ``b`` -- group element
394
+ - ``bounds`` -- a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper``
395
+ - ``operation`` -- string: ``'*'``, ``'+'``, other
396
+ - ``identity`` -- the identity element of the group
397
+ - ``inverse`` -- function of 1 argument ``x``, returning inverse of ``x``
398
+ - ``op`` -- function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group
399
+
400
+ OUTPUT:
401
+
402
+ An integer `n` such that `a^n = b` (or `na = b`). If no
403
+ such `n` exists, this function raises a :exc:`ValueError` exception.
404
+
405
+ .. NOTE::
406
+
407
+ This is a generalization of discrete logarithm. One
408
+ situation where this version is useful is to find the order of
409
+ an element in a group where we only have bounds on the group
410
+ order (see the elliptic curve example below).
411
+
412
+ ALGORITHM: Baby step giant step. Time and space are soft
413
+ `O(\sqrt{n})` where `n` is the difference between upper and lower
414
+ bounds.
415
+
416
+ EXAMPLES::
417
+
418
+ sage: from sage.groups.generic import bsgs
419
+ sage: b = Mod(2,37); a = b^20
420
+ sage: bsgs(b, a, (0, 36))
421
+ 20
422
+
423
+ sage: p = next_prime(10^20) # needs sage.libs.pari
424
+ sage: a = Mod(2,p); b = a^(10^25) # needs sage.libs.pari
425
+ sage: bsgs(a, b, (10^25 - 10^6, 10^25 + 10^6)) == 10^25 # needs sage.libs.pari
426
+ True
427
+
428
+ sage: # needs sage.rings.finite_rings
429
+ sage: K = GF(3^6,'b')
430
+ sage: a = K.gen()
431
+ sage: b = a^210
432
+ sage: bsgs(a, b, (0, K.order() - 1))
433
+ 210
434
+
435
+ sage: K.<z> = CyclotomicField(230) # needs sage.rings.number_field
436
+ sage: w = z^500 # needs sage.rings.number_field
437
+ sage: bsgs(z, w, (0, 229)) # needs sage.rings.number_field
438
+ 40
439
+
440
+ An additive example in an elliptic curve group::
441
+
442
+ sage: # needs sage.rings.finite_rings sage.schemes
443
+ sage: F.<a> = GF(37^5)
444
+ sage: E = EllipticCurve(F, [1,1])
445
+ sage: P = E.lift_x(a); P
446
+ (a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)
447
+
448
+ This will return a multiple of the order of P::
449
+
450
+ sage: bsgs(P, P.parent().zero(), Hasse_bounds(F.order()), operation='+') # needs sage.rings.finite_rings sage.schemes
451
+ 69327408
452
+
453
+ AUTHOR:
454
+
455
+ - John Cremona (2008-03-15)
456
+ """
457
+ Z = integer_ring.ZZ
458
+
459
+ from operator import inv, mul, neg, add
460
+
461
+ if operation in multiplication_names:
462
+ identity = a.parent().one()
463
+ inverse = inv
464
+ op = mul
465
+ elif operation in addition_names:
466
+ # Should this be replaced with .zero()? With an extra AttributeError handler?
467
+ identity = a.parent().zero()
468
+ inverse = neg
469
+ op = add
470
+ else:
471
+ if identity is None or inverse is None or op is None:
472
+ raise ValueError("identity, inverse and operation must be given")
473
+
474
+ lb, ub = bounds
475
+ if lb < 0 or ub < lb:
476
+ raise ValueError("bsgs() requires 0<=lb<=ub")
477
+
478
+ if a == identity and b != identity:
479
+ raise ValueError("no solution in bsgs()")
480
+
481
+ ran = 1 + ub - lb # the length of the interval
482
+
483
+ mult = lambda x, y: multiple(x, y, operation=operation, identity=identity, inverse=inverse, op=op)
484
+ c = op(inverse(b), mult(a, lb))
485
+
486
+ if ran < 30: # use simple search for small ranges
487
+ d = c
488
+ # for i,d in multiples(a,ran,c,indexed=True,operation=operation):
489
+ for i0 in range(ran):
490
+ i = lb + i0
491
+ if identity == d: # identity == b^(-1)*a^i, so return i
492
+ return Z(i)
493
+ d = op(a, d)
494
+ raise ValueError("no solution in bsgs()")
495
+
496
+ m = ran.isqrt() + 1 # we need sqrt(ran) rounded up
497
+ table = {} # will hold pairs (a^(lb+i),lb+i) for i in range(m)
498
+
499
+ d = c
500
+ for i0 in xsrange(m):
501
+ i = lb + i0
502
+ if identity == d: # identity == b^(-1)*a^i, so return i
503
+ return Z(i)
504
+ table[d] = i
505
+ d = op(d, a)
506
+
507
+ c = op(c, inverse(d)) # this is now a**(-m)
508
+ d = identity
509
+ for i in xsrange(m):
510
+ j = table.get(d)
511
+ if j is not None: # then d == b*a**(-i*m) == a**j
512
+ return Z(i * m + j)
513
+ d = op(c, d)
514
+
515
+ raise ValueError("log of %s to the base %s does not exist in %s" % (b, a, bounds))
516
+
517
+
518
+ def discrete_log_rho(a, base, ord=None, operation='*', identity=None, inverse=None, op=None, hash_function=hash):
519
+ """
520
+ Pollard Rho algorithm for computing discrete logarithm in cyclic
521
+ group of prime order.
522
+ If the group order is very small it falls back to the baby step giant step
523
+ algorithm.
524
+
525
+ INPUT:
526
+
527
+ - ``a`` -- a group element
528
+ - ``base`` -- a group element
529
+ - ``ord`` -- the order of ``base`` or ``None``, in this case we try
530
+ to compute it
531
+ - ``operation`` -- string (default: ``'*'``); denoting whether we
532
+ are in an additive group or a multiplicative one
533
+ - ``identity`` -- the group's identity
534
+ - ``inverse`` -- function of 1 argument ``x``, returning inverse of ``x``
535
+ - ``op`` -- function of 2 arguments ``x``, ``y``, returning ``x*y`` in the group
536
+ - ``hash_function`` -- having an efficient hash function is critical
537
+ for this algorithm (see examples)
538
+
539
+ OUTPUT: integer `n` such that `a = base^n` (or `a = n*base`)
540
+
541
+ ALGORITHM: Pollard rho for discrete logarithm, adapted from the
542
+ article of Edlyn Teske, 'A space efficient algorithm for group
543
+ structure computation'.
544
+
545
+ EXAMPLES::
546
+
547
+ sage: F.<a> = GF(2^13) # needs sage.rings.finite_rings
548
+ sage: g = F.gen() # needs sage.rings.finite_rings
549
+ sage: discrete_log_rho(g^1234, g) # needs sage.rings.finite_rings
550
+ 1234
551
+
552
+ sage: # needs sage.rings.finite_rings sage.schemes
553
+ sage: F.<a> = GF(37^5)
554
+ sage: E = EllipticCurve(F, [1,1])
555
+ sage: G = (3*31*2^4)*E.lift_x(a)
556
+ sage: discrete_log_rho(12345*G, G, ord=46591, operation='+')
557
+ 12345
558
+
559
+ It also works with matrices::
560
+
561
+ sage: A = matrix(GF(50021), [[10577, 23999, 28893], # needs sage.modules sage.rings.finite_rings
562
+ ....: [14601, 41019, 30188],
563
+ ....: [3081, 736, 27092]])
564
+ sage: discrete_log_rho(A^1234567, A) # needs sage.modules sage.rings.finite_rings
565
+ 1234567
566
+
567
+ Beware, the order must be prime::
568
+
569
+ sage: I = IntegerModRing(171980)
570
+ sage: discrete_log_rho(I(2), I(3)) # needs sage.libs.pari
571
+ Traceback (most recent call last):
572
+ ...
573
+ ValueError: for Pollard rho algorithm the order of the group must be prime
574
+
575
+ If it fails to find a suitable logarithm, it raises a :exc:`ValueError`::
576
+
577
+ sage: I = IntegerModRing(171980)
578
+ sage: discrete_log_rho(I(31002), I(15501)) # needs sage.libs.pari
579
+ Traceback (most recent call last):
580
+ ...
581
+ ValueError: Pollard rho algorithm failed to find a logarithm
582
+
583
+ The main limitation on the hash function is that we don't want to have
584
+ ``hash(x*y) == hash(x) + hash(y)``::
585
+
586
+ sage: # needs sage.libs.pari
587
+ sage: I = IntegerModRing(next_prime(2^23))
588
+ sage: def test():
589
+ ....: try:
590
+ ....: discrete_log_rho(I(123456), I(1), operation='+')
591
+ ....: except Exception:
592
+ ....: print("FAILURE")
593
+ sage: test() # random failure
594
+ FAILURE
595
+
596
+ If this happens, we can provide a better hash function::
597
+
598
+ sage: discrete_log_rho(I(123456), I(1), operation='+', # needs sage.libs.pari
599
+ ....: hash_function=lambda x: hash(x*x))
600
+ 123456
601
+
602
+ AUTHOR:
603
+
604
+ - Yann Laigle-Chapuy (2009-09-05)
605
+ """
606
+ from sage.rings.integer import Integer
607
+ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
608
+ from operator import mul, add, pow
609
+
610
+ # should be reasonable choices
611
+ partition_size = 20
612
+ memory_size = 4
613
+ mult = op
614
+ power = lambda x, y: multiple(x, y, operation=operation, identity=identity, inverse=inverse, op=op)
615
+ if operation in addition_names:
616
+ mult = add
617
+ power = mul
618
+ if ord is None:
619
+ ord = base.additive_order()
620
+ elif operation in multiplication_names:
621
+ mult = mul
622
+ power = pow
623
+ if ord is None:
624
+ ord = base.multiplicative_order()
625
+ elif ord is None or inverse is None or identity is None or op is None:
626
+ raise ValueError
627
+
628
+ ord = Integer(ord)
629
+ if not ord.is_prime():
630
+ raise ValueError("for Pollard rho algorithm the order of the group must be prime")
631
+
632
+ # check if we need to set immutable before hashing
633
+ mut = hasattr(base, 'set_immutable')
634
+
635
+ isqrtord = ord.isqrt()
636
+
637
+ if isqrtord < partition_size: # setup to costly, use bsgs
638
+ return bsgs(base, a, bounds=(0, ord), identity=identity, inverse=inverse, op=op, operation=operation)
639
+
640
+ reset_bound = 8 * isqrtord # we take some margin
641
+
642
+ I = IntegerModRing(ord)
643
+
644
+ for s in range(10): # to avoid infinite loops
645
+ # random walk function setup
646
+ m = [I.random_element() for i in range(partition_size)]
647
+ n = [I.random_element() for i in range(partition_size)]
648
+ M = [mult(power(base, Integer(m[i])), power(a, Integer(n[i])))
649
+ for i in range(partition_size)]
650
+
651
+ ax = I.random_element()
652
+ x = power(base, Integer(ax))
653
+ if mut:
654
+ x.set_immutable()
655
+
656
+ bx = I(0)
657
+
658
+ sigma = [(0, None)] * memory_size
659
+ H = {} # memory
660
+ i0 = 0
661
+ nextsigma = 0
662
+ for i in range(reset_bound):
663
+ # random walk, we need an efficient hash
664
+ s = hash_function(x) % partition_size
665
+ x, ax, bx = (mult(M[s], x), ax + m[s], bx + n[s])
666
+ if mut:
667
+ x.set_immutable()
668
+ # look for collisions
669
+ if x in H:
670
+ ay, by = H[x]
671
+ if bx == by:
672
+ break
673
+ else:
674
+ res = sage.rings.integer.Integer((ay - ax) / (bx - by))
675
+ if power(base, res) == a:
676
+ return res
677
+ else:
678
+ break
679
+ # should we remember this value?
680
+ elif i >= nextsigma:
681
+ if sigma[i0][1] is not None:
682
+ H.pop(sigma[i0][1])
683
+ sigma[i0] = (i, x)
684
+ i0 = (i0 + 1) % memory_size
685
+ nextsigma = 3 * sigma[i0][0] # 3 seems a good choice
686
+ H[x] = (ax, bx)
687
+
688
+ raise ValueError("Pollard rho algorithm failed to find a logarithm")
689
+
690
+
691
+ def discrete_log(a, base, ord=None, bounds=None, operation='*', identity=None, inverse=None, op=None, algorithm='bsgs', *, verify=True):
692
+ r"""
693
+ Totally generic discrete log function.
694
+
695
+ INPUT:
696
+
697
+ - ``a`` -- group element
698
+ - ``base`` -- group element (the base)
699
+ - ``ord`` -- integer (multiple of order of base, or ``None``)
700
+ - ``bounds`` -- a priori bounds on the log
701
+ - ``operation`` -- string: ``'*'``, ``'+'``, other
702
+ - ``identity`` -- the group's identity
703
+ - ``inverse`` -- function of 1 argument ``x``, returning inverse of ``x``
704
+ - ``op`` -- function of 2 arguments ``x``, ``y``, returning ``x*y`` in the group
705
+ - ``algorithm`` -- string denoting what algorithm to use for prime-order
706
+ logarithms: ``'bsgs'``, ``'rho'``, ``'lambda'``
707
+ - ``verify`` -- boolean (default: ``True``); whether to verify that output is
708
+ correct before returning it.
709
+
710
+ ``a`` and ``base`` must be elements of some group with identity
711
+ given by ``identity``, inverse of ``x`` by ``inverse(x)``, and group
712
+ operation on ``x``, ``y`` by ``op(x,y)``.
713
+
714
+ If operation is ``'*'`` or ``'+'``, then the other
715
+ arguments are provided automatically; otherwise they must be
716
+ provided by the caller.
717
+
718
+ OUTPUT:
719
+
720
+ This returns an integer `n` such that `b^n = a` (or `nb = a`),
721
+ assuming that ``ord`` is a multiple of the order of the base `b`.
722
+ If ``ord`` is not specified, an attempt is made to compute it.
723
+
724
+ If no such `n` exists, this function raises a :exc:`ValueError` exception.
725
+
726
+ .. WARNING::
727
+
728
+ If ``x`` has a ``log`` method, it is likely to be vastly faster
729
+ than using this function. E.g., if ``x`` is an integer modulo
730
+ `n`, use its ``log`` method instead!
731
+
732
+ ALGORITHM: Pohlig-Hellman, Baby step giant step, Pollard's lambda/kangaroo, and Pollard's rho.
733
+
734
+ EXAMPLES::
735
+
736
+ sage: b = Mod(2,37); a = b^20
737
+ sage: discrete_log(a, b)
738
+ 20
739
+ sage: b = Mod(3,2017); a = b^20
740
+ sage: discrete_log(a, b, bounds=(10, 100))
741
+ 20
742
+
743
+ sage: # needs sage.rings.finite_rings
744
+ sage: K = GF(3^6, 'b')
745
+ sage: b = K.gen()
746
+ sage: a = b^210
747
+ sage: discrete_log(a, b, K.order() - 1)
748
+ 210
749
+
750
+ sage: b = Mod(1,37); x = Mod(2,37)
751
+ sage: discrete_log(x, b)
752
+ Traceback (most recent call last):
753
+ ...
754
+ ValueError: no discrete log of 2 found to base 1
755
+ sage: b = Mod(1,997); x = Mod(2,997)
756
+ sage: discrete_log(x, b)
757
+ Traceback (most recent call last):
758
+ ...
759
+ ValueError: no discrete log of 2 found to base 1
760
+
761
+ See :issue:`2356`::
762
+
763
+ sage: F.<w> = GF(121) # needs sage.rings.finite_rings
764
+ sage: v = w^120 # needs sage.rings.finite_rings
765
+ sage: v.log(w) # needs sage.rings.finite_rings
766
+ 0
767
+
768
+ sage: K.<z> = CyclotomicField(230) # needs sage.rings.number_field
769
+ sage: w = z^50 # needs sage.rings.number_field
770
+ sage: discrete_log(w, z) # needs sage.rings.number_field
771
+ 50
772
+
773
+ An example where the order is infinite: note that we must give
774
+ an upper bound here::
775
+
776
+ sage: # needs sage.rings.number_field
777
+ sage: K.<a> = QuadraticField(23)
778
+ sage: eps = 5*a - 24 # a fundamental unit
779
+ sage: eps.multiplicative_order()
780
+ +Infinity
781
+ sage: eta = eps^100
782
+ sage: discrete_log(eta, eps, bounds=(0,1000))
783
+ 100
784
+
785
+ In this case we cannot detect negative powers::
786
+
787
+ sage: eta = eps^(-3) # needs sage.rings.number_field
788
+ sage: discrete_log(eta,eps,bounds=(0,100)) # needs sage.rings.number_field
789
+ Traceback (most recent call last):
790
+ ...
791
+ ValueError: no discrete log of -11515*a - 55224 found to base 5*a - 24 with bounds (0, 100)
792
+
793
+ But we can invert the base (and negate the result) instead::
794
+
795
+ sage: -discrete_log(eta^-1, eps, bounds=(0,100)) # needs sage.rings.number_field
796
+ -3
797
+
798
+ An additive example: elliptic curve DLOG::
799
+
800
+ sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
801
+ sage: F = GF(37^2,'a')
802
+ sage: E = EllipticCurve(F, [1,1])
803
+ sage: F.<a> = GF(37^2,'a')
804
+ sage: E = EllipticCurve(F, [1,1])
805
+ sage: P = E(25*a + 16, 15*a + 7)
806
+ sage: P.order()
807
+ 672
808
+ sage: Q = 39*P; Q
809
+ (36*a + 32 : 5*a + 12 : 1)
810
+ sage: discrete_log(Q, P, P.order(), operation='+')
811
+ 39
812
+
813
+ An example of big smooth group::
814
+
815
+ sage: # needs sage.rings.finite_rings
816
+ sage: F.<a> = GF(2^63)
817
+ sage: g = F.gen()
818
+ sage: u = g**123456789
819
+ sage: discrete_log(u,g)
820
+ 123456789
821
+
822
+ The above examples also work when the ``'rho'`` and ``'lambda'`` algorithms are used::
823
+
824
+ sage: b = Mod(2,37); a = b^20
825
+ sage: discrete_log(a, b, algorithm='rho')
826
+ 20
827
+ sage: b = Mod(3,2017); a = b^20
828
+ sage: discrete_log(a, b, algorithm='lambda', bounds=(10, 100))
829
+ 20
830
+
831
+ sage: # needs sage.rings.finite_rings
832
+ sage: K = GF(3^6,'b')
833
+ sage: b = K.gen()
834
+ sage: a = b^210
835
+ sage: discrete_log(a, b, K.order()-1, algorithm='rho')
836
+ 210
837
+
838
+ sage: b = Mod(1,37); x = Mod(2,37)
839
+ sage: discrete_log(x, b, algorithm='lambda')
840
+ Traceback (most recent call last):
841
+ ...
842
+ ValueError: no discrete log of 2 found to base 1
843
+ sage: b = Mod(1,997); x = Mod(2,997)
844
+ sage: discrete_log(x, b, algorithm='rho')
845
+ Traceback (most recent call last):
846
+ ...
847
+ ValueError: no discrete log of 2 found to base 1
848
+
849
+ sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
850
+ sage: F = GF(37^2,'a')
851
+ sage: E = EllipticCurve(F, [1,1])
852
+ sage: F.<a> = GF(37^2,'a')
853
+ sage: E = EllipticCurve(F, [1,1])
854
+ sage: P = E(25*a + 16, 15*a + 7)
855
+ sage: P.order()
856
+ 672
857
+ sage: Q = 39*P; Q
858
+ (36*a + 32 : 5*a + 12 : 1)
859
+ sage: discrete_log(Q, P, P.order(), operation='+', algorithm='lambda')
860
+ 39
861
+
862
+ sage: # needs sage.rings.finite_rings
863
+ sage: F.<a> = GF(2^63)
864
+ sage: g = F.gen()
865
+ sage: u = g**123456789
866
+ sage: discrete_log(u, g, algorithm='rho')
867
+ 123456789
868
+
869
+ TESTS:
870
+
871
+ Random testing::
872
+
873
+ sage: G = Zmod(randrange(1, 1000))
874
+ sage: base = G.random_element()
875
+ sage: order = choice([base.additive_order(), G.order()])
876
+ sage: assert order.divides(G.cardinality())
877
+ sage: sol = randrange(base.additive_order())
878
+ sage: elem = sol * base
879
+ sage: args = (elem, base, order)
880
+ sage: kwargs = {'operation': '+'}
881
+ sage: kwargs['algorithm'] = choice(['bsgs', 'rho', 'lambda'])
882
+ sage: if randrange(2):
883
+ ....: lo = randrange(-order, sol + 1)
884
+ ....: hi = randrange(sol + 1, 2*order)
885
+ ....: assert lo <= sol <= hi
886
+ ....: kwargs['bounds'] = (lo, hi)
887
+ sage: try:
888
+ ....: res = discrete_log(*args, **kwargs)
889
+ ....: except ValueError:
890
+ ....: # lambda can fail randomly
891
+ ....: assert kwargs['algorithm'] == 'lambda'
892
+ ....: else:
893
+ ....: assert res == sol
894
+
895
+ Verify that :issue:`38316` is fixed::
896
+
897
+ sage: F = GF(5)
898
+ sage: base = F(3)
899
+ sage: a = F(1)
900
+ sage: discrete_log(a, base, bounds=(1,2), operation="*")
901
+ Traceback (most recent call last):
902
+ ...
903
+ ValueError: no discrete log of 1 found to base 3 with bounds (1, 2)
904
+
905
+ AUTHORS:
906
+
907
+ - William Stein and David Joyner (2005-01-05)
908
+ - John Cremona (2008-02-29) rewrite using ``dict()`` and make generic
909
+ - Julien Grijalva (2022-08-09) rewrite to make more generic, more algorithm options, and more effective use of bounds
910
+ """
911
+ from operator import mul, add, pow
912
+ power = mul if operation in addition_names else pow
913
+ mult = add if operation in addition_names else mul
914
+ original_a = a # Store the original value of a so we can verify the answer
915
+ if op:
916
+ mult = op
917
+ power = lambda x, y: multiple(x, y, operation=operation, identity=identity, inverse=inverse, op=op)
918
+ if bounds:
919
+ lb, ub = map(integer_ring.ZZ, bounds)
920
+ if (op is None or identity is None or inverse is None or ord is None) and operation not in addition_names + multiplication_names:
921
+ raise ValueError("ord, op, identity, and inverse must all be specified for this operation")
922
+ if ord is None:
923
+ if operation in multiplication_names:
924
+ try:
925
+ ord = base.multiplicative_order()
926
+ except Exception:
927
+ ord = base.order()
928
+ else:
929
+ try:
930
+ ord = base.additive_order()
931
+ except Exception:
932
+ ord = base.order()
933
+ else:
934
+ ord = integer_ring.ZZ(ord)
935
+ try:
936
+ from sage.rings.infinity import Infinity
937
+ if ord == +Infinity:
938
+ return bsgs(base, a, bounds, identity=identity, inverse=inverse, op=op, operation=operation)
939
+ if base == power(base, 0) and a != base:
940
+ raise ValueError
941
+ f = ord.factor()
942
+ l = [0] * len(f)
943
+ mods = []
944
+ running_mod = 1
945
+ offset = 0
946
+ if bounds:
947
+ a = mult(a, power(base, -lb))
948
+ offset = lb
949
+ bound = ub - lb
950
+ i = -1 # this corrects a bug in which the loop is never entered and i never gets assigned a value
951
+ for i, (pi, ri) in enumerate(f):
952
+ gamma = power(base, ord // pi)
953
+ # pohlig-hellman doesn't work with an incorrect order, and the user might have provided a bad parameter
954
+ while gamma == power(gamma, 0) and ri > 0: # identity might be None
955
+ ord //= pi
956
+ ri -= 1
957
+ gamma = power(base, ord // pi)
958
+ if not bounds:
959
+ bound = ord - 1
960
+ running_bound = min(bound, pi**ri - 1)
961
+ j = -1
962
+ for j in range(ri):
963
+ temp_bound = min(running_bound, pi - 1)
964
+ h = power(mult(a, power(base, -l[i])), ord // pi**(j + 1))
965
+ if algorithm == 'bsgs':
966
+ c = bsgs(gamma, h, (0, temp_bound), inverse=inverse, identity=identity, op=op, operation=operation)
967
+ elif algorithm == 'rho':
968
+ c = discrete_log_rho(h, gamma, ord=pi, inverse=inverse, identity=identity, op=op, operation=operation)
969
+ elif algorithm == 'lambda':
970
+ c = discrete_log_lambda(h, gamma, (0, temp_bound), inverse=inverse, identity=identity, op=op, operation=operation)
971
+ l[i] += c * (pi**j)
972
+ running_bound //= pi
973
+ running_mod *= pi
974
+ if running_mod > bound:
975
+ break
976
+ mods.append(pi ** (j+1))
977
+ if running_mod > bound:
978
+ break # we have log%running_mod. if we know that log<running_mod, then we have the value of log.
979
+ l = l[:i + 1]
980
+ from sage.arith.misc import CRT_list
981
+ result = (CRT_list(l, mods) + offset) % ord
982
+ if (verify and power(base, result) != original_a):
983
+ raise ValueError
984
+ return result
985
+ except ValueError:
986
+ with_bounds = f" with bounds {bounds}" if bounds else ""
987
+ raise ValueError(f"no discrete log of {original_a} found to base {base}{with_bounds}")
988
+
989
+
990
+ def discrete_log_generic(a, base, ord=None, bounds=None, operation='*', identity=None, inverse=None, op=None, algorithm='bsgs'):
991
+ """
992
+ Alias for ``discrete_log``.
993
+ """
994
+ return discrete_log(a, base, ord=ord, bounds=bounds, operation=operation, identity=identity, inverse=inverse, op=op, algorithm=algorithm)
995
+
996
+
997
+ def discrete_log_lambda(a, base, bounds, operation='*', identity=None, inverse=None, op=None, hash_function=hash):
998
+ """
999
+ Pollard Lambda algorithm for computing discrete logarithms. It uses
1000
+ only a logarithmic amount of memory. It's useful if you have
1001
+ bounds on the logarithm. If you are computing logarithms in a
1002
+ whole finite group, you should use Pollard Rho algorithm.
1003
+
1004
+ INPUT:
1005
+
1006
+ - ``a`` -- a group element
1007
+ - ``base`` -- a group element
1008
+ - ``bounds`` -- a couple (lb,ub) representing the range where we look for a logarithm
1009
+ - ``operation`` -- string: '+', '*' or 'other'
1010
+ - ``identity`` -- the identity element of the group
1011
+ - ``inverse`` -- function of 1 argument ``x`` returning inverse of ``x``
1012
+ - ``op`` -- function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group
1013
+ - ``hash_function`` -- having an efficient hash function is critical for this algorithm
1014
+
1015
+ OUTPUT: integer `n` such that `a=base^n` (or `a=n*base`)
1016
+
1017
+ ALGORITHM: Pollard Lambda, if bounds are (lb,ub) it has time complexity
1018
+ O(sqrt(ub-lb)) and space complexity O(log(ub-lb))
1019
+
1020
+ EXAMPLES::
1021
+
1022
+ sage: F.<a> = GF(2^63) # needs sage.rings.finite_rings
1023
+ sage: discrete_log_lambda(a^1234567, a, (1200000,1250000)) # needs sage.rings.finite_rings
1024
+ 1234567
1025
+
1026
+ sage: # needs sage.rings.finite_rings sage.schemes
1027
+ sage: F.<a> = GF(37^5)
1028
+ sage: E = EllipticCurve(F, [1,1])
1029
+ sage: P = E.lift_x(a); P
1030
+ (a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)
1031
+
1032
+ This will return a multiple of the order of P::
1033
+
1034
+ sage: discrete_log_lambda(P.parent().zero(), P, Hasse_bounds(F.order()), # needs sage.rings.finite_rings sage.schemes
1035
+ ....: operation='+')
1036
+ 69327408
1037
+
1038
+ sage: K.<a> = GF(89**5) # needs sage.rings.finite_rings
1039
+ sage: hs = lambda x: hash(x) + 15
1040
+ sage: discrete_log_lambda(a**(89**3 - 3), # long time (10s on sage.math, 2011), needs sage.rings.finite_rings
1041
+ ....: a, (89**2, 89**4), operation='*', hash_function=hs)
1042
+ 704966
1043
+
1044
+ AUTHOR:
1045
+
1046
+ -- Yann Laigle-Chapuy (2009-01-25)
1047
+ """
1048
+ from sage.rings.integer import Integer
1049
+ from operator import mul, add
1050
+
1051
+ mult = op
1052
+ if operation in addition_names:
1053
+ mult = add
1054
+ elif operation in multiplication_names:
1055
+ mult = mul
1056
+ power = lambda x, y: multiple(x, y, operation=operation, identity=identity, inverse=inverse, op=op)
1057
+
1058
+ lb, ub = bounds
1059
+ if lb < 0 or ub < lb:
1060
+ raise ValueError("discrete_log_lambda() requires 0<=lb<=ub")
1061
+
1062
+ # check for mutability
1063
+ mut = hasattr(base, 'set_immutable')
1064
+
1065
+ width = Integer(ub - lb)
1066
+ N = width.isqrt() + 1
1067
+
1068
+ M = {}
1069
+ for s in range(10): # to avoid infinite loops
1070
+ # random walk function setup
1071
+ k = 0
1072
+ while 2**k < N:
1073
+ r = sage.misc.prandom.randrange(1, N)
1074
+ M[k] = (r, power(base, r))
1075
+ k += 1
1076
+ # first random walk
1077
+ H = power(base, ub)
1078
+ c = ub
1079
+ for i in range(N):
1080
+ if mut:
1081
+ H.set_immutable()
1082
+ r, e = M[hash_function(H) % k]
1083
+ H = mult(H, e)
1084
+ c += r
1085
+ if mut:
1086
+ H.set_immutable()
1087
+ mem = {H}
1088
+ # second random walk
1089
+ H = a
1090
+ d = 0
1091
+ while c - d >= lb:
1092
+ if mut:
1093
+ H.set_immutable()
1094
+ if ub >= c - d and H in mem:
1095
+ return c - d
1096
+ r, e = M[hash_function(H) % k]
1097
+ H = mult(H, e)
1098
+ d += r
1099
+
1100
+ raise ValueError("Pollard Lambda failed to find a log")
1101
+
1102
+
1103
+ ################################################################
1104
+ #
1105
+ # Generic linear relation finder
1106
+ #
1107
+ ################################################################
1108
+
1109
+
1110
+ def linear_relation(P, Q, operation='+', identity=None, inverse=None, op=None):
1111
+ r"""
1112
+ Function which solves the equation ``a*P=m*Q`` or ``P^a=Q^m``.
1113
+
1114
+ Additive version: returns `(a,m)` with minimal `m>0` such that
1115
+ `aP=mQ`. Special case: if `\left<P\right>` and `\left<Q\right>`
1116
+ intersect only in `\{0\}` then `(a,m)=(0,n)` where `n` is
1117
+ ``Q.additive_order()``.
1118
+
1119
+ Multiplicative version: returns `(a,m)` with minimal `m>0` such
1120
+ that `P^a=Q^m`. Special case: if `\left<P\right>` and
1121
+ `\left<Q\right>` intersect only in `\{1\}` then `(a,m)=(0,n)`
1122
+ where `n` is ``Q.multiplicative_order()``.
1123
+
1124
+ ALGORITHM:
1125
+
1126
+ Uses the generic ``bsgs()`` function, and so works in general
1127
+ finite abelian groups.
1128
+
1129
+ EXAMPLES:
1130
+
1131
+ An additive example (in an elliptic curve group)::
1132
+
1133
+ sage: # needs sage.rings.finite_rings sage.schemes
1134
+ sage: F.<a> = GF(3^6,'a')
1135
+ sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1])
1136
+ sage: P = E(a^5 + a^4 + a^3 + a^2 + a + 2, 0)
1137
+ sage: Q = E(2*a^3 + 2*a^2 + 2*a, a^3 + 2*a^2 + 1)
1138
+ sage: linear_relation(P, Q, '+')
1139
+ (1, 2)
1140
+ sage: P == 2*Q
1141
+ True
1142
+
1143
+ A multiplicative example (in a finite field's multiplicative group)::
1144
+
1145
+ sage: # needs sage.rings.finite_rings
1146
+ sage: F.<a> = GF(3^6,'a')
1147
+ sage: a.multiplicative_order().factor()
1148
+ 2^3 * 7 * 13
1149
+ sage: b = a^7
1150
+ sage: c = a^13
1151
+ sage: linear_relation(b, c, '*')
1152
+ (13, 7)
1153
+ sage: b^13 == c^7
1154
+ True
1155
+ """
1156
+ Z = integer_ring.ZZ
1157
+
1158
+ if operation in multiplication_names:
1159
+ try:
1160
+ n = P.multiplicative_order()
1161
+ m = Q.multiplicative_order()
1162
+ except Exception:
1163
+ n = P.order()
1164
+ m = Q.order()
1165
+ elif operation in addition_names:
1166
+ try:
1167
+ n = P.additive_order()
1168
+ m = Q.additive_order()
1169
+ except Exception:
1170
+ n = P.order()
1171
+ m = Q.order()
1172
+ else:
1173
+ if op is None:
1174
+ raise ValueError("operation must be specified")
1175
+ n = P.order()
1176
+ m = Q.order()
1177
+
1178
+ g = n.gcd(m)
1179
+ if g == 1:
1180
+ return (m, Z.zero())
1181
+ n1 = n // g
1182
+ m1 = m // g
1183
+ P1 = multiple(P, n1, operation=operation) # has exact order g
1184
+ Q1 = multiple(Q, m1, operation=operation) # has exact order g
1185
+
1186
+ # now see if Q1 is a multiple of P1; the only multiples we
1187
+ # need check are h*Q1 where h divides g
1188
+ for h in g.divisors(): # positive divisors!
1189
+ try:
1190
+ Q2 = multiple(Q1, h, operation=operation)
1191
+ return (n1 * bsgs(P1, Q2, (0, g - 1), operation=operation),
1192
+ m1 * h)
1193
+ except ValueError:
1194
+ pass # to next h
1195
+ raise ValueError("no solution found in linear_relation")
1196
+
1197
+ ################################################################
1198
+ #
1199
+ # Generic functions to find orders of elements
1200
+ #
1201
+ # 1. order_from_multiple: finds the order given a multiple of the order
1202
+ #
1203
+ # 2. order_from_bounds: finds the order given an interval containing a
1204
+ # multiple of the order
1205
+ #
1206
+ # 3. has_order: check if the order is exactly equal to a given integer
1207
+ #
1208
+ ################################################################
1209
+
1210
+
1211
+ def order_from_multiple(P, m, plist=None, factorization=None, check=True,
1212
+ operation='+', identity=None, inverse=None, op=None):
1213
+ r"""
1214
+ Generic function to find order of a group element given a multiple
1215
+ of its order.
1216
+
1217
+ See :meth:`bsgs` for full explanation of the inputs.
1218
+
1219
+ INPUT:
1220
+
1221
+ - ``P`` -- a Sage object which is a group element
1222
+ - ``m`` -- Sage integer which is a multiple of the order of ``P``,
1223
+ i.e. we require that ``m*P=0`` (or ``P**m=1``)
1224
+ - ``check`` -- a Boolean (default: ``True``), indicating whether we check if ``m``
1225
+ really is a multiple of the order
1226
+ - ``factorization`` -- the factorization of ``m``, or ``None`` in which
1227
+ case this function will need to factor ``m``
1228
+ - ``plist`` -- list of the prime factors of ``m``, or ``None``. Kept for compatibility only,
1229
+ prefer the use of ``factorization``
1230
+ - ``operation`` -- string: ``'+'`` (default), ``'*'`` or ``None``
1231
+ - ``identity`` -- the identity element of the group
1232
+ - ``inverse`` -- function of 1 argument ``x``, returning inverse of ``x``
1233
+ - ``op`` -- function of 2 arguments ``x``, ``y`` returning ``x*y`` in the group
1234
+
1235
+ .. NOTE::
1236
+
1237
+ It is more efficient for the caller to factor ``m`` and cache
1238
+ the factors for subsequent calls.
1239
+
1240
+ EXAMPLES::
1241
+
1242
+ sage: from sage.groups.generic import order_from_multiple
1243
+
1244
+ sage: # needs sage.rings.finite_rings
1245
+ sage: k.<a> = GF(5^5)
1246
+ sage: b = a^4
1247
+ sage: order_from_multiple(b, 5^5 - 1, operation='*')
1248
+ 781
1249
+
1250
+ sage: # needs sage.rings.finite_rings sage.schemes
1251
+ sage: E = EllipticCurve(k, [2,4])
1252
+ sage: P = E(3*a^4 + 3*a, 2*a + 1)
1253
+ sage: M = E.cardinality(); M
1254
+ 3227
1255
+ sage: F = M.factor()
1256
+ sage: order_from_multiple(P, M, factorization=F, operation='+')
1257
+ 3227
1258
+ sage: Q = E(0,2)
1259
+ sage: order_from_multiple(Q, M, factorization=F, operation='+')
1260
+ 7
1261
+
1262
+ sage: # needs sage.rings.number_field
1263
+ sage: K.<z> = CyclotomicField(230)
1264
+ sage: w = z^50
1265
+ sage: order_from_multiple(w, 230, operation='*')
1266
+ 23
1267
+
1268
+ sage: # needs sage.modules sage.rings.finite_rings
1269
+ sage: F = GF(2^1279,'a')
1270
+ sage: n = F.cardinality() - 1 # Mersenne prime
1271
+ sage: order_from_multiple(F.random_element(), n,
1272
+ ....: factorization=[(n,1)], operation='*') == n
1273
+ True
1274
+
1275
+ sage: # needs sage.rings.finite_rings
1276
+ sage: K.<a> = GF(3^60)
1277
+ sage: order_from_multiple(a, 3^60 - 1, operation='*', check=False)
1278
+ 42391158275216203514294433200
1279
+
1280
+ TESTS:
1281
+
1282
+ Check that :issue:`38489` is fixed::
1283
+
1284
+ sage: from sage.groups.generic import order_from_multiple
1285
+ sage: plist = [43, 257, 547, 881]
1286
+ sage: m = prod(plist[:-1])
1287
+ sage: elt = Zmod(m)(plist[-1])
1288
+ sage: order_from_multiple(elt, m, plist=plist)
1289
+ 6044897
1290
+ """
1291
+ Z = integer_ring.ZZ
1292
+
1293
+ if operation in multiplication_names:
1294
+ identity = P.parent().one()
1295
+ elif operation in addition_names:
1296
+ identity = P.parent().zero()
1297
+ else:
1298
+ if identity is None or inverse is None or op is None:
1299
+ raise ValueError("identity, inverse and operation must all be specified")
1300
+
1301
+ def _multiple(A, B):
1302
+ return multiple(A,
1303
+ B,
1304
+ operation=operation,
1305
+ identity=identity,
1306
+ inverse=inverse,
1307
+ op=op)
1308
+
1309
+ if P == identity:
1310
+ return Z.one()
1311
+
1312
+ M = Z(m)
1313
+ if check and _multiple(P, M) != identity:
1314
+ raise ValueError(f"The order of P(={P}) does not divide {M}")
1315
+
1316
+ if factorization:
1317
+ F = factorization
1318
+ elif plist:
1319
+ F = [(p, M.valuation(p)) for p in plist]
1320
+ else:
1321
+ F = M.factor()
1322
+
1323
+ if len(F) == 1 and list(F) == [(M, 1)]:
1324
+ return M
1325
+
1326
+ # Efficiency improvement (2009-10-27, implemented by Yann Laigle-Chapuy):
1327
+ # we use an internal recursive function to avoid unnecessary computations.
1328
+ def _order_from_multiple_helper(Q, L, S):
1329
+ """
1330
+ For internal use, to minimize the number of group operations.
1331
+ """
1332
+ l = len(L)
1333
+ if l == 1:
1334
+ # we determine the power of p dividing the order,
1335
+
1336
+ # Efficiency improvement (2009-04-01, suggested by Ryan Hinton,
1337
+ # implemented by John Cremona): avoid the last multiplication by p.
1338
+ # For example, if M itself is prime the code used to compute M*P
1339
+ # twice (unless P=0), now it does it once.
1340
+ p, e = L[0]
1341
+ e0 = 0
1342
+ while (Q != identity) and (e0 < e - 1):
1343
+ Q = _multiple(Q, p)
1344
+ e0 += 1
1345
+ if Q != identity:
1346
+ e0 += 1
1347
+ return p**e0
1348
+ else:
1349
+ # try to split the list wisely
1350
+ sum_left = 0
1351
+ for k in range(l):
1352
+ p, e = L[k]
1353
+ # multiplying by p**e require roughly 'e log_2(p) / 2' additions
1354
+ v = e * sage.functions.log.log(float(p))
1355
+ if abs(sum_left + v - (S / 2)) > abs(sum_left - (S / 2)):
1356
+ break
1357
+ sum_left += v
1358
+ if not 0 < k < l:
1359
+ k = l // 2
1360
+ L1 = L[:k]
1361
+ L2 = L[k:]
1362
+ # recursive calls
1363
+ o1 = _order_from_multiple_helper(
1364
+ _multiple(Q, prod([p**e for p, e in L2])), L1, sum_left)
1365
+ o2 = _order_from_multiple_helper(_multiple(Q, o1), L2, S - sum_left)
1366
+ return o1 * o2
1367
+
1368
+ return _order_from_multiple_helper(P, F, sage.functions.log.log(float(M)))
1369
+
1370
+
1371
+ def order_from_bounds(P, bounds, d=None, operation='+',
1372
+ identity=None, inverse=None, op=None):
1373
+ r"""
1374
+ Generic function to find order of a group element, given only
1375
+ upper and lower bounds for a multiple of the order (e.g. bounds on
1376
+ the order of the group of which it is an element)
1377
+
1378
+ INPUT:
1379
+
1380
+ - ``P`` -- a Sage object which is a group element
1381
+
1382
+ - ``bounds`` -- a 2-tuple ``(lb,ub)`` such that ``m*P=0`` (or
1383
+ ``P**m=1``) for some ``m`` with ``lb<=m<=ub``
1384
+
1385
+ - ``d`` -- (optional) a positive integer; only ``m`` which are
1386
+ multiples of this will be considered
1387
+
1388
+ - ``operation`` -- string; ``'+'`` (default) or ``'*'`` or other.
1389
+ If other, the following must be supplied:
1390
+
1391
+ - ``identity`` -- the identity element for the group
1392
+ - ``inverse`` -- a function of one argument giving the inverse
1393
+ of a group element
1394
+ - ``op`` -- a function of 2 arguments defining the group binary
1395
+ operation
1396
+
1397
+ .. NOTE::
1398
+
1399
+ Typically ``lb`` and ``ub`` will be bounds on the group order,
1400
+ and from previous calculation we know that the group order is
1401
+ divisible by ``d``.
1402
+
1403
+ EXAMPLES::
1404
+
1405
+ sage: from sage.groups.generic import order_from_bounds
1406
+
1407
+ sage: # needs sage.rings.finite_rings
1408
+ sage: k.<a> = GF(5^5)
1409
+ sage: b = a^4
1410
+ sage: order_from_bounds(b, (5^4, 5^5), operation='*')
1411
+ 781
1412
+
1413
+ sage: # needs sage.rings.finite_rings sage.schemes
1414
+ sage: E = EllipticCurve(k, [2,4])
1415
+ sage: P = E(3*a^4 + 3*a, 2*a + 1)
1416
+ sage: bounds = Hasse_bounds(5^5)
1417
+ sage: Q = E(0,2)
1418
+ sage: order_from_bounds(Q, bounds, operation='+')
1419
+ 7
1420
+ sage: order_from_bounds(P, bounds, 7, operation='+')
1421
+ 3227
1422
+
1423
+ sage: # needs sage.rings.number_field
1424
+ sage: K.<z> = CyclotomicField(230)
1425
+ sage: w = z^50
1426
+ sage: order_from_bounds(w, (200, 250), operation='*')
1427
+ 23
1428
+ """
1429
+ from operator import mul, add
1430
+
1431
+ if operation in multiplication_names:
1432
+ op = mul
1433
+ identity = P.parent().one()
1434
+ elif operation in addition_names:
1435
+ op = add
1436
+ identity = P.parent().zero()
1437
+ else:
1438
+ if op is None:
1439
+ raise ValueError("operation and identity must be specified")
1440
+
1441
+ Q = P
1442
+ if d is None:
1443
+ d = 1
1444
+ if d > 1:
1445
+ Q = multiple(P, d, operation=operation)
1446
+ lb, ub = bounds
1447
+ bounds = (integer_ceil(lb / d), integer_floor(ub / d))
1448
+
1449
+ # Use generic bsgs to find n=d*m with lb<=n<=ub and n*P=0
1450
+
1451
+ m = d * bsgs(Q, identity, bounds, operation=operation)
1452
+
1453
+ # Now use the order_from_multiple() function to finish the job:
1454
+
1455
+ return order_from_multiple(P, m, operation=operation, check=False)
1456
+
1457
+
1458
+ def has_order(P, n, operation='+') -> bool:
1459
+ r"""
1460
+ Generic function to test if a group element `P` has order
1461
+ exactly equal to a given positive integer `n`.
1462
+
1463
+ INPUT:
1464
+
1465
+ - ``P`` -- group element with respect to the specified ``operation``
1466
+ - ``n`` -- positive integer, or its :class:`~sage.structure.factorization.Factorization`
1467
+ - ``operation`` -- string, either ``'+'`` (default) or ``'*'``
1468
+
1469
+ EXAMPLES::
1470
+
1471
+ sage: from sage.groups.generic import has_order
1472
+
1473
+ sage: # needs sage.schemes
1474
+ sage: E.<P> = EllipticCurve(GF(71), [5,5])
1475
+ sage: P.order()
1476
+ 57
1477
+ sage: has_order(P, 57)
1478
+ True
1479
+ sage: has_order(P, factor(57))
1480
+ True
1481
+ sage: has_order(P, 19)
1482
+ False
1483
+ sage: has_order(3*P, 19)
1484
+ True
1485
+ sage: has_order(3*P, 57)
1486
+ False
1487
+
1488
+ ::
1489
+
1490
+ sage: R = Zmod(14981)
1491
+ sage: g = R(321)
1492
+ sage: g.multiplicative_order() # needs sage.libs.pari
1493
+ 42
1494
+ sage: has_order(g, 42, operation='*')
1495
+ True
1496
+ sage: has_order(g, factor(42), operation='*')
1497
+ True
1498
+ sage: has_order(g, 70, operation='*')
1499
+ False
1500
+
1501
+ TESTS::
1502
+
1503
+ sage: # needs sage.libs.pari sage.modules
1504
+ sage: ns = [randrange(1,10**5) for _ in range(randrange(1,5))]
1505
+ sage: A = AdditiveAbelianGroup(ns)
1506
+ sage: from sage.groups.generic import has_order
1507
+ sage: el = A.random_element()
1508
+ sage: o = el.order()
1509
+ sage: has_order(el, o)
1510
+ True
1511
+ sage: has_order(el, o.factor())
1512
+ True
1513
+ sage: not_o = ZZ(randrange(100*o))
1514
+ sage: not_o += (not_o == o)
1515
+ sage: has_order(el, not_o)
1516
+ False
1517
+
1518
+ Check for :issue:`37102`::
1519
+
1520
+ sage: from sage.groups.generic import has_order
1521
+ sage: x = Mod(9, 24)
1522
+ sage: has_order(x, 0)
1523
+ False
1524
+ sage: has_order(x, -8)
1525
+ False
1526
+
1527
+ Check for :issue:`38708`::
1528
+
1529
+ sage: has_order(Mod(2,3), int(2), operation='*')
1530
+ True
1531
+
1532
+ .. NOTE::
1533
+
1534
+ In some cases, order *testing* can be much faster than
1535
+ *computing* the order using :func:`order_from_multiple`.
1536
+ """
1537
+ if not isinstance(n, sage.structure.factorization.Factorization):
1538
+ n = integer_ring.ZZ(n)
1539
+ if n <= 0:
1540
+ return False
1541
+ n = n.factor()
1542
+
1543
+ if operation in addition_names:
1544
+ isid = lambda el: not el
1545
+ mult = lambda el, n: multiple(el, n, operation='+')
1546
+ elif operation in multiplication_names:
1547
+ isid = lambda el: el.is_one()
1548
+ mult = multiple
1549
+ else:
1550
+ raise ValueError('unknown group operation')
1551
+
1552
+ def _rec(Q, fn) -> bool:
1553
+ if not fn:
1554
+ return isid(Q)
1555
+
1556
+ if len(fn) == 1:
1557
+ p, k = fn[0]
1558
+ for _ in range(k):
1559
+ if isid(Q):
1560
+ return False
1561
+ Q = mult(Q, p)
1562
+ return isid(Q)
1563
+
1564
+ fl = fn[::2]
1565
+ fr = fn[1::2]
1566
+ l = prod(p**k for p, k in fl)
1567
+ r = prod(p**k for p, k in fr)
1568
+ L, R = mult(Q, r), mult(Q, l)
1569
+ return _rec(L, fl) and _rec(R, fr)
1570
+
1571
+ return _rec(P, n)
1572
+
1573
+
1574
+ def merge_points(P1, P2, operation='+',
1575
+ identity=None, inverse=None, op=None, check=True):
1576
+ r"""
1577
+ Return a group element whose order is the lcm of the given elements.
1578
+
1579
+ INPUT:
1580
+
1581
+ - ``P1`` -- a pair `(g_1,n_1)` where `g_1` is a group element of order `n_1`
1582
+ - ``P2`` -- a pair `(g_2,n_2)` where `g_2` is a group element of order `n_2`
1583
+ - ``operation`` -- string; ``'+'`` (default) or ``'*'`` or other. If
1584
+ other, the following must be supplied:
1585
+
1586
+ - ``identity`` -- the identity element for the group
1587
+ - ``inverse`` -- a function of one argument giving the inverse
1588
+ of a group element
1589
+ - ``op`` -- a function of 2 arguments defining the group
1590
+ binary operation
1591
+
1592
+ OUTPUT: a pair `(g_3,n_3)` where `g_3` has order `n_3=\hbox{lcm}(n_1,n_2)`
1593
+
1594
+ EXAMPLES::
1595
+
1596
+ sage: # needs sage.rings.finite_rings
1597
+ sage: from sage.groups.generic import merge_points
1598
+ sage: F.<a> = GF(3^6,'a')
1599
+ sage: b = a^7
1600
+ sage: c = a^13
1601
+ sage: ob = (3^6-1)//7
1602
+ sage: oc = (3^6-1)//13
1603
+ sage: merge_points((b,ob), (c,oc), operation='*')
1604
+ (a^4 + 2*a^3 + 2*a^2, 728)
1605
+ sage: d, od = merge_points((b,ob), (c,oc), operation='*')
1606
+ sage: od == d.multiplicative_order()
1607
+ True
1608
+ sage: od == lcm(ob, oc)
1609
+ True
1610
+
1611
+ sage: # needs sage.libs.gap sage.rings.finite_rings sage.schemes
1612
+ sage: E = EllipticCurve([a^5 + 2*a^3 + 2*a^2 + 2*a, a^4 + a^3 + 2*a + 1])
1613
+ sage: P = E(2*a^5 + 2*a^4 + a^3 + 2, a^4 + a^3 + a^2 + 2*a + 2)
1614
+ sage: P.order()
1615
+ 7
1616
+ sage: Q = E(2*a^5 + 2*a^4 + 1, a^5 + 2*a^3 + 2*a + 2)
1617
+ sage: Q.order()
1618
+ 4
1619
+ sage: R, m = merge_points((P,7), (Q,4), operation='+')
1620
+ sage: R.order() == m
1621
+ True
1622
+ sage: m == lcm(7,4)
1623
+ True
1624
+ """
1625
+ from operator import mul, add
1626
+
1627
+ g1, n1 = P1
1628
+ g2, n2 = P2
1629
+
1630
+ if operation in multiplication_names:
1631
+ op = mul
1632
+ identity = g1.parent().one()
1633
+ elif operation in addition_names:
1634
+ op = add
1635
+ identity = g1.parent().zero()
1636
+ else:
1637
+ if op is None:
1638
+ raise ValueError("operation and identity must be specified")
1639
+
1640
+ if check:
1641
+ if multiple(g1, n1, operation=operation) != identity or multiple(g2, n2, operation=operation) != identity:
1642
+ raise ValueError("the orders provided do not divide the orders of the points provided")
1643
+
1644
+ # trivial cases
1645
+ if n1.divides(n2):
1646
+ return (g2, n2)
1647
+ if n2.divides(n1):
1648
+ return (g1, n1)
1649
+
1650
+ m, k1, k2 = xlcm(n1, n2)
1651
+ m1 = n1 // k1
1652
+ m2 = n2 // k2
1653
+ g1 = multiple(g1, m1, operation=operation)
1654
+ g2 = multiple(g2, m2, operation=operation)
1655
+ return (op(g1, g2), m)
1656
+
1657
+
1658
+ def structure_description(G, latex=False):
1659
+ r"""
1660
+ Return a string that tries to describe the structure of ``G``.
1661
+
1662
+ This methods wraps GAP's ``StructureDescription`` method.
1663
+
1664
+ For full details, including the form of the returned string and the
1665
+ algorithm to build it, see :gap:`GAP's documentation <chap39>`.
1666
+
1667
+ INPUT:
1668
+
1669
+ - ``latex`` -- boolean (default: ``False``); if ``True``, return a
1670
+ LaTeX formatted string
1671
+
1672
+ OUTPUT: string
1673
+
1674
+ .. WARNING::
1675
+
1676
+ From GAP's documentation: The string returned by
1677
+ ``StructureDescription`` is **not** an isomorphism invariant:
1678
+ non-isomorphic groups can have the same string value, and two
1679
+ isomorphic groups in different representations can produce different
1680
+ strings.
1681
+
1682
+ EXAMPLES::
1683
+
1684
+ sage: # needs sage.groups
1685
+ sage: G = CyclicPermutationGroup(6)
1686
+ sage: G.structure_description()
1687
+ 'C6'
1688
+ sage: G.structure_description(latex=True)
1689
+ 'C_{6}'
1690
+ sage: G2 = G.direct_product(G, maps=False)
1691
+ sage: LatexExpr(G2.structure_description(latex=True))
1692
+ C_{6} \times C_{6}
1693
+
1694
+ This method is mainly intended for small groups or groups with few
1695
+ normal subgroups. Even then there are some surprises::
1696
+
1697
+ sage: D3 = DihedralGroup(3) # needs sage.groups
1698
+ sage: D3.structure_description() # needs sage.groups
1699
+ 'S3'
1700
+
1701
+ We use the Sage notation for the degree of dihedral groups::
1702
+
1703
+ sage: D4 = DihedralGroup(4) # needs sage.groups
1704
+ sage: D4.structure_description() # needs sage.groups
1705
+ 'D4'
1706
+
1707
+ Works for finitely presented groups (:issue:`17573`)::
1708
+
1709
+ sage: F.<x, y> = FreeGroup() # needs sage.combinat sage.groups
1710
+ sage: G = F / [x^2*y^-1, x^3*y^2, x*y*x^-1*y^-1] # needs sage.combinat sage.groups
1711
+ sage: G.structure_description() # needs sage.combinat sage.groups
1712
+ 'C7'
1713
+
1714
+ And matrix groups (:issue:`17573`)::
1715
+
1716
+ sage: groups.matrix.GL(4,2).structure_description() # needs sage.libs.gap sage.modules
1717
+ 'A8'
1718
+ """
1719
+ import re
1720
+
1721
+ def correct_dihedral_degree(match):
1722
+ return "%sD%d" % (match.group(1), int(match.group(2)) // 2)
1723
+
1724
+ description = str(G._gap_().StructureDescription())
1725
+
1726
+ description = re.sub(r"(\A|\W)D(\d+)", correct_dihedral_degree, description)
1727
+ if not latex:
1728
+ return description
1729
+ description = description.replace("x", r"\times").replace(":", r"\rtimes")
1730
+ description = re.sub(r"([A-Za-z]+)([0-9]+)", r"\g<1>_{\g<2>}", description)
1731
+ description = re.sub(r"O([+-])", r"O^{\g<1>}", description)
1732
+
1733
+ return description