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
@@ -0,0 +1,2701 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ """
3
+ Generic data structures for multivariate polynomials
4
+
5
+ This module provides an implementation of a generic data structure
6
+ :class:`PolyDict` and the underlying arithmetic for multi-variate polynomial
7
+ rings. It uses a sparse representation of polynomials encoded as a Python
8
+ dictionary where keys are exponents and values coefficients.
9
+
10
+ ``{(e1,...,er):c1,...} <-> c1*x1^e1*...*xr^er+...``,
11
+
12
+ The exponent ``(e1,...,er)`` in this representation is an instance of the class
13
+ :class:`ETuple`.
14
+
15
+ AUTHORS:
16
+
17
+ - William Stein
18
+ - David Joyner
19
+ - Martin Albrecht (ETuple)
20
+ - Joel B. Mohler (2008-03-17) -- ETuple rewrite as sparse C array
21
+ """
22
+
23
+ # ****************************************************************************
24
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
25
+ # 2022 Vincent Delecroix <20100.delecroix@gmail.com>
26
+ #
27
+ # This program is free software: you can redistribute it and/or modify
28
+ # it under the terms of the GNU General Public License as published by
29
+ # the Free Software Foundation, either version 2 of the License, or
30
+ # (at your option) any later version.
31
+ # https://www.gnu.org/licenses/
32
+ # ****************************************************************************
33
+
34
+ from libc.string cimport memcpy
35
+ from cpython.dict cimport *
36
+ cimport cython
37
+ from cpython.object cimport (Py_EQ, Py_NE, Py_LT, Py_LE, Py_GT, Py_GE)
38
+ from cysignals.memory cimport sig_malloc, sig_free
39
+
40
+ from sage.structure.richcmp cimport rich_to_bool
41
+
42
+ from functools import reduce
43
+ from pprint import pformat
44
+
45
+ from sage.misc.latex import latex
46
+
47
+
48
+ cpdef int gen_index(PolyDict x) noexcept:
49
+ r"""
50
+ Return the index of the variable represented by ``x`` or ``-1`` if ``x``
51
+ is not a monomial of degree one.
52
+
53
+ EXAMPLES::
54
+
55
+ sage: from sage.rings.polynomial.polydict import PolyDict, gen_index
56
+ sage: gen_index(PolyDict({(1, 0): 1}))
57
+ 0
58
+ sage: gen_index(PolyDict({(0, 1): 1}))
59
+ 1
60
+ sage: gen_index(PolyDict({}))
61
+ -1
62
+ """
63
+ if len(x.__repn) != 1:
64
+ return -1
65
+ cdef ETuple e = next(iter(x.__repn))
66
+ if e._nonzero != 1 or e._data[1] != 1:
67
+ return -1
68
+ if not next(iter(x.__repn.values())).is_one():
69
+ return -1
70
+ return e._data[0]
71
+
72
+
73
+ cpdef ETuple monomial_exponent(PolyDict p):
74
+ r"""
75
+ Return the unique exponent of ``p`` if it is a monomial or raise a
76
+ :exc:`ValueError`.
77
+
78
+ EXAMPLES::
79
+
80
+ sage: from sage.rings.polynomial.polydict import PolyDict, monomial_exponent
81
+ sage: monomial_exponent(PolyDict({(2, 3): 1}))
82
+ (2, 3)
83
+ sage: monomial_exponent(PolyDict({(2, 3): 3}))
84
+ Traceback (most recent call last):
85
+ ...
86
+ ValueError: not a monomial
87
+ sage: monomial_exponent(PolyDict({(1, 0): 1, (0, 1): 1}))
88
+ Traceback (most recent call last):
89
+ ...
90
+ ValueError: not a monomial
91
+ """
92
+ if len(p.__repn) != 1 or not next(iter(p.__repn.values())).is_one():
93
+ raise ValueError('not a monomial')
94
+ return next(iter(p.__repn))
95
+
96
+
97
+ cdef class PolyDict:
98
+ r"""
99
+ Data structure for multivariate polynomials.
100
+
101
+ A PolyDict holds a dictionary all of whose keys are :class:`ETuple` and
102
+ whose values are coefficients on which it is implicitely assumed that
103
+ arithmetic operations can be performed.
104
+
105
+ No arithmetic operation on :class:`PolyDict` clear zero coefficients as of
106
+ now there is no reliable way of testing it in the most general setting, see
107
+ :issue:`35319`. For removing zero coefficients from a :class:`PolyDict` you
108
+ can use the method :meth:`remove_zeros` which can be parametrized by a zero
109
+ test.
110
+ """
111
+ def __init__(self, pdict, zero=None, remove_zero=None, force_int_exponents=None, force_etuples=None, bint check=True):
112
+ """
113
+ INPUT:
114
+
115
+ - ``pdict`` -- dictionary or list, which represents a multi-variable
116
+ polynomial with the distribute representation (a copy is made)
117
+
118
+ - ``zero`` -- deprecated
119
+
120
+ - ``remove_zero`` -- deprecated
121
+
122
+ - ``force_int_exponents`` -- deprecated
123
+
124
+ - ``force_etuples`` -- deprecated
125
+
126
+ - ``check`` -- if set to ``False`` then assumes that the exponents are
127
+ all valid ``ETuple``; in that case the construction is a bit faster
128
+
129
+ EXAMPLES::
130
+
131
+ sage: from sage.rings.polynomial.polydict import PolyDict
132
+ sage: PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
133
+ PolyDict with representation {(1, 2): 3, (2, 1): 4, (2, 3): 2}
134
+
135
+ sage: PolyDict({(2, 3): 0, (1, 2): 3, (2, 1): 4})
136
+ PolyDict with representation {(1, 2): 3, (2, 1): 4, (2, 3): 0}
137
+
138
+ sage: PolyDict({(0, 0): RIF(-1,1)}) # needs sage.rings.real_interval_field
139
+ PolyDict with representation {(0, 0): 0.?}
140
+
141
+ TESTS::
142
+
143
+ sage: from sage.rings.polynomial.polydict import PolyDict
144
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
145
+ sage: len(f)
146
+ 3
147
+ sage: f = PolyDict({}, zero=3, force_int_exponents=True, force_etuples=True)
148
+ doctest:warning
149
+ ...
150
+ DeprecationWarning: the arguments "zero", "forced_int_exponents"
151
+ and "forced_etuples" of PolyDict constructor are deprecated
152
+ See https://github.com/sagemath/sage/issues/34000 for details.
153
+ sage: f = PolyDict({}, remove_zero=False)
154
+ doctest:warning
155
+ ...
156
+ DeprecationWarning: the argument "remove_zero" of PolyDict
157
+ constructor is deprecated; call the method remove_zeros
158
+ See https://github.com/sagemath/sage/issues/34000 for details.
159
+ """
160
+ if zero is not None or force_int_exponents is not None or force_etuples is not None:
161
+ from sage.misc.superseded import deprecation
162
+ deprecation(34000, 'the arguments "zero", "forced_int_exponents" and "forced_etuples" of PolyDict constructor are deprecated')
163
+
164
+ self.__repn = {}
165
+ cdef bint has_only_etuple = True
166
+ if isinstance(pdict, (tuple, list)):
167
+ for coeff, exp in pdict:
168
+ if check and type(exp) is not ETuple:
169
+ exp = ETuple(exp)
170
+ self.__repn[exp] = coeff
171
+ elif isinstance(pdict, dict):
172
+ if check:
173
+ for k in (<dict> pdict):
174
+ if type(k) is not ETuple:
175
+ has_only_etuple = False
176
+ break
177
+ if has_only_etuple:
178
+ self.__repn = (<dict> pdict).copy()
179
+ else:
180
+ self.__repn = {}
181
+ for exp, coeff in pdict.items():
182
+ if type(exp) is not ETuple:
183
+ exp = ETuple(exp)
184
+ self.__repn[exp] = coeff
185
+ else:
186
+ raise TypeError("pdict must be a dict or a list of pairs (coeff, exponent)")
187
+
188
+ if remove_zero is not None:
189
+ from sage.misc.superseded import deprecation
190
+ deprecation(34000, 'the argument "remove_zero" of PolyDict constructor is deprecated; call the method remove_zeros')
191
+ if remove_zero:
192
+ self.remove_zeros()
193
+
194
+ cdef PolyDict _new(self, dict pdict):
195
+ cdef PolyDict ans = PolyDict.__new__(PolyDict)
196
+ ans.__repn = pdict
197
+ return ans
198
+
199
+ cpdef remove_zeros(self, zero_test=None):
200
+ r"""
201
+ Remove the entries with zero coefficients.
202
+
203
+ INPUT:
204
+
205
+ - ``zero_test`` -- (optional) function that performs test to zero of a coefficient
206
+
207
+ EXAMPLES::
208
+
209
+ sage: from sage.rings.polynomial.polydict import PolyDict
210
+ sage: f = PolyDict({(2, 3):0})
211
+ sage: f
212
+ PolyDict with representation {(2, 3): 0}
213
+ sage: f.remove_zeros()
214
+ sage: f
215
+ PolyDict with representation {}
216
+
217
+ The following example shows how to remove only exact zeros from a ``PolyDict``
218
+ containing univariate power series::
219
+
220
+ sage: R.<t> = PowerSeriesRing(QQ)
221
+ sage: f = PolyDict({(1, 1): O(t), (1, 0): R.zero()})
222
+ sage: f.remove_zeros(lambda s: s.is_zero() and s.prec() is Infinity)
223
+ sage: f
224
+ PolyDict with representation {(1, 1): O(t^1)}
225
+ """
226
+ if not self.__repn:
227
+ return
228
+ # NOTE: in each of the conditional statements below, what the first
229
+ # loop does is equivalent to
230
+ #
231
+ # if all(self.__repn.values()):
232
+ # return
233
+ #
234
+ # and
235
+ #
236
+ # if all(not zero_test(coeff) for coeff in self.__repn.values()):
237
+ # return
238
+ #
239
+ # However, 'all(...)' is badly handled by the Cython compiler and we
240
+ # rather unfold it for efficiency.
241
+ cdef bint has_zero_coefficient = False
242
+ if zero_test is None:
243
+ for coeff in self.__repn.values():
244
+ if not coeff:
245
+ has_zero_coefficient = True
246
+ break
247
+ if not has_zero_coefficient:
248
+ return
249
+ for k in list(self.__repn):
250
+ if not self.__repn[k]:
251
+ del self.__repn[k]
252
+ else:
253
+ for coeff in self.__repn.values():
254
+ if zero_test(coeff):
255
+ has_zero_coefficient = True
256
+ break
257
+ if not has_zero_coefficient:
258
+ return
259
+ for k in list(self.__repn):
260
+ if zero_test(self.__repn[k]):
261
+ del self.__repn[k]
262
+
263
+ def apply_map(self, f):
264
+ r"""
265
+ Apply the map ``f`` on the coefficients (inplace).
266
+
267
+ EXAMPLES::
268
+
269
+ sage: from sage.rings.polynomial.polydict import PolyDict
270
+ sage: f = PolyDict({(1, 0): 1, (1, 1): -2})
271
+ sage: f.apply_map(lambda x: x^2)
272
+ sage: f
273
+ PolyDict with representation {(1, 0): 1, (1, 1): 4}
274
+ """
275
+ for k, v in self.__repn.items():
276
+ self.__repn[k] = f(v)
277
+
278
+ def coerce_coefficients(self, A):
279
+ r"""
280
+ Coerce the coefficients in the parent ``A``.
281
+
282
+ EXAMPLES::
283
+
284
+ sage: from sage.rings.polynomial.polydict import PolyDict
285
+ sage: f = PolyDict({(2, 3): 0})
286
+ sage: f
287
+ PolyDict with representation {(2, 3): 0}
288
+ sage: f.coerce_coefficients(QQ)
289
+ doctest:warning
290
+ ...
291
+ DeprecationWarning: coerce_cefficients is deprecated; use apply_map instead
292
+ See https://github.com/sagemath/sage/issues/34000 for details.
293
+ sage: f
294
+ PolyDict with representation {(2, 3): 0}
295
+ """
296
+ from sage.misc.superseded import deprecation
297
+ deprecation(34000, 'coerce_cefficients is deprecated; use apply_map instead')
298
+ self.apply_map(A.coerce)
299
+
300
+ def __hash__(self):
301
+ """
302
+ Return the hash.
303
+
304
+ EXAMPLES::
305
+
306
+ sage: from sage.rings.polynomial.polydict import PolyDict
307
+ sage: PD1 = PolyDict({(2, 3): 0, (1, 2): 3, (2, 1): 4})
308
+ sage: PD2 = PolyDict({(2, 3): 0, (1, 2): 3, (2, 1): 4})
309
+ sage: PD3 = PolyDict({(2, 3): 1, (1, 2): 3, (2, 1): 4})
310
+ sage: hash(PD1) == hash(PD2)
311
+ True
312
+ sage: hash(PD1) == hash(PD3)
313
+ False
314
+ """
315
+ return hash(frozenset(self.__repn.items()))
316
+
317
+ def __bool__(self):
318
+ """
319
+ Return whether the PolyDict is empty.
320
+
321
+ EXAMPLES::
322
+
323
+ sage: from sage.rings.polynomial.polydict import PolyDict
324
+ sage: PD1 = PolyDict({(2, 3): 0, (1, 2): 3, (2, 1): 4})
325
+ sage: bool(PD1)
326
+ True
327
+ """
328
+ return bool(self.__repn)
329
+
330
+ def __len__(self):
331
+ """
332
+ Return the number of terms of this polynomial.
333
+
334
+ EXAMPLES::
335
+
336
+ sage: from sage.rings.polynomial.polydict import PolyDict
337
+ sage: PD1 = PolyDict({(2, 3): 0, (1, 2): 3, (2, 1): 4})
338
+ sage: len(PD1)
339
+ 3
340
+ """
341
+ return len(self.__repn)
342
+
343
+ def __richcmp__(PolyDict left, PolyDict right, int op):
344
+ """
345
+ Implement the ``__richcmp__`` protocol for `PolyDict`s.
346
+
347
+ EXAMPLES::
348
+
349
+ sage: from sage.rings.polynomial.polydict import PolyDict
350
+ sage: p1 = PolyDict({(0,): 1})
351
+ sage: p2 = PolyDict({(0,): 2})
352
+ sage: p1 == p2
353
+ False
354
+ sage: p1 < p2
355
+ Traceback (most recent call last):
356
+ ...
357
+ TypeError: unsupported comparison between PolyDict
358
+ """
359
+ if op == Py_EQ:
360
+ return left.__repn == right.__repn
361
+ elif op == Py_NE:
362
+ return left.__repn != right.__repn
363
+
364
+ raise TypeError('unsupported comparison between PolyDict')
365
+
366
+ def rich_compare(self, PolyDict other, int op, sortkey=None):
367
+ """
368
+ Compare two `PolyDict`s using a specified term ordering ``sortkey``.
369
+
370
+ EXAMPLES::
371
+
372
+ sage: from sage.rings.polynomial.polydict import PolyDict
373
+ sage: from sage.structure.richcmp import op_EQ, op_NE, op_LT
374
+ sage: p1 = PolyDict({(0,): 1})
375
+ sage: p2 = PolyDict({(0,): 2})
376
+ sage: O = TermOrder()
377
+ sage: p1.rich_compare(PolyDict({(0,): 1}), op_EQ, O.sortkey)
378
+ True
379
+ sage: p1.rich_compare(p2, op_EQ, O.sortkey)
380
+ False
381
+ sage: p1.rich_compare(p2, op_NE, O.sortkey)
382
+ True
383
+ sage: p1.rich_compare(p2, op_LT, O.sortkey)
384
+ True
385
+
386
+ sage: p3 = PolyDict({(3, 2, 4): 1, (3, 2, 5): 2})
387
+ sage: p4 = PolyDict({(3, 2, 4): 1, (3, 2, 3): 2})
388
+ sage: p3.rich_compare(p4, op_LT, O.sortkey)
389
+ False
390
+
391
+ TESTS::
392
+
393
+ sage: from sage.rings.polynomial.polydict import PolyDict
394
+ sage: from sage.structure.richcmp import op_EQ, op_NE, op_LT
395
+ sage: p = PolyDict({})
396
+ sage: ans = p.rich_compare(p, op_EQ)
397
+ doctest:warning
398
+ ...
399
+ DeprecationWarning: the argument "sortkey" will become mandatory in future sage versions
400
+ See https://github.com/sagemath/sage/issues/34000 for details.
401
+ sage: ans
402
+ True
403
+ """
404
+ if sortkey is None:
405
+ from sage.misc.superseded import deprecation
406
+ deprecation(34000, 'the argument "sortkey" will become mandatory in future sage versions')
407
+
408
+ if op == Py_EQ:
409
+ return self.__repn == other.__repn
410
+ elif op == Py_NE:
411
+ return self.__repn != other.__repn
412
+
413
+ if sortkey is None:
414
+ raise TypeError("ordering of PolyDicts requires a sortkey")
415
+
416
+ # start with biggest
417
+ cdef list left = sorted(self.__repn, key=sortkey, reverse=True)
418
+ cdef list right = sorted(other.__repn, key=sortkey, reverse=True)
419
+
420
+ cdef size_t i
421
+ for i in range(min(len(left), len(right))):
422
+ m = left[i]
423
+ n = right[i]
424
+ keym = sortkey(m)
425
+ keyn = sortkey(n)
426
+
427
+ # first compare the leading monomials
428
+ if keym > keyn:
429
+ return rich_to_bool(op, 1)
430
+ elif keym < keyn:
431
+ return rich_to_bool(op, -1)
432
+
433
+ # same leading monomial, compare their coefficients
434
+ coefm = self.__repn[m]
435
+ coefn = other.__repn[n]
436
+ if coefm > coefn:
437
+ return rich_to_bool(op, 1)
438
+ elif coefm < coefn:
439
+ return rich_to_bool(op, -1)
440
+
441
+ return rich_to_bool(op, (len(left) > len(right)) - (len(left) < len(right)))
442
+
443
+ def list(self):
444
+ """
445
+ Return a list that defines ``self``.
446
+
447
+ EXAMPLES::
448
+
449
+ sage: from sage.rings.polynomial.polydict import PolyDict
450
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
451
+ sage: sorted(f.list())
452
+ [[2, [2, 3]], [3, [1, 2]], [4, [2, 1]]]
453
+ """
454
+ return [[c, list(e)] for e, c in self.__repn.items()]
455
+
456
+ def dict(self):
457
+ """
458
+ Return a copy of the dict that defines ``self``.
459
+
460
+ EXAMPLES::
461
+
462
+ sage: from sage.rings.polynomial.polydict import PolyDict
463
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
464
+ sage: f.dict()
465
+ {(1, 2): 3, (2, 1): 4, (2, 3): 2}
466
+ """
467
+ return self.__repn.copy()
468
+
469
+ def coefficients(self):
470
+ """
471
+ Return the coefficients of ``self``.
472
+
473
+ EXAMPLES::
474
+
475
+ sage: from sage.rings.polynomial.polydict import PolyDict
476
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
477
+ sage: sorted(f.coefficients())
478
+ [2, 3, 4]
479
+ """
480
+ return list(self.__repn.values())
481
+
482
+ def exponents(self):
483
+ """
484
+ Return the exponents of ``self``.
485
+
486
+ EXAMPLES::
487
+
488
+ sage: from sage.rings.polynomial.polydict import PolyDict
489
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
490
+ sage: sorted(f.exponents())
491
+ [(1, 2), (2, 1), (2, 3)]
492
+ """
493
+ return list(self.__repn)
494
+
495
+ def __getitem__(self, e):
496
+ """
497
+ Return a coefficient of the polynomial.
498
+
499
+ EXAMPLES::
500
+
501
+ sage: from sage.rings.polynomial.polydict import PolyDict
502
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
503
+ sage: f[1, 2]
504
+ 3
505
+ sage: f[(2, 1)]
506
+ 4
507
+ """
508
+ if type(e) is not ETuple:
509
+ e = ETuple(e)
510
+ return self.__repn[e]
511
+
512
+ def get(self, ETuple e, default=None):
513
+ r"""
514
+ Return the coefficient of the ETuple ``e`` if present and ``default`` otherwise.
515
+
516
+ EXAMPLES::
517
+
518
+ sage: from sage.rings.polynomial.polydict import PolyDict, ETuple
519
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
520
+ sage: f.get(ETuple([1,2]))
521
+ 3
522
+ sage: f.get(ETuple([1,1]), 'hello')
523
+ 'hello'
524
+ """
525
+ return self.__repn.get(e, default)
526
+
527
+ def __repr__(self):
528
+ r"""
529
+ String representation.
530
+ """
531
+ repn = ' '.join(pformat(self.__repn).splitlines())
532
+ return 'PolyDict with representation %s' % repn
533
+
534
+ def degree(self, PolyDict x=None):
535
+ r"""
536
+ Return the total degree or the maximum degree in the variable ``x``.
537
+
538
+ EXAMPLES::
539
+
540
+ sage: from sage.rings.polynomial.polydict import PolyDict
541
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
542
+ sage: f.degree()
543
+ 5
544
+ sage: f.degree(PolyDict({(1, 0): 1}))
545
+ 2
546
+ sage: f.degree(PolyDict({(0, 1): 1}))
547
+ 3
548
+ """
549
+ if x is None:
550
+ return self.total_degree()
551
+ cdef int i = gen_index(x)
552
+ if i < 0:
553
+ raise ValueError('x must be a generator')
554
+ if not self.__repn:
555
+ return -1
556
+ return max((<ETuple> e).get_exp(i) for e in self.__repn)
557
+
558
+ def total_degree(self, tuple w=None):
559
+ r"""
560
+ Return the total degree.
561
+
562
+ INPUT:
563
+
564
+ - ``w`` -- (optional) a tuple of weights
565
+
566
+ EXAMPLES::
567
+
568
+ sage: from sage.rings.polynomial.polydict import PolyDict
569
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
570
+ sage: f.total_degree()
571
+ 5
572
+ sage: f.total_degree((3, 1))
573
+ 9
574
+ sage: PolyDict({}).degree()
575
+ -1
576
+ """
577
+ if not self.__repn:
578
+ return -1
579
+ if w is None:
580
+ return max((<ETuple> e).unweighted_degree() for e in self.__repn)
581
+ else:
582
+ return max((<ETuple> e).weighted_degree(w) for e in self.__repn)
583
+
584
+ def monomial_coefficient(self, mon):
585
+ """
586
+ Return the coefficient of the monomial ``mon``.
587
+
588
+ INPUT:
589
+
590
+ - ``mon`` -- a PolyDict with a single key
591
+
592
+ EXAMPLES::
593
+
594
+ sage: from sage.rings.polynomial.polydict import PolyDict
595
+ sage: f = PolyDict({(2,3):2, (1,2):3, (2,1):4})
596
+ sage: f.monomial_coefficient(PolyDict({(2,1):1}).dict())
597
+ doctest:warning
598
+ ...
599
+ DeprecationWarning: PolyDict.monomial_coefficient is deprecated; use PolyDict.get instead
600
+ See https://github.com/sagemath/sage/issues/34000 for details.
601
+ 4
602
+ """
603
+ from sage.misc.superseded import deprecation
604
+ deprecation(34000, 'PolyDict.monomial_coefficient is deprecated; use PolyDict.get instead')
605
+ K, = mon.keys()
606
+ if K not in self.__repn:
607
+ return 0
608
+ return self.__repn[K]
609
+
610
+ def polynomial_coefficient(self, degrees):
611
+ """
612
+ Return a polydict that defines the coefficient in the current
613
+ polynomial viewed as a tower of polynomial extensions.
614
+
615
+ INPUT:
616
+
617
+ - ``degrees`` -- list of degree restrictions; list elements are ``None``
618
+ if the variable in that position should be unrestricted
619
+
620
+ EXAMPLES::
621
+
622
+ sage: from sage.rings.polynomial.polydict import PolyDict
623
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
624
+ sage: f.polynomial_coefficient([2, None])
625
+ PolyDict with representation {(0, 1): 4, (0, 3): 2}
626
+ sage: f = PolyDict({(0, 3): 2, (0, 2): 3, (2, 1): 4})
627
+ sage: f.polynomial_coefficient([0, None])
628
+ PolyDict with representation {(0, 2): 3, (0, 3): 2}
629
+ """
630
+ nz = []
631
+ cdef int i
632
+ for i in range(len(degrees)):
633
+ if degrees[i] is not None:
634
+ nz.append(i)
635
+ cdef dict ans = {}
636
+ cdef bint exactly_divides
637
+ for S in self.__repn:
638
+ exactly_divides = True
639
+ for j in nz:
640
+ if S[j] != degrees[j]:
641
+ exactly_divides = False
642
+ break
643
+ if exactly_divides:
644
+ t = list(S)
645
+ for m in nz:
646
+ t[m] = 0
647
+ ans[ETuple(t)] = self.__repn[S]
648
+ return self._new(ans)
649
+
650
+ def coefficient(self, mon):
651
+ """
652
+ Return a polydict that defines a polynomial in 1 less number
653
+ of variables that gives the coefficient of mon in this
654
+ polynomial.
655
+
656
+ The coefficient is defined as follows. If f is this
657
+ polynomial, then the coefficient is the sum T/mon where the
658
+ sum is over terms T in f that are exactly divisible by mon.
659
+ """
660
+ K, = mon.keys()
661
+ nz = K.nonzero_positions() # set([i for i in range(len(K)) if K[i] != 0])
662
+ ans = {}
663
+ for S in self.__repn:
664
+ exactly_divides = True
665
+ for j in nz:
666
+ if S[j] != K[j]:
667
+ exactly_divides = False
668
+ break
669
+ if exactly_divides:
670
+ t = list(S)
671
+ for m in nz:
672
+ t[m] = 0
673
+ ans[ETuple(t)] = self.__repn[S]
674
+ return self._new(ans)
675
+
676
+ def is_homogeneous(self, tuple w=None):
677
+ r"""
678
+ Return whether this polynomial is homogeneous.
679
+
680
+ EXAMPLES::
681
+
682
+ sage: from sage.rings.polynomial.polydict import PolyDict
683
+ sage: PolyDict({}).is_homogeneous()
684
+ True
685
+ sage: PolyDict({(1, 2): 1, (0, 3): -2}).is_homogeneous()
686
+ True
687
+ sage: PolyDict({(1, 0): 1, (1, 2): 3}).is_homogeneous()
688
+ False
689
+ """
690
+ if not self.__repn:
691
+ return True
692
+ cdef size_t s
693
+ it = iter(self.__repn)
694
+ if w is None:
695
+ s = (<ETuple> next(it)).unweighted_degree()
696
+ for elt in it:
697
+ if (<ETuple> elt).unweighted_degree() != s:
698
+ return False
699
+ return True
700
+ else:
701
+ s = (<ETuple> next(it)).weighted_degree(w)
702
+ for elt in it:
703
+ if (<ETuple> elt).weighted_degree(w) != s:
704
+ return False
705
+ return True
706
+
707
+ def is_constant(self):
708
+ """
709
+ Return whether this polynomial is constant.
710
+
711
+ EXAMPLES::
712
+
713
+ sage: from sage.rings.polynomial.polydict import PolyDict
714
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
715
+ sage: f.is_constant()
716
+ False
717
+ sage: g = PolyDict({(0, 0): 2})
718
+ sage: g.is_constant()
719
+ True
720
+ sage: h = PolyDict({})
721
+ sage: h.is_constant()
722
+ True
723
+ """
724
+ if not self.__repn:
725
+ return True
726
+ if len(self.__repn) > 1:
727
+ return False
728
+ return not any(self.__repn)
729
+
730
+ def homogenize(self, size_t var):
731
+ r"""
732
+ Return the homogeneization of ``self`` by increasing the degree of the
733
+ variable ``var``.
734
+
735
+ EXAMPLES::
736
+
737
+ sage: from sage.rings.polynomial.polydict import PolyDict
738
+ sage: f = PolyDict({(0, 0): 1, (2, 1): 3, (1, 1): 5})
739
+ sage: f.homogenize(0)
740
+ PolyDict with representation {(2, 1): 8, (3, 0): 1}
741
+ sage: f.homogenize(1)
742
+ PolyDict with representation {(0, 3): 1, (1, 2): 5, (2, 1): 3}
743
+
744
+ sage: PolyDict({(0, 1): 1, (1, 1): -1}).homogenize(0)
745
+ PolyDict with representation {(1, 1): 0}
746
+ """
747
+ cdef dict H = {}
748
+ cdef int deg = self.degree()
749
+ cdef int shift
750
+ for e, val in self.__repn.items():
751
+ shift = deg - (<ETuple> e).unweighted_degree()
752
+ if shift:
753
+ f = (<ETuple> e).eadd_p(shift, var)
754
+ else:
755
+ f = e
756
+ if f in H:
757
+ H[f] += val
758
+ else:
759
+ H[f] = val
760
+ return self._new(H)
761
+
762
+ def latex(self, vars, atomic_exponents=True,
763
+ atomic_coefficients=True, sortkey=None):
764
+ r"""
765
+ Return a nice polynomial latex representation of this PolyDict, where
766
+ the vars are substituted in.
767
+
768
+ INPUT:
769
+
770
+ - ``vars`` -- list
771
+ - ``atomic_exponents`` -- boolean (default: ``True``)
772
+ - ``atomic_coefficients`` -- boolean (default: ``True``)
773
+
774
+ EXAMPLES::
775
+
776
+ sage: from sage.rings.polynomial.polydict import PolyDict
777
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
778
+ sage: f.latex(['a', 'WW'])
779
+ '2 a^{2} WW^{3} + 4 a^{2} WW + 3 a WW^{2}'
780
+
781
+ TESTS:
782
+
783
+ We check that the issue on :issue:`9478` is resolved::
784
+
785
+ sage: R2.<a> = QQ[]
786
+ sage: R3.<xi, x> = R2[]
787
+ sage: print(latex(xi*x))
788
+ \xi x
789
+
790
+ TESTS:
791
+
792
+ Check that :issue:`29604` is fixed::
793
+
794
+ sage: PolyDict({(1, 0): GF(2)(1)}).latex(['x', 'y'])
795
+ 'x'
796
+ """
797
+ if not self:
798
+ return "0"
799
+
800
+ poly = ""
801
+
802
+ sort_kwargs = {'reverse': True}
803
+ if sortkey:
804
+ sort_kwargs['key'] = sortkey
805
+
806
+ E = sorted(self.__repn, **sort_kwargs)
807
+
808
+ try:
809
+ ring = self.__repn[E[0]].parent()
810
+ pos_one = ring.one()
811
+ neg_one = -pos_one
812
+ except (AttributeError, ArithmeticError):
813
+ # AritchmeticError occurs when self.__repn[E[0]] is a tropical
814
+ # semiring element
815
+ # probably self.__repn[E[0]] is not a ring element
816
+ pos_one = 1
817
+ neg_one = -1
818
+
819
+ is_characteristic_2 = bool(pos_one == neg_one)
820
+
821
+ for e in E:
822
+ c = self.__repn[e]
823
+ sign_switch = False
824
+ # First determine the multinomial:
825
+ multi = " ".join([vars[j] +
826
+ ("^{%s}" % e[j] if e[j] != 1 else "")
827
+ for j in e.nonzero_positions(sort=True)])
828
+ # Next determine coefficient of multinomial
829
+ if len(multi) == 0:
830
+ multi = latex(c)
831
+ elif c == neg_one and not is_characteristic_2:
832
+ # handle -1 specially because it's a pain
833
+ if len(poly) > 0:
834
+ sign_switch = True
835
+ else:
836
+ multi = "-%s" % multi
837
+ elif c != pos_one:
838
+ c = latex(c)
839
+ if (not atomic_coefficients and multi and
840
+ ('+' in c or '-' in c or ' ' in c)):
841
+ c = "\\left(%s\\right)" % c
842
+ multi = "%s %s" % (c, multi)
843
+
844
+ # Now add on coefficiented multinomials
845
+ if len(poly) > 0:
846
+ if sign_switch:
847
+ poly = poly + " - "
848
+ else:
849
+ poly = poly + " + "
850
+ poly = poly + multi
851
+ poly = poly.lstrip().rstrip()
852
+ poly = poly.replace("+ -", "- ")
853
+ if len(poly) == 0:
854
+ return "0"
855
+ return poly
856
+
857
+ def poly_repr(self, vars, atomic_exponents=True,
858
+ atomic_coefficients=True, sortkey=None):
859
+ """
860
+ Return a nice polynomial string representation of this PolyDict, where
861
+ the vars are substituted in.
862
+
863
+ INPUT:
864
+
865
+ - ``vars`` -- list
866
+ - ``atomic_exponents`` -- boolean (default: ``True``)
867
+ - ``atomic_coefficients`` -- boolean (default: ``True``)
868
+
869
+ EXAMPLES::
870
+
871
+ sage: from sage.rings.polynomial.polydict import PolyDict
872
+ sage: f = PolyDict({(2,3):2, (1,2):3, (2,1):4})
873
+ sage: f.poly_repr(['a', 'WW'])
874
+ '2*a^2*WW^3 + 4*a^2*WW + 3*a*WW^2'
875
+
876
+ We check to make sure that when we are in characteristic two, we
877
+ don't put negative signs on the generators. ::
878
+
879
+ sage: Integers(2)['x, y'].gens()
880
+ (x, y)
881
+
882
+ We make sure that intervals are correctly represented. ::
883
+
884
+ sage: f = PolyDict({(2, 3): RIF(1/2,3/2), (1, 2): RIF(-1,1)}) # needs sage.rings.real_interval_field
885
+ sage: f.poly_repr(['x', 'y']) # needs sage.rings.real_interval_field
886
+ '1.?*x^2*y^3 + 0.?*x*y^2'
887
+
888
+ TESTS:
889
+
890
+ Check that :issue:`29604` is fixed::
891
+
892
+ sage: PolyDict({(1, 0): GF(4)(1)}).poly_repr(['x', 'y']) # needs sage.rings.finite_rings
893
+ 'x'
894
+
895
+ sage: # needs sage.modules
896
+ sage: P.<x,y> = LaurentPolynomialRing(GF(2), 2)
897
+ sage: P.gens()
898
+ (x, y)
899
+ sage: -x - y
900
+ x + y
901
+ """
902
+ poly = ""
903
+ sort_kwargs = {'reverse': True}
904
+ if sortkey:
905
+ sort_kwargs['key'] = sortkey
906
+
907
+ E = sorted(self.__repn, **sort_kwargs)
908
+
909
+ if not E:
910
+ return "0"
911
+ try:
912
+ ring = self.__repn[E[0]].parent()
913
+ pos_one = ring.one()
914
+ neg_one = -pos_one
915
+ except (AttributeError, ArithmeticError):
916
+ # AritchmeticError occurs when self.__repn[E[0]] is a tropical
917
+ # semiring element
918
+ # probably self.__repn[E[0]] is not a ring element
919
+ pos_one = 1
920
+ neg_one = -1
921
+
922
+ is_characteristic_2 = bool(pos_one == neg_one)
923
+
924
+ for e in E:
925
+ c = self.__repn[e]
926
+ sign_switch = False
927
+ # First determine the multinomial:
928
+ multi = ""
929
+ for j in e.nonzero_positions(sort=True):
930
+ if multi:
931
+ multi = multi + "*"
932
+ multi = multi + vars[j]
933
+ if e[j] != 1:
934
+ if atomic_exponents:
935
+ multi = multi + "^%s" % e[j]
936
+ else:
937
+ multi = multi + "^(%s)" % e[j]
938
+ # Next determine coefficient of multinomial
939
+ if not multi:
940
+ multi = str(c)
941
+ elif c == neg_one and not is_characteristic_2:
942
+ # handle -1 specially because it's a pain
943
+ if poly:
944
+ sign_switch = True
945
+ else:
946
+ multi = "-%s" % multi
947
+ elif not c == pos_one:
948
+ if not atomic_coefficients:
949
+ c = str(c)
950
+ if c.find("+") != -1 or c.find("-") != -1 or c.find(" ") != -1:
951
+ c = "(%s)" % c
952
+ multi = "%s*%s" % (c, multi)
953
+
954
+ # Now add on coefficiented multinomials
955
+ if poly:
956
+ if sign_switch:
957
+ poly = poly + " - "
958
+ else:
959
+ poly = poly + " + "
960
+ poly = poly + multi
961
+ poly = poly.lstrip().rstrip()
962
+ poly = poly.replace("+ -", "- ")
963
+ if not poly:
964
+ return "0"
965
+ return poly
966
+
967
+ def __iadd__(PolyDict self, PolyDict other):
968
+ r"""
969
+ Inplace addition.
970
+
971
+ EXAMPLES::
972
+
973
+ sage: from sage.rings.polynomial.polydict import PolyDict
974
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
975
+ sage: g = PolyDict({(1, 5): -3, (2, 3): -2, (1, 1): 3})
976
+ sage: f += g
977
+ sage: f
978
+ PolyDict with representation {(1, 1): 3, (1, 2): 3, (1, 5): -3, (2, 1): 4, (2, 3): 0}
979
+ """
980
+ cdef dict D = self.__repn
981
+ if self is other:
982
+ for e in D:
983
+ v = D[e]
984
+ D[e] += v
985
+ else:
986
+ for e, c in other.__repn.items():
987
+ if e in D:
988
+ D[e] += c
989
+ else:
990
+ D[e] = c
991
+ return self
992
+
993
+ def __neg__(self):
994
+ r"""
995
+ TESTS::
996
+
997
+ sage: from sage.rings.polynomial.polydict import PolyDict
998
+ sage: -PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
999
+ PolyDict with representation {(1, 2): -3, (2, 1): -4, (2, 3): -2}
1000
+ """
1001
+ cdef dict D = self.__repn.copy()
1002
+ for e, c in D.items():
1003
+ D[e] = -c
1004
+ return self._new(D)
1005
+
1006
+ def __add__(PolyDict self, PolyDict other):
1007
+ """
1008
+ Add two PolyDict's in the same number of variables.
1009
+
1010
+ EXAMPLES:
1011
+
1012
+ We add two polynomials in 2 variables::
1013
+
1014
+ sage: from sage.rings.polynomial.polydict import PolyDict
1015
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1016
+ sage: g = PolyDict({(1, 5): -3, (2, 3): -2, (1, 1): 3})
1017
+ sage: f + g
1018
+ PolyDict with representation {(1, 1): 3, (1, 2): 3, (1, 5): -3, (2, 1): 4, (2, 3): 0}
1019
+
1020
+ sage: K = GF(2)
1021
+ sage: f = PolyDict({(1, 1): K(1)})
1022
+ sage: f + f
1023
+ PolyDict with representation {(1, 1): 0}
1024
+ """
1025
+ cdef dict D = self.__repn
1026
+ cdef dict R = other.__repn
1027
+ if len(D) < len(R):
1028
+ D, R = R, D
1029
+ D = D.copy()
1030
+ for e, c in R.items():
1031
+ if e in D:
1032
+ D[e] += c
1033
+ else:
1034
+ D[e] = c
1035
+ return self._new(D)
1036
+
1037
+ def __mul__(PolyDict self, PolyDict right):
1038
+ """
1039
+ Multiply two PolyDict's in the same number of variables.
1040
+
1041
+ The algorithm do not test whether a product of coefficients is zero
1042
+ or whether a final coefficient is zero because there is no reliable way
1043
+ to do so in general (eg power series ring or `p`-adic rings).
1044
+
1045
+ EXAMPLES:
1046
+
1047
+ Multiplication of polynomials in 2 variables with rational coefficients::
1048
+
1049
+ sage: from sage.rings.polynomial.polydict import PolyDict
1050
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1051
+ sage: g = PolyDict({(1, 5): -3, (2, 3): -2, (1, 1): 3})
1052
+ sage: f * g
1053
+ PolyDict with representation {(2, 3): 9, (2, 7): -9, (3, 2): 12, (3, 4): 6, (3, 5): -6, (3, 6): -12, (3, 8): -6, (4, 4): -8, (4, 6): -4}
1054
+
1055
+ Multiplication of polynomials in 2 variables with power series coefficients::
1056
+
1057
+ sage: R.<t> = PowerSeriesRing(QQ)
1058
+ sage: f = PolyDict({(1, 0): 1 + O(t), (0, 1): 1 + O(t^2)})
1059
+ sage: g = PolyDict({(1, 0): 1, (0, 1): -1})
1060
+ sage: f * g
1061
+ PolyDict with representation {(0, 2): -1 + O(t^2), (1, 1): O(t^1), (2, 0): 1 + O(t)}
1062
+ sage: f = PolyDict({(1, 0): O(t), (0, 1): O(t)})
1063
+ sage: g = PolyDict({(1, 0): 1, (0, 1): O(t)})
1064
+ sage: f * g
1065
+ PolyDict with representation {(0, 2): O(t^2), (1, 1): O(t^1), (2, 0): O(t^1)}
1066
+ """
1067
+ cdef PyObject *cc
1068
+ cdef dict newpoly
1069
+ if not self.__repn or not right.__repn:
1070
+ return self._new({})
1071
+ newpoly = {}
1072
+ for e0, c0 in self.__repn.items():
1073
+ for e1, c1 in right.__repn.items():
1074
+ e = (<ETuple> e0).eadd(<ETuple> e1)
1075
+ c = c0 * c1
1076
+ cc = PyDict_GetItem(newpoly, e)
1077
+ if cc == <PyObject*> 0:
1078
+ PyDict_SetItem(newpoly, e, c)
1079
+ else:
1080
+ PyDict_SetItem(newpoly, e, <object> cc + c)
1081
+ return self._new(newpoly)
1082
+
1083
+ def scalar_rmult(self, s):
1084
+ """
1085
+ Return the right scalar multiplication of ``self`` by ``s``.
1086
+
1087
+ EXAMPLES::
1088
+
1089
+ sage: from sage.rings.polynomial.polydict import PolyDict
1090
+
1091
+ sage: x, y = FreeMonoid(2, 'x, y').gens() # a strange object to live in a polydict, but non-commutative! # needs sage.combinat
1092
+ sage: f = PolyDict({(2, 3): x}) # needs sage.combinat
1093
+ sage: f.scalar_rmult(y) # needs sage.combinat
1094
+ PolyDict with representation {(2, 3): x*y}
1095
+
1096
+ sage: f = PolyDict({(2,3):2, (1, 2): 3, (2, 1): 4})
1097
+ sage: f.scalar_rmult(-2)
1098
+ PolyDict with representation {(1, 2): -6, (2, 1): -8, (2, 3): -4}
1099
+ sage: f.scalar_rmult(RIF(-1,1)) # needs sage.rings.real_interval_field
1100
+ PolyDict with representation {(1, 2): 0.?e1, (2, 1): 0.?e1, (2, 3): 0.?e1}
1101
+ """
1102
+ cdef dict v = {}
1103
+ for e, c in self.__repn.items():
1104
+ v[e] = c * s
1105
+ return self._new(v)
1106
+
1107
+ def scalar_lmult(self, s):
1108
+ """
1109
+ Return the left scalar multiplication of ``self`` by ``s``.
1110
+
1111
+ EXAMPLES::
1112
+
1113
+ sage: from sage.rings.polynomial.polydict import PolyDict
1114
+
1115
+ sage: x, y = FreeMonoid(2, 'x, y').gens() # a strange object to live in a polydict, but non-commutative! # needs sage.combinat
1116
+ sage: f = PolyDict({(2,3):x}) # needs sage.combinat
1117
+ sage: f.scalar_lmult(y) # needs sage.combinat
1118
+ PolyDict with representation {(2, 3): y*x}
1119
+
1120
+ sage: f = PolyDict({(2,3):2, (1,2):3, (2,1):4})
1121
+ sage: f.scalar_lmult(-2)
1122
+ PolyDict with representation {(1, 2): -6, (2, 1): -8, (2, 3): -4}
1123
+ sage: f.scalar_lmult(RIF(-1,1)) # needs sage.rings.real_interval_field
1124
+ PolyDict with representation {(1, 2): 0.?e1, (2, 1): 0.?e1, (2, 3): 0.?e1}
1125
+ """
1126
+ cdef dict v = {}
1127
+ for e, c in self.__repn.items():
1128
+ v[e] = s * c
1129
+ return self._new(v)
1130
+
1131
+ def term_lmult(self, exponent, s):
1132
+ """
1133
+ Return this element multiplied by ``s`` on the left and with exponents
1134
+ shifted by ``exponent``.
1135
+
1136
+ INPUT:
1137
+
1138
+ - ``exponent`` -- a ETuple
1139
+
1140
+ - ``s`` -- a scalar
1141
+
1142
+ EXAMPLES::
1143
+
1144
+ sage: from sage.rings.polynomial.polydict import ETuple, PolyDict
1145
+
1146
+ sage: x, y = FreeMonoid(2, 'x, y').gens() # a strange object to live in a polydict, but non-commutative! # needs sage.combinat
1147
+ sage: f = PolyDict({(2, 3): x}) # needs sage.combinat
1148
+ sage: f.term_lmult(ETuple((1, 2)), y) # needs sage.combinat
1149
+ PolyDict with representation {(3, 5): y*x}
1150
+
1151
+ sage: f = PolyDict({(2,3): 2, (1,2): 3, (2,1): 4})
1152
+ sage: f.term_lmult(ETuple((1, 2)), -2)
1153
+ PolyDict with representation {(2, 4): -6, (3, 3): -8, (3, 5): -4}
1154
+ """
1155
+ cdef dict v = {}
1156
+ for e, c in self.__repn.items():
1157
+ v[(<ETuple> e).eadd(exponent)] = s*c
1158
+ return self._new(v)
1159
+
1160
+ def term_rmult(self, exponent, s):
1161
+ """
1162
+ Return this element multiplied by ``s`` on the right and with exponents
1163
+ shifted by ``exponent``.
1164
+
1165
+ INPUT:
1166
+
1167
+ - ``exponent`` -- a ETuple
1168
+
1169
+ - ``s`` -- a scalar
1170
+
1171
+ EXAMPLES::
1172
+
1173
+ sage: from sage.rings.polynomial.polydict import ETuple, PolyDict
1174
+
1175
+ sage: x, y = FreeMonoid(2, 'x, y').gens() # a strange object to live in a polydict, but non-commutative! # needs sage.combinat
1176
+ sage: f = PolyDict({(2, 3): x}) # needs sage.combinat
1177
+ sage: f.term_rmult(ETuple((1, 2)), y) # needs sage.combinat
1178
+ PolyDict with representation {(3, 5): x*y}
1179
+
1180
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1181
+ sage: f.term_rmult(ETuple((1, 2)), -2)
1182
+ PolyDict with representation {(2, 4): -6, (3, 3): -8, (3, 5): -4}
1183
+ """
1184
+ cdef dict v = {}
1185
+ for e, c in self.__repn.items():
1186
+ v[(<ETuple> e).eadd(exponent)] = c * s
1187
+ return self._new(v)
1188
+
1189
+ def __sub__(PolyDict self, PolyDict other):
1190
+ """
1191
+ Subtract two PolyDict's.
1192
+
1193
+ EXAMPLES::
1194
+
1195
+ sage: from sage.rings.polynomial.polydict import PolyDict
1196
+ sage: f = PolyDict({(2,3):2, (1,2):3, (2,1):4})
1197
+ sage: g = PolyDict({(2,3):2, (1,1):-10})
1198
+ sage: f - g
1199
+ PolyDict with representation {(1, 1): 10, (1, 2): 3, (2, 1): 4, (2, 3): 0}
1200
+ sage: g - f
1201
+ PolyDict with representation {(1, 1): -10, (1, 2): -3, (2, 1): -4, (2, 3): 0}
1202
+ sage: f - f
1203
+ PolyDict with representation {(1, 2): 0, (2, 1): 0, (2, 3): 0}
1204
+ """
1205
+ cdef dict D = self.__repn.copy()
1206
+ cdef dict R = other.__repn
1207
+ for e, c in R.items():
1208
+ if e in D:
1209
+ D[e] -= c
1210
+ else:
1211
+ D[e] = -c
1212
+ return self._new(D)
1213
+
1214
+ def derivative_i(self, size_t i):
1215
+ r"""
1216
+ Return the derivative of ``self`` with respect to the ``i``-th variable.
1217
+
1218
+ EXAMPLES::
1219
+
1220
+ sage: from sage.rings.polynomial.polydict import PolyDict
1221
+ sage: PolyDict({(1, 1): 1}).derivative_i(0)
1222
+ PolyDict with representation {(0, 1): 1}
1223
+ """
1224
+ cdef dict D = {}
1225
+ for e, c in self.__repn.items():
1226
+ D[(<ETuple> e).eadd_p(-1, i)] = c * (<ETuple> e).get_exp(i)
1227
+ return self._new(D)
1228
+
1229
+ def derivative(self, PolyDict x):
1230
+ r"""
1231
+ Return the derivative of ``self`` with respect to ``x``.
1232
+
1233
+ EXAMPLES::
1234
+
1235
+ sage: from sage.rings.polynomial.polydict import PolyDict
1236
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1237
+ sage: f.derivative(PolyDict({(1, 0): 1}))
1238
+ PolyDict with representation {(0, 2): 3, (1, 1): 8, (1, 3): 4}
1239
+ sage: f.derivative(PolyDict({(0, 1): 1}))
1240
+ PolyDict with representation {(1, 1): 6, (2, 0): 4, (2, 2): 6}
1241
+
1242
+ sage: PolyDict({(-1,): 1}).derivative(PolyDict({(1,): 1}))
1243
+ PolyDict with representation {(-2,): -1}
1244
+ sage: PolyDict({(-2,): 1}).derivative(PolyDict({(1,): 1}))
1245
+ PolyDict with representation {(-3,): -2}
1246
+
1247
+ sage: PolyDict({}).derivative(PolyDict({(1, 1): 1}))
1248
+ Traceback (most recent call last):
1249
+ ...
1250
+ ValueError: x must be a generator
1251
+ """
1252
+ cdef int i = gen_index(x)
1253
+ if i < 0:
1254
+ raise ValueError('x must be a generator')
1255
+ return self.derivative_i(i)
1256
+
1257
+ def integral_i(self, size_t i):
1258
+ r"""
1259
+ Return the derivative of ``self`` with respect to the ``i``-th variable.
1260
+
1261
+ EXAMPLES::
1262
+
1263
+ sage: from sage.rings.polynomial.polydict import PolyDict
1264
+ sage: PolyDict({(1, 1): 1}).integral_i(0)
1265
+ PolyDict with representation {(2, 1): 1/2}
1266
+ """
1267
+ cdef dict D = {}
1268
+ cdef int exp
1269
+ for e, c in self.__repn.items():
1270
+ exp = (<ETuple> e).get_exp(i)
1271
+ if exp == -1:
1272
+ raise ArithmeticError('integral of monomial with exponent -1')
1273
+ D[(<ETuple> e).eadd_p(1, i)] = c / (exp + 1)
1274
+ return self._new(D)
1275
+
1276
+ def integral(self, PolyDict x):
1277
+ r"""
1278
+ Return the integral of ``self`` with respect to ``x``.
1279
+
1280
+ EXAMPLES::
1281
+
1282
+ sage: from sage.rings.polynomial.polydict import PolyDict
1283
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1284
+ sage: f.integral(PolyDict({(1, 0): 1}))
1285
+ PolyDict with representation {(2, 2): 3/2, (3, 1): 4/3, (3, 3): 2/3}
1286
+ sage: f.integral(PolyDict({(0, 1): 1}))
1287
+ PolyDict with representation {(1, 3): 1, (2, 2): 2, (2, 4): 1/2}
1288
+
1289
+ sage: PolyDict({(-1,): 1}).integral(PolyDict({(1,): 1}))
1290
+ Traceback (most recent call last):
1291
+ ...
1292
+ ArithmeticError: integral of monomial with exponent -1
1293
+ sage: PolyDict({(-2,): 1}).integral(PolyDict({(1,): 1}))
1294
+ PolyDict with representation {(-1,): -1}
1295
+ sage: PolyDict({}).integral(PolyDict({(1, 1): 1}))
1296
+ Traceback (most recent call last):
1297
+ ...
1298
+ ValueError: x must be a generator
1299
+ """
1300
+ cdef int i = gen_index(x)
1301
+ if i < 0:
1302
+ raise ValueError('x must be a generator')
1303
+ return self.integral_i(i)
1304
+
1305
+ def lcmt(self, greater_etuple):
1306
+ """
1307
+ Provides functionality of lc, lm, and lt by calling the tuple
1308
+ compare function on the provided term order T.
1309
+
1310
+ INPUT:
1311
+
1312
+ - ``greater_etuple`` -- a term order
1313
+ """
1314
+ try:
1315
+ return ETuple(reduce(greater_etuple, self.__repn))
1316
+ except KeyError:
1317
+ raise ArithmeticError("%s not supported", greater_etuple)
1318
+
1319
+ def __reduce__(self):
1320
+ """
1321
+
1322
+ EXAMPLES::
1323
+
1324
+ sage: from sage.rings.polynomial.polydict import PolyDict
1325
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1326
+ sage: loads(dumps(f)) == f
1327
+ True
1328
+ """
1329
+ return PolyDict, (self.__repn,)
1330
+
1331
+ def min_exp(self):
1332
+ """
1333
+ Return an ETuple containing the minimum exponents appearing. If
1334
+ there are no terms at all in the PolyDict, it returns None.
1335
+
1336
+ The nvars parameter is necessary because a PolyDict doesn't know it
1337
+ from the data it has (and an empty PolyDict offers no clues).
1338
+
1339
+ EXAMPLES::
1340
+
1341
+ sage: from sage.rings.polynomial.polydict import PolyDict
1342
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1343
+ sage: f.min_exp()
1344
+ (1, 1)
1345
+ sage: PolyDict({}).min_exp() # returns None
1346
+ """
1347
+ cdef ETuple r
1348
+ if self.__repn:
1349
+ it = iter(self.__repn)
1350
+ r = next(it)
1351
+ for e in it:
1352
+ r = r.emin(e)
1353
+ return r
1354
+ else:
1355
+ return None
1356
+
1357
+ def max_exp(self):
1358
+ """
1359
+ Return an ETuple containing the maximum exponents appearing. If
1360
+ there are no terms at all in the PolyDict, it returns None.
1361
+
1362
+ The nvars parameter is necessary because a PolyDict doesn't know it
1363
+ from the data it has (and an empty PolyDict offers no clues).
1364
+
1365
+ EXAMPLES::
1366
+
1367
+ sage: from sage.rings.polynomial.polydict import PolyDict
1368
+ sage: f = PolyDict({(2, 3): 2, (1, 2): 3, (2, 1): 4})
1369
+ sage: f.max_exp()
1370
+ (2, 3)
1371
+ sage: PolyDict({}).max_exp() # returns None
1372
+ """
1373
+ cdef ETuple r
1374
+ if self.__repn:
1375
+ it = iter(self.__repn)
1376
+ r = next(it)
1377
+ for e in it:
1378
+ r = r.emax(e)
1379
+ return r
1380
+ else:
1381
+ return None
1382
+
1383
+ cdef inline bint dual_etuple_iter(ETuple self, ETuple other, size_t *ind1, size_t *ind2, size_t *index, int *exp1, int *exp2) noexcept:
1384
+ """
1385
+ This function is a crucial helper function for a number of methods of
1386
+ the ETuple class.
1387
+
1388
+ This is a rather fragile function. Perhaps some Cython guru could make
1389
+ it appear a little less stilted -- a principal difficulty is passing
1390
+ C types by reference. In any case, the complicated features of looping
1391
+ through two ETuple _data members is all packaged up right here and
1392
+ shouldn't be allowed to spread.
1393
+ """
1394
+ if ind1[0] >= self._nonzero and ind2[0] >= other._nonzero:
1395
+ return 0
1396
+ if ind1[0] < self._nonzero and ind2[0] < other._nonzero:
1397
+ if self._data[2*ind1[0]] == other._data[2*ind2[0]]:
1398
+ exp1[0] = self._data[2*ind1[0]+1]
1399
+ exp2[0] = other._data[2*ind2[0]+1]
1400
+ index[0] = self._data[2*ind1[0]]
1401
+ ind1[0] += 1
1402
+ ind2[0] += 1
1403
+ elif self._data[2*ind1[0]] > other._data[2*ind2[0]]:
1404
+ exp1[0] = 0
1405
+ exp2[0] = other._data[2*ind2[0]+1]
1406
+ index[0] = other._data[2*ind2[0]]
1407
+ ind2[0] += 1
1408
+ else:
1409
+ exp1[0] = self._data[2*ind1[0]+1]
1410
+ exp2[0] = 0
1411
+ index[0] = self._data[2*ind1[0]]
1412
+ ind1[0] += 1
1413
+ else:
1414
+ if ind2[0] >= other._nonzero:
1415
+ exp1[0] = self._data[2*ind1[0]+1]
1416
+ exp2[0] = 0
1417
+ index[0] = self._data[2*ind1[0]]
1418
+ ind1[0] += 1
1419
+ elif ind1[0] >= self._nonzero:
1420
+ exp1[0] = 0
1421
+ exp2[0] = other._data[2*ind2[0]+1]
1422
+ index[0] = other._data[2*ind2[0]]
1423
+ ind2[0] += 1
1424
+ return 1
1425
+
1426
+ cdef class ETuple:
1427
+ """
1428
+ Representation of the exponents of a polydict monomial. If
1429
+ (0,0,3,0,5) is the exponent tuple of x_2^3*x_4^5 then this class
1430
+ only stores {2:3, 4:5} instead of the full tuple. This sparse
1431
+ information may be obtained by provided methods.
1432
+
1433
+ The index/value data is all stored in the _data C int array member
1434
+ variable. For the example above, the C array would contain
1435
+ 2,3,4,5. The indices are interlaced with the values.
1436
+
1437
+ This data structure is very nice to work with for some functions
1438
+ implemented in this class, but tricky for others. One reason that
1439
+ I really like the format is that it requires a single memory
1440
+ allocation for all of the values. A hash table would require more
1441
+ allocations and presumably be slower. I didn't benchmark this
1442
+ question (although, there is no question that this is much faster
1443
+ than the prior use of python dicts).
1444
+ """
1445
+ cdef ETuple _new(self):
1446
+ """
1447
+ Quickly create a new initialized ETuple with the
1448
+ same length as ``self``.
1449
+ """
1450
+ cdef type t = type(self)
1451
+ cdef ETuple x = <ETuple>t.__new__(t)
1452
+ x._length = self._length
1453
+ return x
1454
+
1455
+ def __init__(self, data=None, length=None):
1456
+ """
1457
+ - ``ETuple()`` -> an empty ETuple
1458
+ - ``ETuple(sequence)`` -> ETuple initialized from sequence's items
1459
+
1460
+ If the argument is an ETuple, the return value is the same object.
1461
+
1462
+ EXAMPLES::
1463
+
1464
+ sage: from sage.rings.polynomial.polydict import ETuple
1465
+ sage: ETuple([1, 1, 0])
1466
+ (1, 1, 0)
1467
+ sage: ETuple({int(1): int(2)}, int(3))
1468
+ (0, 2, 0)
1469
+ sage: ETuple([1, -1, 0])
1470
+ (1, -1, 0)
1471
+
1472
+ TESTS:
1473
+
1474
+ Iterators are not accepted::
1475
+
1476
+ sage: ETuple(iter([2, 3, 4]))
1477
+ Traceback (most recent call last):
1478
+ ...
1479
+ TypeError: Error in ETuple((), <list... object at ...>, None)
1480
+ """
1481
+ if data is None:
1482
+ return
1483
+ cdef size_t ind
1484
+ cdef int v
1485
+ from sage.combinat.integer_vector import IntegerVector
1486
+ if isinstance(data, ETuple):
1487
+ self._length = (<ETuple>data)._length
1488
+ self._nonzero = (<ETuple>data)._nonzero
1489
+ self._data = <int*>sig_malloc(sizeof(int)*self._nonzero*2)
1490
+ memcpy(self._data, (<ETuple>data)._data, sizeof(int)*self._nonzero*2)
1491
+ elif isinstance(data, dict) and isinstance(length, int):
1492
+ self._length = length
1493
+ self._nonzero = len(data)
1494
+ self._data = <int*>sig_malloc(sizeof(int)*self._nonzero*2)
1495
+ nz_elts = sorted(data.items())
1496
+ ind = 0
1497
+ for index, exp in nz_elts:
1498
+ self._data[2*ind] = index
1499
+ self._data[2*ind+1] = exp
1500
+ ind += 1
1501
+ elif isinstance(data, (list, tuple, IntegerVector)):
1502
+ self._length = len(data)
1503
+ self._nonzero = 0
1504
+ for v in data:
1505
+ if v != 0:
1506
+ self._nonzero += 1
1507
+ ind = 0
1508
+ self._data = <int*>sig_malloc(sizeof(int)*self._nonzero*2)
1509
+ for i from 0 <= i < self._length:
1510
+ v = data[i]
1511
+ if v != 0:
1512
+ self._data[ind] = i
1513
+ self._data[ind+1] = v
1514
+ ind += 2
1515
+ else:
1516
+ raise TypeError("Error in ETuple(%s, %s, %s)" % (self, data, length))
1517
+
1518
+ def __cinit__(self):
1519
+ self._data = <int*>0
1520
+
1521
+ def __dealloc__(self):
1522
+ if self._data != <int*>0:
1523
+ sig_free(self._data)
1524
+
1525
+ def __bool__(self):
1526
+ r"""
1527
+ Return whether ``self`` is nonzero.
1528
+
1529
+ TESTS::
1530
+
1531
+ sage: from sage.rings.polynomial.polydict import ETuple
1532
+ sage: bool(ETuple([1]))
1533
+ True
1534
+ sage: bool(ETuple([]))
1535
+ False
1536
+ sage: bool(ETuple([0, 0, 0]))
1537
+ False
1538
+ """
1539
+ return bool(self._nonzero)
1540
+
1541
+ # methods to simulate tuple
1542
+
1543
+ def __add__(ETuple self, ETuple other):
1544
+ """
1545
+ ``x.__add__(n) <==> x+n``.
1546
+
1547
+ Concatenate two ETuples.
1548
+
1549
+ EXAMPLES::
1550
+
1551
+ sage: from sage.rings.polynomial.polydict import ETuple
1552
+ sage: ETuple([1, 1, 0]) + ETuple({int(1): int(2)}, int(3))
1553
+ (1, 1, 0, 0, 2, 0)
1554
+ """
1555
+ cdef size_t index = 0
1556
+ cdef ETuple result = <ETuple>ETuple.__new__(ETuple)
1557
+ result._length = self._length+other._length
1558
+ result._nonzero = self._nonzero+other._nonzero
1559
+ result._data = <int*>sig_malloc(sizeof(int)*result._nonzero*2)
1560
+ for index from 0 <= index < self._nonzero:
1561
+ result._data[2*index] = self._data[2*index]
1562
+ result._data[2*index+1] = self._data[2*index+1]
1563
+ for index from 0 <= index < other._nonzero:
1564
+ result._data[2*(index+self._nonzero)] = other._data[2*index]+self._length # offset the second tuple (append to end!)
1565
+ result._data[2*(index+self._nonzero)+1] = other._data[2*index+1]
1566
+ return result
1567
+
1568
+ def __mul__(ETuple self, factor):
1569
+ """
1570
+ ``x.__mul__(n) <==> x*n``.
1571
+
1572
+ EXAMPLES::
1573
+
1574
+ sage: from sage.rings.polynomial.polydict import ETuple
1575
+ sage: ETuple([1, 2, 3])*2
1576
+ (1, 2, 3, 1, 2, 3)
1577
+ """
1578
+ cdef int _factor = factor
1579
+ cdef ETuple result = <ETuple>ETuple.__new__(ETuple)
1580
+ if factor <= 0:
1581
+ result._length = 0
1582
+ result._nonzero = 0
1583
+ return result
1584
+ cdef size_t index
1585
+ cdef size_t f
1586
+ result._length = self._length * factor
1587
+ result._nonzero = self._nonzero * factor
1588
+ result._data = <int*>sig_malloc(sizeof(int)*result._nonzero*2)
1589
+ for index from 0 <= index < self._nonzero:
1590
+ for f from 0 <= f < factor:
1591
+ result._data[2*(f*self._nonzero+index)] = self._data[2*index]+f*self._length
1592
+ result._data[2*(f*self._nonzero+index)+1] = self._data[2*index+1]
1593
+ return result
1594
+
1595
+ def __getitem__(self, i):
1596
+ """
1597
+ EXAMPLES::
1598
+
1599
+ sage: from sage.rings.polynomial.polydict import ETuple
1600
+ sage: m = ETuple([1, 2, 0, 3])
1601
+ sage: m[2]
1602
+ 0
1603
+ sage: m[1]
1604
+ 2
1605
+ sage: e = ETuple([1, 2, 3])
1606
+ sage: e[1:]
1607
+ (2, 3)
1608
+ sage: e[:1]
1609
+ (1,)
1610
+ """
1611
+ cdef size_t ind
1612
+ if isinstance(i, slice):
1613
+ start, stop = i.start, i.stop
1614
+ if start is None:
1615
+ start = 0
1616
+ elif start < 0:
1617
+ start = start % self._length
1618
+ elif start > self._length:
1619
+ start = self._length
1620
+
1621
+ if stop is None or stop > self._length:
1622
+ stop = self._length
1623
+ elif stop < 0:
1624
+ stop = stop % self._length
1625
+
1626
+ # this is not particularly fast, but I doubt many people care
1627
+ # if you do, feel free to tweak!
1628
+ d = [self[ind] for ind from start <= ind < stop]
1629
+ return ETuple(d)
1630
+ else:
1631
+ return self.get_exp(i)
1632
+
1633
+ cdef size_t get_position(self, size_t i, size_t start, size_t end) noexcept:
1634
+ r"""
1635
+ Return where to insert ``i`` in the data between ``start`` and ``end``.
1636
+ """
1637
+ if end <= start:
1638
+ return start
1639
+ cdef size_t left = start
1640
+ cdef size_t right = end - 1
1641
+ cdef size_t mid
1642
+ if self._data[2 * left] >= i:
1643
+ return left
1644
+ if self._data[2 * right] < i:
1645
+ return end
1646
+ if self._data[2 * right] == i:
1647
+ return right
1648
+ while right - left > 1:
1649
+ mid = (left + right) / 2
1650
+ if self._data[2 * mid] == i:
1651
+ return mid
1652
+ if self._data[2 * mid] > i:
1653
+ right = mid
1654
+ else:
1655
+ left = mid
1656
+ return right
1657
+
1658
+ cdef int get_exp(self, size_t i) noexcept:
1659
+ """
1660
+ Return the exponent for the ``i``-th variable.
1661
+ """
1662
+ cdef size_t ind = self.get_position(i, 0, self._nonzero)
1663
+ if ind != self._nonzero and self._data[2 * ind] == i:
1664
+ return self._data[2 * ind + 1]
1665
+ return 0
1666
+
1667
+ def __hash__(self):
1668
+ """
1669
+ x.__hash__() <==> hash(x)
1670
+ """
1671
+ cdef int i
1672
+ cdef int result = 0
1673
+ for i in range(self._nonzero):
1674
+ result += (1000003 * result) ^ self._data[2*i]
1675
+ result += (1000003 * result) ^ self._data[2*i+1]
1676
+ result = (1000003 * result) ^ self._length
1677
+ return result
1678
+
1679
+ def __len__(self):
1680
+ """
1681
+ ``x.__len__() <==> len(x)``.
1682
+
1683
+ EXAMPLES::
1684
+
1685
+ sage: from sage.rings.polynomial.polydict import ETuple
1686
+ sage: e = ETuple([1, 0, 2, 0, 3])
1687
+ sage: len(e)
1688
+ 5
1689
+ """
1690
+ return self._length
1691
+
1692
+ def __contains__(self, elem):
1693
+ """
1694
+ ``x.__contains__(n) <==> n in x``.
1695
+
1696
+ EXAMPLES::
1697
+
1698
+ sage: from sage.rings.polynomial.polydict import ETuple
1699
+ sage: e = ETuple({int(1): int(2)}, int(3))
1700
+ sage: e
1701
+ (0, 2, 0)
1702
+ sage: 1 in e
1703
+ False
1704
+ sage: 2 in e
1705
+ True
1706
+ """
1707
+ if elem==0:
1708
+ return self._length > self._nonzero
1709
+
1710
+ cdef size_t ind = 0
1711
+ for ind in range(self._nonzero):
1712
+ if elem == self._data[2 * ind + 1]:
1713
+ return True
1714
+ return False
1715
+
1716
+ def __richcmp__(ETuple self, ETuple other, op):
1717
+ """
1718
+ EXAMPLES::
1719
+
1720
+ sage: from sage.rings.polynomial.polydict import ETuple
1721
+ sage: ETuple([1, 1, 0])<ETuple([1, 1, 0])
1722
+ False
1723
+ sage: ETuple([1, 1, 0])<ETuple([1, 0, 0])
1724
+ False
1725
+ sage: ETuple([1, 1, 0])<ETuple([1, 2, 0])
1726
+ True
1727
+ sage: ETuple([1, 1, 0])<ETuple([1, -1, 0])
1728
+ False
1729
+ sage: ETuple([0, -2, 0])<ETuple([1, -1, 0])
1730
+ True
1731
+ sage: ETuple([1, 1, 0])>ETuple([1, 1, 0])
1732
+ False
1733
+ sage: ETuple([1, 1, 0])>ETuple([1, 0, 0])
1734
+ True
1735
+ sage: ETuple([1, 1, 0])>ETuple([1, 2, 0])
1736
+ False
1737
+ sage: ETuple([1, 1, 0])>ETuple([1, -1, 0])
1738
+ True
1739
+ sage: ETuple([0, -2, 0])>ETuple([1, -1, 0])
1740
+ False
1741
+ """
1742
+ cdef size_t ind = 0
1743
+ if op == Py_EQ: # ==
1744
+ if self._nonzero != other._nonzero:
1745
+ return False
1746
+ for ind in range(self._nonzero):
1747
+ if self._data[2 * ind] != other._data[2 * ind]:
1748
+ return False
1749
+ if self._data[2 * ind + 1] != other._data[2 * ind + 1]:
1750
+ return False
1751
+ return self._length == other._length
1752
+
1753
+ if op == Py_LT: # <
1754
+ while ind < self._nonzero and ind < other._nonzero:
1755
+ if self._data[2*ind] < other._data[2*ind]:
1756
+ return self._data[2*ind+1] < 0
1757
+ if self._data[2*ind] > other._data[2*ind]:
1758
+ return other._data[2*ind+1] > 0
1759
+ if self._data[2*ind] == other._data[2*ind] and self._data[2*ind+1] != other._data[2*ind+1]:
1760
+ return self._data[2*ind+1] < other._data[2*ind+1]
1761
+ ind += 1
1762
+ if ind < self._nonzero and ind == other._nonzero:
1763
+ return self._data[2*ind+1] < 0
1764
+ if ind < other._nonzero and ind == self._nonzero:
1765
+ return other._data[2*ind+1] > 0
1766
+ return self._length < other._length
1767
+
1768
+ if op == Py_GT: # >
1769
+ while ind < self._nonzero and ind < other._nonzero:
1770
+ if self._data[2*ind] < other._data[2*ind]:
1771
+ return self._data[2*ind+1] > 0
1772
+ if self._data[2*ind] > other._data[2*ind]:
1773
+ return other._data[2*ind+1] < 0
1774
+ if self._data[2*ind] == other._data[2*ind] and self._data[2*ind+1] != other._data[2*ind+1]:
1775
+ return self._data[2*ind+1] > other._data[2*ind+1]
1776
+ ind += 1
1777
+ if ind < self._nonzero and ind == other._nonzero:
1778
+ return self._data[2*ind+1] > 0
1779
+ if ind < other._nonzero and ind == self._nonzero:
1780
+ return other._data[2*ind+1] < 0
1781
+ return self._length < other._length
1782
+
1783
+ # the rest of these are not particularly fast
1784
+
1785
+ if op == Py_LE: # <=
1786
+ return tuple(self) <= tuple(other)
1787
+
1788
+ if op == Py_NE: # !=
1789
+ return tuple(self) != tuple(other)
1790
+
1791
+ if op == Py_GE: # >=
1792
+ return tuple(self) >= tuple(other)
1793
+
1794
+ def __iter__(self):
1795
+ """
1796
+ ``x.__iter__() <==> iter(x)``.
1797
+
1798
+ TESTS::
1799
+
1800
+ sage: from sage.rings.polynomial.polydict import ETuple
1801
+ sage: e = ETuple((4, 0, 0, 2, 0))
1802
+ sage: list(e)
1803
+ [4, 0, 0, 2, 0]
1804
+
1805
+ Check that :issue:`28178` is fixed::
1806
+
1807
+ sage: it = iter(e)
1808
+ sage: iter(it) is it
1809
+ True
1810
+ """
1811
+ cdef size_t i
1812
+ cdef size_t ind = 0
1813
+
1814
+ for i in range(self._length):
1815
+ if ind >= self._nonzero:
1816
+ yield 0
1817
+ elif self._data[2*ind] == i:
1818
+ yield self._data[2*ind + 1]
1819
+ ind += 1
1820
+ else:
1821
+ yield 0
1822
+
1823
+ def __str__(self):
1824
+ return repr(self)
1825
+
1826
+ def __repr__(self):
1827
+ r"""
1828
+ TESTS::
1829
+
1830
+ sage: from sage.rings.polynomial.polydict import ETuple
1831
+ sage: ETuple((0,))
1832
+ (0,)
1833
+ sage: ETuple((1,))
1834
+ (1,)
1835
+ sage: ETuple((0, 1, 2))
1836
+ (0, 1, 2)
1837
+ """
1838
+ if self._length == 1:
1839
+ if self._nonzero:
1840
+ return '(%d,)' % self._data[1]
1841
+ else:
1842
+ return '(0,)'
1843
+ else:
1844
+ return '(' + ', '.join(map(str, self)) + ')'
1845
+
1846
+ def __reduce__(self):
1847
+ """
1848
+ EXAMPLES::
1849
+
1850
+ sage: from sage.rings.polynomial.polydict import ETuple
1851
+ sage: e = ETuple([1, 1, 0])
1852
+ sage: e == loads(dumps(e))
1853
+ True
1854
+ """
1855
+ cdef size_t ind
1856
+ d = {self._data[2 * ind]: self._data[2 * ind + 1] for ind in range(self._nonzero)}
1857
+ return ETuple, (d, int(self._length))
1858
+
1859
+ # additional methods
1860
+
1861
+ cdef int _unweighted_degree(self) except *:
1862
+ r"""
1863
+ Return the sum of entries.
1864
+
1865
+ EXAMPLES::
1866
+
1867
+ sage: from sage.rings.polynomial.polydict import ETuple
1868
+ sage: ETuple([1, 1, 0, 2, 0]).unweighted_degree()
1869
+ 4
1870
+ sage: ETuple([-1, 1]).unweighted_degree()
1871
+ 0
1872
+ """
1873
+ cdef int degree = 0
1874
+ cdef size_t i
1875
+ for i in range(self._nonzero):
1876
+ degree += self._data[2 * i + 1]
1877
+ return degree
1878
+
1879
+ cpdef int unweighted_degree(self) except *:
1880
+ r"""
1881
+ Return the sum of entries.
1882
+
1883
+ EXAMPLES::
1884
+
1885
+ sage: from sage.rings.polynomial.polydict import ETuple
1886
+ sage: ETuple([1, 1, 0, 2, 0]).unweighted_degree()
1887
+ 4
1888
+ sage: ETuple([-1, 1]).unweighted_degree()
1889
+ 0
1890
+ """
1891
+ return self._unweighted_degree()
1892
+
1893
+ @cython.boundscheck(False)
1894
+ @cython.wraparound(False)
1895
+ cpdef int weighted_degree(self, tuple w) except *:
1896
+ r"""
1897
+ Return the weighted sum of entries.
1898
+
1899
+ INPUT:
1900
+
1901
+ - ``w`` -- tuple of nonnegative integers
1902
+
1903
+ EXAMPLES::
1904
+
1905
+ sage: from sage.rings.polynomial.polydict import ETuple
1906
+ sage: e = ETuple([1, 1, 0, 2, 0])
1907
+ sage: e.weighted_degree((1, 2, 3, 4, 5))
1908
+ 11
1909
+ sage: ETuple([-1, 1]).weighted_degree((1, 2))
1910
+ 1
1911
+
1912
+ sage: ETuple([1, 0]).weighted_degree((1, 2, 3))
1913
+ Traceback (most recent call last):
1914
+ ...
1915
+ ValueError: w must be of the same length as the ETuple
1916
+ """
1917
+ if len(w) != self._length:
1918
+ raise ValueError('w must be of the same length as the ETuple')
1919
+
1920
+ cdef size_t i
1921
+ cdef int deg = 0
1922
+ if len(w) != self._length:
1923
+ raise ValueError
1924
+ # NOTE: cython does optimize range(a) and range(a, b) but not range(a, b, c)
1925
+ for i in range(self._nonzero):
1926
+ deg += self._data[2 * i + 1] * <int> w[self._data[2 * i]]
1927
+ return deg
1928
+
1929
+ cpdef int unweighted_quotient_degree(self, ETuple other) except *:
1930
+ """
1931
+ Return the degree of ``self`` divided by its gcd with ``other``.
1932
+
1933
+ It amounts to counting the nonnegative entries of
1934
+ ``self.esub(other)``.
1935
+ """
1936
+ cdef size_t ind1 = 0 # both ind1 and ind2 will be increased in double steps.
1937
+ cdef size_t ind2 = 0
1938
+ cdef int exponent
1939
+ cdef int position
1940
+ cdef size_t selfnz = 2 * self._nonzero
1941
+ cdef size_t othernz = 2 * other._nonzero
1942
+
1943
+ cdef int deg = 0
1944
+ while ind1 < selfnz:
1945
+ position = self._data[ind1]
1946
+ exponent = self._data[ind1 + 1]
1947
+ while ind2 < othernz and other._data[ind2] < position:
1948
+ ind2 += 2
1949
+ if ind2 == othernz:
1950
+ while ind1 < selfnz:
1951
+ deg += self._data[ind1 + 1]
1952
+ ind1 += 2
1953
+ return deg
1954
+ if other._data[ind2] > position:
1955
+ # other[position] = 0
1956
+ deg += exponent
1957
+ elif other._data[ind2 + 1] < exponent:
1958
+ # There is a positive difference that we have to insert
1959
+ deg += (exponent - other._data[ind2 + 1])
1960
+ ind1 += 2
1961
+ return deg
1962
+
1963
+ @cython.boundscheck(False)
1964
+ @cython.wraparound(False)
1965
+ cpdef int weighted_quotient_degree(self, ETuple other, tuple w) except *:
1966
+ r"""
1967
+ Return the weighted degree of ``self`` divided by its gcd with ``other``.
1968
+
1969
+ INPUT:
1970
+
1971
+ - ``other`` -- an :class:`~sage.rings.polynomial.polydict.ETuple`
1972
+ - ``w`` -- tuple of nonnegative integers
1973
+ """
1974
+ if len(w) != self._length:
1975
+ raise ValueError('w must be of the same length as the ETuple')
1976
+
1977
+ cdef size_t ind1 = 0 # both ind1 and ind2 will be increased in double steps.
1978
+ cdef size_t ind2 = 0
1979
+ cdef size_t exponent
1980
+ cdef int position
1981
+ cdef size_t selfnz = 2 * self._nonzero
1982
+ cdef size_t othernz = 2 * other._nonzero
1983
+
1984
+ cdef size_t deg = 0
1985
+ assert len(w) == self._length
1986
+ while ind1 < selfnz:
1987
+ position = self._data[ind1]
1988
+ exponent = self._data[ind1+1]
1989
+ while ind2 < othernz and other._data[ind2] < position:
1990
+ ind2 += 2
1991
+ if ind2 == othernz:
1992
+ while ind1 < selfnz:
1993
+ deg += <size_t>self._data[ind1+1] * <size_t> w[self._data[ind1]]
1994
+ ind1 += 2
1995
+ return deg
1996
+ if other._data[ind2] > position:
1997
+ # other[position] = 0
1998
+ deg += exponent * <size_t>w[position]
1999
+ elif other._data[ind2+1] < exponent:
2000
+ # There is a positive difference that we have to insert
2001
+ deg += <size_t> (exponent - other._data[ind2+1]) * <size_t>w[position]
2002
+ ind1 += 2
2003
+ return deg
2004
+
2005
+ cpdef ETuple eadd(self, ETuple other):
2006
+ """
2007
+ Return the vector addition of ``self`` with ``other``.
2008
+
2009
+ EXAMPLES::
2010
+
2011
+ sage: from sage.rings.polynomial.polydict import ETuple
2012
+ sage: e = ETuple([1, 0, 2])
2013
+ sage: f = ETuple([0, 1, 1])
2014
+ sage: e.eadd(f)
2015
+ (1, 1, 3)
2016
+
2017
+ Verify that :issue:`6428` has been addressed::
2018
+
2019
+ sage: # needs sage.libs.singular
2020
+ sage: R.<y, z> = Frac(QQ['x'])[]
2021
+ sage: type(y)
2022
+ <class 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomial_libsingular'>
2023
+ sage: y^(2^32)
2024
+ Traceback (most recent call last):
2025
+ ...
2026
+ OverflowError: exponent overflow (...) # 64-bit
2027
+ OverflowError: Python int too large to convert to C unsigned long # 32-bit
2028
+ """
2029
+ if self._length != other._length:
2030
+ raise ArithmeticError('ETuple of different lengths')
2031
+
2032
+ cdef size_t ind1 = 0
2033
+ cdef size_t ind2 = 0
2034
+ cdef size_t index
2035
+ cdef int exp1
2036
+ cdef int exp2
2037
+ cdef int s # sum
2038
+ cdef size_t alloc_len = self._nonzero + other._nonzero # we simply guesstimate the length -- there might be double the correct amount allocated -- who cares?
2039
+ if alloc_len > self._length:
2040
+ alloc_len = self._length
2041
+ cdef ETuple result = <ETuple>self._new()
2042
+ result._nonzero = 0 # we don't know the correct length quite yet
2043
+ result._data = <int*>sig_malloc(sizeof(int)*alloc_len*2)
2044
+ while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2):
2045
+ s = exp1 + exp2
2046
+ # Check for overflow and underflow
2047
+ if (exp2 > 0 and s < exp1) or (exp2 < 0 and s > exp1):
2048
+ raise OverflowError("exponent overflow (%s)" % (int(exp1)+int(exp2)))
2049
+ if s != 0:
2050
+ result._data[2*result._nonzero] = index
2051
+ result._data[2*result._nonzero+1] = s
2052
+ result._nonzero += 1
2053
+ return result
2054
+
2055
+ cpdef ETuple eadd_p(self, int other, size_t pos):
2056
+ """
2057
+ Add ``other`` to ``self`` at position ``pos``.
2058
+
2059
+ EXAMPLES::
2060
+
2061
+ sage: from sage.rings.polynomial.polydict import ETuple
2062
+ sage: e = ETuple([1, 0, 2])
2063
+ sage: e.eadd_p(5, 1)
2064
+ (1, 5, 2)
2065
+ sage: e = ETuple([0]*7)
2066
+ sage: e.eadd_p(5, 4)
2067
+ (0, 0, 0, 0, 5, 0, 0)
2068
+
2069
+ sage: ETuple([0,1]).eadd_p(1, 0) == ETuple([1,1])
2070
+ True
2071
+
2072
+ sage: e = ETuple([0, 1, 0])
2073
+ sage: e.eadd_p(0, 0).nonzero_positions()
2074
+ [1]
2075
+ sage: e.eadd_p(0, 1).nonzero_positions()
2076
+ [1]
2077
+ sage: e.eadd_p(0, 2).nonzero_positions()
2078
+ [1]
2079
+
2080
+ TESTS:
2081
+
2082
+ Test segmentation faults occurring as described in :issue:`34000`::
2083
+
2084
+ sage: ETuple([0, 1, 1]).eadd_p(1, 0)
2085
+ (1, 1, 1)
2086
+ sage: ETuple([0, 2, 4, 3]).eadd_p(5, 0)
2087
+ (5, 2, 4, 3)
2088
+ sage: ETuple([0, 2]).eadd_p(5, 0)
2089
+ (5, 2)
2090
+ sage: e = ETuple([0, 1, 0])
2091
+ sage: e.eadd_p(0, 0).nonzero_positions()
2092
+ [1]
2093
+ sage: e.eadd_p(0, 1).nonzero_positions()
2094
+ [1]
2095
+ sage: e.eadd_p(0, 2).nonzero_positions()
2096
+ [1]
2097
+ sage: e.eadd_p(-1, 1).nonzero_positions()
2098
+ []
2099
+ """
2100
+ cdef size_t sindex = 0
2101
+ cdef size_t rindex = 0
2102
+ cdef int new_value
2103
+ if pos >= self._length:
2104
+ raise ValueError("pos must be between 0 and %s" % self._length)
2105
+
2106
+ cdef ETuple result = self._new()
2107
+ result._nonzero = self._nonzero
2108
+ if not other:
2109
+ # return a copy
2110
+ result._data = <int*> sig_malloc(sizeof(int) * self._nonzero * 2)
2111
+ memcpy(result._data, self._data, sizeof(int) * self._nonzero * 2)
2112
+ return result
2113
+
2114
+ result._data = <int*> sig_malloc(sizeof(int) * (self._nonzero + 1) * 2)
2115
+ while sindex < self._nonzero and self._data[2 * sindex] < pos:
2116
+ result._data[2 * sindex] = self._data[2 * sindex]
2117
+ result._data[2 * sindex + 1] = self._data[2 * sindex + 1]
2118
+ sindex += 1
2119
+
2120
+ if sindex < self._nonzero and self._data[2 * sindex] == pos:
2121
+ new_value = self._data[2 * sindex + 1] + other
2122
+ if new_value:
2123
+ result._data[2 * sindex] = pos
2124
+ result._data[2 * sindex + 1] = new_value
2125
+ sindex += 1
2126
+ rindex = sindex
2127
+ else:
2128
+ result._nonzero -= 1
2129
+ rindex = sindex
2130
+ sindex += 1
2131
+ else:
2132
+ result._data[2 * sindex] = pos
2133
+ result._data[2 * sindex + 1] = other
2134
+ result._nonzero += 1
2135
+ rindex = sindex + 1
2136
+
2137
+ memcpy(result._data + 2 * rindex,
2138
+ self._data + 2 * sindex,
2139
+ sizeof(int) * 2 * (self._nonzero - sindex))
2140
+
2141
+ return result
2142
+
2143
+ cpdef ETuple eadd_scaled(self, ETuple other, int scalar):
2144
+ """
2145
+ Vector addition of ``self`` with ``scalar * other``.
2146
+
2147
+ EXAMPLES::
2148
+
2149
+ sage: from sage.rings.polynomial.polydict import ETuple
2150
+ sage: e = ETuple([1, 0, 2])
2151
+ sage: f = ETuple([0, 1, 1])
2152
+ sage: e.eadd_scaled(f, 3)
2153
+ (1, 3, 5)
2154
+ """
2155
+ if self._length != other._length:
2156
+ raise ArithmeticError('ETuple of different lengths')
2157
+
2158
+ cdef size_t ind1 = 0
2159
+ cdef size_t ind2 = 0
2160
+ cdef size_t index
2161
+ cdef int exp1
2162
+ cdef int exp2
2163
+ cdef int s # sum
2164
+ cdef size_t alloc_len = self._nonzero + other._nonzero # we simply guesstimate the length -- there might be double the correct amount allocated -- who cares?
2165
+ if alloc_len > self._length:
2166
+ alloc_len = self._length
2167
+ cdef ETuple result = <ETuple>self._new()
2168
+ result._nonzero = 0 # we don't know the correct length quite yet
2169
+ result._data = <int*>sig_malloc(sizeof(int)*alloc_len*2)
2170
+ while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2):
2171
+ exp2 *= scalar
2172
+ s = exp1 + exp2
2173
+ # Check for overflow and underflow
2174
+ if (exp2 > 0 and s < exp1) or (exp2 < 0 and s > exp1):
2175
+ raise OverflowError("exponent overflow (%s)" % (int(exp1)+int(exp2)))
2176
+ if s != 0:
2177
+ result._data[2*result._nonzero] = index
2178
+ result._data[2*result._nonzero+1] = s
2179
+ result._nonzero += 1
2180
+ return result
2181
+
2182
+ cpdef ETuple esub(self, ETuple other):
2183
+ """
2184
+ Vector subtraction of ``self`` with ``other``.
2185
+
2186
+ EXAMPLES::
2187
+
2188
+ sage: from sage.rings.polynomial.polydict import ETuple
2189
+ sage: e = ETuple([1, 0, 2])
2190
+ sage: f = ETuple([0, 1, 1])
2191
+ sage: e.esub(f)
2192
+ (1, -1, 1)
2193
+ """
2194
+ if self._length!=other._length:
2195
+ raise ArithmeticError
2196
+
2197
+ cdef size_t ind1 = 0
2198
+ cdef size_t ind2 = 0
2199
+ cdef size_t index
2200
+ cdef int exp1
2201
+ cdef int exp2
2202
+ cdef int d # difference
2203
+ cdef size_t alloc_len = self._nonzero + other._nonzero # we simply guesstimate the length -- there might be double the correct amount allocated -- who cares?
2204
+ if alloc_len > self._length:
2205
+ alloc_len = self._length
2206
+ cdef ETuple result = <ETuple>self._new()
2207
+ result._nonzero = 0 # we don't know the correct length quite yet
2208
+ result._data = <int*>sig_malloc(sizeof(int)*alloc_len*2)
2209
+ while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2):
2210
+ # Check for overflow and underflow
2211
+ d = exp1 - exp2
2212
+ if (exp2 > 0 and d > exp1) or (exp2 < 0 and d < exp1):
2213
+ raise OverflowError("Exponent overflow (%s)" % (int(exp1)-int(exp2)))
2214
+ if d != 0:
2215
+ result._data[2*result._nonzero] = index
2216
+ result._data[2*result._nonzero+1] = d
2217
+ result._nonzero += 1
2218
+ return result
2219
+
2220
+ cpdef ETuple emul(self, int factor):
2221
+ """
2222
+ Scalar Vector multiplication of ``self``.
2223
+
2224
+ EXAMPLES::
2225
+
2226
+ sage: from sage.rings.polynomial.polydict import ETuple
2227
+ sage: e = ETuple([1, 0, 2])
2228
+ sage: e.emul(2)
2229
+ (2, 0, 4)
2230
+ """
2231
+ cdef size_t ind
2232
+ cdef ETuple result = <ETuple>self._new()
2233
+ if factor == 0:
2234
+ result._nonzero = 0 # all zero, no nonzero entries!
2235
+ result._data = <int*>sig_malloc(sizeof(int) * result._nonzero * 2)
2236
+ else:
2237
+ result._nonzero = self._nonzero
2238
+ result._data = <int*>sig_malloc(sizeof(int) * result._nonzero * 2)
2239
+ for ind in range(self._nonzero):
2240
+ result._data[2 * ind] = self._data[2 * ind]
2241
+ result._data[2 * ind + 1] = self._data[2 * ind + 1] * factor
2242
+ return result
2243
+
2244
+ cpdef ETuple emax(self, ETuple other):
2245
+ """
2246
+ Vector of maximum of components of ``self`` and ``other``.
2247
+
2248
+ EXAMPLES::
2249
+
2250
+ sage: from sage.rings.polynomial.polydict import ETuple
2251
+ sage: e = ETuple([1, 0, 2])
2252
+ sage: f = ETuple([0, 1, 1])
2253
+ sage: e.emax(f)
2254
+ (1, 1, 2)
2255
+ sage: e = ETuple((1, 2, 3, 4))
2256
+ sage: f = ETuple((4, 0, 2, 1))
2257
+ sage: f.emax(e)
2258
+ (4, 2, 3, 4)
2259
+ sage: e = ETuple((1, -2, -2, 4))
2260
+ sage: f = ETuple((4, 0, 0, 0))
2261
+ sage: f.emax(e)
2262
+ (4, 0, 0, 4)
2263
+ sage: f.emax(e).nonzero_positions()
2264
+ [0, 3]
2265
+ """
2266
+ if self._length!=other._length:
2267
+ raise ArithmeticError
2268
+
2269
+ cdef size_t ind1 = 0
2270
+ cdef size_t ind2 = 0
2271
+ cdef size_t index
2272
+ cdef int exp1
2273
+ cdef int exp2
2274
+ cdef size_t alloc_len = self._nonzero + other._nonzero # we simply guesstimate the length -- there might be double the correct amount allocated -- who cares?
2275
+ if alloc_len > self._length:
2276
+ alloc_len = self._length
2277
+ cdef ETuple result = <ETuple>self._new()
2278
+ result._nonzero = 0 # we don't know the correct length quite yet
2279
+ result._data = <int*>sig_malloc(sizeof(int)*alloc_len*2)
2280
+ while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2):
2281
+ if exp1 >= exp2 and exp1 != 0:
2282
+ result._data[2*result._nonzero] = index
2283
+ result._data[2*result._nonzero+1] = exp1
2284
+ result._nonzero += 1
2285
+ elif exp2 >= exp1 and exp2 != 0:
2286
+ result._data[2*result._nonzero] = index
2287
+ result._data[2*result._nonzero+1] = exp2
2288
+ result._nonzero += 1
2289
+ return result
2290
+
2291
+ cpdef ETuple emin(self, ETuple other):
2292
+ """
2293
+ Vector of minimum of components of ``self`` and ``other``.
2294
+
2295
+ EXAMPLES::
2296
+
2297
+ sage: from sage.rings.polynomial.polydict import ETuple
2298
+ sage: e = ETuple([1, 0, 2])
2299
+ sage: f = ETuple([0, 1, 1])
2300
+ sage: e.emin(f)
2301
+ (0, 0, 1)
2302
+ sage: e = ETuple([1, 0, -1])
2303
+ sage: f = ETuple([0, -2, 1])
2304
+ sage: e.emin(f)
2305
+ (0, -2, -1)
2306
+ """
2307
+ if self._length != other._length:
2308
+ raise ArithmeticError
2309
+
2310
+ cdef size_t ind1 = 0
2311
+ cdef size_t ind2 = 0
2312
+ cdef size_t index
2313
+ cdef int exp1
2314
+ cdef int exp2
2315
+ cdef size_t alloc_len = self._nonzero + other._nonzero # we simply guesstimate the length -- there might be double the correct amount allocated -- who cares?
2316
+ if alloc_len > self._length:
2317
+ alloc_len = self._length
2318
+ cdef ETuple result = <ETuple>self._new()
2319
+ result._nonzero = 0 # we don't know the correct length quite yet
2320
+ result._data = <int*>sig_malloc(sizeof(int)*alloc_len*2)
2321
+ while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2):
2322
+ if exp1 <= exp2 and exp1 != 0:
2323
+ result._data[2*result._nonzero] = index
2324
+ result._data[2*result._nonzero+1] = exp1
2325
+ result._nonzero += 1
2326
+ elif exp2 <= exp1 and exp2 != 0:
2327
+ result._data[2*result._nonzero] = index
2328
+ result._data[2*result._nonzero+1] = exp2
2329
+ result._nonzero += 1
2330
+ return result
2331
+
2332
+ cpdef int dotprod(self, ETuple other) except *:
2333
+ """
2334
+ Return the dot product of this tuple by ``other``.
2335
+
2336
+ EXAMPLES::
2337
+
2338
+ sage: from sage.rings.polynomial.polydict import ETuple
2339
+ sage: e = ETuple([1, 0, 2])
2340
+ sage: f = ETuple([0, 1, 1])
2341
+ sage: e.dotprod(f)
2342
+ 2
2343
+ sage: e = ETuple([1, 1, -1])
2344
+ sage: f = ETuple([0, -2, 1])
2345
+ sage: e.dotprod(f)
2346
+ -3
2347
+ """
2348
+ if self._length != other._length:
2349
+ raise ArithmeticError
2350
+
2351
+ cdef size_t ind1 = 0
2352
+ cdef size_t ind2 = 0
2353
+ cdef size_t index
2354
+ cdef int exp1
2355
+ cdef int exp2
2356
+ cdef int result = 0
2357
+ while dual_etuple_iter(self, other, &ind1, &ind2, &index, &exp1, &exp2):
2358
+ result += exp1 * exp2
2359
+ return result
2360
+
2361
+ cpdef ETuple escalar_div(self, int n):
2362
+ r"""
2363
+ Divide each exponent by ``n``.
2364
+
2365
+ EXAMPLES::
2366
+
2367
+ sage: from sage.rings.polynomial.polydict import ETuple
2368
+ sage: ETuple([1, 0, 2]).escalar_div(2)
2369
+ (0, 0, 1)
2370
+ sage: ETuple([0, 3, 12]).escalar_div(3)
2371
+ (0, 1, 4)
2372
+
2373
+ sage: ETuple([1, 5, 2]).escalar_div(0)
2374
+ Traceback (most recent call last):
2375
+ ...
2376
+ ZeroDivisionError
2377
+
2378
+ TESTS:
2379
+
2380
+ Checking that memory allocation works fine::
2381
+
2382
+ sage: from sage.rings.polynomial.polydict import ETuple
2383
+ sage: t = ETuple(list(range(2048)))
2384
+ sage: for n in range(1, 9):
2385
+ ....: t = t.escalar_div(n)
2386
+ sage: assert t.is_constant()
2387
+ """
2388
+ if not n:
2389
+ raise ZeroDivisionError
2390
+ cdef size_t i
2391
+ cdef ETuple result = self._new()
2392
+ result._data = <int*> sig_malloc(sizeof(int) * 2 * self._nonzero)
2393
+ result._nonzero = 0
2394
+ # NOTE: cython does optimize range(a) and range(a, b) but not range(a, b, c)
2395
+ for i in range(self._nonzero):
2396
+ result._data[2 * result._nonzero + 1] = self._data[2 * i + 1] / n
2397
+ if result._data[2 * result._nonzero + 1]:
2398
+ result._data[2 * result._nonzero] = self._data[2 * i]
2399
+ result._nonzero += 1
2400
+ return result
2401
+
2402
+ cpdef ETuple divide_by_gcd(self, ETuple other):
2403
+ """
2404
+ Return ``self / gcd(self, other)``.
2405
+
2406
+ The entries of the result are the maximum of 0 and the
2407
+ difference of the corresponding entries of ``self`` and ``other``.
2408
+ """
2409
+ if self._length != other._length:
2410
+ raise ArithmeticError('ETuple of different lengths')
2411
+ cdef size_t ind1 = 0 # both ind1 and ind2 will be increased in 2-steps.
2412
+ cdef size_t ind2 = 0
2413
+ cdef int exponent
2414
+ cdef int position
2415
+ cdef size_t selfnz = 2 * self._nonzero
2416
+ cdef size_t othernz = 2 * other._nonzero
2417
+ cdef ETuple result = <ETuple> self._new()
2418
+ result._nonzero = 0
2419
+ result._data = <int*> sig_malloc(sizeof(int)*self._nonzero*2)
2420
+ while ind1 < selfnz:
2421
+ position = self._data[ind1]
2422
+ exponent = self._data[ind1+1]
2423
+ while ind2 < othernz and other._data[ind2] < position:
2424
+ ind2 += 2
2425
+ if ind2 == othernz:
2426
+ while ind1 < selfnz:
2427
+ result._data[2*result._nonzero] = self._data[ind1]
2428
+ result._data[2*result._nonzero+1] = self._data[ind1+1]
2429
+ result._nonzero += 1
2430
+ ind1 += 2
2431
+ return result
2432
+ if other._data[ind2] > position:
2433
+ # other[position] == 0
2434
+ result._data[2*result._nonzero] = position
2435
+ result._data[2*result._nonzero+1] = exponent
2436
+ result._nonzero += 1
2437
+ elif other._data[ind2+1] < exponent:
2438
+ # There is a positive difference that we have to insert
2439
+ result._data[2*result._nonzero] = position
2440
+ result._data[2*result._nonzero+1] = exponent - other._data[ind2+1]
2441
+ result._nonzero += 1
2442
+ ind1 += 2
2443
+ return result
2444
+
2445
+ cpdef ETuple divide_by_var(self, size_t pos):
2446
+ """
2447
+ Return division of ``self`` by the variable with index ``pos``.
2448
+
2449
+ If ``self[pos] == 0`` then a :exc:`ArithmeticError` is raised. Otherwise,
2450
+ an :class:`~sage.rings.polynomial.polydict.ETuple` is returned that is
2451
+ zero in position ``pos`` and coincides with ``self`` in the other
2452
+ positions.
2453
+
2454
+ EXAMPLES::
2455
+
2456
+ sage: from sage.rings.polynomial.polydict import ETuple
2457
+ sage: e = ETuple([1, 2, 0, 1])
2458
+ sage: e.divide_by_var(0)
2459
+ (0, 2, 0, 1)
2460
+ sage: e.divide_by_var(1)
2461
+ (1, 1, 0, 1)
2462
+ sage: e.divide_by_var(3)
2463
+ (1, 2, 0, 0)
2464
+ sage: e.divide_by_var(2)
2465
+ Traceback (most recent call last):
2466
+ ...
2467
+ ArithmeticError: not divisible by this variable
2468
+ """
2469
+ cdef int exp1
2470
+ cdef ETuple result
2471
+ cdef size_t ind
2472
+
2473
+ ind = self.get_position(pos, 0, self._nonzero)
2474
+ if ind == self._nonzero or self._data[2 * ind] != pos:
2475
+ raise ArithmeticError('not divisible by this variable')
2476
+ result = <ETuple> self._new()
2477
+ result._data = <int*> sig_malloc(sizeof(int) * 2 * self._nonzero)
2478
+ exp1 = self._data[2 * ind + 1]
2479
+ if exp1 > 1:
2480
+ # division doesn't change the number of nonzero positions
2481
+ result._nonzero = self._nonzero
2482
+ memcpy(result._data, self._data, sizeof(int) * 2 * self._nonzero)
2483
+ result._data[2 * ind + 1] = exp1 - 1
2484
+ else:
2485
+ # var(pos) disappears from self
2486
+ result._nonzero = self._nonzero - 1
2487
+ memcpy(result._data, self._data, sizeof(int) * 2 * ind)
2488
+ if ind + 1 < self._nonzero:
2489
+ memcpy(result._data + 2 * ind, self._data + 2 * (ind + 1), sizeof(int) * 2 * (self._nonzero - ind - 1))
2490
+ return result
2491
+
2492
+ cpdef bint divides(self, ETuple other) except *:
2493
+ """
2494
+ Return whether ``self`` divides ``other``, i.e., no entry of ``self``
2495
+ exceeds that of ``other``.
2496
+
2497
+ EXAMPLES::
2498
+
2499
+ sage: from sage.rings.polynomial.polydict import ETuple
2500
+ sage: ETuple([1, 1, 0, 1, 0]).divides(ETuple([2, 2, 2, 2, 2]))
2501
+ True
2502
+ sage: ETuple([0, 3, 0, 1, 0]).divides(ETuple([2, 2, 2, 2, 2]))
2503
+ False
2504
+ sage: ETuple([0, 3, 0, 1, 0]).divides(ETuple([0, 3, 2, 2, 2]))
2505
+ True
2506
+ sage: ETuple([0, 0, 0, 0, 0]).divides(ETuple([2, 2, 2, 2, 2]))
2507
+ True
2508
+
2509
+ sage: ETuple({104: 18, 256: 25, 314:78}, length=400r).divides(ETuple({104: 19, 105: 20, 106: 21}, length=400r))
2510
+ False
2511
+ sage: ETuple({104: 18, 256: 25, 314:78}, length=400r).divides(ETuple({104: 19, 105: 20, 106: 21, 255: 2, 256: 25, 312: 5, 314: 79, 315: 28}, length=400r))
2512
+ True
2513
+ """
2514
+ cdef size_t ind1 = 0
2515
+ cdef size_t ind2 = 0
2516
+ cdef int pos1
2517
+
2518
+ if self._length != other._length:
2519
+ raise ArithmeticError('ETuple of different length')
2520
+
2521
+ while ind1 < self._nonzero:
2522
+ if self._nonzero - ind1 > other._nonzero - ind2:
2523
+ return False
2524
+ pos1 = self._data[2 * ind1]
2525
+ ind2 = other.get_position(pos1, ind2, other._nonzero)
2526
+ if ind2 == other._nonzero or other._data[2 * ind2] != pos1 or other._data[2 * ind2 + 1] < self._data[2 * ind1 + 1]:
2527
+ return False
2528
+ ind1 += 1
2529
+ ind2 += 1
2530
+
2531
+ return True
2532
+
2533
+ cpdef bint is_constant(self) noexcept:
2534
+ """
2535
+ Return if all exponents are zero in the tuple.
2536
+
2537
+ EXAMPLES::
2538
+
2539
+ sage: from sage.rings.polynomial.polydict import ETuple
2540
+ sage: e = ETuple([1, 0, 2])
2541
+ sage: e.is_constant()
2542
+ False
2543
+ sage: e = ETuple([0, 0])
2544
+ sage: e.is_constant()
2545
+ True
2546
+ """
2547
+ return self._nonzero == 0
2548
+
2549
+ cpdef bint is_multiple_of(self, int n) except *:
2550
+ r"""
2551
+ Test whether each entry is a multiple of ``n``.
2552
+
2553
+ EXAMPLES::
2554
+
2555
+ sage: from sage.rings.polynomial.polydict import ETuple
2556
+
2557
+ sage: ETuple([0, 0]).is_multiple_of(3)
2558
+ True
2559
+ sage: ETuple([0, 3, 12, 0, 6]).is_multiple_of(3)
2560
+ True
2561
+ sage: ETuple([0, 0, 2]).is_multiple_of(3)
2562
+ False
2563
+ """
2564
+ if not n:
2565
+ raise ValueError('n should not be zero')
2566
+ cdef size_t i
2567
+ for i in range(self._nonzero):
2568
+ if self._data[2 * i + 1] % n:
2569
+ return False
2570
+ return True
2571
+
2572
+ cpdef list nonzero_positions(self, bint sort=False):
2573
+ """
2574
+ Return the positions of nonzero exponents in the tuple.
2575
+
2576
+ INPUT:
2577
+
2578
+ - ``sort`` -- boolean (default: ``False``); if ``True`` a sorted list is
2579
+ returned; if ``False`` an unsorted list is returned
2580
+
2581
+ EXAMPLES::
2582
+
2583
+ sage: from sage.rings.polynomial.polydict import ETuple
2584
+ sage: e = ETuple([1, 0, 2])
2585
+ sage: e.nonzero_positions()
2586
+ [0, 2]
2587
+ """
2588
+ cdef size_t ind
2589
+ return [self._data[2 * ind] for ind in range(self._nonzero)]
2590
+
2591
+ cpdef common_nonzero_positions(self, ETuple other, bint sort=False):
2592
+ """
2593
+ Return an optionally sorted list of nonzero positions either
2594
+ in ``self`` or other, i.e. the only positions that need to be
2595
+ considered for any vector operation.
2596
+
2597
+ EXAMPLES::
2598
+
2599
+ sage: from sage.rings.polynomial.polydict import ETuple
2600
+ sage: e = ETuple([1, 0, 2])
2601
+ sage: f = ETuple([0, 0, 1])
2602
+ sage: e.common_nonzero_positions(f)
2603
+ {0, 2}
2604
+ sage: e.common_nonzero_positions(f, sort=True)
2605
+ [0, 2]
2606
+ """
2607
+ # TODO: we should probably make a fast version of this!
2608
+ res = set(self.nonzero_positions()).union(other.nonzero_positions())
2609
+ if sort:
2610
+ return sorted(res)
2611
+ else:
2612
+ return res
2613
+
2614
+ cpdef list nonzero_values(self, bint sort=True):
2615
+ """
2616
+ Return the nonzero values of the tuple.
2617
+
2618
+ INPUT:
2619
+
2620
+ - ``sort`` -- boolean (default: ``True``); if ``True`` the values are
2621
+ sorted by their indices. Otherwise the values are returned unsorted.
2622
+
2623
+ EXAMPLES::
2624
+
2625
+ sage: from sage.rings.polynomial.polydict import ETuple
2626
+ sage: e = ETuple([2, 0, 1])
2627
+ sage: e.nonzero_values()
2628
+ [2, 1]
2629
+ sage: f = ETuple([0, -1, 1])
2630
+ sage: f.nonzero_values(sort=True)
2631
+ [-1, 1]
2632
+ """
2633
+ cdef size_t ind
2634
+ return [self._data[2 * ind + 1] for ind in range(self._nonzero)]
2635
+
2636
+ cpdef ETuple reversed(self):
2637
+ """
2638
+ Return the reversed ETuple of ``self``.
2639
+
2640
+ EXAMPLES::
2641
+
2642
+ sage: from sage.rings.polynomial.polydict import ETuple
2643
+ sage: e = ETuple([1, 2, 3])
2644
+ sage: e.reversed()
2645
+ (3, 2, 1)
2646
+ """
2647
+ cdef size_t ind
2648
+ cdef ETuple result = <ETuple>self._new()
2649
+ result._nonzero = self._nonzero
2650
+ result._data = <int*>sig_malloc(sizeof(int) * result._nonzero * 2)
2651
+ for ind in range(self._nonzero):
2652
+ result._data[2 * (result._nonzero - ind - 1)] = self._length - self._data[2 * ind] - 1
2653
+ result._data[2 * (result._nonzero - ind - 1) + 1] = self._data[2 * ind + 1]
2654
+ return result
2655
+
2656
+ def sparse_iter(self):
2657
+ """
2658
+ Iterator over the elements of ``self`` where the elements are returned
2659
+ as ``(i, e)`` where ``i`` is the position of ``e`` in the tuple.
2660
+
2661
+ EXAMPLES::
2662
+
2663
+ sage: from sage.rings.polynomial.polydict import ETuple
2664
+ sage: e = ETuple([1, 0, 2, 0, 3])
2665
+ sage: list(e.sparse_iter())
2666
+ [(0, 1), (2, 2), (4, 3)]
2667
+ """
2668
+ cdef size_t ind
2669
+ for ind in range(self._nonzero):
2670
+ yield (self._data[2 * ind], self._data[2 * ind + 1])
2671
+
2672
+ def combine_to_positives(self, ETuple other):
2673
+ """
2674
+ Given a pair of ETuples (self, other), returns a triple of
2675
+ ETuples (a, b, c) so that self = a + b, other = a + c and b and c
2676
+ have all positive entries.
2677
+
2678
+ EXAMPLES::
2679
+
2680
+ sage: from sage.rings.polynomial.polydict import ETuple
2681
+ sage: e = ETuple([-2, 1, -5, 3, 1, 0])
2682
+ sage: f = ETuple([1, -3, -3, 4, 0, 2])
2683
+ sage: e.combine_to_positives(f)
2684
+ ((-2, -3, -5, 3, 0, 0), (0, 4, 0, 0, 1, 0), (3, 0, 2, 1, 0, 2))
2685
+ """
2686
+ m = self.emin(other)
2687
+ return m, self.esub(m), other.esub(m)
2688
+
2689
+
2690
+ def make_PolyDict(data):
2691
+ r"""
2692
+ Ensure support for pickled data from older sage versions.
2693
+ """
2694
+ return PolyDict(data)
2695
+
2696
+
2697
+ def make_ETuple(data, length):
2698
+ r"""
2699
+ Ensure support for pickled data from older sage versions.
2700
+ """
2701
+ return ETuple(data, length)