passagemath-flint 10.6.1rc10__cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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 (361) hide show
  1. passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
  2. passagemath_flint-10.6.1rc10.dist-info/RECORD +361 -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-aecb9cc5.so.21.0.0 +0 -0
  6. passagemath_flint.libs/libgf2x-a4cdec90.so.3.0.0 +0 -0
  7. passagemath_flint.libs/libgfortran-8f1e9814.so.5.0.0 +0 -0
  8. passagemath_flint.libs/libgmp-6e109695.so.10.5.0 +0 -0
  9. passagemath_flint.libs/libgsl-cda90e79.so.28.0.0 +0 -0
  10. passagemath_flint.libs/libmpfi-e3c25853.so.0.0.0 +0 -0
  11. passagemath_flint.libs/libmpfr-82690d50.so.6.2.1 +0 -0
  12. passagemath_flint.libs/libntl-74e7d9a3.so.44.0.1 +0 -0
  13. passagemath_flint.libs/libopenblasp-r0-6dcb67f9.3.29.so +0 -0
  14. passagemath_flint.libs/libquadmath-828275a7.so.0.0.0 +0 -0
  15. sage/all__sagemath_flint.py +29 -0
  16. sage/combinat/all__sagemath_flint.py +1 -0
  17. sage/combinat/posets/all__sagemath_flint.py +1 -0
  18. sage/combinat/posets/hasse_cython_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  19. sage/combinat/posets/hasse_cython_flint.pyx +194 -0
  20. sage/data_structures/all__sagemath_flint.py +1 -0
  21. sage/data_structures/bounded_integer_sequences.cpython-313-x86_64-linux-gnu.so +0 -0
  22. sage/data_structures/bounded_integer_sequences.pxd +62 -0
  23. sage/data_structures/bounded_integer_sequences.pyx +1418 -0
  24. sage/graphs/all__sagemath_flint.py +1 -0
  25. sage/graphs/chrompoly.cpython-313-x86_64-linux-gnu.so +0 -0
  26. sage/graphs/chrompoly.pyx +555 -0
  27. sage/graphs/matchpoly.cpython-313-x86_64-linux-gnu.so +0 -0
  28. sage/graphs/matchpoly.pyx +412 -0
  29. sage/libs/all__sagemath_flint.py +17 -0
  30. sage/libs/arb/__init__.py +1 -0
  31. sage/libs/arb/acb.pxd +154 -0
  32. sage/libs/arb/acb_calc.pxd +9 -0
  33. sage/libs/arb/acb_elliptic.pxd +25 -0
  34. sage/libs/arb/acb_hypgeom.pxd +74 -0
  35. sage/libs/arb/acb_mat.pxd +62 -0
  36. sage/libs/arb/acb_modular.pxd +17 -0
  37. sage/libs/arb/acb_poly.pxd +216 -0
  38. sage/libs/arb/arb.pxd +240 -0
  39. sage/libs/arb/arb_fmpz_poly.pxd +21 -0
  40. sage/libs/arb/arb_hypgeom.pxd +83 -0
  41. sage/libs/arb/arb_wrap.h +34 -0
  42. sage/libs/arb/arf.pxd +131 -0
  43. sage/libs/arb/arith.cpython-313-x86_64-linux-gnu.so +0 -0
  44. sage/libs/arb/arith.pyx +87 -0
  45. sage/libs/arb/bernoulli.pxd +6 -0
  46. sage/libs/arb/mag.pxd +77 -0
  47. sage/libs/arb/types.pxd +37 -0
  48. sage/libs/flint/__init__.py +1 -0
  49. sage/libs/flint/acb.pxd +270 -0
  50. sage/libs/flint/acb_calc.pxd +22 -0
  51. sage/libs/flint/acb_dft.pxd +51 -0
  52. sage/libs/flint/acb_dirichlet.pxd +112 -0
  53. sage/libs/flint/acb_elliptic.pxd +42 -0
  54. sage/libs/flint/acb_hypgeom.pxd +169 -0
  55. sage/libs/flint/acb_macros.pxd +9 -0
  56. sage/libs/flint/acb_mat.pxd +136 -0
  57. sage/libs/flint/acb_mat_macros.pxd +10 -0
  58. sage/libs/flint/acb_modular.pxd +62 -0
  59. sage/libs/flint/acb_poly.pxd +251 -0
  60. sage/libs/flint/acb_poly_macros.pxd +8 -0
  61. sage/libs/flint/acb_theta.pxd +124 -0
  62. sage/libs/flint/acf.pxd +32 -0
  63. sage/libs/flint/aprcl.pxd +84 -0
  64. sage/libs/flint/arb.pxd +382 -0
  65. sage/libs/flint/arb_calc.pxd +31 -0
  66. sage/libs/flint/arb_fmpz_poly.pxd +34 -0
  67. sage/libs/flint/arb_fpwrap.pxd +215 -0
  68. sage/libs/flint/arb_hypgeom.pxd +147 -0
  69. sage/libs/flint/arb_macros.pxd +9 -0
  70. sage/libs/flint/arb_mat.pxd +140 -0
  71. sage/libs/flint/arb_mat_macros.pxd +10 -0
  72. sage/libs/flint/arb_poly.pxd +237 -0
  73. sage/libs/flint/arf.pxd +167 -0
  74. sage/libs/flint/arith.cpython-313-x86_64-linux-gnu.so +0 -0
  75. sage/libs/flint/arith.pxd +76 -0
  76. sage/libs/flint/arith.pyx +77 -0
  77. sage/libs/flint/arith_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  78. sage/libs/flint/arith_sage.pyx +308 -0
  79. sage/libs/flint/bernoulli.pxd +28 -0
  80. sage/libs/flint/bool_mat.pxd +52 -0
  81. sage/libs/flint/ca.pxd +203 -0
  82. sage/libs/flint/ca_ext.pxd +34 -0
  83. sage/libs/flint/ca_field.pxd +32 -0
  84. sage/libs/flint/ca_mat.pxd +117 -0
  85. sage/libs/flint/ca_poly.pxd +104 -0
  86. sage/libs/flint/ca_vec.pxd +46 -0
  87. sage/libs/flint/calcium.pxd +27 -0
  88. sage/libs/flint/d_mat.pxd +39 -0
  89. sage/libs/flint/d_vec.pxd +32 -0
  90. sage/libs/flint/dirichlet.pxd +57 -0
  91. sage/libs/flint/dlog.pxd +53 -0
  92. sage/libs/flint/double_extras.pxd +24 -0
  93. sage/libs/flint/double_interval.pxd +36 -0
  94. sage/libs/flint/fexpr.pxd +104 -0
  95. sage/libs/flint/fexpr_builtin.pxd +20 -0
  96. sage/libs/flint/fft.pxd +66 -0
  97. sage/libs/flint/flint.pxd +36 -0
  98. sage/libs/flint/flint_ntl_wrap.h +35 -0
  99. sage/libs/flint/flint_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  100. sage/libs/flint/flint_sage.pyx +163 -0
  101. sage/libs/flint/flint_wrap.h +190 -0
  102. sage/libs/flint/fmpq.pxd +137 -0
  103. sage/libs/flint/fmpq_mat.pxd +105 -0
  104. sage/libs/flint/fmpq_mat_macros.pxd +10 -0
  105. sage/libs/flint/fmpq_mpoly.pxd +165 -0
  106. sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
  107. sage/libs/flint/fmpq_poly.pxd +241 -0
  108. sage/libs/flint/fmpq_poly_macros.pxd +9 -0
  109. sage/libs/flint/fmpq_poly_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  110. sage/libs/flint/fmpq_poly_sage.pxd +31 -0
  111. sage/libs/flint/fmpq_poly_sage.pyx +48 -0
  112. sage/libs/flint/fmpq_vec.pxd +27 -0
  113. sage/libs/flint/fmpz.pxd +256 -0
  114. sage/libs/flint/fmpz_extras.pxd +32 -0
  115. sage/libs/flint/fmpz_factor.pxd +42 -0
  116. sage/libs/flint/fmpz_factor_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  117. sage/libs/flint/fmpz_factor_sage.pxd +4 -0
  118. sage/libs/flint/fmpz_factor_sage.pyx +29 -0
  119. sage/libs/flint/fmpz_lll.pxd +49 -0
  120. sage/libs/flint/fmpz_macros.pxd +8 -0
  121. sage/libs/flint/fmpz_mat.pxd +184 -0
  122. sage/libs/flint/fmpz_mat_macros.pxd +10 -0
  123. sage/libs/flint/fmpz_mod.pxd +46 -0
  124. sage/libs/flint/fmpz_mod_mat.pxd +71 -0
  125. sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
  126. sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
  127. sage/libs/flint/fmpz_mod_poly.pxd +249 -0
  128. sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
  129. sage/libs/flint/fmpz_mod_vec.pxd +27 -0
  130. sage/libs/flint/fmpz_mpoly.pxd +224 -0
  131. sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
  132. sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
  133. sage/libs/flint/fmpz_poly.cpython-313-x86_64-linux-gnu.so +0 -0
  134. sage/libs/flint/fmpz_poly.pxd +407 -0
  135. sage/libs/flint/fmpz_poly.pyx +19 -0
  136. sage/libs/flint/fmpz_poly_factor.pxd +33 -0
  137. sage/libs/flint/fmpz_poly_macros.pxd +8 -0
  138. sage/libs/flint/fmpz_poly_mat.pxd +71 -0
  139. sage/libs/flint/fmpz_poly_q.pxd +55 -0
  140. sage/libs/flint/fmpz_poly_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  141. sage/libs/flint/fmpz_poly_sage.pxd +20 -0
  142. sage/libs/flint/fmpz_poly_sage.pyx +500 -0
  143. sage/libs/flint/fmpz_vec.pxd +80 -0
  144. sage/libs/flint/fmpzi.pxd +52 -0
  145. sage/libs/flint/fq.pxd +97 -0
  146. sage/libs/flint/fq_default.pxd +84 -0
  147. sage/libs/flint/fq_default_mat.pxd +70 -0
  148. sage/libs/flint/fq_default_poly.pxd +97 -0
  149. sage/libs/flint/fq_default_poly_factor.pxd +39 -0
  150. sage/libs/flint/fq_embed.pxd +28 -0
  151. sage/libs/flint/fq_mat.pxd +83 -0
  152. sage/libs/flint/fq_nmod.pxd +95 -0
  153. sage/libs/flint/fq_nmod_embed.pxd +28 -0
  154. sage/libs/flint/fq_nmod_mat.pxd +83 -0
  155. sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
  156. sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
  157. sage/libs/flint/fq_nmod_poly.pxd +202 -0
  158. sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
  159. sage/libs/flint/fq_nmod_vec.pxd +33 -0
  160. sage/libs/flint/fq_poly.pxd +204 -0
  161. sage/libs/flint/fq_poly_factor.pxd +47 -0
  162. sage/libs/flint/fq_vec.pxd +33 -0
  163. sage/libs/flint/fq_zech.pxd +99 -0
  164. sage/libs/flint/fq_zech_embed.pxd +28 -0
  165. sage/libs/flint/fq_zech_mat.pxd +78 -0
  166. sage/libs/flint/fq_zech_poly.pxd +198 -0
  167. sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
  168. sage/libs/flint/fq_zech_vec.pxd +33 -0
  169. sage/libs/flint/gr.pxd +174 -0
  170. sage/libs/flint/gr_generic.pxd +215 -0
  171. sage/libs/flint/gr_mat.pxd +161 -0
  172. sage/libs/flint/gr_mpoly.pxd +68 -0
  173. sage/libs/flint/gr_poly.pxd +276 -0
  174. sage/libs/flint/gr_special.pxd +237 -0
  175. sage/libs/flint/gr_vec.pxd +120 -0
  176. sage/libs/flint/hypgeom.pxd +24 -0
  177. sage/libs/flint/long_extras.pxd +23 -0
  178. sage/libs/flint/mag.pxd +131 -0
  179. sage/libs/flint/mag_macros.pxd +8 -0
  180. sage/libs/flint/mpf_mat.pxd +36 -0
  181. sage/libs/flint/mpf_vec.pxd +34 -0
  182. sage/libs/flint/mpfr_mat.pxd +27 -0
  183. sage/libs/flint/mpfr_vec.pxd +25 -0
  184. sage/libs/flint/mpn_extras.pxd +41 -0
  185. sage/libs/flint/mpoly.pxd +72 -0
  186. sage/libs/flint/nf.pxd +19 -0
  187. sage/libs/flint/nf_elem.pxd +74 -0
  188. sage/libs/flint/nmod.pxd +35 -0
  189. sage/libs/flint/nmod_mat.pxd +104 -0
  190. sage/libs/flint/nmod_mpoly.pxd +144 -0
  191. sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
  192. sage/libs/flint/nmod_poly.pxd +339 -0
  193. sage/libs/flint/nmod_poly_factor.pxd +44 -0
  194. sage/libs/flint/nmod_poly_linkage.pxi +710 -0
  195. sage/libs/flint/nmod_poly_mat.pxd +76 -0
  196. sage/libs/flint/nmod_vec.pxd +40 -0
  197. sage/libs/flint/ntl_interface.pxd +17 -0
  198. sage/libs/flint/padic.pxd +93 -0
  199. sage/libs/flint/padic_mat.pxd +64 -0
  200. sage/libs/flint/padic_poly.pxd +88 -0
  201. sage/libs/flint/partitions.pxd +23 -0
  202. sage/libs/flint/perm.pxd +26 -0
  203. sage/libs/flint/profiler.pxd +24 -0
  204. sage/libs/flint/qadic.pxd +77 -0
  205. sage/libs/flint/qfb.pxd +44 -0
  206. sage/libs/flint/qqbar.pxd +172 -0
  207. sage/libs/flint/qsieve.cpython-313-x86_64-linux-gnu.so +0 -0
  208. sage/libs/flint/qsieve.pxd +41 -0
  209. sage/libs/flint/qsieve.pyx +21 -0
  210. sage/libs/flint/qsieve_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  211. sage/libs/flint/qsieve_sage.pyx +67 -0
  212. sage/libs/flint/thread_pool.pxd +25 -0
  213. sage/libs/flint/types.pxd +2076 -0
  214. sage/libs/flint/ulong_extras.cpython-313-x86_64-linux-gnu.so +0 -0
  215. sage/libs/flint/ulong_extras.pxd +141 -0
  216. sage/libs/flint/ulong_extras.pyx +21 -0
  217. sage/libs/flint/ulong_extras_sage.cpython-313-x86_64-linux-gnu.so +0 -0
  218. sage/libs/flint/ulong_extras_sage.pyx +21 -0
  219. sage/matrix/all__sagemath_flint.py +1 -0
  220. sage/matrix/change_ring.cpython-313-x86_64-linux-gnu.so +0 -0
  221. sage/matrix/change_ring.pyx +43 -0
  222. sage/matrix/matrix_complex_ball_dense.cpython-313-x86_64-linux-gnu.so +0 -0
  223. sage/matrix/matrix_complex_ball_dense.pxd +14 -0
  224. sage/matrix/matrix_complex_ball_dense.pyx +973 -0
  225. sage/matrix/matrix_cyclo_dense.cpython-313-x86_64-linux-gnu.so +0 -0
  226. sage/matrix/matrix_cyclo_dense.pxd +16 -0
  227. sage/matrix/matrix_cyclo_dense.pyx +1761 -0
  228. sage/matrix/matrix_integer_dense.cpython-313-x86_64-linux-gnu.so +0 -0
  229. sage/matrix/matrix_integer_dense.pxd +32 -0
  230. sage/matrix/matrix_integer_dense.pyx +5801 -0
  231. sage/matrix/matrix_integer_dense_hnf.py +1294 -0
  232. sage/matrix/matrix_integer_dense_saturation.py +346 -0
  233. sage/matrix/matrix_integer_sparse.cpython-313-x86_64-linux-gnu.so +0 -0
  234. sage/matrix/matrix_integer_sparse.pxd +9 -0
  235. sage/matrix/matrix_integer_sparse.pyx +1090 -0
  236. sage/matrix/matrix_rational_dense.cpython-313-x86_64-linux-gnu.so +0 -0
  237. sage/matrix/matrix_rational_dense.pxd +23 -0
  238. sage/matrix/matrix_rational_dense.pyx +2995 -0
  239. sage/matrix/matrix_rational_sparse.cpython-313-x86_64-linux-gnu.so +0 -0
  240. sage/matrix/matrix_rational_sparse.pxd +11 -0
  241. sage/matrix/matrix_rational_sparse.pyx +789 -0
  242. sage/matrix/misc_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  243. sage/matrix/misc_flint.pyx +109 -0
  244. sage/modular/all__sagemath_flint.py +1 -0
  245. sage/modular/modform/all__sagemath_flint.py +1 -0
  246. sage/modular/modform/eis_series_cython.cpython-313-x86_64-linux-gnu.so +0 -0
  247. sage/modular/modform/eis_series_cython.pyx +226 -0
  248. sage/modular/modsym/all__sagemath_flint.py +1 -0
  249. sage/modular/modsym/apply.cpython-313-x86_64-linux-gnu.so +0 -0
  250. sage/modular/modsym/apply.pxd +6 -0
  251. sage/modular/modsym/apply.pyx +113 -0
  252. sage/modular/modsym/heilbronn.cpython-313-x86_64-linux-gnu.so +0 -0
  253. sage/modular/modsym/heilbronn.pyx +966 -0
  254. sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
  255. sage/modular/pollack_stevens/dist.cpython-313-x86_64-linux-gnu.so +0 -0
  256. sage/modular/pollack_stevens/dist.pxd +38 -0
  257. sage/modular/pollack_stevens/dist.pyx +1439 -0
  258. sage/quivers/algebra.py +691 -0
  259. sage/quivers/algebra_elements.cpython-313-x86_64-linux-gnu.so +0 -0
  260. sage/quivers/algebra_elements.pxd +97 -0
  261. sage/quivers/algebra_elements.pxi +1324 -0
  262. sage/quivers/algebra_elements.pyx +1424 -0
  263. sage/quivers/all.py +1 -0
  264. sage/quivers/ar_quiver.py +917 -0
  265. sage/quivers/homspace.py +640 -0
  266. sage/quivers/morphism.py +1282 -0
  267. sage/quivers/path_semigroup.py +1155 -0
  268. sage/quivers/paths.cpython-313-x86_64-linux-gnu.so +0 -0
  269. sage/quivers/paths.pxd +13 -0
  270. sage/quivers/paths.pyx +809 -0
  271. sage/quivers/representation.py +2975 -0
  272. sage/rings/all__sagemath_flint.py +37 -0
  273. sage/rings/cif.py +4 -0
  274. sage/rings/complex_arb.cpython-313-x86_64-linux-gnu.so +0 -0
  275. sage/rings/complex_arb.pxd +29 -0
  276. sage/rings/complex_arb.pyx +5176 -0
  277. sage/rings/complex_interval.cpython-313-x86_64-linux-gnu.so +0 -0
  278. sage/rings/complex_interval.pxd +30 -0
  279. sage/rings/complex_interval.pyx +2475 -0
  280. sage/rings/complex_interval_field.py +711 -0
  281. sage/rings/convert/all.py +1 -0
  282. sage/rings/convert/mpfi.cpython-313-x86_64-linux-gnu.so +0 -0
  283. sage/rings/convert/mpfi.pxd +6 -0
  284. sage/rings/convert/mpfi.pyx +576 -0
  285. sage/rings/factorint_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  286. sage/rings/factorint_flint.pyx +99 -0
  287. sage/rings/fraction_field_FpT.cpython-313-x86_64-linux-gnu.so +0 -0
  288. sage/rings/fraction_field_FpT.pxd +28 -0
  289. sage/rings/fraction_field_FpT.pyx +2043 -0
  290. sage/rings/imaginary_unit.py +5 -0
  291. sage/rings/monomials.py +73 -0
  292. sage/rings/number_field/S_unit_solver.py +2870 -0
  293. sage/rings/number_field/all__sagemath_flint.py +7 -0
  294. sage/rings/number_field/bdd_height.py +664 -0
  295. sage/rings/number_field/class_group.py +762 -0
  296. sage/rings/number_field/galois_group.py +1307 -0
  297. sage/rings/number_field/homset.py +612 -0
  298. sage/rings/number_field/maps.py +687 -0
  299. sage/rings/number_field/morphism.py +272 -0
  300. sage/rings/number_field/number_field.py +12820 -0
  301. sage/rings/number_field/number_field_element.cpython-313-x86_64-linux-gnu.so +0 -0
  302. sage/rings/number_field/number_field_element.pxd +59 -0
  303. sage/rings/number_field/number_field_element.pyx +5735 -0
  304. sage/rings/number_field/number_field_element_quadratic.cpython-313-x86_64-linux-gnu.so +0 -0
  305. sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
  306. sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
  307. sage/rings/number_field/number_field_ideal_rel.py +925 -0
  308. sage/rings/number_field/number_field_morphisms.cpython-313-x86_64-linux-gnu.so +0 -0
  309. sage/rings/number_field/number_field_morphisms.pyx +781 -0
  310. sage/rings/number_field/number_field_rel.py +2734 -0
  311. sage/rings/number_field/order.py +2981 -0
  312. sage/rings/number_field/order_ideal.py +804 -0
  313. sage/rings/number_field/selmer_group.py +715 -0
  314. sage/rings/number_field/small_primes_of_degree_one.py +242 -0
  315. sage/rings/number_field/splitting_field.py +606 -0
  316. sage/rings/number_field/structure.py +380 -0
  317. sage/rings/number_field/unit_group.py +721 -0
  318. sage/rings/padics/all__sagemath_flint.py +3 -0
  319. sage/rings/polynomial/all__sagemath_flint.py +1 -0
  320. sage/rings/polynomial/complex_roots.py +312 -0
  321. sage/rings/polynomial/evaluation_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  322. sage/rings/polynomial/evaluation_flint.pxd +7 -0
  323. sage/rings/polynomial/evaluation_flint.pyx +68 -0
  324. sage/rings/polynomial/hilbert.cpython-313-x86_64-linux-gnu.so +0 -0
  325. sage/rings/polynomial/hilbert.pyx +602 -0
  326. sage/rings/polynomial/polynomial_complex_arb.cpython-313-x86_64-linux-gnu.so +0 -0
  327. sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
  328. sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
  329. sage/rings/polynomial/polynomial_integer_dense_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  330. sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
  331. sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
  332. sage/rings/polynomial/polynomial_number_field.cpython-313-x86_64-linux-gnu.so +0 -0
  333. sage/rings/polynomial/polynomial_number_field.pyx +345 -0
  334. sage/rings/polynomial/polynomial_rational_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  335. sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
  336. sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
  337. sage/rings/polynomial/polynomial_zmod_flint.cpython-313-x86_64-linux-gnu.so +0 -0
  338. sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
  339. sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
  340. sage/rings/polynomial/real_roots.cpython-313-x86_64-linux-gnu.so +0 -0
  341. sage/rings/polynomial/real_roots.pxd +81 -0
  342. sage/rings/polynomial/real_roots.pyx +4704 -0
  343. sage/rings/polynomial/refine_root.cpython-313-x86_64-linux-gnu.so +0 -0
  344. sage/rings/polynomial/refine_root.pyx +142 -0
  345. sage/rings/polynomial/weil/all.py +4 -0
  346. sage/rings/polynomial/weil/power_sums.h +46 -0
  347. sage/rings/polynomial/weil/weil_polynomials.cpython-313-x86_64-linux-gnu.so +0 -0
  348. sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
  349. sage/rings/qqbar.py +9025 -0
  350. sage/rings/real_arb.cpython-313-x86_64-linux-gnu.so +0 -0
  351. sage/rings/real_arb.pxd +21 -0
  352. sage/rings/real_arb.pyx +4065 -0
  353. sage/rings/real_interval_absolute.cpython-313-x86_64-linux-gnu.so +0 -0
  354. sage/rings/real_interval_absolute.pyx +1073 -0
  355. sage/rings/real_mpfi.cpython-313-x86_64-linux-gnu.so +0 -0
  356. sage/rings/real_mpfi.pyx +5428 -0
  357. sage/schemes/all__sagemath_flint.py +1 -0
  358. sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
  359. sage/schemes/elliptic_curves/descent_two_isogeny.cpython-313-x86_64-linux-gnu.so +0 -0
  360. sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
  361. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,2043 @@
