passagemath-flint 10.6.1rc10__cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_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 (360) hide show
  1. passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
  2. passagemath_flint-10.6.1rc10.dist-info/RECORD +360 -0
  3. passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
  4. passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
  5. passagemath_flint.libs/libflint-3701249d.so.21.0.0 +0 -0
  6. passagemath_flint.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
  7. passagemath_flint.libs/libgfortran-8a9a71bc.so.5.0.0 +0 -0
  8. passagemath_flint.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  9. passagemath_flint.libs/libgsl-e3525837.so.28.0.0 +0 -0
  10. passagemath_flint.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
  11. passagemath_flint.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
  12. passagemath_flint.libs/libntl-1004113e.so.44.0.1 +0 -0
  13. passagemath_flint.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
  14. sage/all__sagemath_flint.py +29 -0
  15. sage/combinat/all__sagemath_flint.py +1 -0
  16. sage/combinat/posets/all__sagemath_flint.py +1 -0
  17. sage/combinat/posets/hasse_cython_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  18. sage/combinat/posets/hasse_cython_flint.pyx +194 -0
  19. sage/data_structures/all__sagemath_flint.py +1 -0
  20. sage/data_structures/bounded_integer_sequences.cpython-310-aarch64-linux-gnu.so +0 -0
  21. sage/data_structures/bounded_integer_sequences.pxd +62 -0
  22. sage/data_structures/bounded_integer_sequences.pyx +1418 -0
  23. sage/graphs/all__sagemath_flint.py +1 -0
  24. sage/graphs/chrompoly.cpython-310-aarch64-linux-gnu.so +0 -0
  25. sage/graphs/chrompoly.pyx +555 -0
  26. sage/graphs/matchpoly.cpython-310-aarch64-linux-gnu.so +0 -0
  27. sage/graphs/matchpoly.pyx +412 -0
  28. sage/libs/all__sagemath_flint.py +17 -0
  29. sage/libs/arb/__init__.py +1 -0
  30. sage/libs/arb/acb.pxd +154 -0
  31. sage/libs/arb/acb_calc.pxd +9 -0
  32. sage/libs/arb/acb_elliptic.pxd +25 -0
  33. sage/libs/arb/acb_hypgeom.pxd +74 -0
  34. sage/libs/arb/acb_mat.pxd +62 -0
  35. sage/libs/arb/acb_modular.pxd +17 -0
  36. sage/libs/arb/acb_poly.pxd +216 -0
  37. sage/libs/arb/arb.pxd +240 -0
  38. sage/libs/arb/arb_fmpz_poly.pxd +21 -0
  39. sage/libs/arb/arb_hypgeom.pxd +83 -0
  40. sage/libs/arb/arb_wrap.h +34 -0
  41. sage/libs/arb/arf.pxd +131 -0
  42. sage/libs/arb/arith.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/libs/arb/arith.pyx +87 -0
  44. sage/libs/arb/bernoulli.pxd +6 -0
  45. sage/libs/arb/mag.pxd +77 -0
  46. sage/libs/arb/types.pxd +37 -0
  47. sage/libs/flint/__init__.py +1 -0
  48. sage/libs/flint/acb.pxd +270 -0
  49. sage/libs/flint/acb_calc.pxd +22 -0
  50. sage/libs/flint/acb_dft.pxd +51 -0
  51. sage/libs/flint/acb_dirichlet.pxd +112 -0
  52. sage/libs/flint/acb_elliptic.pxd +42 -0
  53. sage/libs/flint/acb_hypgeom.pxd +169 -0
  54. sage/libs/flint/acb_macros.pxd +9 -0
  55. sage/libs/flint/acb_mat.pxd +136 -0
  56. sage/libs/flint/acb_mat_macros.pxd +10 -0
  57. sage/libs/flint/acb_modular.pxd +62 -0
  58. sage/libs/flint/acb_poly.pxd +251 -0
  59. sage/libs/flint/acb_poly_macros.pxd +8 -0
  60. sage/libs/flint/acb_theta.pxd +124 -0
  61. sage/libs/flint/acf.pxd +32 -0
  62. sage/libs/flint/aprcl.pxd +84 -0
  63. sage/libs/flint/arb.pxd +382 -0
  64. sage/libs/flint/arb_calc.pxd +31 -0
  65. sage/libs/flint/arb_fmpz_poly.pxd +34 -0
  66. sage/libs/flint/arb_fpwrap.pxd +215 -0
  67. sage/libs/flint/arb_hypgeom.pxd +147 -0
  68. sage/libs/flint/arb_macros.pxd +9 -0
  69. sage/libs/flint/arb_mat.pxd +140 -0
  70. sage/libs/flint/arb_mat_macros.pxd +10 -0
  71. sage/libs/flint/arb_poly.pxd +237 -0
  72. sage/libs/flint/arf.pxd +167 -0
  73. sage/libs/flint/arith.cpython-310-aarch64-linux-gnu.so +0 -0
  74. sage/libs/flint/arith.pxd +76 -0
  75. sage/libs/flint/arith.pyx +77 -0
  76. sage/libs/flint/arith_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  77. sage/libs/flint/arith_sage.pyx +308 -0
  78. sage/libs/flint/bernoulli.pxd +28 -0
  79. sage/libs/flint/bool_mat.pxd +52 -0
  80. sage/libs/flint/ca.pxd +203 -0
  81. sage/libs/flint/ca_ext.pxd +34 -0
  82. sage/libs/flint/ca_field.pxd +32 -0
  83. sage/libs/flint/ca_mat.pxd +117 -0
  84. sage/libs/flint/ca_poly.pxd +104 -0
  85. sage/libs/flint/ca_vec.pxd +46 -0
  86. sage/libs/flint/calcium.pxd +27 -0
  87. sage/libs/flint/d_mat.pxd +39 -0
  88. sage/libs/flint/d_vec.pxd +32 -0
  89. sage/libs/flint/dirichlet.pxd +57 -0
  90. sage/libs/flint/dlog.pxd +53 -0
  91. sage/libs/flint/double_extras.pxd +24 -0
  92. sage/libs/flint/double_interval.pxd +36 -0
  93. sage/libs/flint/fexpr.pxd +104 -0
  94. sage/libs/flint/fexpr_builtin.pxd +20 -0
  95. sage/libs/flint/fft.pxd +66 -0
  96. sage/libs/flint/flint.pxd +36 -0
  97. sage/libs/flint/flint_ntl_wrap.h +35 -0
  98. sage/libs/flint/flint_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  99. sage/libs/flint/flint_sage.pyx +163 -0
  100. sage/libs/flint/flint_wrap.h +190 -0
  101. sage/libs/flint/fmpq.pxd +137 -0
  102. sage/libs/flint/fmpq_mat.pxd +105 -0
  103. sage/libs/flint/fmpq_mat_macros.pxd +10 -0
  104. sage/libs/flint/fmpq_mpoly.pxd +165 -0
  105. sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
  106. sage/libs/flint/fmpq_poly.pxd +241 -0
  107. sage/libs/flint/fmpq_poly_macros.pxd +9 -0
  108. sage/libs/flint/fmpq_poly_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  109. sage/libs/flint/fmpq_poly_sage.pxd +31 -0
  110. sage/libs/flint/fmpq_poly_sage.pyx +48 -0
  111. sage/libs/flint/fmpq_vec.pxd +27 -0
  112. sage/libs/flint/fmpz.pxd +256 -0
  113. sage/libs/flint/fmpz_extras.pxd +32 -0
  114. sage/libs/flint/fmpz_factor.pxd +42 -0
  115. sage/libs/flint/fmpz_factor_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  116. sage/libs/flint/fmpz_factor_sage.pxd +4 -0
  117. sage/libs/flint/fmpz_factor_sage.pyx +29 -0
  118. sage/libs/flint/fmpz_lll.pxd +49 -0
  119. sage/libs/flint/fmpz_macros.pxd +8 -0
  120. sage/libs/flint/fmpz_mat.pxd +184 -0
  121. sage/libs/flint/fmpz_mat_macros.pxd +10 -0
  122. sage/libs/flint/fmpz_mod.pxd +46 -0
  123. sage/libs/flint/fmpz_mod_mat.pxd +71 -0
  124. sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
  125. sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
  126. sage/libs/flint/fmpz_mod_poly.pxd +249 -0
  127. sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
  128. sage/libs/flint/fmpz_mod_vec.pxd +27 -0
  129. sage/libs/flint/fmpz_mpoly.pxd +224 -0
  130. sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
  131. sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
  132. sage/libs/flint/fmpz_poly.cpython-310-aarch64-linux-gnu.so +0 -0
  133. sage/libs/flint/fmpz_poly.pxd +407 -0
  134. sage/libs/flint/fmpz_poly.pyx +19 -0
  135. sage/libs/flint/fmpz_poly_factor.pxd +33 -0
  136. sage/libs/flint/fmpz_poly_macros.pxd +8 -0
  137. sage/libs/flint/fmpz_poly_mat.pxd +71 -0
  138. sage/libs/flint/fmpz_poly_q.pxd +55 -0
  139. sage/libs/flint/fmpz_poly_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  140. sage/libs/flint/fmpz_poly_sage.pxd +20 -0
  141. sage/libs/flint/fmpz_poly_sage.pyx +500 -0
  142. sage/libs/flint/fmpz_vec.pxd +80 -0
  143. sage/libs/flint/fmpzi.pxd +52 -0
  144. sage/libs/flint/fq.pxd +97 -0
  145. sage/libs/flint/fq_default.pxd +84 -0
  146. sage/libs/flint/fq_default_mat.pxd +70 -0
  147. sage/libs/flint/fq_default_poly.pxd +97 -0
  148. sage/libs/flint/fq_default_poly_factor.pxd +39 -0
  149. sage/libs/flint/fq_embed.pxd +28 -0
  150. sage/libs/flint/fq_mat.pxd +83 -0
  151. sage/libs/flint/fq_nmod.pxd +95 -0
  152. sage/libs/flint/fq_nmod_embed.pxd +28 -0
  153. sage/libs/flint/fq_nmod_mat.pxd +83 -0
  154. sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
  155. sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
  156. sage/libs/flint/fq_nmod_poly.pxd +202 -0
  157. sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
  158. sage/libs/flint/fq_nmod_vec.pxd +33 -0
  159. sage/libs/flint/fq_poly.pxd +204 -0
  160. sage/libs/flint/fq_poly_factor.pxd +47 -0
  161. sage/libs/flint/fq_vec.pxd +33 -0
  162. sage/libs/flint/fq_zech.pxd +99 -0
  163. sage/libs/flint/fq_zech_embed.pxd +28 -0
  164. sage/libs/flint/fq_zech_mat.pxd +78 -0
  165. sage/libs/flint/fq_zech_poly.pxd +198 -0
  166. sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
  167. sage/libs/flint/fq_zech_vec.pxd +33 -0
  168. sage/libs/flint/gr.pxd +174 -0
  169. sage/libs/flint/gr_generic.pxd +215 -0
  170. sage/libs/flint/gr_mat.pxd +161 -0
  171. sage/libs/flint/gr_mpoly.pxd +68 -0
  172. sage/libs/flint/gr_poly.pxd +276 -0
  173. sage/libs/flint/gr_special.pxd +237 -0
  174. sage/libs/flint/gr_vec.pxd +120 -0
  175. sage/libs/flint/hypgeom.pxd +24 -0
  176. sage/libs/flint/long_extras.pxd +23 -0
  177. sage/libs/flint/mag.pxd +131 -0
  178. sage/libs/flint/mag_macros.pxd +8 -0
  179. sage/libs/flint/mpf_mat.pxd +36 -0
  180. sage/libs/flint/mpf_vec.pxd +34 -0
  181. sage/libs/flint/mpfr_mat.pxd +27 -0
  182. sage/libs/flint/mpfr_vec.pxd +25 -0
  183. sage/libs/flint/mpn_extras.pxd +41 -0
  184. sage/libs/flint/mpoly.pxd +72 -0
  185. sage/libs/flint/nf.pxd +19 -0
  186. sage/libs/flint/nf_elem.pxd +74 -0
  187. sage/libs/flint/nmod.pxd +35 -0
  188. sage/libs/flint/nmod_mat.pxd +104 -0
  189. sage/libs/flint/nmod_mpoly.pxd +144 -0
  190. sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
  191. sage/libs/flint/nmod_poly.pxd +339 -0
  192. sage/libs/flint/nmod_poly_factor.pxd +44 -0
  193. sage/libs/flint/nmod_poly_linkage.pxi +710 -0
  194. sage/libs/flint/nmod_poly_mat.pxd +76 -0
  195. sage/libs/flint/nmod_vec.pxd +40 -0
  196. sage/libs/flint/ntl_interface.pxd +17 -0
  197. sage/libs/flint/padic.pxd +93 -0
  198. sage/libs/flint/padic_mat.pxd +64 -0
  199. sage/libs/flint/padic_poly.pxd +88 -0
  200. sage/libs/flint/partitions.pxd +23 -0
  201. sage/libs/flint/perm.pxd +26 -0
  202. sage/libs/flint/profiler.pxd +24 -0
  203. sage/libs/flint/qadic.pxd +77 -0
  204. sage/libs/flint/qfb.pxd +44 -0
  205. sage/libs/flint/qqbar.pxd +172 -0
  206. sage/libs/flint/qsieve.cpython-310-aarch64-linux-gnu.so +0 -0
  207. sage/libs/flint/qsieve.pxd +41 -0
  208. sage/libs/flint/qsieve.pyx +21 -0
  209. sage/libs/flint/qsieve_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/libs/flint/qsieve_sage.pyx +67 -0
  211. sage/libs/flint/thread_pool.pxd +25 -0
  212. sage/libs/flint/types.pxd +2076 -0
  213. sage/libs/flint/ulong_extras.cpython-310-aarch64-linux-gnu.so +0 -0
  214. sage/libs/flint/ulong_extras.pxd +141 -0
  215. sage/libs/flint/ulong_extras.pyx +21 -0
  216. sage/libs/flint/ulong_extras_sage.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/libs/flint/ulong_extras_sage.pyx +21 -0
  218. sage/matrix/all__sagemath_flint.py +1 -0
  219. sage/matrix/change_ring.cpython-310-aarch64-linux-gnu.so +0 -0
  220. sage/matrix/change_ring.pyx +43 -0
  221. sage/matrix/matrix_complex_ball_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/matrix/matrix_complex_ball_dense.pxd +14 -0
  223. sage/matrix/matrix_complex_ball_dense.pyx +973 -0
  224. sage/matrix/matrix_cyclo_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  225. sage/matrix/matrix_cyclo_dense.pxd +16 -0
  226. sage/matrix/matrix_cyclo_dense.pyx +1761 -0
  227. sage/matrix/matrix_integer_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/matrix/matrix_integer_dense.pxd +32 -0
  229. sage/matrix/matrix_integer_dense.pyx +5801 -0
  230. sage/matrix/matrix_integer_dense_hnf.py +1294 -0
  231. sage/matrix/matrix_integer_dense_saturation.py +346 -0
  232. sage/matrix/matrix_integer_sparse.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/matrix/matrix_integer_sparse.pxd +9 -0
  234. sage/matrix/matrix_integer_sparse.pyx +1090 -0
  235. sage/matrix/matrix_rational_dense.cpython-310-aarch64-linux-gnu.so +0 -0
  236. sage/matrix/matrix_rational_dense.pxd +23 -0
  237. sage/matrix/matrix_rational_dense.pyx +2995 -0
  238. sage/matrix/matrix_rational_sparse.cpython-310-aarch64-linux-gnu.so +0 -0
  239. sage/matrix/matrix_rational_sparse.pxd +11 -0
  240. sage/matrix/matrix_rational_sparse.pyx +789 -0
  241. sage/matrix/misc_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  242. sage/matrix/misc_flint.pyx +109 -0
  243. sage/modular/all__sagemath_flint.py +1 -0
  244. sage/modular/modform/all__sagemath_flint.py +1 -0
  245. sage/modular/modform/eis_series_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  246. sage/modular/modform/eis_series_cython.pyx +226 -0
  247. sage/modular/modsym/all__sagemath_flint.py +1 -0
  248. sage/modular/modsym/apply.cpython-310-aarch64-linux-gnu.so +0 -0
  249. sage/modular/modsym/apply.pxd +6 -0
  250. sage/modular/modsym/apply.pyx +113 -0
  251. sage/modular/modsym/heilbronn.cpython-310-aarch64-linux-gnu.so +0 -0
  252. sage/modular/modsym/heilbronn.pyx +966 -0
  253. sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
  254. sage/modular/pollack_stevens/dist.cpython-310-aarch64-linux-gnu.so +0 -0
  255. sage/modular/pollack_stevens/dist.pxd +38 -0
  256. sage/modular/pollack_stevens/dist.pyx +1439 -0
  257. sage/quivers/algebra.py +691 -0
  258. sage/quivers/algebra_elements.cpython-310-aarch64-linux-gnu.so +0 -0
  259. sage/quivers/algebra_elements.pxd +97 -0
  260. sage/quivers/algebra_elements.pxi +1324 -0
  261. sage/quivers/algebra_elements.pyx +1424 -0
  262. sage/quivers/all.py +1 -0
  263. sage/quivers/ar_quiver.py +917 -0
  264. sage/quivers/homspace.py +640 -0
  265. sage/quivers/morphism.py +1282 -0
  266. sage/quivers/path_semigroup.py +1155 -0
  267. sage/quivers/paths.cpython-310-aarch64-linux-gnu.so +0 -0
  268. sage/quivers/paths.pxd +13 -0
  269. sage/quivers/paths.pyx +809 -0
  270. sage/quivers/representation.py +2975 -0
  271. sage/rings/all__sagemath_flint.py +37 -0
  272. sage/rings/cif.py +4 -0
  273. sage/rings/complex_arb.cpython-310-aarch64-linux-gnu.so +0 -0
  274. sage/rings/complex_arb.pxd +29 -0
  275. sage/rings/complex_arb.pyx +5176 -0
  276. sage/rings/complex_interval.cpython-310-aarch64-linux-gnu.so +0 -0
  277. sage/rings/complex_interval.pxd +30 -0
  278. sage/rings/complex_interval.pyx +2475 -0
  279. sage/rings/complex_interval_field.py +711 -0
  280. sage/rings/convert/all.py +1 -0
  281. sage/rings/convert/mpfi.cpython-310-aarch64-linux-gnu.so +0 -0
  282. sage/rings/convert/mpfi.pxd +6 -0
  283. sage/rings/convert/mpfi.pyx +576 -0
  284. sage/rings/factorint_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  285. sage/rings/factorint_flint.pyx +99 -0
  286. sage/rings/fraction_field_FpT.cpython-310-aarch64-linux-gnu.so +0 -0
  287. sage/rings/fraction_field_FpT.pxd +28 -0
  288. sage/rings/fraction_field_FpT.pyx +2043 -0
  289. sage/rings/imaginary_unit.py +5 -0
  290. sage/rings/monomials.py +73 -0
  291. sage/rings/number_field/S_unit_solver.py +2870 -0
  292. sage/rings/number_field/all__sagemath_flint.py +7 -0
  293. sage/rings/number_field/bdd_height.py +664 -0
  294. sage/rings/number_field/class_group.py +762 -0
  295. sage/rings/number_field/galois_group.py +1307 -0
  296. sage/rings/number_field/homset.py +612 -0
  297. sage/rings/number_field/maps.py +687 -0
  298. sage/rings/number_field/morphism.py +272 -0
  299. sage/rings/number_field/number_field.py +12820 -0
  300. sage/rings/number_field/number_field_element.cpython-310-aarch64-linux-gnu.so +0 -0
  301. sage/rings/number_field/number_field_element.pxd +59 -0
  302. sage/rings/number_field/number_field_element.pyx +5735 -0
  303. sage/rings/number_field/number_field_element_quadratic.cpython-310-aarch64-linux-gnu.so +0 -0
  304. sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
  305. sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
  306. sage/rings/number_field/number_field_ideal_rel.py +925 -0
  307. sage/rings/number_field/number_field_morphisms.cpython-310-aarch64-linux-gnu.so +0 -0
  308. sage/rings/number_field/number_field_morphisms.pyx +781 -0
  309. sage/rings/number_field/number_field_rel.py +2734 -0
  310. sage/rings/number_field/order.py +2981 -0
  311. sage/rings/number_field/order_ideal.py +804 -0
  312. sage/rings/number_field/selmer_group.py +715 -0
  313. sage/rings/number_field/small_primes_of_degree_one.py +242 -0
  314. sage/rings/number_field/splitting_field.py +606 -0
  315. sage/rings/number_field/structure.py +380 -0
  316. sage/rings/number_field/unit_group.py +721 -0
  317. sage/rings/padics/all__sagemath_flint.py +3 -0
  318. sage/rings/polynomial/all__sagemath_flint.py +1 -0
  319. sage/rings/polynomial/complex_roots.py +312 -0
  320. sage/rings/polynomial/evaluation_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  321. sage/rings/polynomial/evaluation_flint.pxd +7 -0
  322. sage/rings/polynomial/evaluation_flint.pyx +68 -0
  323. sage/rings/polynomial/hilbert.cpython-310-aarch64-linux-gnu.so +0 -0
  324. sage/rings/polynomial/hilbert.pyx +602 -0
  325. sage/rings/polynomial/polynomial_complex_arb.cpython-310-aarch64-linux-gnu.so +0 -0
  326. sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
  327. sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
  328. sage/rings/polynomial/polynomial_integer_dense_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  329. sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
  330. sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
  331. sage/rings/polynomial/polynomial_number_field.cpython-310-aarch64-linux-gnu.so +0 -0
  332. sage/rings/polynomial/polynomial_number_field.pyx +345 -0
  333. sage/rings/polynomial/polynomial_rational_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  334. sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
  335. sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
  336. sage/rings/polynomial/polynomial_zmod_flint.cpython-310-aarch64-linux-gnu.so +0 -0
  337. sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
  338. sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
  339. sage/rings/polynomial/real_roots.cpython-310-aarch64-linux-gnu.so +0 -0
  340. sage/rings/polynomial/real_roots.pxd +81 -0
  341. sage/rings/polynomial/real_roots.pyx +4704 -0
  342. sage/rings/polynomial/refine_root.cpython-310-aarch64-linux-gnu.so +0 -0
  343. sage/rings/polynomial/refine_root.pyx +142 -0
  344. sage/rings/polynomial/weil/all.py +4 -0
  345. sage/rings/polynomial/weil/power_sums.h +46 -0
  346. sage/rings/polynomial/weil/weil_polynomials.cpython-310-aarch64-linux-gnu.so +0 -0
  347. sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
  348. sage/rings/qqbar.py +9025 -0
  349. sage/rings/real_arb.cpython-310-aarch64-linux-gnu.so +0 -0
  350. sage/rings/real_arb.pxd +21 -0
  351. sage/rings/real_arb.pyx +4065 -0
  352. sage/rings/real_interval_absolute.cpython-310-aarch64-linux-gnu.so +0 -0
  353. sage/rings/real_interval_absolute.pyx +1073 -0
  354. sage/rings/real_mpfi.cpython-310-aarch64-linux-gnu.so +0 -0
  355. sage/rings/real_mpfi.pyx +5428 -0
  356. sage/schemes/all__sagemath_flint.py +1 -0
  357. sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
  358. sage/schemes/elliptic_curves/descent_two_isogeny.cpython-310-aarch64-linux-gnu.so +0 -0
  359. sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
  360. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,3185 @@
