passagemath-pari 10.6.32__cp314-cp314-musllinux_1_2_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.

Potentially problematic release.


This version of passagemath-pari might be problematic. Click here for more details.

Files changed (331) hide show
  1. PARIKernel/__init__.py +2 -0
  2. PARIKernel/__main__.py +5 -0
  3. PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
  4. PARIKernel/io.pxd +7 -0
  5. PARIKernel/io.pyx +84 -0
  6. PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
  7. PARIKernel/kernel.pyx +260 -0
  8. PARIKernel/paridecl.pxd +95 -0
  9. PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
  10. PARIKernel/svg.pyx +52 -0
  11. cypari2/__init__.py +8 -0
  12. cypari2/auto_paridecl.pxd +1070 -0
  13. cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
  14. cypari2/closure.pxd +5 -0
  15. cypari2/closure.pyx +246 -0
  16. cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
  17. cypari2/convert.pxd +80 -0
  18. cypari2/convert.pyx +613 -0
  19. cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
  20. cypari2/custom_block.pyx +30 -0
  21. cypari2/cypari.h +13 -0
  22. cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
  23. cypari2/gen.pxd +69 -0
  24. cypari2/gen.pyx +4819 -0
  25. cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
  26. cypari2/handle_error.pxd +7 -0
  27. cypari2/handle_error.pyx +232 -0
  28. cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
  29. cypari2/pari_instance.pxd +27 -0
  30. cypari2/pari_instance.pyx +1438 -0
  31. cypari2/paridecl.pxd +5353 -0
  32. cypari2/paripriv.pxd +34 -0
  33. cypari2/pycore_long.h +98 -0
  34. cypari2/pycore_long.pxd +9 -0
  35. cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
  36. cypari2/stack.pxd +27 -0
  37. cypari2/stack.pyx +278 -0
  38. cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
  39. cypari2/string_utils.pxd +29 -0
  40. cypari2/string_utils.pyx +65 -0
  41. cypari2/types.pxd +147 -0
  42. passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
  43. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
  44. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
  45. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
  46. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
  47. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
  48. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
  49. passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
  50. passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
  51. passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
  52. passagemath_pari-10.6.32.dist-info/METADATA +209 -0
  53. passagemath_pari-10.6.32.dist-info/RECORD +331 -0
  54. passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
  55. passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
  56. passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
  57. passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
  58. passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
  59. passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
  60. passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
  61. passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
  62. passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  63. passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
  64. passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
  65. passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
  66. passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
  67. passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
  68. passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
  69. passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
  70. passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
  71. passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
  72. passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
  73. passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
  74. passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
  75. passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
  76. passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
  77. sage/all__sagemath_pari.py +26 -0
  78. sage/databases/all__sagemath_pari.py +7 -0
  79. sage/databases/conway.py +274 -0
  80. sage/ext/all__sagemath_pari.py +1 -0
  81. sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
  82. sage/ext/memory.pyx +98 -0
  83. sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
  84. sage/ext_data/pari/buzzard/Tpprog.g +179 -0
  85. sage/ext_data/pari/buzzard/genusn.g +129 -0
  86. sage/ext_data/pari/dokchitser/computel.gp +740 -0
  87. sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
  88. sage/ext_data/pari/dokchitser/ex-bsw +43 -0
  89. sage/ext_data/pari/dokchitser/ex-chgen +48 -0
  90. sage/ext_data/pari/dokchitser/ex-chqua +37 -0
  91. sage/ext_data/pari/dokchitser/ex-delta +35 -0
  92. sage/ext_data/pari/dokchitser/ex-eisen +30 -0
  93. sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
  94. sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
  95. sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
  96. sage/ext_data/pari/dokchitser/ex-nf +48 -0
  97. sage/ext_data/pari/dokchitser/ex-shin +50 -0
  98. sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
  99. sage/ext_data/pari/dokchitser/ex-zeta +27 -0
  100. sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
  101. sage/ext_data/pari/dokchitser/testall +13 -0
  102. sage/ext_data/pari/simon/ell.gp +2129 -0
  103. sage/ext_data/pari/simon/ellQ.gp +2151 -0
  104. sage/ext_data/pari/simon/ellcommon.gp +126 -0
  105. sage/ext_data/pari/simon/qfsolve.gp +722 -0
  106. sage/ext_data/pari/simon/resultant3.gp +306 -0
  107. sage/groups/all__sagemath_pari.py +3 -0
  108. sage/groups/pari_group.py +175 -0
  109. sage/interfaces/all__sagemath_pari.py +1 -0
  110. sage/interfaces/genus2reduction.py +464 -0
  111. sage/interfaces/gp.py +1114 -0
  112. sage/libs/all__sagemath_pari.py +2 -0
  113. sage/libs/linkages/__init__.py +1 -0
  114. sage/libs/linkages/padics/API.pxi +617 -0
  115. sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
  116. sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
  117. sage/libs/linkages/padics/__init__.py +1 -0
  118. sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
  119. sage/libs/linkages/padics/mpz.pxi +691 -0
  120. sage/libs/linkages/padics/relaxed/API.pxi +518 -0
  121. sage/libs/linkages/padics/relaxed/__init__.py +1 -0
  122. sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
  123. sage/libs/linkages/padics/unram_shared.pxi +247 -0
  124. sage/libs/pari/__init__.py +210 -0
  125. sage/libs/pari/all.py +5 -0
  126. sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
  127. sage/libs/pari/convert_flint.pxd +14 -0
  128. sage/libs/pari/convert_flint.pyx +159 -0
  129. sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
  130. sage/libs/pari/convert_gmp.pxd +14 -0
  131. sage/libs/pari/convert_gmp.pyx +210 -0
  132. sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
  133. sage/libs/pari/convert_sage.pxd +16 -0
  134. sage/libs/pari/convert_sage.pyx +588 -0
  135. sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
  136. sage/libs/pari/convert_sage_complex_double.pxd +14 -0
  137. sage/libs/pari/convert_sage_complex_double.pyx +132 -0
  138. sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/libs/pari/convert_sage_matrix.pyx +106 -0
  140. sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
  141. sage/libs/pari/convert_sage_real_double.pxd +5 -0
  142. sage/libs/pari/convert_sage_real_double.pyx +14 -0
  143. sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
  144. sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
  145. sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
  146. sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
  147. sage/libs/pari/misc.pxd +4 -0
  148. sage/libs/pari/misc.pyx +26 -0
  149. sage/libs/pari/tests.py +1848 -0
  150. sage/matrix/all__sagemath_pari.py +1 -0
  151. sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
  152. sage/matrix/matrix_integer_pari.pyx +187 -0
  153. sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
  154. sage/matrix/matrix_rational_pari.pyx +160 -0
  155. sage/quadratic_forms/all__sagemath_pari.py +10 -0
  156. sage/quadratic_forms/genera/all.py +9 -0
  157. sage/quadratic_forms/genera/genus.py +3506 -0
  158. sage/quadratic_forms/genera/normal_form.py +1519 -0
  159. sage/quadratic_forms/genera/spinor_genus.py +243 -0
  160. sage/quadratic_forms/qfsolve.py +255 -0
  161. sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
  162. sage/quadratic_forms/quadratic_form__genus.py +141 -0
  163. sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
  164. sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
  165. sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
  166. sage/quadratic_forms/quadratic_form__mass.py +69 -0
  167. sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
  168. sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
  169. sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
  170. sage/quadratic_forms/special_values.py +323 -0
  171. sage/rings/all__sagemath_pari.py +15 -0
  172. sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
  173. sage/rings/factorint_pari.pyx +80 -0
  174. sage/rings/finite_rings/all__sagemath_pari.py +1 -0
  175. sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  176. sage/rings/finite_rings/element_givaro.pxd +91 -0
  177. sage/rings/finite_rings/element_givaro.pyx +1769 -0
  178. sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
  179. sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
  180. sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
  181. sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
  182. sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
  183. sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
  184. sage/rings/finite_rings/finite_field_givaro.py +612 -0
  185. sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
  186. sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  187. sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
  188. sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
  189. sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
  190. sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
  191. sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
  192. sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
  193. sage/rings/function_field/all__sagemath_pari.py +1 -0
  194. sage/rings/function_field/valuation.py +1450 -0
  195. sage/rings/function_field/valuation_ring.py +212 -0
  196. sage/rings/number_field/all__sagemath_pari.py +14 -0
  197. sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
  198. sage/rings/number_field/totallyreal.pyx +509 -0
  199. sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
  200. sage/rings/number_field/totallyreal_data.pxd +26 -0
  201. sage/rings/number_field/totallyreal_data.pyx +928 -0
  202. sage/rings/number_field/totallyreal_phc.py +144 -0
  203. sage/rings/number_field/totallyreal_rel.py +1018 -0
  204. sage/rings/padics/CA_template.pxi +1847 -0
  205. sage/rings/padics/CA_template_header.pxi +50 -0
  206. sage/rings/padics/CR_template.pxi +2563 -0
  207. sage/rings/padics/CR_template_header.pxi +57 -0
  208. sage/rings/padics/FM_template.pxi +1575 -0
  209. sage/rings/padics/FM_template_header.pxi +50 -0
  210. sage/rings/padics/FP_template.pxi +2176 -0
  211. sage/rings/padics/FP_template_header.pxi +57 -0
  212. sage/rings/padics/all.py +3 -0
  213. sage/rings/padics/all__sagemath_pari.py +11 -0
  214. sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
  215. sage/rings/padics/common_conversion.pxd +15 -0
  216. sage/rings/padics/common_conversion.pyx +508 -0
  217. sage/rings/padics/eisenstein_extension_generic.py +232 -0
  218. sage/rings/padics/factory.py +3623 -0
  219. sage/rings/padics/generic_nodes.py +1615 -0
  220. sage/rings/padics/lattice_precision.py +2889 -0
  221. sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
  222. sage/rings/padics/morphism.pxd +11 -0
  223. sage/rings/padics/morphism.pyx +366 -0
  224. sage/rings/padics/padic_base_generic.py +467 -0
  225. sage/rings/padics/padic_base_leaves.py +1235 -0
  226. sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
  227. sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
  228. sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
  229. sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
  230. sage/rings/padics/padic_capped_relative_element.pxd +14 -0
  231. sage/rings/padics/padic_capped_relative_element.pyx +614 -0
  232. sage/rings/padics/padic_extension_generic.py +990 -0
  233. sage/rings/padics/padic_extension_leaves.py +738 -0
  234. sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
  235. sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
  236. sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
  237. sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
  238. sage/rings/padics/padic_floating_point_element.pxd +14 -0
  239. sage/rings/padics/padic_floating_point_element.pyx +447 -0
  240. sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
  241. sage/rings/padics/padic_generic_element.pxd +48 -0
  242. sage/rings/padics/padic_generic_element.pyx +4642 -0
  243. sage/rings/padics/padic_lattice_element.py +1342 -0
  244. sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
  245. sage/rings/padics/padic_printing.pxd +38 -0
  246. sage/rings/padics/padic_printing.pyx +1505 -0
  247. sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
  248. sage/rings/padics/padic_relaxed_element.pxd +56 -0
  249. sage/rings/padics/padic_relaxed_element.pyx +18 -0
  250. sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
  251. sage/rings/padics/padic_relaxed_errors.pxd +11 -0
  252. sage/rings/padics/padic_relaxed_errors.pyx +71 -0
  253. sage/rings/padics/padic_template_element.pxi +1212 -0
  254. sage/rings/padics/padic_template_element_header.pxi +50 -0
  255. sage/rings/padics/padic_valuation.py +1423 -0
  256. sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
  257. sage/rings/padics/pow_computer_flint.pxd +38 -0
  258. sage/rings/padics/pow_computer_flint.pyx +641 -0
  259. sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
  260. sage/rings/padics/pow_computer_relative.pxd +29 -0
  261. sage/rings/padics/pow_computer_relative.pyx +415 -0
  262. sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
  263. sage/rings/padics/qadic_flint_CA.pxd +21 -0
  264. sage/rings/padics/qadic_flint_CA.pyx +130 -0
  265. sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
  266. sage/rings/padics/qadic_flint_CR.pxd +13 -0
  267. sage/rings/padics/qadic_flint_CR.pyx +172 -0
  268. sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
  269. sage/rings/padics/qadic_flint_FM.pxd +14 -0
  270. sage/rings/padics/qadic_flint_FM.pyx +111 -0
  271. sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
  272. sage/rings/padics/qadic_flint_FP.pxd +12 -0
  273. sage/rings/padics/qadic_flint_FP.pyx +165 -0
  274. sage/rings/padics/relative_extension_leaves.py +429 -0
  275. sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
  276. sage/rings/padics/relative_ramified_CA.pxd +9 -0
  277. sage/rings/padics/relative_ramified_CA.pyx +33 -0
  278. sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
  279. sage/rings/padics/relative_ramified_CR.pxd +8 -0
  280. sage/rings/padics/relative_ramified_CR.pyx +33 -0
  281. sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
  282. sage/rings/padics/relative_ramified_FM.pxd +9 -0
  283. sage/rings/padics/relative_ramified_FM.pyx +33 -0
  284. sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
  285. sage/rings/padics/relative_ramified_FP.pxd +8 -0
  286. sage/rings/padics/relative_ramified_FP.pyx +33 -0
  287. sage/rings/padics/relaxed_template.pxi +4229 -0
  288. sage/rings/padics/relaxed_template_header.pxi +160 -0
  289. sage/rings/padics/tests.py +35 -0
  290. sage/rings/padics/tutorial.py +341 -0
  291. sage/rings/padics/unramified_extension_generic.py +335 -0
  292. sage/rings/padics/witt_vector.py +917 -0
  293. sage/rings/padics/witt_vector_ring.py +934 -0
  294. sage/rings/pari_ring.py +235 -0
  295. sage/rings/polynomial/all__sagemath_pari.py +1 -0
  296. sage/rings/polynomial/padics/all.py +1 -0
  297. sage/rings/polynomial/padics/polynomial_padic.py +360 -0
  298. sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
  299. sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
  300. sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
  301. sage/rings/power_series_pari.pxd +6 -0
  302. sage/rings/power_series_pari.pyx +934 -0
  303. sage/rings/tate_algebra.py +1282 -0
  304. sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
  305. sage/rings/tate_algebra_element.pxd +49 -0
  306. sage/rings/tate_algebra_element.pyx +3464 -0
  307. sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
  308. sage/rings/tate_algebra_ideal.pxd +7 -0
  309. sage/rings/tate_algebra_ideal.pyx +1307 -0
  310. sage/rings/valuation/all.py +7 -0
  311. sage/rings/valuation/augmented_valuation.py +2118 -0
  312. sage/rings/valuation/developing_valuation.py +362 -0
  313. sage/rings/valuation/gauss_valuation.py +812 -0
  314. sage/rings/valuation/inductive_valuation.py +1686 -0
  315. sage/rings/valuation/limit_valuation.py +946 -0
  316. sage/rings/valuation/mapped_valuation.py +656 -0
  317. sage/rings/valuation/scaled_valuation.py +322 -0
  318. sage/rings/valuation/trivial_valuation.py +382 -0
  319. sage/rings/valuation/valuation.py +1119 -0
  320. sage/rings/valuation/valuation_space.py +1615 -0
  321. sage/rings/valuation/valuations_catalog.py +10 -0
  322. sage/rings/valuation/value_group.py +697 -0
  323. sage/schemes/all__sagemath_pari.py +1 -0
  324. sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
  325. sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
  326. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
  327. sage_wheels/bin/gp +0 -0
  328. sage_wheels/bin/gp2c +0 -0
  329. sage_wheels/bin/gp2c-run +57 -0
  330. sage_wheels/bin/xeus-gp +0 -0
  331. sage_wheels/share/gp2c/func.dsc +18414 -0
