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,2465 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ # sage.doctest: needs sage.libs.pari
3
+ """
4
+ Quotients of Univariate Polynomial Rings
5
+
6
+ EXAMPLES::
7
+
8
+ sage: R.<x> = QQ[]
9
+ sage: S = R.quotient(x**3 - 3*x + 1, 'alpha')
10
+ sage: S.gen()**2 in S
11
+ True
12
+ sage: x in S
13
+ True
14
+ sage: S.gen() in R
15
+ False
16
+ sage: 1 in S
17
+ True
18
+
19
+ TESTS::
20
+
21
+ sage: # needs sage.libs.flint sage.libs.singular
22
+ sage: Pol.<y> = CBF[]
23
+ sage: Quo.<y> = Pol.quotient(y^3)
24
+ sage: CBF.zero()*y
25
+ 0
26
+ sage: ((x - 1)/(x + 1))(1 + y)
27
+ -0.2500000000000000*y^2 + 0.5000000000000000*y
28
+ """
29
+
30
+ #*****************************************************************************
31
+ # Copyright (C) 2005, 2006 William Stein <wstein@gmail.com>
32
+ # 2016 Julian Rüth <julian.rueth@fsfe.org>
33
+ #
34
+ # This program is free software: you can redistribute it and/or modify
35
+ # it under the terms of the GNU General Public License as published by
36
+ # the Free Software Foundation, either version 2 of the License, or
37
+ # (at your option) any later version.
38
+ # https://www.gnu.org/licenses/
39
+ #*****************************************************************************
40
+
41
+
42
+ from . import polynomial_element
43
+ import sage.rings.rational_field
44
+
45
+ from sage.arith.misc import crt
46
+ from sage.rings.ring import Field, CommutativeRing
47
+
48
+ from sage.misc.cachefunc import cached_method
49
+ from sage.rings.polynomial.polynomial_quotient_ring_element import PolynomialQuotientRingElement
50
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_commutative
51
+
52
+ from sage.categories.commutative_algebras import CommutativeAlgebras
53
+ from sage.categories.commutative_rings import CommutativeRings
54
+
55
+ from sage.rings.quotient_ring import QuotientRing_generic
56
+
57
+ from sage.structure.category_object import normalize_names
58
+ from sage.structure.coerce_maps import DefaultConvertMap_unique
59
+ from sage.structure.factory import UniqueFactory
60
+
61
+ from sage.rings.polynomial.infinite_polynomial_ring import GenDictWithBasering
62
+
63
+ from sage.structure.richcmp import richcmp
64
+
65
+
66
+ class PolynomialQuotientRingFactory(UniqueFactory):
67
+ r"""
68
+ Create a quotient of a polynomial ring.
69
+
70
+ INPUT:
71
+
72
+ - ``ring`` -- a univariate polynomial ring
73
+
74
+ - ``polynomial`` -- an element of ``ring`` with a unit leading coefficient
75
+
76
+ - ``names`` -- (optional) name for the variable
77
+
78
+ OUTPUT: creates the quotient ring `R/I`, where `R` is the ring and `I` is
79
+ the principal ideal generated by ``polynomial``.
80
+
81
+ EXAMPLES:
82
+
83
+ We create the quotient ring `\ZZ[x]/(x^3+7)`, and
84
+ demonstrate many basic functions with it::
85
+
86
+ sage: Z = IntegerRing()
87
+ sage: R = PolynomialRing(Z, 'x'); x = R.gen()
88
+ sage: S = R.quotient(x^3 + 7, 'a'); a = S.gen()
89
+ sage: S
90
+ Univariate Quotient Polynomial Ring in a
91
+ over Integer Ring with modulus x^3 + 7
92
+ sage: a^3
93
+ -7
94
+ sage: S.is_field()
95
+ False
96
+ sage: a in S
97
+ True
98
+ sage: x in S
99
+ True
100
+ sage: a in R
101
+ False
102
+ sage: S.polynomial_ring()
103
+ Univariate Polynomial Ring in x over Integer Ring
104
+ sage: S.modulus()
105
+ x^3 + 7
106
+ sage: S.degree()
107
+ 3
108
+
109
+ We create the "iterated" polynomial ring quotient
110
+
111
+ .. MATH::
112
+
113
+ R = (\GF{2}[y]/(y^{2}+y+1))[x]/(x^3 - 5).
114
+
115
+ ::
116
+
117
+ sage: # needs sage.libs.ntl
118
+ sage: A.<y> = PolynomialRing(GF(2)); A
119
+ Univariate Polynomial Ring in y over Finite Field of size 2 (using GF2X)
120
+ sage: B = A.quotient(y^2 + y + 1, 'y2'); B
121
+ Univariate Quotient Polynomial Ring in y2 over Finite Field of size 2
122
+ with modulus y^2 + y + 1
123
+ sage: C = PolynomialRing(B, 'x'); x = C.gen(); C
124
+ Univariate Polynomial Ring in x
125
+ over Univariate Quotient Polynomial Ring in y2
126
+ over Finite Field of size 2 with modulus y^2 + y + 1
127
+ sage: R = C.quotient(x^3 - 5); R
128
+ Univariate Quotient Polynomial Ring in xbar
129
+ over Univariate Quotient Polynomial Ring in y2
130
+ over Finite Field of size 2 with modulus y^2 + y + 1
131
+ with modulus x^3 + 1
132
+
133
+ Next we create a number field, but viewed as a quotient of a
134
+ polynomial ring over `\QQ`::
135
+
136
+ sage: R = PolynomialRing(RationalField(), 'x'); x = R.gen()
137
+ sage: S = R.quotient(x^3 + 2*x - 5, 'a'); S
138
+ Univariate Quotient Polynomial Ring in a over Rational Field
139
+ with modulus x^3 + 2*x - 5
140
+ sage: S.is_field()
141
+ True
142
+ sage: S.degree()
143
+ 3
144
+
145
+ There are conversion functions for easily going back and forth
146
+ between quotients of polynomial rings over `\QQ` and
147
+ number fields::
148
+
149
+ sage: K = S.number_field(); K # needs sage.rings.number_field
150
+ Number Field in a with defining polynomial x^3 + 2*x - 5
151
+ sage: K.polynomial_quotient_ring() # needs sage.rings.number_field
152
+ Univariate Quotient Polynomial Ring in a
153
+ over Rational Field with modulus x^3 + 2*x - 5
154
+
155
+ The leading coefficient must be a unit (but need not be 1).
156
+
157
+ ::
158
+
159
+ sage: R = PolynomialRing(Integers(9), 'x'); x = R.gen()
160
+ sage: S = R.quotient(2*x^4 + 2*x^3 + x + 2, 'a')
161
+ sage: S = R.quotient(3*x^4 + 2*x^3 + x + 2, 'a')
162
+ Traceback (most recent call last):
163
+ ...
164
+ TypeError: polynomial must have unit leading coefficient
165
+
166
+ Another example::
167
+
168
+ sage: R.<x> = PolynomialRing(IntegerRing())
169
+ sage: f = x^2 + 1
170
+ sage: R.quotient(f)
171
+ Univariate Quotient Polynomial Ring in xbar over Integer Ring with modulus x^2 + 1
172
+
173
+ This shows that the issue at :issue:`5482` is solved::
174
+
175
+ sage: R.<x> = PolynomialRing(QQ)
176
+ sage: f = x^2 - 1
177
+ sage: R.quotient_by_principal_ideal(f)
178
+ Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 - 1
179
+ """
180
+ def create_key(self, ring, polynomial, names=None):
181
+ r"""
182
+ Return a unique description of the quotient ring specified by the
183
+ arguments.
184
+
185
+ EXAMPLES::
186
+
187
+ sage: R.<x> = QQ[]
188
+ sage: PolynomialQuotientRing.create_key(R, x + 1)
189
+ (Univariate Polynomial Ring in x over Rational Field, x + 1, ('xbar',))
190
+
191
+ TESTS:
192
+
193
+ We do not normalize the modulus even though we could divide out the
194
+ leading coefficient here::
195
+
196
+ sage: PolynomialQuotientRing.create_key(R, 2*x + 2)
197
+ (Univariate Polynomial Ring in x over Rational Field, 2*x + 2, ('xbar',))
198
+
199
+ Consequently, you get two distinct objects::
200
+
201
+ sage: S = PolynomialQuotientRing(R, x + 1); S
202
+ Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x + 1
203
+ sage: T = PolynomialQuotientRing(R, 2*x + 2); T
204
+ Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus 2*x + 2
205
+ sage: S is T
206
+ False
207
+ sage: S == T
208
+ False
209
+
210
+ In most applications this will not be a concern since the calling code
211
+ takes care of normalizing the generators::
212
+
213
+ sage: R.quo(x + 1) is R.quo(2*x + 2)
214
+ True
215
+ """
216
+ if not isinstance(ring, PolynomialRing_commutative):
217
+ raise TypeError("ring must be a polynomial ring")
218
+ if not isinstance(polynomial, polynomial_element.Polynomial):
219
+ raise TypeError("must be a polynomial")
220
+ if polynomial.parent() is not ring:
221
+ raise TypeError("polynomial must be in ring")
222
+
223
+ c = polynomial.leading_coefficient()
224
+ if not c.is_unit():
225
+ raise TypeError("polynomial must have unit leading coefficient")
226
+
227
+ if names is None:
228
+ names = tuple([x + 'bar' for x in ring.variable_names()])
229
+ else:
230
+ names = normalize_names(ring.ngens(), names)
231
+
232
+ return ring, polynomial, names
233
+
234
+ def create_object(self, version, key):
235
+ r"""
236
+ Return the quotient ring specified by ``key``.
237
+
238
+ EXAMPLES::
239
+
240
+ sage: R.<x> = QQ[]
241
+ sage: PolynomialQuotientRing.create_object((8, 0, 0),
242
+ ....: (R, x^2 - 1, ('xbar')))
243
+ Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 - 1
244
+ """
245
+ ring, polynomial, names = key
246
+
247
+ R = ring.base_ring()
248
+ from sage.categories.integral_domains import IntegralDomains
249
+ from sage.categories.fields import Fields
250
+ if R in IntegralDomains():
251
+ try:
252
+ is_irreducible = polynomial.is_irreducible()
253
+ except NotImplementedError: # is_irreducible sometimes not implemented
254
+ pass
255
+ else:
256
+ if is_irreducible:
257
+ if R in Fields():
258
+ return PolynomialQuotientRing_field(ring, polynomial, names)
259
+ else:
260
+ return PolynomialQuotientRing_domain(ring, polynomial, names)
261
+ return PolynomialQuotientRing_generic(ring, polynomial, names)
262
+
263
+
264
+ PolynomialQuotientRing = PolynomialQuotientRingFactory("PolynomialQuotientRing")
265
+
266
+
267
+ def is_PolynomialQuotientRing(x):
268
+ from sage.misc.superseded import deprecation
269
+ deprecation(38266,
270
+ "The function is_PolynomialQuotientRing is deprecated; "
271
+ "use 'isinstance(..., PolynomialQuotientRing_generic)' instead.")
272
+ return isinstance(x, PolynomialQuotientRing_generic)
273
+
274
+
275
+ class PolynomialQuotientRing_generic(QuotientRing_generic):
276
+ """
277
+ Quotient of a univariate polynomial ring by an ideal.
278
+
279
+ EXAMPLES::
280
+
281
+ sage: R.<x> = PolynomialRing(Integers(8)); R
282
+ Univariate Polynomial Ring in x over Ring of integers modulo 8
283
+ sage: S.<xbar> = R.quotient(x^2 + 1); S
284
+ Univariate Quotient Polynomial Ring in xbar over Ring of integers modulo 8
285
+ with modulus x^2 + 1
286
+
287
+ We demonstrate object persistence.
288
+
289
+ ::
290
+
291
+ sage: loads(S.dumps()) == S
292
+ True
293
+ sage: loads(xbar.dumps()) == xbar
294
+ True
295
+
296
+ We create some sample homomorphisms;
297
+
298
+ ::
299
+
300
+ sage: R.<x> = PolynomialRing(ZZ)
301
+ sage: S = R.quo(x^2 - 4)
302
+ sage: f = S.hom([2])
303
+ sage: f
304
+ Ring morphism:
305
+ From: Univariate Quotient Polynomial Ring in xbar over Integer Ring
306
+ with modulus x^2 - 4
307
+ To: Integer Ring
308
+ Defn: xbar |--> 2
309
+ sage: f(x)
310
+ 2
311
+ sage: f(x^2 - 4)
312
+ 0
313
+ sage: f(x^2)
314
+ 4
315
+
316
+ TESTS:
317
+
318
+ By :issue:`11900`, polynomial quotient rings use Sage's
319
+ category framework. They do so in an unusual way: During their
320
+ initialisation, they are declared to be objects in the category of
321
+ quotients of commutative algebras over a base ring. However, if it
322
+ is tested whether a quotient ring is actually a field, the
323
+ category might be refined, which also includes a change of the
324
+ class of the quotient ring and its newly created elements.
325
+
326
+ Thus, in order to document that this works fine, we go into some detail::
327
+
328
+ sage: P.<x> = QQ[]
329
+ sage: Q = P.quotient(x^2 + 2)
330
+ sage: Q.category()
331
+ Category of commutative no zero divisors quotients of algebras over
332
+ (number fields and quotient fields and metric spaces)
333
+
334
+ We verify that the elements belong to the correct element class.
335
+ Also, we list the attributes that are provided by the element
336
+ class of the category, and store the current class of the quotient
337
+ ring::
338
+
339
+ sage: isinstance(Q.an_element(), Q.element_class)
340
+ True
341
+ sage: [s for s in dir(Q.category().element_class) if not s.startswith('_')]
342
+ ['cartesian_product', 'inverse', 'inverse_of_unit', 'is_idempotent',
343
+ 'is_one', 'is_unit', 'lift', 'powers']
344
+ sage: first_class = Q.__class__
345
+
346
+ We try to find out whether `Q` is a field. Indeed it is, and thus its category,
347
+ including its class and element class, is changed accordingly::
348
+
349
+ sage: Q in Fields()
350
+ True
351
+ sage: Q.category()
352
+ Category of commutative division no zero divisors quotients of algebras
353
+ over (number fields and quotient fields and metric spaces)
354
+ sage: first_class == Q.__class__
355
+ False
356
+ sage: [s for s in dir(Q.category().element_class) if not s.startswith('_')]
357
+ ['cartesian_product',
358
+ 'euclidean_degree',
359
+ 'factor',
360
+ 'gcd',
361
+ 'inverse',
362
+ 'inverse_of_unit',
363
+ 'is_idempotent',
364
+ 'is_one',
365
+ 'is_unit',
366
+ 'lcm',
367
+ 'lift',
368
+ 'powers',
369
+ 'quo_rem',
370
+ 'radical',
371
+ 'squarefree_part',
372
+ 'xgcd']
373
+
374
+ As one can see, the elements are now inheriting additional
375
+ methods: lcm and gcd. Even though ``Q.an_element()`` belongs to
376
+ the old and not to the new element class, it still inherits the
377
+ new methods from the category of fields, thanks to
378
+ :meth:`Element.__getattr__`::
379
+
380
+ sage: e = Q.an_element()
381
+ sage: isinstance(e, Q.element_class)
382
+ False
383
+ sage: e.gcd(e + 1)
384
+ 1
385
+
386
+ The test suite passes. However, we have to skip the test for its elements,
387
+ since ``an_element`` has been cached in the call above and its class does not
388
+ match the new category's element class anymore::
389
+
390
+ sage: TestSuite(Q).run(skip=['_test_elements']) # needs sage.rings.number_field
391
+
392
+ Newly created elements are fine, though, and their test suite passes::
393
+
394
+ sage: TestSuite(Q(x)).run()
395
+ sage: isinstance(Q(x), Q.element_class)
396
+ True
397
+ """
398
+ Element = PolynomialQuotientRingElement
399
+
400
+ def __init__(self, ring, polynomial, name=None, category=None):
401
+ """
402
+ TESTS::
403
+
404
+ sage: R.<x> = PolynomialRing(ZZ)
405
+ sage: S = R.quo(x^2 - 4)
406
+ sage: from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_generic
407
+ sage: S == PolynomialQuotientRing_generic(R, x^2 - 4, 'xbar')
408
+ True
409
+
410
+ Check that :issue:`26161` has been resolved::
411
+
412
+ sage: R.<x> = GF(2)[]
413
+ sage: S = R.quo(x) # needs sage.rings.finite_rings
414
+ sage: S in FiniteFields() # needs sage.rings.finite_rings
415
+ True
416
+ sage: type(S).mro() # needs sage.rings.finite_rings
417
+ [<class 'sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_field_with_category'>,
418
+ ...
419
+ <class 'sage.categories.finite_fields.FiniteFields.parent_class'>,
420
+ ...
421
+ """
422
+ if not isinstance(ring, PolynomialRing_commutative):
423
+ raise TypeError("R must be a univariate polynomial ring.")
424
+
425
+ if not isinstance(polynomial, polynomial_element.Polynomial):
426
+ raise TypeError("f must be a Polynomial")
427
+
428
+ if polynomial.parent() != ring:
429
+ raise TypeError("f must have parent R")
430
+
431
+ self.__ring = ring
432
+ self.__polynomial = polynomial
433
+ category = CommutativeAlgebras(ring.base_ring().category()).Quotients().or_subcategory(category)
434
+ if self.is_finite():
435
+ # We refine the category for finite quotients.
436
+ # Note that is_finite() is cheap so it does not seem to do a lazy
437
+ # _refine_category_() in is_finite() as we do for is_field()
438
+ category = category.Finite()
439
+
440
+ QuotientRing_generic.__init__(self, ring, ring.ideal(polynomial), names=name, category=category)
441
+ self._base = ring # backwards compatibility -- different from QuotientRing_generic
442
+
443
+ _ideal_class_ = QuotientRing_generic._ideal_class_
444
+
445
+ def _element_constructor_(self, x):
446
+ """
447
+ Convert x into this quotient ring. Anything that can be converted into
448
+ the polynomial ring can be converted into the quotient.
449
+
450
+ INPUT:
451
+
452
+ - ``x`` -- object to be converted
453
+
454
+ OUTPUT: an element obtained by converting x into this ring
455
+
456
+ EXAMPLES::
457
+
458
+ sage: R.<x> = PolynomialRing(QQ)
459
+ sage: S.<alpha> = R.quotient(x^3 - 3*x + 1)
460
+ sage: S(x)
461
+ alpha
462
+ sage: S(x^3)
463
+ 3*alpha - 1
464
+ sage: S([1,2])
465
+ 2*alpha + 1
466
+ sage: S([1,2,3,4,5])
467
+ 18*alpha^2 + 9*alpha - 3
468
+ sage: S(S.gen()+1)
469
+ alpha + 1
470
+ sage: S(S.gen()^10+1)
471
+ 90*alpha^2 - 109*alpha + 28
472
+
473
+ TESTS:
474
+
475
+ Conversion should work even if there is no coercion.
476
+ This was fixed in :issue:`8800`::
477
+
478
+ sage: P.<x> = QQ[]
479
+ sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
480
+ sage: Q = P.quo([(x^2+1)^2])
481
+ sage: Q1.has_coerce_map_from(Q)
482
+ False
483
+ sage: Q1(Q.gen())
484
+ xbar
485
+
486
+ Here we test against several issues discussed in :issue:`8992`::
487
+
488
+ sage: P.<x> = QQ[]
489
+ sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
490
+ sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)])
491
+ sage: p = Q1.gen() + Q2.gen()
492
+ sage: p
493
+ 2*xbar
494
+ sage: p.parent()
495
+ Univariate Quotient Polynomial Ring in xbar over Rational Field
496
+ with modulus x^4 + 2*x^2 + 1
497
+ sage: p.parent()('xbar')
498
+ xbar
499
+
500
+ Note that the result of string conversion has the correct parent, even
501
+ when the given string suggests an element of the cover ring or the base
502
+ ring::
503
+
504
+ sage: a = Q1('x'); a
505
+ xbar
506
+ sage: a.parent() is Q1
507
+ True
508
+ sage: b = Q1('1'); b
509
+ 1
510
+ sage: b.parent() is Q1
511
+ True
512
+
513
+ Conversion may lift an element of one quotient ring to the base ring of
514
+ another quotient ring::
515
+
516
+ sage: R.<y> = P[]
517
+ sage: Q3 = R.quo([(y^2+1)])
518
+ sage: Q3(Q1.gen())
519
+ x
520
+ sage: Q3.has_coerce_map_from(Q1)
521
+ False
522
+
523
+ String conversion takes into account both the generators of the quotient
524
+ ring and its base ring::
525
+
526
+ sage: Q3('x*ybar^2')
527
+ -x
528
+ """
529
+ if not isinstance(x, str):
530
+ try:
531
+ return self.element_class(self, self.__ring(x) , check=True)
532
+ except TypeError:
533
+ xlift = getattr(x,'lift',None)
534
+ if xlift is not None: # duck typing for quotient ring elements
535
+ return self.element_class(self, self.__ring(x.lift()), check=False)
536
+ # The problem with the string representation is that it could in principle
537
+ # mix elements of self with elements of self's cover ring. We therefore
538
+ # resort to sage_eval.
539
+ # Interpretation in self has priority over interpretation in self.__ring
540
+ try:
541
+ from sage.misc.sage_eval import sage_eval
542
+ out = sage_eval(x, GenDictWithBasering(self,self.gens_dict()))
543
+ if out.parent() is not self:
544
+ return self(out)
545
+ return out
546
+ except (TypeError, NameError):
547
+ pass
548
+ try:
549
+ return self.element_class(self, self.__ring(x), check=False)
550
+ except TypeError:
551
+ raise TypeError("unable to convert %r to an element of %s" % (x, self))
552
+
553
+ def _coerce_map_from_(self, R):
554
+ r"""
555
+ Return a coerce map from ``R``.
556
+
557
+ Anything coercing into the underlying polynomial ring coerces into this
558
+ quotient. Furthermore, for quotients `R=A[x]/(f)` and `S=B[x]/(g)` with
559
+ a coercion `R\to S` there is a coercion iff `f` divides `g`.
560
+
561
+ AUTHOR:
562
+
563
+ - Simon King (2010-12): :issue:`8800`
564
+
565
+ TESTS::
566
+
567
+ sage: P5.<x> = GF(5)[]
568
+ sage: Q = P5.quo([(x^2+1)^2])
569
+ sage: P.<x> = ZZ[]
570
+ sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
571
+ sage: Q2 = P.quo([(x^2+1)^2*(x^5+3)])
572
+ sage: Q.has_coerce_map_from(Q1) #indirect doctest
573
+ True
574
+ sage: Q1.has_coerce_map_from(Q)
575
+ False
576
+ sage: Q1.has_coerce_map_from(Q2)
577
+ False
578
+
579
+ The following tests against a bug fixed in :issue:`8992`::
580
+
581
+ sage: P.<x> = QQ[]
582
+ sage: Q1 = P.quo([(x^2+1)^2*(x^2-3)])
583
+ sage: R.<y> = P[]
584
+ sage: Q2 = R.quo([(y^2 + 1)])
585
+ sage: Q2.has_coerce_map_from(Q1)
586
+ False
587
+ """
588
+ if self.__ring.has_coerce_map_from(R):
589
+ return True
590
+ if isinstance(R, PolynomialQuotientRing_generic):
591
+ try:
592
+ if not self.__polynomial.divides(R.modulus()):
593
+ return False
594
+ except (ZeroDivisionError,ArithmeticError):
595
+ return False
596
+ from sage.categories.homset import Hom
597
+ parent = Hom(R, self, category=self.category()._meet_(R.category()))
598
+ return parent.__make_element_class__(PolynomialQuotientRing_coercion)(R, self, category=parent.homset_category())
599
+
600
+ def _is_valid_homomorphism_(self, codomain, im_gens, base_map=None):
601
+ """
602
+ EXAMPLES::
603
+
604
+ sage: # needs sage.rings.number_field
605
+ sage: T.<t> = ZZ[]
606
+ sage: K.<i> = NumberField(t^2 + 1)
607
+ sage: R.<x> = K[]
608
+ sage: S.<a> = R.quotient(x^2 - i)
609
+ sage: Q8.<z> = CyclotomicField(8)
610
+ sage: S._is_valid_homomorphism_(Q8, [z]) # no coercion from K to Q8
611
+ False
612
+ sage: S._is_valid_homomorphism_(Q8, [z], K.hom([z^2]))
613
+ True
614
+ sage: S._is_valid_homomorphism_(Q8, [1/z], K.hom([z^-2]))
615
+ True
616
+ """
617
+ if base_map is None and not codomain.has_coerce_map_from(self.base_ring()):
618
+ # If no base_map given, we need that elements of the base ring
619
+ # of the polynomial ring map canonically into codomain.
620
+ return False
621
+
622
+ # We also need that the polynomial modulus maps to 0, after twisting by the base_map
623
+ f = self.modulus()
624
+ try:
625
+ if base_map is not None:
626
+ f = f.map_coefficients(base_map)
627
+ return codomain(f(im_gens[0])) == 0
628
+ except (TypeError, ValueError):
629
+ return False
630
+
631
+ def _coerce_impl(self, x):
632
+ """
633
+ Return the coercion of x into this polynomial quotient ring.
634
+
635
+ The rings that coerce into the quotient ring canonically are:
636
+
637
+ - this ring
638
+
639
+ - any canonically isomorphic ring
640
+
641
+ - anything that coerces into the ring of which this is the
642
+ quotient
643
+ """
644
+ if isinstance(x, PolynomialQuotientRingElement):
645
+ if x.parent() == self:
646
+ return self.element_class(self, self.__ring(x.lift()), check=False)
647
+ # any ring that coerces to the base ring of this polynomial ring.
648
+ return self(self.polynomial_ring().coerce(x))
649
+
650
+ ############################################
651
+ # Methods to make the category framework happy...
652
+ #
653
+
654
+ retract = _coerce_impl
655
+ ambient = CommutativeRing.base
656
+
657
+ def lift(self, x):
658
+ """
659
+ Return an element of the ambient ring mapping to the given argument.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: P.<x> = QQ[]
664
+ sage: Q = P.quotient(x^2 + 2)
665
+ sage: Q.lift(Q.0^3)
666
+ -2*x
667
+ sage: Q(-2*x)
668
+ -2*xbar
669
+ sage: Q.0^3
670
+ -2*xbar
671
+ """
672
+ return x.lift()
673
+
674
+ def __eq__(self, other):
675
+ """
676
+ Check whether ``self`` is equal to ``other``.
677
+
678
+ EXAMPLES::
679
+
680
+ sage: Rx.<x> = PolynomialRing(QQ)
681
+ sage: Ry.<y> = PolynomialRing(QQ)
682
+ sage: Rx == Ry
683
+ False
684
+ sage: Qx = Rx.quotient(x^2 + 1)
685
+ sage: Qy = Ry.quotient(y^2 + 1)
686
+ sage: Qx == Qy
687
+ False
688
+ sage: Qx == Qx
689
+ True
690
+ sage: Qz = Rx.quotient(x^2 + 1)
691
+ sage: Qz == Qx
692
+ True
693
+ """
694
+ if not isinstance(other, PolynomialQuotientRing_generic):
695
+ return False
696
+ return (self.polynomial_ring() == other.polynomial_ring() and
697
+ self.modulus() == other.modulus())
698
+
699
+ def __ne__(self, other):
700
+ """
701
+ Check whether ``self`` is not equal to ``other``.
702
+
703
+ EXAMPLES::
704
+
705
+ sage: Rx.<x> = PolynomialRing(QQ)
706
+ sage: Ry.<y> = PolynomialRing(QQ)
707
+ sage: Rx != Ry
708
+ True
709
+ sage: Qx = Rx.quotient(x^2 + 1)
710
+ sage: Qy = Ry.quotient(y^2 + 1)
711
+ sage: Qx != Qy
712
+ True
713
+ sage: Qx != Qx
714
+ False
715
+ sage: Qz = Rx.quotient(x^2 + 1)
716
+ sage: Qz != Qx
717
+ False
718
+ """
719
+ return not (self == other)
720
+
721
+ def __hash__(self):
722
+ """
723
+ Return the hash of ``self``.
724
+
725
+ EXAMPLES::
726
+
727
+ sage: Rx.<x> = PolynomialRing(QQ)
728
+ sage: Ry.<y> = PolynomialRing(QQ)
729
+ sage: hash(Rx) == hash(Ry)
730
+ False
731
+ sage: Qx = Rx.quotient(x^2 + 1)
732
+ sage: Qy = Ry.quotient(y^2 + 1)
733
+ sage: hash(Qx) == hash(Qy)
734
+ False
735
+ sage: hash(Qx) == hash(Qx)
736
+ True
737
+ sage: Qz = Rx.quotient(x^2 + 1)
738
+ sage: hash(Qz) == hash(Qx)
739
+ True
740
+ """
741
+ return hash((self.polynomial_ring(), self.modulus()))
742
+
743
+ def _singular_init_(self, S=None):
744
+ """
745
+ Represent ``self`` in the Singular interface.
746
+
747
+ TESTS::
748
+
749
+ sage: P.<x> = QQ[]
750
+ sage: Q = P.quo([(x^2 + 1)])
751
+ sage: singular(Q) # indirect doctest # needs sage.libs.singular
752
+ polynomial ring, over a field, global ordering
753
+ // coefficients: QQ...
754
+ // number of vars : 1
755
+ // block 1 : ordering lp
756
+ // : names xbar
757
+ // block 2 : ordering C
758
+ // quotient ring from ideal
759
+ _[1]=xbar^2+1
760
+ sage: singular(Q.gen()) # needs sage.libs.singular
761
+ xbar
762
+ """
763
+ if S is None:
764
+ from sage.interfaces.singular import singular as S
765
+ Rpoly = S(self.polynomial_ring())
766
+ Rpoly.set_ring()
767
+ modulus = S(self.modulus()) # should live in Rpoly
768
+ Rtmp = S(self.polynomial_ring().change_var(self.variable_name()))
769
+ Rtmp.set_ring()
770
+ self.__singular = S("ideal(fetch(%s,%s))" % (Rpoly.name(),modulus.name()),"qring")
771
+ return self.__singular
772
+
773
+ def _repr_(self):
774
+ return "Univariate Quotient Polynomial Ring in %s over %s with modulus %s" % (
775
+ self.variable_name(), self.base_ring(), self.modulus())
776
+
777
+ def construction(self):
778
+ """
779
+ Functorial construction of ``self``.
780
+
781
+ EXAMPLES::
782
+
783
+ sage: P.<t> = ZZ[]
784
+ sage: Q = P.quo(5 + t^2)
785
+ sage: F, R = Q.construction()
786
+ sage: F(R) == Q
787
+ True
788
+ sage: P.<t> = GF(3)[]
789
+ sage: Q = P.quo([2 + t^2])
790
+ sage: F, R = Q.construction()
791
+ sage: F(R) == Q
792
+ True
793
+
794
+ AUTHOR:
795
+
796
+ -- Simon King (2010-05)
797
+ """
798
+ from sage.categories.pushout import QuotientFunctor
799
+ Cover = self.__ring
800
+ kwds = {}
801
+ if Cover in CommutativeRings():
802
+ kwds['domain'] = kwds['codomain'] = CommutativeRings()
803
+ return QuotientFunctor([self.modulus()]*Cover, self.variable_names(), **kwds), Cover
804
+
805
+ @cached_method
806
+ def base_ring(self):
807
+ r"""
808
+ Return the base ring of the polynomial ring, of which this ring is
809
+ a quotient.
810
+
811
+ EXAMPLES:
812
+
813
+ The base ring of
814
+ `\ZZ[z]/(z^3 + z^2 + z + 1)` is
815
+ `\ZZ`.
816
+
817
+ ::
818
+
819
+ sage: R.<z> = PolynomialRing(ZZ)
820
+ sage: S.<beta> = R.quo(z^3 + z^2 + z + 1)
821
+ sage: S.base_ring()
822
+ Integer Ring
823
+
824
+ Next we make a polynomial quotient ring over `S` and ask
825
+ for its base ring.
826
+
827
+ ::
828
+
829
+ sage: T.<t> = PolynomialRing(S)
830
+ sage: W = T.quotient(t^99 + 99)
831
+ sage: W.base_ring()
832
+ Univariate Quotient Polynomial Ring in beta
833
+ over Integer Ring with modulus z^3 + z^2 + z + 1
834
+ """
835
+ return self.__ring.base_ring()
836
+
837
+ def cardinality(self):
838
+ """
839
+ Return the number of elements of this quotient ring.
840
+
841
+ ``order`` is an alias of ``cardinality``.
842
+
843
+ EXAMPLES::
844
+
845
+ sage: R.<x> = ZZ[]
846
+ sage: R.quo(1).cardinality()
847
+ 1
848
+ sage: R.quo(x^3 - 2).cardinality()
849
+ +Infinity
850
+
851
+ sage: R.quo(1).order()
852
+ 1
853
+ sage: R.quo(x^3 - 2).order()
854
+ +Infinity
855
+
856
+ ::
857
+
858
+ sage: # needs sage.rings.finite_rings
859
+ sage: R.<x> = GF(9, 'a')[]
860
+ sage: R.quo(2*x^3 + x + 1).cardinality()
861
+ 729
862
+ sage: GF(9, 'a').extension(2*x^3 + x + 1).cardinality()
863
+ 729
864
+ sage: R.quo(2).cardinality()
865
+ 1
866
+
867
+ TESTS::
868
+
869
+ sage: parent(QQ['x'].quo(1).cardinality())
870
+ Integer Ring
871
+ sage: parent(QQ['x'].quo(1).order())
872
+ Integer Ring
873
+ """
874
+ if not self.is_finite():
875
+ from sage.rings.infinity import Infinity
876
+ return Infinity
877
+ f = self.modulus()
878
+ # Two cases where the quotient is finite (see is_finite())
879
+ # 1) R[x]/(1)
880
+ if f.degree() == 0:
881
+ from sage.rings.integer_ring import ZZ
882
+ return ZZ.one()
883
+ # 2) F[x]/(f) where F is finite
884
+ else:
885
+ return self.base_ring().cardinality() ** f.degree()
886
+
887
+ order = cardinality
888
+
889
+ def is_finite(self):
890
+ """
891
+ Return whether or not this quotient ring is finite.
892
+
893
+ EXAMPLES::
894
+
895
+ sage: R.<x> = ZZ[]
896
+ sage: R.quo(1).is_finite()
897
+ True
898
+ sage: R.quo(x^3 - 2).is_finite()
899
+ False
900
+
901
+ ::
902
+
903
+ sage: R.<x> = GF(9, 'a')[] # needs sage.rings.finite_rings
904
+ sage: R.quo(2*x^3 + x + 1).is_finite() # needs sage.rings.finite_rings
905
+ True
906
+ sage: R.quo(2).is_finite() # needs sage.rings.finite_rings
907
+ True
908
+
909
+ ::
910
+
911
+ sage: P.<v> = GF(2)[]
912
+ sage: P.quotient(v^2 - v).is_finite()
913
+ True
914
+ """
915
+ f = self.modulus()
916
+
917
+ # note: the constructor assumes that the leading coefficient is a
918
+ # unit. However, this function would be very wrong if otherwise.
919
+ # As a safety measure, we check that again here.
920
+ assert f.leading_coefficient().is_unit()
921
+
922
+ return f.degree() == 0 or self.base_ring().is_finite()
923
+
924
+ def __iter__(self):
925
+ r"""
926
+ EXAMPLES::
927
+
928
+ sage: R.<x> = GF(3)[]
929
+ sage: Q = R.quo(x^3 - x^2 - x - 1)
930
+ sage: list(Q)
931
+ [0,
932
+ 1,
933
+ 2,
934
+ xbar,
935
+ xbar + 1,
936
+ xbar + 2,
937
+ 2*xbar,
938
+ ...
939
+ 2*xbar^2 + 2*xbar + 1,
940
+ 2*xbar^2 + 2*xbar + 2]
941
+ sage: len(_) == Q.cardinality() == 27
942
+ True
943
+ """
944
+ if not self.is_finite():
945
+ raise NotImplementedError('not possible to iterate through infinite quotient')
946
+
947
+ R = self.polynomial_ring()
948
+ yield self.zero()
949
+ for i in range(self.modulus().degree()):
950
+ for p in R.polynomials(of_degree=i):
951
+ yield self(p)
952
+
953
+ def characteristic(self):
954
+ """
955
+ Return the characteristic of this quotient ring.
956
+
957
+ This is always the same as the characteristic of the base ring.
958
+
959
+ EXAMPLES::
960
+
961
+ sage: R.<z> = PolynomialRing(ZZ)
962
+ sage: S.<a> = R.quo(z - 19)
963
+ sage: S.characteristic()
964
+ 0
965
+ sage: R.<x> = PolynomialRing(GF(9, 'a')) # needs sage.rings.finite_rings
966
+ sage: S = R.quotient(x^3 + 1) # needs sage.rings.finite_rings
967
+ sage: S.characteristic() # needs sage.rings.finite_rings
968
+ 3
969
+ """
970
+ return self.base_ring().characteristic()
971
+
972
+ def degree(self):
973
+ """
974
+ Return the degree of this quotient ring. The degree is the degree
975
+ of the polynomial that we quotiented out by.
976
+
977
+ EXAMPLES::
978
+
979
+ sage: R.<x> = PolynomialRing(GF(3))
980
+ sage: S = R.quotient(x^2005 + 1)
981
+ sage: S.degree()
982
+ 2005
983
+ """
984
+ return self.modulus().degree()
985
+
986
+ def discriminant(self, v=None):
987
+ """
988
+ Return the discriminant of this ring over the base ring. This is by
989
+ definition the discriminant of the polynomial that we quotiented
990
+ out by.
991
+
992
+ EXAMPLES::
993
+
994
+ sage: R.<x> = PolynomialRing(QQ)
995
+ sage: S = R.quotient(x^3 + x^2 + x + 1)
996
+ sage: S.discriminant()
997
+ -16
998
+ sage: S = R.quotient((x + 1) * (x + 1))
999
+ sage: S.discriminant()
1000
+ 0
1001
+
1002
+ The discriminant of the quotient polynomial ring need not equal the
1003
+ discriminant of the corresponding number field, since the
1004
+ discriminant of a number field is by definition the discriminant of
1005
+ the ring of integers of the number field::
1006
+
1007
+ sage: S = R.quotient(x^2 - 8)
1008
+ sage: S.number_field().discriminant() # needs sage.rings.number_field
1009
+ 8
1010
+ sage: S.discriminant()
1011
+ 32
1012
+ """
1013
+ return self.modulus().discriminant()
1014
+
1015
+ def gen(self, n=0):
1016
+ """
1017
+ Return the generator of this quotient ring. This is the equivalence
1018
+ class of the image of the generator of the polynomial ring.
1019
+
1020
+ EXAMPLES::
1021
+
1022
+ sage: R.<x> = PolynomialRing(QQ)
1023
+ sage: S = R.quotient(x^2 - 8, 'gamma')
1024
+ sage: S.gen()
1025
+ gamma
1026
+ """
1027
+ if n != 0:
1028
+ raise IndexError("Only one generator.")
1029
+ try:
1030
+ return self.__gen
1031
+ except AttributeError:
1032
+ self.__gen = self(self.polynomial_ring().gen())
1033
+ return self.__gen
1034
+
1035
+ def is_field(self, proof=True):
1036
+ """
1037
+ Return whether or not this quotient ring is a field.
1038
+
1039
+ EXAMPLES::
1040
+
1041
+ sage: R.<z> = PolynomialRing(ZZ)
1042
+ sage: S = R.quo(z^2 - 2)
1043
+ sage: S.is_field()
1044
+ False
1045
+ sage: R.<x> = PolynomialRing(QQ)
1046
+ sage: S = R.quotient(x^2 - 2)
1047
+ sage: S.is_field()
1048
+ True
1049
+
1050
+ If proof is ``True``, requires the ``is_irreducible`` method of the
1051
+ modulus to be implemented::
1052
+
1053
+ sage: # needs sage.rings.padics
1054
+ sage: R1.<x> = Qp(2)[]
1055
+ sage: F1 = R1.quotient_ring(x^2 + x + 1)
1056
+ sage: R2.<x> = F1[]
1057
+ sage: F2 = R2.quotient_ring(x^2 + x + 1)
1058
+ sage: F2.is_field()
1059
+ Traceback (most recent call last):
1060
+ ...
1061
+ NotImplementedError: cannot rewrite Univariate Quotient Polynomial Ring in
1062
+ xbar over 2-adic Field with capped relative precision 20 with modulus
1063
+ (1 + O(2^20))*x^2 + (1 + O(2^20))*x + 1 + O(2^20) as an isomorphic ring
1064
+ sage: F2.is_field(proof = False)
1065
+ False
1066
+ """
1067
+ ret = self.base_ring().is_field(proof)
1068
+ try:
1069
+ ret = ret and self.modulus().is_irreducible()
1070
+ except NotImplementedError:
1071
+ if proof:
1072
+ raise
1073
+ else:
1074
+ ret = False
1075
+
1076
+ if ret:
1077
+ from sage.categories.fields import Fields
1078
+ self._refine_category_(Fields())
1079
+ return ret
1080
+
1081
+ def is_integral_domain(self, proof=True):
1082
+ """
1083
+ Return whether or not this quotient ring is an integral domain.
1084
+
1085
+ EXAMPLES::
1086
+
1087
+ sage: R.<z> = PolynomialRing(ZZ)
1088
+
1089
+ sage: S = R.quotient(z^2 - z)
1090
+ sage: S.is_integral_domain()
1091
+ False
1092
+ sage: T = R.quotient(z^2 + 1)
1093
+ sage: T.is_integral_domain()
1094
+ True
1095
+ sage: U = R.quotient(-1)
1096
+ sage: U.is_integral_domain()
1097
+ False
1098
+
1099
+ sage: # needs sage.libs.singular
1100
+ sage: R2.<y> = PolynomialRing(R)
1101
+ sage: S2 = R2.quotient(z^2 - y^3)
1102
+ sage: S2.is_integral_domain()
1103
+ True
1104
+ sage: S3 = R2.quotient(z^2 - 2*y*z + y^2)
1105
+ sage: S3.is_integral_domain()
1106
+ False
1107
+
1108
+ sage: R.<z> = PolynomialRing(ZZ.quotient(4))
1109
+ sage: S = R.quotient(z - 1)
1110
+ sage: S.is_integral_domain()
1111
+ False
1112
+
1113
+ TESTS:
1114
+
1115
+ Here is an example of a quotient ring which is not an integral
1116
+ domain, even though the base ring is integral and the modulus is
1117
+ irreducible::
1118
+
1119
+ sage: # needs sage.rings.number_field
1120
+ sage: x = polygen(ZZ, 'x')
1121
+ sage: B = ZZ.extension(x^2 - 5, 'a')
1122
+ sage: R.<y> = PolynomialRing(B)
1123
+ sage: S = R.quotient(y^2 - y - 1)
1124
+ sage: S.is_integral_domain()
1125
+ Traceback (most recent call last):
1126
+ ...
1127
+ NotImplementedError
1128
+ sage: S.is_integral_domain(proof=False)
1129
+ False
1130
+
1131
+ The reason that the modulus y^2 - y - 1 is not prime is that it
1132
+ divides the product
1133
+ (2*y-(1+a))*(2*y-(1-a)) = 4*y^2 - 4*y - 4.
1134
+
1135
+ Unfortunately, the program above is already unable to determine
1136
+ that the modulus is irreducible.
1137
+ """
1138
+ from sage.categories.integral_domains import IntegralDomains
1139
+ if self.category().is_subcategory(IntegralDomains()):
1140
+ return True
1141
+ ret = self.base_ring().is_integral_domain(proof)
1142
+ if ret:
1143
+ try:
1144
+ irr = self.modulus().is_irreducible()
1145
+ if not irr:
1146
+ # since the modulus is nonzero, the condition of the base ring being an
1147
+ # integral domain and the modulus being irreducible are
1148
+ # necessary but not sufficient
1149
+ ret = False
1150
+ else:
1151
+ from sage.categories.gcd_domains import GcdDomains
1152
+ if self.base_ring() in GcdDomains():
1153
+ # if the base ring is a GCD domain, the conditions are sufficient
1154
+ ret = True
1155
+ else:
1156
+ raise NotImplementedError
1157
+ except NotImplementedError:
1158
+ if proof:
1159
+ raise
1160
+ else:
1161
+ ret = False
1162
+
1163
+ if ret:
1164
+ self._refine_category_(IntegralDomains())
1165
+ return ret
1166
+
1167
+ def krull_dimension(self):
1168
+ """
1169
+ Return the Krull dimension.
1170
+
1171
+ This is the Krull dimension of the base ring, unless the
1172
+ quotient is zero.
1173
+
1174
+ EXAMPLES::
1175
+
1176
+ sage: x = polygen(ZZ, 'x')
1177
+ sage: R = PolynomialRing(ZZ, 'x').quotient(x**6 - 1)
1178
+ sage: R.krull_dimension()
1179
+ 1
1180
+ sage: R = PolynomialRing(ZZ, 'x').quotient(1)
1181
+ sage: R.krull_dimension()
1182
+ -1
1183
+ """
1184
+ if self.is_zero():
1185
+ return -1
1186
+ return self.base_ring().krull_dimension()
1187
+
1188
+ def modulus(self):
1189
+ """
1190
+ Return the polynomial modulus of this quotient ring.
1191
+
1192
+ EXAMPLES::
1193
+
1194
+ sage: R.<x> = PolynomialRing(GF(3))
1195
+ sage: S = R.quotient(x^2 - 2)
1196
+ sage: S.modulus()
1197
+ x^2 + 1
1198
+ """
1199
+ return self.__polynomial
1200
+
1201
+ def ngens(self):
1202
+ """
1203
+ Return the number of generators of this quotient ring over the base
1204
+ ring. This function always returns 1.
1205
+
1206
+ EXAMPLES::
1207
+
1208
+ sage: # needs sage.libs.singular
1209
+ sage: R.<x> = PolynomialRing(QQ)
1210
+ sage: S.<y> = PolynomialRing(R)
1211
+ sage: T.<z> = S.quotient(y + x)
1212
+ sage: T
1213
+ Univariate Quotient Polynomial Ring in z over
1214
+ Univariate Polynomial Ring in x over Rational Field with modulus y + x
1215
+ sage: T.ngens()
1216
+ 1
1217
+ """
1218
+ return 1
1219
+
1220
+ def number_field(self):
1221
+ """
1222
+ Return the number field isomorphic to this quotient polynomial
1223
+ ring, if possible.
1224
+
1225
+ EXAMPLES::
1226
+
1227
+ sage: # needs sage.rings.number_field
1228
+ sage: R.<x> = PolynomialRing(QQ)
1229
+ sage: S.<alpha> = R.quotient(x^29 - 17*x - 1)
1230
+ sage: K = S.number_field(); K
1231
+ Number Field in alpha with defining polynomial x^29 - 17*x - 1
1232
+ sage: alpha = K.gen()
1233
+ sage: alpha^29
1234
+ 17*alpha + 1
1235
+ """
1236
+ if self.characteristic() != 0:
1237
+ raise ArithmeticError("Polynomial quotient ring is not isomorphic to a number field (it has positive characteristic).")
1238
+
1239
+ if not isinstance(self.base_ring(), sage.rings.rational_field.RationalField):
1240
+ raise NotImplementedError("Computation of number field only implemented for quotients of the polynomial ring over the rational field.")
1241
+ from sage.rings.number_field.number_field import NumberField
1242
+ return NumberField(self.modulus(), self.variable_name())
1243
+
1244
+ def polynomial_ring(self):
1245
+ """
1246
+ Return the polynomial ring of which this ring is the quotient.
1247
+
1248
+ EXAMPLES::
1249
+
1250
+ sage: R.<x> = PolynomialRing(QQ)
1251
+ sage: S = R.quotient(x^2 - 2)
1252
+ sage: S.polynomial_ring()
1253
+ Univariate Polynomial Ring in x over Rational Field
1254
+ """
1255
+ return self.__ring
1256
+
1257
+ cover_ring = polynomial_ring
1258
+
1259
+ def random_element(self, degree=None, *args, **kwds):
1260
+ """
1261
+ Return a random element of this quotient ring.
1262
+
1263
+ INPUT:
1264
+
1265
+ - ``degree`` -- (optional) argument; either an integer for fixing the
1266
+ degree, or a tuple of the minimum and maximum degree. By default the
1267
+ degree is n - 1 with n the degree of the polynomial ring. Note that
1268
+ the degree of the polynomial is fixed before the modulo calculation.
1269
+ So when `degree` is bigger than the degree of the polynomial ring, the
1270
+ degree of the returned polynomial would be lower than `degree`.
1271
+ - ``*args``, ``**kwds`` -- arguments for randomization that are passed
1272
+ on to the ``random_element`` method of the polynomial ring, and from
1273
+ there to the base ring
1274
+
1275
+ OUTPUT: element of this quotient ring
1276
+
1277
+ EXAMPLES::
1278
+
1279
+ sage: # needs sage.modules sage.rings.finite_rings
1280
+ sage: F1.<a> = GF(2^7)
1281
+ sage: P1.<x> = F1[]
1282
+ sage: F2 = F1.extension(x^2 + x + 1, 'u')
1283
+ sage: F2.random_element().parent() is F2
1284
+ True
1285
+ """
1286
+ if degree is None:
1287
+ degree = self.degree() - 1
1288
+
1289
+ return self(self.polynomial_ring().random_element(
1290
+ degree=degree, *args, **kwds))
1291
+
1292
+ @cached_method
1293
+ def _S_decomposition(self, S):
1294
+ """
1295
+ Compute the decomposition of ``self`` into a product of number fields.
1296
+
1297
+ This is an internal function used by
1298
+ :meth:`S_class_group`, :meth:`S_units` and :meth:`selmer_generators`.
1299
+
1300
+ EXAMPLES::
1301
+
1302
+ sage: # needs sage.rings.number_field
1303
+ sage: K.<a> = QuadraticField(-5)
1304
+ sage: R.<x> = K[]
1305
+ sage: S.<xbar> = R.quotient((x^2 + 23) * (x^2 + 31))
1306
+ sage: fields, isos, iso_classes = S._S_decomposition(tuple(K.primes_above(3)))
1307
+
1308
+ Representatives of the number fields up to isomorphism that
1309
+ occur in the decomposition::
1310
+
1311
+ sage: fields # needs sage.rings.number_field
1312
+ [Number Field in x0 with defining polynomial x^2 + 23 over its base field,
1313
+ Number Field in x1 with defining polynomial x^2 + 31 over its base field]
1314
+
1315
+ In this case, the isomorphisms of these representatives to the components
1316
+ are the identity maps::
1317
+
1318
+ sage: isos # needs sage.rings.number_field
1319
+ [(Ring endomorphism of Number Field in y0 with defining polynomial x^4 + 56*x^2 + 324
1320
+ Defn: y0 |--> y0,
1321
+ 0),
1322
+ (Ring endomorphism of Number Field in y1 with defining polynomial x^4 + 72*x^2 + 676
1323
+ Defn: y1 |--> y1,
1324
+ 1)]
1325
+
1326
+ There are four primes above 3 in the first component and two
1327
+ in the second component::
1328
+
1329
+ sage: len(iso_classes[0][1]) # needs sage.rings.number_field
1330
+ 4
1331
+ sage: len(iso_classes[1][1]) # needs sage.rings.number_field
1332
+ 2
1333
+ """
1334
+ from sage.rings.number_field.number_field_base import NumberField
1335
+ K = self.base_ring()
1336
+ if not isinstance(K, NumberField) or not self.__polynomial.is_squarefree():
1337
+ raise NotImplementedError
1338
+
1339
+ from sage.rings.ideal import Ideal_generic
1340
+ for p in S:
1341
+ # second check due to inconsistency over QQ - see # 7596
1342
+ if not (isinstance(p, Ideal_generic)
1343
+ and (p.ring() is K or p.ring() is K.ring_of_integers())
1344
+ and p.is_prime()):
1345
+ raise TypeError("S must be a list of prime ideals of the base field.")
1346
+
1347
+ F = self.__polynomial.factor()
1348
+ fields = []
1349
+ isos = []
1350
+ iso_classes = []
1351
+ i = 0
1352
+ for f, _ in F:
1353
+ D = K.extension(f, 'x'+str(i))
1354
+ fields.append(D)
1355
+ D_abs = D.absolute_field('y'+str(i))
1356
+ i += 1
1357
+
1358
+ seen_before = False
1359
+ j = 0
1360
+ for D_iso, _ in iso_classes:
1361
+ if D_abs.is_isomorphic(D_iso):
1362
+ seen_before = True
1363
+ break
1364
+ j += 1
1365
+ if not seen_before:
1366
+ S_abs = []
1367
+ for p in S:
1368
+ # next line looks a bit silly,
1369
+ # due to inconsistency over QQ - see # 7596
1370
+ abs_gens = [D_abs.structure()[1](g)
1371
+ for g in D.ideal(p.gens()).gens()]
1372
+ S_abs += [pp for pp, _ in D_abs.ideal(abs_gens).factor()]
1373
+ iso_classes.append((D_abs, S_abs))
1374
+ isos.append((D_abs.embeddings(D_abs)[0], j))
1375
+ return fields, isos, iso_classes
1376
+
1377
+ def S_class_group(self, S, proof=True):
1378
+ r"""
1379
+ If ``self`` is an étale algebra `D` over a number field `K` (i.e.
1380
+ a quotient of `K[x]` by a squarefree polynomial) and `S` is a
1381
+ finite set of places of `K`, return a list of generators of
1382
+ the `S`-class group of `D`.
1383
+
1384
+ NOTE:
1385
+
1386
+ Since the ``ideal`` function behaves differently over number
1387
+ fields than over polynomial quotient rings (the quotient does
1388
+ not even know its ring of integers), we return a set of pairs
1389
+ ``(gen, order)``, where ``gen`` is a tuple of generators of an
1390
+ ideal `I` and ``order`` is the order of `I` in the `S`-class
1391
+ group.
1392
+
1393
+ INPUT:
1394
+
1395
+ - ``S`` -- set of primes of the coefficient ring
1396
+
1397
+ - ``proof`` -- if ``False``, assume the GRH in computing the class group
1398
+
1399
+ OUTPUT:
1400
+
1401
+ A list of generators of the `S`-class group, in the form
1402
+ ``(gen, order)``, where ``gen`` is a tuple of elements
1403
+ generating a fractional ideal `I` and ``order`` is the order
1404
+ of `I` in the `S`-class group.
1405
+
1406
+ EXAMPLES:
1407
+
1408
+ A trivial algebra over `\QQ(\sqrt{-5})` has the same class group as its
1409
+ base::
1410
+
1411
+ sage: # needs sage.rings.number_field
1412
+ sage: K.<a> = QuadraticField(-5)
1413
+ sage: R.<x> = K[]
1414
+ sage: S.<xbar> = R.quotient(x)
1415
+ sage: S.S_class_group([])
1416
+ [((2, -a + 1), 2)]
1417
+
1418
+ When we include the prime `(2, -a+1)`, the `S`-class group
1419
+ becomes trivial::
1420
+
1421
+ sage: S.S_class_group([K.ideal(2, -a+1)]) # needs sage.rings.number_field
1422
+ []
1423
+
1424
+ Here is an example where the base and the extension both contribute to
1425
+ the class group::
1426
+
1427
+ sage: # needs sage.rings.number_field
1428
+ sage: K.<a> = QuadraticField(-5)
1429
+ sage: K.class_group()
1430
+ Class group of order 2 with structure C2 of Number Field in a
1431
+ with defining polynomial x^2 + 5 with a = 2.236067977499790?*I
1432
+ sage: R.<x> = K[]
1433
+ sage: S.<xbar> = R.quotient(x^2 + 23)
1434
+ sage: S.S_class_group([])
1435
+ [((2, a + 1, -1/2*xbar + 3/2, 1/2*a*xbar - 1/2*a + 1), 6)]
1436
+ sage: S.S_class_group([K.ideal(3, a-1)])
1437
+ []
1438
+ sage: S.S_class_group([K.ideal(2, a+1)])
1439
+ []
1440
+ sage: S.S_class_group([K.ideal(a)])
1441
+ [((2, a + 1, -1/2*xbar + 3/2, 1/2*a*xbar - 1/2*a + 1), 6)]
1442
+
1443
+ Now we take an example over a nontrivial base with two factors, each
1444
+ contributing to the class group::
1445
+
1446
+ sage: # needs sage.rings.number_field
1447
+ sage: K.<a> = QuadraticField(-5)
1448
+ sage: R.<x> = K[]
1449
+ sage: S.<xbar> = R.quotient((x^2 + 23) * (x^2 + 31))
1450
+ sage: S.S_class_group([]) # not tested
1451
+ [((1/4*xbar^2 + 31/4,
1452
+ (-1/8*a + 1/8)*xbar^2 - 31/8*a + 31/8,
1453
+ 1/16*xbar^3 + 1/16*xbar^2 + 31/16*xbar + 31/16,
1454
+ -1/16*a*xbar^3 + (1/16*a + 1/8)*xbar^2 - 31/16*a*xbar + 31/16*a + 31/8),
1455
+ 6),
1456
+ ((-1/4*xbar^2 - 23/4,
1457
+ (1/8*a - 1/8)*xbar^2 + 23/8*a - 23/8,
1458
+ -1/16*xbar^3 - 1/16*xbar^2 - 23/16*xbar - 23/16,
1459
+ 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8),
1460
+ 6),
1461
+ ((-5/4*xbar^2 - 115/4,
1462
+ 1/4*a*xbar^2 + 23/4*a,
1463
+ -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16,
1464
+ 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a),
1465
+ 2)]
1466
+
1467
+ By using the ideal `(a)`, we cut the part of the class group coming from
1468
+ `x^2 + 31` from 12 to 2, i.e. we lose a generator of order 6 (this was
1469
+ fixed in :issue:`14489`)::
1470
+
1471
+ sage: S.S_class_group([K.ideal(a)]) # representation varies # not tested, needs sage.rings.number_field
1472
+ [((1/4*xbar^2 + 31/4, (-1/8*a + 1/8)*xbar^2 - 31/8*a + 31/8,
1473
+ 1/16*xbar^3 + 1/16*xbar^2 + 31/16*xbar + 31/16,
1474
+ -1/16*a*xbar^3 + (1/16*a + 1/8)*xbar^2 - 31/16*a*xbar + 31/16*a + 31/8),
1475
+ 6),
1476
+ ((-1/4*xbar^2 - 23/4, (1/8*a - 1/8)*xbar^2 + 23/8*a - 23/8,
1477
+ -1/16*xbar^3 - 1/16*xbar^2 - 23/16*xbar - 23/16,
1478
+ 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8),
1479
+ 2)]
1480
+
1481
+ Note that all the returned values live where we expect them to::
1482
+
1483
+ sage: # needs sage.rings.number_field
1484
+ sage: CG = S.S_class_group([])
1485
+ sage: type(CG[0][0][1])
1486
+ <class 'sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_generic_with_category.element_class'>
1487
+ sage: type(CG[0][1])
1488
+ <class 'sage.rings.integer.Integer'>
1489
+
1490
+ TESTS:
1491
+
1492
+ We verify the above test, where the representation depends on the PARI version::
1493
+
1494
+ sage: # needs sage.rings.number_field
1495
+ sage: K.<a> = QuadraticField(-5)
1496
+ sage: R.<x> = K[]
1497
+ sage: S.<xbar> = R.quotient((x^2 + 23) * (x^2 + 31))
1498
+ sage: C = S.S_class_group([])
1499
+ sage: C[:2]
1500
+ [((1/4*xbar^2 + 31/4,
1501
+ (1/8*a + 1/8)*xbar^2 + 31/8*a + 31/8,
1502
+ -1/16*xbar^3 + 3/16*xbar^2 - 31/16*xbar + 93/16,
1503
+ 1/16*a*xbar^3 + (-1/16*a + 1/8)*xbar^2 + 31/16*a*xbar - 31/16*a + 31/8),
1504
+ 6),
1505
+ ((-1/4*xbar^2 - 23/4,
1506
+ (-1/8*a - 1/8)*xbar^2 - 23/8*a - 23/8,
1507
+ 1/16*xbar^3 + 1/16*xbar^2 + 23/16*xbar + 23/16,
1508
+ -1/16*a*xbar^3 + (1/16*a - 1/8)*xbar^2 - 23/16*a*xbar + 23/16*a - 23/8),
1509
+ 6)]
1510
+ sage: C[2][1]
1511
+ 2
1512
+ sage: gens = C[2][0]
1513
+ sage: expected_gens = (
1514
+ ....: -5/4*xbar^2 - 115/4,
1515
+ ....: 1/4*a*xbar^2 + 23/4*a,
1516
+ ....: -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16,
1517
+ ....: 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a)
1518
+ sage: gens[0] == expected_gens[0]
1519
+ True
1520
+ sage: gens[1] in (expected_gens[1], expected_gens[1]/2 + expected_gens[0]/2, -expected_gens[1]/2 + expected_gens[0]/2)
1521
+ True
1522
+ sage: gens[2] in (expected_gens[2], expected_gens[2] + expected_gens[0]/2, -expected_gens[2] + expected_gens[0]/2)
1523
+ True
1524
+ sage: gens[3] in (expected_gens[3], expected_gens[3] + expected_gens[0]/2, -expected_gens[3] + expected_gens[0]/2)
1525
+ True
1526
+ """
1527
+ fields, isos, iso_classes = self._S_decomposition(tuple(S))
1528
+ n = len(fields)
1529
+
1530
+ component_S_class_groups = []
1531
+ for D_iso, S_iso in iso_classes:
1532
+ # compute S-class group for each distinct component
1533
+ clgp_gens = D_iso._S_class_group_and_units(tuple(S_iso), proof=proof)[1]
1534
+ component_S_class_groups.append(clgp_gens)
1535
+
1536
+ clgp_gens = []
1537
+ moduli = [D.relative_polynomial() for D in fields]
1538
+ for i in range(n):
1539
+ phi = isos[i][0]
1540
+ back_to_rel = phi.codomain().structure()[0]
1541
+
1542
+ for clgp_gen, gen_order in component_S_class_groups[isos[i][1]]:
1543
+ ideal_gens = []
1544
+ for ideal_gen in clgp_gen.gens():
1545
+ rel_ideal_gen = back_to_rel(phi(ideal_gen))
1546
+ prod_ideal_gen = [0]*i + [rel_ideal_gen.lift()] + [0]*(n - i - 1)
1547
+ poly_ideal_gen = self(crt(prod_ideal_gen, moduli))
1548
+ ideal_gens.append(poly_ideal_gen)
1549
+ clgp_gens.append((tuple(ideal_gens), gen_order))
1550
+
1551
+ return clgp_gens
1552
+
1553
+ def class_group(self, proof=True):
1554
+ r"""
1555
+ If ``self`` is a quotient ring of a polynomial ring over a number
1556
+ field `K`, by a polynomial of nonzero discriminant, return a
1557
+ list of generators of the class group.
1558
+
1559
+ NOTE:
1560
+
1561
+ Since the ``ideal`` function behaves differently over number
1562
+ fields than over polynomial quotient rings (the quotient does
1563
+ not even know its ring of integers), we return a set of pairs
1564
+ ``(gen, order)``, where ``gen`` is a tuple of generators of an
1565
+ ideal `I` and ``order`` is the order of `I` in the class group.
1566
+
1567
+ INPUT:
1568
+
1569
+ - ``proof`` -- if ``False``, assume the GRH in computing the class group
1570
+
1571
+ OUTPUT:
1572
+
1573
+ A list of pairs ``(gen, order)``, where ``gen`` is a tuple of
1574
+ elements generating a fractional ideal and ``order`` is
1575
+ the order of `I` in the class group.
1576
+
1577
+ EXAMPLES::
1578
+
1579
+ sage: # needs sage.rings.number_field
1580
+ sage: K.<a> = QuadraticField(-3)
1581
+ sage: K.class_group()
1582
+ Class group of order 1 of Number Field in a
1583
+ with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
1584
+ sage: x = polygen(QQ, 'x')
1585
+ sage: K.<a> = QQ['x'].quotient(x^2 + 3)
1586
+ sage: K.class_group()
1587
+ []
1588
+
1589
+ A trivial algebra over `\QQ(\sqrt{-5})` has the same class group as its
1590
+ base::
1591
+
1592
+ sage: # needs sage.rings.number_field
1593
+ sage: K.<a> = QuadraticField(-5)
1594
+ sage: R.<x> = K[]
1595
+ sage: S.<xbar> = R.quotient(x)
1596
+ sage: S.class_group()
1597
+ [((2, -a + 1), 2)]
1598
+
1599
+ The same algebra constructed in a different way::
1600
+
1601
+ sage: x = polygen(ZZ, 'x')
1602
+ sage: K.<a> = QQ['x'].quotient(x^2 + 5)
1603
+ sage: K.class_group(()) # needs sage.rings.number_field
1604
+ [((2, a + 1), 2)]
1605
+
1606
+ Here is an example where the base and the extension both contribute to
1607
+ the class group::
1608
+
1609
+ sage: # needs sage.rings.number_field
1610
+ sage: K.<a> = QuadraticField(-5)
1611
+ sage: K.class_group()
1612
+ Class group of order 2 with structure C2 of Number Field in a
1613
+ with defining polynomial x^2 + 5 with a = 2.236067977499790?*I
1614
+ sage: R.<x> = K[]
1615
+ sage: S.<xbar> = R.quotient(x^2 + 23)
1616
+ sage: S.class_group()
1617
+ [((2, a + 1, -1/2*xbar + 3/2, 1/2*a*xbar - 1/2*a + 1), 6)]
1618
+
1619
+ Here is an example of a product of number fields, both of which
1620
+ contribute to the class group::
1621
+
1622
+ sage: # needs sage.rings.number_field
1623
+ sage: R.<x> = QQ[]
1624
+ sage: S.<xbar> = R.quotient((x^2 + 23) * (x^2 + 47))
1625
+ sage: S.class_group()
1626
+ [((1/12*xbar^2 + 47/12,
1627
+ 1/48*xbar^3 - 1/48*xbar^2 + 47/48*xbar - 47/48),
1628
+ 3),
1629
+ ((-1/12*xbar^2 - 23/12,
1630
+ -1/48*xbar^3 - 1/48*xbar^2 - 23/48*xbar - 23/48),
1631
+ 5)]
1632
+
1633
+ Now we take an example over a nontrivial base with two factors, each
1634
+ contributing to the class group::
1635
+
1636
+ sage: # needs sage.rings.number_field
1637
+ sage: K.<a> = QuadraticField(-5)
1638
+ sage: R.<x> = K[]
1639
+ sage: S.<xbar> = R.quotient((x^2 + 23) * (x^2 + 31))
1640
+ sage: S.class_group() # not tested
1641
+ [((1/4*xbar^2 + 31/4,
1642
+ (-1/8*a + 1/8)*xbar^2 - 31/8*a + 31/8,
1643
+ 1/16*xbar^3 + 1/16*xbar^2 + 31/16*xbar + 31/16,
1644
+ -1/16*a*xbar^3 + (1/16*a + 1/8)*xbar^2 - 31/16*a*xbar + 31/16*a + 31/8),
1645
+ 6),
1646
+ ((-1/4*xbar^2 - 23/4,
1647
+ (1/8*a - 1/8)*xbar^2 + 23/8*a - 23/8,
1648
+ -1/16*xbar^3 - 1/16*xbar^2 - 23/16*xbar - 23/16,
1649
+ 1/16*a*xbar^3 + (-1/16*a - 1/8)*xbar^2 + 23/16*a*xbar - 23/16*a - 23/8),
1650
+ 6),
1651
+ ((-5/4*xbar^2 - 115/4,
1652
+ 1/4*a*xbar^2 + 23/4*a,
1653
+ -1/16*xbar^3 - 7/16*xbar^2 - 23/16*xbar - 161/16,
1654
+ 1/16*a*xbar^3 - 1/16*a*xbar^2 + 23/16*a*xbar - 23/16*a),
1655
+ 2)]
1656
+
1657
+ Note that all the returned values live where we expect them to::
1658
+
1659
+ sage: # needs sage.rings.number_field
1660
+ sage: CG = S.class_group()
1661
+ sage: type(CG[0][0][1])
1662
+ <class 'sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_generic_with_category.element_class'>
1663
+ sage: type(CG[0][1])
1664
+ <class 'sage.rings.integer.Integer'>
1665
+ """
1666
+ return self.S_class_group((), proof=proof)
1667
+
1668
+ def S_units(self, S, proof=True):
1669
+ """
1670
+ If ``self`` is an étale algebra `D` over a number field `K` (i.e.
1671
+ a quotient of `K[x]` by a squarefree polynomial) and `S` is a
1672
+ finite set of places of `K`, return a list of generators of
1673
+ the group of `S`-units of `D`.
1674
+
1675
+ INPUT:
1676
+
1677
+ - ``S`` -- set of primes of the base field
1678
+
1679
+ - ``proof`` -- if ``False``, assume the GRH in computing the class group
1680
+
1681
+ OUTPUT:
1682
+
1683
+ A list of generators of the `S`-unit group, in the form
1684
+ ``(gen, order)``, where ``gen`` is a unit of order ``order``.
1685
+
1686
+ EXAMPLES::
1687
+
1688
+ sage: K.<a> = QuadraticField(-3) # needs sage.rings.number_field
1689
+ sage: K.unit_group() # needs sage.rings.number_field
1690
+ Unit group with structure C6 of Number Field in a
1691
+ with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
1692
+
1693
+ sage: # needs sage.rings.number_field
1694
+ sage: x = polygen(ZZ, 'x')
1695
+ sage: K.<a> = QQ['x'].quotient(x^2 + 3)
1696
+ sage: u, o = K.S_units([])[0]; o
1697
+ 6
1698
+ sage: 2*u - 1 in {a, -a}
1699
+ True
1700
+ sage: u^6
1701
+ 1
1702
+ sage: u^3
1703
+ -1
1704
+ sage: 2*u^2 + 1 in {a, -a}
1705
+ True
1706
+
1707
+ ::
1708
+
1709
+ sage: # needs sage.rings.number_field
1710
+ sage: K.<a> = QuadraticField(-3)
1711
+ sage: y = polygen(K)
1712
+ sage: L.<b> = K['y'].quotient(y^3 + 5); L
1713
+ Univariate Quotient Polynomial Ring in b over Number Field in a
1714
+ with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
1715
+ with modulus y^3 + 5
1716
+ sage: [u for u, o in L.S_units([]) if o is Infinity]
1717
+ [(-1/3*a - 1)*b^2 - 4/3*a*b - 4/3*a + 3,
1718
+ (-1/3*a - 1)*b^2 + (2/3*a - 2)*b + 13/6*a - 1/2]
1719
+ sage: [u for u, o in L.S_units([K.ideal(1/2*a - 3/2)])
1720
+ ....: if o is Infinity]
1721
+ [(-1/6*a - 1/2)*b^2 + (1/3*a - 1)*b + 4/3*a,
1722
+ (-1/3*a - 1)*b^2 - 4/3*a*b - 4/3*a + 3,
1723
+ (-1/3*a - 1)*b^2 + (2/3*a - 2)*b + 13/6*a - 1/2]
1724
+ sage: [u for u, o in L.S_units([K.ideal(2)]) if o is Infinity]
1725
+ [(1/2*a - 1/2)*b^2 + (a + 1)*b + 3,
1726
+ (1/6*a + 1/2)*b^2 + (-1/3*a + 1)*b - 5/6*a - 1/2,
1727
+ 1/3*a*b^2 + (1/3*a + 1)*b - 1/6*a + 3/2,
1728
+ (-1/3*a - 1)*b^2 - 4/3*a*b - 4/3*a + 3,
1729
+ (-1/3*a - 1)*b^2 + (2/3*a - 2)*b + 13/6*a - 1/2]
1730
+
1731
+ Note that all the returned values live where we expect them to::
1732
+
1733
+ sage: # needs sage.rings.number_field
1734
+ sage: U = L.S_units([])
1735
+ sage: type(U[0][0])
1736
+ <class 'sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_field_with_category.element_class'>
1737
+ sage: type(U[0][1])
1738
+ <class 'sage.rings.integer.Integer'>
1739
+ sage: type(U[1][1])
1740
+ <class 'sage.rings.infinity.PlusInfinity'>
1741
+ """
1742
+ fields, isos, iso_classes = self._S_decomposition(tuple(S))
1743
+ n = len(fields)
1744
+
1745
+ component_S_units = []
1746
+ for D_iso, S_iso in iso_classes:
1747
+ # compute S-units for each distinct component
1748
+ units = D_iso.S_units(S_iso, proof=proof)
1749
+ component_S_units.append(units)
1750
+
1751
+ units = []
1752
+ moduli = [D.relative_polynomial() for D in fields]
1753
+ for i in range(n):
1754
+ phi = isos[i][0]
1755
+ back_to_rel = phi.codomain().structure()[0]
1756
+
1757
+ for unit in component_S_units[isos[i][1]]:
1758
+ mul_order = unit.multiplicative_order()
1759
+ rel_unit = back_to_rel(phi(unit))
1760
+ prod_unit = [1]*i + [rel_unit.lift()] + [1]*(n - i - 1)
1761
+ poly_unit = self(crt(prod_unit, moduli))
1762
+ units.append((poly_unit, mul_order))
1763
+
1764
+ return units
1765
+
1766
+ def units(self, proof=True):
1767
+ """
1768
+ If this quotient ring is over a number field K, by a polynomial of
1769
+ nonzero discriminant, returns a list of generators of the units.
1770
+
1771
+ INPUT:
1772
+
1773
+ - ``proof`` -- if ``False``, assume the GRH in computing the class group
1774
+
1775
+ OUTPUT:
1776
+
1777
+ A list of generators of the unit group, in the form ``(gen, order)``,
1778
+ where ``gen`` is a unit of order ``order``.
1779
+
1780
+ EXAMPLES::
1781
+
1782
+ sage: K.<a> = QuadraticField(-3) # needs sage.rings.number_field
1783
+ sage: K.unit_group() # needs sage.rings.number_field
1784
+ Unit group with structure C6 of
1785
+ Number Field in a with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
1786
+
1787
+ sage: # needs sage.rings.number_field
1788
+ sage: x = polygen(ZZ, 'x')
1789
+ sage: K.<a> = QQ['x'].quotient(x^2 + 3)
1790
+ sage: u = K.units()[0][0]
1791
+ sage: 2*u - 1 in {a, -a}
1792
+ True
1793
+ sage: u^6
1794
+ 1
1795
+ sage: u^3
1796
+ -1
1797
+ sage: 2*u^2 + 1 in {a, -a}
1798
+ True
1799
+ sage: x = polygen(ZZ, 'x')
1800
+ sage: K.<a> = QQ['x'].quotient(x^2 + 5)
1801
+ sage: K.units(())
1802
+ [(-1, 2)]
1803
+
1804
+ ::
1805
+
1806
+ sage: # needs sage.rings.number_field
1807
+ sage: K.<a> = QuadraticField(-3)
1808
+ sage: y = polygen(K)
1809
+ sage: L.<b> = K['y'].quotient(y^3 + 5); L
1810
+ Univariate Quotient Polynomial Ring in b over Number Field in a
1811
+ with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
1812
+ with modulus y^3 + 5
1813
+ sage: [u for u, o in L.units() if o is Infinity]
1814
+ [(-1/3*a - 1)*b^2 - 4/3*a*b - 4/3*a + 3,
1815
+ (-1/3*a - 1)*b^2 + (2/3*a - 2)*b + 13/6*a - 1/2]
1816
+ sage: L.<b> = K.extension(y^3 + 5)
1817
+ sage: L.unit_group()
1818
+ Unit group with structure C6 x Z x Z of
1819
+ Number Field in b with defining polynomial x^3 + 5 over its base field
1820
+ sage: L.unit_group().gens() # abstract generators
1821
+ (u0, u1, u2)
1822
+ sage: L.unit_group().gens_values()[1:]
1823
+ [(-1/3*a - 1)*b^2 - 4/3*a*b - 4/3*a + 3,
1824
+ (-1/3*a - 1)*b^2 + (2/3*a - 2)*b + 13/6*a - 1/2]
1825
+
1826
+ Note that all the returned values live where we expect them to::
1827
+
1828
+ sage: # needs sage.rings.number_field
1829
+ sage: L.<b> = K['y'].quotient(y^3 + 5)
1830
+ sage: U = L.units()
1831
+ sage: type(U[0][0])
1832
+ <class 'sage.rings.polynomial.polynomial_quotient_ring.PolynomialQuotientRing_field_with_category.element_class'>
1833
+ sage: type(U[0][1])
1834
+ <class 'sage.rings.integer.Integer'>
1835
+ sage: type(U[1][1])
1836
+ <class 'sage.rings.infinity.PlusInfinity'>
1837
+ """
1838
+ return self.S_units((), proof=proof)
1839
+
1840
+ def selmer_generators(self, S, m, proof=True):
1841
+ r"""
1842
+ If ``self`` is an étale algebra `D` over a number field `K` (i.e.
1843
+ a quotient of `K[x]` by a squarefree polynomial) and `S` is a
1844
+ finite set of places of `K`, compute the Selmer group
1845
+ `D(S,m)`. This is the subgroup of `D^*/(D^*)^m` consisting of
1846
+ elements `a` such that `D(\sqrt[m]{a})/D` is unramified at all
1847
+ primes of `D` lying above a place outside of `S`.
1848
+
1849
+ INPUT:
1850
+
1851
+ - ``S`` -- set of primes of the coefficient ring (which is a number field)
1852
+
1853
+ - ``m`` -- positive integer
1854
+
1855
+ - ``proof`` -- if ``False``, assume the GRH in computing the class group
1856
+
1857
+ OUTPUT:
1858
+
1859
+ A list of generators of `D(S,m)`.
1860
+
1861
+ EXAMPLES::
1862
+
1863
+ sage: # needs sage.rings.number_field
1864
+ sage: K.<a> = QuadraticField(-5)
1865
+ sage: R.<x> = K[]
1866
+ sage: D.<T> = R.quotient(x)
1867
+ sage: D.selmer_generators((), 2)
1868
+ [-1, 2]
1869
+ sage: D.selmer_generators([K.ideal(2, -a + 1)], 2)
1870
+ [2, -1]
1871
+ sage: D.selmer_generators([K.ideal(2, -a + 1), K.ideal(3, a + 1)], 2)
1872
+ [2, a + 1, -1]
1873
+ sage: D.selmer_generators((K.ideal(2, -a + 1), K.ideal(3, a + 1)), 4)
1874
+ [2, a + 1, -1]
1875
+ sage: D.selmer_generators([K.ideal(2, -a + 1)], 3)
1876
+ [2]
1877
+ sage: D.selmer_generators([K.ideal(2, -a + 1), K.ideal(3, a + 1)], 3)
1878
+ [2, a + 1]
1879
+ sage: D.selmer_generators([K.ideal(2, -a + 1),
1880
+ ....: K.ideal(3, a + 1),
1881
+ ....: K.ideal(a)], 3)
1882
+ [2, a + 1, a]
1883
+ """
1884
+ fields, isos, iso_classes = self._S_decomposition(tuple(S))
1885
+ n = len(fields)
1886
+
1887
+ component_selmer_groups = []
1888
+ for D_iso, S_iso in iso_classes:
1889
+ sel = D_iso.selmer_generators(S_iso, m, proof=proof)
1890
+ component_selmer_groups.append(sel)
1891
+
1892
+ gens = []
1893
+ moduli = [D.relative_polynomial() for D in fields]
1894
+ for i in range(n):
1895
+ phi = isos[i][0]
1896
+ back_to_rel = phi.codomain().structure()[0]
1897
+
1898
+ for gen in component_selmer_groups[isos[i][1]]:
1899
+ rel_gen = back_to_rel(phi(gen))
1900
+ prod_gen = [1]*i + [rel_gen.lift()] + [1]*(n - i - 1)
1901
+ poly_gen = self(crt(prod_gen, moduli))
1902
+ gens.append(poly_gen)
1903
+
1904
+ return gens
1905
+
1906
+ # For backwards compatibility:
1907
+ selmer_group = selmer_generators
1908
+
1909
+ def _factor_multivariate_polynomial(self, f, proof=True):
1910
+ r"""
1911
+ Return the factorization of ``f`` over this ring.
1912
+
1913
+ TESTS::
1914
+
1915
+ sage: # needs sage.rings.finite_rings
1916
+ sage: k.<a> = GF(4)
1917
+ sage: R.<b> = k[]
1918
+ sage: l.<b> = k.extension(b^2 + b + a)
1919
+ sage: K.<x> = FunctionField(l)
1920
+ sage: R.<t> = K[]
1921
+ sage: F = t * x
1922
+ sage: F.factor(proof=False) # needs sage.modules
1923
+ (x) * t
1924
+ """
1925
+ from sage.structure.factorization import Factorization
1926
+
1927
+ if f.is_zero():
1928
+ raise ValueError("factorization of 0 not defined")
1929
+
1930
+ from_isomorphic_ring, to_isomorphic_ring, isomorphic_ring = self._isomorphic_ring()
1931
+ g = f.map_coefficients(to_isomorphic_ring)
1932
+ F = g.factor()
1933
+ unit = f.parent(from_isomorphic_ring(F.unit().constant_coefficient()))
1934
+ return Factorization([(factor.map_coefficients(from_isomorphic_ring), e) for factor,e in F], unit=unit)
1935
+
1936
+ def _factor_univariate_polynomial(self, f):
1937
+ r"""
1938
+ Return the factorization of ``f`` over this ring.
1939
+
1940
+ TESTS::
1941
+
1942
+ sage: # needs sage.rings.finite_rings
1943
+ sage: K = GF(2)
1944
+ sage: R.<x> = K[]
1945
+ sage: L.<x> = K.extension(x^2 + x + 1)
1946
+ sage: R.<y> = L[]
1947
+ sage: M.<y> = L.extension(y^2 + y + x)
1948
+ sage: R.<T> = M[]
1949
+ sage: R(y).factor() # indirect doctest
1950
+ y
1951
+ sage: (T^2 + T + x).factor() # indirect doctest # needs sage.modules
1952
+ (T + y) * (T + y + 1)
1953
+ sage: (y*T^2 + y*T + y*x).factor() # indirect doctest # needs sage.modules
1954
+ (y) * (T + y) * (T + y + 1)
1955
+ """
1956
+ from sage.structure.factorization import Factorization
1957
+
1958
+ if f.is_zero():
1959
+ raise ValueError("factorization of 0 not defined")
1960
+
1961
+ unit = f.leading_coefficient()
1962
+ if not unit.is_unit():
1963
+ raise NotImplementedError("factorization of polynomials with non-unit leading coefficient")
1964
+ unit = f.parent()(unit)
1965
+
1966
+ f = f.monic()
1967
+ if f.degree() == 0:
1968
+ return Factorization(unit=unit)
1969
+ elif f.degree() == 1:
1970
+ return Factorization([(f,1)], unit=unit)
1971
+ else:
1972
+ from_isomorphic_ring, to_isomorphic_ring, isomorphic_ring = self._isomorphic_ring()
1973
+ g = f.map_coefficients(to_isomorphic_ring)
1974
+ F = g.factor()
1975
+ unit *= g.parent()(F.unit()).map_coefficients(from_isomorphic_ring)
1976
+ return Factorization([(factor.map_coefficients(from_isomorphic_ring), e) for factor,e in F], unit=unit)
1977
+
1978
+ @cached_method
1979
+ def _isomorphic_ring(self):
1980
+ """
1981
+ Return a ring isomorphic to this ring which is not a
1982
+ :class:`PolynomialQuotientRing` but of a type which offers more
1983
+ functionality.
1984
+
1985
+ OUTPUT:
1986
+
1987
+ a triple ``from, to, ring`` consisting of an isomorphism from the
1988
+ isomorphic ring to this ring, the inverse of that isomorphism, and the
1989
+ isomorphic ring
1990
+
1991
+ EXAMPLES::
1992
+
1993
+ sage: # needs sage.modules sage.rings.finite_rings
1994
+ sage: K.<a> = GF(4)
1995
+ sage: R.<b> = K[]
1996
+ sage: L.<b> = K.extension(b^2 + b + a); L
1997
+ Univariate Quotient Polynomial Ring in b
1998
+ over Finite Field in a of size 2^2 with modulus b^2 + b + a
1999
+ sage: from_M, to_M, M = L._isomorphic_ring(); M
2000
+ Finite Field in z4 of size 2^4
2001
+ sage: R.<c> = L[]
2002
+ sage: M.<c> = L.extension(c^2 + b*c + b); M
2003
+ Univariate Quotient Polynomial Ring in c
2004
+ over Univariate Quotient Polynomial Ring in b
2005
+ over Finite Field in a of size 2^2 with modulus b^2 + b + a
2006
+ with modulus c^2 + b*c + b
2007
+ sage: from_N, to_N, N = M._isomorphic_ring(); N
2008
+ Finite Field in z8 of size 2^8
2009
+
2010
+ sage: R.<x> = QQ[]
2011
+ sage: K = R.quo(x^2 + 1)
2012
+ sage: from_L, to_L, L = K._isomorphic_ring() # needs sage.rings.number_field
2013
+ sage: L # needs sage.rings.number_field
2014
+ Number Field in xbar with defining polynomial x^2 + 1
2015
+
2016
+ TESTS:
2017
+
2018
+ Verify that this works for trivial extensions::
2019
+
2020
+ sage: K.<a> = GF(4) # needs sage.rings.finite_rings
2021
+ sage: R.<b> = K[] # needs sage.rings.finite_rings
2022
+ sage: from_L, to_L, L = R.quo(b)._isomorphic_ring(); L # needs sage.rings.finite_rings
2023
+ Finite Field in a of size 2^2
2024
+ """
2025
+ from sage.categories.homset import Hom
2026
+ from sage.categories.morphism import SetMorphism
2027
+
2028
+ if isinstance(self.base_ring(), PolynomialQuotientRing_generic):
2029
+ # rewrite this ring over the isomorphic version of the base ring
2030
+ isomorphic_base_to_base, base_to_isomorphic_base, isomorphic_base = self.base_ring()._isomorphic_ring()
2031
+ modulus = self.modulus().map_coefficients(base_to_isomorphic_base)
2032
+ isomorphic_quotient = modulus.parent().quo(modulus)
2033
+ # we do not construct the isomorphisms yet because we want to know
2034
+ # the category that our final result lives in
2035
+
2036
+ # recursively try to rewrite the isomorphic_quotient
2037
+ isomorphic_ring_to_isomorphic_quotient, isomorphic_quotient_to_isomorphic_ring, isomorphic_ring = isomorphic_quotient._isomorphic_ring()
2038
+
2039
+ # the process has likely refined the category of
2040
+ # isomorphic_quotient (to Fields e.g.) so we use the same category
2041
+ # for self
2042
+ self._refine_category_(isomorphic_quotient.category())
2043
+
2044
+ homspace = Hom(isomorphic_quotient, self)
2045
+ from_isomorphic_quotient = homspace.__make_element_class__(SetMorphism)(homspace,
2046
+ lambda f: f.lift().map_coefficients(isomorphic_base_to_base)(self.gen()))
2047
+
2048
+ homspace = Hom(self, isomorphic_quotient)
2049
+ to_isomorphic_quotient = homspace.__make_element_class__(SetMorphism)(homspace,
2050
+ lambda f: f.lift().map_coefficients(base_to_isomorphic_base)(isomorphic_quotient.gen()))
2051
+
2052
+ return (from_isomorphic_quotient * isomorphic_ring_to_isomorphic_quotient,
2053
+ isomorphic_quotient_to_isomorphic_ring * to_isomorphic_quotient,
2054
+ isomorphic_ring)
2055
+
2056
+ if self.modulus().degree() == 1:
2057
+ # this quotient is a trivial extension of the base ring, we can just
2058
+ # return the base ring
2059
+ isomorphic_ring = self.base_ring()
2060
+
2061
+ # With this knowledge we can refine the category of self (and of the resulting morphisms.)
2062
+ # However, we cannot just refine self to
2063
+ # isomorphic_ring.category() because that category might expect an
2064
+ # interface which we cannot provide (e.g. NumberFields).
2065
+ # So we just check some important special cases here (note that
2066
+ # integral domains is already handled elsewhere.)
2067
+ from sage.categories.fields import Fields
2068
+ if isomorphic_ring in Fields():
2069
+ self._refine_category_(Fields())
2070
+
2071
+ from_isomorphic_ring = isomorphic_ring.hom(self)
2072
+
2073
+ homspace = Hom(self, isomorphic_ring)
2074
+ to_isomorphic_ring = homspace.__make_element_class__(SetMorphism)(homspace, lambda f: isomorphic_ring(f.lift()))
2075
+ return from_isomorphic_ring, to_isomorphic_ring, isomorphic_ring
2076
+
2077
+ if self.is_finite() and self.is_field():
2078
+ # for a finite field, we return the isomorphic simple extensions of
2079
+ # the underlying prime field
2080
+ N = self.cardinality()
2081
+ from sage.rings.finite_rings.finite_field_constructor import GF
2082
+ isomorphic_ring = GF(N)
2083
+
2084
+ # the map to GF(N) maps our generator to a root of our modulus in the isomorphic_ring
2085
+ base_image = self.base_ring().modulus().change_ring(isomorphic_ring).any_root()
2086
+ base_to_isomorphic_ring = self.base_ring().hom([isomorphic_ring(base_image)])
2087
+ modulus = self.modulus().map_coefficients(base_to_isomorphic_ring)
2088
+ gen = modulus.any_root(assume_squarefree=True, degree=1, assume_equal_deg=True)
2089
+
2090
+ homspace = Hom(self, isomorphic_ring)
2091
+ to_isomorphic_ring = homspace.__make_element_class__(SetMorphism)(homspace,
2092
+ lambda f: f.lift().map_coefficients(base_to_isomorphic_ring)(gen))
2093
+
2094
+ # For the map from GF(N) we need to figure out where the primitive
2095
+ # element of GF(N) goes. We write down a basis of self over GF(p),
2096
+ # send it to isomorphic_ring, and solve the linear equation which
2097
+ # writes the primitive element of GF(N) as a linear combination of
2098
+ # that basis.
2099
+ basis = [self.gen()**i*self.base_ring().gen()**j
2100
+ for i in range(self.degree())
2101
+ for j in range(self.base_ring().degree())]
2102
+ assert (len(basis) == isomorphic_ring.degree())
2103
+ from sage.matrix.constructor import matrix
2104
+ A = matrix([to_isomorphic_ring(b)._vector_() for b in basis])
2105
+ assert (A.is_square())
2106
+ # solve x*A = (0,1,0,…,0)
2107
+ x = A.solve_left(A.column_space().basis()[1])
2108
+ primitive_element = sum(c*b for c,b in zip(x.list(), basis))
2109
+ from_isomorphic_ring = isomorphic_ring.hom([primitive_element], check=False)
2110
+
2111
+ return from_isomorphic_ring, to_isomorphic_ring, isomorphic_ring
2112
+
2113
+ from sage.categories.number_fields import NumberFields
2114
+ if self.base_ring() in NumberFields():
2115
+ try:
2116
+ isomorphic_ring = self.base_ring().extension(self.modulus(), names=self.variable_names())
2117
+ except ValueError:
2118
+ pass # modulus is not irreducible
2119
+ else:
2120
+ if isomorphic_ring not in NumberFields():
2121
+ raise NotImplementedError("cannot handle extensions of number fields that do not produce number fields")
2122
+ # refine the category of self
2123
+ if not self.is_field():
2124
+ assert False, "self is isomorphic to a field"
2125
+
2126
+ from_isomorphic_ring = isomorphic_ring.hom([self.gen()])
2127
+ to_isomorphic_ring = self.hom([isomorphic_ring.gen()])
2128
+ return from_isomorphic_ring, to_isomorphic_ring, isomorphic_ring
2129
+
2130
+ raise NotImplementedError("cannot rewrite %r as an isomorphic ring" % (self,))
2131
+
2132
+ def _test_isomorphic_ring(self, **options):
2133
+ r"""
2134
+ Check that :meth:`_isomorphic_ring` works correctly.
2135
+
2136
+ TESTS::
2137
+
2138
+ sage: # needs sage.modules sage.rings.finite_rings
2139
+ sage: K.<a> = GF(4)
2140
+ sage: R.<b> = K[]
2141
+ sage: L.<b> = K.extension(b^2 + b + a)
2142
+ sage: L._test_isomorphic_ring()
2143
+ sage: R.<c> = L[]
2144
+ sage: M.<c> = L.extension(c^2 + b*c + b)
2145
+ sage: M._test_isomorphic_ring()
2146
+ """
2147
+ tester = self._tester(**options)
2148
+
2149
+ try:
2150
+ from_isomorphic_ring, to_isomorphic_ring, ring = self._isomorphic_ring()
2151
+ except NotImplementedError:
2152
+ return
2153
+
2154
+ tester.assertNotIsInstance(ring, PolynomialQuotientRing_generic)
2155
+
2156
+ from sage.categories.fields import Fields
2157
+ from sage.categories.integral_domains import IntegralDomains
2158
+ if ring.category().is_subcategory(IntegralDomains()):
2159
+ category = IntegralDomains()
2160
+ if ring.category().is_subcategory(Fields()):
2161
+ category = Fields()
2162
+ tester.assertTrue(self.category().is_subcategory(category))
2163
+ tester.assertTrue(from_isomorphic_ring.category_for().is_subcategory(category))
2164
+ tester.assertTrue(to_isomorphic_ring.category_for().is_subcategory(category))
2165
+
2166
+ for x in tester.some_elements():
2167
+ y = to_isomorphic_ring(x)
2168
+ tester.assertIn(y, ring)
2169
+ tester.assertEqual(from_isomorphic_ring(y), x)
2170
+
2171
+
2172
+ class PolynomialQuotientRing_coercion(DefaultConvertMap_unique):
2173
+ r"""
2174
+ A coercion map from a :class:`PolynomialQuotientRing` to a
2175
+ :class:`PolynomialQuotientRing` that restricts to the coercion map on the
2176
+ underlying ring of constants.
2177
+
2178
+ EXAMPLES::
2179
+
2180
+ sage: R.<x> = ZZ[]
2181
+ sage: S.<x> = QQ[]
2182
+ sage: f = S.quo(x^2 + 1).coerce_map_from(R.quo(x^2 + 1)); f
2183
+ Coercion map:
2184
+ From: Univariate Quotient Polynomial Ring in xbar over Integer Ring
2185
+ with modulus x^2 + 1
2186
+ To: Univariate Quotient Polynomial Ring in xbar over Rational Field
2187
+ with modulus x^2 + 1
2188
+
2189
+ TESTS::
2190
+
2191
+ sage: from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_coercion
2192
+ sage: isinstance(f, PolynomialQuotientRing_coercion)
2193
+ True
2194
+ sage: TestSuite(f).run(skip=['_test_pickling'])
2195
+
2196
+ Pickling works::
2197
+
2198
+ sage: g = loads(dumps(f)); g
2199
+ Coercion map:
2200
+ From: Univariate Quotient Polynomial Ring in xbar over Integer Ring with modulus x^2 + 1
2201
+ To: Univariate Quotient Polynomial Ring in xbar over Rational Field with modulus x^2 + 1
2202
+ sage: f == g
2203
+ True
2204
+ """
2205
+ def is_injective(self):
2206
+ r"""
2207
+ Return whether this coercion is injective.
2208
+
2209
+ EXAMPLES:
2210
+
2211
+ If the modulus of the domain and the codomain is the same and the
2212
+ leading coefficient is a unit in the domain, then the map is injective
2213
+ if the underlying map on the constants is::
2214
+
2215
+ sage: R.<x> = ZZ[]
2216
+ sage: S.<x> = QQ[]
2217
+ sage: f = S.quo(x^2 + 1).coerce_map_from(R.quo(x^2 + 1))
2218
+ sage: f.is_injective()
2219
+ True
2220
+ """
2221
+ if (self.domain().modulus().change_ring(self.codomain().base_ring()) == self.codomain().modulus()
2222
+ and self.domain().modulus().leading_coefficient().is_unit()):
2223
+ if self.codomain().base_ring().coerce_map_from(self.domain().base_ring()).is_injective():
2224
+ return True
2225
+ else:
2226
+ return self.domain().modulus().degree() == 0 # domain and codomain are the zero ring
2227
+ return super().is_injective()
2228
+
2229
+ def is_surjective(self):
2230
+ r"""
2231
+ Return whether this coercion is surjective.
2232
+
2233
+ EXAMPLES:
2234
+
2235
+ If the underlying map on constants is surjective, then this coercion is
2236
+ surjective since the modulus of the codomain divides the modulus of the
2237
+ domain::
2238
+
2239
+ sage: R.<x> = ZZ[]
2240
+ sage: f = R.quo(x).coerce_map_from(R.quo(x^2))
2241
+ sage: f.is_surjective()
2242
+ True
2243
+
2244
+ If the modulus of the domain and the codomain is the same, then the map
2245
+ is surjective iff the underlying map on the constants is::
2246
+
2247
+ sage: # needs sage.rings.padics
2248
+ sage: A.<a> = ZqCA(9)
2249
+ sage: R.<x> = A[]
2250
+ sage: S.<x> = A.fraction_field()[]
2251
+ sage: f = S.quo(x^2 + 2).coerce_map_from(R.quo(x^2 + 2))
2252
+ sage: f.is_surjective()
2253
+ False
2254
+ """
2255
+ constant_map_is_surjective = self.codomain().base_ring().coerce_map_from(self.domain().base_ring()).is_surjective()
2256
+ if constant_map_is_surjective:
2257
+ return True
2258
+ if self.domain().modulus().change_ring(self.codomain().base_ring()) == self.codomain().modulus():
2259
+ return constant_map_is_surjective
2260
+ return super().is_surjective()
2261
+
2262
+ def _richcmp_(self, other, op):
2263
+ r"""
2264
+ Compare this morphism to ``other``.
2265
+
2266
+ EXAMPLES::
2267
+
2268
+ sage: R.<x> = ZZ[]
2269
+ sage: S.<x> = ZZ[]
2270
+ sage: f = S.quo(x).coerce_map_from(R.quo(x^2))
2271
+ sage: g = S.quo(x).coerce_map_from(R.quo(x^3))
2272
+ sage: f == g
2273
+ False
2274
+ sage: f == f
2275
+ True
2276
+ """
2277
+ if type(self) is not type(other):
2278
+ return NotImplemented
2279
+ return richcmp(self.parent(), other.parent(), op)
2280
+
2281
+
2282
+ class PolynomialQuotientRing_domain(PolynomialQuotientRing_generic, CommutativeRing):
2283
+ """
2284
+ EXAMPLES::
2285
+
2286
+ sage: R.<x> = PolynomialRing(ZZ)
2287
+ sage: S.<xbar> = R.quotient(x^2 + 1)
2288
+ sage: S
2289
+ Univariate Quotient Polynomial Ring in xbar
2290
+ over Integer Ring with modulus x^2 + 1
2291
+ sage: loads(S.dumps()) == S
2292
+ True
2293
+ sage: loads(xbar.dumps()) == xbar
2294
+ True
2295
+ """
2296
+ def __init__(self, ring, polynomial, name=None, category=None):
2297
+ r"""
2298
+ Initialize ``self``.
2299
+
2300
+ TESTS::
2301
+
2302
+ sage: R.<x> = PolynomialRing(ZZ)
2303
+ sage: S.<xbar> = R.quotient(x^2 + 1)
2304
+ sage: TestSuite(S).run()
2305
+
2306
+ Check that :issue:`17450` is fixed::
2307
+
2308
+ sage: S in IntegralDomains()
2309
+ True
2310
+
2311
+ Check that :issue:`29017` is fixed::
2312
+
2313
+ sage: R.<x> = ZZ[]
2314
+ sage: Q = R.quo(x - 1)
2315
+ sage: H = R.Hom(Q)
2316
+ sage: h = R.hom(Q)
2317
+ sage: h.parent() is H
2318
+ True
2319
+ """
2320
+ category = CommutativeAlgebras(ring.base_ring().category()).Quotients().NoZeroDivisors().or_subcategory(category)
2321
+ PolynomialQuotientRing_generic.__init__(self, ring, polynomial, name, category)
2322
+
2323
+ def field_extension(self, names):
2324
+ r"""
2325
+ Take a polynomial quotient ring, and return a tuple with three
2326
+ elements: the :class:`NumberField` defined by the same polynomial quotient
2327
+ ring, a homomorphism from its parent to the :class:`NumberField` sending the
2328
+ generators to one another, and the inverse isomorphism.
2329
+
2330
+ OUTPUT:
2331
+
2332
+ - field
2333
+
2334
+ - homomorphism from ``self`` to field
2335
+
2336
+ - homomorphism from field to ``self``
2337
+
2338
+ EXAMPLES::
2339
+
2340
+ sage: # needs sage.rings.number_field
2341
+ sage: R.<x> = PolynomialRing(Rationals())
2342
+ sage: S.<alpha> = R.quotient(x^3 - 2)
2343
+ sage: F.<b>, f, g = S.field_extension()
2344
+ sage: F
2345
+ Number Field in b with defining polynomial x^3 - 2
2346
+ sage: a = F.gen()
2347
+ sage: f(alpha)
2348
+ b
2349
+ sage: g(a)
2350
+ alpha
2351
+
2352
+ Note that the parent ring must be an integral domain::
2353
+
2354
+ sage: R.<x> = GF(25, 'f25')['x'] # needs sage.rings.finite_rings
2355
+ sage: S.<a> = R.quo(x^3 - 2) # needs sage.rings.finite_rings
2356
+ sage: F, g, h = S.field_extension('b') # needs sage.rings.finite_rings
2357
+ Traceback (most recent call last):
2358
+ ...
2359
+ AttributeError: 'PolynomialQuotientRing_generic_with_category' object has no attribute 'field_extension'...
2360
+
2361
+ Over a finite field, the corresponding field extension is not a
2362
+ number field::
2363
+
2364
+ sage: # needs sage.modules sage.rings.finite_rings sage.rings.number_field
2365
+ sage: R.<x> = GF(25, 'a')['x']
2366
+ sage: S.<a> = R.quo(x^3 + 2*x + 1)
2367
+ sage: F, g, h = S.field_extension('b')
2368
+ sage: h(F.0^2 + 3)
2369
+ a^2 + 3
2370
+ sage: g(x^2 + 2)
2371
+ b^2 + 2
2372
+
2373
+ We do an example involving a relative number field::
2374
+
2375
+ sage: # needs sage.rings.number_field
2376
+ sage: R.<x> = QQ['x']
2377
+ sage: K.<a> = NumberField(x^3 - 2)
2378
+ sage: S.<X> = K['X']
2379
+ sage: Q.<b> = S.quo(X^3 + 2*X + 1)
2380
+ sage: Q.field_extension('b')
2381
+ (Number Field in b with defining polynomial X^3 + 2*X + 1 over its base field, ...
2382
+ Defn: b |--> b, Relative number field morphism:
2383
+ From: Number Field in b with defining polynomial X^3 + 2*X + 1 over its base field
2384
+ To: Univariate Quotient Polynomial Ring in b over Number Field in a with defining polynomial x^3 - 2 with modulus X^3 + 2*X + 1
2385
+ Defn: b |--> b
2386
+ a |--> a)
2387
+
2388
+ We slightly change the example above so it works.
2389
+
2390
+ ::
2391
+
2392
+ sage: # needs sage.rings.number_field
2393
+ sage: R.<x> = QQ['x']
2394
+ sage: K.<a> = NumberField(x^3 - 2)
2395
+ sage: S.<X> = K['X']
2396
+ sage: f = (X+a)^3 + 2*(X+a) + 1
2397
+ sage: f
2398
+ X^3 + 3*a*X^2 + (3*a^2 + 2)*X + 2*a + 3
2399
+ sage: Q.<z> = S.quo(f)
2400
+ sage: F.<w>, g, h = Q.field_extension()
2401
+ sage: c = g(z)
2402
+ sage: f(c)
2403
+ 0
2404
+ sage: h(g(z))
2405
+ z
2406
+ sage: g(h(w))
2407
+ w
2408
+
2409
+ AUTHORS:
2410
+
2411
+ - Craig Citro (2006-08-07)
2412
+
2413
+ - William Stein (2006-08-06)
2414
+ """
2415
+
2416
+ return self.gen().field_extension(names)
2417
+
2418
+
2419
+ class PolynomialQuotientRing_field(PolynomialQuotientRing_domain, Field):
2420
+ """
2421
+ EXAMPLES::
2422
+
2423
+ sage: # needs sage.rings.number_field
2424
+ sage: R.<x> = PolynomialRing(QQ)
2425
+ sage: S.<xbar> = R.quotient(x^2 + 1)
2426
+ sage: S
2427
+ Univariate Quotient Polynomial Ring in xbar over Rational Field
2428
+ with modulus x^2 + 1
2429
+ sage: loads(S.dumps()) == S
2430
+ True
2431
+ sage: loads(xbar.dumps()) == xbar
2432
+ True
2433
+ """
2434
+ def __init__(self, ring, polynomial, name=None, category=None):
2435
+ PolynomialQuotientRing_domain.__init__(self, ring, polynomial, name, category)
2436
+
2437
+ def base_field(self):
2438
+ r"""
2439
+ Alias for :meth:`base_ring`, when we're defined over a field.
2440
+ """
2441
+ return self.base_ring()
2442
+
2443
+ def complex_embeddings(self, prec=53):
2444
+ r"""
2445
+ Return all homomorphisms of this ring into the approximate complex
2446
+ field with precision ``prec``.
2447
+
2448
+ EXAMPLES::
2449
+
2450
+ sage: # needs sage.rings.number_field
2451
+ sage: R.<x> = QQ[]
2452
+ sage: f = x^5 + x + 17
2453
+ sage: k = R.quotient(f)
2454
+ sage: v = k.complex_embeddings(100)
2455
+ sage: [phi(k.0^2) for phi in v]
2456
+ [2.9757207403766761469671194565,
2457
+ -2.4088994371613850098316292196 + 1.9025410530350528612407363802*I,
2458
+ -2.4088994371613850098316292196 - 1.9025410530350528612407363802*I,
2459
+ 0.92103906697304693634806949137 - 3.0755331188457794473265418086*I,
2460
+ 0.92103906697304693634806949137 + 3.0755331188457794473265418086*I]
2461
+ """
2462
+ from sage.rings.complex_mpfr import ComplexField
2463
+ CC = ComplexField(prec)
2464
+ v = self.modulus().roots(multiplicities=False, ring=CC)
2465
+ return [self.hom([a], check=False) for a in v]