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,3550 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ # sage.doctest: needs sage.libs.pari sage.rings.number_field
3
+ """
4
+ Ideals of number fields
5
+
6
+ AUTHORS:
7
+
8
+ - Steven Sivek (2005-05-16): initial version
9
+ - William Stein (2007-09-06): vastly improved the doctesting
10
+ - William Stein and John Cremona (2007-01-28): new class
11
+ NumberFieldFractionalIdeal now used for all except the 0 ideal
12
+ - Radoslav Kirov and Alyson Deines (2010-06-22):
13
+ prime_to_S_part, is_S_unit, is_S_integral
14
+ """
15
+
16
+ # ****************************************************************************
17
+ # Copyright (C) 2004 William Stein <wstein@gmail.com>
18
+ #
19
+ # Distributed under the terms of the GNU General Public License (GPL)
20
+ #
21
+ # This code is distributed in the hope that it will be useful,
22
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24
+ # General Public License for more details.
25
+ #
26
+ # The full text of the GPL is available at:
27
+ #
28
+ # https://www.gnu.org/licenses/
29
+ # ****************************************************************************
30
+
31
+ SMALL_DISC = 1000000
32
+
33
+ import sage.misc.latex as latex
34
+
35
+ import sage.rings.rational_field as rational_field
36
+ import sage.rings.integer_ring as integer_ring
37
+ from sage.arith.misc import kronecker as kronecker_symbol
38
+ from sage.arith.misc import GCD as gcd
39
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField
40
+
41
+ from sage.rings.ideal import Ideal_generic, Ideal_fractional
42
+ from sage.misc.misc_c import prod
43
+ from sage.misc.mrange import xmrange_iter
44
+ from sage.misc.cachefunc import cached_method
45
+ from sage.structure.element import MultiplicativeGroupElement
46
+ from sage.structure.factorization import Factorization
47
+ from sage.structure.sequence import Sequence
48
+ from sage.structure.proof.proof import get_flag
49
+ from sage.structure.richcmp import richcmp
50
+
51
+ QQ = rational_field.RationalField()
52
+ ZZ = integer_ring.IntegerRing()
53
+
54
+
55
+ class NumberFieldIdeal(Ideal_generic):
56
+ """
57
+ An ideal of a number field.
58
+
59
+ EXAMPLES::
60
+
61
+ sage: x = polygen(ZZ)
62
+ sage: K.<i> = NumberField(x^2 + 1)
63
+ sage: K.ideal(7)
64
+ Fractional ideal (7)
65
+
66
+ Initialization from PARI::
67
+
68
+ sage: K.ideal(pari(7))
69
+ Fractional ideal (7)
70
+ sage: K.ideal(pari(4), pari(4 + 2*i))
71
+ Fractional ideal (2)
72
+ sage: K.ideal(pari("i + 2"))
73
+ Fractional ideal (i + 2)
74
+ sage: K.ideal(pari("[3,0;0,3]"))
75
+ Fractional ideal (3)
76
+ sage: F = pari(K).idealprimedec(5)
77
+ sage: K.ideal(F[0])
78
+ Fractional ideal (-2*i - 1)
79
+
80
+ TESTS:
81
+
82
+ Check that ``_pari_prime`` is set when initializing from a PARI
83
+ prime ideal::
84
+
85
+ sage: K.ideal(pari(K).idealprimedec(5)[0])._pari_prime
86
+ [5, [-2, 1]~, 1, 1, [2, -1; 1, 2]]
87
+
88
+ Number fields defined by non-monic and non-integral
89
+ polynomials are supported (:issue:`252`)::
90
+
91
+ sage: K.<a> = NumberField(2*x^2 - 1/3)
92
+ sage: I = K.ideal(a); I
93
+ Fractional ideal (a)
94
+ sage: I.norm()
95
+ 1/6
96
+ """
97
+ def __init__(self, field, gens, coerce=True):
98
+ """
99
+ INPUT:
100
+
101
+ - ``field`` -- a number field
102
+
103
+ - ``gens`` -- list of :class:`NumberFieldElement` objects belonging to
104
+ the field
105
+
106
+ TESTS:
107
+
108
+ We test that pickling works::
109
+
110
+ sage: x = polygen(ZZ)
111
+ sage: K.<a> = NumberField(x^2 - 5)
112
+ sage: I = K.ideal(2/(5+a))
113
+ sage: I == loads(dumps(I))
114
+ True
115
+ """
116
+ from .number_field import NumberField_generic
117
+ if not isinstance(field, NumberField_generic):
118
+ raise TypeError("field (=%s) must be a number field." % field)
119
+
120
+ if len(gens) == 1 and isinstance(gens[0], (list, tuple)):
121
+ gens = gens[0]
122
+ from cypari2.gen import Gen as pari_gen
123
+ if len(gens) == 1 and isinstance(gens[0], pari_gen):
124
+ # Init from PARI
125
+ gens = gens[0]
126
+ if gens.type() == "t_MAT":
127
+ # Assume columns are generators
128
+ gens = [field(x, check=False) for x in field.pari_zk() * gens]
129
+ elif gens.type() == "t_VEC":
130
+ # Assume prime ideal form
131
+ self._pari_prime = gens
132
+ gens = [ZZ(gens.pr_get_p()), field(gens.pr_get_gen())]
133
+ else:
134
+ # Assume one element of the field
135
+ gens = [field(gens, check=False)]
136
+ if len(gens) == 0:
137
+ raise ValueError("gens must have length at least 1 (zero ideal is not a fractional ideal)")
138
+ Ideal_generic.__init__(self, field, gens, coerce)
139
+ if field.absolute_degree() == 2:
140
+ self.quadratic_form = self._quadratic_form
141
+
142
+ def _magma_init_(self, magma):
143
+ """
144
+ Return Magma version of this ideal.
145
+
146
+ INPUT:
147
+
148
+ - ``magma`` -- a Magma interpreter
149
+
150
+ OUTPUT: :class:`MagmaElement` corresponding to this ideal
151
+
152
+ EXAMPLES::
153
+
154
+ sage: x = polygen(ZZ)
155
+ sage: K.<a> = NumberField(x^3 + 2) # optional - magma
156
+ sage: I = K.ideal(5) # optional - magma
157
+ sage: I._magma_init_(magma) # optional - magma
158
+ '(_sage_[...]![5, 0, 0]) * _sage_[...]'
159
+ """
160
+ O = magma(self.number_field().maximal_order())
161
+ g = self.gens()[0]
162
+ ans = magma(g) * O
163
+ for g in self.gens()[1:]:
164
+ ans += magma(g) * O
165
+ return '+'.join('%s * %s' % (g._magma_init_(magma), O.name())
166
+ for g in self.gens())
167
+
168
+ def __hash__(self):
169
+ """
170
+ EXAMPLES::
171
+
172
+ sage: x = polygen(ZZ)
173
+ sage: NumberField(x^2 + 1, 'a').ideal(7).__hash__() # random
174
+ 7806919040325273549
175
+ """
176
+ try:
177
+ return self._hash
178
+ except AttributeError:
179
+ # At some point in the future (e.g., for relative extensions),
180
+ # we'll likely have to consider other hashes.
181
+ self._hash = hash(self.pari_hnf())
182
+ return self._hash
183
+
184
+ def _latex_(self):
185
+ r"""
186
+ EXAMPLES::
187
+
188
+ sage: x = polygen(ZZ)
189
+ sage: K.<a> = NumberField(x^2 + 23)
190
+ sage: K.ideal([2, 1/2*a - 1/2])._latex_()
191
+ '\\left(2, \\frac{1}{2} a - \\frac{1}{2}\\right)'
192
+ sage: latex(K.ideal([2, 1/2*a - 1/2]))
193
+ \left(2, \frac{1}{2} a - \frac{1}{2}\right)
194
+
195
+ The gens are reduced only if the norm of the discriminant of
196
+ the defining polynomial is at most
197
+ sage.rings.number_field.number_field_ideal.SMALL_DISC::
198
+
199
+ sage: K.<a> = NumberField(x^2 + 902384092834); K
200
+ Number Field in a with defining polynomial x^2 + 902384092834
201
+ sage: I = K.factor(19)[0][0]; I._latex_()
202
+ '\\left(19\\right)'
203
+
204
+ We can make the generators reduced by increasing SMALL_DISC.
205
+ We had better also set proof to False, or computing reduced
206
+ gens could take too long::
207
+
208
+ sage: proof.number_field(False)
209
+ sage: sage.rings.number_field.number_field_ideal.SMALL_DISC = 10^20
210
+ sage: K.<a> = NumberField(x^4 + 3*x^2 - 17)
211
+ sage: K.ideal([17*a,17,17,17*a])._latex_()
212
+ '\\left(17\\right)'
213
+
214
+ TESTS:
215
+
216
+ Reset SMALL_DISC for continued testing::
217
+
218
+ sage: sage.rings.number_field.number_field_ideal.SMALL_DISC = 1000000
219
+ """
220
+ return '\\left(%s\\right)' % (", ".join(map(latex.latex, self._gens_repr())))
221
+
222
+ def _richcmp_(self, other, op):
223
+ """
224
+ Compare an ideal of a number field to something else.
225
+
226
+ REMARK:
227
+
228
+ By default, comparing ideals is the same as comparing
229
+ their generator list. But of course, different generators
230
+ can give rise to the same ideal. And this can easily
231
+ be detected using Hermite normal form.
232
+
233
+ As an implementation detail (this may change in the future),
234
+ the Hermite normal form is with respect to the integral basis
235
+ computed by Pari, and this may be different across different
236
+ runs and operating systems.
237
+
238
+ EXAMPLES::
239
+
240
+ sage: x = polygen(ZZ)
241
+ sage: K.<a> = NumberField(x^2 + 3); K
242
+ Number Field in a with defining polynomial x^2 + 3
243
+ sage: f = K.factor(15); f
244
+ (Fractional ideal (-a))^2 * (Fractional ideal (5))
245
+ sage: (f[0][0] < f[1][0]) # potentially random
246
+ True
247
+ sage: (f[0][0] == f[0][0])
248
+ True
249
+ sage: (f[1][0] > f[0][0])
250
+ True
251
+ sage: f[1][0] == 5
252
+ True
253
+ sage: f[1][0] == GF(7)(5)
254
+ False
255
+
256
+ TESTS::
257
+
258
+ sage: L.<b> = NumberField(x^8-x^4+1)
259
+ sage: F_2 = L.fractional_ideal(b^2-1)
260
+ sage: F_4 = L.fractional_ideal(b^4-1)
261
+ sage: F_2 == F_4
262
+ True
263
+ """
264
+ if not isinstance(other, NumberFieldIdeal):
265
+ return NotImplemented
266
+ return richcmp(self.pari_hnf().sage(), other.pari_hnf().sage(), op)
267
+
268
+ def _mul_(self, other):
269
+ """
270
+ Return the product of ``self`` and ``other``.
271
+
272
+ This is implemented by just calling PARI to do the multiplication.
273
+
274
+ EXAMPLES::
275
+
276
+ sage: # needs sage.symbolic
277
+ sage: K.<I>=QQ[i]
278
+ sage: A = K.ideal([5, 2 + I])
279
+ sage: B = K.ideal([13, 5 + 12*I])
280
+ sage: A*B
281
+ Fractional ideal (-4*I + 7)
282
+ sage: (K.ideal(3 + I) * K.ideal(7 + I)).gens()
283
+ (10*I + 20,)
284
+
285
+ TESTS:
286
+
287
+ Make sure that :issue:`13958` is fixed::
288
+
289
+ sage: I = QuadraticField(-5).ideal(2).factor()[0][0]
290
+ sage: I = I * I * I; I.ngens() == 2
291
+ True
292
+ sage: I = I^301; I.ngens() == 2
293
+ True
294
+ """
295
+ if self.ngens() == 1 and other.ngens() == 1:
296
+ return self.ring().ideal(self.gen(0) * other.gen(0))
297
+
298
+ K = self.ring()
299
+ K_pari = K.pari_nf()
300
+ return K.ideal(K_pari.idealmul(self, other))
301
+
302
+ def coordinates(self, x):
303
+ r"""
304
+ Return the coordinate vector of `x` with respect to this ideal.
305
+
306
+ INPUT:
307
+
308
+ - ``x`` -- an element of the number field (or ring of integers) of this
309
+ ideal
310
+
311
+ OUTPUT:
312
+
313
+ List giving the coordinates of `x` with respect to the integral basis
314
+ of the ideal. In general this will be a vector of
315
+ rationals; it will consist of integers if and only if `x`
316
+ is in the ideal.
317
+
318
+ AUTHOR: John Cremona 2008-10-31
319
+
320
+ ALGORITHM:
321
+
322
+ Uses linear algebra.
323
+ Provides simpler implementations for :meth:`_contains_`,
324
+ :meth:`is_integral` and :meth:`smallest_integer`.
325
+
326
+ EXAMPLES::
327
+
328
+ sage: K.<i> = QuadraticField(-1)
329
+ sage: I = K.ideal(7 + 3*i)
330
+ sage: Ibasis = I.integral_basis(); Ibasis
331
+ [58, i + 41]
332
+ sage: a = 23 - 14*i
333
+ sage: acoords = I.coordinates(a); acoords
334
+ (597/58, -14)
335
+ sage: sum([Ibasis[j]*acoords[j] for j in range(2)]) == a
336
+ True
337
+ sage: b = 123 + 456*i
338
+ sage: bcoords = I.coordinates(b); bcoords
339
+ (-18573/58, 456)
340
+ sage: sum([Ibasis[j]*bcoords[j] for j in range(2)]) == b
341
+ True
342
+ sage: J = K.ideal(0)
343
+ sage: J.coordinates(0)
344
+ ()
345
+ sage: J.coordinates(1)
346
+ Traceback (most recent call last):
347
+ ...
348
+ TypeError: vector is not in free module
349
+ """
350
+ K = self.number_field()
351
+ V, from_V, to_V = K.absolute_vector_space()
352
+ try:
353
+ return self.free_module().coordinate_vector(to_V(K(x)))
354
+ except ArithmeticError as e:
355
+ raise TypeError(e)
356
+
357
+ def _contains_(self, x):
358
+ """
359
+ Return ``True`` if `x` is an element of this ideal.
360
+
361
+ This function is called (indirectly) when the ``in`` operator is used.
362
+
363
+ EXAMPLES::
364
+
365
+ sage: x = polygen(ZZ)
366
+ sage: K.<a> = NumberField(x^2 + 23); K
367
+ Number Field in a with defining polynomial x^2 + 23
368
+ sage: I = K.factor(13)[0][0]; I
369
+ Fractional ideal (13, 1/2*a + 9/2)
370
+ sage: I._contains_(a)
371
+ False
372
+ sage: a in I
373
+ False
374
+ sage: 13 in I
375
+ True
376
+ sage: 13/2 in I
377
+ False
378
+ sage: a + 9 in I
379
+ True
380
+ sage: J = K.ideal(0)
381
+ sage: 0 in J
382
+ True
383
+ sage: 1 in J
384
+ False
385
+
386
+ sage: K.<a> = NumberField(x^4 + 3); K
387
+ Number Field in a with defining polynomial x^4 + 3
388
+ sage: I = K.factor(13)[0][0]
389
+ sage: I # random sign in output
390
+ Fractional ideal (-2*a^2 - 1)
391
+ sage: 2/3 in I
392
+ False
393
+ sage: 1 in I
394
+ False
395
+ sage: 13 in I
396
+ True
397
+ sage: 1 in I*I^(-1)
398
+ True
399
+ sage: I # random sign in output
400
+ Fractional ideal (-2*a^2 - 1)
401
+
402
+ sage: K.<y>=NumberField(x^2-3)
403
+ sage: L.<z>=K.extension(x^2-5)
404
+ sage: 0 in L.ideal(0)
405
+ True
406
+ sage: 1 in L.ideal(0)
407
+ False
408
+ """
409
+ return self.coordinates(x).denominator() == 1
410
+
411
+ def __elements_from_hnf(self, hnf):
412
+ """
413
+ Convert a PARI Hermite normal form matrix to a list of
414
+ NumberFieldElements.
415
+
416
+ EXAMPLES::
417
+
418
+ sage: x = polygen(ZZ)
419
+ sage: K.<a> = NumberField(x^3 + 389); K
420
+ Number Field in a with defining polynomial x^3 + 389
421
+ sage: I = K.factor(17)[0][0]
422
+ sage: I # random sign in generator
423
+ Fractional ideal (-100*a^2 + 730*a - 5329)
424
+ sage: hnf = I.pari_hnf(); hnf
425
+ [17, 0, 13; 0, 17, 8; 0, 0, 1]
426
+ sage: I._NumberFieldIdeal__elements_from_hnf(hnf)
427
+ [17, 17*a, a^2 + 8*a + 13]
428
+ sage: I._NumberFieldIdeal__elements_from_hnf(hnf^(-1))
429
+ [1/17, 1/17*a, a^2 - 8/17*a - 13/17]
430
+ """
431
+ K = self.number_field()
432
+ return [K(x, check=False) for x in K.pari_zk() * hnf]
433
+
434
+ def _repr_(self):
435
+ """
436
+ Return the string representation of this number field ideal.
437
+
438
+ .. NOTE::
439
+
440
+ Only the zero ideal actually has type NumberFieldIdeal; all
441
+ others have type NumberFieldFractionalIdeal. So this function
442
+ will only ever be called on the zero ideal.
443
+
444
+ EXAMPLES::
445
+
446
+ sage: x = polygen(ZZ)
447
+ sage: K.<a> = NumberField(x^3 - 2)
448
+ sage: I = K.ideal(0); I
449
+ Ideal (0) of Number Field in a with defining polynomial x^3 - 2
450
+ sage: type(I)
451
+ <class 'sage.rings.number_field.number_field_ideal.NumberFieldIdeal'>
452
+ sage: I = K.ideal(1); I
453
+ Fractional ideal (1)
454
+ sage: type(I)
455
+ <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
456
+ sage: I = K.ideal(a); I
457
+ Fractional ideal (a)
458
+ sage: type(I)
459
+ <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
460
+ sage: I = K.ideal(1/a); I
461
+ Fractional ideal (1/2*a^2)
462
+ sage: type(I)
463
+ <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
464
+ """
465
+ return "Ideal %s of %s" % (self._repr_short(), self.number_field())
466
+
467
+ def _repr_short(self):
468
+ """
469
+ Compact string representation of this ideal. When the norm of
470
+ the discriminant of the defining polynomial of the number field
471
+ is less than
472
+
473
+ sage.rings.number_field.number_field_ideal.SMALL_DISC
474
+
475
+ then display reduced generators. Otherwise display two
476
+ generators.
477
+
478
+ EXAMPLES::
479
+
480
+ sage: x = polygen(ZZ)
481
+ sage: K.<a> = NumberField(x^4 + 389); K
482
+ Number Field in a with defining polynomial x^4 + 389
483
+ sage: I = K.factor(17)[0][0]; I
484
+ Fractional ideal (17, a^2 + 6)
485
+ sage: I._repr_short()
486
+ '(17, a^2 + 6)'
487
+
488
+ We use reduced gens, because the discriminant is small::
489
+
490
+ sage: K.<a> = NumberField(x^2 + 17); K
491
+ Number Field in a with defining polynomial x^2 + 17
492
+ sage: I = K.factor(17)[0][0]; I
493
+ Fractional ideal (a)
494
+
495
+ Here the discriminant is 'large', so the gens aren't reduced::
496
+
497
+ sage: sage.rings.number_field.number_field_ideal.SMALL_DISC
498
+ 1000000
499
+ sage: K.<a> = NumberField(x^2 + 902384094); K
500
+ Number Field in a with defining polynomial x^2 + 902384094
501
+ sage: I = K.factor(19)[0][0]; I
502
+ Fractional ideal (19, a + 5)
503
+ sage: I.gens_reduced()
504
+ (19, a + 5)
505
+ """
506
+ return '(%s)' % (', '.join(map(str, self._gens_repr())))
507
+
508
+ def _gens_repr(self):
509
+ """
510
+ Return tuple of generators to be used for printing this number
511
+ field ideal. The gens are reduced only if the absolute value of
512
+ the norm of the discriminant of the defining polynomial is at
513
+ most sage.rings.number_field.number_field_ideal.SMALL_DISC.
514
+
515
+ EXAMPLES::
516
+
517
+ sage: x = polygen(ZZ)
518
+ sage: sage.rings.number_field.number_field_ideal.SMALL_DISC
519
+ 1000000
520
+ sage: K.<a> = NumberField(x^4 + 3*x^2 - 17)
521
+ sage: K.discriminant() # too big
522
+ -1612688
523
+ sage: I = K.ideal([17*a*(2*a-2),17*a*(2*a-3)]); I._gens_repr()
524
+ (289, 17*a)
525
+ sage: I.gens_reduced()
526
+ (17*a,)
527
+ """
528
+ # If the discriminant is small, it is easy to find nice gens.
529
+ # Otherwise it is potentially very hard.
530
+ try:
531
+ if abs(self.number_field().defining_polynomial().discriminant().norm()) <= SMALL_DISC:
532
+ return self.gens_reduced()
533
+ except TypeError:
534
+ # In some cases with relative extensions, computing the
535
+ # discriminant of the defining polynomial is not
536
+ # supported.
537
+ pass
538
+ # Return two generators unless the second one is zero
539
+ two_gens = self.gens_two()
540
+ if two_gens[1]:
541
+ return two_gens
542
+ else:
543
+ return (two_gens[0],)
544
+
545
+ def __pari__(self):
546
+ """
547
+ Return PARI Hermite Normal Form representations of this
548
+ ideal.
549
+
550
+ EXAMPLES::
551
+
552
+ sage: x = polygen(ZZ)
553
+ sage: K.<w> = NumberField(x^2 + 23)
554
+ sage: I = K.class_group().0.ideal(); I
555
+ Fractional ideal (2, 1/2*w - 1/2)
556
+ sage: I.__pari__()
557
+ [2, 0; 0, 1]
558
+ """
559
+ return self.pari_hnf()
560
+
561
+ def _pari_init_(self):
562
+ """
563
+ Return ``self`` in PARI Hermite Normal Form as a string.
564
+
565
+ EXAMPLES::
566
+
567
+ sage: x = polygen(ZZ)
568
+ sage: K.<w> = NumberField(x^2 + 23)
569
+ sage: I = K.class_group().0.ideal()
570
+ sage: I._pari_init_()
571
+ '[2, 0; 0, 1]'
572
+ """
573
+ return str(self.__pari__())
574
+
575
+ def pari_hnf(self):
576
+ """
577
+ Return PARI's representation of this ideal in Hermite normal form.
578
+
579
+ EXAMPLES::
580
+
581
+ sage: x = polygen(ZZ)
582
+ sage: R.<x> = PolynomialRing(QQ)
583
+ sage: K.<a> = NumberField(x^3 - 2)
584
+ sage: I = K.ideal(2/(5+a))
585
+ sage: I.pari_hnf()
586
+ [2, 0, 50/127; 0, 2, 244/127; 0, 0, 2/127]
587
+ """
588
+ try:
589
+ return self.__pari_hnf
590
+ except AttributeError:
591
+ nf = self.number_field().pari_nf()
592
+ self.__pari_hnf = nf.idealhnf(0)
593
+ hnflist = [ nf.idealhnf(x) for x in self.gens() ]
594
+ for ideal in hnflist:
595
+ self.__pari_hnf = nf.idealadd(self.__pari_hnf, ideal)
596
+ return self.__pari_hnf
597
+
598
+ @cached_method
599
+ def basis(self):
600
+ r"""
601
+ Return a basis for this ideal viewed as a `\ZZ`-module.
602
+
603
+ OUTPUT:
604
+
605
+ An immutable sequence of elements of this ideal (note: their
606
+ parent is the number field) forming a basis for this ideal.
607
+
608
+ EXAMPLES::
609
+
610
+ sage: K.<z> = CyclotomicField(7)
611
+ sage: I = K.factor(11)[0][0]
612
+ sage: I.basis() # warning -- choice of basis can be somewhat random
613
+ [11, 11*z, 11*z^2, z^3 + 5*z^2 + 4*z + 10,
614
+ z^4 + z^2 + z + 5, z^5 + z^4 + z^3 + 2*z^2 + 6*z + 5]
615
+
616
+ An example of a non-integral ideal.::
617
+
618
+ sage: J = 1/I
619
+ sage: J # warning -- choice of generators can be somewhat random
620
+ Fractional ideal (2/11*z^5 + 2/11*z^4 + 3/11*z^3 + 2/11)
621
+ sage: J.basis() # warning -- choice of basis can be somewhat random
622
+ [1, z, z^2, 1/11*z^3 + 7/11*z^2 + 6/11*z + 10/11,
623
+ 1/11*z^4 + 1/11*z^2 + 1/11*z + 7/11,
624
+ 1/11*z^5 + 1/11*z^4 + 1/11*z^3 + 2/11*z^2 + 8/11*z + 7/11]
625
+
626
+ Number fields defined by non-monic and non-integral
627
+ polynomials are supported (:issue:`252`)::
628
+
629
+ sage: x = polygen(ZZ)
630
+ sage: K.<a> = NumberField(2*x^2 - 1/3)
631
+ sage: K.ideal(a).basis()
632
+ [1, a]
633
+ """
634
+ hnf = self.pari_hnf()
635
+ v = self.__elements_from_hnf(hnf)
636
+ return Sequence(v, immutable=True)
637
+
638
+ @cached_method
639
+ def free_module(self):
640
+ r"""
641
+ Return the free `\ZZ`-module contained in the vector space
642
+ associated to the ambient number field, that corresponds
643
+ to this ideal.
644
+
645
+ EXAMPLES::
646
+
647
+ sage: K.<z> = CyclotomicField(7)
648
+ sage: I = K.factor(11)[0][0]; I
649
+ Fractional ideal (-3*z^4 - 2*z^3 - 2*z^2 - 2)
650
+ sage: A = I.free_module()
651
+ sage: A # warning -- choice of basis can be somewhat random
652
+ Free module of degree 6 and rank 6 over Integer Ring
653
+ User basis matrix:
654
+ [11 0 0 0 0 0]
655
+ [ 0 11 0 0 0 0]
656
+ [ 0 0 11 0 0 0]
657
+ [10 4 5 1 0 0]
658
+ [ 5 1 1 0 1 0]
659
+ [ 5 6 2 1 1 1]
660
+
661
+ However, the actual `\ZZ`-module is not at all random::
662
+
663
+ sage: A.basis_matrix().change_ring(ZZ).echelon_form()
664
+ [ 1 0 0 5 1 1]
665
+ [ 0 1 0 1 1 7]
666
+ [ 0 0 1 7 6 10]
667
+ [ 0 0 0 11 0 0]
668
+ [ 0 0 0 0 11 0]
669
+ [ 0 0 0 0 0 11]
670
+
671
+ The ideal doesn't have to be integral::
672
+
673
+ sage: J = I^(-1)
674
+ sage: B = J.free_module()
675
+ sage: B.echelonized_basis_matrix()
676
+ [ 1/11 0 0 7/11 1/11 1/11]
677
+ [ 0 1/11 0 1/11 1/11 5/11]
678
+ [ 0 0 1/11 5/11 4/11 10/11]
679
+ [ 0 0 0 1 0 0]
680
+ [ 0 0 0 0 1 0]
681
+ [ 0 0 0 0 0 1]
682
+
683
+ This also works for relative extensions::
684
+
685
+ sage: x = polygen(ZZ)
686
+ sage: K.<a,b> = NumberField([x^2 + 1, x^2 + 2])
687
+ sage: I = K.fractional_ideal(4)
688
+ sage: I.free_module()
689
+ Free module of degree 4 and rank 4 over Integer Ring
690
+ User basis matrix:
691
+ [ 4 0 0 0]
692
+ [ 3 7 1 1]
693
+ [ 0 10 0 2]
694
+ [ 3 -7 1 -1]
695
+ sage: J = I^(-1); J.free_module()
696
+ Free module of degree 4 and rank 4 over Integer Ring
697
+ User basis matrix:
698
+ [ 1/4 0 0 0]
699
+ [ 3/16 7/16 1/16 1/16]
700
+ [ 0 5/8 0 1/8]
701
+ [ 3/16 -7/16 1/16 -1/16]
702
+
703
+ An example of intersecting ideals by intersecting free modules.::
704
+
705
+ sage: K.<a> = NumberField(x^3 + x^2 - 2*x + 8)
706
+ sage: I = K.factor(2)
707
+ sage: p1 = I[0][0]; p2 = I[1][0]
708
+ sage: N = p1.free_module().intersection(p2.free_module()); N
709
+ Free module of degree 3 and rank 3 over Integer Ring
710
+ Echelon basis matrix:
711
+ [ 1 1/2 1/2]
712
+ [ 0 1 1]
713
+ [ 0 0 2]
714
+ sage: N.index_in(p1.free_module()).abs()
715
+ 2
716
+
717
+ TESTS:
718
+
719
+ Sage can find the free module associated to quite large ideals
720
+ quickly (see :issue:`4627`)::
721
+
722
+ sage: y = polygen(ZZ)
723
+ sage: M.<a> = NumberField(y^20 - 2*y^19 + 10*y^17 - 15*y^16 + 40*y^14 - 64*y^13 + 46*y^12 + 8*y^11 - 32*y^10 + 8*y^9 + 46*y^8 - 64*y^7 + 40*y^6 - 15*y^4 + 10*y^3 - 2*y + 1)
724
+ sage: M.ideal(prod(prime_range(6000, 6200))).free_module()
725
+ Free module of degree 20 and rank 20 over Integer Ring
726
+ User basis matrix:
727
+ 20 x 20 dense matrix over Rational Field
728
+ """
729
+ return basis_to_module(self.basis(), self.number_field())
730
+
731
+ def reduce_equiv(self):
732
+ """
733
+ Return a small ideal that is equivalent to ``self`` in the group
734
+ of fractional ideals modulo principal ideals. Very often (but
735
+ not always) if ``self`` is principal then this function returns
736
+ the unit ideal.
737
+
738
+ ALGORITHM: Calls :pari:`idealred` function.
739
+
740
+ EXAMPLES::
741
+
742
+ sage: x = polygen(ZZ)
743
+ sage: K.<w> = NumberField(x^2 + 23)
744
+ sage: I = ideal(w*23^5); I
745
+ Fractional ideal (6436343*w)
746
+ sage: I.reduce_equiv()
747
+ Fractional ideal (1)
748
+ sage: I = K.class_group().0.ideal()^10; I
749
+ Fractional ideal (1024, 1/2*w + 979/2)
750
+ sage: I.reduce_equiv()
751
+ Fractional ideal (2, 1/2*w - 1/2)
752
+ """
753
+ K = self.number_field()
754
+ P = K.pari_nf()
755
+ hnf = P.idealred(self.pari_hnf())
756
+ gens = self.__elements_from_hnf(hnf)
757
+ return K.ideal(gens)
758
+
759
+ def gens_reduced(self, proof=None):
760
+ r"""
761
+ Express this ideal in terms of at most two generators, and one
762
+ if possible.
763
+
764
+ This function indirectly uses :pari:`bnfisprincipal`, so set
765
+ ``proof=True`` if you want to prove correctness (which *is* the
766
+ default).
767
+
768
+ EXAMPLES::
769
+
770
+ sage: x = polygen(ZZ)
771
+ sage: R.<x> = PolynomialRing(QQ)
772
+ sage: K.<a> = NumberField(x^2 + 5)
773
+ sage: K.ideal(0).gens_reduced()
774
+ (0,)
775
+ sage: J = K.ideal([a + 2, 9])
776
+ sage: J.gens()
777
+ (a + 2, 9)
778
+ sage: J.gens_reduced() # random sign
779
+ (a + 2,)
780
+ sage: K.ideal([a + 2, 3]).gens_reduced()
781
+ (3, a + 2)
782
+
783
+ TESTS::
784
+
785
+ sage: len(J.gens_reduced()) == 1
786
+ True
787
+
788
+ sage: all(j.parent() is K for j in J.gens())
789
+ True
790
+ sage: all(j.parent() is K for j in J.gens_reduced())
791
+ True
792
+
793
+ sage: K.<a> = NumberField(x^4 + 10*x^2 + 20)
794
+ sage: J = K.prime_above(5)
795
+ sage: J.is_principal()
796
+ False
797
+ sage: J.gens_reduced()
798
+ (5, -a)
799
+ sage: all(j.parent() is K for j in J.gens())
800
+ True
801
+ sage: all(j.parent() is K for j in J.gens_reduced())
802
+ True
803
+
804
+ Make sure this works with large ideals (:issue:`11836`)::
805
+
806
+ sage: R.<x> = QQ['x']
807
+ sage: L.<b> = NumberField(x^10 - 10*x^8 - 20*x^7 + 165*x^6 - 12*x^5 - 760*x^3 + 2220*x^2 + 5280*x + 7744)
808
+ sage: z_x = -96698852571685/2145672615243325696*b^9 + 2472249905907/195061146840302336*b^8 + 916693155514421/2145672615243325696*b^7 + 1348520950997779/2145672615243325696*b^6 - 82344497086595/12191321677518896*b^5 + 2627122040194919/536418153810831424*b^4 - 452199105143745/48765286710075584*b^3 + 4317002771457621/536418153810831424*b^2 + 2050725777454935/67052269226353928*b + 3711967683469209/3047830419379724
809
+
810
+ sage: # needs database_cremona_mini_ellcurve sage.schemes
811
+ sage: P = EllipticCurve(L, '57a1').lift_x(z_x) * 3
812
+ sage: ideal = L.fractional_ideal(P[0], P[1])
813
+ sage: ideal.is_principal(proof=False)
814
+ True
815
+ sage: len(ideal.gens_reduced(proof=False))
816
+ 1
817
+ """
818
+ if len(self.gens()) <= 1:
819
+ self._is_principal = True
820
+ self._reduced_generators = self.gens()
821
+ return self._reduced_generators
822
+ self._cache_bnfisprincipal(proof=proof, gens=True)
823
+ return self._reduced_generators
824
+
825
+ def gens_two(self) -> tuple:
826
+ r"""
827
+ Express this ideal using exactly two generators, the first of
828
+ which is a generator for the intersection of the ideal with `\QQ`.
829
+
830
+ ALGORITHM: uses PARI's :pari:`idealtwoelt` function, which runs in
831
+ randomized polynomial time and is very fast in practice.
832
+
833
+ EXAMPLES::
834
+
835
+ sage: x = polygen(ZZ)
836
+ sage: R.<x> = PolynomialRing(QQ)
837
+ sage: K.<a> = NumberField(x^2 + 5)
838
+ sage: J = K.ideal([a + 2, 9])
839
+ sage: J.gens()
840
+ (a + 2, 9)
841
+ sage: J.gens_two()
842
+ (9, a + 2)
843
+ sage: K.ideal([a + 5, a + 8]).gens_two()
844
+ (3, a + 2)
845
+ sage: K.ideal(0).gens_two()
846
+ (0, 0)
847
+
848
+ The second generator is zero if and only if the ideal is
849
+ generated by a rational, in contrast to the PARI function
850
+ :pari:`idealtwoelt`::
851
+
852
+ sage: I = K.ideal(12)
853
+ sage: pari(K).idealtwoelt(I) # Note that second element is not zero
854
+ [12, [0, 12]~]
855
+ sage: I.gens_two()
856
+ (12, 0)
857
+ """
858
+ try:
859
+ return self.__two_generators
860
+ except AttributeError:
861
+ pass
862
+
863
+ K = self.number_field()
864
+
865
+ if self.is_zero():
866
+ self.__two_generators = (K.zero(), K.zero())
867
+ else:
868
+ HNF = self.pari_hnf()
869
+ # Check whether the ideal is generated by an integer, i.e.
870
+ # whether HNF is a multiple of the identity matrix
871
+ if HNF.gequal(HNF[0, 0]):
872
+ a = HNF[0, 0]
873
+ alpha = 0
874
+ else:
875
+ a, alpha = K.pari_nf().idealtwoelt(HNF)
876
+ self.__two_generators = (K(a), K(alpha))
877
+
878
+ return self.__two_generators
879
+
880
+ def integral_basis(self):
881
+ r"""
882
+ Return a list of generators for this ideal as a `\ZZ`-module.
883
+
884
+ EXAMPLES::
885
+
886
+ sage: x = polygen(ZZ)
887
+ sage: R.<x> = PolynomialRing(QQ)
888
+ sage: K.<i> = NumberField(x^2 + 1)
889
+ sage: J = K.ideal(i + 1)
890
+ sage: J.integral_basis()
891
+ [2, i + 1]
892
+ """
893
+ hnf = self.pari_hnf()
894
+ return self.__elements_from_hnf(hnf)
895
+
896
+ def integral_split(self):
897
+ r"""
898
+ Return a tuple `(I, d)`, where `I` is an integral ideal, and `d` is the
899
+ smallest positive integer such that this ideal is equal to `I/d`.
900
+
901
+ EXAMPLES::
902
+
903
+ sage: x = polygen(ZZ)
904
+ sage: R.<x> = PolynomialRing(QQ)
905
+ sage: K.<a> = NumberField(x^2 - 5)
906
+ sage: I = K.ideal(2/(5+a))
907
+ sage: I.is_integral()
908
+ False
909
+ sage: J, d = I.integral_split()
910
+ sage: J
911
+ Fractional ideal (-1/2*a + 5/2)
912
+ sage: J.is_integral()
913
+ True
914
+ sage: d
915
+ 5
916
+ sage: I == J/d
917
+ True
918
+ """
919
+ try:
920
+ return self.__integral_split
921
+ except AttributeError:
922
+ if self.is_integral():
923
+ self.__integral_split = (self, ZZ(1))
924
+ else:
925
+ factors = self.factor()
926
+ denom_list = [p_e for p_e in factors if p_e[1] < 0]
927
+ denominator = prod([ p.smallest_integer()**(-e)
928
+ for (p,e) in denom_list ])
929
+ ## Get a list of the primes dividing the denominator
930
+ plist = [ p.smallest_integer() for (p,e) in denom_list ]
931
+ for p in plist:
932
+ while denominator % p == 0 and (self*(denominator/p)).is_integral():
933
+ denominator //= p
934
+ self.__integral_split = (self*denominator, denominator)
935
+ return self.__integral_split
936
+
937
+ def intersection(self, other):
938
+ r"""
939
+ Return the intersection of ``self`` and ``other``.
940
+
941
+ EXAMPLES::
942
+
943
+ sage: K.<a> = QuadraticField(-11)
944
+ sage: p = K.ideal((a + 1)/2); q = K.ideal((a + 3)/2)
945
+ sage: p.intersection(q) == q.intersection(p) == K.ideal(a - 2)
946
+ True
947
+
948
+ An example with non-principal ideals::
949
+
950
+ sage: x = polygen(ZZ)
951
+ sage: L.<a> = NumberField(x^3 - 7)
952
+ sage: p = L.ideal(a^2 + a + 1, 2)
953
+ sage: q = L.ideal(a + 1)
954
+ sage: p.intersection(q) == L.ideal(8, 2*a + 2)
955
+ True
956
+
957
+ A relative example::
958
+
959
+ sage: L.<a,b> = NumberField([x^2 + 11, x^2 - 5])
960
+ sage: A = L.ideal([15, (-3/2*b + 7/2)*a - 8])
961
+ sage: B = L.ideal([6, (-1/2*b + 1)*a - b - 5/2])
962
+ sage: A.intersection(B) == L.ideal(-1/2*a - 3/2*b - 1)
963
+ True
964
+
965
+ TESTS:
966
+
967
+ Test that this works with non-integral ideals (:issue:`10767`)::
968
+
969
+ sage: K = QuadraticField(-2)
970
+ sage: I = K.ideal(1/2)
971
+ sage: I.intersection(I)
972
+ Fractional ideal (1/2)
973
+ """
974
+ L = self.number_field()
975
+ other = L.ideal(other)
976
+ nf = L.pari_nf()
977
+ hnf = nf.idealintersect(self.pari_hnf(), other.pari_hnf())
978
+ I = L.ideal(self._NumberFieldIdeal__elements_from_hnf(hnf))
979
+ I.__pari_hnf = hnf
980
+ return I
981
+
982
+ def is_integral(self):
983
+ """
984
+ Return ``True`` if this ideal is integral.
985
+
986
+ EXAMPLES::
987
+
988
+ sage: R.<x> = PolynomialRing(QQ)
989
+ sage: K.<a> = NumberField(x^5 - x + 1)
990
+ sage: K.ideal(a).is_integral()
991
+ True
992
+ sage: (K.ideal(1) / (3*a+1)).is_integral()
993
+ False
994
+ """
995
+ try:
996
+ return self.__is_integral
997
+ except AttributeError:
998
+ one = self.number_field().ideal(1)
999
+ self.__is_integral = all(a in one for a in self.integral_basis())
1000
+ return self.__is_integral
1001
+
1002
+ def is_maximal(self):
1003
+ """
1004
+ Return ``True`` if this ideal is maximal. This is equivalent to
1005
+ ``self`` being prime and nonzero.
1006
+
1007
+ EXAMPLES::
1008
+
1009
+ sage: x = polygen(ZZ)
1010
+ sage: K.<a> = NumberField(x^3 + 3); K
1011
+ Number Field in a with defining polynomial x^3 + 3
1012
+ sage: K.ideal(5).is_maximal()
1013
+ False
1014
+ sage: K.ideal(7).is_maximal()
1015
+ True
1016
+ """
1017
+ return self.is_prime() and not self.is_zero()
1018
+
1019
+ def is_prime(self):
1020
+ """
1021
+ Return ``True`` if this ideal is prime.
1022
+
1023
+ EXAMPLES::
1024
+
1025
+ sage: x = polygen(ZZ)
1026
+ sage: K.<a> = NumberField(x^2 - 17); K
1027
+ Number Field in a with defining polynomial x^2 - 17
1028
+ sage: K.ideal(5).is_prime() # inert prime
1029
+ True
1030
+ sage: K.ideal(13).is_prime() # split
1031
+ False
1032
+ sage: K.ideal(17).is_prime() # ramified
1033
+ False
1034
+
1035
+ TESTS:
1036
+
1037
+ Check that we do not factor the norm of the ideal, this used
1038
+ to take half an hour, see :issue:`33360`::
1039
+
1040
+ sage: K.<a,b,c> = NumberField([x^2 - 2, x^2 - 3, x^2 - 5])
1041
+ sage: t = (((-2611940*c + 1925290/7653)*b - 1537130/7653*c
1042
+ ....: + 10130950)*a + (1343014/7653*c - 8349770)*b
1043
+ ....: + 6477058*c - 2801449990/4002519)
1044
+ sage: t.is_prime()
1045
+ False
1046
+ """
1047
+ try:
1048
+ return self._pari_prime is not None
1049
+ except AttributeError:
1050
+ pass
1051
+
1052
+ K = self.number_field().pari_nf()
1053
+ I = self.pari_hnf()
1054
+
1055
+ candidate = K.idealismaximal(I) or None
1056
+
1057
+ # PARI uses probabilistic primality testing inside idealismaximal().
1058
+ if get_flag(None, 'arithmetic'):
1059
+ # proof required, check using isprime()
1060
+ if candidate and not candidate[0].isprime():
1061
+ candidate = None
1062
+
1063
+ self._pari_prime = candidate
1064
+
1065
+ return self._pari_prime is not None
1066
+
1067
+ def pari_prime(self):
1068
+ r"""
1069
+ Return a PARI prime ideal corresponding to the ideal ``self``.
1070
+
1071
+ INPUT:
1072
+
1073
+ - ``self`` -- a prime ideal
1074
+
1075
+ OUTPUT: a PARI "prime ideal", i.e. a five-component vector `[p,a,e,f,b]`
1076
+ representing the prime ideal `p O_K + a O_K`, `e`, `f` as usual, `a` as
1077
+ vector of components on the integral basis, `b` Lenstra's constant.
1078
+
1079
+ EXAMPLES::
1080
+
1081
+ sage: K.<i> = QuadraticField(-1)
1082
+ sage: K.ideal(3).pari_prime()
1083
+ [3, [3, 0]~, 1, 2, 1]
1084
+ sage: K.ideal(2+i).pari_prime()
1085
+ [5, [2, 1]~, 1, 1, [-2, -1; 1, -2]]
1086
+ sage: K.ideal(2).pari_prime()
1087
+ Traceback (most recent call last):
1088
+ ...
1089
+ ValueError: Fractional ideal (2) is not a prime ideal
1090
+ """
1091
+ if not self.is_prime():
1092
+ raise ValueError("%s is not a prime ideal" % self)
1093
+ return self._pari_prime
1094
+
1095
+ def _cache_bnfisprincipal(self, proof=None, gens=False):
1096
+ r"""
1097
+ This function is essentially the implementation of
1098
+ :meth:`is_principal`, :meth:`gens_reduced` and
1099
+ :meth:`ideal_class_log`.
1100
+
1101
+ INPUT:
1102
+
1103
+ - ``self`` -- an ideal
1104
+
1105
+ - ``proof`` -- proof flag. If ``proof=False``, assume GRH
1106
+
1107
+ - ``gens`` -- boolean (default: ``False``); if ``True``, also computes
1108
+ the reduced generators of the ideal
1109
+
1110
+ OUTPUT:
1111
+
1112
+ None. This function simply caches the results: it sets
1113
+ ``_ideal_class_log`` (see :meth:`ideal_class_log`),
1114
+ ``_is_principal`` (see :meth:`is_principal`) and
1115
+ ``_reduced_generators``.
1116
+
1117
+ TESTS:
1118
+
1119
+ Check that no warnings are triggered from PARI/GP (see :issue:`30801`)::
1120
+
1121
+ sage: x = polygen(ZZ)
1122
+ sage: K.<a> = NumberField(x^2 - x + 112941801)
1123
+ sage: I = K.ideal((112941823, a + 49942513))
1124
+ sage: I.is_principal()
1125
+ False
1126
+ """
1127
+ # Since pari_bnf() is cached, this call to pari_bnf() should not
1128
+ # influence the run-time much. Also, this simplifies the handling
1129
+ # of the proof flag: if we computed bnfisprincipal() in the past
1130
+ # with proof=False, then we do not need to recompute the result.
1131
+ # We just need to check correctness of pari_bnf().
1132
+ proof = get_flag(proof, "number_field")
1133
+ bnf = self.number_field().pari_bnf(proof)
1134
+
1135
+ # If we already have _reduced_generators, no need to compute them again
1136
+ if hasattr(self, "_reduced_generators"):
1137
+ gens = False
1138
+
1139
+ # Is there something to do?
1140
+ if hasattr(self, "_ideal_class_log") and not gens:
1141
+ self._is_principal = not any(self._ideal_class_log)
1142
+ return
1143
+
1144
+ if not gens:
1145
+ v = bnf.bnfisprincipal(self.pari_hnf(), 0)
1146
+ self._ideal_class_log = list(v)
1147
+ self._is_principal = not any(self._ideal_class_log)
1148
+ else:
1149
+ # TODO: this is a bit of a waste. We ask bnfisprincipal to compute the compact form and then
1150
+ # convert this compact form back into an expanded form.
1151
+ # (though calling with 3 instead of 5 most likely triggers an error with memory allocation failure)
1152
+ v = bnf.bnfisprincipal(self.pari_hnf(), 5)
1153
+ e = v[0]
1154
+ t = v[1]
1155
+ t = bnf.nfbasistoalg(bnf.nffactorback(t))
1156
+ self._ideal_class_log = list(e)
1157
+ self._is_principal = not any(self._ideal_class_log)
1158
+
1159
+ if self._is_principal:
1160
+ g = self.number_field()(t)
1161
+ self._reduced_generators = (g,)
1162
+ elif gens:
1163
+ # Non-principal ideal
1164
+ self._reduced_generators = self.gens_two()
1165
+
1166
+ def is_principal(self, proof=None):
1167
+ r"""
1168
+ Return ``True`` if this ideal is principal.
1169
+
1170
+ Since it uses the PARI method :pari:`bnfisprincipal`, specify
1171
+ ``proof=True`` (this is the default setting) to prove the correctness
1172
+ of the output.
1173
+
1174
+ EXAMPLES::
1175
+
1176
+ sage: K = QuadraticField(-119,'a')
1177
+ sage: P = K.factor(2)[1][0]
1178
+ sage: P.is_principal()
1179
+ False
1180
+ sage: I = P^5
1181
+ sage: I.is_principal()
1182
+ True
1183
+ sage: I # random
1184
+ Fractional ideal (-1/2*a + 3/2)
1185
+ sage: P = K.ideal([2]).factor()[1][0]
1186
+ sage: I = P^5
1187
+ sage: I.is_principal()
1188
+ True
1189
+ """
1190
+ if len(self.gens()) <= 1:
1191
+ self._is_principal = True
1192
+ self._reduced_generators = self.gens()
1193
+ return self._is_principal
1194
+ self._cache_bnfisprincipal(proof)
1195
+ return self._is_principal
1196
+
1197
+ def ideal_class_log(self, proof=None):
1198
+ r"""
1199
+ Return the output of PARI's :pari:`bnfisprincipal` for this ideal,
1200
+ i.e. a vector expressing the class of this ideal in terms of a
1201
+ set of generators for the class group.
1202
+
1203
+ Since it uses the PARI method :pari:`bnfisprincipal`, specify
1204
+ ``proof=True`` (this is the default setting) to prove the correctness
1205
+ of the output.
1206
+
1207
+ EXAMPLES:
1208
+
1209
+ When the class number is 1, the result is always the empty list::
1210
+
1211
+ sage: K.<a> = QuadraticField(-163)
1212
+ sage: J = K.primes_above(random_prime(10^6))[0]
1213
+ sage: J.ideal_class_log()
1214
+ []
1215
+
1216
+ An example with class group of order 2. The first ideal is
1217
+ not principal, the second one is::
1218
+
1219
+ sage: K.<a> = QuadraticField(-5)
1220
+ sage: J = K.ideal(23).factor()[0][0]
1221
+ sage: J.ideal_class_log()
1222
+ [1]
1223
+ sage: (J^10).ideal_class_log()
1224
+ [0]
1225
+
1226
+ An example with a more complicated class group::
1227
+
1228
+ sage: x = polygen(ZZ)
1229
+ sage: K.<a, b> = NumberField([x^3 - x + 1, x^2 + 26])
1230
+ sage: K.class_group()
1231
+ Class group of order 18 with structure C6 x C3 of
1232
+ Number Field in a with defining polynomial x^3 - x + 1 over its base field
1233
+ sage: K.primes_above(7)[0].ideal_class_log() # random
1234
+ [1, 2]
1235
+ """
1236
+ self._cache_bnfisprincipal(proof)
1237
+ return self._ideal_class_log
1238
+
1239
+ def S_ideal_class_log(self, S):
1240
+ r"""
1241
+ S-class group version of :meth:`ideal_class_log`.
1242
+
1243
+ EXAMPLES::
1244
+
1245
+ sage: K.<a> = QuadraticField(-14)
1246
+ sage: S = K.primes_above(2)
1247
+ sage: I = K.ideal(3, a + 1)
1248
+ sage: I.S_ideal_class_log(S)
1249
+ [1]
1250
+ sage: I.S_ideal_class_log([])
1251
+ [3]
1252
+
1253
+ TESTS::
1254
+
1255
+ sage: K.<a> = QuadraticField(-974)
1256
+ sage: S = K.primes_above(2)
1257
+ sage: G = K.S_class_group(S)
1258
+ sage: I0 = G.0.ideal(); I1 = G.1.ideal()
1259
+ sage: for p in prime_range(100):
1260
+ ....: for P in K.primes_above(p):
1261
+ ....: v = P.S_ideal_class_log(S)
1262
+ ....: assert(G(P) == G(I0^v[0] * I1^v[1]))
1263
+ """
1264
+ from sage.modules.free_module_element import vector
1265
+ from sage.rings.finite_rings.integer_mod_ring import Zmod
1266
+ v = vector(ZZ, self.ideal_class_log())
1267
+ if all(P.is_principal() for P in S):
1268
+ L = v.list()
1269
+ invs = self.number_field().class_group().invariants()
1270
+ else:
1271
+ M = self.number_field()._S_class_group_quotient_matrix(tuple(S))
1272
+ L = (v * M).list()
1273
+ D = self.number_field()._S_class_group_and_units(tuple(S))[1]
1274
+ invs = [x[1] for x in D]
1275
+ return [Zmod(invs[i])(L[i]) for i in range(len(L))]
1276
+
1277
+ def is_zero(self):
1278
+ """
1279
+ Return ``True`` iff ``self`` is the zero ideal.
1280
+
1281
+ Note that `(0)` is a :class:`NumberFieldIdeal`, not a
1282
+ :class:`NumberFieldFractionalIdeal`.
1283
+
1284
+ EXAMPLES::
1285
+
1286
+ sage: x = polygen(ZZ)
1287
+ sage: K.<a> = NumberField(x^2 + 2); K
1288
+ Number Field in a with defining polynomial x^2 + 2
1289
+ sage: K.ideal(3).is_zero()
1290
+ False
1291
+ sage: I = K.ideal(0); I.is_zero()
1292
+ True
1293
+ sage: I
1294
+ Ideal (0) of Number Field in a with defining polynomial x^2 + 2
1295
+ """
1296
+ return self == self.number_field().ideal(0)
1297
+
1298
+ def norm(self):
1299
+ """
1300
+ Return the norm of this fractional ideal as a rational number.
1301
+
1302
+ EXAMPLES::
1303
+
1304
+ sage: x = polygen(ZZ)
1305
+ sage: K.<a> = NumberField(x^4 + 23); K
1306
+ Number Field in a with defining polynomial x^4 + 23
1307
+ sage: I = K.ideal(19); I
1308
+ Fractional ideal (19)
1309
+ sage: factor(I.norm())
1310
+ 19^4
1311
+ sage: F = I.factor()
1312
+ sage: F[0][0].norm().factor()
1313
+ 19^2
1314
+ """
1315
+ try:
1316
+ return self._norm
1317
+ except AttributeError:
1318
+ pass
1319
+ self._norm = QQ(self.number_field().pari_nf().idealnorm(self.pari_hnf()))
1320
+ return self._norm
1321
+
1322
+ # synonyms (using terminology of relative number fields)
1323
+
1324
+ def absolute_norm(self):
1325
+ """
1326
+ A synonym for :meth:`norm`.
1327
+
1328
+ EXAMPLES::
1329
+
1330
+ sage: x = polygen(ZZ)
1331
+ sage: K.<i> = NumberField(x^2 + 1)
1332
+ sage: K.ideal(1 + 2*i).absolute_norm()
1333
+ 5
1334
+ """
1335
+ return self.norm()
1336
+
1337
+ def relative_norm(self):
1338
+ """
1339
+ A synonym for :meth:`norm`.
1340
+
1341
+ EXAMPLES::
1342
+
1343
+ sage: x = polygen(ZZ)
1344
+ sage: K.<i> = NumberField(x^2 + 1)
1345
+ sage: K.ideal(1 + 2*i).relative_norm()
1346
+ 5
1347
+ """
1348
+ return self.norm()
1349
+
1350
+ def absolute_ramification_index(self):
1351
+ """
1352
+ A synonym for :meth:`ramification_index`.
1353
+
1354
+ EXAMPLES::
1355
+
1356
+ sage: x = polygen(ZZ)
1357
+ sage: K.<i> = NumberField(x^2 + 1)
1358
+ sage: K.ideal(1 + i).absolute_ramification_index()
1359
+ 2
1360
+ """
1361
+ return self.ramification_index()
1362
+
1363
+ def relative_ramification_index(self):
1364
+ """
1365
+ A synonym for :meth:`ramification_index`.
1366
+
1367
+ EXAMPLES::
1368
+
1369
+ sage: x = polygen(ZZ)
1370
+ sage: K.<i> = NumberField(x^2 + 1)
1371
+ sage: K.ideal(1 + i).relative_ramification_index()
1372
+ 2
1373
+ """
1374
+ return self.ramification_index()
1375
+
1376
+ def number_field(self):
1377
+ """
1378
+ Return the number field that this is a fractional ideal in.
1379
+
1380
+ EXAMPLES::
1381
+
1382
+ sage: x = polygen(ZZ)
1383
+ sage: K.<a> = NumberField(x^2 + 2); K
1384
+ Number Field in a with defining polynomial x^2 + 2
1385
+ sage: K.ideal(3).number_field()
1386
+ Number Field in a with defining polynomial x^2 + 2
1387
+ sage: K.ideal(0).number_field() # not tested (not implemented)
1388
+ Number Field in a with defining polynomial x^2 + 2
1389
+ """
1390
+ return self.ring()
1391
+
1392
+ def smallest_integer(self):
1393
+ r"""
1394
+ Return the smallest nonnegative integer in `I \cap \ZZ`,
1395
+ where `I` is this ideal. If `I = 0`, returns 0.
1396
+
1397
+ EXAMPLES::
1398
+
1399
+ sage: R.<x> = PolynomialRing(QQ)
1400
+ sage: K.<a> = NumberField(x^2 + 6)
1401
+ sage: I = K.ideal([4, a])/7; I
1402
+ Fractional ideal (2/7, 1/7*a)
1403
+ sage: I.smallest_integer()
1404
+ 2
1405
+
1406
+ TESTS::
1407
+
1408
+ sage: K.<i> = QuadraticField(-1)
1409
+ sage: P1, P2 = [P for P,e in K.factor(13)]
1410
+ sage: all((P1^i*P2^j).smallest_integer() == 13^max(i,j,0) for i in range(-3,3) for j in range(-3,3))
1411
+ True
1412
+ sage: I = K.ideal(0)
1413
+ sage: I.smallest_integer()
1414
+ 0
1415
+
1416
+ See :issue:`4392`::
1417
+
1418
+ sage: K.<a>=QuadraticField(-5)
1419
+ sage: I=K.ideal(7)
1420
+ sage: I.smallest_integer()
1421
+ 7
1422
+
1423
+ sage: K.<z> = CyclotomicField(13)
1424
+ sage: a = K([-8, -4, -4, -6, 3, -4, 8, 0, 7, 4, 1, 2])
1425
+ sage: I = K.ideal(a)
1426
+ sage: I.smallest_integer()
1427
+ 146196692151
1428
+ sage: I.norm()
1429
+ 1315770229359
1430
+ sage: I.norm() / I.smallest_integer()
1431
+ 9
1432
+ """
1433
+ if self.is_zero():
1434
+ return ZZ(0)
1435
+
1436
+ # There is no need for caching since pari_hnf() is already cached.
1437
+ q = self.pari_hnf()[0,0] # PARI integer or rational
1438
+ return ZZ(q.numerator())
1439
+
1440
+ #Old code by John Cremona, 2008-10-30, using the new coordinates()
1441
+ #function instead of factorization.
1442
+ #
1443
+ #Idea: We write 1 as a Q-linear combination of the Z-basis of self,
1444
+ #and return the denominator of this vector.
1445
+ #
1446
+ #self.__smallest_integer = self.coordinates(1).denominator()
1447
+ #return self.__smallest_integer
1448
+
1449
+ def valuation(self, p):
1450
+ r"""
1451
+ Return the valuation of ``self`` at ``p``.
1452
+
1453
+ INPUT:
1454
+
1455
+ - ``p`` -- a prime ideal `\mathfrak{p}` of this number field
1456
+
1457
+ OUTPUT:
1458
+
1459
+ (integer) The valuation of this fractional ideal at the prime
1460
+ `\mathfrak{p}`. If `\mathfrak{p}` is not prime, raise a
1461
+ :exc:`ValueError`.
1462
+
1463
+ EXAMPLES::
1464
+
1465
+ sage: x = polygen(ZZ)
1466
+ sage: K.<a> = NumberField(x^5 + 2); K
1467
+ Number Field in a with defining polynomial x^5 + 2
1468
+ sage: i = K.ideal(38); i
1469
+ Fractional ideal (38)
1470
+ sage: i.valuation(K.factor(19)[0][0])
1471
+ 1
1472
+ sage: i.valuation(K.factor(2)[0][0])
1473
+ 5
1474
+ sage: i.valuation(K.factor(3)[0][0])
1475
+ 0
1476
+ sage: i.valuation(0)
1477
+ Traceback (most recent call last):
1478
+ ...
1479
+ ValueError: p (= Ideal (0) of Number Field in a
1480
+ with defining polynomial x^5 + 2) must be nonzero
1481
+ sage: K.ideal(0).valuation(K.factor(2)[0][0])
1482
+ +Infinity
1483
+ """
1484
+ if not isinstance(p, NumberFieldIdeal):
1485
+ p = self.number_field().ideal(p)
1486
+ if not p:
1487
+ raise ValueError("p (= %s) must be nonzero" % p)
1488
+ if not p.is_prime():
1489
+ raise ValueError("p (= %s) must be a prime" % p)
1490
+ if p.ring() != self.number_field():
1491
+ raise ValueError("p (= %s) must be an ideal in %s" % self.number_field())
1492
+ nf = self.number_field().pari_nf()
1493
+ return nf.idealval(self.pari_hnf(), p.pari_prime()).sage()
1494
+
1495
+ def decomposition_group(self):
1496
+ r"""
1497
+ Return the decomposition group of ``self``, as a subset of the
1498
+ automorphism group of the number field of ``self``. Raises an
1499
+ error if the field isn't Galois. See the :meth:`GaloisGroup_v2.decomposition_group`
1500
+ method for further examples and doctests.
1501
+
1502
+ EXAMPLES::
1503
+
1504
+ sage: QuadraticField(-23, 'w').primes_above(7)[0].decomposition_group() # needs sage.groups
1505
+ Subgroup generated by [(1,2)] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
1506
+ """
1507
+ return self.number_field().galois_group().decomposition_group(self)
1508
+
1509
+ def ramification_group(self, v):
1510
+ r"""
1511
+ Return the `v`-th ramification group of ``self``, i.e. the set of
1512
+ elements `s` of the Galois group of the number field of ``self``
1513
+ (which we assume is Galois) such that `s` acts trivially
1514
+ modulo the `(v+1)`'st power of ``self``. See the
1515
+ :meth:`GaloisGroup.ramification_group` method for
1516
+ further examples and doctests.
1517
+
1518
+ EXAMPLES::
1519
+
1520
+ sage: QuadraticField(-23, 'w').primes_above(23)[0].ramification_group(0) # needs sage.groups
1521
+ Subgroup generated by [(1,2)] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
1522
+ sage: QuadraticField(-23, 'w').primes_above(23)[0].ramification_group(1) # needs sage.groups
1523
+ Subgroup generated by [()] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
1524
+ """
1525
+
1526
+ return self.number_field().galois_group().ramification_group(self, v)
1527
+
1528
+ def inertia_group(self):
1529
+ r"""
1530
+ Return the inertia group of ``self``, i.e. the set of elements `s` of the
1531
+ Galois group of the number field of ``self`` (which we assume is Galois)
1532
+ such that `s` acts trivially modulo ``self``. This is the same as the 0th
1533
+ ramification group of ``self``. See the
1534
+ :meth:`GaloisGroup_v2.inertia_group` method further examples and doctests.
1535
+
1536
+ EXAMPLES::
1537
+
1538
+ sage: QuadraticField(-23, 'w').primes_above(23)[0].inertia_group() # needs sage.groups
1539
+ Subgroup generated by [(1,2)] of (Galois group 2T1 (S2) with order 2 of x^2 + 23)
1540
+ """
1541
+ return self.ramification_group(0)
1542
+
1543
+ def random_element(self, *args, **kwds):
1544
+ r"""
1545
+ Return a random element of this ideal.
1546
+
1547
+ INPUT:
1548
+
1549
+ - ``*args``, ``*kwds`` -- parameters passed to the random integer
1550
+ function. See the documentation of ``ZZ.random_element()`` for
1551
+ details.
1552
+
1553
+ OUTPUT:
1554
+
1555
+ A random element of this fractional ideal, computed as a random
1556
+ `\ZZ`-linear combination of the basis.
1557
+
1558
+ EXAMPLES::
1559
+
1560
+ sage: x = polygen(ZZ)
1561
+ sage: K.<a> = NumberField(x^3 + 2)
1562
+ sage: I = K.ideal(1 - a)
1563
+ sage: I.random_element() # random output
1564
+ -a^2 - a - 19
1565
+ sage: I.random_element(distribution='uniform') # random output
1566
+ a^2 - 2*a - 8
1567
+ sage: I.random_element(-30, 30) # random output
1568
+ -7*a^2 - 17*a - 75
1569
+ sage: I.random_element(-100, 200).is_integral()
1570
+ True
1571
+ sage: I.random_element(-30, 30).parent() is K
1572
+ True
1573
+
1574
+ A relative example::
1575
+
1576
+ sage: K.<a, b> = NumberField([x^2 + 2, x^2 + 1000*x + 1])
1577
+ sage: I = K.ideal(1 - a)
1578
+ sage: I.random_element() # random output
1579
+ 17/500002*a^3 + 737253/250001*a^2 - 1494505893/500002*a + 752473260/250001
1580
+ sage: I.random_element().is_integral()
1581
+ True
1582
+ sage: I.random_element(-100, 200).parent() is K
1583
+ True
1584
+ """
1585
+ if self.number_field().is_absolute():
1586
+ basis = self.basis()
1587
+ else:
1588
+ basis = self.absolute_ideal().basis()
1589
+ return self.number_field()(sum([ZZ.random_element(*args, **kwds)*a for a in basis]))
1590
+
1591
+ def artin_symbol(self):
1592
+ r"""
1593
+ Return the Artin symbol `(K / \QQ, P)`, where `K` is the
1594
+ number field of `P` = ``self``. This is the unique element `s` of
1595
+ the decomposition group of `P` such that `s(x) = x^p \pmod{P}`
1596
+ where `p` is the residue characteristic of `P`. (Here `P`
1597
+ (``self``) should be prime and unramified.)
1598
+
1599
+ See the :meth:`GaloisGroup_v2.artin_symbol` method
1600
+ for further documentation and examples.
1601
+
1602
+ EXAMPLES::
1603
+
1604
+ sage: QuadraticField(-23, 'w').primes_above(7)[0].artin_symbol() # needs sage.groups
1605
+ (1,2)
1606
+ """
1607
+ return self.number_field().galois_group().artin_symbol(self)
1608
+
1609
+ def residue_symbol(self, e, m, check=True):
1610
+ r"""
1611
+ The `m`-th power residue symbol for an element `e` and the proper ideal.
1612
+
1613
+ .. MATH:: \left(\frac{\alpha}{\mathbf{P}}\right) \equiv \alpha^{\frac{N(\mathbf{P})-1}{m}} \operatorname{mod} \mathbf{P}
1614
+
1615
+ .. NOTE:: accepts `m=1`, in which case returns 1
1616
+
1617
+ .. NOTE:: can also be called for an element from sage.rings.number_field_element.residue_symbol
1618
+
1619
+ .. NOTE:: `e` is coerced into the number field of ``self``
1620
+
1621
+ .. NOTE::
1622
+
1623
+ if `m=2`, `e` is an integer, and ``self.number_field()`` has absolute degree 1 (i.e. it is a copy of the rationals),
1624
+ then this calls :func:`kronecker_symbol`, which is implemented using GMP.
1625
+
1626
+ INPUT:
1627
+
1628
+ - ``e`` -- element of the number field
1629
+
1630
+ - ``m`` -- positive integer
1631
+
1632
+ OUTPUT: an `m`-th root of unity in the number field
1633
+
1634
+ EXAMPLES:
1635
+
1636
+ Quadratic Residue (7 is not a square modulo 11)::
1637
+
1638
+ sage: x = polygen(ZZ)
1639
+ sage: K.<a> = NumberField(x - 1)
1640
+ sage: K.ideal(11).residue_symbol(7,2)
1641
+ -1
1642
+
1643
+ Cubic Residue::
1644
+
1645
+ sage: K.<w> = NumberField(x^2 - x + 1)
1646
+ sage: K.ideal(17).residue_symbol(w^2 + 3, 3)
1647
+ -w
1648
+
1649
+ The field must contain the `m`-th roots of unity::
1650
+
1651
+ sage: K.<w> = NumberField(x^2 - x + 1)
1652
+ sage: K.ideal(17).residue_symbol(w^2 + 3, 5)
1653
+ Traceback (most recent call last):
1654
+ ...
1655
+ ValueError: The residue symbol to that power is not defined for the number field
1656
+ """
1657
+ K = self.ring()
1658
+ if m == 2 and K.absolute_degree() == 1:
1659
+ try:
1660
+ ze = ZZ(e)
1661
+ zp = self.smallest_integer()
1662
+ except TypeError:
1663
+ pass
1664
+ else:
1665
+ return kronecker_symbol(ze, zp)
1666
+ if check:
1667
+ if self.is_trivial():
1668
+ raise ValueError("Ideal must be proper")
1669
+ if m < 1:
1670
+ raise ValueError("Power must be positive")
1671
+ if not self.is_coprime(e):
1672
+ raise ValueError("Element is not coprime to the ideal")
1673
+ if not self.is_coprime(m):
1674
+ raise ValueError("Ideal is not coprime to the power")
1675
+ primroot = K.primitive_root_of_unity()
1676
+ rootorder = primroot.multiplicative_order()
1677
+ if check:
1678
+ if rootorder % m:
1679
+ raise ValueError("The residue symbol to that power is not defined for the number field")
1680
+ if not self.is_prime():
1681
+ return prod(Q.residue_symbol(e,m,check=False)**i for Q, i in self.factor())
1682
+ k = self.residue_field()
1683
+ try:
1684
+ r = k(e)
1685
+ except TypeError:
1686
+ raise ValueError("Element and ideal must be in a common number field")
1687
+ r = k(r**((k.order()-1)/m))
1688
+ resroot = primroot**(rootorder/m)
1689
+ from sage.groups.generic import discrete_log
1690
+ j = discrete_log(k(r), k(resroot), ord=m)
1691
+ return resroot**j
1692
+
1693
+ def _quadratic_form(self):
1694
+ r"""
1695
+ If this is a quadratic extension over `\QQ`, return the binary
1696
+ quadratic form associated with this ideal.
1697
+
1698
+ EXAMPLES::
1699
+
1700
+ sage: K.<a> = QuadraticField(23)
1701
+ sage: K.ideal(a).quadratic_form()
1702
+ 23*x^2 - y^2
1703
+
1704
+ sage: K.<a> = QuadraticField(-5)
1705
+ sage: K.class_group().order()
1706
+ 2
1707
+ sage: A = K.class_group().gen()
1708
+ sage: A.ideal().quadratic_form().reduced_form()
1709
+ 2*x^2 + 2*x*y + 3*y^2
1710
+ sage: (A^2).ideal().quadratic_form().reduced_form()
1711
+ x^2 + 5*y^2
1712
+
1713
+ sage: K.<a> = QuadraticField(-40)
1714
+ sage: K.class_group().order()
1715
+ 2
1716
+ sage: A = K.class_group().gen()
1717
+ sage: A.ideal().quadratic_form().reduced_form()
1718
+ 2*x^2 + 5*y^2
1719
+ sage: (A^2).ideal().quadratic_form().reduced_form()
1720
+ x^2 + 10*y^2
1721
+
1722
+ One more check::
1723
+
1724
+ sage: K = QuadraticField(-79)
1725
+ sage: A = K.class_group().gen()
1726
+ sage: [(A**i).ideal().quadratic_form().discriminant()
1727
+ ....: for i in range(5)]
1728
+ [-79, -79, -79, -79, -79]
1729
+
1730
+ This is not defined for higher-degree extensions::
1731
+
1732
+ sage: x = polygen(ZZ)
1733
+ sage: K.<a> = NumberField(x**3 - x - 1)
1734
+ sage: K.ideal(a)._quadratic_form()
1735
+ Traceback (most recent call last):
1736
+ ...
1737
+ ValueError: not defined for ideals in number fields of degree > 2 over Q.
1738
+
1739
+ REFERENCES:
1740
+
1741
+ - [Coh1993]_
1742
+ """
1743
+ K = self.number_field()
1744
+ if K.degree() == 2:
1745
+ from sage.quadratic_forms.binary_qf import BinaryQF
1746
+ gens = self.gens_reduced()
1747
+ if len(gens) == 1:
1748
+ u, v = K.ring_of_integers().basis()
1749
+ alpha, beta = gens[0] * u, gens[0] * v
1750
+ else:
1751
+ alpha, beta = gens
1752
+ if QQ((beta * alpha.galois_conjugate() - alpha * beta.galois_conjugate()) / K.gen()) < 0:
1753
+ alpha, beta = beta, alpha
1754
+ N = self.norm()
1755
+ a = alpha.norm() // N
1756
+ b = ZZ(alpha * beta.galois_conjugate() +
1757
+ beta * alpha.galois_conjugate()) // N
1758
+ c = beta.norm() // N
1759
+ return BinaryQF([a, b, c])
1760
+
1761
+ raise ValueError("not defined for ideals in number fields of degree > 2 over Q.")
1762
+
1763
+
1764
+ def basis_to_module(B, K):
1765
+ r"""
1766
+ Given a basis `B` of elements for a `\ZZ`-submodule of a number
1767
+ field `K`, return the corresponding `\ZZ`-submodule.
1768
+
1769
+ EXAMPLES::
1770
+
1771
+ sage: x = polygen(ZZ)
1772
+ sage: K.<w> = NumberField(x^4 + 1)
1773
+ sage: from sage.rings.number_field.number_field_ideal import basis_to_module
1774
+ sage: basis_to_module([K.0, K.0^2 + 3], K)
1775
+ Free module of degree 4 and rank 2 over Integer Ring
1776
+ User basis matrix:
1777
+ [0 1 0 0]
1778
+ [3 0 1 0]
1779
+ """
1780
+ V, from_V, to_V = K.absolute_vector_space()
1781
+ M = ZZ**(V.dimension())
1782
+ C = [to_V(K(b)) for b in B]
1783
+ return M.span_of_basis(C)
1784
+
1785
+
1786
+ def is_NumberFieldIdeal(x):
1787
+ """
1788
+ Return ``True`` if `x` is an ideal of a number field.
1789
+
1790
+ EXAMPLES::
1791
+
1792
+ sage: from sage.rings.number_field.number_field_ideal import is_NumberFieldIdeal
1793
+ sage: is_NumberFieldIdeal(2/3)
1794
+ doctest:warning...
1795
+ DeprecationWarning: The function is_NumberFieldIdeal is deprecated;
1796
+ use 'isinstance(..., NumberFieldIdeal)' instead.
1797
+ See https://github.com/sagemath/sage/issues/38124 for details.
1798
+ False
1799
+ sage: is_NumberFieldIdeal(ideal(5))
1800
+ False
1801
+
1802
+ sage: x = polygen(ZZ)
1803
+ sage: k.<a> = NumberField(x^2 + 2)
1804
+ sage: I = k.ideal([a + 1]); I
1805
+ Fractional ideal (a + 1)
1806
+ sage: is_NumberFieldIdeal(I)
1807
+ True
1808
+ sage: Z = k.ideal(0); Z
1809
+ Ideal (0) of Number Field in a with defining polynomial x^2 + 2
1810
+ sage: is_NumberFieldIdeal(Z)
1811
+ True
1812
+ """
1813
+ from sage.misc.superseded import deprecation
1814
+ deprecation(38124,
1815
+ "The function is_NumberFieldIdeal is deprecated; "
1816
+ "use 'isinstance(..., NumberFieldIdeal)' instead.")
1817
+ return isinstance(x, NumberFieldIdeal)
1818
+
1819
+
1820
+ class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal, Ideal_fractional):
1821
+ r"""
1822
+ A fractional ideal in a number field.
1823
+
1824
+ EXAMPLES::
1825
+
1826
+ sage: x = polygen(ZZ)
1827
+ sage: R.<x> = PolynomialRing(QQ)
1828
+ sage: K.<a> = NumberField(x^3 - 2)
1829
+ sage: I = K.ideal(2/(5+a))
1830
+ sage: J = I^2
1831
+ sage: Jinv = I^(-2)
1832
+ sage: J*Jinv
1833
+ Fractional ideal (1)
1834
+
1835
+ TESTS:
1836
+
1837
+ Number-field fractional ideals are fractional ideals (:issue:`32380`)::
1838
+
1839
+ sage: from sage.rings.ideal import Ideal_fractional
1840
+ sage: isinstance(I, Ideal_fractional)
1841
+ True
1842
+ """
1843
+ def __init__(self, field, gens, coerce=True):
1844
+ """
1845
+ INPUT:
1846
+
1847
+ - ``field`` -- a number field
1848
+ - ``x`` -- list of NumberFieldElements of the field, not all zero
1849
+
1850
+ EXAMPLES::
1851
+
1852
+ sage: x = polygen(ZZ)
1853
+ sage: NumberField(x^2 + 1, 'a').ideal(7)
1854
+ Fractional ideal (7)
1855
+ """
1856
+ from .number_field import NumberField_generic
1857
+ if not isinstance(field, NumberField_generic):
1858
+ raise TypeError("field (=%s) must be a number field." % field)
1859
+
1860
+ if not gens:
1861
+ raise ValueError("gens must have length at least 1 (zero ideal is not a fractional ideal)")
1862
+ if len(gens) == 1 and isinstance(gens[0], (list, tuple)):
1863
+ gens = gens[0]
1864
+ if any(bool(x) for x in gens):
1865
+ NumberFieldIdeal.__init__(self, field, gens)
1866
+ else:
1867
+ raise ValueError("gens must have a nonzero element (zero ideal is not a fractional ideal)")
1868
+
1869
+ def _repr_(self):
1870
+ """
1871
+ Return the string representation of this number field fractional ideal.
1872
+
1873
+ .. NOTE::
1874
+
1875
+ Only the zero ideal actually has type NumberFieldIdeal; all
1876
+ others have type NumberFieldFractionalIdeal.
1877
+
1878
+ EXAMPLES::
1879
+
1880
+ sage: x = polygen(ZZ)
1881
+ sage: K.<a> = NumberField(x^2 + 5)
1882
+ sage: I = K.ideal([2,1+a]); I
1883
+ Fractional ideal (2, a + 1)
1884
+ sage: type(I)
1885
+ <class 'sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal'>
1886
+ """
1887
+ return "Fractional ideal %s" % self._repr_short()
1888
+
1889
+ def divides(self, other):
1890
+ """
1891
+ Return ``True`` if this ideal divides ``other`` and ``False`` otherwise.
1892
+
1893
+ EXAMPLES::
1894
+
1895
+ sage: K.<a> = CyclotomicField(11); K
1896
+ Cyclotomic Field of order 11 and degree 10
1897
+ sage: I = K.factor(31)[0][0]; I
1898
+ Fractional ideal (31, a^5 + 10*a^4 - a^3 + a^2 + 9*a - 1)
1899
+ sage: I.divides(I)
1900
+ True
1901
+ sage: I.divides(31)
1902
+ True
1903
+ sage: I.divides(29)
1904
+ False
1905
+ """
1906
+ if not isinstance(other, NumberFieldIdeal):
1907
+ other = self.number_field().ideal(other)
1908
+ return (other / self).is_integral()
1909
+
1910
+ def factor(self):
1911
+ """
1912
+ Factorization of this ideal in terms of prime ideals.
1913
+
1914
+ EXAMPLES::
1915
+
1916
+ sage: x = polygen(ZZ)
1917
+ sage: K.<a> = NumberField(x^4 + 23); K
1918
+ Number Field in a with defining polynomial x^4 + 23
1919
+ sage: I = K.ideal(19); I
1920
+ Fractional ideal (19)
1921
+ sage: F = I.factor(); F
1922
+ (Fractional ideal (19, 1/2*a^2 + a - 17/2))
1923
+ * (Fractional ideal (19, 1/2*a^2 - a - 17/2))
1924
+ sage: type(F)
1925
+ <class 'sage.structure.factorization.Factorization'>
1926
+ sage: list(F)
1927
+ [(Fractional ideal (19, 1/2*a^2 + a - 17/2), 1),
1928
+ (Fractional ideal (19, 1/2*a^2 - a - 17/2), 1)]
1929
+ sage: F.prod()
1930
+ Fractional ideal (19)
1931
+
1932
+ TESTS:
1933
+
1934
+ Number fields defined by non-monic and non-integral
1935
+ polynomials are supported (:issue:`252`);
1936
+ the representation depends on the PARI version::
1937
+
1938
+ sage: F.<a> = NumberField(2*x^3 + x + 1)
1939
+ sage: fact = F.factor(2)
1940
+ sage: (fact[0][1], fact[1][1])
1941
+ (2, 1)
1942
+ sage: fact[0][0] == F.ideal(2*a^2 + 1)
1943
+ True
1944
+ sage: fact[1][0] == F.ideal(-2*a^2)
1945
+ True
1946
+ sage: [p[0].norm() for p in fact]
1947
+ [2, 2]
1948
+ """
1949
+ try:
1950
+ return self.__factorization
1951
+ except AttributeError:
1952
+ K = self.number_field()
1953
+ F = K.pari_nf().idealfactor(self.pari_hnf())
1954
+ A = []
1955
+ for j in range(0, len(F[0])):
1956
+ I = K.ideal(F[j,0])
1957
+ A.append((I,ZZ(F[j,1])))
1958
+ self.__factorization = Factorization(A)
1959
+ return self.__factorization
1960
+
1961
+ def prime_factors(self):
1962
+ """
1963
+ Return a list of the prime ideal factors of ``self``.
1964
+
1965
+ OUTPUT:
1966
+
1967
+ list of prime ideals (a new list is returned
1968
+ each time this function is called)
1969
+
1970
+ EXAMPLES::
1971
+
1972
+ sage: x = polygen(ZZ)
1973
+ sage: K.<w> = NumberField(x^2 + 23)
1974
+ sage: I = ideal(w+1)
1975
+ sage: I.prime_factors()
1976
+ [Fractional ideal (2, 1/2*w - 1/2),
1977
+ Fractional ideal (2, 1/2*w + 1/2),
1978
+ Fractional ideal (3, 1/2*w + 1/2)]
1979
+ """
1980
+ return [x[0] for x in self.factor()]
1981
+
1982
+ support = prime_factors
1983
+
1984
+ def _div_(self, other):
1985
+ """
1986
+ Return the quotient ``self`` / ``other``.
1987
+
1988
+ EXAMPLES::
1989
+
1990
+ sage: x = polygen(ZZ)
1991
+ sage: R.<x> = PolynomialRing(QQ)
1992
+ sage: K.<a> = NumberField(x^2 - 5)
1993
+ sage: I = K.ideal(2/(5+a))
1994
+ sage: J = K.ideal(17+a)
1995
+ sage: I/J
1996
+ Fractional ideal (-11/1420*a + 9/284)
1997
+ sage: (I/J) * J == I
1998
+ True
1999
+ """
2000
+ K = self.ring()
2001
+ if self.ngens() == 1 and other.ngens() == 1:
2002
+ return K.ideal(self.gen(0) / other.gen(0))
2003
+ return K.ideal(K.pari_nf().idealdiv(self, other))
2004
+
2005
+ def __invert__(self):
2006
+ """
2007
+ Return the multiplicative inverse of ``self``. Call with ``~self``.
2008
+
2009
+ EXAMPLES::
2010
+
2011
+ sage: x = polygen(ZZ)
2012
+ sage: R.<x> = PolynomialRing(QQ)
2013
+ sage: K.<a> = NumberField(x^3 - 2)
2014
+ sage: I = K.ideal(2/(5+a))
2015
+ sage: ~I
2016
+ Fractional ideal (1/2*a + 5/2)
2017
+ sage: 1/I
2018
+ Fractional ideal (1/2*a + 5/2)
2019
+ sage: (1/I) * I
2020
+ Fractional ideal (1)
2021
+ """
2022
+ nf = self.number_field().pari_nf()
2023
+ hnf = nf.idealdiv(self.number_field().ideal(1).pari_hnf(),
2024
+ self.pari_hnf())
2025
+ I = self.number_field().ideal(NumberFieldIdeal._NumberFieldIdeal__elements_from_hnf(self,hnf))
2026
+ I.__pari_hnf = hnf
2027
+ return I
2028
+
2029
+ def is_maximal(self):
2030
+ """
2031
+ Return ``True`` if this ideal is maximal. This is equivalent to
2032
+ ``self`` being prime, since it is nonzero.
2033
+
2034
+ EXAMPLES::
2035
+
2036
+ sage: x = polygen(ZZ)
2037
+ sage: K.<a> = NumberField(x^3 + 3); K
2038
+ Number Field in a with defining polynomial x^3 + 3
2039
+ sage: K.ideal(5).is_maximal()
2040
+ False
2041
+ sage: K.ideal(7).is_maximal()
2042
+ True
2043
+ """
2044
+ return self.is_prime()
2045
+
2046
+ def is_trivial(self, proof=None):
2047
+ """
2048
+ Return ``True`` if this is a trivial ideal.
2049
+
2050
+ EXAMPLES::
2051
+
2052
+ sage: F.<a> = QuadraticField(-5)
2053
+ sage: I = F.ideal(3)
2054
+ sage: I.is_trivial()
2055
+ False
2056
+ sage: J = F.ideal(5)
2057
+ sage: J.is_trivial()
2058
+ False
2059
+ sage: (I + J).is_trivial()
2060
+ True
2061
+ """
2062
+ return self == self.number_field().ideal(1)
2063
+
2064
+ def ramification_index(self):
2065
+ r"""
2066
+ Return the ramification index of this fractional ideal,
2067
+ assuming it is prime. Otherwise, raise a :exc:`ValueError`.
2068
+
2069
+ The ramification index is the power of this prime appearing in
2070
+ the factorization of the prime in `\ZZ` that this prime lies
2071
+ over.
2072
+
2073
+ EXAMPLES::
2074
+
2075
+ sage: x = polygen(ZZ)
2076
+ sage: K.<a> = NumberField(x^2 + 2); K
2077
+ Number Field in a with defining polynomial x^2 + 2
2078
+ sage: f = K.factor(2); f
2079
+ (Fractional ideal (a))^2
2080
+ sage: f[0][0].ramification_index()
2081
+ 2
2082
+ sage: K.ideal(13).ramification_index()
2083
+ 1
2084
+ sage: K.ideal(17).ramification_index()
2085
+ Traceback (most recent call last):
2086
+ ...
2087
+ ValueError: Fractional ideal (17) is not a prime ideal
2088
+ """
2089
+ return ZZ(self.pari_prime().pr_get_e())
2090
+
2091
+ def reduce(self, f):
2092
+ r"""
2093
+ Return the canonical reduction of the element `f` modulo the ideal
2094
+ `I` (= ``self``). This is an element of `R` (the ring of integers of the
2095
+ number field) that is equivalent modulo `I` to `f`.
2096
+
2097
+ An error is raised if this fractional ideal is not integral or
2098
+ the element `f` is not integral.
2099
+
2100
+ INPUT:
2101
+
2102
+ - ``f`` -- an integral element of the number field
2103
+
2104
+ OUTPUT:
2105
+
2106
+ An integral element `g`, such that `f - g` belongs to the ideal ``self``
2107
+ and such that `g` is a canonical reduced representative of the coset
2108
+ `f + I` (where `I` = ``self``) as described in the method :meth:`residues`,
2109
+ namely an integral element with coordinates `(r_0, \dots,r_{n-1})`, where:
2110
+
2111
+ - `r_i` is reduced modulo `d_i`
2112
+ - `d_i = b_i[i]`, with `\{b_0, b_1, \dots, b_n\}` HNF basis
2113
+ of the ideal ``self``.
2114
+
2115
+ .. NOTE::
2116
+
2117
+ The reduced element `g` is not necessarily small. To get a
2118
+ small `g` use the method :meth:`small_residue`.
2119
+
2120
+ EXAMPLES::
2121
+
2122
+ sage: x = polygen(ZZ)
2123
+ sage: k.<a> = NumberField(x^3 + 11)
2124
+ sage: I = k.ideal(5, a^2 - a + 1)
2125
+ sage: c = 4*a + 9
2126
+ sage: I.reduce(c)
2127
+ a^2 - 2*a
2128
+ sage: c - I.reduce(c) in I
2129
+ True
2130
+
2131
+ The reduced element is in the list of canonical representatives
2132
+ returned by the ``residues`` method:
2133
+
2134
+ ::
2135
+
2136
+ sage: I.reduce(c) in list(I.residues())
2137
+ True
2138
+
2139
+ The reduced element does not necessarily have smaller norm (use
2140
+ :meth:`small_residue` for that)
2141
+
2142
+ ::
2143
+
2144
+ sage: c.norm()
2145
+ 25
2146
+ sage: (I.reduce(c)).norm()
2147
+ 209
2148
+ sage: (I.small_residue(c)).norm()
2149
+ 10
2150
+
2151
+ Sometimes the canonical reduced representative of `1` won't be `1`
2152
+ (it depends on the choice of basis for the ring of integers):
2153
+
2154
+ ::
2155
+
2156
+ sage: k.<a> = NumberField(x^2 + 23)
2157
+ sage: I = k.ideal(3)
2158
+ sage: I.reduce(3*a + 1)
2159
+ -3/2*a - 1/2
2160
+ sage: k.ring_of_integers().basis()
2161
+ [1/2*a + 1/2, a]
2162
+
2163
+ AUTHOR: Maite Aranes.
2164
+ """
2165
+
2166
+ if not self.is_integral():
2167
+ raise ValueError("reduce only defined for integral ideals")
2168
+
2169
+ R = self.number_field().maximal_order()
2170
+
2171
+ if f not in R:
2172
+ raise TypeError("reduce only defined for integral elements")
2173
+
2174
+ Rbasis = R.basis()
2175
+ n = len(Rbasis)
2176
+ from sage.matrix.matrix_space import MatrixSpace
2177
+ M = MatrixSpace(ZZ,n)([R.coordinates(y) for y in self.basis()])
2178
+
2179
+ D = M.hermite_form()
2180
+ d = [D[i, i] for i in range(n)]
2181
+
2182
+ v = R.coordinates(f)
2183
+
2184
+ for i in range(n):
2185
+ q, r = ZZ(v[i]).quo_rem(d[i])
2186
+ # v is a vector of rationals, we want division of integers
2187
+ if 2*r > d[i]:
2188
+ q = q + 1
2189
+ v = v - q*D[i]
2190
+
2191
+ return sum([v[i] * Rbasis[i] for i in range(n)])
2192
+
2193
+ def residues(self):
2194
+ r"""
2195
+ Return a iterator through a complete list of residues modulo this integral ideal.
2196
+
2197
+ An error is raised if this fractional ideal is not integral.
2198
+
2199
+ OUTPUT:
2200
+
2201
+ An iterator through a complete list of residues modulo the integral
2202
+ ideal ``self``. This list is the set of canonical reduced representatives
2203
+ given by all integral elements with coordinates `(r_0, \dots,r_{n-1})`,
2204
+ where:
2205
+
2206
+ - `r_i` is reduced modulo `d_i`
2207
+
2208
+ - `d_i = b_i[i]`, with `\{b_0, b_1, \dots, b_n\}` HNF basis
2209
+ of the ideal.
2210
+
2211
+ AUTHOR: John Cremona (modified by Maite Aranes)
2212
+
2213
+ EXAMPLES::
2214
+
2215
+ sage: x = polygen(ZZ)
2216
+ sage: K.<i> = NumberField(x^2 + 1)
2217
+ sage: res = K.ideal(2).residues(); res
2218
+ xmrange_iter([[0, 1], [0, 1]], <function ...<lambda> at 0x...>)
2219
+ sage: list(res)
2220
+ [0, i, 1, i + 1]
2221
+ sage: list(K.ideal(2 + i).residues())
2222
+ [-2*i, -i, 0, i, 2*i]
2223
+ sage: list(K.ideal(i).residues())
2224
+ [0]
2225
+ sage: I = K.ideal(3 + 6*i)
2226
+ sage: reps = I.residues()
2227
+ sage: len(list(reps)) == I.norm()
2228
+ True
2229
+ sage: all(r == s or not (r-s) in I # long time (6s on sage.math, 2011)
2230
+ ....: for r in reps for s in reps)
2231
+ True
2232
+
2233
+ sage: K.<a> = NumberField(x^3 - 10)
2234
+ sage: I = K.ideal(a - 1)
2235
+ sage: len(list(I.residues())) == I.norm()
2236
+ True
2237
+
2238
+ sage: K.<z> = CyclotomicField(11)
2239
+ sage: len(list(K.primes_above(3)[0].residues())) == 3**5 # long time (5s on sage.math, 2011)
2240
+ True
2241
+ """
2242
+ if not self.is_integral():
2243
+ raise ValueError("residues only defined for integral ideals")
2244
+
2245
+ R = self.number_field().maximal_order()
2246
+ Rbasis = R.basis()
2247
+ n = len(Rbasis)
2248
+ from sage.matrix.matrix_space import MatrixSpace
2249
+ M = MatrixSpace(ZZ, n)([R.coordinates(_) for _ in self.basis()])
2250
+
2251
+ D = M.hermite_form()
2252
+ d = [D[i, i] for i in range(n)]
2253
+ coord_ranges = [list(range((-di+2)//2,(di+2)//2)) for di in d]
2254
+ combo = lambda c: sum(c[i] * Rbasis[i] for i in range(n))
2255
+ return xmrange_iter(coord_ranges, combo)
2256
+
2257
+ def invertible_residues(self, reduce=True):
2258
+ r"""
2259
+ Return an iterator through a list of invertible residues
2260
+ modulo this integral ideal.
2261
+
2262
+ An error is raised if this fractional ideal is not integral.
2263
+
2264
+ INPUT:
2265
+
2266
+ - ``reduce`` -- boolean; if ``True`` (default), use ``small_residue`` to get
2267
+ small representatives of the residues
2268
+
2269
+ OUTPUT:
2270
+
2271
+ An iterator through a list of invertible residues modulo this ideal
2272
+ `I`, i.e. a list of elements in the ring of integers `R` representing
2273
+ the elements of `(R/I)^*`.
2274
+
2275
+ ALGORITHM: Use :pari:`idealstar` to find the group structure and
2276
+ generators of the multiplicative group modulo the ideal.
2277
+
2278
+ EXAMPLES::
2279
+
2280
+ sage: x = polygen(ZZ)
2281
+ sage: K.<i> = NumberField(x^2 + 1)
2282
+ sage: ires = K.ideal(2).invertible_residues(); ires
2283
+ xmrange_iter([[0, 1]], <function ...<lambda> at 0x...>)
2284
+ sage: list(ires)
2285
+ [1, -i]
2286
+ sage: list(K.ideal(2 + i).invertible_residues())
2287
+ [1, 2, 4, 3]
2288
+ sage: list(K.ideal(i).residues())
2289
+ [0]
2290
+ sage: list(K.ideal(i).invertible_residues())
2291
+ [1]
2292
+ sage: I = K.ideal(3 + 6*i)
2293
+ sage: units = I.invertible_residues()
2294
+ sage: len(list(units)) == I.euler_phi()
2295
+ True
2296
+
2297
+ sage: K.<a> = NumberField(x^3 - 10)
2298
+ sage: I = K.ideal(a - 1)
2299
+ sage: len(list(I.invertible_residues())) == I.euler_phi()
2300
+ True
2301
+
2302
+ sage: K.<z> = CyclotomicField(10)
2303
+ sage: len(list(K.primes_above(3)[0].invertible_residues()))
2304
+ 80
2305
+
2306
+ TESTS:
2307
+
2308
+ Check that the integrality is not lost, cf. :issue:`30801`::
2309
+
2310
+ sage: K.<a> = NumberField(x^2 + x + 1)
2311
+ sage: all(x.is_integral() for x in K.ideal(8).invertible_residues())
2312
+ True
2313
+
2314
+ AUTHOR: John Cremona
2315
+ """
2316
+ return self.invertible_residues_mod(subgp_gens=None, reduce=reduce)
2317
+
2318
+ def invertible_residues_mod(self, subgp_gens=[], reduce=True):
2319
+ r"""
2320
+ Return a iterator through a list of representatives for the invertible
2321
+ residues modulo this integral ideal, modulo the subgroup generated by
2322
+ the elements in the list ``subgp_gens``.
2323
+
2324
+ INPUT:
2325
+
2326
+ - ``subgp_gens`` -- either ``None`` or a list of elements of the number
2327
+ field of ``self``. These need not be integral, but should be coprime to
2328
+ the ideal ``self``. If the list is empty or ``None``, the function returns
2329
+ an iterator through a list of representatives for the invertible
2330
+ residues modulo the integral ideal ``self``.
2331
+
2332
+ - ``reduce`` -- boolean; if ``True`` (default), use ``small_residues`` to
2333
+ get small representatives of the residues
2334
+
2335
+ .. NOTE::
2336
+
2337
+ See also :meth:`invertible_residues` for a simpler version without the subgroup.
2338
+
2339
+ OUTPUT:
2340
+
2341
+ An iterator through a list of representatives for the invertible
2342
+ residues modulo ``self`` and modulo the group generated by
2343
+ ``subgp_gens``, i.e. a list of elements in the ring of integers `R`
2344
+ representing the elements of `(R/I)^*/U`, where `I` is this ideal and
2345
+ `U` is the subgroup of `(R/I)^*` generated by ``subgp_gens``.
2346
+
2347
+ EXAMPLES:
2348
+
2349
+ ::
2350
+
2351
+ sage: x = polygen(ZZ)
2352
+ sage: k.<a> = NumberField(x^2 + 23)
2353
+ sage: I = k.ideal(a)
2354
+ sage: list(I.invertible_residues_mod([-1]))
2355
+ [1, 5, 2, 10, 4, 20, 8, 17, 16, 11, 9]
2356
+ sage: list(I.invertible_residues_mod([1/2]))
2357
+ [1, 5]
2358
+ sage: list(I.invertible_residues_mod([23]))
2359
+ Traceback (most recent call last):
2360
+ ...
2361
+ TypeError: the element must be invertible mod the ideal
2362
+
2363
+ ::
2364
+
2365
+ sage: K.<a> = NumberField(x^3 - 10)
2366
+ sage: I = K.ideal(a - 1)
2367
+ sage: len(list(I.invertible_residues_mod([]))) == I.euler_phi()
2368
+ True
2369
+
2370
+ sage: I = K.ideal(1)
2371
+ sage: list(I.invertible_residues_mod([]))
2372
+ [1]
2373
+
2374
+ ::
2375
+
2376
+ sage: K.<z> = CyclotomicField(10)
2377
+ sage: len(list(K.primes_above(3)[0].invertible_residues_mod([])))
2378
+ 80
2379
+
2380
+ AUTHOR: Maite Aranes.
2381
+ """
2382
+ if self.norm() == 1:
2383
+ return xmrange_iter([[1]], lambda l: l[0])
2384
+
2385
+ G = self.idealstar(2)
2386
+
2387
+ invs = G.invariants()
2388
+ g = G.gens_values()
2389
+ n = G.ngens()
2390
+
2391
+ from sage.matrix.constructor import Matrix
2392
+ from sage.matrix.special import diagonal_matrix
2393
+
2394
+ M = diagonal_matrix(ZZ, invs)
2395
+ if subgp_gens:
2396
+ Units = Matrix(ZZ, [self.ideallog(_) for _ in subgp_gens])
2397
+ M = M.stack(Units)
2398
+
2399
+ A, U, V = M.smith_form()
2400
+
2401
+ V = V.inverse()
2402
+ new_basis = [prod([g[j]**(V[i, j] % invs[j]) for j in range(n)]) for i in range(n)]
2403
+
2404
+ if reduce:
2405
+ combo = lambda c: self.small_residue(prod(new_basis[i] ** c[i]
2406
+ for i in range(n)))
2407
+ else:
2408
+ combo = lambda c: prod(new_basis[i] ** c[i] for i in range(n))
2409
+
2410
+ coord_ranges = [list(range(A[i, i])) for i in range(n)]
2411
+
2412
+ return xmrange_iter(coord_ranges, combo)
2413
+
2414
+ def denominator(self):
2415
+ r"""
2416
+ Return the denominator ideal of this fractional ideal. Each
2417
+ fractional ideal has a unique expression as `N/D` where `N`,
2418
+ `D` are coprime integral ideals; the denominator is `D`.
2419
+
2420
+ EXAMPLES::
2421
+
2422
+ sage: x = polygen(ZZ)
2423
+ sage: K.<i> = NumberField(x^2 + 1)
2424
+ sage: I = K.ideal((3+4*i)/5); I
2425
+ Fractional ideal (4/5*i + 3/5)
2426
+ sage: I.denominator()
2427
+ Fractional ideal (-2*i - 1)
2428
+ sage: I.numerator()
2429
+ Fractional ideal (2*i - 1)
2430
+ sage: I.numerator().is_integral() and I.denominator().is_integral()
2431
+ True
2432
+ sage: I.numerator() + I.denominator() == K.unit_ideal()
2433
+ True
2434
+ sage: I.numerator()/I.denominator() == I
2435
+ True
2436
+ """
2437
+ try:
2438
+ return self._denom_ideal
2439
+ except AttributeError:
2440
+ pass
2441
+ self._denom_ideal = (self + self.number_field().unit_ideal())**(-1)
2442
+ return self._denom_ideal
2443
+
2444
+ def numerator(self):
2445
+ r"""
2446
+ Return the numerator ideal of this fractional ideal.
2447
+
2448
+ Each fractional ideal has a unique expression as `N/D` where `N`,
2449
+ `D` are coprime integral ideals. The numerator is `N`.
2450
+
2451
+ EXAMPLES::
2452
+
2453
+ sage: x = polygen(ZZ)
2454
+ sage: K.<i> = NumberField(x^2 + 1)
2455
+ sage: I = K.ideal((3+4*i)/5); I
2456
+ Fractional ideal (4/5*i + 3/5)
2457
+ sage: I.denominator()
2458
+ Fractional ideal (-2*i - 1)
2459
+ sage: I.numerator()
2460
+ Fractional ideal (2*i - 1)
2461
+ sage: I.numerator().is_integral() and I.denominator().is_integral()
2462
+ True
2463
+ sage: I.numerator() + I.denominator() == K.unit_ideal()
2464
+ True
2465
+ sage: I.numerator()/I.denominator() == I
2466
+ True
2467
+ """
2468
+ try:
2469
+ return self._num_ideal
2470
+ except AttributeError:
2471
+ pass
2472
+ self._num_ideal = self * self.denominator()
2473
+ return self._num_ideal
2474
+
2475
+ def is_coprime(self, other):
2476
+ """
2477
+ Return ``True`` if this ideal is coprime to ``other``, else ``False``.
2478
+
2479
+ INPUT:
2480
+
2481
+ - ``other`` -- another ideal of the same field, or generators
2482
+ of an ideal
2483
+
2484
+ OUTPUT: ``True`` if ``self`` and ``other`` are coprime, else ``False``
2485
+
2486
+ .. NOTE::
2487
+
2488
+ This function works for fractional ideals as well as
2489
+ integral ideals.
2490
+
2491
+ AUTHOR: John Cremona
2492
+
2493
+ EXAMPLES::
2494
+
2495
+ sage: x = polygen(ZZ)
2496
+ sage: K.<i> = NumberField(x^2 + 1)
2497
+ sage: I = K.ideal(2 + i)
2498
+ sage: J = K.ideal(2 - i)
2499
+ sage: I.is_coprime(J)
2500
+ True
2501
+ sage: (I^-1).is_coprime(J^3)
2502
+ True
2503
+ sage: I.is_coprime(5)
2504
+ False
2505
+ sage: I.is_coprime(6 + i)
2506
+ True
2507
+
2508
+ See :issue:`4536`::
2509
+
2510
+ sage: E.<a> = NumberField(x^5 + 7*x^4 + 18*x^2 + x - 3)
2511
+ sage: i,j,k = [u[0] for u in factor(3*E)]
2512
+ sage: (i/j).is_coprime(j/k)
2513
+ False
2514
+ sage: (j/k).is_coprime(j/k)
2515
+ False
2516
+
2517
+ sage: F.<a, b> = NumberField([x^2 - 2, x^2 - 3])
2518
+ sage: F.ideal(3 - a*b).is_coprime(F.ideal(3))
2519
+ False
2520
+ """
2521
+ # Catch invalid inputs by making sure that we can make an ideal out of other.
2522
+ K = self.number_field()
2523
+ one = K.unit_ideal()
2524
+ other = K.ideal(other)
2525
+ if self.is_integral() and other.is_integral():
2526
+ if gcd(ZZ(self.absolute_norm()), ZZ(other.absolute_norm())) == 1:
2527
+ return True
2528
+ else:
2529
+ return self+other == one
2530
+ # This special case is necessary since the zero ideal is not a
2531
+ # fractional ideal!
2532
+ if other.absolute_norm() == 0:
2533
+ return self == one
2534
+ D1 = self.denominator()
2535
+ N1 = self.numerator()
2536
+ D2 = other.denominator()
2537
+ N2 = other.numerator()
2538
+ return N1+N2 == one and N1+D2 == one and D1+N2 == one and D1+D2 == one
2539
+
2540
+ def idealcoprime(self, J):
2541
+ """
2542
+ Return `l` such that ``l*self`` is coprime to `J`.
2543
+
2544
+ INPUT:
2545
+
2546
+ - ``J`` -- another integral ideal of the same field as ``self``, which
2547
+ must also be integral
2548
+
2549
+ OUTPUT: an element `l` such that ``l*self`` is coprime to the ideal `J`
2550
+
2551
+ .. TODO::
2552
+
2553
+ Extend the implementation to non-integral ideals.
2554
+
2555
+ EXAMPLES::
2556
+
2557
+ sage: x = polygen(ZZ)
2558
+ sage: k.<a> = NumberField(x^2 + 23)
2559
+ sage: A = k.ideal(a + 1)
2560
+ sage: B = k.ideal(3)
2561
+ sage: A.is_coprime(B)
2562
+ False
2563
+ sage: lam = A.idealcoprime(B)
2564
+ sage: lam # representation depends, not tested
2565
+ -1/6*a + 1/6
2566
+ sage: (lam*A).is_coprime(B)
2567
+ True
2568
+
2569
+ ALGORITHM: Uses Pari function :pari:`idealcoprime`.
2570
+
2571
+ TESTS:
2572
+
2573
+ Check the above doctests, where the representation
2574
+ depends on the PARI version::
2575
+
2576
+ sage: k.<a> = NumberField(x^2 + 23)
2577
+ sage: A = k.ideal(a + 1)
2578
+ sage: B = k.ideal(3)
2579
+ sage: lam = A.idealcoprime(B)
2580
+ sage: lam in (-1/6*a + 1/6, 1/6*a - 1/6)
2581
+ True
2582
+ """
2583
+ if not (self.is_integral() and J.is_integral()):
2584
+ raise ValueError("Both ideals must be integral.")
2585
+
2586
+ k = self.number_field()
2587
+ # Catch invalid inputs by making sure that J is an ideal of the same field as self:
2588
+ assert k == J.number_field()
2589
+ l = k.pari_nf().idealcoprime(self.pari_hnf(), J.pari_hnf())
2590
+ return k(l)
2591
+
2592
+ def small_residue(self, f):
2593
+ r"""
2594
+ Given an element `f` of the ambient number field, return an
2595
+ element `g` such that `f - g` belongs to the ideal ``self`` (which
2596
+ must be integral), and `g` is small.
2597
+
2598
+ .. NOTE::
2599
+
2600
+ The reduced representative returned is not uniquely determined.
2601
+
2602
+ ALGORITHM: Uses PARI function :pari:`nfeltreduce`.
2603
+
2604
+ EXAMPLES:
2605
+
2606
+ ::
2607
+
2608
+ sage: x = polygen(ZZ)
2609
+ sage: k.<a> = NumberField(x^2 + 5)
2610
+ sage: I = k.ideal(a)
2611
+ sage: I.small_residue(14)
2612
+ 4
2613
+
2614
+ ::
2615
+
2616
+ sage: K.<a> = NumberField(x^5 + 7*x^4 + 18*x^2 + x - 3)
2617
+ sage: I = K.ideal(5)
2618
+ sage: I.small_residue(a^2 -13)
2619
+ a^2 + 5*a - 3
2620
+ """
2621
+ if not self.is_integral():
2622
+ raise ValueError("The ideal must be integral")
2623
+ k = self.number_field()
2624
+ return k(k.pari_nf().nfeltreduce(f, self.pari_hnf()))
2625
+
2626
+ def _pari_bid_(self, flag=1):
2627
+ """
2628
+ Return the PARI structure ``bid`` associated to the ideal ``self``.
2629
+
2630
+ INPUT:
2631
+
2632
+ - ``flag`` -- when ``flag=2`` it computes the generators of the group
2633
+ `(O_K/I)^*`, which takes more time. By default
2634
+ ``flag=1`` (no generators are computed).
2635
+
2636
+ OUTPUT: the PARI special structure ``bid``
2637
+
2638
+ EXAMPLES::
2639
+
2640
+ sage: x = polygen(ZZ)
2641
+ sage: k.<a> = NumberField(x^4 + 13)
2642
+ sage: I = k.ideal(2, a^2 + 1)
2643
+ sage: hasattr(I, '_bid')
2644
+ False
2645
+ sage: bid = I._pari_bid_()
2646
+ sage: hasattr(I, '_bid')
2647
+ True
2648
+ sage: bid.getattr('clgp')
2649
+ [2, [2]]
2650
+ """
2651
+ from cypari2.handle_error import PariError
2652
+ try:
2653
+ bid = self._bid
2654
+ if flag == 2:
2655
+ # Try to access generators, we get PariError if this fails.
2656
+ bid.bid_get_gen()
2657
+ except (AttributeError, PariError):
2658
+ k = self.number_field()
2659
+ bid = k.pari_nf().idealstar(self.pari_hnf(), flag)
2660
+ self._bid = bid
2661
+ return bid
2662
+
2663
+ def idealstar(self, flag=1):
2664
+ r"""
2665
+ Return the finite abelian group `(O_K/I)^*`, where `I` is the ideal ``self``
2666
+ of the number field `K`, and `O_K` is the ring of integers of `K`.
2667
+
2668
+ INPUT:
2669
+
2670
+ - ``flag`` -- integer (default: 1); when ``flag==2``, it also
2671
+ computes the generators of the group `(O_K/I)^*`, which
2672
+ takes more time. By default ``flag`` is 1 (no generators are
2673
+ computed). In both cases the special PARI structure ``bid``
2674
+ is computed as well. If ``flag`` is 0 (deprecated) it computes
2675
+ only the group structure of `(O_K/I)^*` (with generators)
2676
+ and not the special ``bid`` structure.
2677
+
2678
+ OUTPUT:
2679
+
2680
+ The finite abelian group `(O_K/I)^*`.
2681
+
2682
+ .. NOTE::
2683
+
2684
+ Uses the PARI function :pari:`idealstar`. The PARI function outputs
2685
+ a special ``bid`` structure which is stored in the internal
2686
+ field ``_bid`` of the ideal (when ``flag`` = 1,2). The special structure
2687
+ ``bid`` is used in the PARI function :pari:`ideallog`
2688
+ to compute discrete logarithms.
2689
+
2690
+ EXAMPLES::
2691
+
2692
+ sage: x = polygen(ZZ)
2693
+ sage: k.<a> = NumberField(x^3 - 11)
2694
+ sage: A = k.ideal(5)
2695
+ sage: G = A.idealstar(); G
2696
+ Multiplicative Abelian group isomorphic to C24 x C4
2697
+ sage: G.gens()
2698
+ (f0, f1)
2699
+
2700
+ sage: G = A.idealstar(2)
2701
+ sage: G.gens()
2702
+ (f0, f1)
2703
+ sage: G.gens_values() # random output
2704
+ (2*a^2 - 1, 2*a^2 + 2*a - 2)
2705
+ sage: all(G.gen(i).value() in k for i in range(G.ngens()))
2706
+ True
2707
+
2708
+ TESTS::
2709
+
2710
+ sage: k.<a> = NumberField(x^2 + 1)
2711
+ sage: k.ideal(a+1).idealstar(2)
2712
+ Trivial Abelian group
2713
+
2714
+ ALGORITHM: Uses Pari function :pari:`idealstar`
2715
+ """
2716
+ k = self.number_field()
2717
+ if flag == 0 and not hasattr(self, '_bid'):
2718
+ G = k.pari_nf().idealstar(self.pari_hnf(), 0)
2719
+ else:
2720
+ G = self._pari_bid_(flag)
2721
+ inv = [ZZ(c) for c in G.bid_get_cyc()]
2722
+
2723
+ if flag == 2 or flag == 0:
2724
+ from sage.groups.abelian_gps.values import AbelianGroupWithValues
2725
+ g = G.bid_get_gen()
2726
+ AG = AbelianGroupWithValues(tuple(map(k, g)), inv, values_group=k)
2727
+ else:
2728
+ from sage.groups.abelian_gps.abelian_group import AbelianGroup
2729
+ AG = AbelianGroup(inv)
2730
+ return AG
2731
+
2732
+ def ideallog(self, x, gens=None, check=True):
2733
+ r"""
2734
+ Return the discrete logarithm of `x` with respect to the generators
2735
+ given in the ``bid`` structure of the ideal ``self``, or with respect to
2736
+ the generators ``gens`` if these are given.
2737
+
2738
+ INPUT:
2739
+
2740
+ - ``x`` -- a nonzero element of the number field of ``self``,
2741
+ which must have valuation equal to 0 at all prime ideals in
2742
+ the support of the ideal ``self``
2743
+ - ``gens`` -- list of elements of the number field which generate `(R
2744
+ / I)^*`, where `R` is the ring of integers of the field and `I` is
2745
+ this ideal, or ``None``. If ``None``, use the generators calculated
2746
+ by :meth:`~idealstar`.
2747
+ - ``check`` -- if ``True``, do a consistency check on the results.
2748
+ Ignored if ``gens`` is ``None``.
2749
+
2750
+ OUTPUT:
2751
+
2752
+ a list of nonnegative integers `(x_i)` such that `x =
2753
+ \prod_i g_i^{x_i}` in `(R/I)^*`, where `x_i` are the generators, and
2754
+ the list `(x_i)` is lexicographically minimal with respect to this
2755
+ requirement. If the `x_i` generate independent cyclic factors of
2756
+ order `d_i`, as is the case for the default generators calculated by
2757
+ :meth:`~idealstar`, this just means that `0 \le x_i < d_i`.
2758
+
2759
+ A :exc:`ValueError` will be raised if the elements specified in ``gens``
2760
+ do not in fact generate the unit group (even if the element `x` is in
2761
+ the subgroup they generate).
2762
+
2763
+ EXAMPLES::
2764
+
2765
+ sage: x = polygen(ZZ)
2766
+ sage: k.<a> = NumberField(x^3 - 11)
2767
+ sage: A = k.ideal(5)
2768
+ sage: G = A.idealstar(2)
2769
+ sage: l = A.ideallog(a^2 + 3)
2770
+ sage: r = G(l).value()
2771
+ sage: (a^2 + 3) - r in A
2772
+ True
2773
+ sage: A.small_residue(r) # random
2774
+ a^2 - 2
2775
+
2776
+ Examples with custom generators::
2777
+
2778
+ sage: K.<a> = NumberField(x^2 - 7)
2779
+ sage: I = K.ideal(17)
2780
+ sage: I.ideallog(a + 7, [1 + a, 2])
2781
+ [10, 3]
2782
+ sage: I.ideallog(a + 7, [2, 1 + a])
2783
+ [0, 118]
2784
+
2785
+ sage: L.<b> = NumberField(x^4 - x^3 - 7*x^2 + 3*x + 2)
2786
+ sage: J = L.ideal(-b^3 - b^2 - 2)
2787
+ sage: u = -14*b^3 + 21*b^2 + b - 1
2788
+ sage: v = 4*b^2 + 2*b - 1
2789
+ sage: J.ideallog(5 + 2*b, [u, v], check=True)
2790
+ [4, 13]
2791
+
2792
+ A non-example::
2793
+
2794
+ sage: I.ideallog(a + 7, [2])
2795
+ Traceback (most recent call last):
2796
+ ...
2797
+ ValueError: Given elements do not generate unit group --
2798
+ they generate a subgroup of index 36
2799
+
2800
+ ALGORITHM: Uses PARI function :pari:`ideallog`, and (if ``gens`` is not
2801
+ ``None``) a Hermite normal form calculation to express the result in terms
2802
+ of the generators ``gens``.
2803
+ """
2804
+ # sanitise input
2805
+
2806
+ k = self.number_field()
2807
+ if not all(k(x).valuation(p) == 0 for p, e in self.factor()):
2808
+ raise TypeError("the element must be invertible mod the ideal")
2809
+
2810
+ # calculate ideal log w.r.t. standard gens
2811
+
2812
+ #Now it is important to call _pari_bid_() with flag=2 to make sure
2813
+ #we fix a basis, since the log would be different for a different
2814
+ #choice of basis.
2815
+ L = [ZZ(_) for _ in k.pari_nf().ideallog(x, self._pari_bid_(2))]
2816
+
2817
+ if gens is None:
2818
+ return L
2819
+
2820
+ # otherwise translate answer in terms of given gens
2821
+ G = self.idealstar(2)
2822
+ invs = G.invariants()
2823
+
2824
+ from sage.matrix.constructor import matrix
2825
+ from sage.matrix.special import identity_matrix
2826
+ from sage.matrix.special import zero_matrix
2827
+ from sage.matrix.special import diagonal_matrix
2828
+ from sage.matrix.special import block_matrix
2829
+
2830
+ # We use Hermite normal form twice: once to express the standard
2831
+ # generators in terms of the new ones (independently of x) and once to
2832
+ # reduce the resulting logarithm of x so it is lexicographically
2833
+ # minimal.
2834
+
2835
+ mat = matrix(ZZ, [self.ideallog(_) for _ in gens]).augment(identity_matrix(ZZ, len(gens)))
2836
+ mat = mat.stack( diagonal_matrix(ZZ, invs).augment(zero_matrix(ZZ, len(invs), len(gens))))
2837
+ hmat = mat.hermite_form()
2838
+ A = hmat[0:len(invs), 0:len(invs)]
2839
+ if A != identity_matrix(len(invs)):
2840
+ raise ValueError("Given elements do not generate unit group -- they generate a subgroup of index %s" % A.det())
2841
+ B = hmat[0:len(invs), len(invs):]
2842
+ C = hmat[len(invs):, len(invs):]
2843
+ M = (matrix(ZZ, L) * B)
2844
+ N = block_matrix(2, 2, [[identity_matrix(1), M], [zero_matrix(len(gens), 1), C]], subdivide=False)
2845
+ ans = N.hermite_form()[0, 1:].list()
2846
+
2847
+ if check:
2848
+ from sage.rings.finite_rings.integer_mod_ring import Zmod
2849
+ Z_norm = Zmod(self.norm().numerator()) # norm is an integer ?
2850
+ t = 1
2851
+ for gi, ai in zip(gens, ans):
2852
+ t = self.reduce(t * gi**ai)
2853
+ assert t == self.reduce(x * x.denominator() * (~Z_norm(x.denominator())).lift())
2854
+
2855
+ return ans
2856
+
2857
+ def element_1_mod(self, other):
2858
+ r"""
2859
+ Return an element `r` in this ideal such that `1-r` is in ``other``.
2860
+
2861
+ An error is raised if either ideal is not integral of if they
2862
+ are not coprime.
2863
+
2864
+ INPUT:
2865
+
2866
+ - ``other`` -- another ideal of the same field, or generators
2867
+ of an ideal
2868
+
2869
+ OUTPUT: an element `r` of the ideal ``self`` such that `1-r` is in the
2870
+ ideal ``other``
2871
+
2872
+ AUTHOR: Maite Aranes (modified to use PARI's :pari:`idealaddtoone` by Francis Clarke)
2873
+
2874
+ EXAMPLES::
2875
+
2876
+ sage: x = polygen(ZZ)
2877
+ sage: K.<a> = NumberField(x^3 - 2)
2878
+ sage: A = K.ideal(a + 1); A; A.norm()
2879
+ Fractional ideal (a + 1)
2880
+ 3
2881
+ sage: B = K.ideal(a^2 - 4*a + 2); B; B.norm()
2882
+ Fractional ideal (a^2 - 4*a + 2)
2883
+ 68
2884
+ sage: r = A.element_1_mod(B); r
2885
+ -33
2886
+ sage: r in A
2887
+ True
2888
+ sage: 1 - r in B
2889
+ True
2890
+
2891
+ TESTS::
2892
+
2893
+ sage: K.<a> = NumberField(x^3 - 2)
2894
+ sage: A = K.ideal(a+1)
2895
+ sage: B = K.ideal(a^2-4*a+1); B; B.norm()
2896
+ Fractional ideal (a^2 - 4*a + 1)
2897
+ 99
2898
+ sage: A.element_1_mod(B)
2899
+ Traceback (most recent call last):
2900
+ ...
2901
+ TypeError: Fractional ideal (a + 1), Fractional ideal (a^2 - 4*a + 1) are not coprime ideals
2902
+
2903
+ sage: B = K.ideal(1/a); B
2904
+ Fractional ideal (1/2*a^2)
2905
+ sage: A.element_1_mod(B)
2906
+ Traceback (most recent call last):
2907
+ ...
2908
+ TypeError: Fractional ideal (1/2*a^2) is not an integral ideal
2909
+ """
2910
+ if not self.is_integral():
2911
+ raise TypeError("%s is not an integral ideal" % self)
2912
+
2913
+ # Catch invalid inputs by making sure that we can make an ideal out of other.
2914
+ K = self.number_field()
2915
+ other = K.ideal(other)
2916
+ if not other.is_integral():
2917
+ raise TypeError("%s is not an integral ideal" % other)
2918
+
2919
+ if not self.is_coprime(other):
2920
+ raise TypeError("%s, %s are not coprime ideals" % (self, other))
2921
+
2922
+ bnf = K.pari_bnf()
2923
+ r = bnf.idealaddtoone(self.pari_hnf(), other.pari_hnf())[0]
2924
+ return K(r)
2925
+
2926
+ def euler_phi(self):
2927
+ r"""
2928
+ Return the Euler `\varphi`-function of this integral ideal.
2929
+
2930
+ This is the order of the multiplicative group of the quotient
2931
+ modulo the ideal.
2932
+
2933
+ An error is raised if the ideal is not integral.
2934
+
2935
+ EXAMPLES::
2936
+
2937
+ sage: x = polygen(ZZ)
2938
+ sage: K.<i> = NumberField(x^2 + 1)
2939
+ sage: I = K.ideal(2 + i)
2940
+ sage: [r for r in I.residues() if I.is_coprime(r)]
2941
+ [-2*i, -i, i, 2*i]
2942
+ sage: I.euler_phi()
2943
+ 4
2944
+ sage: J = I^3
2945
+ sage: J.euler_phi()
2946
+ 100
2947
+ sage: len([r for r in J.residues() if J.is_coprime(r)])
2948
+ 100
2949
+ sage: J = K.ideal(3 - 2*i)
2950
+ sage: I.is_coprime(J)
2951
+ True
2952
+ sage: I.euler_phi()*J.euler_phi() == (I*J).euler_phi()
2953
+ True
2954
+ sage: L.<b> = K.extension(x^2 - 7)
2955
+ sage: L.ideal(3).euler_phi()
2956
+ 64
2957
+ """
2958
+ if not self.is_integral():
2959
+ raise ValueError("euler_phi only defined for integral ideals")
2960
+ it = ((p.absolute_norm(), e) for p, e in self.factor())
2961
+ return prod((np - 1) * np**(e - 1) for np, e in it)
2962
+
2963
+ def prime_to_S_part(self, S):
2964
+ r"""
2965
+ Return the part of this fractional ideal which is coprime to
2966
+ the prime ideals in the list `S`.
2967
+
2968
+ .. NOTE::
2969
+
2970
+ This function assumes that `S` is a list of prime ideals,
2971
+ but does not check this. This function will fail if `S` is
2972
+ not a list of prime ideals.
2973
+
2974
+ INPUT:
2975
+
2976
+ - ``S`` -- list of prime ideals
2977
+
2978
+ OUTPUT:
2979
+
2980
+ A fractional ideal coprime to the primes in `S`, whose prime
2981
+ factorization is that of ``self`` with the primes in `S`
2982
+ removed.
2983
+
2984
+ EXAMPLES::
2985
+
2986
+ sage: x = polygen(ZZ)
2987
+ sage: K.<a> = NumberField(x^2 - 23)
2988
+ sage: I = K.ideal(24)
2989
+ sage: S = [K.ideal(-a + 5), K.ideal(5)]
2990
+ sage: I.prime_to_S_part(S)
2991
+ Fractional ideal (3)
2992
+ sage: J = K.ideal(15)
2993
+ sage: J.prime_to_S_part(S)
2994
+ Fractional ideal (3)
2995
+
2996
+ sage: K.<a> = NumberField(x^5 - 23)
2997
+ sage: I = K.ideal(24)
2998
+ sage: S = [K.ideal(15161*a^4 + 28383*a^3 + 53135*a^2 + 99478*a + 186250),
2999
+ ....: K.ideal(2*a^4 + 3*a^3 + 4*a^2 + 15*a + 11),
3000
+ ....: K.ideal(101)]
3001
+ sage: I.prime_to_S_part(S)
3002
+ Fractional ideal (24)
3003
+ """
3004
+ a = self
3005
+ for p in S:
3006
+ n = a.valuation(p)
3007
+ a = a*p**(-n)
3008
+ return a
3009
+
3010
+ def is_S_unit(self, S):
3011
+ r"""
3012
+ Return ``True`` if this fractional ideal is a unit with respect to the list of primes `S`.
3013
+
3014
+ INPUT:
3015
+
3016
+ - ``S`` -- list of prime ideals (not checked if they are
3017
+ indeed prime)
3018
+
3019
+ .. NOTE::
3020
+
3021
+ This function assumes that `S` is a list of prime ideals,
3022
+ but does not check this. This function will fail if `S` is
3023
+ not a list of prime ideals.
3024
+
3025
+ OUTPUT:
3026
+
3027
+ ``True``, if the ideal is an `S`-unit: that is, if the valuations of
3028
+ the ideal at all primes not in `S` are zero. ``False``, otherwise.
3029
+
3030
+ EXAMPLES::
3031
+
3032
+ sage: x = polygen(ZZ)
3033
+ sage: K.<a> = NumberField(x^2 + 23)
3034
+ sage: I = K.ideal(2)
3035
+ sage: P = I.factor()[0][0]
3036
+ sage: I.is_S_unit([P])
3037
+ False
3038
+ """
3039
+ return self.prime_to_S_part(S).is_trivial()
3040
+
3041
+ def is_S_integral(self, S):
3042
+ r"""
3043
+ Return ``True`` if this fractional ideal is integral with respect to the list of primes `S`.
3044
+
3045
+ INPUT:
3046
+
3047
+ - ``S`` -- list of prime ideals (not checked if they are indeed prime)
3048
+
3049
+ .. NOTE::
3050
+
3051
+ This function assumes that `S` is a list of prime ideals,
3052
+ but does not check this. This function will fail if `S` is
3053
+ not a list of prime ideals.
3054
+
3055
+ OUTPUT:
3056
+
3057
+ ``True``, if the ideal is `S`-integral: that is, if the valuations
3058
+ of the ideal at all primes not in `S` are nonnegative. ``False``,
3059
+ otherwise.
3060
+
3061
+ EXAMPLES::
3062
+
3063
+ sage: x = polygen(ZZ)
3064
+ sage: K.<a> = NumberField(x^2 + 23)
3065
+ sage: I = K.ideal(1/2)
3066
+ sage: P = K.ideal(2, 1/2*a - 1/2)
3067
+ sage: I.is_S_integral([P])
3068
+ False
3069
+
3070
+ sage: J = K.ideal(1/5)
3071
+ sage: J.is_S_integral([K.ideal(5)])
3072
+ True
3073
+ """
3074
+ if self.is_integral():
3075
+ return True
3076
+ return self.prime_to_S_part(S).is_integral()
3077
+
3078
+ def prime_to_idealM_part(self, M):
3079
+ r"""
3080
+ Version for integral ideals of the ``prime_to_m_part`` function over `\ZZ`.
3081
+ Return the largest divisor of ``self`` that is coprime to the ideal `M`.
3082
+
3083
+ INPUT:
3084
+
3085
+ - ``M`` -- an integral ideal of the same field, or generators of an ideal
3086
+
3087
+ OUTPUT: an ideal which is the largest divisor of ``self`` that is coprime to `M`
3088
+
3089
+ AUTHOR: Maite Aranes
3090
+
3091
+ EXAMPLES::
3092
+
3093
+ sage: x = polygen(ZZ)
3094
+ sage: k.<a> = NumberField(x^2 + 23)
3095
+ sage: I = k.ideal(a + 1)
3096
+ sage: M = k.ideal(2, 1/2*a - 1/2)
3097
+ sage: J = I.prime_to_idealM_part(M); J
3098
+ Fractional ideal (12, 1/2*a + 13/2)
3099
+ sage: J.is_coprime(M)
3100
+ True
3101
+
3102
+ sage: J = I.prime_to_idealM_part(2); J
3103
+ Fractional ideal (3, 1/2*a + 1/2)
3104
+ sage: J.is_coprime(M)
3105
+ True
3106
+ """
3107
+ # Catch invalid inputs by making sure that we can make an ideal out of M.
3108
+ k = self.number_field()
3109
+ M = k.ideal(M)
3110
+
3111
+ if not self.is_integral or not M.is_integral():
3112
+ raise TypeError("prime_to_idealM_part defined only for integral ideals")
3113
+
3114
+ if self.is_coprime(M):
3115
+ return self
3116
+ G = self + M
3117
+ I = self
3118
+ while not G.is_trivial():
3119
+ I = I/G
3120
+ G = I + G
3121
+ return I
3122
+
3123
+ def _p_quotient(self, p):
3124
+ """
3125
+ This is an internal technical function that is used for example for
3126
+ computing the quotient of the ring of integers by a prime ideal.
3127
+
3128
+ INPUT:
3129
+
3130
+ - ``p`` -- a prime number contained in ``self``
3131
+
3132
+ OUTPUT:
3133
+
3134
+ - ``V`` -- a vector space of characteristic `p`
3135
+ - ``quo`` -- a partially defined quotient homomorphism from the
3136
+ ambient number field to `V`
3137
+ - ``lift`` -- a section of ``quo``
3138
+
3139
+ EXAMPLES::
3140
+
3141
+ sage: x = polygen(ZZ)
3142
+ sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order()
3143
+ sage: I = K.factor(3)[0][0]
3144
+ sage: Q, quo, lift = I._p_quotient(3); Q
3145
+ Vector space quotient V/W of dimension 2 over Finite Field of size 3 where
3146
+ V: Vector space of dimension 2 over Finite Field of size 3
3147
+ W: Vector space of degree 2 and dimension 0 over Finite Field of size 3
3148
+ Basis matrix:
3149
+ []
3150
+
3151
+ We do an example with a split prime and show both the quo
3152
+ and lift maps::
3153
+
3154
+ sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order()
3155
+ sage: I = K.factor(5)[0][0]
3156
+ sage: Q, quo, lift = I._p_quotient(5)
3157
+ sage: lift(quo(i))
3158
+ 3
3159
+ sage: lift(quo(i)) - i in I
3160
+ True
3161
+ sage: quo(lift(Q.0))
3162
+ (1)
3163
+ sage: Q.0
3164
+ (1)
3165
+ sage: Q
3166
+ Vector space quotient V/W of dimension 1 over Finite Field of size 5 where
3167
+ V: Vector space of dimension 2 over Finite Field of size 5
3168
+ W: Vector space of degree 2 and dimension 1 over Finite Field of size 5
3169
+ Basis matrix:
3170
+ [1 3]
3171
+ sage: quo
3172
+ Partially defined quotient map
3173
+ from Number Field in i with defining polynomial x^2 + 1
3174
+ to an explicit vector space representation for the quotient of
3175
+ the ring of integers by (p,I) for the ideal I=Fractional ideal (2*i - 1).
3176
+ sage: lift
3177
+ Lifting map
3178
+ to Gaussian Integers generated by i in Number Field in i with defining polynomial x^2 + 1
3179
+ from quotient of integers by Fractional ideal (2*i - 1)
3180
+ """
3181
+ return quotient_char_p(self, p)
3182
+
3183
+ def residue_field(self, names=None):
3184
+ r"""
3185
+ Return the residue class field of this fractional ideal, which
3186
+ must be prime.
3187
+
3188
+ EXAMPLES::
3189
+
3190
+ sage: x = polygen(ZZ)
3191
+ sage: K.<a> = NumberField(x^3 - 7)
3192
+ sage: P = K.ideal(29).factor()[0][0]
3193
+ sage: P.residue_field()
3194
+ Residue field in abar of Fractional ideal (2*a^2 + 3*a - 10)
3195
+ sage: P.residue_field('z')
3196
+ Residue field in z of Fractional ideal (2*a^2 + 3*a - 10)
3197
+
3198
+ Another example::
3199
+
3200
+ sage: K.<a> = NumberField(x^3 - 7)
3201
+ sage: P = K.ideal(389).factor()[0][0]; P
3202
+ Fractional ideal (389, a^2 - 44*a - 9)
3203
+ sage: P.residue_class_degree()
3204
+ 2
3205
+ sage: P.residue_field()
3206
+ Residue field in abar of Fractional ideal (389, a^2 - 44*a - 9)
3207
+ sage: P.residue_field('z')
3208
+ Residue field in z of Fractional ideal (389, a^2 - 44*a - 9)
3209
+ sage: FF.<w> = P.residue_field()
3210
+ sage: FF
3211
+ Residue field in w of Fractional ideal (389, a^2 - 44*a - 9)
3212
+ sage: FF((a+1)^390)
3213
+ 36
3214
+ sage: FF(a)
3215
+ w
3216
+
3217
+ An example of reduction maps to the residue field: these are defined on
3218
+ the whole valuation ring, i.e. the subring of the number field
3219
+ consisting of elements with nonnegative valuation. This shows that the
3220
+ issue raised in :issue:`1951` has been fixed::
3221
+
3222
+ sage: K.<i> = NumberField(x^2 + 1)
3223
+ sage: P1, P2 = [g[0] for g in K.factor(5)]; P1, P2
3224
+ (Fractional ideal (2*i - 1), Fractional ideal (-2*i - 1))
3225
+ sage: a = 1/(1+2*i)
3226
+ sage: F1, F2 = [g.residue_field() for g in [P1, P2]]; F1, F2
3227
+ (Residue field of Fractional ideal (2*i - 1),
3228
+ Residue field of Fractional ideal (-2*i - 1))
3229
+ sage: a.valuation(P1)
3230
+ 0
3231
+ sage: F1(i/7)
3232
+ 4
3233
+ sage: F1(a)
3234
+ 3
3235
+ sage: a.valuation(P2)
3236
+ -1
3237
+ sage: F2(a)
3238
+ Traceback (most recent call last):
3239
+ ...
3240
+ ZeroDivisionError: Cannot reduce field element -2/5*i + 1/5
3241
+ modulo Fractional ideal (-2*i - 1): it has negative valuation
3242
+
3243
+ An example with a relative number field::
3244
+
3245
+ sage: L.<a,b> = NumberField([x^2 + 1, x^2 - 5])
3246
+ sage: p = L.ideal((-1/2*b - 1/2)*a + 1/2*b - 1/2)
3247
+ sage: R = p.residue_field(); R
3248
+ Residue field in abar of Fractional ideal ((-1/2*b - 1/2)*a + 1/2*b - 1/2)
3249
+ sage: R.cardinality()
3250
+ 9
3251
+ sage: R(17)
3252
+ 2
3253
+ sage: R((a + b)/17)
3254
+ abar
3255
+ sage: R(1/b)
3256
+ 2*abar
3257
+
3258
+ We verify that :issue:`8721` is fixed::
3259
+
3260
+ sage: L.<a, b> = NumberField([x^2 - 3, x^2 - 5])
3261
+ sage: L.ideal(a).residue_field()
3262
+ Residue field in abar of Fractional ideal (a)
3263
+ """
3264
+ if not self.is_prime():
3265
+ raise ValueError("The ideal must be prime")
3266
+ return self.number_field().residue_field(self, names=names)
3267
+
3268
+ def residue_class_degree(self):
3269
+ r"""
3270
+ Return the residue class degree of this fractional ideal,
3271
+ assuming it is prime. Otherwise, raise a :exc:`ValueError`.
3272
+
3273
+ The residue class degree of a prime ideal `I` is the degree of
3274
+ the extension `O_K/I` of its prime subfield.
3275
+
3276
+ EXAMPLES::
3277
+
3278
+ sage: x = polygen(ZZ)
3279
+ sage: K.<a> = NumberField(x^5 + 2); K
3280
+ Number Field in a with defining polynomial x^5 + 2
3281
+ sage: f = K.factor(19); f
3282
+ (Fractional ideal (a^2 + a - 3))
3283
+ * (Fractional ideal (2*a^4 + a^2 - 2*a + 1))
3284
+ * (Fractional ideal (a^2 + a - 1))
3285
+ sage: [i.residue_class_degree() for i, _ in f]
3286
+ [2, 2, 1]
3287
+ """
3288
+ return ZZ(self.pari_prime().pr_get_f())
3289
+
3290
+ def ray_class_number(self):
3291
+ r"""
3292
+ Return the order of the ray class group modulo this ideal. This is a
3293
+ wrapper around PARI's :pari:`bnrclassno` function.
3294
+
3295
+ EXAMPLES::
3296
+
3297
+ sage: K.<z> = QuadraticField(-23)
3298
+ sage: p = K.primes_above(3)[0]
3299
+ sage: p.ray_class_number()
3300
+ 3
3301
+
3302
+ sage: x = polygen(K)
3303
+ sage: L.<w> = K.extension(x^3 - z)
3304
+ sage: I = L.ideal(5)
3305
+ sage: I.ray_class_number()
3306
+ 5184
3307
+ """
3308
+ bid = self._pari_bid_()
3309
+ return ZZ(self.number_field().pari_bnf().bnrclassno(bid))
3310
+
3311
+
3312
+ def is_NumberFieldFractionalIdeal(x):
3313
+ """
3314
+ Return ``True`` if `x` is a fractional ideal of a number field.
3315
+
3316
+ EXAMPLES::
3317
+
3318
+ sage: from sage.rings.number_field.number_field_ideal import is_NumberFieldFractionalIdeal
3319
+ sage: is_NumberFieldFractionalIdeal(2/3)
3320
+ doctest:warning...
3321
+ DeprecationWarning: The function is_NumberFieldFractionalIdeal is deprecated;
3322
+ use 'isinstance(..., NumberFieldFractionalIdeal)' instead.
3323
+ See https://github.com/sagemath/sage/issues/38124 for details.
3324
+ False
3325
+ sage: is_NumberFieldFractionalIdeal(ideal(5))
3326
+ False
3327
+ sage: x = polygen(ZZ)
3328
+ sage: k.<a> = NumberField(x^2 + 2)
3329
+ sage: I = k.ideal([a + 1]); I
3330
+ Fractional ideal (a + 1)
3331
+ sage: is_NumberFieldFractionalIdeal(I)
3332
+ True
3333
+ sage: Z = k.ideal(0); Z
3334
+ Ideal (0) of Number Field in a with defining polynomial x^2 + 2
3335
+ sage: is_NumberFieldFractionalIdeal(Z)
3336
+ False
3337
+ """
3338
+ from sage.misc.superseded import deprecation
3339
+ deprecation(38124,
3340
+ "The function is_NumberFieldFractionalIdeal is deprecated; "
3341
+ "use 'isinstance(..., NumberFieldFractionalIdeal)' instead.")
3342
+ return isinstance(x, NumberFieldFractionalIdeal)
3343
+
3344
+
3345
+ class QuotientMap:
3346
+ """
3347
+ Class to hold data needed by quotient maps from number field
3348
+ orders to residue fields. These are only partial maps: the exact
3349
+ domain is the appropriate valuation ring. For examples, see
3350
+ :meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.residue_field`.
3351
+ """
3352
+ def __init__(self, K, M_OK_change, Q, I):
3353
+ """
3354
+ Initialize this QuotientMap.
3355
+
3356
+ EXAMPLES::
3357
+
3358
+ sage: x = polygen(ZZ)
3359
+ sage: K.<a> = NumberField(x^3 + 4)
3360
+ sage: f = K.ideal(1 + a^2/2).residue_field().reduction_map(); f # indirect doctest
3361
+ Partially defined reduction map:
3362
+ From: Number Field in a with defining polynomial x^3 + 4
3363
+ To: Residue field of Fractional ideal (1/2*a^2 + 1)
3364
+ sage: f.__class__
3365
+ <class 'sage.rings.finite_rings.residue_field.ReductionMap'>
3366
+ """
3367
+ self.__M_OK_change = M_OK_change
3368
+ self.__Q = Q
3369
+ self.__K = K
3370
+ self.__I = I
3371
+ self.__L, self.__from_L, self.__to_L = K.absolute_vector_space()
3372
+
3373
+ def __call__(self, x):
3374
+ """
3375
+ Apply this QuotientMap to an element of the number field.
3376
+
3377
+ INPUT:
3378
+
3379
+ - ``x`` -- an element of the field
3380
+
3381
+ EXAMPLES::
3382
+
3383
+ sage: x = polygen(ZZ)
3384
+ sage: K.<a> = NumberField(x^3 + 4)
3385
+ sage: f = K.ideal(1 + a^2/2).residue_field().reduction_map()
3386
+ sage: f(a)
3387
+ 2
3388
+ """
3389
+ v = self.__to_L(x)
3390
+ w = v * self.__M_OK_change
3391
+ return self.__Q( list(w) )
3392
+
3393
+ def __repr__(self):
3394
+ r"""
3395
+ Return a string representation of this QuotientMap.
3396
+
3397
+ EXAMPLES::
3398
+
3399
+ sage: x = polygen(ZZ)
3400
+ sage: K.<a> = NumberField(x^3 + 4)
3401
+ sage: f = K.ideal(1 + a^2/2).residue_field().reduction_map()
3402
+ sage: repr(f)
3403
+ 'Partially defined reduction map:\n From: Number Field in a with defining polynomial x^3 + 4\n To: Residue field of Fractional ideal (1/2*a^2 + 1)'
3404
+ """
3405
+ return "Partially defined quotient map from %s to an explicit vector space representation for the quotient of the ring of integers by (p,I) for the ideal I=%s." % (self.__K, self.__I)
3406
+
3407
+
3408
+ class LiftMap:
3409
+ """
3410
+ Class to hold data needed by lifting maps from residue fields to
3411
+ number field orders.
3412
+ """
3413
+ def __init__(self, OK, M_OK_map, Q, I):
3414
+ """
3415
+ Initialize this LiftMap.
3416
+
3417
+ EXAMPLES::
3418
+
3419
+ sage: x = polygen(ZZ)
3420
+ sage: K.<a> = NumberField(x^3 + 4)
3421
+ sage: I = K.ideal(1 + a^2/2)
3422
+ sage: f = I.residue_field().lift_map()
3423
+ sage: f.__class__
3424
+ <class 'sage.rings.finite_rings.residue_field.LiftingMap'>
3425
+ """
3426
+ self.__I = I
3427
+ self.__OK = OK
3428
+ self.__Q = Q
3429
+ self.__M_OK_map = M_OK_map
3430
+ self.__Kgen = OK.number_field().absolute_generator()
3431
+
3432
+ def __call__(self, x):
3433
+ """
3434
+ Apply this LiftMap to an element of the residue field.
3435
+
3436
+ EXAMPLES::
3437
+
3438
+ sage: x = polygen(ZZ)
3439
+ sage: K.<a> = NumberField(x^3 + 4)
3440
+ sage: R = K.ideal(1 + a^2/2).residue_field()
3441
+ sage: f = R.lift_map()
3442
+ sage: f(R(a/17))
3443
+ 1
3444
+
3445
+ A relative example, which used to fail but is fixed by :issue:`8721`::
3446
+
3447
+ sage: L.<a, b> = NumberField([x^2 + 1, x^2 - 5])
3448
+ sage: p = L.ideal(2*a + 3)
3449
+ sage: V, to_V, from_V = p._p_quotient(13)
3450
+ sage: from_V(V.0)
3451
+ (-1/2*b + 7/2)*a - 1/2*b + 3/2
3452
+ """
3453
+ # This lifts to OK tensor F_p
3454
+ v = self.__Q.lift(x)
3455
+ # This lifts to ZZ^n (= OK)
3456
+ w = v.lift()
3457
+ # Write back in terms of K
3458
+ z = (w * self.__M_OK_map).list()
3459
+ return self.__OK(sum(z[i] * self.__Kgen ** i for i in range(len(z))))
3460
+
3461
+ def __repr__(self):
3462
+ r"""
3463
+ Return a string representation of this QuotientMap.
3464
+
3465
+ EXAMPLES::
3466
+
3467
+ sage: x = polygen(ZZ)
3468
+ sage: K.<a> = NumberField(x^3 + 4)
3469
+ sage: R = K.ideal(1 + a^2/2).residue_field()
3470
+ sage: repr(R.lift_map())
3471
+ 'Lifting map:\n From: Residue field of Fractional ideal (1/2*a^2 + 1)\n To: Maximal Order generated by [a, 1/2*a^2] in Number Field in a with defining polynomial x^3 + 4'
3472
+ """
3473
+ return "Lifting map to %s from quotient of integers by %s" % (self.__OK, self.__I)
3474
+
3475
+
3476
+ def quotient_char_p(I, p):
3477
+ r"""
3478
+ Given an integral ideal `I` that contains a prime number `p`, compute
3479
+ a vector space `V = (O_K \mod p) / (I \mod p)`, along with a
3480
+ homomorphism `O_K \to V` and a section `V \to O_K`.
3481
+
3482
+ EXAMPLES::
3483
+
3484
+ sage: from sage.rings.number_field.number_field_ideal import quotient_char_p
3485
+
3486
+ sage: x = polygen(ZZ)
3487
+ sage: K.<i> = NumberField(x^2 + 1); O = K.maximal_order(); I = K.fractional_ideal(15)
3488
+ sage: quotient_char_p(I, 5)[0]
3489
+ Vector space quotient V/W of dimension 2 over Finite Field of size 5 where
3490
+ V: Vector space of dimension 2 over Finite Field of size 5
3491
+ W: Vector space of degree 2 and dimension 0 over Finite Field of size 5
3492
+ Basis matrix:
3493
+ []
3494
+ sage: quotient_char_p(I, 3)[0]
3495
+ Vector space quotient V/W of dimension 2 over Finite Field of size 3 where
3496
+ V: Vector space of dimension 2 over Finite Field of size 3
3497
+ W: Vector space of degree 2 and dimension 0 over Finite Field of size 3
3498
+ Basis matrix:
3499
+ []
3500
+
3501
+ sage: I = K.factor(13)[0][0]; I
3502
+ Fractional ideal (3*i + 2)
3503
+ sage: I.residue_class_degree()
3504
+ 1
3505
+ sage: quotient_char_p(I, 13)[0]
3506
+ Vector space quotient V/W of dimension 1 over Finite Field of size 13 where
3507
+ V: Vector space of dimension 2 over Finite Field of size 13
3508
+ W: Vector space of degree 2 and dimension 1 over Finite Field of size 13
3509
+ Basis matrix:
3510
+ [1 8]
3511
+ """
3512
+ if not I.is_integral():
3513
+ raise ValueError("I must be an integral ideal.")
3514
+
3515
+ K = I.number_field()
3516
+ OK = K.maximal_order() # will in the long run only really need a p-maximal order.
3517
+ M_OK = OK.free_module()
3518
+ M_I = I.free_module()
3519
+
3520
+ # Now we have to quite explicitly find a way to compute
3521
+ # with OK / I viewed as a quotient of two F_p vector spaces,
3522
+ # and itself viewed as an F_p vector space.
3523
+
3524
+ # Step 1. Write each basis vector for I (as a ZZ-module)
3525
+ # in terms of the basis for OK.
3526
+
3527
+ M_OK_mat = M_OK.basis_matrix()
3528
+ M_OK_change = M_OK_mat**(-1)
3529
+ B_I_in_terms_of_M = M_I.basis_matrix() * M_OK_change
3530
+
3531
+ # Step 2. Define "M_OK mod p" to just be (F_p)^n and
3532
+ # "M_I mod p" to be the reduction mod p of the elements
3533
+ # compute in step 1.
3534
+
3535
+ n = K.absolute_degree()
3536
+ k = FiniteField(p)
3537
+ M_OK_modp = k**n
3538
+ B_mod = B_I_in_terms_of_M.change_ring(k)
3539
+ M_I_modp = M_OK_modp.span(B_mod.row_space())
3540
+
3541
+ # Step 3. Compute the quotient of these two F_p vector space.
3542
+
3543
+ Q = M_OK_modp.quotient(M_I_modp)
3544
+
3545
+ # Step 4. Now we get the maps we need from the above data.
3546
+
3547
+ K_to_Q = QuotientMap(K, M_OK_change, Q, I)
3548
+ Q_to_OK = LiftMap(OK, M_OK_mat, Q, I)
3549
+
3550
+ return Q, K_to_Q, Q_to_OK