@@ -0,0 +1,1686 @@
1
+ # sage_setup: distribution = sagemath-pari
2
+ r"""
3
+ Inductive valuations on polynomial rings
4
+
5
+ This module provides functionality for inductive valuations, i.e., finite
6
+ chains of :mod:`augmented valuations <sage.rings.valuation.augmented_valuation>` on top of a :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`.
7
+
8
+ AUTHORS:
9
+
10
+ - Julian Rüth (2016-11-01): initial version
11
+
12
+ EXAMPLES:
13
+
14
+ A :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>` is an example of an inductive valuation::
15
+
16
+ sage: R.<x> = QQ[]
17
+ sage: v = GaussValuation(R, QQ.valuation(2))
18
+
19
+ Generally, an inductive valuation is an augmentation of an inductive valuation,
20
+ i.e., a valuation that was created from a Gauss valuation in a finite number of
21
+ augmentation steps::
22
+
23
+ sage: w = v.augmentation(x, 1)
24
+ sage: w = w.augmentation(x^2 + 2*x + 4, 3)
25
+
26
+ REFERENCES:
27
+
28
+ Inductive valuations are originally discussed in [Mac1936I]_ and [Mac1936II]_.
29
+ An introduction is also given in Chapter 4 of [Rüt2014]_.
30
+ """
31
+ # ****************************************************************************
32
+ # Copyright (C) 2016-2018 Julian Rüth <julian.rueth@fsfe.org>
33
+ #
34
+ # Distributed under the terms of the GNU General Public License (GPL)
35
+ # as published by the Free Software Foundation; either version 2 of
36
+ # the License, or (at your option) any later version.
37
+ # https://www.gnu.org/licenses/
38
+ # ****************************************************************************
39
+
40
+ from .valuation import DiscreteValuation, InfiniteDiscretePseudoValuation
41
+ from .developing_valuation import DevelopingValuation
42
+
43
+ from sage.misc.cachefunc import cached_method
44
+ from sage.misc.abstract_method import abstract_method
45
+
46
+
47
+ class InductiveValuation(DevelopingValuation):
48
+ r"""
49
+ Abstract base class for iterated :mod:`augmented valuations <sage.rings.valuation.augmented_valuation>` on top of a :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`.
50
+
51
+ EXAMPLES::
52
+
53
+ sage: R.<x> = QQ[]
54
+ sage: v = GaussValuation(R, QQ.valuation(5))
55
+
56
+ TESTS::
57
+
58
+ sage: TestSuite(v).run() # long time # needs sage.geometry.polyhedron
59
+ """
60
+ def is_equivalence_unit(self, f, valuations=None):
61
+ r"""
62
+ Return whether the polynomial ``f`` is an equivalence unit, i.e., an
63
+ element of :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.effective_degree`
64
+ zero (see [Mac1936II]_ p.497.)
65
+
66
+ INPUT:
67
+
68
+ - ``f`` -- a polynomial in the domain of this valuation
69
+
70
+ EXAMPLES::
71
+
72
+ sage: # needs sage.libs.ntl
73
+ sage: R = Zp(2,5)
74
+ sage: S.<x> = R[]
75
+ sage: v = GaussValuation(S)
76
+ sage: v.is_equivalence_unit(x)
77
+ False
78
+ sage: v.is_equivalence_unit(S.zero())
79
+ False
80
+ sage: v.is_equivalence_unit(2*x + 1)
81
+ True
82
+ """
83
+ f = self.domain().coerce(f)
84
+
85
+ if f.is_zero():
86
+ return False
87
+ return self.effective_degree(f, valuations=valuations) == 0
88
+
89
+ def equivalence_reciprocal(self, f, coefficients=None, valuations=None, check=True):
90
+ r"""
91
+ Return an equivalence reciprocal of ``f``.
92
+
93
+ An equivalence reciprocal of `f` is a polynomial `h` such that `f\cdot
94
+ h` is equivalent to 1 modulo this valuation (see [Mac1936II]_ p.497.)
95
+
96
+ INPUT:
97
+
98
+ - ``f`` -- a polynomial in the domain of this valuation which is an
99
+ :meth:`equivalence_unit`
100
+
101
+ - ``coefficients`` -- the coefficients of ``f`` in the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic
102
+ expansion if known (default: ``None``)
103
+
104
+ - ``valuations`` -- the valuations of ``coefficients`` if known
105
+ (default: ``None``)
106
+
107
+ - ``check`` -- whether or not to check the validity of ``f`` (default:
108
+ ``True``)
109
+
110
+ .. WARNING::
111
+
112
+ This method may not work over `p`-adic rings due to problems with
113
+ the xgcd implementation there.
114
+
115
+ EXAMPLES::
116
+
117
+ sage: # needs sage.libs.ntl
118
+ sage: R = Zp(3,5)
119
+ sage: S.<x> = R[]
120
+ sage: v = GaussValuation(S)
121
+ sage: f = 3*x + 2
122
+ sage: h = v.equivalence_reciprocal(f); h
123
+ 2 + O(3^5)
124
+ sage: v.is_equivalent(f*h, 1)
125
+ True
126
+
127
+ In an extended valuation over an extension field::
128
+
129
+ sage: # needs sage.libs.ntl
130
+ sage: R.<u> = Qq(4,5)
131
+ sage: S.<x> = R[]
132
+ sage: v = GaussValuation(S)
133
+ sage: v = v.augmentation(x^2 + x + u, 1)
134
+ sage: f = 2*x + u
135
+ sage: h = v.equivalence_reciprocal(f); h
136
+ (u + 1) + O(2^5)
137
+ sage: v.is_equivalent(f*h, 1)
138
+ True
139
+
140
+ Extending the valuation once more::
141
+
142
+ sage: # needs sage.libs.ntl
143
+ sage: v = v.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
144
+ sage: h = v.equivalence_reciprocal(f); h
145
+ (u + 1) + O(2^5)
146
+ sage: v.is_equivalent(f*h, 1)
147
+ True
148
+
149
+ TESTS:
150
+
151
+ A case that caused problems at some point::
152
+
153
+ sage: # needs sage.libs.ntl
154
+ sage: K = Qp(2, 4)
155
+ sage: R.<x> = K[]
156
+ sage: L.<a> = K.extension(x^4 + 4*x^3 + 6*x^2 + 4*x + 2)
157
+ sage: R.<t> = L[]
158
+ sage: v = GaussValuation(R)
159
+ sage: w = v.augmentation(t + 1, 5/16)
160
+ sage: w = w.augmentation(t^4 + (a^8 + a^12 + a^14 + a^16 + a^17 + a^19 + a^20 + a^23)*t^3 + (a^6 + a^9 + a^13 + a^15 + a^18 + a^19 + a^21)*t^2 + a^10*t + 1 + a^4 + a^5 + a^8 + a^13 + a^14 + a^15, 17/8)
161
+ sage: f = a^-15*t^2 + (a^-11 + a^-9 + a^-6 + a^-5 + a^-3 + a^-2)*t + a^-15
162
+ sage: f_ = w.equivalence_reciprocal(f)
163
+ sage: w.reduce(f*f_)
164
+ 1
165
+ sage: f = f.parent()([f[0], f[1].add_bigoh(1), f[2]])
166
+ sage: f_ = w.equivalence_reciprocal(f)
167
+ sage: w.reduce(f*f_)
168
+ 1
169
+ """
170
+ f = self.domain().coerce(f)
171
+
172
+ if check:
173
+ if coefficients is None:
174
+ coefficients = list(self.coefficients(f))
175
+ if valuations is None:
176
+ valuations = list(self.valuations(f, coefficients=coefficients))
177
+ if not self.is_equivalence_unit(f, valuations=valuations):
178
+ raise ValueError("f must be an equivalence unit but %r is not" % (f,))
179
+
180
+ if coefficients is None:
181
+ e0 = next(self.coefficients(f))
182
+ else:
183
+ e0 = coefficients[0]
184
+
185
+ # f is an equivalence unit, its valuation is given by the constant coefficient
186
+ if valuations is None:
187
+ vf = self(e0)
188
+ else:
189
+ vf = valuations[0]
190
+
191
+ e0 = self.simplify(e0, error=vf)
192
+ s_ = self.equivalence_unit(-vf)
193
+ residue = self.reduce(e0 * s_)
194
+ if not isinstance(self, FinalInductiveValuation):
195
+ assert residue.is_constant()
196
+ residue = residue[0]
197
+ h = self.lift(~residue) * s_
198
+
199
+ h = self.simplify(h, -vf)
200
+
201
+ # it might be the case that f*h has nonzero valuation because h has
202
+ # insufficient precision, so we must not assert that here but only
203
+ # until we lifted to higher precision
204
+
205
+ # We do not actually need g*phi + h*e0 = 1, it is only important that
206
+ # the RHS is 1 in reduction.
207
+ # This allows us to do two things:
208
+ # - we may lift h to arbitrary precision
209
+ # - we can add anything which times e0 has positive valuation, e.g., we
210
+ # may drop coefficients of positive valuation
211
+ return h.map_coefficients(_lift_to_maximal_precision)
212
+
213
+ @cached_method
214
+ def mu(self):
215
+ r"""
216
+ Return the valuation of :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`.
217
+
218
+ EXAMPLES::
219
+
220
+ sage: R.<x> = QQ[]
221
+ sage: v = GaussValuation(R, QQ.valuation(2))
222
+ sage: v.mu()
223
+ 0
224
+ """
225
+ return self(self.phi())
226
+
227
+ @abstract_method
228
+ def equivalence_unit(self, s, reciprocal=False):
229
+ """
230
+ Return an equivalence unit of valuation ``s``.
231
+
232
+ INPUT:
233
+
234
+ - ``s`` -- an element of the :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.value_group`
235
+
236
+ - ``reciprocal`` -- boolean (default: ``False``); whether or not to
237
+ return the equivalence unit as the :meth:`equivalence_reciprocal` of
238
+ the equivalence unit of valuation ``-s``.
239
+
240
+ EXAMPLES::
241
+
242
+ sage: # needs sage.libs.ntl
243
+ sage: S.<x> = Qp(3,5)[]
244
+ sage: v = GaussValuation(S)
245
+ sage: v.equivalence_unit(2)
246
+ 3^2 + O(3^7)
247
+ sage: v.equivalence_unit(-2)
248
+ 3^-2 + O(3^3)
249
+
250
+ Note that this might fail for negative ``s`` if the domain is not
251
+ defined over a field::
252
+
253
+ sage: v = ZZ.valuation(2)
254
+ sage: R.<x> = ZZ[]
255
+ sage: w = GaussValuation(R, v)
256
+ sage: w.equivalence_unit(1)
257
+ 2
258
+ sage: w.equivalence_unit(-1)
259
+ Traceback (most recent call last):
260
+ ...
261
+ ValueError: s must be in the value semigroup of this valuation
262
+ but -1 is not in Additive Abelian Semigroup generated by 1
263
+ """
264
+
265
+ @abstract_method
266
+ def augmentation_chain(self):
267
+ r"""
268
+ Return a list with the chain of augmentations down to the underlying
269
+ :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>`.
270
+
271
+ EXAMPLES::
272
+
273
+ sage: # needs sage.libs.ntl
274
+ sage: R.<u> = Qq(4,5)
275
+ sage: S.<x> = R[]
276
+ sage: v = GaussValuation(S)
277
+ sage: v.augmentation_chain()
278
+ [Gauss valuation induced by 2-adic valuation]
279
+ """
280
+
281
+ @abstract_method
282
+ def is_gauss_valuation(self):
283
+ r"""
284
+ Return whether this valuation is a Gauss valuation over the domain.
285
+
286
+ EXAMPLES::
287
+
288
+ sage: # needs sage.libs.ntl
289
+ sage: R.<u> = Qq(4,5)
290
+ sage: S.<x> = R[]
291
+ sage: v = GaussValuation(S)
292
+ sage: v.is_gauss_valuation()
293
+ True
294
+ """
295
+
296
+ @abstract_method
297
+ def E(self):
298
+ """
299
+ Return the ramification index of this valuation over its underlying
300
+ Gauss valuation.
301
+
302
+ EXAMPLES::
303
+
304
+ sage: # needs sage.libs.ntl
305
+ sage: R.<u> = Qq(4,5)
306
+ sage: S.<x> = R[]
307
+ sage: v = GaussValuation(S)
308
+ sage: v.E()
309
+ 1
310
+ """
311
+
312
+ @abstract_method
313
+ def F(self):
314
+ """
315
+ Return the residual degree of this valuation over its Gauss extension.
316
+
317
+ EXAMPLES::
318
+
319
+ sage: # needs sage.libs.ntl
320
+ sage: R.<u> = Qq(4,5)
321
+ sage: S.<x> = R[]
322
+ sage: v = GaussValuation(S)
323
+ sage: v.F()
324
+ 1
325
+ """
326
+
327
+ @abstract_method
328
+ def monic_integral_model(self, G):
329
+ r"""
330
+ Return a monic integral irreducible polynomial which defines the same
331
+ extension of the base ring of the domain as the irreducible polynomial
332
+ ``G`` together with maps between the old and the new polynomial.
333
+
334
+ EXAMPLES::
335
+
336
+ sage: R.<x> = QQ[]
337
+ sage: v = GaussValuation(R, QQ.valuation(2))
338
+ sage: v.monic_integral_model(5*x^2 + 1/2*x + 1/4)
339
+ (Ring endomorphism of Univariate Polynomial Ring in x over Rational Field
340
+ Defn: x |--> 1/2*x,
341
+ Ring endomorphism of Univariate Polynomial Ring in x over Rational Field
342
+ Defn: x |--> 2*x,
343
+ x^2 + 1/5*x + 1/5)
344
+ """
345
+
346
+ @abstract_method
347
+ def element_with_valuation(self, s):
348
+ r"""
349
+ Return a polynomial of minimal degree with valuation ``s``.
350
+
351
+ EXAMPLES::
352
+
353
+ sage: R.<x> = QQ[]
354
+ sage: v = GaussValuation(R, QQ.valuation(2))
355
+ sage: v.element_with_valuation(-2)
356
+ 1/4
357
+
358
+ Depending on the base ring, an element of valuation ``s`` might not
359
+ exist::
360
+
361
+ sage: R.<x> = ZZ[]
362
+ sage: v = GaussValuation(R, ZZ.valuation(2))
363
+ sage: v.element_with_valuation(-2)
364
+ Traceback (most recent call last):
365
+ ...
366
+ ValueError: s must be in the value semigroup of this valuation
367
+ but -2 is not in Additive Abelian Semigroup generated by 1
368
+ """
369
+
370
+ def _test_element_with_valuation_inductive_valuation(self, **options):
371
+ r"""
372
+ Test the correctness of :meth:`element_with_valuation`.
373
+
374
+ EXAMPLES::
375
+
376
+ sage: R.<x> = QQ[]
377
+ sage: v = GaussValuation(R, QQ.valuation(2))
378
+ sage: v._test_element_with_valuation_inductive_valuation()
379
+ """
380
+ tester = self._tester(**options)
381
+ chain = self.augmentation_chain()
382
+ for s in tester.some_elements(self.value_group().some_elements()):
383
+ try:
384
+ R = self.element_with_valuation(s)
385
+ except (ValueError, NotImplementedError):
386
+ # this is often not possible unless the underlying ring of
387
+ # constants is a field
388
+ from sage.categories.fields import Fields
389
+ if self.domain().base() not in Fields():
390
+ continue
391
+ raise
392
+ tester.assertEqual(self(R), s)
393
+ if chain != [self]:
394
+ base = chain[1]
395
+ if s in base.value_group():
396
+ S = base.element_with_valuation(s)
397
+ tester.assertEqual(self(S), s)
398
+ tester.assertGreaterEqual(S.degree(), R.degree())
399
+
400
+ def _test_EF(self, **options):
401
+ r"""
402
+ Test the correctness of :meth:`E` and :meth:`F`.
403
+
404
+ EXAMPLES::
405
+
406
+ sage: # needs sage.libs.ntl
407
+ sage: R.<u> = Qq(4,5)
408
+ sage: S.<x> = R[]
409
+ sage: v = GaussValuation(S)
410
+ sage: v._test_EF()
411
+ """
412
+ tester = self._tester(**options)
413
+ chain = self.augmentation_chain()
414
+ for w, v in zip(chain, chain[1:]):
415
+ from sage.rings.infinity import infinity
416
+ from sage.rings.integer_ring import ZZ
417
+ if w(w.phi()) is infinity:
418
+ tester.assertEqual(w.E(), v.E())
419
+ tester.assertIn(w.E(), ZZ)
420
+ tester.assertIn(w.F(), ZZ)
421
+ tester.assertGreaterEqual(w.E(), v.E())
422
+ tester.assertGreaterEqual(w.F(), v.F())
423
+
424
+ def _test_augmentation_chain(self, **options):
425
+ r"""
426
+ Test the correctness of :meth:`augmentation_chain`.
427
+
428
+ EXAMPLES::
429
+
430
+ sage: R.<x> = QQ[]
431
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
432
+ sage: v._test_augmentation_chain()
433
+ """
434
+ tester = self._tester(**options)
435
+ chain = self.augmentation_chain()
436
+ tester.assertIs(chain[0], self)
437
+ tester.assertTrue(chain[-1].is_gauss_valuation())
438
+ for w, v in zip(chain, chain[1:]):
439
+ tester.assertGreaterEqual(w, v)
440
+
441
+ def _test_equivalence_unit(self, **options):
442
+ r"""
443
+ Test the correctness of :meth:`lift_to_key`.
444
+
445
+ EXAMPLES::
446
+
447
+ sage: R.<x> = QQ[]
448
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
449
+ sage: v._test_equivalence_unit()
450
+ """
451
+ tester = self._tester(**options)
452
+
453
+ if self.is_gauss_valuation():
454
+ value_group = self.value_group()
455
+ else:
456
+ value_group = self.augmentation_chain()[1].value_group()
457
+
458
+ for s in tester.some_elements(value_group.some_elements()):
459
+ try:
460
+ R = self.equivalence_unit(s)
461
+ except (ValueError, NotImplementedError):
462
+ # this is often not possible unless the underlying ring of
463
+ # constants is a field
464
+ from sage.categories.fields import Fields
465
+ if self.domain().base() not in Fields():
466
+ continue
467
+ raise
468
+ tester.assertIs(R.parent(), self.domain())
469
+ tester.assertEqual(self(R), s)
470
+ tester.assertTrue(self.is_equivalence_unit(R))
471
+
472
+ def _test_is_equivalence_unit(self, **options):
473
+ r"""
474
+ Test the correctness of :meth:`is_equivalence_unit`.
475
+
476
+ EXAMPLES::
477
+
478
+ sage: R.<x> = QQ[]
479
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
480
+ sage: v._test_is_equivalence_unit()
481
+ """
482
+ tester = self._tester(**options)
483
+ tester.assertFalse(self.is_equivalence_unit(self.phi()))
484
+
485
+ def _test_equivalence_reciprocal(self, **options):
486
+ r"""
487
+ Test the correctness of :meth:`equivalence_reciprocal`.
488
+
489
+ EXAMPLES::
490
+
491
+ sage: R.<x> = QQ[]
492
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
493
+ sage: v._test_equivalence_reciprocal()
494
+ """
495
+ tester = self._tester(**options)
496
+ S = tester.some_elements(self.domain().some_elements())
497
+ for f in S:
498
+ if self.is_equivalence_unit(f):
499
+ try:
500
+ g = self.equivalence_reciprocal(f)
501
+ except (ValueError, NotImplementedError):
502
+ # this is often not possible unless the underlying ring of
503
+ # constants is a field
504
+ from sage.categories.fields import Fields
505
+ if self.domain().base() not in Fields():
506
+ continue
507
+ raise
508
+ tester.assertEqual(self.reduce(f * g), 1)
509
+
510
+ def _test_inductive_valuation_inheritance(self, **options):
511
+ r"""
512
+ Test that every instance that is a :class:`InductiveValuation` is
513
+ either a :class:`FiniteInductiveValuation` or a
514
+ :class:`InfiniteInductiveValuation`. Same for
515
+ :class:`FinalInductiveValuation` and
516
+ :class:`NonFinalInductiveValuation`.
517
+
518
+ EXAMPLES::
519
+
520
+ sage: R.<x> = QQ[]
521
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
522
+ sage: v._test_inductive_valuation_inheritance()
523
+ """
524
+ tester = self._tester(**options)
525
+ tester.assertNotEqual(isinstance(self, InfiniteInductiveValuation),
526
+ isinstance(self, FiniteInductiveValuation))
527
+ tester.assertNotEqual(isinstance(self, FinalInductiveValuation),
528
+ isinstance(self, NonFinalInductiveValuation))
529
+
530
+
531
+ class FiniteInductiveValuation(InductiveValuation, DiscreteValuation):
532
+ r"""
533
+ Abstract base class for iterated :mod:`augmented valuations <sage.rings.valuation.augmented_valuation>`
534
+ on top of a :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>` which is a discrete valuation,
535
+ i.e., the last key polynomial has finite valuation.
536
+
537
+ EXAMPLES::
538
+
539
+ sage: R.<x> = QQ[]
540
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
541
+ """
542
+ def __init__(self, parent, phi):
543
+ r"""
544
+ TESTS::
545
+
546
+ sage: R.<x> = QQ[]
547
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
548
+ sage: from sage.rings.valuation.inductive_valuation import FiniteInductiveValuation
549
+ sage: isinstance(v, FiniteInductiveValuation)
550
+ True
551
+ """
552
+ InductiveValuation.__init__(self, parent, phi)
553
+ DiscreteValuation.__init__(self, parent)
554
+
555
+ def extensions(self, other):
556
+ r"""
557
+ Return the extensions of this valuation to ``other``.
558
+
559
+ EXAMPLES::
560
+
561
+ sage: R.<x> = ZZ[]
562
+ sage: v = GaussValuation(R, valuations.TrivialValuation(ZZ))
563
+ sage: K.<x> = FunctionField(QQ)
564
+ sage: v.extensions(K)
565
+ [Trivial valuation on Rational Field]
566
+ """
567
+ from sage.categories.function_fields import FunctionFields
568
+ if other in FunctionFields() and other.ngens() == 1:
569
+ # extend to K[x] and from there to K(x)
570
+ v = self.extension(self.domain().change_ring(self.domain().base().fraction_field()))
571
+ return [other.valuation(v)]
572
+ return super().extensions(other)
573
+
574
+
575
+ class NonFinalInductiveValuation(FiniteInductiveValuation, DiscreteValuation):
576
+ r"""
577
+ Abstract base class for iterated :mod:`augmented valuations <sage.rings.valuation.augmented_valuation>`
578
+ on top of a :mod:`Gauss valuation <sage.rings.valuation.gauss_valuation>` which can be extended further
579
+ through :meth:`augmentation`.
580
+
581
+ EXAMPLES::
582
+
583
+ sage: # needs sage.libs.ntl
584
+ sage: R.<u> = Qq(4,5)
585
+ sage: S.<x> = R[]
586
+ sage: v = GaussValuation(S)
587
+ sage: v = v.augmentation(x^2 + x + u, 1)
588
+ """
589
+ def __init__(self, parent, phi):
590
+ r"""
591
+ TESTS::
592
+
593
+ sage: # needs sage.libs.ntl
594
+ sage: R.<u> = Qq(4,5)
595
+ sage: S.<x> = R[]
596
+ sage: v = GaussValuation(S)
597
+ sage: v = v.augmentation(x^2 + x + u, 1)
598
+ sage: from sage.rings.valuation.inductive_valuation import NonFinalInductiveValuation
599
+ sage: isinstance(v, NonFinalInductiveValuation)
600
+ True
601
+ """
602
+ FiniteInductiveValuation.__init__(self, parent, phi)
603
+ DiscreteValuation.__init__(self, parent)
604
+
605
+ def augmentation(self, phi, mu, check=True):
606
+ r"""
607
+ Return the inductive valuation which extends this valuation by mapping
608
+ ``phi`` to ``mu``.
609
+
610
+ INPUT:
611
+
612
+ - ``phi`` -- a polynomial in the domain of this valuation; this must be
613
+ a key polynomial, see :meth:`is_key` for properties of key
614
+ polynomials.
615
+
616
+ - ``mu`` -- a rational number or infinity, the valuation of ``phi`` in
617
+ the extended valuation
618
+
619
+ - ``check`` -- boolean (default: ``True``); whether or not to check
620
+ the correctness of the parameters
621
+
622
+ EXAMPLES::
623
+
624
+ sage: # needs sage.libs.ntl
625
+ sage: R.<u> = Qq(4,5)
626
+ sage: S.<x> = R[]
627
+ sage: v = GaussValuation(S)
628
+ sage: v = v.augmentation(x^2 + x + u, 1)
629
+ sage: v = v.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
630
+ sage: v
631
+ [ Gauss valuation induced by 2-adic valuation,
632
+ v((1 + O(2^5))*x^2 + (1 + O(2^5))*x + u + O(2^5)) = 1,
633
+ v((1 + O(2^5))*x^4
634
+ + (2^2 + O(2^6))*x^3
635
+ + (1 + (u + 1)*2 + O(2^5))*x^2
636
+ + ((u + 1)*2^2 + O(2^6))*x
637
+ + (u + 1) + (u + 1)*2 + (u + 1)*2^2 + (u + 1)*2^3 + (u + 1)*2^4 + O(2^5)) = 3 ]
638
+
639
+ TESTS:
640
+
641
+ Make sure that we do not make the assumption that the degrees of the
642
+ key polynomials are strictly increasing::
643
+
644
+ sage: v_K = QQ.valuation(3)
645
+ sage: A.<t> = QQ[]
646
+ sage: v0 = GaussValuation(A,v_K)
647
+
648
+ sage: v1 = v0.augmentation(t, 1/12)
649
+ sage: v2 = v1.augmentation(t^12 + 3, 7/6)
650
+ sage: v3 = v2.augmentation(t^12 + 3*t^2 + 3, 9/4)
651
+ sage: v4 = v1.augmentation(t^12 + 3*t^2 + 3, 9/4)
652
+ sage: v3 <= v4 and v3 >= v4
653
+ True
654
+
655
+ .. SEEALSO::
656
+
657
+ :mod:`~sage.rings.valuation.augmented_valuation`
658
+ """
659
+ from .augmented_valuation import AugmentedValuation
660
+ return AugmentedValuation(self, phi, mu, check)
661
+
662
+ def mac_lane_step(self, G, principal_part_bound=None, assume_squarefree=False, assume_equivalence_irreducible=False, report_degree_bounds_and_caches=False, coefficients=None, valuations=None, check=True, allow_equivalent_key=True):
663
+ r"""
664
+ Perform an approximation step towards the squarefree monic non-constant
665
+ integral polynomial ``G`` which is not an :meth:`equivalence unit <InductiveValuation.is_equivalence_unit>`.
666
+
667
+ This performs the individual steps that are used in
668
+ :meth:`~sage.rings.valuation.valuation.DiscreteValuation.mac_lane_approximants`.
669
+
670
+ INPUT:
671
+
672
+ - ``G`` -- a squarefree monic non-constant integral polynomial ``G``
673
+ which is not an :meth:`equivalence unit <InductiveValuation.is_equivalence_unit>`
674
+
675
+ - ``principal_part_bound`` -- integer or ``None`` (default:
676
+ ``None``), a bound on the length of the principal part, i.e., the
677
+ section of negative slope, of the Newton polygon of ``G``
678
+
679
+ - ``assume_squarefree`` -- whether or not to assume that ``G`` is
680
+ squarefree (default: ``False``)
681
+
682
+ - ``assume_equivalence_irreducible`` -- whether or not to assume that
683
+ ``G`` is equivalence irreducible (default: ``False``)
684
+
685
+ - ``report_degree_bounds_and_caches`` -- whether or not to include internal state with the returned value (used by :meth:`~sage.rings.valuation.valuation.DiscreteValuation.mac_lane_approximants` to speed up sequential calls)
686
+
687
+ - ``coefficients`` -- the coefficients of ``G`` in the :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic expansion if known (default: ``None``)
688
+
689
+ - ``valuations`` -- the valuations of ``coefficients`` if known
690
+ (default: ``None``)
691
+
692
+ - ``check`` -- whether to check that ``G`` is a squarefree monic
693
+ non-constant integral polynomial and not an :meth:`equivalence unit <InductiveValuation.is_equivalence_unit>`
694
+ (default: ``True``)
695
+
696
+ - ``allow_equivalent_key`` -- whether to return valuations which end in
697
+ essentially the same key polynomial as this valuation but have a
698
+ higher valuation assigned to that key polynomial (default: ``True``)
699
+
700
+ EXAMPLES:
701
+
702
+ We can use this method to perform the individual steps of
703
+ :meth:`~sage.rings.valuation.valuation.DiscreteValuation.mac_lane_approximants`::
704
+
705
+ sage: R.<x> = QQ[]
706
+ sage: v = QQ.valuation(2)
707
+ sage: f = x^36 + 1160/81*x^31 + 9920/27*x^30 + 1040/81*x^26 + 52480/81*x^25 + 220160/81*x^24 - 5120/81*x^21 - 143360/81*x^20 - 573440/81*x^19 + 12451840/81*x^18 - 266240/567*x^16 - 20316160/567*x^15 - 198737920/189*x^14 - 1129840640/81*x^13 - 1907359744/27*x^12 + 8192/81*x^11 + 655360/81*x^10 + 5242880/21*x^9 + 2118123520/567*x^8 + 15460204544/567*x^7 + 6509559808/81*x^6 - 16777216/567*x^2 - 268435456/567*x - 1073741824/567
708
+ sage: v.mac_lane_approximants(f) # needs sage.geometry.polyhedron
709
+ [[ Gauss valuation induced by 2-adic valuation, v(x + 2056) = 23/2 ],
710
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 11/9 ],
711
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 2/5, v(x^5 + 4) = 7/2 ],
712
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3/5, v(x^10 + 8*x^5 + 64) = 7 ],
713
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3/5, v(x^5 + 8) = 5 ]]
714
+
715
+ Starting from the Gauss valuation, a MacLane step branches off with
716
+ some linear key polynomials in the above example::
717
+
718
+ sage: v0 = GaussValuation(R, v)
719
+ sage: V1 = sorted(v0.mac_lane_step(f)); V1 # needs sage.geometry.polyhedron
720
+ [[ Gauss valuation induced by 2-adic valuation, v(x) = 2/5 ],
721
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3/5 ],
722
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 11/9 ],
723
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3 ]]
724
+
725
+ The computation of MacLane approximants would now perform a MacLane
726
+ step on each of these branches, note however, that a direct call to
727
+ this method might produce some unexpected results::
728
+
729
+ sage: V1[1].mac_lane_step(f) # needs sage.geometry.polyhedron
730
+ [[ Gauss valuation induced by 2-adic valuation, v(x) = 3/5, v(x^5 + 8) = 5 ],
731
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3/5, v(x^10 + 8*x^5 + 64) = 7 ],
732
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3 ],
733
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 11/9 ]]
734
+
735
+ Note how this detected the two augmentations of ``V1[1]`` but also two
736
+ other valuations that we had seen in the previous step and that are
737
+ greater than ``V1[1]``. To ignore such trivial augmentations, we can
738
+ set ``allow_equivalent_key``::
739
+
740
+ sage: V1[1].mac_lane_step(f, allow_equivalent_key=False) # needs sage.geometry.polyhedron
741
+ [[ Gauss valuation induced by 2-adic valuation, v(x) = 3/5, v(x^5 + 8) = 5 ],
742
+ [ Gauss valuation induced by 2-adic valuation, v(x) = 3/5, v(x^10 + 8*x^5 + 64) = 7 ]]
743
+
744
+ TESTS::
745
+
746
+ sage: K.<x> = FunctionField(QQ)
747
+ sage: S.<y> = K[]
748
+ sage: F = y^2 - x^2 - x^3 - 3
749
+ sage: v0 = GaussValuation(K._ring, QQ.valuation(3))
750
+ sage: v1 = v0.augmentation(K._ring.gen(), 1/3)
751
+ sage: mu0 = K.valuation(v1)
752
+ sage: eta0 = GaussValuation(S, mu0)
753
+ sage: eta1 = eta0.mac_lane_step(F)[0] # needs sage.geometry.polyhedron
754
+ sage: eta2 = eta1.mac_lane_step(F)[0] # needs sage.geometry.polyhedron
755
+ sage: eta2 # needs sage.geometry.polyhedron
756
+ [ Gauss valuation induced by Valuation on rational function field induced by [ Gauss valuation induced by 3-adic valuation, v(x) = 1/3 ], v(y + x) = 2/3 ]
757
+
758
+ Check that :issue:`26066` has been resolved::
759
+
760
+ sage: R.<x> = QQ[]
761
+ sage: v = QQ.valuation(2)
762
+ sage: v = GaussValuation(R, v).augmentation(x+1, 1/2)
763
+ sage: f = x^4 - 30*x^2 - 75
764
+ sage: v.mac_lane_step(f) # needs sage.geometry.polyhedron
765
+ [[ Gauss valuation induced by 2-adic valuation, v(x + 1) = 3/4 ]]
766
+ """
767
+ G = self.domain().coerce(G)
768
+
769
+ if G.is_constant():
770
+ raise ValueError("G must not be constant")
771
+
772
+ from itertools import islice
773
+ from sage.misc.verbose import verbose
774
+ verbose("Augmenting %s towards %s" % (self, G), level=10)
775
+
776
+ if not G.is_monic():
777
+ raise ValueError("G must be monic")
778
+
779
+ if coefficients is None:
780
+ coefficients = self.coefficients(G)
781
+ if principal_part_bound:
782
+ coefficients = islice(coefficients, 0,
783
+ int(principal_part_bound) + 1, 1)
784
+ coefficients = list(coefficients)
785
+ if valuations is None:
786
+ valuations = self.valuations(G, coefficients=coefficients)
787
+ if principal_part_bound:
788
+ valuations = islice(valuations, 0,
789
+ int(principal_part_bound) + 1, 1)
790
+ valuations = list(valuations)
791
+
792
+ if check and min(valuations) < 0:
793
+ raise ValueError("G must be integral")
794
+
795
+ if check and self.is_equivalence_unit(G, valuations=valuations):
796
+ raise ValueError("G must not be an equivalence-unit")
797
+
798
+ if check and not assume_squarefree and not G.is_squarefree():
799
+ raise ValueError("G must be squarefree")
800
+
801
+ from sage.rings.infinity import infinity
802
+ assert self(G) is not infinity # this is a valuation and G is nonzero
803
+
804
+ ret = []
805
+
806
+ F = self.equivalence_decomposition(G, assume_not_equivalence_unit=True, coefficients=coefficients, valuations=valuations, compute_unit=False, degree_bound=principal_part_bound)
807
+ assert len(F), "%s equivalence-decomposes as an equivalence-unit %s" % (G, F)
808
+ if len(F) == 1 and F[0][1] == 1 and F[0][0].degree() == G.degree():
809
+ assert self.is_key(G, assume_equivalence_irreducible=assume_equivalence_irreducible)
810
+ ret.append((self.augmentation(G, infinity, check=False), G.degree(), principal_part_bound, None, None))
811
+ else:
812
+ for phi, e in F:
813
+ if G == phi:
814
+ # Something strange happened here:
815
+ # G is not a key (we checked that before) but phi==G is; so phi must have less precision than G
816
+ # this can happen if not all coefficients of G have the same precision
817
+ # if we drop some precision of G then it will be a key (but is
818
+ # that really what we should do?)
819
+ assert not G.base_ring().is_exact()
820
+ prec = min([c.precision_absolute() for c in phi.list()])
821
+ g = G.map_coefficients(lambda c: c.add_bigoh(prec))
822
+ assert self.is_key(g)
823
+ ret.append((self.augmentation(g, infinity, check=False), g.degree(), principal_part_bound, None, None))
824
+ assert len(F) == 1
825
+ break
826
+
827
+ if not allow_equivalent_key and self.phi().degree() == phi.degree():
828
+ # We ignore augmentations that could have been detected in
829
+ # the previous MacLane step, see [Rüt2014, Theorem 4.33],
830
+ # i.e., we ignore key polynomials that are equivalent to
831
+ # the current key in the sense of that theorem.
832
+ if self.is_equivalent(self.phi(), phi):
833
+ continue
834
+
835
+ verbose("Determining the augmentation of %s for %s" % (self, phi), level=11)
836
+
837
+ base = self
838
+ if phi.degree() == base.phi().degree():
839
+ # very frequently, the degree of the key polynomials
840
+ # stagnate for a bit while the valuation of the key
841
+ # polynomial is slowly increased.
842
+ # In this case, we can drop previous key polynomials
843
+ # of the same degree. (They have no influence on the
844
+ # phi-adic expansion.)
845
+ if not base.is_gauss_valuation():
846
+ base = base._base_valuation
847
+ old_mu = self(phi)
848
+ w = base.augmentation(phi, old_mu, check=False)
849
+
850
+ # we made some experiments here: instead of computing the
851
+ # coefficients again from scratch, update the coefficients when
852
+ # phi - self.phi() is a constant.
853
+ # It turned out to be slightly slower than just recomputing the
854
+ # coefficients. The main issue with the approach was that we
855
+ # needed to keep track of all the coefficients and not just of
856
+ # the coefficients up to principal_part_bound.
857
+
858
+ w_coefficients = w.coefficients(G)
859
+ if principal_part_bound:
860
+ w_coefficients = islice(w_coefficients, 0,
861
+ int(principal_part_bound) + 1, 1)
862
+ w_coefficients = list(w_coefficients)
863
+
864
+ w_valuations = w.valuations(G, coefficients=w_coefficients)
865
+ if principal_part_bound:
866
+ w_valuations = islice(w_valuations, 0,
867
+ int(principal_part_bound) + 1, 1)
868
+ w_valuations = list(w_valuations)
869
+
870
+ from sage.geometry.newton_polygon import NewtonPolygon
871
+ NP = NewtonPolygon(w.newton_polygon(G, valuations=w_valuations).vertices(), last_slope=0)
872
+
873
+ verbose("Newton-Polygon for v(phi)=%s : %s" % (self(phi), NP), level=11)
874
+ slopes = NP.slopes(repetition=True)
875
+ multiplicities = {slope: len([s for s in slopes if s == slope]) for slope in slopes}
876
+ slopes = list(multiplicities)
877
+ if NP.vertices()[0][0] != 0:
878
+ slopes = [-infinity] + slopes
879
+ multiplicities[-infinity] = 1
880
+
881
+ for i, slope in enumerate(slopes):
882
+ verbose("Slope = %s" % slope, level=12)
883
+ new_mu = old_mu - slope
884
+ new_valuations = [val - (j * slope if slope is not -infinity else (0 if j == 0 else -infinity))
885
+ for j, val in enumerate(w_valuations)]
886
+ if phi.degree() == self.phi().degree():
887
+ assert new_mu > self(phi), "the valuation of the key polynomial must increase when the degree stagnates"
888
+ # phi has already been simplified internally by the
889
+ # equivalence_decomposition method but we can now possibly
890
+ # simplify it further as we know exactly up to which
891
+ # precision it needs to be defined.
892
+ phi = base.simplify(phi, new_mu, force=True)
893
+ w = base.augmentation(phi, new_mu, check=False)
894
+ verbose("Augmented %s to %s" % (self, w), level=13)
895
+ assert slope is -infinity or 0 in w.newton_polygon(G).slopes(repetition=False)
896
+
897
+ from sage.rings.integer_ring import ZZ
898
+ assert (phi.degree() / self.phi().degree()) in ZZ
899
+ degree_bound = multiplicities[slope] * phi.degree()
900
+ assert degree_bound <= G.degree()
901
+ assert degree_bound >= phi.degree()
902
+ ret.append((w, degree_bound, multiplicities[slope], w_coefficients, new_valuations))
903
+
904
+ if len(ret) == 0:
905
+ assert not allow_equivalent_key, "a MacLane step produced no augmentation"
906
+ assert 0 not in self.newton_polygon(G).slopes(), "a MacLane step produced no augmentation but the valuation given to the key polynomial was correct, i.e., it appears to come out of a call to mac_lane_approximants"
907
+
908
+ assert ret, "a MacLane step produced no augmentations"
909
+ if not report_degree_bounds_and_caches:
910
+ ret = [v for v, _, _, _, _ in ret]
911
+ return ret
912
+
913
+ def is_key(self, phi, explain=False, assume_equivalence_irreducible=False):
914
+ r"""
915
+ Return whether ``phi`` is a key polynomial for this valuation, i.e.,
916
+ whether it is monic, whether it :meth:`is_equivalence_irreducible`, and
917
+ whether it is :meth:`is_minimal`.
918
+
919
+ INPUT:
920
+
921
+ - ``phi`` -- a polynomial in the domain of this valuation
922
+
923
+ - ``explain`` -- boolean (default: ``False``); if ``True``, return a
924
+ string explaining why ``phi`` is not a key polynomial
925
+
926
+ EXAMPLES::
927
+
928
+ sage: # needs sage.libs.ntl
929
+ sage: R.<u> = Qq(4, 5)
930
+ sage: S.<x> = R[]
931
+ sage: v = GaussValuation(S)
932
+ sage: v.is_key(x)
933
+ True
934
+ sage: v.is_key(2*x, explain=True)
935
+ (False, 'phi must be monic')
936
+ sage: v.is_key(x^2, explain=True)
937
+ (False, 'phi must be equivalence irreducible')
938
+ sage: w = v.augmentation(x, 1)
939
+ sage: w.is_key(x + 1, explain = True)
940
+ (False, 'phi must be minimal')
941
+ """
942
+ phi = self.domain().coerce(phi)
943
+
944
+ reason = None
945
+
946
+ if not phi.is_monic():
947
+ reason = "phi must be monic"
948
+ elif not assume_equivalence_irreducible and not self.is_equivalence_irreducible(phi):
949
+ reason = "phi must be equivalence irreducible"
950
+ elif not self.is_minimal(phi, assume_equivalence_irreducible=True):
951
+ reason = "phi must be minimal"
952
+
953
+ if explain:
954
+ return reason is None, reason
955
+ else:
956
+ return reason is None
957
+
958
+ def is_minimal(self, f, assume_equivalence_irreducible=False):
959
+ r"""
960
+ Return whether the polynomial ``f`` is minimal with respect to this
961
+ valuation.
962
+
963
+ A polynomial `f` is minimal with respect to `v` if it is not a constant
964
+ and any nonzero polynomial `h` which is `v`-divisible by `f` has at
965
+ least the degree of `f`.
966
+
967
+ A polynomial `h` is `v`-divisible by `f` if there is a polynomial `c`
968
+ such that `fc` :meth:`~sage.rings.valuation.valuation.DiscretePseudoValuation.is_equivalent` to `h`.
969
+
970
+ ALGORITHM:
971
+
972
+ Based on Theorem 9.4 of [Mac1936II]_.
973
+
974
+ EXAMPLES::
975
+
976
+ sage: # needs sage.libs.ntl
977
+ sage: R.<u> = Qq(4, 5)
978
+ sage: S.<x> = R[]
979
+ sage: v = GaussValuation(S)
980
+ sage: v.is_minimal(x + 1)
981
+ True
982
+ sage: w = v.augmentation(x, 1)
983
+ sage: w.is_minimal(x + 1)
984
+ False
985
+
986
+ TESTS::
987
+
988
+ sage: # needs sage.libs.ntl
989
+ sage: K = Qp(2, 10)
990
+ sage: R.<x> = K[]
991
+ sage: vp = K.valuation()
992
+ sage: v0 = GaussValuation(R, vp)
993
+ sage: v1 = v0.augmentation(x, 1/4)
994
+ sage: v2 = v1.augmentation(x^4 + 2, 5/4)
995
+ sage: v2.is_minimal(x^5 + x^4 + 2)
996
+ False
997
+
998
+ Polynomials which are equivalent to the key polynomial are minimal if
999
+ and only if they have the same degree as the key polynomial::
1000
+
1001
+ sage: v2.is_minimal(x^4 + 2) # needs sage.libs.ntl
1002
+ True
1003
+ sage: v2.is_minimal(x^4 + 4) # needs sage.libs.ntl
1004
+ False
1005
+ """
1006
+ f = self.domain().coerce(f)
1007
+
1008
+ if f.is_constant():
1009
+ return False
1010
+
1011
+ if not assume_equivalence_irreducible and not self.is_equivalence_irreducible(f):
1012
+ # any factor divides f with respect to this valuation
1013
+ return False
1014
+
1015
+ if not f.is_monic():
1016
+ # divide out the leading factor, it does not change minimality
1017
+ v = self
1018
+ if not self.domain().base_ring().is_field():
1019
+ domain = self.domain().change_ring(self.domain().base_ring().fraction_field())
1020
+ v = self.extension(domain)
1021
+ f = domain(f)
1022
+ return v.is_minimal(f / f.leading_coefficient())
1023
+
1024
+ if self.is_gauss_valuation():
1025
+ if self(f) == 0:
1026
+ F = self.reduce(f, check=False)
1027
+ assert not F.is_constant()
1028
+ return F.is_irreducible()
1029
+ else:
1030
+ assert (self(f) <= 0) # f is monic
1031
+ # f is not minimal:
1032
+ # Let g be f stripped of its leading term, i.e., g = f - x^n.
1033
+ # Then g and f are equivalent with respect to this valuation
1034
+ # and in particular g divides f with respect to this valuation
1035
+ return False
1036
+
1037
+ if self.is_equivalent(self.phi(), f):
1038
+ assert f.degree() >= self.phi().degree()
1039
+ # If an h divides f with respect to this valuation, then it also divides phi:
1040
+ # v(f - c*h) > v(f) = v(c*h) => v(phi - c*h) = v((phi - f) + (f - c*h)) > v(phi) = v(c*h)
1041
+ # So if f were not minimal then phi would not be minimal but it is.
1042
+ return f.degree() == self.phi().degree()
1043
+
1044
+ else:
1045
+ tau = self.value_group().index(self._base_valuation.value_group())
1046
+ # see Theorem 9.4 of [Mac1936II]
1047
+ return list(self.valuations(f))[-1] == self(f) and \
1048
+ list(self.coefficients(f))[-1].is_constant() and \
1049
+ list(self.valuations(f))[0] == self(f) and \
1050
+ tau.divides(len(list(self.coefficients(f))) - 1)
1051
+
1052
+ def _equivalence_reduction(self, f, coefficients=None, valuations=None, degree_bound=None):
1053
+ r"""
1054
+ Helper method for :meth:`is_equivalence_irreducible` and
1055
+ :meth:`equivalence_decomposition` which essentially returns the
1056
+ reduction of ``f`` after multiplication with an ``R`` which
1057
+ :meth:`is_equivalence_unit`.
1058
+
1059
+ This only works when ``f`` is not divisible by :meth:`phi` with respect
1060
+ to this valuation. Therefore, we also return the number of times that
1061
+ we took out :meth:`phi` of ``f`` before we computed the reduction.
1062
+
1063
+ EXAMPLES::
1064
+
1065
+ sage: R.<x> = QQ[]
1066
+ sage: v = GaussValuation(R, QQ.valuation(2))
1067
+ sage: v._equivalence_reduction(2*x^6 + 4*x^5 + 2*x^4 + 8)
1068
+ (1, 4, x^2 + 1)
1069
+ """
1070
+ f = self.domain().coerce(f)
1071
+
1072
+ # base change from R[x] to K[x], so divisions work and sufficient
1073
+ # elements of negative valuation exist
1074
+ if not self.domain().base_ring().is_field():
1075
+ domain = self.domain().change_ring(self.domain().base_ring().fraction_field())
1076
+ v = self.extension(domain)
1077
+ assert self.residue_ring() is v.residue_ring()
1078
+ return v._equivalence_reduction(f)
1079
+
1080
+ if coefficients is None:
1081
+ coefficients = list(self.coefficients(f))
1082
+ if valuations is None:
1083
+ valuations = list(self.valuations(f, coefficients=coefficients))
1084
+ valuation = min(valuations)
1085
+ for phi_divides in range(len(valuations)):
1086
+ # count how many times phi divides f
1087
+ if valuations[phi_divides] <= valuation:
1088
+ break
1089
+
1090
+ if phi_divides:
1091
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1092
+ R = PolynomialRing(f.parent(), 'phi')
1093
+ f = R(coefficients[phi_divides:])(self.phi())
1094
+ valuations = [vv - self.mu() * phi_divides
1095
+ for vv in valuations[phi_divides:]]
1096
+ coefficients = coefficients[phi_divides:]
1097
+ valuation = min(valuations)
1098
+
1099
+ R = self.equivalence_unit(-valuation)
1100
+ R = next(self.coefficients(R))
1101
+ fR_valuations = [vv - valuation for vv in valuations]
1102
+ from sage.rings.infinity import infinity
1103
+ fR_coefficients = [next(self.coefficients(c * R))
1104
+ if vv is not infinity and vv == 0 else 0
1105
+ for c, vv in zip(coefficients, fR_valuations)]
1106
+
1107
+ return valuation, phi_divides, self.reduce(f * R, check=False, degree_bound=degree_bound, coefficients=fR_coefficients, valuations=fR_valuations)
1108
+
1109
+ def is_equivalence_irreducible(self, f, coefficients=None, valuations=None):
1110
+ r"""
1111
+ Return whether the polynomial ``f`` is equivalence-irreducible, i.e.,
1112
+ whether its :meth:`equivalence_decomposition` is trivial.
1113
+
1114
+ ALGORITHM:
1115
+
1116
+ We use the same algorithm as in :meth:`equivalence_decomposition` we
1117
+ just do not lift the result to key polynomials.
1118
+
1119
+ INPUT:
1120
+
1121
+ - ``f`` -- a non-constant polynomial in the domain of this valuation
1122
+
1123
+ EXAMPLES::
1124
+
1125
+ sage: # needs sage.libs.ntl
1126
+ sage: R.<u> = Qq(4,5)
1127
+ sage: S.<x> = R[]
1128
+ sage: v = GaussValuation(S)
1129
+ sage: v.is_equivalence_irreducible(x)
1130
+ True
1131
+ sage: v.is_equivalence_irreducible(x^2)
1132
+ False
1133
+ sage: v.is_equivalence_irreducible(x^2 + 2)
1134
+ False
1135
+ """
1136
+ f = self.domain().coerce(f)
1137
+
1138
+ if not self.domain().base_ring().is_field():
1139
+ domain = self.domain().change_ring(self.domain().base_ring().fraction_field())
1140
+ v = self.extension(domain)
1141
+ return v.is_equivalence_irreducible(v.domain()(f))
1142
+
1143
+ if f.is_constant():
1144
+ raise ValueError("f must not be constant")
1145
+
1146
+ _, phi_divides, F = self._equivalence_reduction(f, coefficients=coefficients, valuations=valuations)
1147
+ if phi_divides == 0:
1148
+ return F.is_constant() or F.is_irreducible()
1149
+ if phi_divides == 1:
1150
+ return F.is_constant()
1151
+ if phi_divides > 1:
1152
+ return False
1153
+
1154
+ def equivalence_decomposition(self, f, assume_not_equivalence_unit=False, coefficients=None, valuations=None, compute_unit=True, degree_bound=None):
1155
+ r"""
1156
+ Return an equivalence decomposition of ``f``, i.e., a polynomial
1157
+ `g(x)=e(x)\prod_i \phi_i(x)` with `e(x)` an :meth:`equivalence unit
1158
+ <InductiveValuation.is_equivalence_unit>` and the `\phi_i` :meth:`key
1159
+ polynomials <is_key>` such that ``f`` :meth:`~sage.rings.valuation.valuation.DiscretePseudoValuation.is_equivalent` to `g`.
1160
+
1161
+ INPUT:
1162
+
1163
+ - ``f`` -- a nonzero polynomial in the domain of this valuation
1164
+
1165
+ - ``assume_not_equivalence_unit`` -- whether or not to assume that
1166
+ ``f`` is not an :meth:`equivalence unit <InductiveValuation.is_equivalence_unit>`
1167
+ (default: ``False``)
1168
+
1169
+ - ``coefficients`` -- the coefficients of ``f`` in the
1170
+ :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.phi`-adic
1171
+ expansion if known (default: ``None``)
1172
+
1173
+ - ``valuations`` -- the valuations of ``coefficients`` if known
1174
+ (default: ``None``)
1175
+
1176
+ - ``compute_unit`` -- whether or not to compute the unit part of the
1177
+ decomposition (default: ``True``)
1178
+
1179
+ - ``degree_bound`` -- a bound on the degree of the
1180
+ :meth:`_equivalence_reduction` of ``f`` (default: ``None``)
1181
+
1182
+ ALGORITHM:
1183
+
1184
+ We use the algorithm described in Theorem 4.4 of [Mac1936II]_. After
1185
+ removing all factors `\phi` from a polynomial `f`, there is an
1186
+ equivalence unit `R` such that `Rf` has valuation zero. Now `Rf` can be
1187
+ factored as `\prod_i \alpha_i` over the :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.residue_field`. Lifting
1188
+ all `\alpha_i` to key polynomials `\phi_i` gives `Rf=\prod_i R_i f_i`
1189
+ for suitable equivalence units `R_i` (see :meth:`lift_to_key`). Taking
1190
+ `R'` an :meth:`~InductiveValuation.equivalence_reciprocal` of `R`, we have `f` equivalent
1191
+ to `(R'\prod_i R_i)\prod_i\phi_i`.
1192
+
1193
+ EXAMPLES::
1194
+
1195
+ sage: # needs sage.libs.ntl
1196
+ sage: R.<u> = Qq(4,10)
1197
+ sage: S.<x> = R[]
1198
+ sage: v = GaussValuation(S)
1199
+ sage: v.equivalence_decomposition(S.zero())
1200
+ Traceback (most recent call last):
1201
+ ...
1202
+ ValueError: equivalence decomposition of zero is not defined
1203
+ sage: v.equivalence_decomposition(S.one())
1204
+ 1 + O(2^10)
1205
+ sage: v.equivalence_decomposition(x^2+2)
1206
+ ((1 + O(2^10))*x)^2
1207
+ sage: v.equivalence_decomposition(x^2+1)
1208
+ ((1 + O(2^10))*x + 1 + O(2^10))^2
1209
+
1210
+ A polynomial that is an equivalence unit, is returned as the unit part
1211
+ of a :class:`~sage.structure.factorization.Factorization`, leading to a unit
1212
+ non-minimal degree::
1213
+
1214
+ sage: w = v.augmentation(x, 1) # needs sage.libs.ntl
1215
+ sage: F = w.equivalence_decomposition(x^2+1); F # needs sage.libs.ntl
1216
+ (1 + O(2^10))*x^2 + 1 + O(2^10)
1217
+ sage: F.unit() # needs sage.libs.ntl
1218
+ (1 + O(2^10))*x^2 + 1 + O(2^10)
1219
+
1220
+ However, if the polynomial has a non-unit factor, then the unit might
1221
+ be replaced by a factor of lower degree::
1222
+
1223
+ sage: f = x * (x^2 + 1) # needs sage.libs.ntl
1224
+ sage: F = w.equivalence_decomposition(f); F # needs sage.libs.ntl
1225
+ (1 + O(2^10))*x
1226
+ sage: F.unit() # needs sage.libs.ntl
1227
+ 1 + O(2^10)
1228
+
1229
+ Examples over an iterated unramified extension::
1230
+
1231
+ sage: # needs sage.libs.ntl
1232
+ sage: v = v.augmentation(x^2 + x + u, 1)
1233
+ sage: v = v.augmentation((x^2 + x + u)^2 + 2*x*(x^2 + x + u) + 4*x, 3)
1234
+ sage: v.equivalence_decomposition(x)
1235
+ (1 + O(2^10))*x
1236
+ sage: F = v.equivalence_decomposition( v.phi() )
1237
+ sage: len(F)
1238
+ 1
1239
+ sage: F = v.equivalence_decomposition( v.phi() * (x^4 + 4*x^3 + (7 + 2*u)*x^2 + (8 + 4*u)*x + 1023 + 3*u) )
1240
+ sage: len(F)
1241
+ 2
1242
+
1243
+ TESTS::
1244
+
1245
+ sage: # needs sage.geometry.polyhedron sage.groups sage.rings.number_field
1246
+ sage: R.<x> = QQ[]
1247
+ sage: K1.<pi> = NumberField(x^3 - 2)
1248
+ sage: K.<alpha> = K1.galois_closure()
1249
+ sage: R.<x> = K[]
1250
+ sage: vp = QQ.valuation(2)
1251
+ sage: vp = vp.extension(K)
1252
+ sage: v0 = GaussValuation(R, vp)
1253
+ sage: G = x^36 + 36*x^35 + 630*x^34 + 7144*x^33 + 59055*x^32 + 379688*x^31 +1978792*x^30 + 8604440*x^29 + 31895428*x^28 + 102487784*x^27 + 289310720*x^26 + 725361352*x^25 + 1629938380*x^24 + 3307417800*x^23 + 6098786184*x^22+10273444280*x^21 + 15878121214*x^20 + 22596599536*x^19 + 29695703772*x^18 +36117601976*x^17 + 40722105266*x^16 + 42608585080*x^15 + 41395961848*x^14 +37344435656*x^13 + 31267160756*x^12 + 24271543640*x^11 + 17439809008*x^10 + 11571651608*x^9 + 7066815164*x^8 + 3953912472*x^7 + 2013737432*x^6 + 925014888*x^5 + 378067657*x^4 + 134716588*x^3 + 40441790*x^2 + 9532544*x + 1584151
1254
+ sage: v1 = v0.mac_lane_step(G)[0]
1255
+ sage: V = v1.mac_lane_step(G)
1256
+ sage: v2 = V[0]
1257
+ sage: F = v2.equivalence_decomposition(G); F # needs sage.libs.singular
1258
+ (x^4 + 2*alpha + 1)^3 * (x^4 + 1/2*alpha^4 + alpha + 1)^3 * (x^4 + 1/2*alpha^4 + 3*alpha + 1)^3
1259
+ sage: v2.is_equivalent(F.prod(), G) # needs sage.libs.singular
1260
+ True
1261
+
1262
+ Check that :issue:`33422` is fixed::
1263
+
1264
+ sage: R.<x> = QQ[]
1265
+ sage: v_7 = QQ.valuation(7)
1266
+ sage: v0 = GaussValuation(R, v_7)
1267
+ sage: v1 = v0.augmentation(x, 3/2)
1268
+ sage: v2 = v1.augmentation(x^2-686, 7/2)
1269
+ sage: f = x^4 - 8001504*x^2 - 592815428352
1270
+ sage: F = v2.equivalence_decomposition(f); F # needs sage.libs.singular
1271
+ x^4 - 343/2*x^2 + 1294139
1272
+ sage: v2.is_equivalent(F.prod(), f) # needs sage.libs.singular
1273
+ True
1274
+ """
1275
+ f = self.domain().coerce(f)
1276
+
1277
+ if f.is_zero():
1278
+ raise ValueError("equivalence decomposition of zero is not defined")
1279
+
1280
+ from sage.structure.factorization import Factorization
1281
+ if not assume_not_equivalence_unit and self.is_equivalence_unit(f):
1282
+ return Factorization([], unit=f, sort=False)
1283
+
1284
+ if not self.domain().base_ring().is_field():
1285
+ nonfractions = self.domain().base_ring()
1286
+ domain = self.domain().change_ring(nonfractions.fraction_field())
1287
+ v = self.extension(domain)
1288
+ ret = v.equivalence_decomposition(v.domain()(f))
1289
+ return Factorization([(self._eliminate_denominators(g), e)
1290
+ for (g, e) in ret], unit=self._eliminate_denominators(ret.unit()), sort=False)
1291
+
1292
+ valuation, phi_divides, F = self._equivalence_reduction(f, coefficients=coefficients, valuations=valuations, degree_bound=degree_bound)
1293
+ F = F.factor()
1294
+ from sage.misc.verbose import verbose
1295
+ verbose("%s factors as %s = %s in reduction" % (f, F.prod(), F), level=20)
1296
+
1297
+ unit = self.domain().one()
1298
+ if compute_unit:
1299
+ R_ = self.equivalence_unit(valuation, reciprocal=True)
1300
+ unit = self.lift(self.residue_ring()(F.unit())) * R_
1301
+ F = list(F)
1302
+
1303
+ if compute_unit:
1304
+ from sage.misc.misc_c import prod
1305
+ unit *= self.lift(self.residue_ring()(prod([psi.leading_coefficient()**e for psi, e in F])))
1306
+ if not self.is_gauss_valuation():
1307
+ unit *= prod([self._Q_reciprocal(e*psi.degree()) for psi, e in F])
1308
+ unit = self.simplify(unit, effective_degree=0, force=True)
1309
+
1310
+ # A potential speedup that we tried to implement here:
1311
+ # When F factors as T^n - a, then instead of using any lift of T^n - a
1312
+ # we tried to take a lift that approximates well an n-th root of the
1313
+ # constant coefficient of f[0]. Doing so saved a few invocations of
1314
+ # mac_lane_step but in the end made hardly any difference.
1315
+
1316
+ F = [(self.lift_to_key(psi / psi.leading_coefficient()), e)
1317
+ for psi, e in F]
1318
+
1319
+ if phi_divides:
1320
+ for i, (g, e) in enumerate(F):
1321
+ if g == self.phi():
1322
+ F[i] = (self.phi(), e + phi_divides)
1323
+ break
1324
+ else:
1325
+ F.append((self.phi(), phi_divides))
1326
+
1327
+ ret = Factorization(F, unit=unit, sort=False)
1328
+
1329
+ if compute_unit:
1330
+ assert self.is_equivalent(ret.prod(), f) # this might fail because of leading zeros in inexact rings
1331
+ assert self.is_equivalence_unit(ret.unit())
1332
+
1333
+ return ret
1334
+
1335
+ def minimal_representative(self, f):
1336
+ r"""
1337
+ Return a minimal representative for ``f``, i.e., a pair `e, a` such
1338
+ that ``f`` :meth:`~sage.rings.valuation.valuation.DiscretePseudoValuation.is_equivalent` to `e a`, `e` is an
1339
+ :meth:`equivalence unit <InductiveValuation.is_equivalence_unit>`, and `a` :meth:`is_minimal` and monic.
1340
+
1341
+ INPUT:
1342
+
1343
+ - ``f`` -- a nonzero polynomial which is not an equivalence unit
1344
+
1345
+ OUTPUT: a factorization which has `e` as its unit and `a` as its unique factor
1346
+
1347
+ ALGORITHM:
1348
+
1349
+ We use the algorithm described in the proof of Lemma 4.1 of [Mac1936II]_.
1350
+ In the expansion `f=\sum_i f_i\phi^i` take `e=f_i` for the largest `i`
1351
+ with `f_i\phi^i` minimal (see :meth:`~sage.rings.valuation.developing_valuation.DevelopingValuation.effective_degree`).
1352
+ Let `h` be the :meth:`~InductiveValuation.equivalence_reciprocal` of `e` and take `a` given
1353
+ by the terms of minimal valuation in the expansion of `e f`.
1354
+
1355
+ EXAMPLES::
1356
+
1357
+ sage: # needs sage.libs.ntl
1358
+ sage: R.<u> = Qq(4,10)
1359
+ sage: S.<x> = R[]
1360
+ sage: v = GaussValuation(S)
1361
+ sage: v.minimal_representative(x + 2)
1362
+ (1 + O(2^10))*x
1363
+
1364
+ sage: # needs sage.libs.ntl
1365
+ sage: v = v.augmentation(x, 1)
1366
+ sage: v.minimal_representative(x + 2)
1367
+ (1 + O(2^10))*x + 2 + O(2^11)
1368
+ sage: f = x^3 + 6*x + 4
1369
+ sage: F = v.minimal_representative(f); F
1370
+ (2 + 2^2 + O(2^11)) * ((1 + O(2^10))*x + 2 + O(2^11))
1371
+ sage: v.is_minimal(F[0][0])
1372
+ True
1373
+ sage: v.is_equivalent(F.prod(), f)
1374
+ True
1375
+ """
1376
+ f = self.domain().coerce(f)
1377
+
1378
+ from sage.categories.fields import Fields
1379
+ if self.domain().base_ring() not in Fields():
1380
+ raise NotImplementedError("only implemented for polynomial rings over fields")
1381
+
1382
+ if f.is_zero():
1383
+ raise ValueError("zero has no minimal representative")
1384
+
1385
+ degree = self.effective_degree(f)
1386
+ if degree == 0:
1387
+ raise ValueError("equivalence units cannot have a minimal representative")
1388
+
1389
+ e = list(self.coefficients(f))[degree]
1390
+ h = self.equivalence_reciprocal(e).map_coefficients(_lift_to_maximal_precision)
1391
+ g = h * f
1392
+ vg = self(g)
1393
+
1394
+ coeffs = [c if v == vg else c.parent().zero()
1395
+ for v, c in zip(self.valuations(g), self.coefficients(g))]
1396
+ coeffs[degree] = self.domain().base_ring().one()
1397
+ ret = sum([c * self._phi**i for i, c in enumerate(coeffs)])
1398
+
1399
+ assert self.effective_degree(ret) == degree
1400
+ assert ret.is_monic()
1401
+ assert self.is_minimal(ret)
1402
+
1403
+ from sage.structure.factorization import Factorization
1404
+ ret = Factorization([(ret, 1)], unit=e, sort=False)
1405
+
1406
+ assert self.is_equivalent(ret.prod(), f) # this might fail because of leading zeros
1407
+ return ret
1408
+
1409
+ @abstract_method
1410
+ def lift_to_key(self, F):
1411
+ """
1412
+ Lift the irreducible polynomial ``F`` from the
1413
+ :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.residue_ring`
1414
+ to a key polynomial over this valuation.
1415
+
1416
+ INPUT:
1417
+
1418
+ - ``F`` -- an irreducible non-constant monic polynomial in
1419
+ :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.residue_ring`
1420
+ of this valuation
1421
+
1422
+ OUTPUT:
1423
+
1424
+ A polynomial `f` in the domain of this valuation which is a key
1425
+ polynomial for this valuation and which is such that an
1426
+ :meth:`augmentation` with this polynomial adjoins a root of ``F`` to
1427
+ the resulting :meth:`~sage.rings.valuation.valuation_space.DiscretePseudoValuationSpace.ElementMethods.residue_ring`.
1428
+
1429
+ More specifically, if ``F`` is not the generator of the residue ring,
1430
+ then multiplying ``f`` with the :meth:`~InductiveValuation.equivalence_reciprocal` of the
1431
+ :meth:`~InductiveValuation.equivalence_unit` of the valuation of ``f``, produces a unit
1432
+ which reduces to ``F``.
1433
+
1434
+ EXAMPLES::
1435
+
1436
+ sage: # needs sage.libs.ntl
1437
+ sage: R.<u> = Qq(4,10)
1438
+ sage: S.<x> = R[]
1439
+ sage: v = GaussValuation(S)
1440
+ sage: y = v.residue_ring().gen()
1441
+ sage: u0 = v.residue_ring().base_ring().gen()
1442
+ sage: f = v.lift_to_key(y^2 + y + u0); f
1443
+ (1 + O(2^10))*x^2 + (1 + O(2^10))*x + u + O(2^10)
1444
+ """
1445
+
1446
+ def _eliminate_denominators(self, f):
1447
+ r"""
1448
+ Return a polynomial in the domain of this valuation that
1449
+ :meth:`is_equivalent` to ``f``.
1450
+
1451
+ INPUT:
1452
+
1453
+ - ``f`` -- a polynomial with coefficients in the fraction field of the
1454
+ base ring of the domain of this valuation
1455
+
1456
+ EXAMPLES::
1457
+
1458
+ sage: R.<x> = ZZ[]
1459
+ sage: v = GaussValuation(R, ZZ.valuation(2))
1460
+ sage: v._eliminate_denominators(x/3)
1461
+ x
1462
+
1463
+ In general such a polynomial may not exist::
1464
+
1465
+ sage: w = v.augmentation(x, 1)
1466
+ sage: w._eliminate_denominators(x/2)
1467
+ Traceback (most recent call last):
1468
+ ...
1469
+ ValueError: element has no approximate inverse in this ring
1470
+
1471
+ In general it exists iff the coefficients of minimal valuation in the
1472
+ `\phi`-adic expansion of ``f`` do not have denominators of positive
1473
+ valuation and if the same is true for these coefficients in their
1474
+ expansion; at least if the coefficient ring's residue ring is already a
1475
+ field::
1476
+
1477
+ sage: w._eliminate_denominators(x^3/2 + x)
1478
+ x
1479
+ """
1480
+ if f in self.domain():
1481
+ return self.domain()(f)
1482
+
1483
+ nonfractions = self.domain().base_ring()
1484
+ fractions = nonfractions.fraction_field()
1485
+
1486
+ extended_domain = self.domain().change_ring(fractions)
1487
+
1488
+ g = extended_domain.coerce(f)
1489
+
1490
+ w = self.extension(extended_domain)
1491
+ # drop coefficients whose valuation is not minimal (recursively)
1492
+ valuation = w(g)
1493
+ g = w.simplify(g, error=valuation, force=True, phiadic=True)
1494
+
1495
+ if g in self.domain():
1496
+ return self.domain()(g)
1497
+
1498
+ nonfraction_valuation = self.restriction(nonfractions)
1499
+ # if this fails then there is no equivalent polynomial in the domain of this valuation
1500
+ ret = g.map_coefficients(
1501
+ lambda c: c.numerator() * nonfraction_valuation.inverse(c.denominator(),
1502
+ valuation
1503
+ + nonfraction_valuation(c.denominator())
1504
+ - nonfraction_valuation(c.numerator())
1505
+ + nonfraction_valuation.value_group().gen()),
1506
+ nonfractions)
1507
+ assert w.is_equivalent(f, ret)
1508
+ return ret
1509
+
1510
+ def _test_eliminate_denominators(self, **options):
1511
+ r"""
1512
+ Test the correctness of :meth:`_eliminate_denominators`.
1513
+
1514
+ EXAMPLES::
1515
+
1516
+ sage: R.<x> = ZZ[]
1517
+ sage: v = GaussValuation(R, ZZ.valuation(2))
1518
+ sage: v._test_eliminate_denominators()
1519
+ """
1520
+ tester = self._tester(**options)
1521
+
1522
+ nonfractions = self.domain().base_ring()
1523
+ fractions = nonfractions.fraction_field()
1524
+ extended_domain = self.domain().change_ring(fractions)
1525
+ w = self.extension(extended_domain)
1526
+
1527
+ S = tester.some_elements(w.domain().some_elements())
1528
+ for f in S:
1529
+ try:
1530
+ g = self._eliminate_denominators(f)
1531
+ except ValueError:
1532
+ continue
1533
+ tester.assertIs(g.parent(), self.domain())
1534
+ tester.assertTrue(w.is_equivalent(f, g))
1535
+
1536
+ def _test_lift_to_key(self, **options):
1537
+ r"""
1538
+ Test the correctness of :meth:`lift_to_key`.
1539
+
1540
+ EXAMPLES::
1541
+
1542
+ sage: R.<x> = QQ[]
1543
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1544
+ sage: v._test_lift_to_key() # needs sage.rings.number_field
1545
+ """
1546
+ tester = self._tester(**options)
1547
+
1548
+ try:
1549
+ self.residue_ring()
1550
+ except NotImplementedError:
1551
+ from sage.categories.fields import Fields
1552
+ if self.domain().base() in Fields():
1553
+ raise
1554
+ return
1555
+
1556
+ S = tester.some_elements(self.residue_ring().some_elements())
1557
+ for F in S:
1558
+ if F.is_monic() and not F.is_constant() and F.is_irreducible():
1559
+ try:
1560
+ f = self.lift_to_key(F)
1561
+ except NotImplementedError:
1562
+ from sage.categories.fields import Fields
1563
+ if self.domain().base() in Fields():
1564
+ raise
1565
+ continue
1566
+ tester.assertIs(f.parent(), self.domain())
1567
+ tester.assertTrue(self.is_key(f))
1568
+
1569
+ # check that augmentation produces a valuation with roots of F
1570
+ # in the residue ring
1571
+ from sage.rings.infinity import infinity
1572
+ w = self.augmentation(f, infinity)
1573
+ F = F.change_ring(w.residue_ring())
1574
+ roots = F.roots(multiplicities=False)
1575
+ tester.assertGreaterEqual(len(roots), 1)
1576
+
1577
+ # check that f has the right reduction
1578
+ if F == F.parent().gen():
1579
+ tester.assertTrue(self.is_equivalent(f, self.phi()))
1580
+ else:
1581
+ tester.assertEqual(self.reduce(f * self.equivalence_reciprocal(self.equivalence_unit(self(f)))), F)
1582
+
1583
+ def _test_is_equivalence_irreducible(self, **options):
1584
+ r"""
1585
+ Test the correctness of :meth:`is_equivalence_irreducible`.
1586
+
1587
+ EXAMPLES::
1588
+
1589
+ sage: R.<x> = QQ[]
1590
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1591
+ sage: v._test_is_equivalence_irreducible()
1592
+ """
1593
+ tester = self._tester(**options)
1594
+ S = tester.some_elements(self.domain().some_elements())
1595
+ for f in S:
1596
+ if f.is_constant():
1597
+ continue
1598
+ is_equivalence_irreducible = self.is_equivalence_irreducible(f)
1599
+ F = self.equivalence_decomposition(f)
1600
+ tester.assertEqual(is_equivalence_irreducible, len(F) == 0 or (len(F) == 1 and F[0][1] == 1))
1601
+ if self.is_equivalence_unit(f):
1602
+ tester.assertTrue(f.is_constant() or self.is_equivalence_irreducible(f))
1603
+
1604
+ tester.assertTrue(self.is_equivalence_irreducible(self.phi()))
1605
+ tester.assertTrue(self.is_equivalence_irreducible(-self.phi()))
1606
+ tester.assertFalse(self.is_equivalence_irreducible(self.phi() ** 2))
1607
+
1608
+
1609
+ class FinalInductiveValuation(InductiveValuation):
1610
+ r"""
1611
+ Abstract base class for an inductive valuation which cannot be augmented further.
1612
+
1613
+ TESTS::
1614
+
1615
+ sage: R.<x> = QQ[]
1616
+ sage: v = GaussValuation(R, valuations.TrivialValuation(QQ))
1617
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
1618
+ sage: from sage.rings.valuation.inductive_valuation import FinalInductiveValuation
1619
+ sage: isinstance(w, FinalInductiveValuation)
1620
+ True
1621
+ """
1622
+
1623
+
1624
+ class InfiniteInductiveValuation(FinalInductiveValuation, InfiniteDiscretePseudoValuation):
1625
+ r"""
1626
+ Abstract base class for an inductive valuation which is not discrete, i.e.,
1627
+ which assigns infinite valuation to its last key polynomial.
1628
+
1629
+ EXAMPLES::
1630
+
1631
+ sage: R.<x> = QQ[]
1632
+ sage: v = GaussValuation(R, QQ.valuation(2))
1633
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
1634
+ """
1635
+ def __init__(self, parent, base_valuation):
1636
+ r"""
1637
+ TESTS::
1638
+
1639
+ sage: R.<x> = QQ[]
1640
+ sage: v = GaussValuation(R, QQ.valuation(2))
1641
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
1642
+ sage: from sage.rings.valuation.inductive_valuation import InfiniteInductiveValuation
1643
+ sage: isinstance(w, InfiniteInductiveValuation)
1644
+ True
1645
+ """
1646
+ FinalInductiveValuation.__init__(self, parent, base_valuation)
1647
+ InfiniteDiscretePseudoValuation.__init__(self, parent)
1648
+
1649
+ def change_domain(self, ring):
1650
+ r"""
1651
+ Return this valuation over ``ring``.
1652
+
1653
+ EXAMPLES:
1654
+
1655
+ We can turn an infinite valuation into a valuation on the quotient::
1656
+
1657
+ sage: R.<x> = QQ[]
1658
+ sage: v = GaussValuation(R, QQ.valuation(2))
1659
+ sage: w = v.augmentation(x^2 + x + 1, infinity)
1660
+ sage: w.change_domain(R.quo(x^2 + x + 1))
1661
+ 2-adic valuation
1662
+ """
1663
+ from sage.rings.polynomial.polynomial_quotient_ring import PolynomialQuotientRing_generic
1664
+ if isinstance(ring, PolynomialQuotientRing_generic) and ring.base() is self.domain() and ring.modulus() == self.phi():
1665
+ return self.restriction(self.domain().base())._extensions_to_quotient(ring, approximants=[self])[0]
1666
+ return super().change_domain(ring)
1667
+
1668
+
1669
+ def _lift_to_maximal_precision(c):
1670
+ r"""
1671
+ Lift ``c`` to maximal precision if the parent is not exact.
1672
+
1673
+ EXAMPLES::
1674
+
1675
+ sage: R = Zp(2,5)
1676
+ sage: x = R(1,2); x
1677
+ 1 + O(2^2)
1678
+ sage: from sage.rings.valuation.inductive_valuation import _lift_to_maximal_precision
1679
+ sage: _lift_to_maximal_precision(x)
1680
+ 1 + O(2^5)
1681
+
1682
+ sage: x = 1
1683
+ sage: _lift_to_maximal_precision(x)
1684
+ 1
1685
+ """
1686
+ return c if c.parent().is_exact() else c.lift_to_precision()