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,1615 @@
1
+ # sage_setup: distribution = sagemath-pari
2
+ r"""
3
+ Spaces of valuations
4
+
5
+ This module provides spaces of exponential pseudo-valuations on integral
6
+ domains. It currently only provides support for such valuations if they are
7
+ discrete, i.e., their image is a discrete additive subgroup of the rational
8
+ numbers extended by `\infty`.
9
+
10
+ AUTHORS:
11
+
12
+ - Julian Rüth (2016-10-14): initial version
13
+
14
+ EXAMPLES::
15
+
16
+ sage: QQ.valuation(2).parent()
17
+ Discrete pseudo-valuations on Rational Field
18
+
19
+ .. NOTE::
20
+
21
+ Note that many tests not only in this module do not create instances of
22
+ valuations directly since this gives the wrong inheritance structure on
23
+ the resulting objects::
24
+
25
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
26
+ sage: from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
27
+ sage: H = DiscretePseudoValuationSpace(QQ)
28
+ sage: v = TrivialDiscretePseudoValuation(H)
29
+ sage: v._test_category()
30
+ Traceback (most recent call last):
31
+ ...
32
+ AssertionError: False is not true
33
+
34
+ Instead, the valuations need to be created through the
35
+ ``__make_element_class__`` of the containing space::
36
+
37
+ sage: from sage.rings.valuation.trivial_valuation import TrivialDiscretePseudoValuation
38
+ sage: v = H.__make_element_class__(TrivialDiscretePseudoValuation)(H)
39
+ sage: v._test_category()
40
+
41
+ The factories such as ``TrivialPseudoValuation`` provide the right
42
+ inheritance structure::
43
+
44
+ sage: v = valuations.TrivialPseudoValuation(QQ)
45
+ sage: v._test_category()
46
+ """
47
+ # ****************************************************************************
48
+ # Copyright (C) 2016-2017 Julian Rüth <julian.rueth@fsfe.org>
49
+ #
50
+ # Distributed under the terms of the GNU General Public License (GPL)
51
+ # as published by the Free Software Foundation; either version 2 of
52
+ # the License, or (at your option) any later version.
53
+ # https://www.gnu.org/licenses/
54
+ # ****************************************************************************
55
+
56
+ from sage.categories.homset import Homset
57
+ from sage.misc.lazy_attribute import lazy_attribute
58
+ from sage.misc.abstract_method import abstract_method
59
+ from sage.structure.unique_representation import UniqueRepresentation
60
+ from sage.misc.cachefunc import cached_method
61
+ from sage.categories.action import Action
62
+
63
+
64
+ class DiscretePseudoValuationSpace(UniqueRepresentation, Homset):
65
+ r"""
66
+ The space of discrete pseudo-valuations on ``domain``.
67
+
68
+ EXAMPLES::
69
+
70
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
71
+ sage: H = DiscretePseudoValuationSpace(QQ)
72
+ sage: QQ.valuation(2) in H
73
+ True
74
+
75
+ .. NOTE::
76
+
77
+ We do not distinguish between the space of discrete valuations and the
78
+ space of discrete pseudo-valuations. This is entirely for practical
79
+ reasons: We would like to model the fact that every discrete valuation
80
+ is also a discrete pseudo-valuation. At first, it seems to be
81
+ sufficient to make sure that the ``in`` operator works which can
82
+ essentially be achieved by overriding ``_element_constructor_`` of
83
+ the space of discrete pseudo-valuations to accept discrete valuations
84
+ by just returning them. Currently, however, if one does not change the
85
+ parent of an element in ``_element_constructor_`` to ``self``, then
86
+ one cannot register that conversion as a coercion. Consequently, the
87
+ operators ``<=`` and ``>=`` cannot be made to work between discrete
88
+ valuations and discrete pseudo-valuations on the same domain (because
89
+ the implementation only calls ``_richcmp`` if both operands have the
90
+ same parent.) Of course, we could override ``__ge__`` and ``__le__``
91
+ but then we would likely run into other surprises.
92
+ So in the end, we went for a single homspace for all discrete
93
+ valuations (pseudo or not) as this makes the implementation much
94
+ easier.
95
+
96
+ .. TODO::
97
+
98
+ The comparison problem might be fixed by :issue:`22029` or similar.
99
+
100
+ TESTS::
101
+
102
+ sage: TestSuite(H).run() # long time
103
+ """
104
+ def __init__(self, domain):
105
+ r"""
106
+ TESTS::
107
+
108
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
109
+ sage: isinstance(QQ.valuation(2).parent(), DiscretePseudoValuationSpace)
110
+ True
111
+ """
112
+ from .value_group import DiscreteValuationCodomain
113
+ # A valuation is a map from an additive semigroup to an additive semigroup, however, it
114
+ # does not preserve that structure. It is therefore only a morphism in the category of sets.
115
+ from sage.categories.sets_cat import Sets
116
+
117
+ UniqueRepresentation.__init__(self)
118
+ Homset.__init__(self, domain, DiscreteValuationCodomain(), category=Sets())
119
+
120
+ from sage.categories.domains import Domains
121
+ if domain not in Domains():
122
+ raise ValueError("domain must be an integral domain")
123
+
124
+ @lazy_attribute
125
+ def _abstract_element_class(self):
126
+ r"""
127
+ Return an abstract base class for all valuations in this space.
128
+
129
+ This is used to extend every valuation with a number of generic methods
130
+ that are independent of implementation details.
131
+
132
+ Usually, extensions of this kind would be done by implementing an
133
+ appropriate class ``MorphismMethods`` in the category of this homset.
134
+ However, there is no category whose arrows are the valuations, so we
135
+ need to move this magic down to the level of the actual homset.
136
+
137
+ EXAMPLES::
138
+
139
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
140
+ sage: isinstance(QQ.valuation(2), DiscretePseudoValuationSpace.ElementMethods) # indirect doctest
141
+ True
142
+ """
143
+ class_name = "%s._abstract_element_class" % self.__class__.__name__
144
+ from sage.structure.dynamic_class import dynamic_class
145
+ return dynamic_class(class_name, (super()._abstract_element_class, self.__class__.ElementMethods))
146
+
147
+ def _get_action_(self, S, op, self_on_left):
148
+ r"""
149
+ Return the ``op`` action of ``S`` on elements in this space.
150
+
151
+ EXAMPLES::
152
+
153
+ sage: v = QQ.valuation(2)
154
+ sage: from operator import mul
155
+ sage: v.parent().get_action(ZZ, mul) # indirect doctest
156
+ Right action by Integer Ring on Discrete pseudo-valuations on Rational Field
157
+ """
158
+ from operator import mul
159
+ from sage.rings.infinity import InfinityRing
160
+ from sage.rings.rational_field import QQ
161
+ from sage.rings.integer_ring import ZZ
162
+ if op == mul and (S is InfinityRing or S is QQ or S is ZZ):
163
+ return ScaleAction(S, self, not self_on_left, op)
164
+ return None
165
+
166
+ def _an_element_(self):
167
+ r"""
168
+ Return a trivial valuation in this space.
169
+
170
+ EXAMPLES::
171
+
172
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
173
+ sage: DiscretePseudoValuationSpace(QQ).an_element() # indirect doctest
174
+ Trivial pseudo-valuation on Rational Field
175
+ """
176
+ from .trivial_valuation import TrivialPseudoValuation
177
+ return TrivialPseudoValuation(self.domain())
178
+
179
+ def _repr_(self):
180
+ r"""
181
+ Return a printable representation of this space.
182
+
183
+ EXAMPLES::
184
+
185
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
186
+ sage: DiscretePseudoValuationSpace(QQ) # indirect doctest
187
+ Discrete pseudo-valuations on Rational Field
188
+ """
189
+ return "Discrete pseudo-valuations on %r" % (self.domain(),)
190
+
191
+ def __contains__(self, x):
192
+ r"""
193
+ Return whether ``x`` is a valuation in this space.
194
+
195
+ EXAMPLES::
196
+
197
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
198
+ sage: H = DiscretePseudoValuationSpace(QQ)
199
+ sage: H.an_element() in H
200
+ True
201
+ sage: QQ.valuation(2) in H
202
+ True
203
+ """
204
+ # override the logic from Homset with the original implementation for Parent
205
+ # which entirely relies on a proper implementation of
206
+ # _element_constructor_ and coercion maps
207
+ from sage.structure.parent import Parent
208
+ return Parent.__contains__(self, x)
209
+
210
+ def __call__(self, x):
211
+ r"""
212
+ Create an element in this space from ``x``.
213
+
214
+ EXAMPLES::
215
+
216
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
217
+ sage: H = DiscretePseudoValuationSpace(QQ)
218
+ sage: H(QQ.valuation(2))
219
+ 2-adic valuation
220
+ """
221
+ # override the logic from Homset with the original implementation for Parent
222
+ # which entirely relies on a proper implementation of
223
+ # _element_constructor_ and coercion maps
224
+ from sage.structure.parent import Parent
225
+ return Parent.__call__(self, x)
226
+
227
+ def _element_constructor_(self, x):
228
+ r"""
229
+ Create an element in this space from ``x``.
230
+
231
+ EXAMPLES:
232
+
233
+ We try to convert valuations defined on different domains by changing
234
+ their base ring::
235
+
236
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
237
+ sage: Z = DiscretePseudoValuationSpace(ZZ)
238
+ sage: Q = DiscretePseudoValuationSpace(QQ)
239
+ sage: v = ZZ.valuation(2)
240
+ sage: v in Q
241
+ False
242
+ sage: Q(v) in Q
243
+ True
244
+ sage: Q(v) in Z
245
+ False
246
+ sage: Z(Q(v)) in Z
247
+ True
248
+ """
249
+ if isinstance(x.parent(), DiscretePseudoValuationSpace):
250
+ if x.domain() is not self.domain():
251
+ try:
252
+ return self(x.change_domain(self.domain()))
253
+ except NotImplementedError:
254
+ pass
255
+ else:
256
+ return x
257
+ raise ValueError("element cannot be converted into the space of %r" % (self,))
258
+
259
+ class ElementMethods:
260
+ r"""
261
+ Provides methods for discrete pseudo-valuations that are added
262
+ automatically to valuations in this space.
263
+
264
+ EXAMPLES:
265
+
266
+ Here is an example of a method that is automagically added to a
267
+ discrete valuation::
268
+
269
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
270
+ sage: H = DiscretePseudoValuationSpace(QQ)
271
+ sage: QQ.valuation(2).is_discrete_pseudo_valuation() # indirect doctest
272
+ True
273
+
274
+ The methods will be provided even if the concrete type is not created
275
+ with ``__make_element_class__``::
276
+
277
+ sage: from sage.rings.valuation.valuation import DiscretePseudoValuation
278
+ sage: m = DiscretePseudoValuation(H)
279
+ sage: m.parent() is H
280
+ True
281
+ sage: m.is_discrete_pseudo_valuation()
282
+ True
283
+
284
+ However, the category framework advises you to use inheritance::
285
+
286
+ sage: m._test_category()
287
+ Traceback (most recent call last):
288
+ ...
289
+ AssertionError: False is not true
290
+
291
+ Using ``__make_element_class__``, makes your concrete valuation inherit
292
+ from this class::
293
+
294
+ sage: m = H.__make_element_class__(DiscretePseudoValuation)(H)
295
+ sage: m._test_category()
296
+ """
297
+ def is_discrete_pseudo_valuation(self):
298
+ r"""
299
+ Return whether this valuation is a discrete pseudo-valuation.
300
+
301
+ EXAMPLES::
302
+
303
+ sage: QQ.valuation(2).is_discrete_pseudo_valuation()
304
+ True
305
+ """
306
+ return True
307
+
308
+ @abstract_method
309
+ def is_discrete_valuation(self):
310
+ r"""
311
+ Return whether this valuation is a discrete valuation, i.e.,
312
+ whether it is a :meth:`discrete pseudo valuation
313
+ <is_discrete_pseudo_valuation>` that only sends zero to `\infty`.
314
+
315
+ EXAMPLES::
316
+
317
+ sage: QQ.valuation(2).is_discrete_valuation()
318
+ True
319
+ """
320
+
321
+ def is_negative_pseudo_valuation(self):
322
+ r"""
323
+ Return whether this valuation is a discrete pseudo-valuation that
324
+ does attain `-\infty`, i.e., it is non-trivial and its domain
325
+ contains an element with valuation `\infty` that has an inverse.
326
+
327
+ EXAMPLES::
328
+
329
+ sage: QQ.valuation(2).is_negative_pseudo_valuation()
330
+ False
331
+ """
332
+ from sage.categories.fields import Fields
333
+ if self.is_discrete_valuation():
334
+ return False
335
+ elif self.domain() in Fields():
336
+ return True
337
+ raise NotImplementedError
338
+
339
+ @cached_method
340
+ def is_trivial(self):
341
+ r"""
342
+ Return whether this valuation is trivial, i.e., whether it is
343
+ constant `\infty` or constant zero for everything but the zero
344
+ element.
345
+
346
+ Subclasses need to override this method if they do not implement
347
+ :meth:`uniformizer`.
348
+
349
+ EXAMPLES::
350
+
351
+ sage: QQ.valuation(7).is_trivial()
352
+ False
353
+ """
354
+ from sage.rings.infinity import infinity
355
+ if self(self.domain().one()) is infinity:
356
+ # the constant infinity
357
+ return True
358
+ if self(self.uniformizer()) != 0:
359
+ # not constant on the nonzero elements
360
+ return False
361
+ return True
362
+
363
+ @abstract_method
364
+ def uniformizer(self):
365
+ r"""
366
+ Return an element in the domain which has positive valuation and
367
+ generates the value group of this valuation.
368
+
369
+ EXAMPLES::
370
+
371
+ sage: QQ.valuation(11).uniformizer()
372
+ 11
373
+
374
+ Trivial valuations have no uniformizer::
375
+
376
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
377
+ sage: v = DiscretePseudoValuationSpace(QQ).an_element()
378
+ sage: v.is_trivial()
379
+ True
380
+ sage: v.uniformizer()
381
+ Traceback (most recent call last):
382
+ ...
383
+ ValueError: Trivial valuations do not define a uniformizing element
384
+ """
385
+
386
+ @cached_method
387
+ def value_group(self):
388
+ r"""
389
+ Return the value group of this discrete pseudo-valuation, the
390
+ discrete additive subgroup of the rational numbers which is
391
+ generated by the valuation of the :meth:`uniformizer`.
392
+
393
+ EXAMPLES::
394
+
395
+ sage: QQ.valuation(2).value_group()
396
+ Additive Abelian Group generated by 1
397
+
398
+ A pseudo-valuation that is `\infty` everywhere, does not have a
399
+ value group::
400
+
401
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
402
+ sage: v = DiscretePseudoValuationSpace(QQ).an_element()
403
+ sage: v.value_group()
404
+ Traceback (most recent call last):
405
+ ...
406
+ ValueError: The trivial pseudo-valuation that is infinity everywhere does not have a value group.
407
+ """
408
+ from .value_group import DiscreteValueGroup
409
+ return DiscreteValueGroup(self(self.uniformizer()))
410
+
411
+ def value_semigroup(self):
412
+ r"""
413
+ Return the value semigroup of this discrete pseudo-valuation, the
414
+ additive subsemigroup of the rational numbers which is generated by
415
+ the valuations of the elements in the domain.
416
+
417
+ EXAMPLES:
418
+
419
+ Most commonly, in particular over fields, the semigroup is the
420
+ group generated by the valuation of the uniformizer::
421
+
422
+ sage: G = QQ.valuation(2).value_semigroup(); G
423
+ Additive Abelian Semigroup generated by -1, 1
424
+ sage: G in AdditiveMagmas().AdditiveAssociative().AdditiveUnital().AdditiveInverse()
425
+ True
426
+
427
+ If the domain is a discrete valuation ring, then the semigroup
428
+ consists of the positive elements of the :meth:`value_group`::
429
+
430
+ sage: Zp(2).valuation().value_semigroup()
431
+ Additive Abelian Semigroup generated by 1
432
+
433
+ The semigroup can have a more complicated structure when the
434
+ uniformizer is not in the domain::
435
+
436
+ sage: v = ZZ.valuation(2)
437
+ sage: R.<x> = ZZ[]
438
+ sage: w = GaussValuation(R, v)
439
+ sage: u = w.augmentation(x, 5/3)
440
+ sage: u.value_semigroup()
441
+ Additive Abelian Semigroup generated by 1, 5/3
442
+ """
443
+ from sage.categories.fields import Fields
444
+ if self.domain() in Fields():
445
+ from .value_group import DiscreteValueSemigroup
446
+ # return the semigroup generated by the elements of the group
447
+ return DiscreteValueSemigroup([]) + self.value_group()
448
+ raise NotImplementedError("cannot determine value semigroup of %r" % (self,))
449
+
450
+ def element_with_valuation(self, s):
451
+ r"""
452
+ Return an element in the domain of this valuation with valuation
453
+ ``s``.
454
+
455
+ EXAMPLES::
456
+
457
+ sage: v = ZZ.valuation(2)
458
+ sage: v.element_with_valuation(10)
459
+ 1024
460
+ """
461
+ from sage.rings.integer_ring import ZZ
462
+ from sage.rings.rational_field import QQ
463
+ s = QQ.coerce(s)
464
+ if s not in self.value_semigroup():
465
+ raise ValueError("s must be in the value semigroup of this valuation but %r is not in %r" % (s, self.value_semigroup()))
466
+ if s == 0:
467
+ return self.domain().one()
468
+ exp = s / self.value_group().gen()
469
+ if exp not in ZZ:
470
+ raise NotImplementedError("s must be a multiple of %r but %r is not" % (self.value_group().gen(), s))
471
+ ret = self.domain()(self.uniformizer() ** ZZ(exp))
472
+ return self.simplify(ret, error=s)
473
+
474
+ @abstract_method
475
+ def residue_ring(self):
476
+ r"""
477
+ Return the residue ring of this valuation, i.e., the elements of
478
+ nonnegative valuation modulo the elements of positive valuation.
479
+ EXAMPLES::
480
+
481
+ sage: QQ.valuation(2).residue_ring()
482
+ Finite Field of size 2
483
+ sage: valuations.TrivialValuation(QQ).residue_ring()
484
+ Rational Field
485
+
486
+ Note that a residue ring always exists, even when a residue field
487
+ may not::
488
+
489
+ sage: valuations.TrivialPseudoValuation(QQ).residue_ring()
490
+ Quotient of Rational Field by the ideal (1)
491
+ sage: valuations.TrivialValuation(ZZ).residue_ring()
492
+ Integer Ring
493
+ sage: GaussValuation(ZZ['x'], ZZ.valuation(2)).residue_ring()
494
+ Univariate Polynomial Ring in x over Finite Field of size 2...
495
+ """
496
+
497
+ def residue_field(self):
498
+ r"""
499
+ Return the residue field of this valuation, i.e., the field of
500
+ fractions of the :meth:`residue_ring`, the elements of nonnegative
501
+ valuation modulo the elements of positive valuation.
502
+
503
+ EXAMPLES::
504
+
505
+ sage: QQ.valuation(2).residue_field()
506
+ Finite Field of size 2
507
+ sage: valuations.TrivialValuation(QQ).residue_field()
508
+ Rational Field
509
+
510
+ sage: valuations.TrivialValuation(ZZ).residue_field()
511
+ Rational Field
512
+ sage: GaussValuation(ZZ['x'], ZZ.valuation(2)).residue_field()
513
+ Rational function field in x over Finite Field of size 2
514
+ """
515
+ ret = self.residue_ring()
516
+ from sage.categories.fields import Fields
517
+ if ret in Fields():
518
+ return ret
519
+ from sage.rings.polynomial.polynomial_ring import PolynomialRing_generic
520
+ if isinstance(ret, PolynomialRing_generic):
521
+ from sage.rings.function_field.constructor import FunctionField
522
+ return FunctionField(ret.base_ring().fraction_field(), names=(ret.variable_name(),))
523
+ return ret.fraction_field()
524
+
525
+ @abstract_method
526
+ def reduce(self, x):
527
+ r"""
528
+ Return the image of ``x`` in the :meth:`residue_ring` of this
529
+ valuation.
530
+
531
+ EXAMPLES::
532
+
533
+ sage: v = QQ.valuation(2)
534
+ sage: v.reduce(2)
535
+ 0
536
+ sage: v.reduce(1)
537
+ 1
538
+ sage: v.reduce(1/3)
539
+ 1
540
+ sage: v.reduce(1/2)
541
+ Traceback (most recent call last):
542
+ ...
543
+ ValueError: reduction is only defined for elements of nonnegative valuation
544
+ """
545
+
546
+ @abstract_method
547
+ def lift(self, X):
548
+ r"""
549
+ Return a lift of ``X`` in the domain which reduces down to ``X``
550
+ again via :meth:`reduce`.
551
+
552
+ EXAMPLES::
553
+
554
+ sage: v = QQ.valuation(2)
555
+ sage: v.lift(v.residue_ring().one())
556
+ 1
557
+ """
558
+
559
+ def extension(self, ring):
560
+ r"""
561
+ Return the unique extension of this valuation to ``ring``.
562
+
563
+ EXAMPLES::
564
+
565
+ sage: v = ZZ.valuation(2)
566
+ sage: w = v.extension(QQ)
567
+ sage: w.domain()
568
+ Rational Field
569
+ """
570
+ extensions = self.extensions(ring)
571
+ assert extensions
572
+ if len(extensions) > 1:
573
+ raise ValueError("there is no unique extension of %r from %r to %r" % (self, self.domain(), ring))
574
+ return extensions[0]
575
+
576
+ def extensions(self, ring):
577
+ r"""
578
+ Return the extensions of this valuation to ``ring``.
579
+
580
+ EXAMPLES::
581
+
582
+ sage: v = ZZ.valuation(2)
583
+ sage: v.extensions(QQ)
584
+ [2-adic valuation]
585
+ """
586
+ if ring is self.domain():
587
+ return [self]
588
+ raise NotImplementedError("extending %r from %r to %r not implemented" % (self, self.domain(), ring))
589
+
590
+ def restriction(self, ring):
591
+ r"""
592
+ Return the restriction of this valuation to ``ring``.
593
+
594
+ EXAMPLES::
595
+
596
+ sage: v = QQ.valuation(2)
597
+ sage: w = v.restriction(ZZ)
598
+ sage: w.domain()
599
+ Integer Ring
600
+ """
601
+ if ring is self.domain():
602
+ return self
603
+ raise NotImplementedError("restricting %r from %r to %r not implemented" % (self, self.domain(), ring))
604
+
605
+ def change_domain(self, ring):
606
+ r"""
607
+ Return this valuation over ``ring``.
608
+
609
+ Unlike :meth:`extension` or :meth:`restriction`, this might not be
610
+ completely sane mathematically. It is essentially a conversion of
611
+ this valuation into another space of valuations.
612
+
613
+ EXAMPLES::
614
+
615
+ sage: v = QQ.valuation(3)
616
+ sage: v.change_domain(ZZ)
617
+ 3-adic valuation
618
+ """
619
+ if ring is self.domain():
620
+ return self
621
+ if self.domain().is_subring(ring):
622
+ return self.extension(ring)
623
+ if ring.is_subring(self.domain()):
624
+ return self.restriction(ring)
625
+ raise NotImplementedError("changing %r from %r to %r not implemented" % (self, self.domain(), ring))
626
+
627
+ def scale(self, scalar):
628
+ r"""
629
+ Return this valuation scaled by ``scalar``.
630
+
631
+ INPUT:
632
+
633
+ - ``scalar`` -- a nonnegative rational number or infinity
634
+
635
+ EXAMPLES::
636
+
637
+ sage: v = ZZ.valuation(3)
638
+ sage: w = v.scale(3)
639
+ sage: w(3)
640
+ 3
641
+
642
+ Scaling can also be done through multiplication with a scalar::
643
+
644
+ sage: w/3 == v
645
+ True
646
+
647
+ Multiplication by zero produces the trivial discrete valuation::
648
+
649
+ sage: w = 0*v
650
+ sage: w(3)
651
+ 0
652
+ sage: w(0)
653
+ +Infinity
654
+
655
+ Multiplication by infinity produces the trivial discrete
656
+ pseudo-valuation::
657
+
658
+ sage: w = infinity*v
659
+ sage: w(3)
660
+ +Infinity
661
+ sage: w(0)
662
+ +Infinity
663
+ """
664
+ from sage.rings.infinity import infinity
665
+ if scalar is infinity:
666
+ from .trivial_valuation import TrivialPseudoValuation
667
+ return TrivialPseudoValuation(self.domain())
668
+ if scalar == 0:
669
+ from .trivial_valuation import TrivialValuation
670
+ return TrivialValuation(self.domain())
671
+ if scalar == 1:
672
+ return self
673
+ if scalar < 0:
674
+ raise ValueError("scalar must be nonnegative")
675
+ if self.is_trivial():
676
+ return self
677
+
678
+ from .scaled_valuation import ScaledValuation_generic
679
+ if isinstance(self, ScaledValuation_generic):
680
+ return self._base_valuation.scale(scalar * self._scale)
681
+
682
+ from .scaled_valuation import ScaledValuation
683
+ return ScaledValuation(self, scalar)
684
+
685
+ def separating_element(self, others):
686
+ r"""
687
+ Return an element in the domain of this valuation which has
688
+ positive valuation with respect to this valuation but negative
689
+ valuation with respect to the valuations in ``others``.
690
+
691
+ EXAMPLES::
692
+
693
+ sage: v2 = QQ.valuation(2)
694
+ sage: v3 = QQ.valuation(3)
695
+ sage: v5 = QQ.valuation(5)
696
+ sage: v2.separating_element([v3,v5])
697
+ 4/15
698
+ """
699
+ try:
700
+ iter(others)
701
+ except TypeError:
702
+ raise ValueError("others must be a list of valuations")
703
+
704
+ for other in others + [self]:
705
+ if other.parent() is not self.parent():
706
+ raise ValueError("all valuations must be valuations on %r but %r is a valuation on %r" % (self.domain(), other, other.domain()))
707
+ if not other.is_discrete_valuation():
708
+ raise ValueError("all valuations must be discrete valuations but %r is not" % (other,))
709
+ if other.is_trivial():
710
+ raise ValueError("all valuations must be non-trivial but %r is not" % (other,))
711
+
712
+ if len(others) == 0:
713
+ return self.uniformizer()
714
+
715
+ # see the proof of Lemma 6.9 in http://www1.spms.ntu.edu.sg/~frederique/antchap6.pdf
716
+ ret = self._strictly_separating_element(others[0])
717
+ for i in range(1, len(others)):
718
+ # ret is an element which separates self and others[:i]
719
+ if others[i](ret) < 0:
720
+ # it also separates self and others[i]
721
+ continue
722
+
723
+ delta = self._strictly_separating_element(others[i])
724
+ if others[i](ret) == 0:
725
+ # combining powers of ret and delta, we produce a
726
+ # separating element for self and others[:i+1]
727
+ factor = ret
728
+ ret = delta
729
+ while any(other(ret) >= 0 for other in others[:i]):
730
+ assert others[i](ret) < 0
731
+ ret *= factor
732
+ else: # others[i](ret) > 0
733
+ # construct an element which approximates a unit with respect to others[i]
734
+ # and has negative valuation with respect to others[:i]
735
+ from sage.rings.semirings.non_negative_integer_semiring import NN
736
+ for r in iter(NN):
737
+ # When we enter this loop we are essentially out of
738
+ # luck. The size of the coefficients is likely going
739
+ # through the roof here and this is not going to
740
+ # terminate in reasonable time.
741
+ factor = (ret**r)/(1+ret**r)
742
+ ret = factor * delta
743
+ if all(other(ret) < 0 for other in others[:i+1]):
744
+ break
745
+ return ret
746
+
747
+ def _strictly_separating_element(self, other):
748
+ r"""
749
+ Return an element in the domain of this valuation which has
750
+ positive valuation with respect to this valuation but negative
751
+ valuation with respect to ``other``.
752
+
753
+ .. NOTE::
754
+
755
+ Overriding this method tends to be a nuisance as you need to
756
+ handle all possible types (as in Python type) of valuations.
757
+ This is essentially the same problem that you have when
758
+ implementing operators such as ``+`` or ``>=``. A sufficiently
759
+ fancy multimethod implementation could solve that here but
760
+ there is currently nothing like that in Sage/Python.
761
+
762
+ EXAMPLES::
763
+
764
+ sage: v2 = QQ.valuation(2)
765
+ sage: v3 = QQ.valuation(3)
766
+ sage: v2._strictly_separating_element(v3)
767
+ 2/3
768
+ """
769
+ from sage.rings.infinity import infinity
770
+
771
+ numerator = self._weakly_separating_element(other)
772
+ n = self(numerator)
773
+ nn = other(numerator)
774
+ assert n > 0
775
+ assert nn is not infinity
776
+ if nn < 0:
777
+ return numerator
778
+
779
+ denominator = other._weakly_separating_element(self)
780
+ d = self(denominator)
781
+ dd = other(denominator)
782
+ assert dd > 0
783
+ assert d is not infinity
784
+ if d < 0:
785
+ # The following may fail if denominator is not
786
+ # invertible in the domain, but we don't have a better
787
+ # option this generically.
788
+ return self.domain()(~denominator)
789
+
790
+ # We need nonnegative integers a and b such that
791
+ # a*n - b*d > 0 and a*nn - b*dd < 0
792
+ if nn == 0:
793
+ # the above becomes b != 0 and a/b > d/n
794
+ b = 1
795
+ a = (d/n + 1).floor()
796
+ else:
797
+ # Since n,nn,d,dd are all nonnegative this is essentially equivalent to
798
+ # a/b > d/n and b/a > nn/dd
799
+ # which is
800
+ # dd/nn > a/b > d/n
801
+ assert dd / nn > d / n
802
+ from sage.rings.continued_fraction import continued_fraction
803
+ ab_cf = []
804
+ dn_cf = continued_fraction(d / n)
805
+ ddnn_cf = continued_fraction(dd / nn)
806
+ for i, (x,y) in enumerate(zip(dn_cf, ddnn_cf)):
807
+ if x == y:
808
+ ab_cf.append(x)
809
+ elif x < y:
810
+ if y > x+1 or len(ddnn_cf) > i+1:
811
+ ab_cf.append(x+1)
812
+ else:
813
+ # the expansion of dd/nn is ending, so we can't append x+1
814
+ ab_cf.extend([x,1,1])
815
+ elif y < x:
816
+ if x > y+1 or len(dn_cf) > i+1:
817
+ ab_cf.append(y+1)
818
+ else:
819
+ ab_cf.extend([y,1,1])
820
+ ab = continued_fraction(ab_cf).value()
821
+ a,b = ab.numerator(), ab.denominator()
822
+
823
+ ret = self.domain()(numerator**a / denominator**b)
824
+ assert (self(ret) > 0)
825
+ assert (other(ret) < 0)
826
+ return ret
827
+
828
+ def _weakly_separating_element(self, other):
829
+ r"""
830
+ Return an element in the domain of this valuation which has
831
+ positive valuation with respect to this valuation and higher
832
+ valuation with respect to this valuation than with respect to
833
+ ``other``.
834
+
835
+ .. NOTE::
836
+
837
+ Overriding this method tends to be a nuisance as you need to
838
+ handle all possible types (as in Python type) of valuations.
839
+ This is essentially the same problem that you have when
840
+ implementing operators such as ``+`` or ``>=``. A sufficiently
841
+ fancy multimethod implementation could solve that here but
842
+ there is currently nothing like that in Sage/Python.
843
+
844
+ EXAMPLES::
845
+
846
+ sage: v2 = QQ.valuation(2)
847
+ sage: v3 = QQ.valuation(3)
848
+ sage: v2._weakly_separating_element(v3)
849
+ 2
850
+ """
851
+ ret = self.uniformizer()
852
+ if self(ret) > other(ret):
853
+ return ret
854
+ raise NotImplementedError("weakly separating element for %r and %r" % (self, other))
855
+
856
+ def shift(self, x, s):
857
+ r"""
858
+ Shift ``x`` in its expansion with respect to :meth:`uniformizer` by
859
+ ``s`` "digits".
860
+
861
+ For nonnegative ``s``, this just returns ``x`` multiplied by a
862
+ power of the uniformizer `\pi`.
863
+
864
+ For negative ``s``, it does the same but when not over a field, it
865
+ drops coefficients in the `\pi`-adic expansion which have negative
866
+ valuation.
867
+
868
+ EXAMPLES::
869
+
870
+ sage: v = ZZ.valuation(2)
871
+ sage: v.shift(1, 10)
872
+ 1024
873
+ sage: v.shift(11, -1)
874
+ 5
875
+
876
+ For some rings, there is no clear `\pi`-adic expansion. In this
877
+ case, this method performs negative shifts by iterated division by
878
+ the uniformizer and substraction of a lift of the reduction::
879
+
880
+ sage: R.<x> = ZZ[]
881
+ sage: v = ZZ.valuation(2)
882
+ sage: w = GaussValuation(R, v)
883
+ sage: w.shift(x, 1)
884
+ 2*x
885
+ sage: w.shift(2*x, -1)
886
+ x
887
+ sage: w.shift(x + 2*x^2, -1)
888
+ x^2
889
+ """
890
+ from sage.rings.integer_ring import ZZ
891
+ x = self.domain().coerce(x)
892
+ s = self.value_group()(s)
893
+ if s == 0:
894
+ return x
895
+
896
+ s = ZZ(s / self.value_group().gen())
897
+ if s > 0:
898
+ return x * self.uniformizer()**s
899
+ else: # s < 0
900
+ if ~self.uniformizer() in self.domain():
901
+ return self.domain()(x / self.uniformizer()**(-s))
902
+ else:
903
+ for i in range(-s):
904
+ if self(x) < 0:
905
+ raise NotImplementedError("cannot compute general shifts over non-fields which contain elements of negative valuation")
906
+ x -= self.lift(self.reduce(x))
907
+ x //= self.uniformizer()
908
+ return x
909
+
910
+ def simplify(self, x, error=None, force=False):
911
+ r"""
912
+ Return a simplified version of ``x``.
913
+
914
+ Produce an element which differs from ``x`` by an element of
915
+ valuation strictly greater than the valuation of ``x`` (or strictly
916
+ greater than ``error`` if set.)
917
+
918
+ If ``force`` is not set, then expensive simplifications may be avoided.
919
+
920
+ EXAMPLES::
921
+
922
+ sage: v = ZZ.valuation(2)
923
+ sage: v.simplify(6, force=True)
924
+ 2
925
+ sage: v.simplify(6, error=0, force=True)
926
+ 0
927
+ """
928
+ x = self.domain().coerce(x)
929
+
930
+ if error is not None and self(x) > error:
931
+ return self.domain().zero()
932
+ return x
933
+
934
+ def lower_bound(self, x):
935
+ r"""
936
+ Return a lower bound of this valuation at ``x``.
937
+
938
+ Use this method to get an approximation of the valuation of ``x``
939
+ when speed is more important than accuracy.
940
+
941
+ EXAMPLES::
942
+
943
+ sage: v = ZZ.valuation(2)
944
+ sage: v.lower_bound(2^10)
945
+ 10
946
+ """
947
+ return self(x)
948
+
949
+ def upper_bound(self, x):
950
+ r"""
951
+ Return an upper bound of this valuation at ``x``.
952
+
953
+ Use this method to get an approximation of the valuation of ``x``
954
+ when speed is more important than accuracy.
955
+
956
+ EXAMPLES::
957
+
958
+ sage: v = ZZ.valuation(2)
959
+ sage: v.upper_bound(2^10)
960
+ 10
961
+ """
962
+ return self(x)
963
+
964
+ def inverse(self, x, precision):
965
+ r"""
966
+ Return an approximate inverse of ``x``.
967
+
968
+ The element returned is such that the product differs from 1 by an
969
+ element of valuation at least ``precision``.
970
+
971
+ INPUT:
972
+
973
+ - ``x`` -- an element in the domain of this valuation
974
+
975
+ - ``precision`` -- a rational or infinity
976
+
977
+ EXAMPLES::
978
+
979
+ sage: v = ZZ.valuation(2)
980
+ sage: x = 3
981
+ sage: y = v.inverse(3, 2); y
982
+ 3
983
+ sage: x*y - 1
984
+ 8
985
+
986
+ This might not be possible for elements of positive valuation::
987
+
988
+ sage: v.inverse(2, 2)
989
+ Traceback (most recent call last):
990
+ ...
991
+ ValueError: element has no approximate inverse in this ring
992
+
993
+ Of course this always works over fields::
994
+
995
+ sage: v = QQ.valuation(2)
996
+ sage: v.inverse(2, 2)
997
+ 1/2
998
+ """
999
+ return x.inverse_of_unit()
1000
+
1001
+ def _relative_size(self, x):
1002
+ r"""
1003
+ Return an estimate on the coefficient size of ``x``.
1004
+
1005
+ The number returned is an estimate on the factor between the number of
1006
+ bits used by ``x`` and the minimal number of bits used by an element
1007
+ congruent to ``x``.
1008
+
1009
+ This is used by :meth:`simplify` to decide whether simplification of
1010
+ coefficients is going to lead to a significant shrinking of the
1011
+ coefficients of ``x``.
1012
+
1013
+ EXAMPLES::
1014
+
1015
+ sage: v = Qp(2).valuation()
1016
+ sage: v._relative_size(2)
1017
+ 1
1018
+
1019
+ Some valuations do not overwrite this method because simplification
1020
+ does not increase the speed of valuations, e.g., some `p`-adic
1021
+ valuations::
1022
+
1023
+ sage: v._relative_size(2**20)
1024
+ 1
1025
+ """
1026
+ return 1
1027
+
1028
+ def _test_is_negative_pseudo_valuation(self, **options):
1029
+ r"""
1030
+ Check that :meth:`is_negative_pseudo_valuation` works correctly.
1031
+
1032
+ TESTS::
1033
+
1034
+ sage: v = ZZ.valuation(3)
1035
+ sage: v._test_is_negative_pseudo_valuation()
1036
+ """
1037
+ tester = self._tester(**options)
1038
+
1039
+ if self.is_discrete_valuation():
1040
+ tester.assertFalse(self.is_negative_pseudo_valuation())
1041
+ return
1042
+
1043
+ if not self.is_negative_pseudo_valuation():
1044
+ X = self.domain().some_elements()
1045
+ for x in tester.some_elements(X):
1046
+ from sage.rings.infinity import infinity
1047
+ tester.assertNotEqual(self(x), -infinity)
1048
+
1049
+ def _test_bounds(self, **options):
1050
+ r"""
1051
+ Check that :meth:`lower_bound` and :meth:`upper_bound` work
1052
+ correctly.
1053
+
1054
+ TESTS::
1055
+
1056
+ sage: v = ZZ.valuation(3)
1057
+ sage: v._test_bounds()
1058
+ """
1059
+ tester = self._tester(**options)
1060
+
1061
+ X = self.domain().some_elements()
1062
+ for x in tester.some_elements(X):
1063
+ tester.assertGreaterEqual(self.upper_bound(x), self(x))
1064
+ tester.assertLessEqual(self.lower_bound(x), self(x))
1065
+
1066
+ def _test_simplify(self, **options):
1067
+ r"""
1068
+ Check that :meth:`simplify` works correctly.
1069
+
1070
+ TESTS::
1071
+
1072
+ sage: v = ZZ.valuation(3)
1073
+ sage: v._test_simplify()
1074
+ """
1075
+ tester = self._tester(**options)
1076
+
1077
+ try:
1078
+ self.residue_ring()
1079
+ has_residue_ring = True
1080
+ except NotImplementedError:
1081
+ # over non-fields (and especially polynomial rings over
1082
+ # non-fields) computation of the residue ring is often
1083
+ # difficult and not very interesting
1084
+ from sage.categories.fields import Fields
1085
+ if self.domain() not in Fields():
1086
+ return
1087
+ raise
1088
+
1089
+ X = self.domain().some_elements()
1090
+ for x in tester.some_elements(X):
1091
+ y = self.simplify(x)
1092
+ tester.assertEqual(self(x), self(y))
1093
+ if self(x) >= 0 and has_residue_ring:
1094
+ tester.assertEqual(self.reduce(x), self.reduce(y))
1095
+
1096
+ if self.is_trivial() and not self.is_discrete_valuation():
1097
+ return
1098
+
1099
+ S = self.value_group().some_elements()
1100
+ from itertools import product
1101
+ for x,s in tester.some_elements(product(X, S)):
1102
+ y = self.simplify(x, error=s)
1103
+ if self.domain().is_exact():
1104
+ tester.assertGreaterEqual(self(x-y), s)
1105
+ elif hasattr(y, 'precision_absolute'):
1106
+ tester.assertGreaterEqual(self(x-y), min(s, y.precision_absolute()))
1107
+
1108
+ def _test_shift(self, **options):
1109
+ r"""
1110
+ Check that :meth:`shift` works correctly.
1111
+
1112
+ TESTS::
1113
+
1114
+ sage: v = ZZ.valuation(3)
1115
+ sage: v._test_shift()
1116
+ """
1117
+ if self.is_trivial() and not self.is_discrete_valuation():
1118
+ return
1119
+
1120
+ try:
1121
+ self.residue_ring()
1122
+ except Exception:
1123
+ # it is not clear what a shift should be in this case
1124
+ return
1125
+
1126
+ tester = self._tester(**options)
1127
+ X = self.domain().some_elements()
1128
+ S = self.value_group().some_elements()
1129
+ from itertools import product
1130
+ for x,s in tester.some_elements(product(X, S)):
1131
+ if self(x) < 0 and ~self.uniformizer() not in self.domain():
1132
+ # it is not clear what a shift should be in this case
1133
+ continue
1134
+ y = self.shift(x, s)
1135
+ if s >= 0:
1136
+ tester.assertGreaterEqual(self(y),self(x))
1137
+ from sage.categories.fields import Fields
1138
+ if self.domain().is_exact() and self.domain() in Fields():
1139
+ # the shift here sometimes fails if elements implement
1140
+ # __floordiv__ incorrectly, see #23971
1141
+ tester.assertEqual(x, self.shift(y, -s))
1142
+
1143
+ def _test_scale(self, **options):
1144
+ r"""
1145
+ Check that :meth:`scale` works correctly.
1146
+
1147
+ TESTS::
1148
+
1149
+ sage: v = ZZ.valuation(3)
1150
+ sage: v._test_scale()
1151
+ """
1152
+ tester = self._tester(**options)
1153
+
1154
+ from sage.rings.rational_field import QQ
1155
+ from sage.rings.infinity import infinity
1156
+ from .trivial_valuation import TrivialValuation, TrivialPseudoValuation
1157
+
1158
+ tester.assertEqual(QQ(0)*self, TrivialValuation(self.domain()))
1159
+ tester.assertEqual(infinity*self, TrivialPseudoValuation(self.domain()))
1160
+
1161
+ for s in tester.some_elements(QQ.some_elements()):
1162
+ if s < 0:
1163
+ with tester.assertRaises(ValueError):
1164
+ s * self
1165
+ continue
1166
+ if s == 0:
1167
+ continue
1168
+
1169
+ scaled = s * self
1170
+
1171
+ tester.assertEqual(self.is_trivial(), scaled.is_trivial())
1172
+ if not self.is_trivial():
1173
+ tester.assertEqual(self.uniformizer(), scaled.uniformizer())
1174
+ tester.assertEqual(scaled(self.uniformizer()), s * self(self.uniformizer()))
1175
+ unscaled = scaled / s
1176
+ tester.assertEqual(self, unscaled)
1177
+
1178
+ def _test_add(self, **options):
1179
+ r"""
1180
+ Check that the (strict) triangle equality is satisfied for the
1181
+ valuation of this ring.
1182
+
1183
+ TESTS::
1184
+
1185
+ sage: v = ZZ.valuation(3)
1186
+ sage: v._test_add()
1187
+ """
1188
+ tester = self._tester(**options)
1189
+ S = self.domain().some_elements()
1190
+ from itertools import product
1191
+ for x, y in tester.some_elements(product(S, S)):
1192
+ tester.assertGreaterEqual(self(x + y), min(self(x), self(y)))
1193
+ if self(x) != self(y):
1194
+ tester.assertEqual(self(x + y), min(self(x), self(y)))
1195
+
1196
+ def _test_infinite_zero(self, **options):
1197
+ r"""
1198
+ Check that zero is sent to infinity.
1199
+
1200
+ TESTS::
1201
+
1202
+ sage: v = QQ.valuation(5)
1203
+ sage: v._test_infinite_zero()
1204
+ """
1205
+ tester = self._tester(**options)
1206
+ from sage.rings.infinity import infinity
1207
+ tester.assertEqual(self(self.domain().zero()), infinity)
1208
+
1209
+ def _test_mul(self, **options):
1210
+ r"""
1211
+ Check that multiplication translates to addition of valuations.
1212
+
1213
+ TESTS::
1214
+
1215
+ sage: v = QQ.valuation(5)
1216
+ sage: v._test_mul()
1217
+ """
1218
+ from sage.rings.infinity import infinity
1219
+ from itertools import product
1220
+ tester = self._tester(**options)
1221
+ S = self.domain().some_elements()
1222
+ infis = {infinity, -infinity}
1223
+
1224
+ for x, y in tester.some_elements(product(S, S)):
1225
+ if {Sx := self(x), Sy := self(y)} == infis:
1226
+ continue
1227
+ tester.assertEqual(self(x * y), Sx + Sy)
1228
+
1229
+ def _test_no_infinite_units(self, **options):
1230
+ r"""
1231
+ Check that no units are sent to infinity.
1232
+
1233
+ TESTS::
1234
+
1235
+ sage: v = QQ.valuation(5)
1236
+ sage: v._test_no_infinite_units()
1237
+
1238
+ As multiplication translates to addition, pseudo-valuations which
1239
+ send a unit to infinity are necessarily trivial::
1240
+
1241
+ sage: from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace
1242
+ sage: v = DiscretePseudoValuationSpace(QQ).an_element()
1243
+ sage: v(1)
1244
+ +Infinity
1245
+ sage: v.is_trivial()
1246
+ True
1247
+ """
1248
+ if not self.is_discrete_valuation() and self.is_trivial():
1249
+ return
1250
+ if self.is_negative_pseudo_valuation():
1251
+ return
1252
+
1253
+ from sage.rings.infinity import infinity
1254
+ tester = self._tester(**options)
1255
+ for x in tester.some_elements(self.domain().some_elements()):
1256
+ if self(x) is infinity:
1257
+ tester.assertFalse(x.is_unit())
1258
+
1259
+ def _test_value_group(self, **options):
1260
+ r"""
1261
+ Check correctness of the value group.
1262
+
1263
+ TESTS::
1264
+
1265
+ sage: v = QQ.valuation(5)
1266
+ sage: v._test_value_group()
1267
+ """
1268
+ from sage.rings.infinity import infinity
1269
+ tester = self._tester(**options)
1270
+ # check consistency of trivial valuations first
1271
+ if self.is_trivial():
1272
+ if self(self.domain().one()) is infinity:
1273
+ # a trivial pseudo-valuation that sends everything to infinity
1274
+ with tester.assertRaises(ValueError):
1275
+ self.value_group()
1276
+ return
1277
+
1278
+ # check that all valuations are in the value group
1279
+ for x in tester.some_elements(self.domain().some_elements()):
1280
+ if self(x) is not infinity and self(x) is not -infinity:
1281
+ tester.assertIn(self(x), self.value_group())
1282
+
1283
+ if not self.is_trivial():
1284
+ # check that the uniformizer generates the value group
1285
+ tester.assertEqual(self.value_group().gen(), self(self.uniformizer()))
1286
+
1287
+ def _test_value_semigroup(self, **options):
1288
+ r"""
1289
+ Check correctness of the value semigroup.
1290
+
1291
+ TESTS::
1292
+
1293
+ sage: v = QQ.valuation(5)
1294
+ sage: v._test_value_semigroup() # needs sage.geometry.polyhedron
1295
+ """
1296
+ tester = self._tester(**options)
1297
+
1298
+ if self.is_trivial() and not self.is_discrete_valuation():
1299
+ # the trivial pseudo-valuation does not have a value semigroup
1300
+ return
1301
+
1302
+ for s in tester.some_elements(self.value_semigroup().some_elements()):
1303
+ tester.assertIn(s, self.value_group())
1304
+
1305
+ def _test_element_with_valuation(self, **options):
1306
+ r"""
1307
+ Check correctness of :meth:`element_with_valuation`.
1308
+
1309
+ TESTS::
1310
+
1311
+ sage: v = QQ.valuation(5)
1312
+ sage: v._test_element_with_valuation() # needs sage.geometry.polyhedron
1313
+ """
1314
+ tester = self._tester(**options)
1315
+
1316
+ if self.is_trivial() and not self.is_discrete_valuation():
1317
+ # the trivial pseudo-valuation does not have a value semigroup
1318
+ return
1319
+
1320
+ for s in tester.some_elements(self.value_semigroup().some_elements()):
1321
+ tester.assertEqual(self(self.element_with_valuation(s)), s)
1322
+
1323
+ def _test_residue_ring(self, **options):
1324
+ r"""
1325
+ Check the correctness of residue rings.
1326
+
1327
+ TESTS::
1328
+
1329
+ sage: v = QQ.valuation(5)
1330
+ sage: v._test_residue_ring()
1331
+ """
1332
+ tester = self._tester(**options)
1333
+
1334
+ try:
1335
+ r = self.residue_ring()
1336
+ except NotImplementedError:
1337
+ # over non-fields (and especially polynomial rings over
1338
+ # non-fields) computation of the residue ring is often
1339
+ # difficult and not very interesting
1340
+ from sage.categories.fields import Fields
1341
+ if self.domain() not in Fields():
1342
+ return
1343
+ raise
1344
+
1345
+ if r.zero() == r.one():
1346
+ # residue ring is the zero rng
1347
+ tester.assertGreater(self(1), 0)
1348
+ return
1349
+
1350
+ c = self.residue_ring().characteristic()
1351
+ if c != 0:
1352
+ tester.assertGreater(self(c), 0)
1353
+
1354
+ def _test_reduce(self, **options):
1355
+ r"""
1356
+ Check the correctness of reductions.
1357
+
1358
+ TESTS::
1359
+
1360
+ sage: v = QQ.valuation(5)
1361
+ sage: v._test_reduce()
1362
+ """
1363
+ tester = self._tester(**options)
1364
+
1365
+ try:
1366
+ self.residue_ring()
1367
+ except NotImplementedError:
1368
+ # over non-fields (and especially polynomial rings over
1369
+ # non-fields) computation of the residue ring is often
1370
+ # difficult and not very interesting
1371
+ from sage.categories.fields import Fields
1372
+ if self.domain() not in Fields():
1373
+ return
1374
+ raise
1375
+
1376
+ for x in tester.some_elements(self.domain().some_elements()):
1377
+ if self(x) < 0:
1378
+ with tester.assertRaises((ValueError, ArithmeticError)):
1379
+ self.reduce(x)
1380
+ continue
1381
+ if self(x) == 0:
1382
+ y = self.reduce(x)
1383
+ tester.assertIn(y, self.residue_ring())
1384
+ tester.assertNotEqual(y, 0)
1385
+ if x.is_unit() and ~x in self.domain():
1386
+ tester.assertTrue(y.is_unit())
1387
+ tester.assertIn(~y, self.residue_ring())
1388
+ tester.assertEqual(~y, self.reduce(self.domain()(~x)))
1389
+ if self(x) > 0:
1390
+ tester.assertEqual(self.reduce(x), 0)
1391
+
1392
+ def _test_lift(self, **options):
1393
+ r"""
1394
+ Check the correctness of lifts.
1395
+
1396
+ TESTS::
1397
+
1398
+ sage: v = QQ.valuation(5)
1399
+ sage: v._test_lift()
1400
+ """
1401
+ tester = self._tester(**options)
1402
+
1403
+ try:
1404
+ self.residue_ring()
1405
+ except NotImplementedError:
1406
+ # over non-fields (and especially polynomial rings over
1407
+ # non-fields) computation of the residue ring is often
1408
+ # difficult and not very interesting
1409
+ from sage.categories.fields import Fields
1410
+ if self.domain() not in Fields():
1411
+ return
1412
+ raise
1413
+
1414
+ for X in tester.some_elements(self.residue_ring().some_elements()):
1415
+ x = self.lift(X)
1416
+ y = self.reduce(x)
1417
+ tester.assertEqual(X, y)
1418
+ if X != 0:
1419
+ tester.assertEqual(self(x), 0)
1420
+
1421
+ def _test_restriction(self, **options):
1422
+ r"""
1423
+ Check the correctness of reductions.
1424
+
1425
+ TESTS::
1426
+
1427
+ sage: v = QQ.valuation(5)
1428
+ sage: v._test_restriction()
1429
+ """
1430
+ tester = self._tester(**options)
1431
+
1432
+ tester.assertEqual(self.restriction(self.domain()), self)
1433
+
1434
+ def _test_extension(self, **options):
1435
+ r"""
1436
+ Check the correctness of extensions.
1437
+
1438
+ TESTS::
1439
+
1440
+ sage: v = QQ.valuation(5)
1441
+ sage: v._test_extension()
1442
+ """
1443
+ tester = self._tester(**options)
1444
+
1445
+ tester.assertEqual(self.extension(self.domain()), self)
1446
+ tester.assertEqual(self.extensions(self.domain()), [self])
1447
+
1448
+ def _test_change_domain(self, **options):
1449
+ r"""
1450
+ Check the correctness of :meth:`change_domain`.
1451
+
1452
+ TESTS::
1453
+
1454
+ sage: v = QQ.valuation(5)
1455
+ sage: v._test_change_domain()
1456
+ """
1457
+ tester = self._tester(**options)
1458
+
1459
+ tester.assertEqual(self.change_domain(self.domain()), self)
1460
+
1461
+ def _test_no_infinite_nonzero(self, **options):
1462
+ r"""
1463
+ Check that only zero is sent to infinity.
1464
+
1465
+ TESTS::
1466
+
1467
+ sage: v = QQ.valuation(5)
1468
+ sage: v._test_no_infinite_nonzero()
1469
+ """
1470
+ if not self.is_discrete_valuation():
1471
+ return
1472
+
1473
+ from sage.rings.infinity import infinity
1474
+ tester = self._tester(**options)
1475
+ for x in tester.some_elements(self.domain().some_elements()):
1476
+ if self(x) is infinity:
1477
+ tester.assertEqual(x, 0)
1478
+
1479
+ def _test_residue_field(self, **options):
1480
+ r"""
1481
+ Check the correctness of residue fields.
1482
+
1483
+ TESTS::
1484
+
1485
+ sage: v = QQ.valuation(5)
1486
+ sage: v._test_residue_field()
1487
+ """
1488
+ if not self.is_discrete_valuation():
1489
+ return
1490
+
1491
+ tester = self._tester(**options)
1492
+ try:
1493
+ self.residue_field()
1494
+ except ValueError:
1495
+ from sage.categories.fields import Fields
1496
+ # a discrete valuation on a field has a residue field
1497
+ tester.assertNotIn(self.domain(), Fields())
1498
+ return
1499
+ except NotImplementedError:
1500
+ # over non-fields (and especially polynomial rings over
1501
+ # non-fields) computation of the residue ring is often
1502
+ # difficult and not very interesting
1503
+ from sage.categories.fields import Fields
1504
+ if self.domain() not in Fields():
1505
+ return
1506
+ raise
1507
+
1508
+ try:
1509
+ r = self.residue_ring()
1510
+ except Exception:
1511
+ # If the residue ring cannot be constructed for some reason
1512
+ # then we do not check its relation to the residue field.
1513
+ # _test_residue_ring() is responsible for checking whether the
1514
+ # residue ring should be constructible or not.
1515
+ pass
1516
+ else:
1517
+ # the residue ring must coerce into the residue field
1518
+ tester.assertTrue(self.residue_field().has_coerce_map_from(r))
1519
+
1520
+ c = self.residue_field().characteristic()
1521
+ if c != 0:
1522
+ tester.assertGreater(self(c), 0)
1523
+
1524
+ def _test_ge(self, **options):
1525
+ r"""
1526
+ Check the correctness of the ``>=`` operator.
1527
+
1528
+ TESTS::
1529
+
1530
+ sage: v = QQ.valuation(5)
1531
+ sage: v._test_ge()
1532
+ """
1533
+ tester = self._tester(**options)
1534
+
1535
+ tester.assertGreaterEqual(self, self)
1536
+
1537
+ if self.is_negative_pseudo_valuation():
1538
+ return
1539
+
1540
+ from .trivial_valuation import TrivialPseudoValuation, TrivialValuation
1541
+ tester.assertGreaterEqual(self, TrivialValuation(self.domain()))
1542
+ tester.assertLessEqual(self, TrivialPseudoValuation(self.domain()))
1543
+
1544
+ def _test_le(self, **options):
1545
+ r"""
1546
+ Check the correctness of the ``<=`` operator.
1547
+
1548
+ TESTS::
1549
+
1550
+ sage: v = QQ.valuation(5)
1551
+ sage: v._test_le()
1552
+ """
1553
+ tester = self._tester(**options)
1554
+
1555
+ tester.assertGreaterEqual(self, self)
1556
+
1557
+ if self.is_negative_pseudo_valuation():
1558
+ return
1559
+
1560
+ from .trivial_valuation import TrivialPseudoValuation, TrivialValuation
1561
+ tester.assertLessEqual(TrivialValuation(self.domain()), self)
1562
+ tester.assertGreaterEqual(TrivialPseudoValuation(self.domain()), self)
1563
+
1564
+ def _test_inverse(self, **options):
1565
+ r"""
1566
+ Check the correctness of :meth:`inverse`.
1567
+
1568
+ TESTS::
1569
+
1570
+ sage: v = QQ.valuation(5)
1571
+ sage: v._test_inverse()
1572
+ """
1573
+ tester = self._tester(**options)
1574
+
1575
+ for x in tester.some_elements(self.domain().some_elements()):
1576
+ from sage.rings.infinity import infinity
1577
+ for prec in (0, 1, 42, infinity):
1578
+ try:
1579
+ y = self.inverse(x, prec)
1580
+ except ArithmeticError: # Inverse does not exist
1581
+ continue
1582
+ except ValueError:
1583
+ if prec is not infinity:
1584
+ tester.assertNotEqual(self(x), 0)
1585
+ tester.assertFalse(x.is_unit())
1586
+ continue
1587
+
1588
+ tester.assertIs(y.parent(), self.domain())
1589
+ if self.domain().is_exact():
1590
+ tester.assertGreaterEqual(self(x * y - 1), prec)
1591
+
1592
+
1593
+ class ScaleAction(Action):
1594
+ r"""
1595
+ Action of integers, rationals and the infinity ring on valuations by
1596
+ scaling it.
1597
+
1598
+ EXAMPLES::
1599
+
1600
+ sage: v = QQ.valuation(5)
1601
+ sage: from operator import mul
1602
+ sage: v.parent().get_action(ZZ, mul, self_on_left=False)
1603
+ Left action by Integer Ring on Discrete pseudo-valuations on Rational Field
1604
+ """
1605
+ def _act_(self, s, v):
1606
+ r"""
1607
+ Let ``s`` act on ``v``.
1608
+
1609
+ EXAMPLES::
1610
+
1611
+ sage: v = QQ.valuation(5)
1612
+ sage: 3 * v # indirect doctest
1613
+ 3 * 5-adic valuation
1614
+ """
1615
+ return v.scale(s)