1
+ # sage_setup: distribution = sagemath-flint
2
+ # distutils: libraries = NTL_LIBRARIES
3
+ # distutils: extra_compile_args = NTL_CFLAGS
4
+ # distutils: include_dirs = NTL_INCDIR
5
+ # distutils: library_dirs = NTL_LIBDIR
6
+ # distutils: extra_link_args = NTL_LIBEXTRA
7
+ # distutils: language = c++
8
+ # sage.doctest: needs sage.rings.number_field
9
+ r"""
10
+ Elements optimized for quadratic number fields
11
+
12
+ This module defines a Cython class :class:`NumberFieldElement_quadratic` to speed up
13
+ computations in quadratic extensions of `\QQ`.
14
+
15
+ .. TODO::
16
+
17
+ The ``_new()`` method should be overridden in this class to copy the ``D``
18
+ and ``standard_embedding`` attributes.
19
+
20
+ AUTHORS:
21
+
22
+ - Robert Bradshaw (2007-09): initial version
23
+ - David Harvey (2007-10): fixed up a few bugs, polish around the edges
24
+ - David Loeffler (2009-05): added more documentation and tests
25
+ - Vincent Delecroix (2012-07): added comparisons for quadratic number fields
26
+ (:issue:`13213`), abs, floor and ceil functions (:issue:`13256`)
27
+ """
28
+ # ****************************************************************************
29
+ # Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
30
+ #
31
+ # This program is free software: you can redistribute it and/or modify
32
+ # it under the terms of the GNU General Public License as published by
33
+ # the Free Software Foundation, either version 2 of the License, or
34
+ # (at your option) any later version.
35
+ # https://www.gnu.org/licenses/
36
+ # ****************************************************************************
37
+
38
+ include "sage/libs/ntl/decl.pxi"
39
+ from cpython.object cimport Py_EQ, Py_NE, Py_LE, Py_GE, Py_LT, Py_GT
40
+
41
+ from cysignals.signals cimport sig_on, sig_off
42
+
43
+ from sage.libs.gmp.mpz cimport *
44
+ from sage.libs.gmp.mpq cimport *
45
+ from sage.libs.flint.fmpz cimport *
46
+ from sage.libs.flint.arb cimport *
47
+ from sage.libs.flint.acb cimport *
48
+ from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
49
+ from sage.libs.ntl.ntl_ZZX cimport ntl_ZZX
50
+ from sage.libs.mpfi cimport *
51
+
52
+ from sage.structure.parent cimport Parent
53
+ from sage.structure.element cimport Element
54
+ from sage.structure.richcmp cimport rich_to_bool_sgn
55
+
56
+ from sage.rings.rational cimport Rational
57
+ from sage.rings.integer_ring import ZZ
58
+ from sage.rings.rational_field import QQ
59
+ from sage.categories.morphism cimport Morphism
60
+ from sage.rings.number_field.number_field_element import _inverse_mod_generic
61
+ from sage.rings.real_mpfi cimport RealIntervalField_class
62
+ from sage.rings.complex_interval cimport ComplexIntervalFieldElement
63
+ from sage.rings.real_arb cimport RealBall
64
+ from sage.rings.complex_arb cimport ComplexBall
65
+
66
+ from sage.libs.gmp.pylong cimport mpz_pythonhash
67
+
68
+
69
+ def __make_NumberFieldElement_quadratic0(parent, a, b, denom):
70
+ """
71
+ Used in unpickling elements of number fields.
72
+
73
+ TESTS::
74
+
75
+ sage: x = polygen(ZZ, 'x')
76
+ sage: K.<a> = NumberField(x^2 - x + 13)
77
+ sage: loads(dumps(a)) == a # indirect doctest
78
+ True
79
+ """
80
+ return NumberFieldElement_quadratic(parent, (a, b, denom))
81
+
82
+
83
+ def __make_NumberFieldElement_quadratic1(parent, cls, a, b, denom):
84
+ """
85
+ Used in unpickling elements of number fields.
86
+
87
+ TESTS::
88
+
89
+ sage: x = polygen(ZZ, 'x')
90
+ sage: K.<a> = NumberField(x^2 - x + 13)
91
+ sage: loads(dumps(a)) == a # indirect doctest
92
+ True
93
+
94
+ We test that :issue:`6462` is fixed::
95
+
96
+ sage: L = QuadraticField(-11,'a'); OL = L.maximal_order(); w = OL.0
97
+ sage: loads(dumps(w)) == w # indirect doctest
98
+ True
99
+ """
100
+ return cls(parent, (a, b, denom))
101
+
102
+
103
+ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute):
104
+ r"""
105
+ A :class:`NumberFieldElement_quadratic` object gives an efficient representation of
106
+ an element of a quadratic extension of `\QQ`.
107
+
108
+ Elements are represented internally as triples `(a, b, c)` of integers,
109
+ where `\gcd(a, b, c) = 1` and `c > 0`, representing the element `(a +
110
+ b \sqrt{D}) / c`. Note that if the discriminant `D` is `1 \bmod 4`,
111
+ integral elements do not necessarily have `c = 1`.
112
+
113
+ TESTS::
114
+
115
+ sage: from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_quadratic
116
+ sage: from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_quadratic_sqrt
117
+
118
+ We set up some fields::
119
+
120
+ sage: x = polygen(ZZ, 'x')
121
+ sage: K.<a> = NumberField(x^2 + 23)
122
+ sage: a.parts()
123
+ (0, 1)
124
+ sage: F.<b> = NumberField(x^2 - x + 7)
125
+ sage: b.parts()
126
+ (1/2, 3/2)
127
+
128
+ We construct elements of these fields in various ways -- firstly, from
129
+ polynomials::
130
+
131
+ sage: NumberFieldElement_quadratic_sqrt(K, x - 1)
132
+ a - 1
133
+ sage: NumberFieldElement_quadratic(F, x - 1)
134
+ b - 1
135
+
136
+ From triples of Integers::
137
+
138
+ sage: NumberFieldElement_quadratic_sqrt(K, (1,2,3))
139
+ 2/3*a + 1/3
140
+ sage: NumberFieldElement_quadratic(F, (1,2,3))
141
+ 4/9*b + 1/9
142
+ sage: NumberFieldElement_quadratic(F, (1,2,3)).parts()
143
+ (1/3, 2/3)
144
+
145
+ From pairs of Rationals::
146
+
147
+ sage: NumberFieldElement_quadratic_sqrt(K, (1/2, 1/3))
148
+ 1/3*a + 1/2
149
+ sage: NumberFieldElement_quadratic(F, (1/2, 1/3))
150
+ 2/9*b + 7/18
151
+ sage: NumberFieldElement_quadratic(F, (1/2, 1/3)).parts()
152
+ (1/2, 1/3)
153
+
154
+ Direct from Rationals::
155
+
156
+ sage: NumberFieldElement_quadratic_sqrt(K, 2/3)
157
+ 2/3
158
+ sage: NumberFieldElement_quadratic(F, 2/3)
159
+ 2/3
160
+
161
+ This checks a bug when converting from lists::
162
+
163
+ sage: w = CyclotomicField(3)([1/2, 1])
164
+ sage: w == w.__invert__().__invert__()
165
+ True
166
+ """
167
+
168
+ def __init__(self, parent, f):
169
+ """
170
+ Standard initialisation function.
171
+
172
+ EXAMPLES::
173
+
174
+ sage: F.<a> = QuadraticField(-7)
175
+ sage: c = a + 7
176
+ sage: type(c) # indirect doctest
177
+ <class 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_quadratic_sqrt'>
178
+ """
179
+ self.D = parent._D
180
+ cdef Integer a, b, denom
181
+ cdef Rational ad, bd
182
+
183
+ cdef NumberFieldElement_quadratic gen
184
+
185
+ if isinstance(f, NumberFieldElement_quadratic):
186
+ self._parent = parent # NOTE: We do *not* call NumberFieldElement_absolute.__init__, for speed reasons.
187
+ mpz_set(self.a, (<NumberFieldElement_quadratic>f).a)
188
+ mpz_set(self.b, (<NumberFieldElement_quadratic>f).b)
189
+ mpz_set(self.denom, (<NumberFieldElement_quadratic>f).denom)
190
+
191
+ elif type(f) is tuple and len(f) == 2:
192
+ NumberFieldElement_absolute.__init__(self, parent, None)
193
+ ad, bd = f
194
+ mpz_lcm(self.denom, mpq_denref(ad.value), mpq_denref(bd.value))
195
+ mpz_divexact(self.a, self.denom, mpq_denref(ad.value))
196
+ mpz_mul(self.a, self.a, mpq_numref(ad.value))
197
+ mpz_divexact(self.b, self.denom, mpq_denref(bd.value))
198
+ mpz_mul(self.b, self.b, mpq_numref(bd.value))
199
+
200
+ elif type(f) is tuple and len(f) == 3:
201
+ NumberFieldElement_absolute.__init__(self, parent, None)
202
+ a, b, denom = f
203
+ mpz_set(self.a, a.value)
204
+ mpz_set(self.b, b.value)
205
+ mpz_set(self.denom, denom.value)
206
+ self._reduce_c_()
207
+
208
+ else:
209
+ NumberFieldElement_absolute.__init__(self, parent, f)
210
+ # poly is in gen (which may not be sqrt(d))
211
+ self._ntl_coeff_as_mpz(self.a, 0)
212
+ self._ntl_coeff_as_mpz(self.b, 1)
213
+ if mpz_cmp_ui(self.a, 0) or mpz_cmp_ui(self.b, 0):
214
+ gen = parent.gen() # should this be cached?
215
+ self._ntl_denom_as_mpz(self.denom)
216
+ if mpz_cmp_ui(self.b, 0):
217
+ mpz_mul(self.a, self.a, gen.denom)
218
+ mpz_addmul(self.a, self.b, gen.a)
219
+ mpz_mul(self.b, self.b, gen.b)
220
+ mpz_mul(self.denom, self.denom, gen.denom)
221
+ else:
222
+ mpz_set_ui(self.denom, 1)
223
+ self._reduce_c_()
224
+
225
+ # set the attribute standard embedding which is used in the methods
226
+ # __cmp__, sign, real, imag, floor, ceil, ...
227
+ self.standard_embedding = parent._standard_embedding
228
+
229
+ cdef _new(self):
230
+ """
231
+ Quickly create a new initialized NumberFieldElement_quadratic with the
232
+ same parent as ``self``.
233
+
234
+ EXAMPLES::
235
+
236
+ sage: F.<b> = CyclotomicField(3)
237
+ sage: b + b # indirect doctest
238
+ 2*b
239
+ """
240
+ cdef type t = type(self)
241
+ cdef NumberFieldElement_quadratic x = <NumberFieldElement_quadratic>t.__new__(t)
242
+ x._parent = self._parent
243
+ x.standard_embedding = self.standard_embedding
244
+ x.D = self.D
245
+ return x
246
+
247
+ cdef number_field(self):
248
+ r"""
249
+ Return the number field to which this element belongs. Since this is a
250
+ Cython cdef method, it is not directly accessible by the user, but the
251
+ function "_number_field" calls this one.
252
+
253
+ EXAMPLES::
254
+
255
+ sage: F.<b> = QuadraticField(-7)
256
+ sage: b._number_field() # indirect doctest
257
+ Number Field in b with defining polynomial x^2 + 7 with b = 2.645751311064591?*I
258
+ """
259
+ return self._parent
260
+
261
+ def _maxima_init_(self, I=None):
262
+ """
263
+ EXAMPLES::
264
+
265
+ sage: K.<a> = QuadraticField(-1)
266
+ sage: (1 + a)._maxima_init_()
267
+ '1+%i*1'
268
+ sage: (1+3*a)._fricas_init_()
269
+ '1+%i*3'
270
+
271
+ sage: K.<J> = QuadraticField(-1, embedding=CC(0,-1))
272
+ sage: J._maxima_init_()
273
+ Traceback (most recent call last):
274
+ ...
275
+ NotImplementedError: conversion implemented only for elements of quadratic fields with discriminant -1 and standard embedding
276
+
277
+ sage: K.<sqrt2> = QuadraticField(2, embedding=AA(2))
278
+ sage: sqrt2._maxima_init_()
279
+ Traceback (most recent call last):
280
+ ...
281
+ NotImplementedError: conversion implemented only for elements of quadratic fields with discriminant -1 and standard embedding
282
+ """
283
+ a = self.parent().gen()
284
+ if a**2 == -1 and self.standard_embedding:
285
+ x0, x1 = self
286
+ return str(x0) + "+" + "%i*" + str(x1)
287
+ raise NotImplementedError("conversion implemented only for elements of quadratic fields with discriminant -1 and standard embedding")
288
+
289
+ # by coincidence, maxima and fricas both use %i for the imaginary unit I
290
+ _fricas_init_ = _maxima_init_
291
+
292
+ def _sympy_(self):
293
+ """
294
+ Convert this number to Sympy.
295
+
296
+ EXAMPLES::
297
+
298
+ sage: K.<a> = QuadraticField(-1)
299
+ sage: (1/3 + a/2)._sympy_() # needs sympy
300
+ 1/3 + I/2
301
+ sage: type(_) # needs sympy
302
+ <class 'sympy.core.add.Add'>
303
+ """
304
+ a = self.parent().gen()
305
+ if a**2 == -1 and self.standard_embedding:
306
+ x0, x1 = self
307
+ import sympy
308
+ return x0._sympy_() + x1._sympy_() * sympy.I
309
+ raise NotImplementedError(
310
+ "conversion implemented only for elements of quadratic "
311
+ "fields with discriminant -1 and standard embedding")
312
+
313
+ def _polymake_init_(self):
314
+ """
315
+ EXAMPLES::
316
+
317
+ sage: K.<sqrt5> = QuadraticField(5)
318
+ sage: polymake(3 + 2*sqrt5) # optional - jupymake
319
+ 3+2r5
320
+ sage: polymake(2**100/7 - 2*sqrt5/3**50) # optional - jupymake
321
+ 1267650600228229401496703205376/7-2/717897987691852588770249r5
322
+ sage: K.<i> = QuadraticField(-1)
323
+ sage: polymake(i) # optional - jupymake
324
+ Traceback (most recent call last):
325
+ ...
326
+ TypeError: Negative values for the root of the extension ... Bad Thing...
327
+
328
+ TESTS:
329
+
330
+ Test that :issue:`28377` is fixed::
331
+
332
+ sage: x = polygen(QQ, 'x')
333
+ sage: K = NumberField(x^2 - x -1, 'a', embedding=(1-AA(5).sqrt())/2)
334
+ sage: L = NumberField(x^2 - x -1, 'a', embedding=(1+AA(5).sqrt())/2)
335
+ sage: polymake(K.gen()) # optional - jupymake
336
+ 1/2-1/2r5
337
+ sage: polymake(L.gen()) # optional - jupymake
338
+ 1/2+1/2r5
339
+ """
340
+ cdef Integer a = Integer.__new__(Integer)
341
+ cdef Integer b = Integer.__new__(Integer)
342
+ cdef Integer denom
343
+ mpz_set(a.value, self.a)
344
+ mpz_set(b.value, self.b)
345
+ if not self.standard_embedding:
346
+ mpz_neg(b.value, b.value)
347
+ if mpz_cmp_ui(self.denom, 1) == 0:
348
+ return "new QuadraticExtension({}, {}, {})".format(a, b, self.D)
349
+ else:
350
+ denom = Integer.__new__(Integer)
351
+ mpz_set(denom.value, self.denom)
352
+ return "new QuadraticExtension({}, {}, {})".format(a/denom, b/denom, self.D)
353
+
354
+ cpdef _copy_for_parent(self, Parent parent):
355
+ r"""
356
+ Return a copy of ``self`` with the parent replaced by ``parent``.
357
+
358
+ EXAMPLES::
359
+
360
+ sage: K.<a> = QuadraticField(3)
361
+ sage: L.<b> = K.change_names()
362
+ sage: La = a._copy_for_parent(L)
363
+ sage: La.parent() is L
364
+ True
365
+ sage: La == b
366
+ True
367
+ """
368
+ cdef NumberFieldElement_quadratic x = <NumberFieldElement_quadratic>self._new()
369
+ mpz_set(x.a, self.a)
370
+ mpz_set(x.b, self.b)
371
+ mpz_set(x.denom, self.denom)
372
+ x._set_parent(parent)
373
+ return x
374
+
375
+ def __copy__(self):
376
+ r"""
377
+ TESTS::
378
+
379
+ sage: K.<a> = QuadraticField(-3)
380
+ sage: b = a + 3
381
+ sage: c = b.__copy__()
382
+ sage: b is c
383
+ True
384
+ """
385
+ # immutable
386
+ return self
387
+
388
+ def __deepcopy__(self, memo):
389
+ r"""
390
+ TESTS::
391
+
392
+ sage: K.<a> = QuadraticField(-3)
393
+ sage: b = a + 3
394
+ sage: c = deepcopy(b)
395
+ sage: b is c
396
+ True
397
+ """
398
+ # immutable
399
+ return self
400
+
401
+ def __cinit__(self):
402
+ r"""
403
+ Initialisation function.
404
+
405
+ EXAMPLES::
406
+
407
+ sage: QuadraticField(-3, 'a').gen() # indirect doctest
408
+ a
409
+ """
410
+ mpz_init(self.a)
411
+ mpz_init(self.b)
412
+ mpz_init(self.denom)
413
+
414
+ def __dealloc__(self):
415
+ mpz_clear(self.a)
416
+ mpz_clear(self.b)
417
+ mpz_clear(self.denom)
418
+
419
+ def __reduce__(self):
420
+ """
421
+ Used for pickling.
422
+
423
+ TESTS::
424
+
425
+ sage: x = polygen(ZZ, 'x')
426
+ sage: K.<a> = NumberField(x^2 - 13)
427
+ sage: loads(dumps(a)) == a
428
+ True
429
+ sage: loads(dumps(a/3+5)) == a/3+5
430
+ True
431
+ """
432
+ cdef Integer a = Integer.__new__(Integer)
433
+ cdef Integer b = Integer.__new__(Integer)
434
+ cdef Integer denom = Integer.__new__(Integer)
435
+ mpz_set(a.value, self.a)
436
+ mpz_set(b.value, self.b)
437
+ mpz_set(denom.value, self.denom)
438
+ return __make_NumberFieldElement_quadratic1, (self._parent, type(self), a, b, denom)
439
+
440
+ cdef int _randomize(self, num_bound, den_bound, distribution) except -1:
441
+ """
442
+ TESTS::
443
+
444
+ sage: a = ZZ.random_element(-100, 100)
445
+ sage: while a.is_square():
446
+ ....: a = ZZ.random_element(-100, 100)
447
+ sage: K = QuadraticField(a)
448
+ sage: K.random_element().parent() is K # indirect doctest
449
+ True
450
+ sage: len(set(K.random_element() for _ in range(100))) >= 40
451
+ True
452
+
453
+ Verify that :issue:`30017` is fixed::
454
+
455
+ sage: all(K.random_element().is_integral() for s in range(100))
456
+ False
457
+ """
458
+ cdef Integer temp, denom1, denom2
459
+
460
+ # in theory, we could just generate two random numerators and
461
+ # a random denominator. however, this would mean that we were
462
+ # extraordinarily unlikely to run into results of the form
463
+ # 1/3 + 1/5*sqrt(D), which are often some of the best examples
464
+ # for testing out code. since this is probably the primary use
465
+ # of the random element code, it's worth doing slightly more
466
+ # work to make this possible.
467
+
468
+ # generate denominators
469
+ if den_bound is None:
470
+ denom1 = <Integer>(1 + abs(ZZ.random_element(distribution=distribution)))
471
+ denom2 = <Integer>(1 + abs(ZZ.random_element(distribution=distribution)))
472
+ else:
473
+ # normalize denominator bound
474
+ if den_bound < 1:
475
+ den_bound = 1
476
+ denom1 = <Integer>(ZZ.random_element(x=1,
477
+ y=den_bound+1,
478
+ distribution=distribution))
479
+ denom2 = <Integer>(ZZ.random_element(x=1,
480
+ y=den_bound+1,
481
+ distribution=distribution))
482
+
483
+ # set a, b
484
+ temp = <Integer>(ZZ.random_element(x=num_bound, distribution=distribution))
485
+ mpz_mul(self.a, temp.value, denom2.value)
486
+ temp = <Integer>(ZZ.random_element(x=num_bound, distribution=distribution))
487
+ mpz_mul(self.b, temp.value, denom1.value)
488
+ # set denom
489
+ mpz_mul(self.denom, denom1.value, denom2.value)
490
+
491
+ self._reduce_c_()
492
+ return 0 # No error
493
+
494
+ def _lift_cyclotomic_element(self, new_parent, bint check=True, int rel=0):
495
+ """
496
+ Create an element of the passed field from this field. This
497
+ is specific to creating elements in a cyclotomic field from
498
+ elements in another cyclotomic field, in the case that
499
+ self.number_field()._n() divides new_parent()._n(). This
500
+ function aims to make this common coercion extremely fast!
501
+
502
+ More general coercion (i.e. of zeta6 into CyclotomicField(3))
503
+ is implemented in the _coerce_from_other_cyclotomic_field
504
+ method of a CyclotomicField.
505
+
506
+ EXAMPLES::
507
+
508
+ sage: C.<zeta4>=CyclotomicField(4)
509
+ sage: CyclotomicField(20)(zeta4+1) # The function _lift_cyclotomic_element does the heavy lifting in the background
510
+ zeta20^5 + 1
511
+ sage: (zeta4+1)._lift_cyclotomic_element(CyclotomicField(40)) # There is rarely a purpose to call this function directly
512
+ zeta40^10 + 1
513
+
514
+ sage: cf3 = CyclotomicField(3) ; z3 = cf3.0
515
+ sage: cf6 = CyclotomicField(6) ; z6 = cf6.0
516
+ sage: z6._lift_cyclotomic_element(cf3)
517
+ Traceback (most recent call last):
518
+ ...
519
+ TypeError: The zeta_order of the new field must be a multiple of the zeta_order of the original.
520
+ sage: cf3(z6)
521
+ zeta3 + 1
522
+ sage: z3._lift_cyclotomic_element(cf6)
523
+ zeta6 - 1
524
+
525
+ Verify embeddings are respected::
526
+
527
+ sage: cf6c = CyclotomicField(6, embedding=CDF(exp(-pi*I/3))); z6c = cf6c.0 # needs sage.symbolic
528
+ sage: cf3(z6c) # needs sage.symbolic
529
+ -zeta3
530
+ sage: cf6c(z3) # needs sage.symbolic
531
+ -zeta6
532
+
533
+ AUTHOR:
534
+
535
+ - Joel B. Mohler (original version)
536
+
537
+ - Craig Citro (reworked for quadratic elements)
538
+ """
539
+ if check:
540
+ from sage.rings.number_field.number_field import NumberField_cyclotomic
541
+ if not isinstance(self.number_field(), NumberField_cyclotomic) \
542
+ or not isinstance(new_parent, NumberField_cyclotomic):
543
+ raise TypeError("The field and the new parent field must both be cyclotomic fields.")
544
+
545
+ if rel == 0:
546
+ small_order = self.number_field()._n()
547
+ large_order = new_parent._n()
548
+
549
+ try:
550
+ rel = ZZ(large_order / small_order)
551
+ except TypeError:
552
+ raise TypeError("The zeta_order of the new field must be a multiple of the zeta_order of the original.")
553
+
554
+ cdef NumberFieldElement_quadratic x2
555
+ cdef int n = self._parent._n()
556
+
557
+ if new_parent.degree() == 2:
558
+ ## since self is a *quadratic* element, we can only get
559
+ ## here if self.parent() and new_parent are:
560
+ ## - CyclotomicField(3) and CyclotomicField(6)
561
+ ## - CyclotomicField(3) and CyclotomicField(3)
562
+ ## - CyclotomicField(6) and CyclotomicField(6)
563
+ ## - CyclotomicField(4) and CyclotomicField(4)
564
+ ## In all cases, conversion of elements is trivial!
565
+ if n == <int>new_parent._n():
566
+ conjugate = rel != 1
567
+ else:
568
+ # n = 3, new_n = 6
569
+ conjugate = rel == 4
570
+ x2 = <NumberFieldElement_quadratic>(self._new())
571
+ x2._parent = new_parent
572
+ mpz_set(x2.a, self.a)
573
+ if conjugate:
574
+ mpz_neg(x2.b, self.b)
575
+ else:
576
+ mpz_set(x2.b, self.b)
577
+ mpz_set(x2.denom, self.denom)
578
+ x2.D = self.D
579
+ return x2
580
+
581
+ cdef NumberFieldElement x
582
+ cdef ZZX_c elt_num
583
+ cdef ZZ_c elt_den, tmp_coeff
584
+ cdef mpz_t tmp_mpz
585
+ cdef long tmp_const
586
+
587
+ x = <NumberFieldElement_absolute>NumberFieldElement_absolute.__new__(NumberFieldElement_absolute)
588
+
589
+ mpz_to_ZZ(&elt_den, self.denom)
590
+
591
+ mpz_init(tmp_mpz)
592
+
593
+ ## set the two terms in the polynomial
594
+ if n == 4:
595
+ mpz_to_ZZ(&tmp_coeff, self.a)
596
+ ZZX_SetCoeff(elt_num, 0, tmp_coeff)
597
+ mpz_to_ZZ(&tmp_coeff, self.b)
598
+ ZZX_SetCoeff(elt_num, 1, tmp_coeff)
599
+
600
+ elif n == 3:
601
+ ## num[0] = a + b
602
+ mpz_add(tmp_mpz, tmp_mpz, self.a)
603
+ mpz_add(tmp_mpz, tmp_mpz, self.b)
604
+ mpz_to_ZZ(&tmp_coeff, tmp_mpz)
605
+ ZZX_SetCoeff(elt_num, 0, tmp_coeff)
606
+
607
+ ## num[1] = 2*b
608
+ mpz_sub(tmp_mpz, tmp_mpz, self.a)
609
+ tmp_const = 2
610
+ mpz_mul_si(tmp_mpz, tmp_mpz, tmp_const)
611
+ mpz_to_ZZ(&tmp_coeff, tmp_mpz)
612
+ ZZX_SetCoeff(elt_num, 1, tmp_coeff)
613
+
614
+ elif n == 6:
615
+ ## num[0] = a - b
616
+ mpz_add(tmp_mpz, tmp_mpz, self.a)
617
+ mpz_sub(tmp_mpz, tmp_mpz, self.b)
618
+ mpz_to_ZZ(&tmp_coeff, tmp_mpz)
619
+ ZZX_SetCoeff(elt_num, 0, tmp_coeff)
620
+
621
+ ## num[1] = 2*b
622
+ mpz_sub(tmp_mpz, tmp_mpz, self.a)
623
+ tmp_const = -2
624
+ mpz_mul_si(tmp_mpz, tmp_mpz, tmp_const)
625
+ mpz_to_ZZ(&tmp_coeff, tmp_mpz)
626
+ ZZX_SetCoeff(elt_num, 1, tmp_coeff)
627
+
628
+ mpz_clear(tmp_mpz)
629
+
630
+ x._parent = <Parent>new_parent
631
+ x._fld_numerator, x._fld_denominator = new_parent.polynomial_ntl()
632
+ x._denominator = elt_den
633
+ cdef ZZX_c result
634
+ cdef ZZ_c tmp
635
+ cdef int i
636
+ cdef ntl_ZZX _num
637
+ cdef ntl_ZZ _den
638
+ _num, _den = new_parent.polynomial_ntl()
639
+ for i from 0 <= i <= ZZX_deg(elt_num):
640
+ tmp = ZZX_coeff(elt_num, i)
641
+ ZZX_SetCoeff(result, i*rel, tmp)
642
+ ZZX_rem(x._numerator, result, _num.x)
643
+ (<NumberFieldElement_absolute>x)._reduce_c_()
644
+ return x
645
+
646
+ def _real_mpfi_(self, R):
647
+ r"""
648
+ Conversion to a real interval field.
649
+
650
+ TESTS::
651
+
652
+ sage: K1 = QuadraticField(2)
653
+ sage: RIF(K1.gen())
654
+ 1.414213562373095?
655
+ sage: RIF(K1(1/5))
656
+ 0.2000000000000000?
657
+ sage: RIF(3/5*K1.gen() + 1/5)
658
+ 1.048528137423857?
659
+
660
+ sage: K2 = QuadraticField(2, embedding=-RLF(2).sqrt())
661
+ sage: RIF(K2.gen())
662
+ -1.414213562373095?
663
+
664
+ sage: K3 = QuadraticField(-1)
665
+ sage: RIF(K3.gen())
666
+ Traceback (most recent call last):
667
+ ...
668
+ ValueError: unable to convert complex algebraic number a to real interval
669
+ sage: RIF(K3(2))
670
+ 2
671
+
672
+ Check that :issue:`21979` is fixed::
673
+
674
+ sage: a = QuadraticField(5).gen()
675
+ sage: u = -573147844013817084101/2*a + 1281597540372340914251/2
676
+ sage: RealIntervalField(128)(u)
677
+ 0.?e-17
678
+ sage: RealIntervalField(128)(u).is_zero()
679
+ False
680
+
681
+ This was fixed in :issue:`24371`::
682
+
683
+ sage: RIF.convert_map_from(QuadraticField(5))
684
+ Conversion via _real_mpfi_ method map:
685
+ From: Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?
686
+ To: Real Interval Field with 53 bits of precision
687
+ """
688
+ ans = (<RealIntervalField_class?>R)._new()
689
+
690
+ if mpz_cmp_ui(self.b, 0):
691
+ if mpz_cmp_ui(self.D.value, 0) < 0:
692
+ raise ValueError(f"unable to convert complex algebraic number {self!r} to real interval")
693
+ mpfi_set_z(ans.value, self.D.value)
694
+ mpfi_sqrt(ans.value, ans.value)
695
+ if not self.standard_embedding:
696
+ mpfi_neg(ans.value, ans.value)
697
+ mpfi_mul_z(ans.value, ans.value, self.b)
698
+ mpfi_add_z(ans.value, ans.value, self.a)
699
+ else:
700
+ mpfi_set_z(ans.value, self.a)
701
+
702
+ mpfi_div_z(ans.value, ans.value, self.denom)
703
+ return ans
704
+
705
+ def _complex_mpfi_(self, R):
706
+ r"""
707
+ Conversion to a complex interval field.
708
+
709
+ TESTS::
710
+
711
+ sage: K.<a> = QuadraticField(2)
712
+ sage: CIF(a)
713
+ 1.414213562373095?
714
+ sage: CIF(K(1/5))
715
+ 0.2000000000000000?
716
+ sage: CIF(1/5 + 3/5*a)
717
+ 1.048528137423857?
718
+
719
+ sage: K.<a> = QuadraticField(-2)
720
+ sage: CIF(a)
721
+ 1.414213562373095?*I
722
+ sage: CIF(K(1/5))
723
+ 0.2000000000000000?
724
+ sage: CIF(1/5 + 3/5*a)
725
+ 0.2000000000000000? + 0.848528137423857?*I
726
+
727
+ sage: K.<a> = QuadraticField(-2, embedding=-CLF(-2).sqrt())
728
+ sage: CIF(a)
729
+ -1.414213562373095?*I
730
+
731
+ This was fixed in :issue:`24371`::
732
+
733
+ sage: CIF.convert_map_from(QuadraticField(-5))
734
+ Conversion via _complex_mpfi_ method map:
735
+ From: Number Field in a with defining polynomial x^2 + 5 with a = 2.236067977499790?*I
736
+ To: Complex Interval Field with 53 bits of precision
737
+ """
738
+ ans = <ComplexIntervalFieldElement>ComplexIntervalFieldElement.__new__(ComplexIntervalFieldElement, R)
739
+
740
+ if mpz_cmp_ui(self.b, 0):
741
+ mpfi_set_z(ans.__re, self.D.value)
742
+ if mpfi_is_neg(ans.__re):
743
+ # Imaginary quadratic
744
+ mpfi_neg(ans.__re, ans.__re)
745
+ mpfi_sqrt(ans.__im, ans.__re)
746
+ if not self.standard_embedding:
747
+ mpfi_neg(ans.__im, ans.__im)
748
+ mpfi_set_z(ans.__re, self.a)
749
+ mpfi_mul_z(ans.__im, ans.__im, self.b)
750
+ mpfi_div_z(ans.__im, ans.__im, self.denom)
751
+ else:
752
+ # Real quadratic
753
+ mpfi_sqrt(ans.__re, ans.__re)
754
+ if not self.standard_embedding:
755
+ mpfi_neg(ans.__re, ans.__re)
756
+ mpfi_mul_z(ans.__re, ans.__re, self.b)
757
+ mpfi_add_z(ans.__re, ans.__re, self.a)
758
+ mpfi_set_ui(ans.__im, 0)
759
+ else:
760
+ mpfi_set_z(ans.__re, self.a)
761
+ mpfi_set_ui(ans.__im, 0)
762
+
763
+ mpfi_div_z(ans.__re, ans.__re, self.denom)
764
+ return ans
765
+
766
+ cdef int arb_set_real(self, arb_t x, long prec) except -1:
767
+ "Set x to the real part of this element"
768
+ cdef fmpz_t tmpz
769
+ cdef arb_t rootD
770
+ cdef long prec2
771
+
772
+ fmpz_init(tmpz)
773
+
774
+ if mpz_sgn(self.D.value) > 0:
775
+ # To mitigate the effect of cancellations between
776
+ # a and b*sqrt(D) we perform a loop with increasing
777
+ # working precision
778
+ arb_init(rootD)
779
+ prec2 = prec
780
+ sig_on()
781
+ while True:
782
+ fmpz_set_mpz(tmpz, self.a)
783
+ arb_set_fmpz(x, tmpz)
784
+ fmpz_set_mpz(tmpz, self.D.value)
785
+ arb_sqrt_fmpz(rootD, tmpz, prec2)
786
+ fmpz_set_mpz(tmpz, self.b)
787
+ if self.standard_embedding:
788
+ arb_addmul_fmpz(x, rootD, tmpz, prec2)
789
+ else:
790
+ arb_submul_fmpz(x, rootD, tmpz, prec2)
791
+ if arb_rel_accuracy_bits(x) < prec - 4:
792
+ prec2 *= 2
793
+ continue
794
+ else:
795
+ break
796
+ sig_off()
797
+ arb_clear(rootD)
798
+ else:
799
+ fmpz_set_mpz(tmpz, self.a)
800
+ arb_set_fmpz(x, tmpz)
801
+
802
+ fmpz_set_mpz(tmpz, self.denom)
803
+ arb_div_fmpz(x, x, tmpz, prec)
804
+ fmpz_clear(tmpz)
805
+ return 0
806
+
807
+ cdef void arb_set_imag(self, arb_t x, long prec) noexcept:
808
+ "Set x to the imaginary part of this element"
809
+ cdef fmpz_t tmpz
810
+ cdef arb_t rootD
811
+
812
+ if mpz_sgn(self.D.value) < 0 and mpz_sgn(self.b):
813
+ arb_init(rootD)
814
+ fmpz_init(tmpz)
815
+ fmpz_set_mpz(tmpz, self.D.value)
816
+ fmpz_neg(tmpz, tmpz)
817
+ arb_sqrt_fmpz(rootD, tmpz, prec)
818
+ fmpz_set_mpz(tmpz, self.b)
819
+ if self.standard_embedding:
820
+ arb_addmul_fmpz(x, rootD, tmpz, prec)
821
+ else:
822
+ arb_submul_fmpz(x, rootD, tmpz, prec)
823
+ fmpz_set_mpz(tmpz, self.denom)
824
+ arb_div_fmpz(x, x, tmpz, prec)
825
+
826
+ fmpz_clear(tmpz)
827
+ arb_clear(rootD)
828
+
829
+ def _arb_(self, R):
830
+ r"""
831
+ Conversion to a real ball with parent ``R``.
832
+
833
+ EXAMPLES::
834
+
835
+ sage: a = QuadraticField(7).gen()
836
+ sage: a._arb_(RBF)
837
+ [2.645751311064590 +/- 7.17e-16]
838
+ sage: RBF(a)
839
+ [2.645751311064590 +/- 7.17e-16]
840
+
841
+ sage: a = QuadraticField(7, embedding=-AA(7).sqrt()).gen()
842
+ sage: a._arb_(RBF)
843
+ [-2.645751311064590 +/- 7.17e-16]
844
+
845
+ sage: a = QuadraticField(-1).gen()
846
+ sage: RBF(a)
847
+ Traceback (most recent call last):
848
+ ...
849
+ ValueError: nonzero imaginary part
850
+
851
+ This conversion takes care of cancellations::
852
+
853
+ sage: K.<a> = QuadraticField(3)
854
+ sage: b = (a - 1)**1000
855
+ sage: RBF(b)
856
+ [3.477155118441024e-136 +/- 8.45e-152]
857
+
858
+ TESTS:
859
+
860
+ Check that coercions and conversions go through this method::
861
+
862
+ sage: RBF.convert_map_from(QuadraticField(5))
863
+ Conversion via _arb_ method map:
864
+ From: Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?
865
+ To: Real ball field with 53 bits of precision
866
+ sage: RBF.coerce_map_from(QuadraticField(5, embedding=-AA(5).sqrt()))
867
+ Conversion via _arb_ method map:
868
+ From: Number Field in a with defining polynomial x^2 - 5 with a = -2.236067977499790?
869
+ To: Real ball field with 53 bits of precision
870
+ """
871
+ cdef RealBall res = RealBall.__new__(RealBall)
872
+ res._parent = R
873
+ if mpz_sgn(self.D.value) < 0 and mpz_sgn(self.b):
874
+ raise ValueError('nonzero imaginary part')
875
+ self.arb_set_real(res.value, R._prec)
876
+ return res
877
+
878
+ def _acb_(self, R):
879
+ r"""
880
+ Conversion to complex ball with parent ``R``.
881
+
882
+ EXAMPLES::
883
+
884
+ sage: K.<a> = QuadraticField(-3)
885
+ sage: CBF(1/7 + 3/2 * a)
886
+ [0.1428571428571428 +/- 7.70e-17] + [2.59807621135332 +/- 6.17e-15]*I
887
+ sage: CBF(1/7) + CBF(3/2) * CBF(a)
888
+ [0.1428571428571428 +/- 7.70e-17] + [2.59807621135332 +/- 5.21e-15]*I
889
+
890
+ sage: a._acb_(CBF)
891
+ [1.732050807568877 +/- 4.16e-16]*I
892
+
893
+ TESTS:
894
+
895
+ Check that coercions and conversions go through this method::
896
+
897
+ sage: CBF.convert_map_from(QuadraticField(-3))
898
+ Conversion via _acb_ method map:
899
+ From: Number Field in a with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
900
+ To: Complex ball field with 53 bits of precision
901
+
902
+ sage: CBF.coerce_map_from(QuadraticField(-3, embedding=-QQbar(-3).sqrt()))
903
+ Conversion via _acb_ method map:
904
+ From: Number Field in a with defining polynomial x^2 + 3 with a = -1.732050807568878?*I
905
+ To: Complex ball field with 53 bits of precision
906
+ """
907
+ cdef ComplexBall res = ComplexBall.__new__(ComplexBall)
908
+ res._parent = R
909
+ self.arb_set_real(acb_realref(res.value), R._prec)
910
+ self.arb_set_imag(acb_imagref(res.value), R._prec)
911
+ return res
912
+
913
+ cpdef tuple parts(self):
914
+ r"""
915
+ Return a pair of rationals `a` and `b` such that ``self`` `=
916
+ a+b\sqrt{D}`.
917
+
918
+ This is much closer to the internal storage format of the
919
+ elements than the polynomial representation coefficients (the output of
920
+ ``self.list()``), unless the generator with which this number field was
921
+ constructed was equal to `\sqrt{D}`. See the last example below.
922
+
923
+ EXAMPLES::
924
+
925
+ sage: x = polygen(ZZ, 'x')
926
+ sage: K.<a> = NumberField(x^2 - 13)
927
+ sage: K.discriminant()
928
+ 13
929
+ sage: a.parts()
930
+ (0, 1)
931
+ sage: (a/2 - 4).parts()
932
+ (-4, 1/2)
933
+ sage: K.<a> = NumberField(x^2 - 7)
934
+ sage: K.discriminant()
935
+ 28
936
+ sage: a.parts()
937
+ (0, 1)
938
+ sage: K.<a> = NumberField(x^2 - x + 7)
939
+ sage: a.parts()
940
+ (1/2, 3/2)
941
+ sage: a._coefficients()
942
+ [0, 1]
943
+ """
944
+ cdef Rational ad = <Rational>Rational.__new__(Rational)
945
+ cdef Rational bd = <Rational>Rational.__new__(Rational)
946
+ if mpz_cmp_ui(self.a, 0) == 0:
947
+ mpq_set_ui(ad.value, 0, 1)
948
+ else:
949
+ mpz_set(mpq_numref(ad.value), self.a)
950
+ mpz_set(mpq_denref(ad.value), self.denom)
951
+ mpq_canonicalize(ad.value)
952
+ if mpz_cmp_ui(self.b, 0) == 0:
953
+ mpq_set_ui(bd.value, 0, 1)
954
+ else:
955
+ mpz_set(mpq_numref(bd.value), self.b)
956
+ mpz_set(mpq_denref(bd.value), self.denom)
957
+ mpq_canonicalize(bd.value)
958
+
959
+ return (ad, bd)
960
+
961
+ #########################################################
962
+ # Comparisons
963
+ #########################################################
964
+
965
+ def sign(self):
966
+ r"""
967
+ Return the sign of ``self`` (`0` if zero, `+1` if positive, and `-1` if
968
+ negative).
969
+
970
+ EXAMPLES::
971
+
972
+ sage: K.<sqrt2> = QuadraticField(2, name='sqrt2')
973
+ sage: K(0).sign()
974
+ 0
975
+ sage: sqrt2.sign()
976
+ 1
977
+ sage: (sqrt2+1).sign()
978
+ 1
979
+ sage: (sqrt2-1).sign()
980
+ 1
981
+ sage: (sqrt2-2).sign()
982
+ -1
983
+ sage: (-sqrt2).sign()
984
+ -1
985
+ sage: (-sqrt2+1).sign()
986
+ -1
987
+ sage: (-sqrt2+2).sign()
988
+ 1
989
+
990
+ sage: K.<a> = QuadraticField(2, embedding=-1.4142)
991
+ sage: K(0).sign()
992
+ 0
993
+ sage: a.sign()
994
+ -1
995
+ sage: (a+1).sign()
996
+ -1
997
+ sage: (a+2).sign()
998
+ 1
999
+ sage: (a-1).sign()
1000
+ -1
1001
+ sage: (-a).sign()
1002
+ 1
1003
+ sage: (-a-1).sign()
1004
+ 1
1005
+ sage: (-a-2).sign()
1006
+ -1
1007
+
1008
+ sage: # needs sage.symbolic
1009
+ sage: x = polygen(ZZ, 'x')
1010
+ sage: K.<b> = NumberField(x^2 + 2*x + 7, 'b', embedding=CC(-1,-sqrt(6)))
1011
+ sage: b.sign()
1012
+ Traceback (most recent call last):
1013
+ ...
1014
+ ValueError: a complex number has no sign!
1015
+ sage: K(1).sign()
1016
+ 1
1017
+ sage: K(0).sign()
1018
+ 0
1019
+ sage: K(-2/3).sign()
1020
+ -1
1021
+ """
1022
+ cdef mpz_t i, j
1023
+ cdef int s = 1, test
1024
+
1025
+ if mpz_sgn(self.b) == 0:
1026
+ return mpz_sgn(self.a)
1027
+
1028
+ if mpz_sgn(self.D.value) == -1:
1029
+ raise ValueError("a complex number has no sign!")
1030
+
1031
+ if not self.standard_embedding:
1032
+ s = -1
1033
+
1034
+ if mpz_sgn(self.a) == 0:
1035
+ return s*mpz_sgn(self.b)
1036
+
1037
+ if mpz_sgn(self.a) == 1:
1038
+ if mpz_sgn(self.b) == s:
1039
+ return 1
1040
+
1041
+ elif mpz_sgn(self.b) == -s:
1042
+ return -1
1043
+
1044
+ mpz_init_set(i,self.a)
1045
+ mpz_mul(i,i,i)
1046
+ mpz_init_set(j,self.b)
1047
+ mpz_mul(j,j,j)
1048
+ mpz_mul(j,j,self.D.value)
1049
+ test = mpz_cmp(i,j)
1050
+ mpz_clear(i)
1051
+ mpz_clear(j)
1052
+ if test > 0:
1053
+ test = 1
1054
+ elif test < 0:
1055
+ test = -1
1056
+ if mpz_sgn(self.a) == 1 and mpz_sgn(self.b) == -s:
1057
+ return test
1058
+ return -test
1059
+
1060
+ cpdef _richcmp_(left, _right, int op):
1061
+ r"""
1062
+ Rich comparison of elements.
1063
+
1064
+ TESTS::
1065
+
1066
+ sage: K.<i> = QuadraticField(-1)
1067
+ sage: sorted([5*i+1, 2, 3*i+1, 2-i])
1068
+ [3*i + 1, 5*i + 1, -i + 2, 2]
1069
+
1070
+ Make some random tests to check that the order is compatible with the
1071
+ ones of the real field (RR) and complex field (CC)::
1072
+
1073
+ sage: x = polygen(ZZ, 'x')
1074
+ sage: K1 = NumberField(x^2 - 2, 'a', embedding=RR(1.4))
1075
+ sage: K2 = NumberField(x^2 - 2, 'a', embedding=RR(-1.4))
1076
+ sage: for _ in range(500): # long time
1077
+ ....: for K in K1, K2:
1078
+ ....: a = K.random_element()
1079
+ ....: b = K.random_element()
1080
+ ....: assert (a < b) == (RR(a) < RR(b))
1081
+ ....: assert (a > b) == (RR(a) > RR(b))
1082
+ ....: assert (a == b) == (RR(a) == RR(b))
1083
+ ....: assert (a != b) == (RR(a) != RR(b))
1084
+ ....: assert (a >= b) == (RR(a) >= RR(b))
1085
+ ....: assert (a <= b) == (RR(a) <= RR(b))
1086
+
1087
+ ::
1088
+
1089
+ sage: K1 = NumberField(x^2 + 2, 'a', embedding=CC(0,1))
1090
+ sage: K2 = NumberField(x^2 + 2, 'a', embedding=CC(0,-1))
1091
+ sage: for _ in range(500): # long time
1092
+ ....: for K in K1, K2:
1093
+ ....: a = K.random_element()
1094
+ ....: b = K.random_element()
1095
+ ....: assert (a < b) == (CC(a) < CC(b))
1096
+ ....: assert (a > b) == (CC(a) > CC(b))
1097
+ ....: assert (a == b) == (CC(a) == CC(b))
1098
+ ....: assert (a != b) == (CC(a) != CC(b))
1099
+ ....: assert (a >= b) == (CC(a) >= CC(b))
1100
+ ....: assert (a <= b) == (CC(a) <= CC(b))
1101
+
1102
+ The following is tested because of the implementation of
1103
+ :func:`Q_to_quadratic_field_element` which was the cause of
1104
+ some problems with :issue:`13213`::
1105
+
1106
+ sage: K.<sqrt2> = QuadraticField(2)
1107
+ sage: 1/2 + sqrt2 > 0
1108
+ True
1109
+
1110
+ Two examples from the same number field with its two possible real
1111
+ embeddings::
1112
+
1113
+ sage: K.<phi> = NumberField(x^2-x-1, 'phi', embedding=1.618)
1114
+ sage: phi > 0
1115
+ True
1116
+ sage: -phi > 0
1117
+ False
1118
+ sage: phi - 3 == 2*phi + 1
1119
+ False
1120
+ sage: fibonacci(10)*phi < fibonacci(11)
1121
+ True
1122
+ sage: RDF(fibonacci(10)*phi)
1123
+ 88.99186938124421
1124
+ sage: fibonacci(11)
1125
+ 89
1126
+ sage: l = [-2, phi+3, 2*phi-1, 2*phi-5, 0, -phi+2, fibonacci(20)*phi - fibonacci(21)]
1127
+ sage: l.sort()
1128
+ sage: l
1129
+ [-2, 2*phi - 5, 6765*phi - 10946, 0, -phi + 2, 2*phi - 1, phi + 3]
1130
+ sage: list(map(RDF, l))
1131
+ [-2.0, -1.7639320225002102, -6.610696073039435e-05, 0.0, 0.3819660112501051, 2.23606797749979, 4.618033988749895]
1132
+
1133
+ ::
1134
+
1135
+ sage: L.<psi> = NumberField(x^2-x-1, 'psi', embedding=-0.618)
1136
+ sage: psi < 0
1137
+ True
1138
+ sage: 2*psi + 3 == 2*psi + 3
1139
+ True
1140
+ sage: fibonacci(10)*psi < -fibonacci(9)
1141
+ False
1142
+ sage: RDF(fibonacci(10)*psi)
1143
+ -33.99186938124422
1144
+ sage: fibonacci(9)
1145
+ 34
1146
+ sage: l = [-1, psi, 0, fibonacci(20)*psi + fibonacci(19), 3*psi+2]
1147
+ sage: l.sort()
1148
+ sage: l
1149
+ [-1, psi, 0, 6765*psi + 4181, 3*psi + 2]
1150
+ sage: list(map(RDF, l))
1151
+ [-1.0, -0.6180339887498949, 0.0, 6.610696073039435e-05, 0.1458980337503153]
1152
+
1153
+ For a field with no specified embedding the comparison uses the standard
1154
+ embedding::
1155
+
1156
+ sage: K.<sqrt2> = NumberField(x^2-2, 'sqrt2')
1157
+ sage: sqrt2 > 1 and sqrt2 < 2
1158
+ True
1159
+
1160
+ The following examples illustrate the same behavior for a complex
1161
+ quadratic field::
1162
+
1163
+ sage: K.<i> = QuadraticField(-1)
1164
+ sage: l = [-2, i-3, 2*i-2, 2*i+2, 5*i, 1-3*i, -1+i, 1]
1165
+ sage: l.sort()
1166
+ sage: l
1167
+ [i - 3, -2, 2*i - 2, i - 1, 5*i, -3*i + 1, 1, 2*i + 2]
1168
+ sage: list(map(CDF, l))
1169
+ [-3.0 + 1.0*I, -2.0, -2.0 + 2.0*I, -1.0 + 1.0*I, 5.0*I, 1.0 - 3.0*I, 1.0, 2.0 + 2.0*I]
1170
+ sage: list(map(CDF, l)) == sorted(map(CDF, l))
1171
+ True
1172
+ """
1173
+ # When D > 0 and standard embedding, we compare (a + b * sqrt(D)) / d and (aa +
1174
+ # bb * sqrt(D)) / dd using the comparison of (dd*a - d * aa)^2 and (d*bb - dd*b)^2 * D
1175
+ # mpz_sgn: returns 1 if > 0, 0 if 0 and -1 if < 0
1176
+ cdef mpz_t i, j
1177
+ cdef NumberFieldElement_quadratic right = <NumberFieldElement_quadratic> _right
1178
+ cdef int test
1179
+
1180
+ # inequality and equality
1181
+ if mpz_cmp(left.a, right.a) or mpz_cmp(left.b, right.b) or mpz_cmp(left.denom, right.denom):
1182
+ if op == Py_EQ:
1183
+ return False
1184
+ elif op == Py_NE:
1185
+ return True
1186
+ else: # equality
1187
+ if op == Py_EQ or op == Py_LE or op == Py_GE:
1188
+ return True
1189
+ if op == Py_NE or op == Py_LT or op == Py_GT:
1190
+ return False
1191
+
1192
+ # comparisons are valid only in *real* quadratic number field
1193
+ # when no embedding is specified or in the case of complex embeddings we
1194
+ # use a lexicographic order.
1195
+ if mpz_sgn(left.D.value) == -1:
1196
+ mpz_init(i)
1197
+ mpz_init(j)
1198
+ mpz_mul(i, left.a, right.denom)
1199
+ mpz_mul(j, right.a, left.denom)
1200
+ test = mpz_cmp(i,j)
1201
+ if test:
1202
+ mpz_clear(i)
1203
+ mpz_clear(j)
1204
+ return rich_to_bool_sgn(op, test)
1205
+ mpz_mul(i, left.b, right.denom)
1206
+ mpz_mul(j, right.b, left.denom)
1207
+ test = mpz_cmp(i,j)
1208
+ if test:
1209
+ if not left.standard_embedding:
1210
+ test = -test
1211
+ mpz_clear(i)
1212
+ mpz_clear(j)
1213
+ return rich_to_bool_sgn(op, test)
1214
+ test = mpz_cmp(left.denom, right.denom)
1215
+ mpz_clear(i)
1216
+ mpz_clear(j)
1217
+ return rich_to_bool_sgn(op, test)
1218
+
1219
+ # comparison in the real case
1220
+ mpz_init(i)
1221
+ mpz_mul(i, right.denom, left.a)
1222
+ mpz_submul(i, left.denom, right.a)
1223
+
1224
+ mpz_init(j)
1225
+ mpz_mul(j, left.denom, right.b)
1226
+ mpz_submul(j, right.denom, left.b)
1227
+
1228
+ if not left.standard_embedding:
1229
+ mpz_neg(j, j)
1230
+
1231
+ if mpz_sgn(i) == 1:
1232
+ if mpz_sgn(j) == 1:
1233
+ mpz_mul(i, i, i)
1234
+ mpz_mul(j, j, j)
1235
+ mpz_mul(j, j, left.D.value)
1236
+ test = mpz_cmp(i, j)
1237
+ else:
1238
+ test = 1
1239
+
1240
+ else:
1241
+ if mpz_sgn(j) == -1:
1242
+ mpz_mul(i, i, i)
1243
+ mpz_mul(j, j, j)
1244
+ mpz_mul(j, j, left.D.value)
1245
+ test = mpz_cmp(j, i)
1246
+ else:
1247
+ test = -1
1248
+
1249
+ mpz_clear(i)
1250
+ mpz_clear(j)
1251
+ return rich_to_bool_sgn(op, test)
1252
+
1253
+ def continued_fraction_list(self):
1254
+ r"""
1255
+ Return the preperiod and the period of the continued fraction expansion
1256
+ of ``self``.
1257
+
1258
+ EXAMPLES::
1259
+
1260
+ sage: K.<sqrt2> = QuadraticField(2)
1261
+ sage: sqrt2.continued_fraction_list()
1262
+ ((1,), (2,))
1263
+ sage: (1/2 + sqrt2/3).continued_fraction_list()
1264
+ ((0, 1, 33), (1, 32))
1265
+
1266
+ For rational entries a pair of tuples is also returned but the second
1267
+ one is empty::
1268
+
1269
+ sage: K(123/567).continued_fraction_list()
1270
+ ((0, 4, 1, 1, 1, 1, 3, 2), ())
1271
+ """
1272
+ if mpz_sgn(self.b) == 0:
1273
+ return tuple(Rational(self).continued_fraction_list()),()
1274
+
1275
+ if mpz_sgn(self.D.value) < 0:
1276
+ raise ValueError("the method is only available for positive discriminant")
1277
+
1278
+ x = self
1279
+ orbit = []
1280
+ quots = []
1281
+ while x not in orbit:
1282
+ quots.append(x.floor())
1283
+ orbit.append(x)
1284
+ x = ~(x - quots[-1])
1285
+
1286
+ i = orbit.index(x)
1287
+
1288
+ return tuple(quots[:i]), tuple(quots[i:])
1289
+
1290
+ def continued_fraction(self):
1291
+ r"""
1292
+ Return the (finite or ultimately periodic) continued fraction of ``self``.
1293
+
1294
+ EXAMPLES::
1295
+
1296
+ sage: K.<sqrt2> = QuadraticField(2)
1297
+ sage: cf = sqrt2.continued_fraction(); cf
1298
+ [1; (2)*]
1299
+ sage: cf.n()
1300
+ 1.41421356237310
1301
+ sage: sqrt2.n()
1302
+ 1.41421356237309
1303
+ sage: cf.value()
1304
+ sqrt2
1305
+
1306
+ sage: (sqrt2/3 + 1/4).continued_fraction()
1307
+ [0; 1, (2, 1, 1, 2, 3, 2, 1, 1, 2, 5, 1, 1, 14, 1, 1, 5)*]
1308
+ """
1309
+ t1,t2 = self.continued_fraction_list()
1310
+ from sage.rings.continued_fraction import ContinuedFraction_periodic
1311
+ return ContinuedFraction_periodic(t1,t2)
1312
+
1313
+ #########################################################
1314
+ # Arithmetic
1315
+ #########################################################
1316
+
1317
+ cdef void _reduce_c_(self) noexcept:
1318
+ r"""
1319
+ Reduces into canonical form.
1320
+
1321
+ WARNING: this mutates ``self``.
1322
+ """
1323
+ cdef mpz_t gcd
1324
+ # cancel out common factors
1325
+ mpz_init(gcd)
1326
+ mpz_gcd(gcd, self.a, self.denom)
1327
+ mpz_gcd(gcd, gcd, self.b)
1328
+ if mpz_cmp_si(gcd, 1): # != 0 (i.e. it is not 1)
1329
+ mpz_divexact(self.a, self.a, gcd)
1330
+ mpz_divexact(self.b, self.b, gcd)
1331
+ mpz_divexact(self.denom, self.denom, gcd)
1332
+ # make denominator positive
1333
+ if mpz_sgn(self.denom) < 0:
1334
+ mpz_neg(self.denom, self.denom)
1335
+ mpz_neg(self.a, self.a)
1336
+ mpz_neg(self.b, self.b)
1337
+ mpz_clear(gcd)
1338
+
1339
+ cpdef _add_(self, other_m):
1340
+ """
1341
+ EXAMPLES::
1342
+
1343
+ sage: x = polygen(ZZ, 'x')
1344
+ sage: K.<a> = NumberField(x^2 - 5)
1345
+ sage: K.discriminant()
1346
+ 5
1347
+ sage: a+a # indirect doctest
1348
+ 2*a
1349
+ sage: s = (a+2)/6; s
1350
+ 1/6*a + 1/3
1351
+ sage: s+a
1352
+ 7/6*a + 1/3
1353
+ sage: s+10
1354
+ 1/6*a + 31/3
1355
+ sage: s+(2*a+5)/7
1356
+ 19/42*a + 22/21
1357
+ sage: s+(1+a)/2
1358
+ 2/3*a + 5/6
1359
+ sage: s+(1+a)/8
1360
+ 7/24*a + 11/24
1361
+ sage: s+(a+5)/6
1362
+ 1/3*a + 7/6
1363
+ sage: (a/3+2/3) + (2*a/3+1/3)
1364
+ a + 1
1365
+ """
1366
+ cdef NumberFieldElement_quadratic other = <NumberFieldElement_quadratic>other_m
1367
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1368
+ cdef mpz_t gcd, tmp
1369
+ if mpz_cmp(self.denom, other.denom) == 0:
1370
+ mpz_add(res.a, self.a, other.a)
1371
+ mpz_add(res.b, self.b, other.b)
1372
+ mpz_set(res.denom, self.denom)
1373
+ else:
1374
+ mpz_init(gcd)
1375
+ mpz_gcd(gcd, self.denom, other.denom)
1376
+ if mpz_cmp_ui(gcd, 1) == 0:
1377
+ mpz_mul(res.a, self.a, other.denom)
1378
+ mpz_addmul(res.a, self.denom, other.a)
1379
+ mpz_mul(res.b, self.b, other.denom)
1380
+ mpz_addmul(res.b, self.denom, other.b)
1381
+ mpz_mul(res.denom, self.denom, other.denom)
1382
+ else:
1383
+ mpz_init(tmp)
1384
+ mpz_divexact(tmp, other.denom, gcd)
1385
+ mpz_mul(res.a, self.a, tmp)
1386
+ mpz_mul(res.b, self.b, tmp)
1387
+ mpz_divexact(tmp, self.denom, gcd)
1388
+ mpz_addmul(res.a, other.a, tmp)
1389
+ mpz_addmul(res.b, other.b, tmp)
1390
+ mpz_mul(res.denom, other.denom, tmp)
1391
+ mpz_clear(tmp)
1392
+ mpz_clear(gcd)
1393
+ res._reduce_c_()
1394
+ return res
1395
+
1396
+ cpdef _sub_(self, other_m):
1397
+ """
1398
+ EXAMPLES::
1399
+
1400
+ sage: x = polygen(ZZ, 'x')
1401
+ sage: K.<a> = NumberField(x^2 - 13)
1402
+ sage: b = (a-3)/10; b # indirect doctest
1403
+ 1/10*a - 3/10
1404
+ sage: b-1
1405
+ 1/10*a - 13/10
1406
+ sage: b-a
1407
+ -9/10*a - 3/10
1408
+ sage: b-1/2
1409
+ 1/10*a - 4/5
1410
+ sage: b-a/15
1411
+ 1/30*a - 3/10
1412
+ """
1413
+ cdef NumberFieldElement_quadratic other = <NumberFieldElement_quadratic>other_m
1414
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1415
+ cdef mpz_t gcd, tmp
1416
+ if mpz_cmp(self.denom, other.denom) == 0:
1417
+ mpz_sub(res.a, self.a, other.a)
1418
+ mpz_sub(res.b, self.b, other.b)
1419
+ mpz_set(res.denom, self.denom)
1420
+ else:
1421
+ mpz_init(gcd)
1422
+ mpz_gcd(gcd, self.denom, other.denom)
1423
+ if mpz_cmp_ui(gcd, 1) == 0:
1424
+ mpz_mul(res.a, self.a, other.denom)
1425
+ mpz_submul(res.a, self.denom, other.a)
1426
+ mpz_mul(res.b, self.b, other.denom)
1427
+ mpz_submul(res.b, self.denom, other.b)
1428
+ mpz_mul(res.denom, self.denom, other.denom)
1429
+ else:
1430
+ mpz_init(tmp)
1431
+ mpz_divexact(tmp, other.denom, gcd)
1432
+ mpz_mul(res.a, self.a, tmp)
1433
+ mpz_mul(res.b, self.b, tmp)
1434
+ mpz_divexact(tmp, self.denom, gcd)
1435
+ mpz_submul(res.a, other.a, tmp)
1436
+ mpz_submul(res.b, other.b, tmp)
1437
+ mpz_mul(res.denom, other.denom, tmp)
1438
+ mpz_clear(tmp)
1439
+ mpz_clear(gcd)
1440
+ res._reduce_c_()
1441
+ return res
1442
+
1443
+ def __neg__(self):
1444
+ """
1445
+ EXAMPLES::
1446
+
1447
+ sage: x = polygen(ZZ, 'x')
1448
+ sage: K.<a> = NumberField(x^2 + 163)
1449
+ sage: -a
1450
+ -a
1451
+ sage: -(a+4)
1452
+ -a - 4
1453
+ sage: b = (a-3)/2
1454
+ sage: -b
1455
+ -1/2*a + 3/2
1456
+ """
1457
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1458
+ mpz_neg(res.a, self.a)
1459
+ mpz_neg(res.b, self.b)
1460
+ mpz_set(res.denom, self.denom)
1461
+ return res
1462
+
1463
+ cpdef _mul_(self, other_m):
1464
+ """
1465
+ EXAMPLES::
1466
+
1467
+ sage: x = polygen(ZZ, 'x')
1468
+ sage: K.<a> = NumberField(x^2 + 23)
1469
+ sage: a*a # indirect doctest
1470
+ -23
1471
+ sage: (a+1)*(a-1)
1472
+ -24
1473
+ sage: (a+1)*(a+2)
1474
+ 3*a - 21
1475
+ sage: (a+1)/2 * (a+2)
1476
+ 3/2*a - 21/2
1477
+ sage: (a+1)/2 * (a+2)/3
1478
+ 1/2*a - 7/2
1479
+ sage: (2*a+4) * (3*a)/2
1480
+ 6*a - 69
1481
+
1482
+ Verify Karatsuba::
1483
+
1484
+ sage: K.<a> = NumberField(x^2-41)
1485
+ sage: (10^1000 * (a+1)) * K(2+3*a) == 10^1000 * ((a+1) * K(2+3*a))
1486
+ True
1487
+
1488
+ TESTS:
1489
+
1490
+ Test that :issue:`30360` is fixed::
1491
+
1492
+ sage: K.<sqrt5> = QuadraticField(5, embedding=AA(5).sqrt())
1493
+ sage: sqrt5*vector([1,2])
1494
+ (sqrt5, 2*sqrt5)
1495
+ """
1496
+ cdef NumberFieldElement_quadratic other = <NumberFieldElement_quadratic>other_m
1497
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1498
+ cdef mpz_t tmp
1499
+
1500
+ if mpz_size(self.a) + mpz_size(self.b) < 8: # could I use a macro instead?
1501
+ # Do it the traditional way
1502
+ mpz_mul(res.a, self.b, other.b)
1503
+ mpz_mul(res.a, res.a, self.D.value)
1504
+ mpz_addmul(res.a, self.a, other.a)
1505
+
1506
+ mpz_mul(res.b, self.a, other.b)
1507
+ mpz_addmul(res.b, self.b, other.a)
1508
+
1509
+ else:
1510
+ # Karatsuba
1511
+ sig_on()
1512
+ mpz_init(tmp)
1513
+ mpz_add(res.a, self.a, self.b) # using res.a as tmp
1514
+ mpz_add(tmp, other.a, other.b)
1515
+ mpz_mul(res.b, res.a, tmp) # res.b = (self.a + self.b)(other.a + other.b)
1516
+
1517
+ mpz_mul(res.a, self.a, other.a)
1518
+ mpz_sub(res.b, res.b, res.a)
1519
+ mpz_mul(tmp, self.b, other.b)
1520
+ mpz_sub(res.b, res.b, tmp)
1521
+ mpz_mul(tmp, tmp, self.D.value)
1522
+ mpz_add(res.a, res.a, tmp)
1523
+ mpz_clear(tmp)
1524
+ sig_off()
1525
+
1526
+ mpz_mul(res.denom, self.denom, other.denom)
1527
+ res._reduce_c_()
1528
+ return res
1529
+
1530
+ cpdef _rmul_(self, Element _c):
1531
+ """
1532
+ EXAMPLES::
1533
+
1534
+ sage: x = polygen(ZZ, 'x')
1535
+ sage: K.<a> = NumberField(x^2 + 43)
1536
+ sage: (1+a)*3 # indirect doctest
1537
+ 3*a + 3
1538
+ """
1539
+ cdef Rational c = <Rational>_c
1540
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1541
+ mpz_mul(res.a, self.a, mpq_numref(c.value))
1542
+ mpz_mul(res.b, self.b, mpq_numref(c.value))
1543
+ mpz_mul(res.denom, self.denom, mpq_denref(c.value))
1544
+ res._reduce_c_()
1545
+ return res
1546
+
1547
+ cpdef _lmul_(self, Element _c):
1548
+ """
1549
+ EXAMPLES::
1550
+
1551
+ sage: x = polygen(ZZ, 'x')
1552
+ sage: K.<a> = NumberField(x^2 + 43)
1553
+ sage: 5*(a-1/5) # indirect doctest
1554
+ 5*a - 1
1555
+ """
1556
+ cdef Rational c = <Rational>_c
1557
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1558
+ mpz_mul(res.a, self.a, mpq_numref(c.value))
1559
+ mpz_mul(res.b, self.b, mpq_numref(c.value))
1560
+ mpz_mul(res.denom, self.denom, mpq_denref(c.value))
1561
+ res._reduce_c_()
1562
+ return res
1563
+
1564
+ def __invert__(self):
1565
+ """
1566
+ EXAMPLES::
1567
+
1568
+ sage: x = polygen(ZZ, 'x')
1569
+ sage: K.<a> = NumberField(x^2 - 5)
1570
+ sage: ~a
1571
+ 1/5*a
1572
+ sage: ~(a+1)
1573
+ 1/4*a - 1/4
1574
+ sage: (a-1)*(a+1)
1575
+ 4
1576
+ sage: b = ~(5*a-3); b
1577
+ 5/116*a + 3/116
1578
+ sage: b*(5*a-3)
1579
+ 1
1580
+ sage: b = ~((3*a-2)/7); b
1581
+ 21/41*a + 14/41
1582
+ sage: (3*a-2)/7 * b
1583
+ 1
1584
+
1585
+ This fixes issue :issue:`9357`::
1586
+
1587
+ sage: K.<a> = NumberField(x^2+1)
1588
+ sage: d = K(0)
1589
+ sage: ~d
1590
+ Traceback (most recent call last):
1591
+ ...
1592
+ ZeroDivisionError: number field element division by zero
1593
+ sage: K.random_element() / d
1594
+ Traceback (most recent call last):
1595
+ ...
1596
+ ZeroDivisionError: number field element division by zero
1597
+ """
1598
+ if mpz_cmp_ui(self.a, 0) == 0 and mpz_cmp_ui(self.b, 0) == 0:
1599
+ raise ZeroDivisionError("number field element division by zero")
1600
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1601
+ cdef mpz_t tmp, gcd
1602
+ mpz_init(tmp)
1603
+ mpz_init(gcd)
1604
+
1605
+ mpz_gcd(gcd, self.a, self.b)
1606
+ if mpz_cmp_si(gcd, 1): # != 0 (i.e. it is not 1)
1607
+ # cancel out g (g(a'-b'd)) / (g^2 (a'^2-b'^2d^2))
1608
+ mpz_divexact(res.a, self.a, gcd)
1609
+ mpz_divexact(res.b, self.b, gcd)
1610
+ mpz_neg(res.b, res.b)
1611
+ else:
1612
+ mpz_set(res.a, self.a)
1613
+ mpz_neg(res.b, self.b)
1614
+
1615
+ mpz_pow_ui(res.denom, res.a, 2)
1616
+ mpz_pow_ui(tmp, res.b, 2)
1617
+ mpz_mul(tmp, tmp, self.D.value)
1618
+ mpz_sub(res.denom, res.denom, tmp)
1619
+ # need to multiply the leftover g back in
1620
+ mpz_mul(res.denom, res.denom, gcd)
1621
+
1622
+ mpz_mul(res.a, res.a, self.denom)
1623
+ mpz_mul(res.b, res.b, self.denom)
1624
+
1625
+ mpz_clear(tmp)
1626
+ mpz_clear(gcd)
1627
+
1628
+ res._reduce_c_()
1629
+ return res
1630
+
1631
+ cpdef NumberFieldElement galois_conjugate(self):
1632
+ """
1633
+ Return the image of this element under action of the nontrivial
1634
+ element of the Galois group of this field.
1635
+
1636
+ EXAMPLES::
1637
+
1638
+ sage: K.<a> = QuadraticField(23)
1639
+ sage: a.galois_conjugate()
1640
+ -a
1641
+
1642
+ sage: x = polygen(ZZ, 'x')
1643
+ sage: K.<a> = NumberField(x^2 - 5*x + 1)
1644
+ sage: a.galois_conjugate()
1645
+ -a + 5
1646
+ sage: b = 5*a + 1/3
1647
+ sage: b.galois_conjugate()
1648
+ -5*a + 76/3
1649
+ sage: b.norm() == b * b.galois_conjugate()
1650
+ True
1651
+ sage: b.trace() == b + b.galois_conjugate()
1652
+ True
1653
+ """
1654
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
1655
+ mpz_set(res.a, self.a)
1656
+ mpz_neg(res.b, self.b)
1657
+ mpz_set(res.denom, self.denom)
1658
+ return res
1659
+
1660
+ #################################################################################
1661
+ # We must override everything that makes uses of self._numerator/_denominator
1662
+ #################################################################################
1663
+
1664
+ def __hash__(self):
1665
+ r"""
1666
+ Return hash of this number field element.
1667
+
1668
+ For elements in `\ZZ` or `\QQ` the hash coincides with the one in the
1669
+ native `\ZZ` or `\QQ`.
1670
+
1671
+ EXAMPLES::
1672
+
1673
+ sage: L.<a> = QuadraticField(-7)
1674
+ sage: hash(a)
1675
+ 42082631
1676
+ sage: hash(L(1))
1677
+ 1
1678
+ sage: hash(L(-3))
1679
+ -3
1680
+ sage: hash(L(-32/118)) == hash(-32/118)
1681
+ True
1682
+ """
1683
+ # 1. compute the hash of a/denom as if it was a rational
1684
+ # (see the corresponding code in sage/rings/rational.pyx)
1685
+ cdef Py_hash_t n = mpz_pythonhash(self.a)
1686
+ cdef Py_hash_t d = mpz_pythonhash(self.denom)
1687
+ cdef Py_hash_t h = n + (d - 1) * <Py_hash_t>(7461864723258187525)
1688
+
1689
+ # 2. mix the hash together with b
1690
+ h += 42082631 * mpz_pythonhash(self.b)
1691
+ return h
1692
+
1693
+ def __bool__(self):
1694
+ """
1695
+ Check whether this element is not zero.
1696
+
1697
+ EXAMPLES::
1698
+
1699
+ sage: x = polygen(ZZ, 'x')
1700
+ sage: K.<a> = NumberField(x^2 + 163)
1701
+ sage: not a
1702
+ False
1703
+ sage: not (a-a)
1704
+ True
1705
+ """
1706
+ return mpz_cmp_ui(self.a, 0) != 0 or mpz_cmp_ui(self.b, 0) != 0
1707
+
1708
+ def _integer_(self, Z=None):
1709
+ """
1710
+ EXAMPLES::
1711
+
1712
+ sage: x = polygen(ZZ, 'x')
1713
+ sage: K.<a> = NumberField(x^2 + 163)
1714
+ sage: (a+1-a)._integer_()
1715
+ 1
1716
+ sage: (a+1/2-a)._integer_()
1717
+ Traceback (most recent call last):
1718
+ ...
1719
+ TypeError: Unable to coerce 1/2 to an integer
1720
+ """
1721
+ cdef Integer res
1722
+ if mpz_cmp_ui(self.b, 0) != 0 or mpz_cmp_ui(self.denom, 1) != 0:
1723
+ raise TypeError("Unable to coerce %s to an integer" % self)
1724
+ else:
1725
+ res = Integer.__new__(Integer)
1726
+ mpz_set(res.value, self.a)
1727
+ return res
1728
+
1729
+ def _rational_(self):
1730
+ """
1731
+ EXAMPLES::
1732
+
1733
+ sage: x = polygen(ZZ, 'x')
1734
+ sage: K.<a> = NumberField(x^2 + 163)
1735
+ sage: (a+1/2-a)._rational_()
1736
+ 1/2
1737
+ sage: (a+1/2)._rational_()
1738
+ Traceback (most recent call last):
1739
+ ...
1740
+ TypeError: Unable to coerce a + 1/2 to a rational
1741
+ """
1742
+ cdef Rational res
1743
+ if mpz_cmp_ui(self.b, 0)!=0:
1744
+ raise TypeError("Unable to coerce %s to a rational" % self)
1745
+ else:
1746
+ res = <Rational>Rational.__new__(Rational)
1747
+ mpz_set(mpq_numref(res.value), self.a)
1748
+ mpz_set(mpq_denref(res.value), self.denom)
1749
+ mpq_canonicalize(res.value)
1750
+ return res
1751
+
1752
+ cpdef bint is_one(self) noexcept:
1753
+ r"""
1754
+ Check whether this number field element is `1`.
1755
+
1756
+ EXAMPLES::
1757
+
1758
+ sage: K = QuadraticField(-2)
1759
+ sage: K(1).is_one()
1760
+ True
1761
+ sage: K(-1).is_one()
1762
+ False
1763
+ sage: K(2).is_one()
1764
+ False
1765
+ sage: K(0).is_one()
1766
+ False
1767
+ sage: K(1/2).is_one()
1768
+ False
1769
+ sage: K.gen().is_one()
1770
+ False
1771
+ """
1772
+ return (mpz_cmp_ui(self.a, 1) == 0 and
1773
+ mpz_cmp_ui(self.b, 0) == 0 and
1774
+ mpz_cmp_ui(self.denom, 1) == 0)
1775
+
1776
+ cpdef bint is_rational(self) noexcept:
1777
+ r"""
1778
+ Check whether this number field element is a rational number.
1779
+
1780
+ .. SEEALSO::
1781
+
1782
+ - :meth:`is_integer` to test if this element is an integer
1783
+ - :meth:`is_integral` to test if this element is an algebraic integer
1784
+
1785
+ EXAMPLES::
1786
+
1787
+ sage: K.<sqrt3> = QuadraticField(3)
1788
+ sage: sqrt3.is_rational()
1789
+ False
1790
+ sage: (sqrt3 - 1/2).is_rational()
1791
+ False
1792
+ sage: K(0).is_rational()
1793
+ True
1794
+ sage: K(-12).is_rational()
1795
+ True
1796
+ sage: K(1/3).is_rational()
1797
+ True
1798
+ """
1799
+ return mpz_cmp_ui(self.b, 0) == 0
1800
+
1801
+ def is_integer(self):
1802
+ r"""
1803
+ Check whether this number field element is an integer.
1804
+
1805
+ .. SEEALSO::
1806
+
1807
+ - :meth:`is_rational` to test if this element is a rational number
1808
+ - :meth:`is_integral` to test if this element is an algebraic integer
1809
+
1810
+ EXAMPLES::
1811
+
1812
+ sage: K.<sqrt3> = QuadraticField(3)
1813
+ sage: sqrt3.is_integer()
1814
+ False
1815
+ sage: (sqrt3 - 1/2).is_integer()
1816
+ False
1817
+ sage: K(0).is_integer()
1818
+ True
1819
+ sage: K(-12).is_integer()
1820
+ True
1821
+ sage: K(1/3).is_integer()
1822
+ False
1823
+ """
1824
+ return mpz_cmp_ui(self.b, 0) == mpz_cmp_ui(self.denom, 1) == 0
1825
+
1826
+ def real(self):
1827
+ r"""
1828
+ Return the real part of ``self``, which is either ``self`` (if
1829
+ ``self`` lives in a totally real field) or a rational number.
1830
+
1831
+ EXAMPLES::
1832
+
1833
+ sage: K.<sqrt2> = QuadraticField(2)
1834
+ sage: sqrt2.real()
1835
+ sqrt2
1836
+ sage: K.<a> = QuadraticField(-3)
1837
+ sage: a.real()
1838
+ 0
1839
+ sage: (a + 1/2).real()
1840
+ 1/2
1841
+ sage: x = polygen(ZZ, 'x')
1842
+ sage: K.<a> = NumberField(x^2 + x + 1)
1843
+ sage: a.real()
1844
+ -1/2
1845
+ sage: parent(a.real())
1846
+ Rational Field
1847
+ sage: K.<i> = QuadraticField(-1)
1848
+ sage: i.real()
1849
+ 0
1850
+ """
1851
+ cdef Rational res
1852
+ if mpz_sgn(self.D.value) > 0:
1853
+ return self # totally real
1854
+ else:
1855
+ res = <Rational>Rational.__new__(Rational)
1856
+ mpz_set(mpq_numref(res.value), self.a)
1857
+ mpz_set(mpq_denref(res.value), self.denom)
1858
+ mpq_canonicalize(res.value)
1859
+ return res
1860
+
1861
+ def imag(self):
1862
+ r"""
1863
+ Return the imaginary part of ``self``.
1864
+
1865
+ EXAMPLES::
1866
+
1867
+ sage: K.<sqrt2> = QuadraticField(2)
1868
+ sage: sqrt2.imag()
1869
+ 0
1870
+ sage: parent(sqrt2.imag())
1871
+ Rational Field
1872
+
1873
+ sage: K.<i> = QuadraticField(-1)
1874
+ sage: i.imag()
1875
+ 1
1876
+ sage: parent(i.imag())
1877
+ Rational Field
1878
+
1879
+ sage: x = polygen(ZZ, 'x')
1880
+ sage: K.<a> = NumberField(x^2 + x + 1, embedding=CDF.0)
1881
+ sage: a.imag()
1882
+ 1/2*sqrt3
1883
+ sage: a.real()
1884
+ -1/2
1885
+ sage: SR(a) # needs sage.symbolic
1886
+ 1/2*I*sqrt(3) - 1/2
1887
+ sage: bool(QQbar(I)*QQbar(a.imag()) + QQbar(a.real()) == QQbar(a))
1888
+ True
1889
+
1890
+ TESTS::
1891
+
1892
+ sage: K.<a> = QuadraticField(-9, embedding=-CDF.0)
1893
+ sage: a.imag()
1894
+ -3
1895
+ sage: parent(a.imag())
1896
+ Rational Field
1897
+
1898
+ Check that :issue:`22095` is fixed::
1899
+
1900
+ sage: K.<a> = NumberField(x^2 + 2*x + 14, embedding=CC(-1,+3))
1901
+ sage: K13.<sqrt13> = QuadraticField(13)
1902
+ sage: K13.zero()
1903
+ 0
1904
+ sage: a.imag()
1905
+ sqrt13
1906
+ sage: K13.zero()
1907
+ 0
1908
+ """
1909
+ if mpz_sgn(self.D.value) > 0:
1910
+ return Rational.__new__(Rational) # = 0
1911
+ cdef Integer negD = <Integer>Integer.__new__(Integer)
1912
+ mpz_neg(negD.value, self.D.value)
1913
+ cdef NumberFieldElement_quadratic q = <NumberFieldElement_quadratic>self._new()
1914
+ mpz_set_ui(q.b, 1)
1915
+ mpz_set_ui(q.denom, 1)
1916
+ cdef Rational res
1917
+ if mpz_cmp_ui(negD.value, 1) == 0 or mpz_perfect_square_p(negD.value):
1918
+ # D = -1 is the most common case we'll see here
1919
+ if self._parent._embedding is None:
1920
+ raise ValueError("Embedding must be specified.")
1921
+ res = <Rational>Rational.__new__(Rational)
1922
+ if mpz_cmp_ui(negD.value, 1) == 0:
1923
+ mpz_set(mpq_numref(res.value), self.b)
1924
+ else:
1925
+ mpz_sqrt(mpq_numref(res.value), negD.value)
1926
+ mpz_mul(mpq_numref(res.value), mpq_numref(res.value), self.b)
1927
+ mpz_set(mpq_denref(res.value), self.denom)
1928
+ mpq_canonicalize(res.value)
1929
+ if not self.standard_embedding:
1930
+ mpq_neg(res.value, res.value)
1931
+ return res
1932
+ else:
1933
+ # avoid circular import
1934
+ if self._parent._embedding is None:
1935
+ from sage.rings.number_field.number_field import NumberField
1936
+ K = NumberField(QQ['x'].gen()**2 - negD, 'sqrt%s' % negD)
1937
+ else:
1938
+ from sage.rings.number_field.number_field import QuadraticField
1939
+ K = QuadraticField(negD, 'sqrt%s' % negD)
1940
+ q = (<NumberFieldElement_quadratic> K._zero_element)._new()
1941
+ mpz_set(q.denom, self.denom)
1942
+ mpz_set_ui(q.a, 0)
1943
+ if self.standard_embedding:
1944
+ mpz_set(q.b, self.b)
1945
+ else:
1946
+ mpz_neg(q.b, self.b)
1947
+ return q
1948
+
1949
+ cpdef list _coefficients(self):
1950
+ """
1951
+ EXAMPLES::
1952
+
1953
+ sage: x = polygen(ZZ, 'x')
1954
+ sage: F.<b> = NumberField(x^2 - x + 7)
1955
+ sage: b._coefficients()
1956
+ [0, 1]
1957
+ """
1958
+ if not self:
1959
+ return []
1960
+ ad, bd = self.parts()
1961
+ if not bd:
1962
+ return [ad]
1963
+
1964
+ cdef NumberFieldElement_quadratic gen = self.number_field().gen() # should this be cached?
1965
+ alpha, beta = gen.parts()
1966
+ scale = bd/beta
1967
+ return [ad - scale*alpha, scale]
1968
+
1969
+ def denominator(self):
1970
+ r"""
1971
+ Return the denominator of ``self``.
1972
+
1973
+ This is the LCM of the denominators of the coefficients of ``self``, and
1974
+ thus it may well be `> 1` even when the element is an algebraic integer.
1975
+
1976
+ EXAMPLES::
1977
+
1978
+ sage: x = polygen(ZZ, 'x')
1979
+ sage: K.<a> = NumberField(x^2 - 5)
1980
+ sage: b = (a + 1)/2
1981
+ sage: b.denominator()
1982
+ 2
1983
+ sage: b.is_integral()
1984
+ True
1985
+
1986
+ sage: K.<c> = NumberField(x^2 - x + 7)
1987
+ sage: c.denominator()
1988
+ 1
1989
+ """
1990
+ c = self._coefficients()
1991
+ if len(c) == 2:
1992
+ const, lin = c
1993
+ elif len(c) == 1:
1994
+ const = c[0]
1995
+ lin = Rational(0)
1996
+ else:
1997
+ const = lin = Rational(0)
1998
+ return const.denominator().lcm(lin.denominator())
1999
+
2000
+ def numerator(self):
2001
+ r"""
2002
+ Return ``self * self.denominator()``.
2003
+
2004
+ EXAMPLES::
2005
+
2006
+ sage: x = polygen(ZZ, 'x')
2007
+ sage: K.<a> = NumberField(x^2 + x + 41)
2008
+ sage: b = (2*a+1)/6
2009
+ sage: b.denominator()
2010
+ 6
2011
+ sage: b.numerator()
2012
+ 2*a + 1
2013
+ """
2014
+ return self * self.denominator()
2015
+
2016
+ #########################################################
2017
+ # Some things are so much easier to compute
2018
+ #########################################################
2019
+
2020
+ def trace(self):
2021
+ """
2022
+ EXAMPLES::
2023
+
2024
+ sage: x = polygen(ZZ, 'x')
2025
+ sage: K.<a> = NumberField(x^2 + x + 41)
2026
+ sage: a.trace()
2027
+ -1
2028
+ sage: a.matrix()
2029
+ [ 0 1]
2030
+ [-41 -1]
2031
+
2032
+ The trace is additive::
2033
+
2034
+ sage: K.<a> = NumberField(x^2 + 7)
2035
+ sage: (a + 1).trace()
2036
+ 2
2037
+ sage: K(3).trace()
2038
+ 6
2039
+ sage: (a + 4).trace()
2040
+ 8
2041
+ sage: (a/3 + 1).trace()
2042
+ 2
2043
+ """
2044
+ # trace = 2*self.a / self.denom
2045
+ cdef Rational res = <Rational>Rational.__new__(Rational)
2046
+ if mpz_odd_p(self.denom):
2047
+ mpz_mul_2exp(mpq_numref(res.value), self.a, 1)
2048
+ mpz_set(mpq_denref(res.value), self.denom)
2049
+ else:
2050
+ mpz_set(mpq_numref(res.value), self.a)
2051
+ mpz_divexact_ui(mpq_denref(res.value), self.denom, 2)
2052
+ mpq_canonicalize(res.value)
2053
+ return res
2054
+
2055
+ def norm(self, K=None):
2056
+ r"""
2057
+ Return the norm of ``self``.
2058
+
2059
+ If the second argument is ``None``, this is the
2060
+ norm down to `\QQ`. Otherwise, return the norm down to `K` (which had
2061
+ better be either `\QQ` or this number field).
2062
+
2063
+ EXAMPLES::
2064
+
2065
+ sage: x = polygen(ZZ, 'x')
2066
+ sage: K.<a> = NumberField(x^2 - x + 3)
2067
+ sage: a.norm()
2068
+ 3
2069
+ sage: a.matrix()
2070
+ [ 0 1]
2071
+ [-3 1]
2072
+ sage: K.<a> = NumberField(x^2 + 5)
2073
+ sage: (1 + a).norm()
2074
+ 6
2075
+
2076
+ The norm is multiplicative::
2077
+
2078
+ sage: K.<a> = NumberField(x^2 - 3)
2079
+ sage: a.norm()
2080
+ -3
2081
+ sage: K(3).norm()
2082
+ 9
2083
+ sage: (3*a).norm()
2084
+ -27
2085
+
2086
+ We test that the optional argument is handled sensibly::
2087
+
2088
+ sage: (3*a).norm(QQ)
2089
+ -27
2090
+ sage: (3*a).norm(K)
2091
+ 3*a
2092
+ sage: (3*a).norm(CyclotomicField(3))
2093
+ Traceback (most recent call last):
2094
+ ...
2095
+ ValueError: no way to embed L into parent's base ring K
2096
+ """
2097
+ cdef Rational res = <Rational>Rational.__new__(Rational)
2098
+
2099
+ if K is None or K == QQ:
2100
+ # norm = (a^2 - d b^2) / self.denom^2
2101
+ mpz_pow_ui(mpq_numref(res.value), self.a, 2)
2102
+ mpz_pow_ui(mpq_denref(res.value), self.b, 2) # use as temp
2103
+ mpz_mul(mpq_denref(res.value), mpq_denref(res.value), self.D.value)
2104
+ mpz_sub(mpq_numref(res.value), mpq_numref(res.value), mpq_denref(res.value))
2105
+ mpz_pow_ui(mpq_denref(res.value), self.denom, 2)
2106
+ mpq_canonicalize(res.value)
2107
+ return res
2108
+ else:
2109
+ return NumberFieldElement.norm(self, K)
2110
+
2111
+ def is_integral(self):
2112
+ r"""
2113
+ Return whether this element is an algebraic integer.
2114
+
2115
+ TESTS::
2116
+
2117
+ sage: K.<a> = QuadraticField(-1)
2118
+ sage: a.is_integral()
2119
+ True
2120
+ sage: K(1).is_integral()
2121
+ True
2122
+ sage: K(1/2).is_integral()
2123
+ False
2124
+ sage: (a/2).is_integral()
2125
+ False
2126
+ sage: ((a+1)/2).is_integral()
2127
+ False
2128
+ sage: ((a+1)/3).is_integral()
2129
+ False
2130
+
2131
+ sage: K.<a> = QuadraticField(-3)
2132
+ sage: a.is_integral()
2133
+ True
2134
+ sage: K(1).is_integral()
2135
+ True
2136
+ sage: K(1/2).is_integral()
2137
+ False
2138
+ sage: (a/2).is_integral()
2139
+ False
2140
+ sage: ((a+1)/2).is_integral()
2141
+ True
2142
+ sage: ((a+1)/3).is_integral()
2143
+ False
2144
+
2145
+ This works for order elements too, see :issue:`24077`::
2146
+
2147
+ sage: O.<w> = EisensteinIntegers()
2148
+ sage: w.is_integral()
2149
+ True
2150
+ sage: for _ in range(20):
2151
+ ....: assert O.random_element().is_integral()
2152
+
2153
+ Check that :issue:`34800` is fixed::
2154
+
2155
+ sage: K.<t> = QuadraticField(-10007^2)
2156
+ sage: (t/10007).is_integral()
2157
+ True
2158
+ """
2159
+ cdef mpz_t m, n, q, r, s, t, u
2160
+ cdef bint result = False
2161
+
2162
+ # Shortcut for "obviously integral" elements
2163
+ if mpz_cmp_ui(self.denom, 1) == 0:
2164
+ return True
2165
+
2166
+ # a + b*sqrt(D) is integral if and only if
2167
+ # denom | 2*a and denom^2 | a^2 - D*b^2.
2168
+ # Do division with remainder: 2*a = denom*m + n.
2169
+ mpz_init(t)
2170
+ mpz_init(m)
2171
+ mpz_init(n)
2172
+ mpz_mul_ui(t, self.a, 2)
2173
+ mpz_fdiv_qr(m, n, t, self.denom)
2174
+ if mpz_cmp_ui(n, 0) == 0:
2175
+ # Now 2*a = denom*m.
2176
+ # If m is even, then denom | a and gcd(denom, b) = 1, so
2177
+ # a + b*sqrt(D) is integral if and only if denom^2 | D.
2178
+ # If m is odd, then denom is even; put u = denom/2.
2179
+ # Then a + b*sqrt(D) is integral if and only if
2180
+ # b is odd, u^2 | D and D/u^2 is congruent to 1 mod 4.
2181
+ if mpz_even_p(m):
2182
+ mpz_init(s)
2183
+ mpz_mul(s, self.denom, self.denom)
2184
+ result = mpz_divisible_p(self.D.value, s)
2185
+ mpz_clear(s)
2186
+ elif mpz_odd_p(self.b):
2187
+ mpz_init(u)
2188
+ mpz_init(s)
2189
+ mpz_init(q)
2190
+ mpz_init(r)
2191
+ mpz_divexact_ui(u, self.denom, 2)
2192
+ mpz_mul(s, u, u)
2193
+ mpz_fdiv_qr(q, r, self.D.value, s)
2194
+ result = mpz_cmp_ui(r, 0) == 0 and mpz_fdiv_ui(q, 4) == 1
2195
+ mpz_clear(u)
2196
+ mpz_clear(s)
2197
+ mpz_clear(q)
2198
+ mpz_clear(r)
2199
+ mpz_clear(t)
2200
+ mpz_clear(m)
2201
+ mpz_clear(n)
2202
+ return result
2203
+
2204
+ def charpoly(self, var='x', algorithm=None):
2205
+ r"""
2206
+ The characteristic polynomial of this element over `\QQ`.
2207
+
2208
+ INPUT:
2209
+
2210
+ - ``var`` -- the minimal polynomial is defined over a polynomial ring
2211
+ in a variable with this name; if not specified, this defaults to ``'x'``
2212
+ - ``algorithm`` -- for compatibility with general number field
2213
+ elements; ignored
2214
+
2215
+ EXAMPLES::
2216
+
2217
+ sage: x = polygen(ZZ, 'x')
2218
+ sage: K.<a> = NumberField(x^2 - x + 13)
2219
+ sage: a.charpoly()
2220
+ x^2 - x + 13
2221
+ sage: b = 3 - a/2
2222
+ sage: f = b.charpoly(); f
2223
+ x^2 - 11/2*x + 43/4
2224
+ sage: f(b)
2225
+ 0
2226
+ """
2227
+ R = QQ[var]
2228
+ return R([self.norm(), -self.trace(), 1])
2229
+
2230
+ def minpoly(self, var='x', algorithm=None):
2231
+ r"""
2232
+ The minimal polynomial of this element over `\QQ`.
2233
+
2234
+ INPUT:
2235
+
2236
+ - ``var`` -- the minimal polynomial is defined over a polynomial ring
2237
+ in a variable with this name; if not specified, this defaults to ``'x'``
2238
+ - ``algorithm`` -- for compatibility with general number field
2239
+ elements; ignored
2240
+
2241
+ EXAMPLES::
2242
+
2243
+ sage: x = polygen(ZZ, 'x')
2244
+ sage: K.<a> = NumberField(x^2 + 13)
2245
+ sage: a.minpoly()
2246
+ x^2 + 13
2247
+ sage: a.minpoly('T')
2248
+ T^2 + 13
2249
+ sage: (a + 1/2 - a).minpoly()
2250
+ x - 1/2
2251
+ """
2252
+ if self.is_rational():
2253
+ R = QQ[var]
2254
+ return R([-self._rational_(), 1])
2255
+ else:
2256
+ return self.charpoly(var)
2257
+
2258
+ def __abs__(self):
2259
+ """
2260
+ EXAMPLES::
2261
+
2262
+ sage: K.<a> = QuadraticField(2, 'a', embedding=-1.4142)
2263
+ sage: abs(a) # indirect test
2264
+ -a
2265
+ sage: abs(a+1) # indirect test
2266
+ -a - 1
2267
+ sage: abs(a+2) # indirect test
2268
+ a + 2
2269
+
2270
+ sage: x = polygen(ZZ, 'x')
2271
+ sage: K.<a> = NumberField(x^2 + 1, embedding=CDF.gen())
2272
+ sage: abs(a+1) # needs sage.symbolic
2273
+ sqrt(2)
2274
+ """
2275
+ if mpz_sgn(self.D.value) == 1:
2276
+ if self.sign() >= 0:
2277
+ return self
2278
+ return -self
2279
+
2280
+ # doing that way the parent is the symbolic ring (or IntegerRing if the
2281
+ # norm of self is a square). On the other hand, it is coherent with
2282
+ # sage.rings.integer.Integer.sqrt
2283
+ return (self.real()**2 + self.imag()**2).sqrt()
2284
+
2285
+ def floor(self):
2286
+ r"""
2287
+ Return the floor of ``self``.
2288
+
2289
+ EXAMPLES::
2290
+
2291
+ sage: K.<sqrt2> = QuadraticField(2, name='sqrt2')
2292
+ sage: sqrt2.floor()
2293
+ 1
2294
+ sage: (-sqrt2).floor()
2295
+ -2
2296
+ sage: (13/197 + 3702/123*sqrt2).floor()
2297
+ 42
2298
+ sage: (13/197 - 3702/123*sqrt2).floor()
2299
+ -43
2300
+
2301
+ TESTS::
2302
+
2303
+ sage: K2.<sqrt2> = QuadraticField(2)
2304
+ sage: K3.<sqrt3> = QuadraticField(3)
2305
+ sage: K5.<sqrt5> = QuadraticField(5)
2306
+ sage: for _ in range(100):
2307
+ ....: a = QQ.random_element(1000,20)
2308
+ ....: b = QQ.random_element(1000,20)
2309
+ ....: assert floor(a+b*sqrt(2.)) == floor(a+b*sqrt2)
2310
+ ....: assert floor(a+b*sqrt(3.)) == floor(a+b*sqrt3)
2311
+ ....: assert floor(a+b*sqrt(5.)) == floor(a+b*sqrt5)
2312
+
2313
+ sage: K = QuadraticField(-2)
2314
+ sage: l = [K(52), K(-3), K(43/12), K(-43/12)]
2315
+ sage: [x.floor() for x in l]
2316
+ [52, -3, 3, -4]
2317
+ """
2318
+ cdef mpz_t x
2319
+ cdef Integer result
2320
+
2321
+ if mpz_sgn(self.b) == 0:
2322
+ mpz_init_set(x,self.a)
2323
+ mpz_fdiv_q(x,x,self.denom)
2324
+ result = Integer.__new__(Integer)
2325
+ mpz_set(result.value,x)
2326
+ mpz_clear(x)
2327
+ return result
2328
+
2329
+ if not mpz_sgn(self.D.value) == 1:
2330
+ raise ValueError("floor is not defined for complex quadratic number field")
2331
+
2332
+ mpz_init(x)
2333
+ mpz_mul(x,self.b,self.b)
2334
+ mpz_mul(x,x,self.D.value)
2335
+ mpz_sqrt(x,x)
2336
+ if mpz_sgn(self.b) == -1:
2337
+ if self.standard_embedding:
2338
+ mpz_neg(x,x)
2339
+ mpz_sub_ui(x,x,1)
2340
+ elif not self.standard_embedding:
2341
+ mpz_neg(x,x)
2342
+ mpz_sub_ui(x,x,1)
2343
+
2344
+ mpz_add(x,x,self.a) # here x = a + floor(sqrt(b^2 D)) or a + floor(-sqrt(b^2 D))
2345
+ mpz_fdiv_q(x,x,self.denom)
2346
+ result = Integer.__new__(Integer)
2347
+ mpz_set(result.value,x)
2348
+ mpz_clear(x)
2349
+ return result
2350
+
2351
+ def ceil(self):
2352
+ r"""
2353
+ Return the ceil.
2354
+
2355
+ EXAMPLES::
2356
+
2357
+ sage: K.<sqrt7> = QuadraticField(7, name='sqrt7')
2358
+ sage: sqrt7.ceil()
2359
+ 3
2360
+ sage: (-sqrt7).ceil()
2361
+ -2
2362
+ sage: (1022/313*sqrt7 - 14/23).ceil()
2363
+ 9
2364
+
2365
+ TESTS::
2366
+
2367
+ sage: K2.<sqrt2> = QuadraticField(2)
2368
+ sage: K3.<sqrt3> = QuadraticField(3)
2369
+ sage: K5.<sqrt5> = QuadraticField(5)
2370
+ sage: for _ in range(100):
2371
+ ....: a = QQ.random_element(1000,20)
2372
+ ....: b = QQ.random_element(1000,20)
2373
+ ....: assert ceil(a+b*sqrt(2.)) == ceil(a+b*sqrt2)
2374
+ ....: assert ceil(a+b*sqrt(3.)) == ceil(a+b*sqrt3)
2375
+ ....: assert ceil(a+b*sqrt(5.)) == ceil(a+b*sqrt5)
2376
+
2377
+ sage: K = QuadraticField(-2)
2378
+ sage: l = [K(52), K(-3), K(43/12), K(-43/12)]
2379
+ sage: [x.ceil() for x in l]
2380
+ [52, -3, 4, -3]
2381
+ """
2382
+ x = self.floor()
2383
+ if mpz_sgn(self.b) == 0 and mpz_cmp_ui(self.denom,1) == 0:
2384
+ return x
2385
+ return x+1
2386
+
2387
+ def round(self):
2388
+ r"""
2389
+ Return the round (nearest integer) of this number field element. In case
2390
+ of ties, this relies on the default rounding for rational numbers.
2391
+
2392
+ EXAMPLES::
2393
+
2394
+ sage: K.<sqrt7> = QuadraticField(7, name='sqrt7')
2395
+ sage: sqrt7.round()
2396
+ 3
2397
+ sage: (-sqrt7).round()
2398
+ -3
2399
+ sage: (12/313*sqrt7 - 1745917/2902921).round()
2400
+ 0
2401
+ sage: (12/313*sqrt7 - 1745918/2902921).round()
2402
+ -1
2403
+
2404
+ TESTS::
2405
+
2406
+ sage: K2.<sqrt2> = QuadraticField(2)
2407
+ sage: K3.<sqrt3> = QuadraticField(3)
2408
+ sage: K5.<sqrt5> = QuadraticField(5)
2409
+ sage: for _ in range(100):
2410
+ ....: a = QQ.random_element(1000,20)
2411
+ ....: b = QQ.random_element(1000,20)
2412
+ ....: assert a.round() == round(K2(a)), a
2413
+ ....: assert a.round() == round(K3(a)), a
2414
+ ....: assert a.round() == round(K5(a)), a
2415
+ ....: assert round(a+b*sqrt(2.)) == round(a+b*sqrt2), (a, b)
2416
+ ....: assert round(a+b*sqrt(3.)) == round(a+b*sqrt3), (a, b)
2417
+ ....: assert round(a+b*sqrt(5.)) == round(a+b*sqrt5), (a, b)
2418
+ """
2419
+ n = self.floor()
2420
+ test = 2 * (self - n)
2421
+ if test < 1:
2422
+ return n
2423
+ elif test > 1:
2424
+ return n + 1
2425
+ elif n % 2 == 0:
2426
+ return n
2427
+ else:
2428
+ return n + 1
2429
+
2430
+
2431
+ cdef class NumberFieldElement_quadratic_sqrt(NumberFieldElement_quadratic):
2432
+ r"""
2433
+ A :class:`NumberFieldElement_quadratic_sqrt` object gives an efficient representation of
2434
+ an element of a quadratic extension of `\QQ` for the case when
2435
+ :func:`is_sqrt_disc()` is ``True``.
2436
+ """
2437
+ def denominator(self):
2438
+ r"""
2439
+ Return the denominator of ``self``.
2440
+
2441
+ This is the LCM of the denominators of the coefficients of ``self``, and
2442
+ thus it may well be `> 1` even when the element is an algebraic integer.
2443
+
2444
+ EXAMPLES::
2445
+
2446
+ sage: x = polygen(ZZ, 'x')
2447
+ sage: K.<a> = NumberField(x^2 + x + 41)
2448
+ sage: a.denominator()
2449
+ 1
2450
+ sage: b = (2*a+1)/6
2451
+ sage: b.denominator()
2452
+ 6
2453
+ sage: K(1).denominator()
2454
+ 1
2455
+ sage: K(1/2).denominator()
2456
+ 2
2457
+ sage: K(0).denominator()
2458
+ 1
2459
+
2460
+ sage: K.<a> = NumberField(x^2 - 5)
2461
+ sage: b = (a + 1)/2
2462
+ sage: b.denominator()
2463
+ 2
2464
+ sage: b.is_integral()
2465
+ True
2466
+ """
2467
+ cdef Integer denom
2468
+ denom = Integer.__new__(Integer)
2469
+ mpz_set(denom.value, self.denom)
2470
+ return denom
2471
+
2472
+ cpdef list _coefficients(self):
2473
+ """
2474
+ EXAMPLES::
2475
+
2476
+ sage: x = polygen(ZZ, 'x')
2477
+ sage: K.<a> = NumberField(x^2 + 41)
2478
+ sage: a._coefficients()
2479
+ [0, 1]
2480
+ sage: K.zero()._coefficients()
2481
+ []
2482
+ sage: (3/2*K.one())._coefficients()
2483
+ [3/2]
2484
+ """
2485
+ if not self:
2486
+ return []
2487
+ cdef tuple parts = self.parts()
2488
+ if not <Rational> (parts[1]):
2489
+ return [parts[0]]
2490
+ return list(parts)
2491
+
2492
+ def __getitem__(self, n):
2493
+ """
2494
+ Return the ``n``-th coefficient of this number field element,
2495
+ written as a polynomial in the generator.
2496
+
2497
+ Note that ``n`` must be either ``0`` or ``1``.
2498
+
2499
+ EXAMPLES::
2500
+
2501
+ sage: x = polygen(ZZ, 'x')
2502
+ sage: K.<a> = NumberField(x^2 - 13)
2503
+ sage: elt = a/4 + 1/3
2504
+ sage: elt[0]
2505
+ 1/3
2506
+ sage: elt[1]
2507
+ 1/4
2508
+
2509
+ sage: K.zero()[0]
2510
+ 0
2511
+ sage: K.zero()[1]
2512
+ 0
2513
+
2514
+ sage: K.one()[0]
2515
+ 1
2516
+ sage: K.one()[1]
2517
+ 0
2518
+
2519
+ sage: elt[2]
2520
+ Traceback (most recent call last):
2521
+ ...
2522
+ IndexError: index must be either 0 or 1
2523
+
2524
+ sage: C.<z3> = CyclotomicField(3)
2525
+ sage: list(z3)
2526
+ [0, 1]
2527
+ """
2528
+ try:
2529
+ return self.parts()[n]
2530
+ except IndexError: # So we have a better error message
2531
+ raise IndexError("index must be either 0 or 1")
2532
+
2533
+ cdef class NumberFieldElement_gaussian(NumberFieldElement_quadratic_sqrt):
2534
+ r"""
2535
+ An element of `\QQ[i]`.
2536
+
2537
+ Some methods of this class behave slightly differently than the
2538
+ corresponding methods of general elements of quadratic number fields,
2539
+ especially with regard to conversions to parents that can represent complex
2540
+ numbers in rectangular form.
2541
+
2542
+ In addition, this class provides some convenience methods similar to methods
2543
+ of symbolic expressions to make the behavior of ``a + I*b`` with rational
2544
+ ``a``, ``b`` closer to that when ``a``, ``b`` are expressions.
2545
+
2546
+ EXAMPLES::
2547
+
2548
+ sage: type(I)
2549
+ <class 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_gaussian'>
2550
+
2551
+ sage: mi = QuadraticField(-1, embedding=CC(0,-1)).gen()
2552
+ sage: type(mi)
2553
+ <class 'sage.rings.number_field.number_field_element_quadratic.NumberFieldElement_gaussian'>
2554
+ sage: CC(mi)
2555
+ -1.00000000000000*I
2556
+ """
2557
+
2558
+ def _symbolic_(self, SR):
2559
+ r"""
2560
+ EXAMPLES::
2561
+
2562
+ sage: SR(1 + 2*i) # needs sage.symbolic
2563
+ 2*I + 1
2564
+
2565
+ sage: K.<mi> = QuadraticField(-1, embedding=CC(0,-1))
2566
+ sage: SR(1 + mi) # needs sage.symbolic
2567
+ -I + 1
2568
+ """
2569
+ from sage.symbolic.constants import I
2570
+ return self[1]*(I if self.standard_embedding else -I) + self[0]
2571
+
2572
+ def _algebraic_(self, parent):
2573
+ r"""
2574
+ Convert this element to an algebraic number, if possible.
2575
+
2576
+ EXAMPLES::
2577
+
2578
+ sage: NF.<i> = QuadraticField(-1)
2579
+ sage: QQbar(i+2)
2580
+ I + 2
2581
+ sage: K.<ii> = QuadraticField(-1, embedding=CC(0,-1))
2582
+ sage: QQbar(ii+2)
2583
+ -I + 2
2584
+ sage: AA(i)
2585
+ Traceback (most recent call last):
2586
+ ...
2587
+ ValueError: unable to convert i to an element of Algebraic Real Field
2588
+
2589
+ TESTS:
2590
+
2591
+ Check that :issue:`31808` is fixed::
2592
+
2593
+ sage: C.<I> = QuadraticField(-1)
2594
+ sage: AA(C.one())
2595
+ 1
2596
+ sage: AA(C.zero())
2597
+ 0
2598
+ """
2599
+ import sage.rings.qqbar as qqbar
2600
+ cdef tuple coeffs
2601
+ if parent is qqbar.QQbar:
2602
+ # AlgebraicNumber.__init__ does a better job than
2603
+ # NumberFieldElement._algebraic_ in this case, but
2604
+ # QQbar._element_constructor_ calls the latter first.
2605
+ return qqbar.AlgebraicNumber(self)
2606
+ if parent is qqbar.AA:
2607
+ coeffs = self.parts()
2608
+ if coeffs[1].is_zero():
2609
+ return qqbar.AlgebraicReal(coeffs[0])
2610
+ raise ValueError(f"unable to convert {self!r} to an element of {parent!r}")
2611
+
2612
+ cpdef real_part(self):
2613
+ r"""
2614
+ Real part.
2615
+
2616
+ EXAMPLES::
2617
+
2618
+ sage: (1 + 2*I).real()
2619
+ 1
2620
+ sage: (1 + 2*I).real().parent()
2621
+ Rational Field
2622
+ """
2623
+ cdef Rational ad = <Rational> Rational.__new__(Rational)
2624
+ if mpz_cmp_ui(self.a, 0) == 0:
2625
+ mpq_set_ui(ad.value, 0, 1)
2626
+ else:
2627
+ mpz_set(mpq_numref(ad.value), self.a)
2628
+ mpz_set(mpq_denref(ad.value), self.denom)
2629
+ mpq_canonicalize(ad.value)
2630
+ return ad
2631
+
2632
+ real = real_part
2633
+
2634
+ cpdef imag_part(self):
2635
+ r"""
2636
+ Imaginary part.
2637
+
2638
+ EXAMPLES::
2639
+
2640
+ sage: (1 + 2*I).imag()
2641
+ 2
2642
+ sage: (1 + 2*I).imag().parent()
2643
+ Rational Field
2644
+
2645
+ sage: K.<mi> = QuadraticField(-1, embedding=CC(0,-1))
2646
+ sage: (1 - mi).imag()
2647
+ 1
2648
+ """
2649
+ cdef Rational bd = <Rational> Rational.__new__(Rational)
2650
+ if mpz_cmp_ui(self.b, 0) == 0:
2651
+ # It is 0, so all we need to do is initialize the result
2652
+ mpq_set_ui(bd.value, 0, 1)
2653
+ return bd
2654
+
2655
+ mpz_set(mpq_numref(bd.value), self.b)
2656
+ mpz_set(mpq_denref(bd.value), self.denom)
2657
+ mpq_canonicalize(bd.value)
2658
+ if not self.standard_embedding:
2659
+ mpq_neg(bd.value, bd.value)
2660
+ return bd
2661
+
2662
+ imag = imag_part
2663
+
2664
+ # for compatibility with the old symbolic I
2665
+
2666
+ def log(self, *args, **kwds):
2667
+ r"""
2668
+ Complex logarithm (standard branch).
2669
+
2670
+ EXAMPLES::
2671
+
2672
+ sage: I.log() # needs sage.symbolic
2673
+ 1/2*I*pi
2674
+ """
2675
+ from sage.symbolic.ring import SR
2676
+ return SR(self).log(*args, **kwds)
2677
+
2678
+ cdef class OrderElement_quadratic(NumberFieldElement_quadratic):
2679
+ """
2680
+ Element of an order in a quadratic field.
2681
+
2682
+ EXAMPLES::
2683
+
2684
+ sage: x = polygen(ZZ, 'x')
2685
+ sage: K.<a> = NumberField(x^2 + 1)
2686
+ sage: O2 = K.order(2*a)
2687
+ sage: w = O2.1; w
2688
+ 2*a
2689
+ sage: parent(w)
2690
+ Order of conductor 2 generated by 2*a in Number Field in a with defining polynomial x^2 + 1
2691
+ """
2692
+ def __init__(self, order, f):
2693
+ r"""
2694
+ Standard initialisation function.
2695
+
2696
+ EXAMPLES::
2697
+
2698
+ sage: x = polygen(ZZ, 'x')
2699
+ sage: OK.<y> = EquationOrder(x^2 + 5)
2700
+ sage: v = OK.1 # indirect doctest
2701
+ sage: type(v)
2702
+ <class 'sage.rings.number_field.number_field_element_quadratic.OrderElement_quadratic'>
2703
+ """
2704
+ K = order.number_field()
2705
+ NumberFieldElement_quadratic.__init__(self, K, f)
2706
+ (<Element>self)._parent = order
2707
+
2708
+ def norm(self):
2709
+ """
2710
+ The norm of an element of the ring of integers is an Integer.
2711
+
2712
+ EXAMPLES::
2713
+
2714
+ sage: x = polygen(ZZ, 'x')
2715
+ sage: K.<a> = NumberField(x^2 + 3)
2716
+ sage: O2 = K.order(2*a)
2717
+ sage: w = O2.gen(1); w
2718
+ 2*a
2719
+ sage: w.norm()
2720
+ 12
2721
+ sage: parent(w.norm())
2722
+ Integer Ring
2723
+ """
2724
+ return ZZ(NumberFieldElement_quadratic.norm(self))
2725
+
2726
+ def trace(self):
2727
+ """
2728
+ The trace of an element of the ring of integers is an Integer.
2729
+
2730
+ EXAMPLES::
2731
+
2732
+ sage: x = polygen(ZZ, 'x')
2733
+ sage: K.<a> = NumberField(x^2 - 5)
2734
+ sage: R = K.ring_of_integers()
2735
+ sage: b = R((1+a)/2)
2736
+ sage: b.trace()
2737
+ 1
2738
+ sage: parent(b.trace())
2739
+ Integer Ring
2740
+ """
2741
+ return ZZ(NumberFieldElement_quadratic.trace(self))
2742
+
2743
+ def charpoly(self, var='x', algorithm=None):
2744
+ r"""
2745
+ The characteristic polynomial of this element, which is over `\ZZ`
2746
+ because this element is an algebraic integer.
2747
+
2748
+ INPUT:
2749
+
2750
+ - ``var`` -- the minimal polynomial is defined over a polynomial ring
2751
+ in a variable with this name; if not specified, this defaults to ``'x'``
2752
+ - ``algorithm`` -- for compatibility with general number field
2753
+ elements; ignored
2754
+
2755
+ EXAMPLES::
2756
+
2757
+ sage: x = polygen(ZZ, 'x')
2758
+ sage: K.<a> = NumberField(x^2 - 5)
2759
+ sage: R = K.ring_of_integers()
2760
+ sage: b = R((5+a)/2)
2761
+ sage: f = b.charpoly('x'); f
2762
+ x^2 - 5*x + 5
2763
+ sage: f.parent()
2764
+ Univariate Polynomial Ring in x over Integer Ring
2765
+ sage: f(b)
2766
+ 0
2767
+ """
2768
+ R = ZZ[var]
2769
+ return R([self.norm(), -self.trace(), 1])
2770
+
2771
+ def minpoly(self, var='x', algorithm=None):
2772
+ r"""
2773
+ The minimal polynomial of this element over `\ZZ`.
2774
+
2775
+ INPUT:
2776
+
2777
+ - ``var`` -- the minimal polynomial is defined over a polynomial ring
2778
+ in a variable with this name; if not specified, this defaults to ``'x'``
2779
+ - ``algorithm`` -- for compatibility with general number field
2780
+ elements; ignored
2781
+
2782
+ EXAMPLES::
2783
+
2784
+ sage: x = polygen(ZZ, 'x')
2785
+ sage: K.<a> = NumberField(x^2 + 163)
2786
+ sage: R = K.ring_of_integers()
2787
+ sage: f = R(a).minpoly('x'); f
2788
+ x^2 + 163
2789
+ sage: f.parent()
2790
+ Univariate Polynomial Ring in x over Integer Ring
2791
+ sage: R(5).minpoly()
2792
+ x - 5
2793
+ """
2794
+ if self.is_rational():
2795
+ R = ZZ[var]
2796
+ return R([-self._rational_(), 1])
2797
+ else:
2798
+ return self.charpoly()
2799
+
2800
+ cdef number_field(self):
2801
+ # So few functions actually use self.number_field() for quadratic elements, so
2802
+ # it is better *not* to return a cached value (since the call to _parent.number_field())
2803
+ # is expensive.
2804
+ return self._parent.number_field()
2805
+
2806
+ # We must override these since the basering is now ZZ not QQ.
2807
+ cpdef _rmul_(self, Element _c):
2808
+ """
2809
+ EXAMPLES::
2810
+
2811
+ sage: x = polygen(ZZ, 'x')
2812
+ sage: K.<a> = NumberField(x^2 - 27)
2813
+ sage: R = K.ring_of_integers()
2814
+ sage: aa = R.gen(1); aa
2815
+ 1/3*a
2816
+ sage: 5 * aa # indirect doctest
2817
+ 5/3*a
2818
+ """
2819
+ cdef Integer c = <Integer>_c
2820
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
2821
+ mpz_mul(res.a, self.a, c.value)
2822
+ mpz_mul(res.b, self.b, c.value)
2823
+ mpz_set(res.denom, self.denom)
2824
+ res._reduce_c_()
2825
+ return res
2826
+
2827
+ cpdef _lmul_(self, Element _c):
2828
+ """
2829
+ EXAMPLES::
2830
+
2831
+ sage: x = polygen(ZZ, 'x')
2832
+ sage: K.<a> = NumberField(x^2 + 43)
2833
+ sage: R = K.ring_of_integers()
2834
+ sage: aa = R.gen(0); aa
2835
+ 1/2*a + 1/2
2836
+ sage: aa*3 # indirect doctest
2837
+ 3/2*a + 3/2
2838
+ """
2839
+ cdef Integer c = <Integer>_c
2840
+ cdef NumberFieldElement_quadratic res = <NumberFieldElement_quadratic>self._new()
2841
+ mpz_mul(res.a, self.a, c.value)
2842
+ mpz_mul(res.b, self.b, c.value)
2843
+ mpz_set(res.denom, self.denom)
2844
+ res._reduce_c_()
2845
+ return res
2846
+
2847
+ def __invert__(self):
2848
+ r"""
2849
+ Implement inversion, checking that the return value has the right parent.
2850
+ See :issue:`4190`.
2851
+
2852
+ EXAMPLES::
2853
+
2854
+ sage: x = polygen(ZZ, 'x')
2855
+ sage: K = NumberField(x^2 - x + 2, 'a')
2856
+ sage: OK = K.ring_of_integers()
2857
+ sage: a = OK(K.gen())
2858
+ sage: (~a).parent() is K
2859
+ True
2860
+ sage: (~a) in OK
2861
+ False
2862
+ sage: a**(-1) in OK
2863
+ False
2864
+ """
2865
+ return self._parent.number_field()(NumberFieldElement_quadratic.__invert__(self))
2866
+
2867
+ def inverse_mod(self, I):
2868
+ r"""
2869
+ Return an inverse of ``self`` modulo the given ideal.
2870
+
2871
+ INPUT:
2872
+
2873
+ - ``I`` -- may be an ideal of ``self.parent()``, or an
2874
+ element or list of elements of ``self.parent()`` generating a nonzero
2875
+ ideal. A :exc:`ValueError` is raised if `I` is non-integral or is zero.
2876
+ A :exc:`ZeroDivisionError` is raised if `I + (x) \neq (1)`.
2877
+
2878
+ EXAMPLES::
2879
+
2880
+ sage: x = polygen(ZZ, 'x')
2881
+ sage: OE.<w> = EquationOrder(x^2 - x + 2)
2882
+ sage: w.inverse_mod(13) == 6*w - 6
2883
+ True
2884
+ sage: w*(6*w - 6) - 1
2885
+ -13
2886
+ sage: w.inverse_mod(13).parent() == OE
2887
+ True
2888
+ sage: w.inverse_mod(2)
2889
+ Traceback (most recent call last):
2890
+ ...
2891
+ ZeroDivisionError: w is not invertible modulo Fractional ideal (2)
2892
+ """
2893
+ R = self.parent()
2894
+ return R(_inverse_mod_generic(self, I))
2895
+
2896
+ cpdef list _coefficients(self):
2897
+ """
2898
+ EXAMPLES::
2899
+
2900
+ sage: x = polygen(ZZ, 'x')
2901
+ sage: K.<a> = NumberField(x^2 - 27)
2902
+ sage: R = K.ring_of_integers()
2903
+ sage: aa = R.gen(1)
2904
+ sage: aa._coefficients()
2905
+ [0, 1/3]
2906
+ """
2907
+ if not self:
2908
+ return []
2909
+ ad, bd = self.parts()
2910
+ if not bd:
2911
+ return [ad]
2912
+
2913
+ cdef NumberFieldElement_quadratic gen = self.number_field().gen()
2914
+ alpha, beta = gen.parts()
2915
+ if is_sqrt_disc(alpha, beta):
2916
+ return [ad, bd]
2917
+ else:
2918
+ scale = bd / beta
2919
+ return [ad - scale*alpha, scale]
2920
+
2921
+ def denominator(self):
2922
+ r"""
2923
+ Return the denominator of ``self``.
2924
+
2925
+ This is the LCM of the denominators of the coefficients of ``self``, and
2926
+ thus it may well be `> 1` even when the element is an algebraic integer.
2927
+
2928
+ EXAMPLES::
2929
+
2930
+ sage: x = polygen(ZZ, 'x')
2931
+ sage: K.<a> = NumberField(x^2 - 27)
2932
+ sage: R = K.ring_of_integers()
2933
+ sage: aa = R.gen(1)
2934
+ sage: aa.denominator()
2935
+ 3
2936
+ """
2937
+ # In terms of the generator...
2938
+ cdef NumberFieldElement_quadratic gen = self.number_field().gen() # should this be cached?
2939
+ cdef Integer denom
2940
+ cdef tuple parts = gen.parts()
2941
+ cdef Rational alpha, beta, const, lin
2942
+ alpha = <Rational> (parts[0])
2943
+ beta = <Rational> (parts[1])
2944
+ if is_sqrt_disc(alpha, beta):
2945
+ denom = Integer.__new__(Integer)
2946
+ mpz_set(denom.value, self.denom)
2947
+ return denom
2948
+ else:
2949
+ parts = self.parts()
2950
+ const = <Rational> (parts[0])
2951
+ lin = <Rational> (parts[1])
2952
+ scale = lin / beta
2953
+ const = const - scale * alpha
2954
+ return const.denominator().lcm(scale.denominator())
2955
+
2956
+ cdef class Z_to_quadratic_field_element(Morphism):
2957
+ """
2958
+ Morphism that coerces from integers to elements of a quadratic number
2959
+ field `K`.
2960
+
2961
+ EXAMPLES::
2962
+
2963
+ sage: K.<a> = QuadraticField(3)
2964
+ sage: phi = K.coerce_map_from(ZZ); phi
2965
+ Natural morphism:
2966
+ From: Integer Ring
2967
+ To: Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878?
2968
+ sage: phi(4)
2969
+ 4
2970
+ sage: phi(5).parent() is K
2971
+ True
2972
+ """
2973
+ # The zero element of K, lazily initialized
2974
+ cdef NumberFieldElement_quadratic zero_element
2975
+
2976
+ # TODO: implement __richcmp__ properly so we can have a loads/dumps doctest
2977
+
2978
+ def __init__(self, K):
2979
+ """
2980
+ ``K`` is the target quadratic field.
2981
+
2982
+ EXAMPLES::
2983
+
2984
+ sage: K.<a> = QuadraticField(3)
2985
+ sage: phi = K.coerce_map_from(ZZ) # indirect doctest
2986
+ sage: type(phi)
2987
+ <class 'sage.rings.number_field.number_field_element_quadratic.Z_to_quadratic_field_element'>
2988
+ sage: phi == loads(dumps(phi)) # todo: comparison not implemented
2989
+ True
2990
+
2991
+ sage: R.<b> = CyclotomicField(6)
2992
+ sage: psi = R.coerce_map_from(ZZ) # indirect doctest
2993
+ sage: type(psi)
2994
+ <class 'sage.rings.number_field.number_field_element_quadratic.Z_to_quadratic_field_element'>
2995
+ sage: psi == loads(dumps(psi)) # todo: comparison not implemented
2996
+ True
2997
+ """
2998
+ import sage.categories.homset
2999
+ Morphism.__init__(self, sage.categories.homset.Hom(ZZ, K))
3000
+
3001
+ cpdef Element _call_(self, x):
3002
+ r"""
3003
+ Evaluate at an integer ``x``.
3004
+
3005
+ EXAMPLES::
3006
+
3007
+ sage: K.<a> = QuadraticField(3)
3008
+ sage: phi = K.coerce_map_from(ZZ)
3009
+ sage: a = phi(2); a # indirect doctest
3010
+ 2
3011
+ sage: a.parent() is K
3012
+ True
3013
+
3014
+ sage: R.<b> = CyclotomicField(6)
3015
+ sage: psi = R.coerce_map_from(ZZ)
3016
+ sage: b = psi(-42); b # indirect doctest
3017
+ -42
3018
+ sage: b.parent() is R
3019
+ True
3020
+ """
3021
+ cdef NumberFieldElement_quadratic y
3022
+ if self.zero_element is None:
3023
+ self.zero_element = self._codomain.zero()
3024
+ if mpz_sgn((<Integer> x).value) == 0:
3025
+ return self.zero_element
3026
+ y = self.zero_element._new()
3027
+ mpz_set(y.a, (<Integer> x).value)
3028
+
3029
+ # we need to set the denominator to 1 as it is 0 for
3030
+ # the zero element of K... (because gcd(0,0) = 0).
3031
+ mpz_set_ui(y.denom, 1)
3032
+
3033
+ return y
3034
+
3035
+ def _repr_type(self):
3036
+ r"""
3037
+ Return a short name for this morphism.
3038
+
3039
+ EXAMPLES::
3040
+
3041
+ sage: K.<a> = QuadraticField(3)
3042
+ sage: phi = K.coerce_map_from(ZZ)
3043
+ sage: phi # indirect doctest
3044
+ Natural morphism:
3045
+ From: Integer Ring
3046
+ To: Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878?
3047
+
3048
+ sage: R.<b> = CyclotomicField(6)
3049
+ sage: psi = R.coerce_map_from(ZZ)
3050
+ sage: psi # indirect doctest
3051
+ Natural morphism:
3052
+ From: Integer Ring
3053
+ To: Cyclotomic Field of order 6 and degree 2
3054
+ """
3055
+ return "Natural"
3056
+
3057
+
3058
+ cdef class Q_to_quadratic_field_element(Morphism):
3059
+ """
3060
+ Morphism that coerces from rationals to elements of a quadratic number
3061
+ field `K`.
3062
+
3063
+ EXAMPLES::
3064
+
3065
+ sage: K.<a> = QuadraticField(-3)
3066
+ sage: f = K.coerce_map_from(QQ); f
3067
+ Natural morphism:
3068
+ From: Rational Field
3069
+ To: Number Field in a with defining polynomial x^2 + 3 with a = 1.732050807568878?*I
3070
+ sage: f(3/1)
3071
+ 3
3072
+ sage: f(1/2).parent() is K
3073
+ True
3074
+ """
3075
+ # The zero element of K, lazily initialized
3076
+ cdef NumberFieldElement_quadratic zero_element
3077
+
3078
+ # TODO: implement __richcmp__ properly so we can have a loads/dumps doctest
3079
+
3080
+ def __init__(self, K):
3081
+ """
3082
+ INPUT:
3083
+
3084
+ - ``K`` -- the target quadratic field
3085
+
3086
+ EXAMPLES::
3087
+
3088
+ sage: K.<a> = QuadraticField(3)
3089
+ sage: phi = K.coerce_map_from(QQ) # indirect doctest
3090
+ sage: type(phi)
3091
+ <class 'sage.rings.number_field.number_field_element_quadratic.Q_to_quadratic_field_element'>
3092
+ sage: phi == loads(dumps(phi)) # todo: comparison not implemented
3093
+ True
3094
+
3095
+ sage: R.<b> = CyclotomicField(6)
3096
+ sage: psi = R.coerce_map_from(QQ)
3097
+ sage: type(psi)
3098
+ <class 'sage.rings.number_field.number_field_element_quadratic.Q_to_quadratic_field_element'>
3099
+ sage: psi == loads(dumps(psi)) # todo: comparison not implemented
3100
+ True
3101
+ """
3102
+ import sage.categories.homset
3103
+ Morphism.__init__(self, sage.categories.homset.Hom(QQ, K))
3104
+
3105
+ cpdef Element _call_(self, x):
3106
+ r"""
3107
+ Evaluate at a rational ``x``.
3108
+
3109
+ EXAMPLES::
3110
+
3111
+ sage: K.<a> = QuadraticField(3)
3112
+ sage: phi = K.coerce_map_from(QQ)
3113
+ sage: a = phi(2/3); a # indirect doctest
3114
+ 2/3
3115
+ sage: a.parent() is K
3116
+ True
3117
+
3118
+ sage: R.<b> = CyclotomicField(6)
3119
+ sage: psi = R.coerce_map_from(QQ)
3120
+ sage: b = psi(-23/15); b # indirect doctest
3121
+ -23/15
3122
+ sage: b.parent() is R
3123
+ True
3124
+ """
3125
+ if self.zero_element is None:
3126
+ self.zero_element = self._codomain.zero()
3127
+ cdef NumberFieldElement_quadratic y = self.zero_element._new()
3128
+ mpz_set(y.a, mpq_numref((<Rational>x).value))
3129
+ mpz_set(y.denom, mpq_denref((<Rational>x).value))
3130
+ return y
3131
+
3132
+ def _repr_type(self):
3133
+ r"""
3134
+ Return a short name for this morphism.
3135
+
3136
+ EXAMPLES::
3137
+
3138
+ sage: K.<a> = QuadraticField(3)
3139
+ sage: phi = K.coerce_map_from(QQ)
3140
+ sage: phi # indirect doctest
3141
+ Natural morphism:
3142
+ From: Rational Field
3143
+ To: Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878?
3144
+
3145
+ sage: R.<b> = CyclotomicField(6)
3146
+ sage: psi = R.coerce_map_from(QQ)
3147
+ sage: psi # indirect doctest
3148
+ Natural morphism:
3149
+ From: Rational Field
3150
+ To: Cyclotomic Field of order 6 and degree 2
3151
+ """
3152
+ return "Natural"
3153
+
3154
+ #####################################################################
3155
+ ## Helper function
3156
+
3157
+ cpdef bint is_sqrt_disc(Rational ad, Rational bd) noexcept:
3158
+ r"""
3159
+ Return ``True`` if the pair ``(ad, bd)`` is `\sqrt{D}`.
3160
+
3161
+ EXAMPLES::
3162
+
3163
+ sage: x = polygen(ZZ, 'x')
3164
+ sage: F.<b> = NumberField(x^2 - x + 7)
3165
+ sage: b.denominator() # indirect doctest
3166
+ 1
3167
+ """
3168
+ cdef mpz_t a, b, denom
3169
+ mpz_init(a)
3170
+ mpz_init(b)
3171
+ mpz_init(denom)
3172
+
3173
+ mpz_lcm(denom, mpq_denref(ad.value), mpq_denref(bd.value))
3174
+ mpz_divexact(a, denom, mpq_denref(ad.value))
3175
+ mpz_mul(a, a, mpq_numref(ad.value))
3176
+ mpz_divexact(b, denom, mpq_denref(bd.value))
3177
+ mpz_mul(b, b, mpq_numref(bd.value))
3178
+
3179
+ cdef bint ret = mpz_cmp_ui(denom, 1) == 0 and mpz_cmp_ui(a, 0) == 0 and mpz_cmp_ui(b, 1) == 0
3180
+
3181
+ mpz_clear(a)
3182
+ mpz_clear(b)
3183
+ mpz_clear(denom)
3184
+
3185
+ return ret