1
+ # sage_setup: distribution = sagemath-flint
2
+ # distutils: libraries = gmp 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
+ "Univariate rational functions over prime fields"
9
+
10
+ from cysignals.signals cimport sig_on, sig_off
11
+
12
+ from sage.rings.finite_rings.stdint cimport INTEGER_MOD_INT32_LIMIT
13
+
14
+ from sage.libs.gmp.mpz cimport *
15
+ from sage.libs.flint.nmod_poly cimport *
16
+ from sage.libs.flint.ulong_extras cimport n_jacobi
17
+ from sage.structure.element cimport Element, FieldElement
18
+ from sage.rings.integer_ring import ZZ
19
+ from sage.rings.fraction_field import FractionField_1poly_field
20
+ from sage.rings.finite_rings.integer_mod cimport IntegerMod_int
21
+ from sage.rings.integer cimport Integer
22
+ from sage.rings.polynomial.polynomial_zmod_flint cimport Polynomial_zmod_flint, get_cparent
23
+
24
+ from sage.structure.richcmp cimport rich_to_bool
25
+ from sage.rings.finite_rings.integer_mod cimport mod_inverse_int
26
+
27
+
28
+ class FpT(FractionField_1poly_field):
29
+ r"""
30
+ This class represents the fraction field `\GF{p}(T)` for `2 < p < \sqrt{2^31-1}`.
31
+
32
+ EXAMPLES::
33
+
34
+ sage: R.<T> = GF(71)[]
35
+ sage: K = FractionField(R); K
36
+ Fraction Field of Univariate Polynomial Ring in T over Finite Field of size 71
37
+ sage: 1-1/T
38
+ (T + 70)/T
39
+ sage: parent(1-1/T) is K
40
+ True
41
+ """
42
+ INTEGER_LIMIT = INTEGER_MOD_INT32_LIMIT
43
+
44
+ def __init__(self, R, names=None): # we include names so that one can use the syntax K.<t> = FpT(GF(5)['t']). It's actually ignored
45
+ """
46
+ INPUT:
47
+
48
+ - ``R`` -- a dense polynomial ring over a finite field of prime order
49
+ `p` with `2 < p < 2^{16}`
50
+
51
+ EXAMPLES::
52
+
53
+ sage: R.<x> = GF(31)[]
54
+ sage: K = R.fraction_field(); K
55
+ Fraction Field of Univariate Polynomial Ring in x over Finite Field of size 31
56
+
57
+ TESTS::
58
+
59
+ sage: from sage.rings.fraction_field_FpT import FpT
60
+ sage: FpT(PolynomialRing(GF(37), ['x'], sparse=True))
61
+ Traceback (most recent call last):
62
+ ...
63
+ TypeError: unsupported polynomial ring
64
+ """
65
+ cdef long p = R.base_ring().characteristic()
66
+ assert 2 < p < FpT.INTEGER_LIMIT
67
+ if not issubclass(R.element_class, Polynomial_zmod_flint):
68
+ raise TypeError("unsupported polynomial ring")
69
+ self.p = p
70
+ self.poly_ring = R
71
+ FractionField_1poly_field.__init__(self, R, element_class=FpTElement)
72
+ self._populate_coercion_lists_(coerce_list=[Polyring_FpT_coerce(self), Fp_FpT_coerce(self), ZZ_FpT_coerce(self)])
73
+
74
+ def __iter__(self):
75
+ """
76
+ Return an iterator over this fraction field.
77
+
78
+ EXAMPLES::
79
+
80
+ sage: R.<t> = GF(3)[]; K = R.fraction_field()
81
+ sage: iter(K)
82
+ <sage.rings.fraction_field_FpT.FpT_iter object at ...>
83
+ """
84
+ return self.iter()
85
+
86
+ def iter(self, bound=None, start=None):
87
+ """
88
+ EXAMPLES::
89
+
90
+ sage: from sage.rings.fraction_field_FpT import *
91
+ sage: R.<t> = FpT(GF(5)['t'])
92
+ sage: list(R.iter(2))[350:355]
93
+ [(t^2 + t + 1)/(t + 2),
94
+ (t^2 + t + 2)/(t + 2),
95
+ (t^2 + t + 4)/(t + 2),
96
+ (t^2 + 2*t + 1)/(t + 2),
97
+ (t^2 + 2*t + 2)/(t + 2)]
98
+ """
99
+ return FpT_iter(self, bound, start)
100
+
101
+
102
+ cdef class FpTElement(FieldElement):
103
+ """
104
+ An element of an :class:`FpT` fraction field.
105
+
106
+ TESTS::
107
+
108
+ sage: R.<t> = GF(5)[]
109
+ sage: K = R.fraction_field()
110
+ sage: A.<x> = K[]
111
+ sage: x.divides(x) # Testing issue #27064
112
+ True
113
+ """
114
+
115
+ def __init__(self, parent, numer, denom=1, coerce=True, reduce=True):
116
+ """
117
+ INPUT:
118
+
119
+ - ``parent`` -- the Fraction field containing this element
120
+ - ``numer`` -- something that can be converted into the polynomial
121
+ ring, giving the numerator
122
+ - ``denom`` -- something that can be converted into the polynomial
123
+ ring, giving the numerator (default: 1)
124
+
125
+ EXAMPLES::
126
+
127
+ sage: from sage.rings.fraction_field_FpT import *
128
+ sage: R.<t> = FpT(GF(5)['t'])
129
+ sage: R(7)
130
+ 2
131
+ """
132
+ super().__init__(parent)
133
+ if coerce:
134
+ numer = parent.poly_ring(numer)
135
+ denom = parent.poly_ring(denom)
136
+ self.p = parent.p
137
+ nmod_poly_init(self._numer, self.p)
138
+ nmod_poly_init(self._denom, self.p)
139
+ self.initialized = True
140
+ cdef long n
141
+ for n, a in enumerate(numer):
142
+ nmod_poly_set_coeff_ui(self._numer, n, a)
143
+ for n, a in enumerate(denom):
144
+ nmod_poly_set_coeff_ui(self._denom, n, a)
145
+ if reduce:
146
+ normalize(self._numer, self._denom, self.p)
147
+
148
+ def __dealloc__(self):
149
+ """
150
+ Deallocation.
151
+
152
+ EXAMPLES::
153
+
154
+ sage: K = GF(11)['t'].fraction_field()
155
+ sage: t = K.gen()
156
+ sage: del t # indirect doctest
157
+ """
158
+ if self.initialized:
159
+ nmod_poly_clear(self._numer)
160
+ nmod_poly_clear(self._denom)
161
+
162
+ def __reduce__(self):
163
+ """
164
+ For pickling.
165
+
166
+ TESTS::
167
+
168
+ sage: K = GF(11)['t'].fraction_field()
169
+ sage: loads(dumps(K.gen()))
170
+ t
171
+ sage: loads(dumps(1/K.gen()))
172
+ 1/t
173
+ """
174
+ return (unpickle_FpT_element,
175
+ (self._parent, self.numer(), self.denom()))
176
+
177
+ cdef FpTElement _new_c(self):
178
+ """
179
+ Create a new FpTElement in the same field, leaving the value to be
180
+ initialized.
181
+ """
182
+ cdef FpTElement x = <FpTElement>FpTElement.__new__(FpTElement)
183
+ x._parent = self._parent
184
+ x.p = self.p
185
+ nmod_poly_init_preinv(x._numer, x.p, self._numer.mod.ninv)
186
+ nmod_poly_init_preinv(x._denom, x.p, self._numer.mod.ninv)
187
+ x.initialized = True
188
+ return x
189
+
190
+ cdef FpTElement _copy_c(self):
191
+ """
192
+ Create a new FpTElement in the same field, with the same value as
193
+ ``self``.
194
+ """
195
+ cdef FpTElement x = <FpTElement>FpTElement.__new__(FpTElement)
196
+ x._parent = self._parent
197
+ x.p = self.p
198
+ nmod_poly_init2_preinv(x._numer, x.p, self._numer.mod.ninv, self._numer.length)
199
+ nmod_poly_init2_preinv(x._denom, x.p, self._denom.mod.ninv, self._denom.length)
200
+ nmod_poly_set(x._numer, self._numer)
201
+ nmod_poly_set(x._denom, self._denom)
202
+ x.initialized = True
203
+ return x
204
+
205
+ def numer(self):
206
+ """
207
+ Return the numerator of this element, as an element of the polynomial ring.
208
+
209
+ EXAMPLES::
210
+
211
+ sage: K = GF(11)['t'].fraction_field()
212
+ sage: t = K.gen(0); a = (t + 1/t)^3 - 1
213
+ sage: a.numer()
214
+ t^6 + 3*t^4 + 10*t^3 + 3*t^2 + 1
215
+ """
216
+ return self.numerator()
217
+
218
+ cpdef numerator(self):
219
+ """
220
+ Return the numerator of this element, as an element of the polynomial ring.
221
+
222
+ EXAMPLES::
223
+
224
+ sage: K = GF(11)['t'].fraction_field()
225
+ sage: t = K.gen(0); a = (t + 1/t)^3 - 1
226
+ sage: a.numerator()
227
+ t^6 + 3*t^4 + 10*t^3 + 3*t^2 + 1
228
+ """
229
+ cdef Polynomial_zmod_flint res = <Polynomial_zmod_flint>Polynomial_zmod_flint.__new__(Polynomial_zmod_flint)
230
+ nmod_poly_init2_preinv(&res.x, self.p, self._numer.mod.ninv, self._numer.length)
231
+ nmod_poly_set(&res.x, self._numer)
232
+ res._parent = self._parent.poly_ring
233
+ res._cparent = get_cparent(self._parent.poly_ring)
234
+ return res
235
+
236
+ def denom(self):
237
+ """
238
+ Return the denominator of this element, as an element of the polynomial ring.
239
+
240
+ EXAMPLES::
241
+
242
+ sage: K = GF(11)['t'].fraction_field()
243
+ sage: t = K.gen(0); a = (t + 1/t)^3 - 1
244
+ sage: a.denom()
245
+ t^3
246
+ """
247
+ return self.denominator()
248
+
249
+ cpdef denominator(self):
250
+ """
251
+ Return the denominator of this element, as an element of the polynomial ring.
252
+
253
+ EXAMPLES::
254
+
255
+ sage: K = GF(11)['t'].fraction_field()
256
+ sage: t = K.gen(0); a = (t + 1/t)^3 - 1
257
+ sage: a.denominator()
258
+ t^3
259
+ """
260
+ cdef Polynomial_zmod_flint res = <Polynomial_zmod_flint>Polynomial_zmod_flint.__new__(Polynomial_zmod_flint)
261
+ nmod_poly_init2_preinv(&res.x, self.p, self._denom.mod.ninv, self._denom.length)
262
+ nmod_poly_set(&res.x, self._denom)
263
+ res._parent = self._parent.poly_ring
264
+ res._cparent = get_cparent(self._parent.poly_ring)
265
+ return res
266
+
267
+ def __call__(self, *args, **kwds):
268
+ """
269
+ EXAMPLES::
270
+
271
+ sage: K = Frac(GF(5)['t'])
272
+ sage: t = K.gen()
273
+ sage: t(3)
274
+ 3
275
+ sage: f = t^2/(1-t)
276
+ sage: f(2)
277
+ 1
278
+ sage: f(t)
279
+ 4*t^2/(t + 4)
280
+ sage: f(t^3)
281
+ 4*t^6/(t^3 + 4)
282
+ sage: f((t+1)/t^3)
283
+ (t^2 + 2*t + 1)/(t^6 + 4*t^4 + 4*t^3)
284
+ """
285
+ return self.numer()(*args, **kwds) / self.denom()(*args, **kwds)
286
+
287
+ def subs(self, in_dict=None, *args, **kwds):
288
+ """
289
+ EXAMPLES::
290
+
291
+ sage: K = Frac(GF(11)['t'])
292
+ sage: t = K.gen()
293
+ sage: f = (t+1)/(t-1)
294
+ sage: f.subs(t=2)
295
+ 3
296
+ sage: f.subs(X=2)
297
+ (t + 1)/(t + 10)
298
+ """
299
+ return self.numer().subs(in_dict, *args, **kwds) / self.denom().subs(in_dict, *args, **kwds)
300
+
301
+ def valuation(self, v):
302
+ """
303
+ Return the valuation of ``self`` at `v`.
304
+
305
+ EXAMPLES::
306
+
307
+ sage: R.<t> = GF(5)[]
308
+ sage: f = (t+1)^2 * (t^2+t+1) / (t-1)^3
309
+ sage: f.valuation(t+1)
310
+ 2
311
+ sage: f.valuation(t-1)
312
+ -3
313
+ sage: f.valuation(t)
314
+ 0
315
+ """
316
+ return self.numer().valuation(v) - self.denom().valuation(v)
317
+
318
+ def factor(self):
319
+ """
320
+ EXAMPLES::
321
+
322
+ sage: K = Frac(GF(5)['t'])
323
+ sage: t = K.gen()
324
+ sage: f = 2 * (t+1) * (t^2+t+1)^2 / (t-1)
325
+ sage: factor(f)
326
+ (2) * (t + 4)^-1 * (t + 1) * (t^2 + t + 1)^2
327
+ """
328
+ return self.numer().factor() / self.denom().factor()
329
+
330
+ def _repr_(self):
331
+ """
332
+ Return a string representation of this element.
333
+
334
+ EXAMPLES::
335
+
336
+ sage: from sage.rings.fraction_field_FpT import *
337
+ sage: R.<t> = FpT(GF(17)['t'])
338
+ sage: -t # indirect doctest
339
+ 16*t
340
+ sage: 1/t
341
+ 1/t
342
+ sage: 1/(t+1)
343
+ 1/(t + 1)
344
+ sage: 1-t/t
345
+ 0
346
+ sage: (1-t)/t
347
+ (16*t + 1)/t
348
+ """
349
+ if nmod_poly_degree(self._denom) == 0 and nmod_poly_get_coeff_ui(self._denom, 0) == 1:
350
+ return repr(self.numer())
351
+ else:
352
+ numer_s = repr(self.numer())
353
+ denom_s = repr(self.denom())
354
+ if '-' in numer_s or '+' in numer_s:
355
+ numer_s = "(%s)" % numer_s
356
+ if '-' in denom_s or '+' in denom_s:
357
+ denom_s = "(%s)" % denom_s
358
+ return "%s/%s" % (numer_s, denom_s)
359
+
360
+ def _latex_(self):
361
+ r"""
362
+ Return a latex representation of this element.
363
+
364
+ EXAMPLES::
365
+
366
+ sage: K = GF(7)['t'].fraction_field(); t = K.gen(0)
367
+ sage: latex(t^2 + 1) # indirect doctest
368
+ t^{2} + 1
369
+ sage: latex((t + 1)/(t-1))
370
+ \frac{t + 1}{t + 6}
371
+ """
372
+ if nmod_poly_degree(self._denom) == 0 and nmod_poly_get_coeff_ui(self._denom, 0) == 1:
373
+ return self.numer()._latex_()
374
+ else:
375
+ return "\\frac{%s}{%s}" % (self.numer()._latex_(), self.denom()._latex_())
376
+
377
+ cpdef _richcmp_(self, other, int op):
378
+ """
379
+ Compare this with another element.
380
+
381
+ The ordering is arbitrary, but it is an ordering, and it is
382
+ consistent between runs. It has nothing to do with the
383
+ algebra structure.
384
+
385
+ TESTS::
386
+
387
+ sage: from sage.rings.fraction_field_FpT import *
388
+ sage: R.<t> = FpT(GF(7)['t'])
389
+ sage: t == t
390
+ True
391
+ sage: t == -t
392
+ False
393
+ sage: -t == 6*t
394
+ True
395
+ sage: 1/t == 1/t
396
+ True
397
+ sage: 1/t == 1/(t+1)
398
+ False
399
+ sage: 2*t/t == 2
400
+ True
401
+ sage: 2*t/2 == t
402
+ True
403
+
404
+ sage: a = (t^3 + 3*t)/(5*t-2); b = (t^2-2)/(t-1)
405
+ sage: b < a
406
+ True
407
+ sage: a < b
408
+ False
409
+ sage: 1/a < b
410
+ True
411
+ sage: b < 1/a
412
+ False
413
+
414
+ ::
415
+
416
+ sage: K = Frac(GF(5)['t']); t = K.gen()
417
+ sage: t == 1
418
+ False
419
+ sage: t + 1 < t^2
420
+ True
421
+ """
422
+ # They are normalized.
423
+ cdef int j = sage_cmp_nmod_poly_t(self._numer, (<FpTElement>other)._numer)
424
+ if j:
425
+ return rich_to_bool(op, j)
426
+ j = sage_cmp_nmod_poly_t(self._denom, (<FpTElement>other)._denom)
427
+ return rich_to_bool(op, j)
428
+
429
+ def __hash__(self):
430
+ """
431
+ Return a hash value for this element.
432
+
433
+ TESTS::
434
+
435
+ sage: from sage.rings.fraction_field_FpT import *
436
+ sage: K.<t> = FpT(GF(7)['t'])
437
+ sage: hash(K(0))
438
+ 0
439
+ sage: hash(K(5))
440
+ 5
441
+ sage: set([1, t, 1/t, t, t, 1/t, 1+1/t, t/t])
442
+ {1, 1/t, t, (t + 1)/t}
443
+ sage: a = (t+1)/(t^2-1); hash(a) == hash((a.numer(),a.denom()))
444
+ True
445
+ """
446
+ if self.denom() == 1:
447
+ return hash(self.numer())
448
+ return hash((self.numer(), self.denom()))
449
+
450
+ def __neg__(self):
451
+ """
452
+ Negate this element.
453
+
454
+ EXAMPLES::
455
+
456
+ sage: K = GF(5)['t'].fraction_field(); t = K.gen(0)
457
+ sage: a = (t^2 + 2)/(t-1)
458
+ sage: -a # indirect doctest
459
+ (4*t^2 + 3)/(t + 4)
460
+ """
461
+ cdef FpTElement x = self._copy_c()
462
+ nmod_poly_neg(x._numer, x._numer)
463
+ return x
464
+
465
+ def __invert__(self):
466
+ """
467
+ Return the multiplicative inverse of this element.
468
+
469
+ EXAMPLES::
470
+
471
+ sage: K = GF(5)['t'].fraction_field(); t = K.gen(0)
472
+ sage: a = (t^2 + 2)/(t-1)
473
+ sage: ~a # indirect doctest
474
+ (t + 4)/(t^2 + 2)
475
+ """
476
+ if nmod_poly_degree(self._numer) == -1:
477
+ raise ZeroDivisionError
478
+ cdef FpTElement x = self._copy_c()
479
+ nmod_poly_swap(x._numer, x._denom)
480
+ return x
481
+
482
+ cpdef _add_(self, _other):
483
+ """
484
+ Return the sum of this fraction field element and another.
485
+
486
+ EXAMPLES::
487
+
488
+ sage: from sage.rings.fraction_field_FpT import *
489
+ sage: R.<t> = FpT(GF(7)['t'])
490
+ sage: t + t # indirect doctest
491
+ 2*t
492
+ sage: (t + 3) + (t + 10)
493
+ 2*t + 6
494
+ sage: sum([t] * 7)
495
+ 0
496
+ sage: 1/t + t
497
+ (t^2 + 1)/t
498
+ sage: 1/t + 1/t^2
499
+ (t + 1)/t^2
500
+ """
501
+ cdef FpTElement other = <FpTElement>_other
502
+ cdef FpTElement x = self._new_c()
503
+ nmod_poly_mul(x._numer, self._numer, other._denom)
504
+ nmod_poly_mul(x._denom, self._denom, other._numer) # use x._denom as a temp
505
+ nmod_poly_add(x._numer, x._numer, x._denom)
506
+ nmod_poly_mul(x._denom, self._denom, other._denom)
507
+ normalize(x._numer, x._denom, self.p)
508
+ return x
509
+
510
+ cpdef _sub_(self, _other):
511
+ """
512
+ Return the difference of this fraction field element and another.
513
+
514
+ EXAMPLES::
515
+
516
+ sage: from sage.rings.fraction_field_FpT import *
517
+ sage: R.<t> = FpT(GF(7)['t'])
518
+ sage: t - t # indirect doctest
519
+ 0
520
+ sage: (t + 3) - (t + 11)
521
+ 6
522
+ """
523
+ cdef FpTElement other = <FpTElement>_other
524
+ cdef FpTElement x = self._new_c()
525
+ nmod_poly_mul(x._numer, self._numer, other._denom)
526
+ nmod_poly_mul(x._denom, self._denom, other._numer) # use x._denom as a temp
527
+ nmod_poly_sub(x._numer, x._numer, x._denom)
528
+ nmod_poly_mul(x._denom, self._denom, other._denom)
529
+ normalize(x._numer, x._denom, self.p)
530
+ return x
531
+
532
+ cpdef _mul_(self, _other):
533
+ """
534
+ Return the product of this fraction field element and another.
535
+
536
+ EXAMPLES::
537
+
538
+ sage: from sage.rings.fraction_field_FpT import *
539
+ sage: R.<t> = FpT(GF(7)['t'])
540
+ sage: t * t # indirect doctest
541
+ t^2
542
+ sage: (t + 3) * (t + 10)
543
+ t^2 + 6*t + 2
544
+ """
545
+ cdef FpTElement other = <FpTElement>_other
546
+ cdef FpTElement x = self._new_c()
547
+ nmod_poly_mul(x._numer, self._numer, other._numer)
548
+ nmod_poly_mul(x._denom, self._denom, other._denom)
549
+ normalize(x._numer, x._denom, self.p)
550
+ return x
551
+
552
+ cpdef _div_(self, _other):
553
+ """
554
+ Return the quotient of this fraction field element and another.
555
+
556
+ EXAMPLES::
557
+
558
+ sage: from sage.rings.fraction_field_FpT import *
559
+ sage: R.<t> = FpT(GF(5)['t'])
560
+ sage: t / t # indirect doctest
561
+ 1
562
+ sage: (t + 3) / (t + 11)
563
+ (t + 3)/(t + 1)
564
+ sage: (t^2 + 2*t + 1) / (t + 1)
565
+ t + 1
566
+ """
567
+ cdef FpTElement other = <FpTElement>_other
568
+ if nmod_poly_degree(other._numer) == -1:
569
+ raise ZeroDivisionError
570
+ cdef FpTElement x = self._new_c()
571
+ nmod_poly_mul(x._numer, self._numer, other._denom)
572
+ nmod_poly_mul(x._denom, self._denom, other._numer)
573
+ normalize(x._numer, x._denom, self.p)
574
+ return x
575
+
576
+ def _im_gens_(self, codomain, im_gens, base_map=None):
577
+ r"""
578
+ Return the image of this element in ``codomain`` under the
579
+ map that sends the image of the generator of the parent to
580
+ the element in ``im_gens``.
581
+
582
+ INPUT:
583
+
584
+ - ``codomain`` -- a ring; where the image is computed
585
+
586
+ - ``im_gens`` -- a list containing the image of the
587
+ generator of the parent as unique element
588
+
589
+ - ``base_map`` -- a morphism (default: ``None``);
590
+ the action on the underlying base ring
591
+
592
+ EXAMPLES::
593
+
594
+ sage: A.<T> = GF(5)[]
595
+ sage: K.<T> = Frac(A)
596
+ sage: f = K.hom([T^2])
597
+ sage: f(1/T)
598
+ 1/T^2
599
+ """
600
+ nden = self.denom()._im_gens_(codomain, im_gens, base_map=base_map)
601
+ invden = nden.inverse_of_unit()
602
+ nnum = self.numer()._im_gens_(codomain, im_gens, base_map=base_map)
603
+ return nnum * invden
604
+
605
+ cpdef FpTElement next(self):
606
+ """
607
+ Iterate through all polynomials, returning the "next" polynomial after this one.
608
+
609
+ The strategy is as follows:
610
+
611
+ - We always leave the denominator monic.
612
+
613
+ - We progress through the elements with both numerator and denominator monic, and with the denominator less than the numerator.
614
+ For each such, we output all the scalar multiples of it, then all of the scalar multiples of its inverse.
615
+
616
+ - So if the leading coefficient of the numerator is less than `p-1`, we scale the numerator to increase it by 1.
617
+
618
+ - Otherwise, we consider the multiple with numerator and denominator monic.
619
+
620
+ - If the numerator is less than the denominator (lexicographically), we return the inverse of that element.
621
+
622
+ - If the numerator is greater than the denominator, we invert, and then increase the numerator (remaining monic) until we either get something relatively prime to the new denominator, or we reach the new denominator. In this case, we increase the denominator and set the numerator to 1.
623
+
624
+ EXAMPLES::
625
+
626
+ sage: from sage.rings.fraction_field_FpT import *
627
+ sage: R.<t> = FpT(GF(3)['t'])
628
+ sage: a = R(0)
629
+ sage: for _ in range(30):
630
+ ....: a = a.next()
631
+ ....: print(a)
632
+ 1
633
+ 2
634
+ 1/t
635
+ 2/t
636
+ t
637
+ 2*t
638
+ 1/(t + 1)
639
+ 2/(t + 1)
640
+ t + 1
641
+ 2*t + 2
642
+ t/(t + 1)
643
+ 2*t/(t + 1)
644
+ (t + 1)/t
645
+ (2*t + 2)/t
646
+ 1/(t + 2)
647
+ 2/(t + 2)
648
+ t + 2
649
+ 2*t + 1
650
+ t/(t + 2)
651
+ 2*t/(t + 2)
652
+ (t + 2)/t
653
+ (2*t + 1)/t
654
+ (t + 1)/(t + 2)
655
+ (2*t + 2)/(t + 2)
656
+ (t + 2)/(t + 1)
657
+ (2*t + 1)/(t + 1)
658
+ 1/t^2
659
+ 2/t^2
660
+ t^2
661
+ 2*t^2
662
+ """
663
+ cdef FpTElement next = self._copy_c()
664
+ cdef long a, lead
665
+ cdef nmod_poly_t g
666
+ if nmod_poly_degree(self._numer) == -1:
667
+ # self should be normalized, so denom == 1
668
+ nmod_poly_set_coeff_ui(next._numer, 0, 1)
669
+ return next
670
+ lead = nmod_poly_leading(next._numer)
671
+ if lead < self.p - 1:
672
+ a = mod_inverse_int(lead, self.p)
673
+ # no overflow since self.p < 2^16
674
+ a = a * (lead + 1) % self.p
675
+ nmod_poly_scalar_mul_nmod(next._numer, next._numer, a)
676
+ else:
677
+ a = mod_inverse_int(lead, self.p)
678
+ nmod_poly_scalar_mul_nmod(next._numer, next._numer, a)
679
+ # now both next._numer and next._denom are monic. We figure out which is lexicographically bigger:
680
+ a = nmod_poly_cmp(next._numer, next._denom)
681
+ if a == 0:
682
+ # next._numer and next._denom are relatively prime, so they're both 1.
683
+ nmod_poly_inc(next._denom, True)
684
+ return next
685
+ nmod_poly_set(next._denom, next._numer)
686
+ nmod_poly_set(next._numer, self._denom)
687
+ if a < 0:
688
+ # since next._numer is smaller, we flip and return the inverse.
689
+ return next
690
+ elif a > 0:
691
+ # since next._numer is bigger, we're in the flipped phase. We flip back, and increment the numerator (until we reach the denominator).
692
+ nmod_poly_init(g, self.p)
693
+ try:
694
+ while True:
695
+ nmod_poly_inc(next._numer, True)
696
+ if nmod_poly_equal(next._numer, next._denom):
697
+ # Since we've reached the denominator, we reset the numerator to 1 and increment the denominator.
698
+ nmod_poly_inc(next._denom, True)
699
+ nmod_poly_zero(next._numer)
700
+ nmod_poly_set_coeff_ui(next._numer, 0, 1)
701
+ break
702
+ else:
703
+ # otherwise, we keep incrementing until we have a relatively prime numerator.
704
+ nmod_poly_gcd(g, next._numer, next._denom)
705
+ if nmod_poly_is_one(g):
706
+ break
707
+ finally:
708
+ nmod_poly_clear(g)
709
+ return next
710
+
711
+ cpdef _sqrt_or_None(self):
712
+ """
713
+ Return the square root of ``self``, or ``None``.
714
+
715
+ Differs from sqrt() by not raising an exception.
716
+
717
+ TESTS::
718
+
719
+ sage: from sage.rings.fraction_field_FpT import *
720
+ sage: R.<t> = FpT(GF(17)['t'])
721
+ sage: sqrt(t^2) # indirect doctest
722
+ t
723
+ sage: sqrt(1/t^2)
724
+ 1/t
725
+ sage: sqrt((1+t)^2)
726
+ t + 1
727
+ sage: sqrt((1+t)^2 / t^2)
728
+ (t + 1)/t
729
+
730
+ sage: sqrt(4 * (1+t)^2 / t^2)
731
+ (2*t + 2)/t
732
+
733
+ sage: sqrt(R(0))
734
+ 0
735
+ sage: sqrt(R(-1))
736
+ 4
737
+
738
+ sage: sqrt(t^4)
739
+ t^2
740
+ sage: sqrt(4*t^4/(1+t)^8)
741
+ 2*t^2/(t^4 + 4*t^3 + 6*t^2 + 4*t + 1)
742
+
743
+ sage: R.<t> = FpT(GF(5)['t'])
744
+ sage: [a for a in R.iter(2) if (a^2).sqrt() not in (a,-a)]
745
+ []
746
+ sage: [a for a in R.iter(2) if a.is_square() and a.sqrt()^2 != a]
747
+ []
748
+ """
749
+ if nmod_poly_is_zero(self._numer):
750
+ return self
751
+
752
+ if not nmod_poly_sqrt_check(self._numer) or not nmod_poly_sqrt_check(self._denom):
753
+ return None
754
+
755
+ cdef nmod_poly_t numer
756
+ cdef nmod_poly_t denom
757
+ cdef long a
758
+ cdef FpTElement res
759
+
760
+ nmod_poly_init(denom, self.p)
761
+ nmod_poly_init(numer, self.p)
762
+
763
+ if nmod_poly_sqrt(numer, self._numer) and nmod_poly_sqrt(denom, self._denom):
764
+ # Make denominator monic
765
+ a = nmod_poly_leading(denom)
766
+ if a != 1:
767
+ a = mod_inverse_int(a, self.p)
768
+ nmod_poly_scalar_mul_nmod(numer, numer, a)
769
+ nmod_poly_scalar_mul_nmod(denom, denom, a)
770
+ # Choose numerator with smaller leading coefficient
771
+ a = nmod_poly_leading(numer)
772
+ if a > self.p - a:
773
+ nmod_poly_neg(numer, numer)
774
+ res = self._new_c()
775
+ nmod_poly_swap(numer, res._numer)
776
+ nmod_poly_swap(denom, res._denom)
777
+ return res
778
+ else:
779
+ nmod_poly_clear(numer)
780
+ nmod_poly_clear(denom)
781
+ return None
782
+
783
+ cpdef bint is_square(self) noexcept:
784
+ """
785
+ Return ``True`` if this element is the square of another element of the fraction field.
786
+
787
+ EXAMPLES::
788
+
789
+ sage: K = GF(13)['t'].fraction_field(); t = K.gen()
790
+ sage: t.is_square()
791
+ False
792
+ sage: (1/t^2).is_square()
793
+ True
794
+ sage: K(0).is_square()
795
+ True
796
+ """
797
+ return self._sqrt_or_None() is not None
798
+
799
+ def sqrt(self, extend=True, all=False):
800
+ """
801
+ Return the square root of this element.
802
+
803
+ INPUT:
804
+
805
+ - ``extend`` -- boolean (default: ``True``); if ``True``, return a
806
+ square root in an extension ring, if necessary. Otherwise, raise a
807
+ :exc:`ValueError` if the square is not in the base ring.
808
+
809
+ - ``all`` -- boolean (default: ``False``); if ``True``, return all
810
+ square roots of self, instead of just one
811
+
812
+ EXAMPLES::
813
+
814
+ sage: from sage.rings.fraction_field_FpT import *
815
+ sage: K = GF(7)['t'].fraction_field(); t = K.gen(0)
816
+ sage: p = (t + 2)^2/(3*t^3 + 1)^4
817
+ sage: p.sqrt()
818
+ (3*t + 6)/(t^6 + 3*t^3 + 4)
819
+ sage: p.sqrt()^2 == p
820
+ True
821
+ """
822
+ s = self._sqrt_or_None()
823
+ if s is None:
824
+ if extend:
825
+ raise NotImplementedError("function fields not yet implemented")
826
+ else:
827
+ raise ValueError("not a perfect square")
828
+ else:
829
+ if all:
830
+ if not s:
831
+ return [s]
832
+ else:
833
+ return [s, -s]
834
+ else:
835
+ return s
836
+
837
+ def __pow__(FpTElement self, Py_ssize_t e, dummy):
838
+ r"""
839
+ Return the `e`-th power of this element.
840
+
841
+ EXAMPLES::
842
+
843
+ sage: from sage.rings.fraction_field_FpT import *
844
+ sage: R.<t> = FpT(GF(7)['t'])
845
+ sage: t^5
846
+ t^5
847
+ sage: t^-5
848
+ 1/t^5
849
+
850
+ sage: a = (t+1)/(t-1); a
851
+ (t + 1)/(t + 6)
852
+ sage: a^5
853
+ (t^5 + 5*t^4 + 3*t^3 + 3*t^2 + 5*t + 1)/(t^5 + 2*t^4 + 3*t^3 + 4*t^2 + 5*t + 6)
854
+ sage: a^7
855
+ (t^7 + 1)/(t^7 + 6)
856
+ sage: a^14
857
+ (t^14 + 2*t^7 + 1)/(t^14 + 5*t^7 + 1)
858
+
859
+ sage: (a^2)^2 == a^4
860
+ True
861
+ sage: a^3 * a^2 == a^5
862
+ True
863
+ sage: a^47 * a^92 == a^(47+92)
864
+ True
865
+ """
866
+ cdef long a
867
+ assert dummy is None
868
+ cdef FpTElement x = self._new_c()
869
+ if e >= 0:
870
+ nmod_poly_pow(x._numer, self._numer, e)
871
+ nmod_poly_pow(x._denom, self._denom, e)
872
+ else:
873
+ nmod_poly_pow(x._denom, self._numer, -e)
874
+ nmod_poly_pow(x._numer, self._denom, -e)
875
+ if nmod_poly_leading(x._denom) != 1:
876
+ a = mod_inverse_int(nmod_poly_leading(x._denom), self.p)
877
+ nmod_poly_scalar_mul_nmod(x._numer, x._numer, a)
878
+ nmod_poly_scalar_mul_nmod(x._denom, x._denom, a)
879
+ return x
880
+
881
+
882
+ cdef class FpT_iter:
883
+ """
884
+ Return a class that iterates over all elements of an FpT.
885
+
886
+ EXAMPLES::
887
+
888
+ sage: K = GF(3)['t'].fraction_field()
889
+ sage: I = K.iter(1)
890
+ sage: list(I)
891
+ [0,
892
+ 1,
893
+ 2,
894
+ t,
895
+ t + 1,
896
+ t + 2,
897
+ 2*t,
898
+ 2*t + 1,
899
+ 2*t + 2,
900
+ 1/t,
901
+ 2/t,
902
+ (t + 1)/t,
903
+ (t + 2)/t,
904
+ (2*t + 1)/t,
905
+ (2*t + 2)/t,
906
+ 1/(t + 1),
907
+ 2/(t + 1),
908
+ t/(t + 1),
909
+ (t + 2)/(t + 1),
910
+ 2*t/(t + 1),
911
+ (2*t + 1)/(t + 1),
912
+ 1/(t + 2),
913
+ 2/(t + 2),
914
+ t/(t + 2),
915
+ (t + 1)/(t + 2),
916
+ 2*t/(t + 2),
917
+ (2*t + 2)/(t + 2)]
918
+ """
919
+ def __init__(self, parent, degree=None, FpTElement start=None):
920
+ """
921
+ INPUT:
922
+
923
+ - ``parent`` -- the FpT that we're iterating over
924
+
925
+ - ``degree`` -- the maximum degree of the numerator and denominator of
926
+ the elements over which we iterate
927
+
928
+ - ``start`` -- (default: 0) the element on which to start
929
+
930
+ EXAMPLES::
931
+
932
+ sage: K = GF(11)['t'].fraction_field()
933
+ sage: I = K.iter(2) # indirect doctest
934
+ sage: for a in I:
935
+ ....: if a.denom()[0] == 3 and a.numer()[1] == 2:
936
+ ....: print(a); break
937
+ 2*t/(t + 3)
938
+ """
939
+ # if degree is None:
940
+ # raise NotImplementedError
941
+ self.parent = parent
942
+ self.cur = start
943
+ self.degree = -2 if degree is None else degree
944
+
945
+ def __cinit__(self, parent, *args, **kwds):
946
+ """
947
+ Memory allocation for the temp variable storing the gcd of the numerator and denominator.
948
+
949
+ TESTS::
950
+
951
+ sage: from sage.rings.fraction_field_FpT import FpT_iter
952
+ sage: K = GF(7)['t'].fraction_field()
953
+ sage: I = FpT_iter(K, 3) # indirect doctest
954
+ sage: I
955
+ <sage.rings.fraction_field_FpT.FpT_iter object at ...>
956
+ """
957
+ nmod_poly_init(self.g, parent.characteristic())
958
+
959
+ def __dealloc__(self):
960
+ """
961
+ Deallocating of self.g.
962
+
963
+ TESTS::
964
+
965
+ sage: from sage.rings.fraction_field_FpT import FpT_iter
966
+ sage: K = GF(7)['t'].fraction_field()
967
+ sage: I = FpT_iter(K, 3)
968
+ sage: del I # indirect doctest
969
+ """
970
+ nmod_poly_clear(self.g)
971
+
972
+ def __iter__(self):
973
+ """
974
+ Return this iterator.
975
+
976
+ TESTS::
977
+
978
+ sage: from sage.rings.fraction_field_FpT import FpT_iter
979
+ sage: K = GF(3)['t'].fraction_field()
980
+ sage: I = FpT_iter(K, 3)
981
+ sage: for a in I: # indirect doctest
982
+ ....: if a.numer()[1] == 1 and a.denom()[1] == 2 and a.is_square():
983
+ ....: print(a); break
984
+ (t^2 + t + 1)/(t^2 + 2*t + 1)
985
+ """
986
+ return self
987
+
988
+ def __next__(self):
989
+ """
990
+ Return the next element to iterate over.
991
+
992
+ This is achieved by iterating over monic denominators, and for each denominator,
993
+ iterating over all numerators relatively prime to the given denominator.
994
+
995
+ EXAMPLES::
996
+
997
+ sage: from sage.rings.fraction_field_FpT import *
998
+ sage: K.<t> = FpT(GF(3)['t'])
999
+ sage: list(K.iter(1)) # indirect doctest
1000
+ [0,
1001
+ 1,
1002
+ 2,
1003
+ t,
1004
+ t + 1,
1005
+ t + 2,
1006
+ 2*t,
1007
+ 2*t + 1,
1008
+ 2*t + 2,
1009
+ 1/t,
1010
+ 2/t,
1011
+ (t + 1)/t,
1012
+ (t + 2)/t,
1013
+ (2*t + 1)/t,
1014
+ (2*t + 2)/t,
1015
+ 1/(t + 1),
1016
+ 2/(t + 1),
1017
+ t/(t + 1),
1018
+ (t + 2)/(t + 1),
1019
+ 2*t/(t + 1),
1020
+ (2*t + 1)/(t + 1),
1021
+ 1/(t + 2),
1022
+ 2/(t + 2),
1023
+ t/(t + 2),
1024
+ (t + 1)/(t + 2),
1025
+ 2*t/(t + 2),
1026
+ (2*t + 2)/(t + 2)]
1027
+
1028
+ sage: len(list(K.iter(3)))
1029
+ 2187
1030
+
1031
+ sage: K.<t> = FpT(GF(5)['t'])
1032
+ sage: L = list(K.iter(3)); len(L)
1033
+ 78125
1034
+ sage: L[:10]
1035
+ [0, 1, 2, 3, 4, t, t + 1, t + 2, t + 3, t + 4]
1036
+ sage: L[2000]
1037
+ (3*t^3 + 3*t^2 + 3*t + 4)/(t + 2)
1038
+ sage: L[-1]
1039
+ (4*t^3 + 4*t^2 + 4*t + 4)/(t^3 + 4*t^2 + 4*t + 4)
1040
+ """
1041
+ cdef FpTElement next_
1042
+ if self.cur is None:
1043
+ self.cur = self.parent(0)
1044
+ elif self.degree == -2:
1045
+ self.cur = next(self.cur)
1046
+ else:
1047
+ next_ = self.cur._copy_c()
1048
+ sig_on()
1049
+ while True:
1050
+ nmod_poly_inc(next_._numer, False)
1051
+ if nmod_poly_degree(next_._numer) > self.degree:
1052
+ nmod_poly_inc(next_._denom, True)
1053
+ if nmod_poly_degree(next_._denom) > self.degree:
1054
+ sig_off()
1055
+ raise StopIteration
1056
+ nmod_poly_zero(next_._numer)
1057
+ nmod_poly_set_coeff_ui(next_._numer, 0, 1)
1058
+ nmod_poly_gcd(self.g, next_._numer, next_._denom)
1059
+ if nmod_poly_is_one(self.g):
1060
+ break
1061
+ sig_off()
1062
+ self.cur = next_
1063
+ return self.cur
1064
+
1065
+ cdef class Polyring_FpT_coerce(RingHomomorphism):
1066
+ """
1067
+ This class represents the coercion map from GF(p)[t] to GF(p)(t).
1068
+
1069
+ EXAMPLES::
1070
+
1071
+ sage: R.<t> = GF(5)[]
1072
+ sage: K = R.fraction_field()
1073
+ sage: f = K.coerce_map_from(R); f
1074
+ Ring morphism:
1075
+ From: Univariate Polynomial Ring in t over Finite Field of size 5
1076
+ To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1077
+ sage: type(f)
1078
+ <class 'sage.rings.fraction_field_FpT.Polyring_FpT_coerce'>
1079
+
1080
+ TESTS::
1081
+
1082
+ TestSuite(f).run()
1083
+ """
1084
+ cdef long p
1085
+
1086
+ def __init__(self, R):
1087
+ """
1088
+ INPUT:
1089
+
1090
+ - ``R`` -- an FpT
1091
+
1092
+ EXAMPLES::
1093
+
1094
+ sage: # needs sage.rings.finite_rings
1095
+ sage: R.<t> = GF(next_prime(2000))[]
1096
+ sage: K = R.fraction_field() # indirect doctest
1097
+ """
1098
+ RingHomomorphism.__init__(self, R.ring_of_integers().Hom(R))
1099
+ self.p = R.base_ring().characteristic()
1100
+
1101
+ cdef dict _extra_slots(self):
1102
+ """
1103
+ Helper for copying and pickling.
1104
+
1105
+ EXAMPLES::
1106
+
1107
+ sage: R.<t> = GF(5)[]
1108
+ sage: K = R.fraction_field()
1109
+ sage: f = K.coerce_map_from(R) # indirect doctest
1110
+ sage: f(t^2 + 1)
1111
+ t^2 + 1
1112
+ """
1113
+ slots = RingHomomorphism._extra_slots(self)
1114
+ slots['p'] = self.p
1115
+ return slots
1116
+
1117
+ cdef _update_slots(self, dict _slots):
1118
+ """
1119
+ Helper for copying and pickling.
1120
+
1121
+ EXAMPLES::
1122
+
1123
+ sage: R.<t> = GF(5)[]
1124
+ sage: K = R.fraction_field()
1125
+ sage: f = K.coerce_map_from(R) # indirect doctest
1126
+ sage: f(t^2 + 1)
1127
+ t^2 + 1
1128
+ """
1129
+ self.p = _slots['p']
1130
+ RingHomomorphism._update_slots(self, _slots)
1131
+
1132
+ cpdef Element _call_(self, _x):
1133
+ """
1134
+ Applies the coercion.
1135
+
1136
+ EXAMPLES::
1137
+
1138
+ sage: R.<t> = GF(5)[]
1139
+ sage: K = R.fraction_field()
1140
+ sage: f = K.coerce_map_from(R)
1141
+ sage: f(t^2 + 1) # indirect doctest
1142
+ t^2 + 1
1143
+ """
1144
+ cdef Polynomial_zmod_flint x = <Polynomial_zmod_flint?> _x
1145
+ cdef FpTElement ans = <FpTElement>FpTElement.__new__(FpTElement)
1146
+ ans._parent = self.codomain()
1147
+ ans.p = self.p
1148
+ nmod_poly_init(ans._numer, ans.p)
1149
+ nmod_poly_init(ans._denom, ans.p)
1150
+ nmod_poly_set(ans._numer, &x.x)
1151
+ nmod_poly_set_coeff_ui(ans._denom, 0, 1)
1152
+ ans.initialized = True
1153
+ return ans
1154
+
1155
+ cpdef Element _call_with_args(self, _x, args=(), kwds={}):
1156
+ """
1157
+ This function allows the map to take multiple arguments,
1158
+ usually used to specify both numerator and denominator.
1159
+
1160
+ If ``reduce`` is specified as False, then the result won't be
1161
+ normalized.
1162
+
1163
+ EXAMPLES::
1164
+
1165
+ sage: R.<t> = GF(5)[]
1166
+ sage: K = R.fraction_field()
1167
+ sage: f = K.coerce_map_from(R)
1168
+ sage: f(2*t + 2, t + 3) # indirect doctest
1169
+ (2*t + 2)/(t + 3)
1170
+ sage: f(2*t + 2, 2)
1171
+ t + 1
1172
+ sage: f(2*t + 2, 2, reduce=False)
1173
+ (2*t + 2)/2
1174
+
1175
+ TESTS:
1176
+
1177
+ Check that :issue:`12217` and :issue:`16811` are fixed::
1178
+
1179
+ sage: R.<t> = GF(5)[]
1180
+ sage: K = R.fraction_field()
1181
+ sage: f = K.coerce_map_from(R)
1182
+ sage: f(t, 0)
1183
+ Traceback (most recent call last):
1184
+ ...
1185
+ ZeroDivisionError: fraction has denominator 0
1186
+ sage: f(t, GF(5).zero())
1187
+ Traceback (most recent call last):
1188
+ ...
1189
+ ZeroDivisionError: fraction has denominator 0
1190
+ sage: f(t, R.zero())
1191
+ Traceback (most recent call last):
1192
+ ...
1193
+ ZeroDivisionError: fraction has denominator 0
1194
+ """
1195
+ cdef Polynomial_zmod_flint x
1196
+ cdef unsigned long r
1197
+ try:
1198
+ x = <Polynomial_zmod_flint?> _x
1199
+ except TypeError:
1200
+ raise NotImplementedError('Fraction fields not implemented for this type.')
1201
+ cdef FpTElement ans = <FpTElement>FpTElement.__new__(FpTElement)
1202
+ ans._parent = self.codomain()
1203
+ ans.p = self.p
1204
+ nmod_poly_init(ans._numer, ans.p)
1205
+ nmod_poly_init(ans._denom, ans.p)
1206
+ nmod_poly_set(ans._numer, &x.x)
1207
+ if len(args) == 0:
1208
+ nmod_poly_set_coeff_ui(ans._denom, 0, 1) # No need to normalize
1209
+ elif len(args) == 1:
1210
+ y = args[0]
1211
+ if isinstance(y, Integer):
1212
+ r = mpz_fdiv_ui((<Integer>y).value, self.p)
1213
+ nmod_poly_set_coeff_ui(ans._denom, 0, r)
1214
+ else:
1215
+ # could use the coerce keyword being set to False to not check this...
1216
+ if not (isinstance(y, Element) and y.parent() is self.domain()):
1217
+ # We could special case integers and GF(p) elements here.
1218
+ y = self.domain()(y)
1219
+ nmod_poly_set(ans._denom, &((<Polynomial_zmod_flint?>y).x))
1220
+ # Normalize the fraction, checking for division by zero
1221
+ if nmod_poly_is_zero(ans._denom):
1222
+ raise ZeroDivisionError('fraction has denominator 0')
1223
+ if kwds.get('reduce', True):
1224
+ normalize(ans._numer, ans._denom, ans.p)
1225
+ else:
1226
+ raise TypeError("FpT only supports two positional arguments")
1227
+ ans.initialized = True
1228
+ return ans
1229
+
1230
+ def section(self):
1231
+ """
1232
+ Return the section of this inclusion: the partially defined map from ``GF(p)(t)``
1233
+ back to ``GF(p)[t]``, defined on elements with unit denominator.
1234
+
1235
+ EXAMPLES::
1236
+
1237
+ sage: R.<t> = GF(5)[]
1238
+ sage: K = R.fraction_field()
1239
+ sage: f = K.coerce_map_from(R)
1240
+ sage: g = f.section(); g
1241
+ Section map:
1242
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1243
+ To: Univariate Polynomial Ring in t over Finite Field of size 5
1244
+ sage: t = K.gen()
1245
+ sage: g(t)
1246
+ t
1247
+ sage: g(1/t)
1248
+ Traceback (most recent call last):
1249
+ ...
1250
+ ValueError: not integral
1251
+ """
1252
+ return FpT_Polyring_section(self)
1253
+
1254
+ cdef class FpT_Polyring_section(Section):
1255
+ """
1256
+ This class represents the section from GF(p)(t) back to GF(p)[t].
1257
+
1258
+ EXAMPLES::
1259
+
1260
+ sage: R.<t> = GF(5)[]
1261
+ sage: K = R.fraction_field()
1262
+ sage: f = R.convert_map_from(K); f
1263
+ Section map:
1264
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1265
+ To: Univariate Polynomial Ring in t over Finite Field of size 5
1266
+ sage: type(f)
1267
+ <class 'sage.rings.fraction_field_FpT.FpT_Polyring_section'>
1268
+
1269
+ .. WARNING::
1270
+
1271
+ Comparison of ``FpT_Polyring_section`` objects is not currently
1272
+ implemented. See :issue:`23469`. ::
1273
+
1274
+ sage: fprime = loads(dumps(f))
1275
+ sage: fprime == f
1276
+ False
1277
+
1278
+ sage: fprime(1+t) == f(1+t)
1279
+ True
1280
+
1281
+ TESTS::
1282
+
1283
+ sage: TestSuite(f).run(skip='_test_pickling')
1284
+ """
1285
+ cdef long p
1286
+
1287
+ def __init__(self, Polyring_FpT_coerce f):
1288
+ """
1289
+ INPUT:
1290
+
1291
+ - ``f`` -- a Polyring_FpT_coerce homomorphism
1292
+
1293
+ EXAMPLES::
1294
+
1295
+ sage: # needs sage.rings.finite_rings
1296
+ sage: R.<t> = GF(next_prime(2000))[]
1297
+ sage: K = R.fraction_field()
1298
+ sage: R(K.gen(0)) # indirect doctest
1299
+ t
1300
+ """
1301
+ self.p = f.p
1302
+ Section.__init__(self, f)
1303
+
1304
+ cdef dict _extra_slots(self):
1305
+ """
1306
+ Helper for copying and pickling.
1307
+
1308
+ EXAMPLES::
1309
+
1310
+ sage: R.<t> = GF(7)[]
1311
+ sage: K = R.fraction_field()
1312
+ sage: f = K.coerce_map_from(R)
1313
+ sage: g = f.section() # indirect doctest
1314
+ sage: t = K.gen()
1315
+ sage: g(t^2)
1316
+ t^2
1317
+ sage: g(1/t)
1318
+ Traceback (most recent call last):
1319
+ ...
1320
+ ValueError: not integral
1321
+ """
1322
+ slots = Section._extra_slots(self)
1323
+ slots['p'] = self.p
1324
+ return slots
1325
+
1326
+ cdef _update_slots(self, dict _slots):
1327
+ """
1328
+ Helper for copying and pickling.
1329
+
1330
+ EXAMPLES::
1331
+
1332
+ sage: R.<t> = GF(7)[]
1333
+ sage: K = R.fraction_field()
1334
+ sage: f = K.coerce_map_from(R)
1335
+ sage: g = f.section() # indirect doctest
1336
+ sage: t = K.gen()
1337
+ sage: g(t^2)
1338
+ t^2
1339
+ sage: g(1/t)
1340
+ Traceback (most recent call last):
1341
+ ...
1342
+ ValueError: not integral
1343
+ """
1344
+ self.p = _slots['p']
1345
+ Section._update_slots(self, _slots)
1346
+
1347
+ cpdef Element _call_(self, _x):
1348
+ """
1349
+ Applies the section.
1350
+
1351
+ EXAMPLES::
1352
+
1353
+ sage: R.<t> = GF(7)[]
1354
+ sage: K = R.fraction_field()
1355
+ sage: f = K.coerce_map_from(R)
1356
+ sage: g = f.section(); g
1357
+ Section map:
1358
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7
1359
+ To: Univariate Polynomial Ring in t over Finite Field of size 7
1360
+ sage: t = K.gen()
1361
+ sage: g(t^2) # indirect doctest
1362
+ t^2
1363
+ sage: g(1/t)
1364
+ Traceback (most recent call last):
1365
+ ...
1366
+ ValueError: not integral
1367
+ """
1368
+ cdef FpTElement x = <FpTElement?>_x
1369
+ cdef Polynomial_zmod_flint ans
1370
+ if nmod_poly_degree(x._denom) != 0:
1371
+ normalize(x._numer, x._denom, self.p)
1372
+ if nmod_poly_degree(x._denom) != 0:
1373
+ raise ValueError("not integral")
1374
+ ans = Polynomial_zmod_flint.__new__(Polynomial_zmod_flint)
1375
+ if nmod_poly_get_coeff_ui(x._denom, 0) != 1:
1376
+ normalize(x._numer, x._denom, self.p)
1377
+ nmod_poly_init(&ans.x, self.p)
1378
+ nmod_poly_set(&ans.x, x._numer)
1379
+ ans._parent = self.codomain()
1380
+ ans._cparent = get_cparent(ans._parent)
1381
+ return ans
1382
+
1383
+ cdef class Fp_FpT_coerce(RingHomomorphism):
1384
+ """
1385
+ This class represents the coercion map from GF(p) to GF(p)(t).
1386
+
1387
+ EXAMPLES::
1388
+
1389
+ sage: R.<t> = GF(5)[]
1390
+ sage: K = R.fraction_field()
1391
+ sage: f = K.coerce_map_from(GF(5)); f
1392
+ Ring morphism:
1393
+ From: Finite Field of size 5
1394
+ To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1395
+ sage: type(f)
1396
+ <class 'sage.rings.fraction_field_FpT.Fp_FpT_coerce'>
1397
+
1398
+ TESTS::
1399
+
1400
+ sage: TestSuite(f).run()
1401
+ """
1402
+ cdef long p
1403
+
1404
+ def __init__(self, R):
1405
+ """
1406
+ INPUT:
1407
+
1408
+ - ``R`` -- an FpT
1409
+
1410
+ EXAMPLES::
1411
+
1412
+ sage: # needs sage.rings.finite_rings
1413
+ sage: R.<t> = GF(next_prime(3000))[]
1414
+ sage: K = R.fraction_field() # indirect doctest
1415
+ """
1416
+ RingHomomorphism.__init__(self, R.base_ring().Hom(R))
1417
+ self.p = R.base_ring().characteristic()
1418
+
1419
+ cdef dict _extra_slots(self):
1420
+ """
1421
+ Helper for copying and pickling.
1422
+
1423
+ EXAMPLES::
1424
+
1425
+ sage: R.<t> = GF(5)[]
1426
+ sage: K = R.fraction_field()
1427
+ sage: f = K.coerce_map_from(GF(5))
1428
+ sage: g = copy(f)
1429
+ sage: g == f
1430
+ True
1431
+ sage: g(GF(5)(2)) == f(GF(5)(2))
1432
+ True
1433
+ """
1434
+ slots = RingHomomorphism._extra_slots(self)
1435
+ slots['p'] = self.p
1436
+ return slots
1437
+
1438
+ cdef _update_slots(self, dict _slots):
1439
+ """
1440
+ Helper for copying and pickling.
1441
+
1442
+ EXAMPLES::
1443
+
1444
+ sage: R.<t> = GF(5)[]
1445
+ sage: K = R.fraction_field()
1446
+ sage: f = K.coerce_map_from(GF(5))
1447
+ sage: g = copy(f)
1448
+ sage: g == f
1449
+ True
1450
+ sage: g(GF(5)(2)) == f(GF(5)(2))
1451
+ True
1452
+ """
1453
+ self.p = _slots['p']
1454
+ RingHomomorphism._update_slots(self, _slots)
1455
+
1456
+ cpdef Element _call_(self, _x):
1457
+ """
1458
+ Applies the coercion.
1459
+
1460
+ EXAMPLES::
1461
+
1462
+ sage: R.<t> = GF(5)[]
1463
+ sage: K = R.fraction_field()
1464
+ sage: f = K.coerce_map_from(GF(5))
1465
+ sage: f(GF(5)(3)) # indirect doctest
1466
+ 3
1467
+ """
1468
+ cdef IntegerMod_int x = <IntegerMod_int?> _x
1469
+ cdef FpTElement ans = <FpTElement>FpTElement.__new__(FpTElement)
1470
+ ans._parent = self.codomain()
1471
+ ans.p = self.p
1472
+ nmod_poly_init(ans._numer, ans.p)
1473
+ nmod_poly_init(ans._denom, ans.p)
1474
+ nmod_poly_set_coeff_ui(ans._numer, 0, x.ivalue)
1475
+ nmod_poly_set_coeff_ui(ans._denom, 0, 1)
1476
+ ans.initialized = True
1477
+ return ans
1478
+
1479
+ cpdef Element _call_with_args(self, _x, args=(), kwds={}):
1480
+ """
1481
+ This function allows the map to take multiple arguments, usually used to specify both numerator and denominator.
1482
+
1483
+ If ``reduce`` is specified as False, then the result won't be normalized.
1484
+
1485
+ EXAMPLES::
1486
+
1487
+ sage: R.<t> = GF(5)[]
1488
+ sage: K = R.fraction_field()
1489
+ sage: f = K.coerce_map_from(GF(5))
1490
+ sage: f(1, t + 3) # indirect doctest
1491
+ 1/(t + 3)
1492
+ sage: f(2, 2*t)
1493
+ 1/t
1494
+ sage: f(2, 2*t, reduce=False)
1495
+ 2/2*t
1496
+ """
1497
+ cdef IntegerMod_int x = <IntegerMod_int?> _x
1498
+ cdef FpTElement ans = <FpTElement>FpTElement.__new__(FpTElement)
1499
+ ans._parent = self.codomain()
1500
+ ans.p = self.p
1501
+ nmod_poly_init(ans._numer, ans.p)
1502
+ nmod_poly_init(ans._denom, ans.p)
1503
+ cdef long r
1504
+ nmod_poly_set_coeff_ui(ans._numer, 0, x.ivalue)
1505
+ if len(args) == 0:
1506
+ nmod_poly_set_coeff_ui(ans._denom, 0, 1)
1507
+ if len(args) == 1:
1508
+ y = args[0]
1509
+ if isinstance(y, Integer):
1510
+ r = mpz_fdiv_ui((<Integer>y).value, self.p)
1511
+ if r == 0:
1512
+ raise ZeroDivisionError
1513
+ nmod_poly_set_coeff_ui(ans._denom, 0, r)
1514
+ else:
1515
+ R = ans._parent.ring_of_integers()
1516
+ # could use the coerce keyword being set to False to not check this...
1517
+ if not (isinstance(y, Element) and y.parent() is R):
1518
+ # We could special case integers and GF(p) elements here.
1519
+ y = R(y)
1520
+ nmod_poly_set(ans._denom, &((<Polynomial_zmod_flint?>y).x))
1521
+ else:
1522
+ raise ValueError("FpT only supports two positional arguments")
1523
+ if 'reduce' not in kwds or kwds['reduce']:
1524
+ normalize(ans._numer, ans._denom, ans.p)
1525
+ ans.initialized = True
1526
+ return ans
1527
+
1528
+ def section(self):
1529
+ """
1530
+ Return the section of this inclusion: the partially defined map from ``GF(p)(t)``
1531
+ back to ``GF(p)``, defined on constant elements.
1532
+
1533
+ EXAMPLES::
1534
+
1535
+ sage: R.<t> = GF(5)[]
1536
+ sage: K = R.fraction_field()
1537
+ sage: f = K.coerce_map_from(GF(5))
1538
+ sage: g = f.section(); g
1539
+ Section map:
1540
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1541
+ To: Finite Field of size 5
1542
+ sage: t = K.gen()
1543
+ sage: g(f(1,3,reduce=False))
1544
+ 2
1545
+ sage: g(t)
1546
+ Traceback (most recent call last):
1547
+ ...
1548
+ ValueError: not constant
1549
+ sage: g(1/t)
1550
+ Traceback (most recent call last):
1551
+ ...
1552
+ ValueError: not integral
1553
+ """
1554
+ return FpT_Fp_section(self)
1555
+
1556
+ cdef class FpT_Fp_section(Section):
1557
+ """
1558
+ This class represents the section from GF(p)(t) back to GF(p)[t].
1559
+
1560
+ EXAMPLES::
1561
+
1562
+ sage: R.<t> = GF(5)[]
1563
+ sage: K = R.fraction_field()
1564
+ sage: f = GF(5).convert_map_from(K); f
1565
+ Section map:
1566
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1567
+ To: Finite Field of size 5
1568
+ sage: type(f)
1569
+ <class 'sage.rings.fraction_field_FpT.FpT_Fp_section'>
1570
+
1571
+ .. WARNING::
1572
+
1573
+ Comparison of ``FpT_Fp_section`` objects is not currently
1574
+ implemented. See :issue:`23469`. ::
1575
+
1576
+ sage: fprime = loads(dumps(f))
1577
+ sage: fprime == f
1578
+ False
1579
+
1580
+ sage: fprime(3) == f(3)
1581
+ True
1582
+
1583
+ TESTS::
1584
+
1585
+ sage: TestSuite(f).run(skip='_test_pickling')
1586
+ """
1587
+ cdef long p
1588
+
1589
+ def __init__(self, Fp_FpT_coerce f):
1590
+ """
1591
+ INPUT:
1592
+
1593
+ - ``f`` -- an ``Fp_FpT_coerce`` homomorphism
1594
+
1595
+ EXAMPLES::
1596
+
1597
+ sage: # needs sage.rings.finite_rings
1598
+ sage: R.<t> = GF(next_prime(2000))[]
1599
+ sage: K = R.fraction_field()
1600
+ sage: GF(next_prime(2000))(K(127)) # indirect doctest
1601
+ 127
1602
+ """
1603
+ self.p = f.p
1604
+ Section.__init__(self, f)
1605
+
1606
+ cdef dict _extra_slots(self):
1607
+ """
1608
+ Helper for copying and pickling.
1609
+
1610
+ EXAMPLES::
1611
+
1612
+ sage: R.<t> = GF(7)[]
1613
+ sage: K = R.fraction_field()
1614
+ sage: f = K.coerce_map_from(GF(7))
1615
+ sage: g = f.section() # indirect doctest
1616
+ sage: t = K.gen()
1617
+ sage: g(t^2)
1618
+ Traceback (most recent call last):
1619
+ ...
1620
+ ValueError: not constant
1621
+ sage: g(1/t)
1622
+ Traceback (most recent call last):
1623
+ ...
1624
+ ValueError: not integral
1625
+ sage: g(K(4))
1626
+ 4
1627
+ sage: g(K(0))
1628
+ 0
1629
+ """
1630
+ slots = Section._extra_slots(self)
1631
+ slots['p'] = self.p
1632
+ return slots
1633
+
1634
+ cdef _update_slots(self, dict _slots):
1635
+ """
1636
+ Helper for copying and pickling.
1637
+
1638
+ EXAMPLES::
1639
+
1640
+ sage: R.<t> = GF(7)[]
1641
+ sage: K = R.fraction_field()
1642
+ sage: f = K.coerce_map_from(GF(7))
1643
+ sage: g = f.section() # indirect doctest
1644
+ sage: t = K.gen()
1645
+ sage: g(t^2)
1646
+ Traceback (most recent call last):
1647
+ ...
1648
+ ValueError: not constant
1649
+ sage: g(1/t)
1650
+ Traceback (most recent call last):
1651
+ ...
1652
+ ValueError: not integral
1653
+ sage: g(K(4))
1654
+ 4
1655
+ sage: g(K(0))
1656
+ 0
1657
+ """
1658
+ self.p = _slots['p']
1659
+ Section._update_slots(self, _slots)
1660
+
1661
+ cpdef Element _call_(self, _x):
1662
+ """
1663
+ Applies the section.
1664
+
1665
+ EXAMPLES::
1666
+
1667
+ sage: R.<t> = GF(7)[]
1668
+ sage: K = R.fraction_field()
1669
+ sage: f = K.coerce_map_from(GF(7))
1670
+ sage: g = f.section(); g
1671
+ Section map:
1672
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7
1673
+ To: Finite Field of size 7
1674
+ sage: t = K.gen()
1675
+ sage: g(t^2) # indirect doctest
1676
+ Traceback (most recent call last):
1677
+ ...
1678
+ ValueError: not constant
1679
+ sage: g(1/t)
1680
+ Traceback (most recent call last):
1681
+ ...
1682
+ ValueError: not integral
1683
+ sage: g(K(4))
1684
+ 4
1685
+ sage: g(K(0))
1686
+ 0
1687
+ """
1688
+ cdef FpTElement x = <FpTElement?>_x
1689
+ cdef IntegerMod_int ans
1690
+ if nmod_poly_degree(x._denom) != 0 or nmod_poly_degree(x._numer) > 0:
1691
+ normalize(x._numer, x._denom, self.p)
1692
+ if nmod_poly_degree(x._denom) != 0:
1693
+ raise ValueError("not integral")
1694
+ if nmod_poly_degree(x._numer) > 0:
1695
+ raise ValueError("not constant")
1696
+ ans = IntegerMod_int.__new__(IntegerMod_int)
1697
+ ans._parent = self.codomain()
1698
+ ans._modulus = ans._parent._pyx_order
1699
+ if nmod_poly_get_coeff_ui(x._denom, 0) != 1:
1700
+ normalize(x._numer, x._denom, self.p)
1701
+ ans.ivalue = nmod_poly_get_coeff_ui(x._numer, 0)
1702
+ return ans
1703
+
1704
+ cdef class ZZ_FpT_coerce(RingHomomorphism):
1705
+ """
1706
+ This class represents the coercion map from ZZ to GF(p)(t).
1707
+
1708
+ EXAMPLES::
1709
+
1710
+ sage: R.<t> = GF(17)[]
1711
+ sage: K = R.fraction_field()
1712
+ sage: f = K.coerce_map_from(ZZ); f
1713
+ Ring morphism:
1714
+ From: Integer Ring
1715
+ To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17
1716
+ sage: type(f)
1717
+ <class 'sage.rings.fraction_field_FpT.ZZ_FpT_coerce'>
1718
+
1719
+ TESTS::
1720
+
1721
+ sage: TestSuite(f).run()
1722
+ """
1723
+ cdef long p
1724
+
1725
+ def __init__(self, R):
1726
+ """
1727
+ INPUT:
1728
+
1729
+ - ``R`` -- an FpT
1730
+
1731
+ EXAMPLES::
1732
+
1733
+ sage: # needs sage.rings.finite_rings
1734
+ sage: R.<t> = GF(next_prime(3000))[]
1735
+ sage: K = R.fraction_field() # indirect doctest
1736
+ """
1737
+ RingHomomorphism.__init__(self, ZZ.Hom(R))
1738
+ self.p = R.base_ring().characteristic()
1739
+
1740
+ cdef dict _extra_slots(self):
1741
+ """
1742
+ Helper for copying and pickling.
1743
+
1744
+ EXAMPLES::
1745
+
1746
+ sage: R.<t> = GF(5)[]
1747
+ sage: K = R.fraction_field()
1748
+ sage: f = K.coerce_map_from(ZZ)
1749
+ sage: g = copy(f) # indirect doctest
1750
+ sage: g == f
1751
+ True
1752
+ sage: g(5) == f(5)
1753
+ True
1754
+ sage: g(0) == f(0)
1755
+ True
1756
+ """
1757
+ slots = RingHomomorphism._extra_slots(self)
1758
+ slots['p'] = self.p
1759
+ return slots
1760
+
1761
+ cdef _update_slots(self, dict _slots):
1762
+ """
1763
+ Helper for copying and pickling.
1764
+
1765
+ EXAMPLES::
1766
+
1767
+ sage: R.<t> = GF(5)[]
1768
+ sage: K = R.fraction_field()
1769
+ sage: f = K.coerce_map_from(ZZ)
1770
+ sage: g = copy(f) # indirect doctest
1771
+ sage: g == f
1772
+ True
1773
+ sage: g(5) == f(5)
1774
+ True
1775
+ sage: g(0) == f(0)
1776
+ True
1777
+ """
1778
+ self.p = _slots['p']
1779
+ RingHomomorphism._update_slots(self, _slots)
1780
+
1781
+ cpdef Element _call_(self, _x):
1782
+ """
1783
+ Applies the coercion.
1784
+
1785
+ EXAMPLES::
1786
+
1787
+ sage: R.<t> = GF(5)[]
1788
+ sage: K = R.fraction_field()
1789
+ sage: f = K.coerce_map_from(ZZ)
1790
+ sage: f(3) # indirect doctest
1791
+ 3
1792
+ """
1793
+ cdef Integer x = <Integer?> _x
1794
+ cdef FpTElement ans = <FpTElement>FpTElement.__new__(FpTElement)
1795
+ ans._parent = self.codomain()
1796
+ ans.p = self.p
1797
+ nmod_poly_init(ans._numer, ans.p)
1798
+ nmod_poly_init(ans._denom, ans.p)
1799
+ nmod_poly_set_coeff_ui(ans._numer, 0, mpz_fdiv_ui(x.value, self.p))
1800
+ nmod_poly_set_coeff_ui(ans._denom, 0, 1)
1801
+ ans.initialized = True
1802
+ return ans
1803
+
1804
+ cpdef Element _call_with_args(self, _x, args=(), kwds={}):
1805
+ """
1806
+ This function allows the map to take multiple arguments, usually used to specify both numerator and denominator.
1807
+
1808
+ If ``reduce`` is specified as False, then the result won't be normalized.
1809
+
1810
+ EXAMPLES::
1811
+
1812
+ sage: R.<t> = GF(5)[]
1813
+ sage: K = R.fraction_field()
1814
+ sage: f = K.coerce_map_from(ZZ)
1815
+ sage: f(1, t + 3) # indirect doctest
1816
+ 1/(t + 3)
1817
+ sage: f(1,2)
1818
+ 3
1819
+ sage: f(2, 2*t)
1820
+ 1/t
1821
+ sage: f(2, 2*t, reduce=False)
1822
+ 2/2*t
1823
+ """
1824
+ cdef Integer x = <Integer?> _x
1825
+ cdef FpTElement ans = <FpTElement>FpTElement.__new__(FpTElement)
1826
+ ans._parent = self.codomain()
1827
+ ans.p = self.p
1828
+ nmod_poly_init(ans._numer, ans.p)
1829
+ nmod_poly_init(ans._denom, ans.p)
1830
+ cdef long r
1831
+ nmod_poly_set_coeff_ui(ans._numer, 0, mpz_fdiv_ui(x.value, self.p))
1832
+ if len(args) == 0:
1833
+ nmod_poly_set_coeff_ui(ans._denom, 0, 1)
1834
+ if len(args) == 1:
1835
+ y = args[0]
1836
+ if isinstance(y, Integer):
1837
+ r = mpz_fdiv_ui((<Integer>y).value, self.p)
1838
+ if r == 0:
1839
+ raise ZeroDivisionError
1840
+ nmod_poly_set_coeff_ui(ans._denom, 0, r)
1841
+ else:
1842
+ R = ans._parent.ring_of_integers()
1843
+ # could use the coerce keyword being set to False to not check this...
1844
+ if not (isinstance(y, Element) and y.parent() is R):
1845
+ # We could special case integers and GF(p) elements here.
1846
+ y = R(y)
1847
+ nmod_poly_set(ans._denom, &((<Polynomial_zmod_flint?>y).x))
1848
+ else:
1849
+ raise ValueError("FpT only supports two positional arguments")
1850
+ if 'reduce' not in kwds or kwds['reduce']:
1851
+ normalize(ans._numer, ans._denom, ans.p)
1852
+ ans.initialized = True
1853
+ return ans
1854
+
1855
+ def section(self):
1856
+ """
1857
+ Return the section of this inclusion: the partially defined map from ``GF(p)(t)``
1858
+ back to ``ZZ``, defined on constant elements.
1859
+
1860
+ EXAMPLES::
1861
+
1862
+ sage: R.<t> = GF(5)[]
1863
+ sage: K = R.fraction_field()
1864
+ sage: f = K.coerce_map_from(ZZ)
1865
+ sage: g = f.section(); g
1866
+ Composite map:
1867
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1868
+ To: Integer Ring
1869
+ Defn: Section map:
1870
+ From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5
1871
+ To: Finite Field of size 5
1872
+ then
1873
+ Lifting map:
1874
+ From: Finite Field of size 5
1875
+ To: Integer Ring
1876
+ sage: t = K.gen()
1877
+ sage: g(f(1,3,reduce=False))
1878
+ 2
1879
+ sage: g(t)
1880
+ Traceback (most recent call last):
1881
+ ...
1882
+ ValueError: not constant
1883
+ sage: g(1/t)
1884
+ Traceback (most recent call last):
1885
+ ...
1886
+ ValueError: not integral
1887
+ """
1888
+ return ZZ.convert_map_from(self.codomain().base_ring()) * Fp_FpT_coerce(self.codomain()).section()
1889
+
1890
+ cdef inline bint normalize(nmod_poly_t numer, nmod_poly_t denom, long p) noexcept:
1891
+ """
1892
+ Put ``numer`` / ``denom`` into a normal form: denominator monic and sharing no common factor with the numerator.
1893
+
1894
+ The normalized form of 0 is 0/1.
1895
+
1896
+ Return ``True`` if ``numer`` and ``denom`` were changed.
1897
+ """
1898
+ cdef long a
1899
+ cdef bint changed
1900
+ if nmod_poly_degree(numer) == -1:
1901
+ if nmod_poly_degree(denom) > 0 or nmod_poly_leading(denom) != 1:
1902
+ changed = True
1903
+ else:
1904
+ changed = False
1905
+ nmod_poly_truncate(denom, 0)
1906
+ nmod_poly_set_coeff_ui(denom, 0, 1)
1907
+ return changed
1908
+ elif nmod_poly_degree(numer) == 0 or nmod_poly_degree(denom) == 0:
1909
+ if nmod_poly_leading(denom) != 1:
1910
+ a = mod_inverse_int(nmod_poly_leading(denom), p)
1911
+ nmod_poly_scalar_mul_nmod(numer, numer, a)
1912
+ nmod_poly_scalar_mul_nmod(denom, denom, a)
1913
+ return True
1914
+ return False
1915
+ cdef nmod_poly_t g
1916
+ changed = False
1917
+ try:
1918
+ nmod_poly_init_preinv(g, p, numer.mod.ninv)
1919
+ nmod_poly_gcd(g, numer, denom)
1920
+ if nmod_poly_degree(g) != 0:
1921
+ # Divide knowing divisible by? Can we get these quotients as a byproduct of the gcd?
1922
+ nmod_poly_div(numer, numer, g)
1923
+ nmod_poly_div(denom, denom, g)
1924
+ changed = True
1925
+ if nmod_poly_leading(denom) != 1:
1926
+ a = mod_inverse_int(nmod_poly_leading(denom), p)
1927
+ nmod_poly_scalar_mul_nmod(numer, numer, a)
1928
+ nmod_poly_scalar_mul_nmod(denom, denom, a)
1929
+ changed = True
1930
+ return changed
1931
+ finally:
1932
+ nmod_poly_clear(g)
1933
+
1934
+
1935
+ cdef inline unsigned long nmod_poly_leading(nmod_poly_t poly) noexcept:
1936
+ """
1937
+ Return the leading coefficient of ``poly``.
1938
+ """
1939
+ return nmod_poly_get_coeff_ui(poly, nmod_poly_degree(poly))
1940
+
1941
+
1942
+ cdef inline void nmod_poly_inc(nmod_poly_t poly, bint monic) noexcept:
1943
+ """
1944
+ Set poly to the "next" polynomial: this is just counting in base p.
1945
+
1946
+ If monic is ``True`` then will only iterate through monic polynomials.
1947
+ """
1948
+ cdef long n
1949
+ cdef long a
1950
+ cdef long p = poly.mod.n
1951
+ for n from 0 <= n <= nmod_poly_degree(poly) + 1:
1952
+ a = nmod_poly_get_coeff_ui(poly, n) + 1
1953
+ if a == p:
1954
+ nmod_poly_set_coeff_ui(poly, n, 0)
1955
+ else:
1956
+ nmod_poly_set_coeff_ui(poly, n, a)
1957
+ break
1958
+ if monic and a == 2 and n == nmod_poly_degree(poly):
1959
+ nmod_poly_set_coeff_ui(poly, n, 0)
1960
+ nmod_poly_set_coeff_ui(poly, n + 1, 1)
1961
+
1962
+
1963
+ cdef inline long nmod_poly_cmp(nmod_poly_t a, nmod_poly_t b) noexcept:
1964
+ """
1965
+ Compare `a` and `b`, returning 0 if they are equal.
1966
+
1967
+ - If the degree of `a` is less than that of `b`, returns `-1`.
1968
+
1969
+ - If the degree of `b` is less than that of `a`, returns `1`.
1970
+
1971
+ - Otherwise, compares `a` and `b` lexicographically, starting at the leading terms.
1972
+ """
1973
+ cdef long ad = nmod_poly_degree(a)
1974
+ cdef long bd = nmod_poly_degree(b)
1975
+ if ad < bd:
1976
+ return -1
1977
+ elif ad > bd:
1978
+ return 1
1979
+ cdef long d = nmod_poly_degree(a)
1980
+ while d >= 0:
1981
+ ad = nmod_poly_get_coeff_ui(a, d)
1982
+ bd = nmod_poly_get_coeff_ui(b, d)
1983
+ if ad < bd:
1984
+ return -1
1985
+ elif ad > bd:
1986
+ return 1
1987
+ d -= 1
1988
+ return 0
1989
+
1990
+
1991
+ cdef bint nmod_poly_sqrt_check(nmod_poly_t poly) noexcept:
1992
+ """
1993
+ Quick check to see if ``poly`` could possibly be a square.
1994
+ """
1995
+ # We could use Sage's jacobi_int which is for 32 bits integers rather
1996
+ # than FLINT's n_jacobi which is for longs as the FpT class is crafted
1997
+ # for primes 2 < p < 2^16
1998
+ return (nmod_poly_degree(poly) % 2 == 0
1999
+ and n_jacobi(nmod_poly_leading(poly), poly.mod.n) == 1
2000
+ and n_jacobi(nmod_poly_get_coeff_ui(poly, 0), poly.mod.n) != -1)
2001
+
2002
+
2003
+ def unpickle_FpT_element(K, numer, denom):
2004
+ """
2005
+ Used for pickling.
2006
+
2007
+ TESTS::
2008
+
2009
+ sage: from sage.rings.fraction_field_FpT import unpickle_FpT_element
2010
+ sage: R.<t> = GF(13)['t']
2011
+ sage: unpickle_FpT_element(Frac(R), t+1, t)
2012
+ (t + 1)/t
2013
+ """
2014
+ return FpTElement(K, numer, denom, coerce=False, reduce=False)
2015
+
2016
+
2017
+ # Somehow this isn't in FLINT, evidently. It could be moved
2018
+ # elsewhere at some point.
2019
+ cdef int sage_cmp_nmod_poly_t(nmod_poly_t L, nmod_poly_t R) noexcept:
2020
+ """
2021
+ Compare two ``nmod_poly_t`` in a Pythonic way, so this returns `-1`, `0`,
2022
+ or `1`, and is consistent.
2023
+ """
2024
+ cdef int j
2025
+ cdef Py_ssize_t i
2026
+
2027
+ # First compare the degrees
2028
+ j = nmod_poly_degree(L) - nmod_poly_degree(R)
2029
+ if j < 0:
2030
+ return -1
2031
+ elif j > 0:
2032
+ return 1
2033
+
2034
+ # Same degree, so compare coefficients, term by term
2035
+ for i in range(nmod_poly_degree(L) + 1):
2036
+ j = nmod_poly_get_coeff_ui(L, i) - nmod_poly_get_coeff_ui(R, i)
2037
+ if j < 0:
2038
+ return -1
2039
+ elif j > 0:
2040
+ return 1
2041
+
2042
+ # Two polynomials are equal
2043
+ return 0