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.
- PARIKernel/__init__.py +2 -0
- PARIKernel/__main__.py +5 -0
- PARIKernel/io.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/io.pxd +7 -0
- PARIKernel/io.pyx +84 -0
- PARIKernel/kernel.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/kernel.pyx +260 -0
- PARIKernel/paridecl.pxd +95 -0
- PARIKernel/svg.cpython-314-x86_64-linux-musl.so +0 -0
- PARIKernel/svg.pyx +52 -0
- cypari2/__init__.py +8 -0
- cypari2/auto_paridecl.pxd +1070 -0
- cypari2/closure.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/closure.pxd +5 -0
- cypari2/closure.pyx +246 -0
- cypari2/convert.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/convert.pxd +80 -0
- cypari2/convert.pyx +613 -0
- cypari2/custom_block.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/custom_block.pyx +30 -0
- cypari2/cypari.h +13 -0
- cypari2/gen.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/gen.pxd +69 -0
- cypari2/gen.pyx +4819 -0
- cypari2/handle_error.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/handle_error.pxd +7 -0
- cypari2/handle_error.pyx +232 -0
- cypari2/pari_instance.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/pari_instance.pxd +27 -0
- cypari2/pari_instance.pyx +1438 -0
- cypari2/paridecl.pxd +5353 -0
- cypari2/paripriv.pxd +34 -0
- cypari2/pycore_long.h +98 -0
- cypari2/pycore_long.pxd +9 -0
- cypari2/stack.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/stack.pxd +27 -0
- cypari2/stack.pyx +278 -0
- cypari2/string_utils.cpython-314-x86_64-linux-musl.so +0 -0
- cypari2/string_utils.pxd +29 -0
- cypari2/string_utils.pyx +65 -0
- cypari2/types.pxd +147 -0
- passagemath_pari-10.6.32.data/data/etc/jupyter/nbconfig/notebook.d/gp-mode.json +5 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.js +28 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/kernel.json +6 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/pari_jupyter/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/kernel.json +13 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-32x32.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-64x64.png +0 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/kernels/xeus-gp/logo-svg.svg +75 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/gp.js +284 -0
- passagemath_pari-10.6.32.data/data/share/jupyter/nbextensions/gp-mode/main.js +15 -0
- passagemath_pari-10.6.32.dist-info/METADATA +209 -0
- passagemath_pari-10.6.32.dist-info/RECORD +331 -0
- passagemath_pari-10.6.32.dist-info/WHEEL +5 -0
- passagemath_pari-10.6.32.dist-info/top_level.txt +4 -0
- passagemath_pari.libs/libcrypto-f04afe95.so.3 +0 -0
- passagemath_pari.libs/libflint-fd6f12fc.so.21.0.0 +0 -0
- passagemath_pari.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_pari.libs/libgf2x-9e30c3e3.so.3.0.0 +0 -0
- passagemath_pari.libs/libgfortran-2c33b284.so.5.0.0 +0 -0
- passagemath_pari.libs/libgivaro-9a94c711.so.9.2.1 +0 -0
- passagemath_pari.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_pari.libs/libgmpxx-9e08595c.so.4.7.0 +0 -0
- passagemath_pari.libs/libgsl-42cda06f.so.28.0.0 +0 -0
- passagemath_pari.libs/libmpfr-aaecbfc0.so.6.2.1 +0 -0
- passagemath_pari.libs/libncursesw-9c9e32c3.so.6.5 +0 -0
- passagemath_pari.libs/libntl-26885ca2.so.44.0.1 +0 -0
- passagemath_pari.libs/libopenblasp-r0-905cb27d.3.29.so +0 -0
- passagemath_pari.libs/libpari-gmp-tls-f31f908f.so.2.17.2 +0 -0
- passagemath_pari.libs/libquadmath-bb76a5fc.so.0.0.0 +0 -0
- passagemath_pari.libs/libreadline-06542304.so.8.2 +0 -0
- passagemath_pari.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- passagemath_pari.libs/libuuid-f3770415.so.1.3.0 +0 -0
- passagemath_pari.libs/libxeus-735780ff.so.13.1.0 +0 -0
- passagemath_pari.libs/libxeus-zmq-c68577b4.so.6.0.1 +0 -0
- passagemath_pari.libs/libzmq-1ba9a3da.so.5.2.5 +0 -0
- sage/all__sagemath_pari.py +26 -0
- sage/databases/all__sagemath_pari.py +7 -0
- sage/databases/conway.py +274 -0
- sage/ext/all__sagemath_pari.py +1 -0
- sage/ext/memory.cpython-314-x86_64-linux-musl.so +0 -0
- sage/ext/memory.pyx +98 -0
- sage/ext_data/pari/buzzard/DimensionSk.g +286 -0
- sage/ext_data/pari/buzzard/Tpprog.g +179 -0
- sage/ext_data/pari/buzzard/genusn.g +129 -0
- sage/ext_data/pari/dokchitser/computel.gp +740 -0
- sage/ext_data/pari/dokchitser/computel.gp.template +740 -0
- sage/ext_data/pari/dokchitser/ex-bsw +43 -0
- sage/ext_data/pari/dokchitser/ex-chgen +48 -0
- sage/ext_data/pari/dokchitser/ex-chqua +37 -0
- sage/ext_data/pari/dokchitser/ex-delta +35 -0
- sage/ext_data/pari/dokchitser/ex-eisen +30 -0
- sage/ext_data/pari/dokchitser/ex-gen2 +38 -0
- sage/ext_data/pari/dokchitser/ex-gen3 +49 -0
- sage/ext_data/pari/dokchitser/ex-gen4 +54 -0
- sage/ext_data/pari/dokchitser/ex-nf +48 -0
- sage/ext_data/pari/dokchitser/ex-shin +50 -0
- sage/ext_data/pari/dokchitser/ex-tau2 +30 -0
- sage/ext_data/pari/dokchitser/ex-zeta +27 -0
- sage/ext_data/pari/dokchitser/ex-zeta2 +47 -0
- sage/ext_data/pari/dokchitser/testall +13 -0
- sage/ext_data/pari/simon/ell.gp +2129 -0
- sage/ext_data/pari/simon/ellQ.gp +2151 -0
- sage/ext_data/pari/simon/ellcommon.gp +126 -0
- sage/ext_data/pari/simon/qfsolve.gp +722 -0
- sage/ext_data/pari/simon/resultant3.gp +306 -0
- sage/groups/all__sagemath_pari.py +3 -0
- sage/groups/pari_group.py +175 -0
- sage/interfaces/all__sagemath_pari.py +1 -0
- sage/interfaces/genus2reduction.py +464 -0
- sage/interfaces/gp.py +1114 -0
- sage/libs/all__sagemath_pari.py +2 -0
- sage/libs/linkages/__init__.py +1 -0
- sage/libs/linkages/padics/API.pxi +617 -0
- sage/libs/linkages/padics/Polynomial_ram.pxi +388 -0
- sage/libs/linkages/padics/Polynomial_shared.pxi +554 -0
- sage/libs/linkages/padics/__init__.py +1 -0
- sage/libs/linkages/padics/fmpz_poly_unram.pxi +869 -0
- sage/libs/linkages/padics/mpz.pxi +691 -0
- sage/libs/linkages/padics/relaxed/API.pxi +518 -0
- sage/libs/linkages/padics/relaxed/__init__.py +1 -0
- sage/libs/linkages/padics/relaxed/flint.pxi +543 -0
- sage/libs/linkages/padics/unram_shared.pxi +247 -0
- sage/libs/pari/__init__.py +210 -0
- sage/libs/pari/all.py +5 -0
- sage/libs/pari/convert_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_flint.pxd +14 -0
- sage/libs/pari/convert_flint.pyx +159 -0
- sage/libs/pari/convert_gmp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_gmp.pxd +14 -0
- sage/libs/pari/convert_gmp.pyx +210 -0
- sage/libs/pari/convert_sage.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage.pxd +16 -0
- sage/libs/pari/convert_sage.pyx +588 -0
- sage/libs/pari/convert_sage_complex_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_complex_double.pxd +14 -0
- sage/libs/pari/convert_sage_complex_double.pyx +132 -0
- sage/libs/pari/convert_sage_matrix.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_matrix.pyx +106 -0
- sage/libs/pari/convert_sage_real_double.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_double.pxd +5 -0
- sage/libs/pari/convert_sage_real_double.pyx +14 -0
- sage/libs/pari/convert_sage_real_mpfr.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/convert_sage_real_mpfr.pxd +7 -0
- sage/libs/pari/convert_sage_real_mpfr.pyx +108 -0
- sage/libs/pari/misc.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/pari/misc.pxd +4 -0
- sage/libs/pari/misc.pyx +26 -0
- sage/libs/pari/tests.py +1848 -0
- sage/matrix/all__sagemath_pari.py +1 -0
- sage/matrix/matrix_integer_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_integer_pari.pyx +187 -0
- sage/matrix/matrix_rational_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/matrix/matrix_rational_pari.pyx +160 -0
- sage/quadratic_forms/all__sagemath_pari.py +10 -0
- sage/quadratic_forms/genera/all.py +9 -0
- sage/quadratic_forms/genera/genus.py +3506 -0
- sage/quadratic_forms/genera/normal_form.py +1519 -0
- sage/quadratic_forms/genera/spinor_genus.py +243 -0
- sage/quadratic_forms/qfsolve.py +255 -0
- sage/quadratic_forms/quadratic_form__automorphisms.py +427 -0
- sage/quadratic_forms/quadratic_form__genus.py +141 -0
- sage/quadratic_forms/quadratic_form__local_density_interfaces.py +140 -0
- sage/quadratic_forms/quadratic_form__local_normal_form.py +421 -0
- sage/quadratic_forms/quadratic_form__local_representation_conditions.py +889 -0
- sage/quadratic_forms/quadratic_form__mass.py +69 -0
- sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +663 -0
- sage/quadratic_forms/quadratic_form__mass__Siegel_densities.py +373 -0
- sage/quadratic_forms/quadratic_form__siegel_product.py +198 -0
- sage/quadratic_forms/special_values.py +323 -0
- sage/rings/all__sagemath_pari.py +15 -0
- sage/rings/factorint_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/factorint_pari.pyx +80 -0
- sage/rings/finite_rings/all__sagemath_pari.py +1 -0
- sage/rings/finite_rings/element_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_givaro.pxd +91 -0
- sage/rings/finite_rings/element_givaro.pyx +1769 -0
- sage/rings/finite_rings/element_ntl_gf2e.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_ntl_gf2e.pxd +22 -0
- sage/rings/finite_rings/element_ntl_gf2e.pyx +1333 -0
- sage/rings/finite_rings/element_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/element_pari_ffelt.pxd +13 -0
- sage/rings/finite_rings/element_pari_ffelt.pyx +1441 -0
- sage/rings/finite_rings/finite_field_givaro.py +612 -0
- sage/rings/finite_rings/finite_field_pari_ffelt.py +238 -0
- sage/rings/finite_rings/hom_finite_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pxd +28 -0
- sage/rings/finite_rings/hom_finite_field_givaro.pyx +280 -0
- sage/rings/finite_rings/residue_field_givaro.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_givaro.pyx +133 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/finite_rings/residue_field_pari_ffelt.pyx +128 -0
- sage/rings/function_field/all__sagemath_pari.py +1 -0
- sage/rings/function_field/valuation.py +1450 -0
- sage/rings/function_field/valuation_ring.py +212 -0
- sage/rings/number_field/all__sagemath_pari.py +14 -0
- sage/rings/number_field/totallyreal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal.pyx +509 -0
- sage/rings/number_field/totallyreal_data.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/number_field/totallyreal_data.pxd +26 -0
- sage/rings/number_field/totallyreal_data.pyx +928 -0
- sage/rings/number_field/totallyreal_phc.py +144 -0
- sage/rings/number_field/totallyreal_rel.py +1018 -0
- sage/rings/padics/CA_template.pxi +1847 -0
- sage/rings/padics/CA_template_header.pxi +50 -0
- sage/rings/padics/CR_template.pxi +2563 -0
- sage/rings/padics/CR_template_header.pxi +57 -0
- sage/rings/padics/FM_template.pxi +1575 -0
- sage/rings/padics/FM_template_header.pxi +50 -0
- sage/rings/padics/FP_template.pxi +2176 -0
- sage/rings/padics/FP_template_header.pxi +57 -0
- sage/rings/padics/all.py +3 -0
- sage/rings/padics/all__sagemath_pari.py +11 -0
- sage/rings/padics/common_conversion.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/common_conversion.pxd +15 -0
- sage/rings/padics/common_conversion.pyx +508 -0
- sage/rings/padics/eisenstein_extension_generic.py +232 -0
- sage/rings/padics/factory.py +3623 -0
- sage/rings/padics/generic_nodes.py +1615 -0
- sage/rings/padics/lattice_precision.py +2889 -0
- sage/rings/padics/morphism.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/morphism.pxd +11 -0
- sage/rings/padics/morphism.pyx +366 -0
- sage/rings/padics/padic_base_generic.py +467 -0
- sage/rings/padics/padic_base_leaves.py +1235 -0
- sage/rings/padics/padic_capped_absolute_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_absolute_element.pxd +15 -0
- sage/rings/padics/padic_capped_absolute_element.pyx +520 -0
- sage/rings/padics/padic_capped_relative_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_capped_relative_element.pxd +14 -0
- sage/rings/padics/padic_capped_relative_element.pyx +614 -0
- sage/rings/padics/padic_extension_generic.py +990 -0
- sage/rings/padics/padic_extension_leaves.py +738 -0
- sage/rings/padics/padic_fixed_mod_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_fixed_mod_element.pxd +15 -0
- sage/rings/padics/padic_fixed_mod_element.pyx +584 -0
- sage/rings/padics/padic_floating_point_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_floating_point_element.pxd +14 -0
- sage/rings/padics/padic_floating_point_element.pyx +447 -0
- sage/rings/padics/padic_generic_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_generic_element.pxd +48 -0
- sage/rings/padics/padic_generic_element.pyx +4642 -0
- sage/rings/padics/padic_lattice_element.py +1342 -0
- sage/rings/padics/padic_printing.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_printing.pxd +38 -0
- sage/rings/padics/padic_printing.pyx +1505 -0
- sage/rings/padics/padic_relaxed_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_element.pxd +56 -0
- sage/rings/padics/padic_relaxed_element.pyx +18 -0
- sage/rings/padics/padic_relaxed_errors.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/padic_relaxed_errors.pxd +11 -0
- sage/rings/padics/padic_relaxed_errors.pyx +71 -0
- sage/rings/padics/padic_template_element.pxi +1212 -0
- sage/rings/padics/padic_template_element_header.pxi +50 -0
- sage/rings/padics/padic_valuation.py +1423 -0
- sage/rings/padics/pow_computer_flint.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_flint.pxd +38 -0
- sage/rings/padics/pow_computer_flint.pyx +641 -0
- sage/rings/padics/pow_computer_relative.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/pow_computer_relative.pxd +29 -0
- sage/rings/padics/pow_computer_relative.pyx +415 -0
- sage/rings/padics/qadic_flint_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CA.pxd +21 -0
- sage/rings/padics/qadic_flint_CA.pyx +130 -0
- sage/rings/padics/qadic_flint_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_CR.pxd +13 -0
- sage/rings/padics/qadic_flint_CR.pyx +172 -0
- sage/rings/padics/qadic_flint_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FM.pxd +14 -0
- sage/rings/padics/qadic_flint_FM.pyx +111 -0
- sage/rings/padics/qadic_flint_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/qadic_flint_FP.pxd +12 -0
- sage/rings/padics/qadic_flint_FP.pyx +165 -0
- sage/rings/padics/relative_extension_leaves.py +429 -0
- sage/rings/padics/relative_ramified_CA.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CA.pxd +9 -0
- sage/rings/padics/relative_ramified_CA.pyx +33 -0
- sage/rings/padics/relative_ramified_CR.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_CR.pxd +8 -0
- sage/rings/padics/relative_ramified_CR.pyx +33 -0
- sage/rings/padics/relative_ramified_FM.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FM.pxd +9 -0
- sage/rings/padics/relative_ramified_FM.pyx +33 -0
- sage/rings/padics/relative_ramified_FP.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/padics/relative_ramified_FP.pxd +8 -0
- sage/rings/padics/relative_ramified_FP.pyx +33 -0
- sage/rings/padics/relaxed_template.pxi +4229 -0
- sage/rings/padics/relaxed_template_header.pxi +160 -0
- sage/rings/padics/tests.py +35 -0
- sage/rings/padics/tutorial.py +341 -0
- sage/rings/padics/unramified_extension_generic.py +335 -0
- sage/rings/padics/witt_vector.py +917 -0
- sage/rings/padics/witt_vector_ring.py +934 -0
- sage/rings/pari_ring.py +235 -0
- sage/rings/polynomial/all__sagemath_pari.py +1 -0
- sage/rings/polynomial/padics/all.py +1 -0
- sage/rings/polynomial/padics/polynomial_padic.py +360 -0
- sage/rings/polynomial/padics/polynomial_padic_capped_relative_dense.py +1324 -0
- sage/rings/polynomial/padics/polynomial_padic_flat.py +72 -0
- sage/rings/power_series_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/power_series_pari.pxd +6 -0
- sage/rings/power_series_pari.pyx +934 -0
- sage/rings/tate_algebra.py +1282 -0
- sage/rings/tate_algebra_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_element.pxd +49 -0
- sage/rings/tate_algebra_element.pyx +3464 -0
- sage/rings/tate_algebra_ideal.cpython-314-x86_64-linux-musl.so +0 -0
- sage/rings/tate_algebra_ideal.pxd +7 -0
- sage/rings/tate_algebra_ideal.pyx +1307 -0
- sage/rings/valuation/all.py +7 -0
- sage/rings/valuation/augmented_valuation.py +2118 -0
- sage/rings/valuation/developing_valuation.py +362 -0
- sage/rings/valuation/gauss_valuation.py +812 -0
- sage/rings/valuation/inductive_valuation.py +1686 -0
- sage/rings/valuation/limit_valuation.py +946 -0
- sage/rings/valuation/mapped_valuation.py +656 -0
- sage/rings/valuation/scaled_valuation.py +322 -0
- sage/rings/valuation/trivial_valuation.py +382 -0
- sage/rings/valuation/valuation.py +1119 -0
- sage/rings/valuation/valuation_space.py +1615 -0
- sage/rings/valuation/valuations_catalog.py +10 -0
- sage/rings/valuation/value_group.py +697 -0
- sage/schemes/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/all__sagemath_pari.py +1 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/elliptic_curves/descent_two_isogeny_pari.pyx +46 -0
- sage_wheels/bin/gp +0 -0
- sage_wheels/bin/gp2c +0 -0
- sage_wheels/bin/gp2c-run +57 -0
- sage_wheels/bin/xeus-gp +0 -0
- sage_wheels/share/gp2c/func.dsc +18414 -0
|
@@ -0,0 +1,4229 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
# sage.doctest: needs sage.libs.flint
|
|
3
|
+
r"""
|
|
4
|
+
Template for relaxed `p`-adic rings and fields.
|
|
5
|
+
|
|
6
|
+
In order to use this template you need to write a linkage file and
|
|
7
|
+
gluing file.
|
|
8
|
+
|
|
9
|
+
The linkage file implements a common API that is then used in the
|
|
10
|
+
class FMElement defined here.
|
|
11
|
+
See sage/libs/linkages/padics/relaxed/API.pxi for the functions needed.
|
|
12
|
+
|
|
13
|
+
The gluing file does the following:
|
|
14
|
+
- ctypedef's ``cdigit``, ``cdigit_ptr``, ``celement`` and ``randgen``
|
|
15
|
+
to be the appropriate types
|
|
16
|
+
- includes the linkage file
|
|
17
|
+
- includes this template
|
|
18
|
+
- defines classes inheriting for classes defined in this file,
|
|
19
|
+
and implements any desired extra methods
|
|
20
|
+
See padic_relaxed_element.pxd and padic_relaxed_element.pyx for an example.
|
|
21
|
+
|
|
22
|
+
AUTHOR:
|
|
23
|
+
|
|
24
|
+
- Xavier Caruso (2021-02): initial version
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# ****************************************************************************
|
|
28
|
+
# Copyright (C) 2021 Xavier Caruso <xavier.caruso@normalesup.org>
|
|
29
|
+
#
|
|
30
|
+
# This program is free software: you can redistribute it and/or modify
|
|
31
|
+
# it under the terms of the GNU General Public License as published by
|
|
32
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
33
|
+
# (at your option) any later version.
|
|
34
|
+
# http://www.gnu.org/licenses/
|
|
35
|
+
# ****************************************************************************
|
|
36
|
+
|
|
37
|
+
import re
|
|
38
|
+
from sage.misc import persist
|
|
39
|
+
|
|
40
|
+
from libc.stdlib cimport malloc, free
|
|
41
|
+
from sage.libs.gmp.mpz cimport mpz_sizeinbase, mpz_tstbit
|
|
42
|
+
|
|
43
|
+
from sage.structure.element import coerce_binop
|
|
44
|
+
from sage.structure.element cimport have_same_parent
|
|
45
|
+
from sage.structure.coerce cimport coercion_model
|
|
46
|
+
from sage.misc.prandom import randint
|
|
47
|
+
|
|
48
|
+
from sage.rings.integer_ring import ZZ
|
|
49
|
+
from sage.rings.integer cimport Integer
|
|
50
|
+
from sage.rings.infinity import Infinity
|
|
51
|
+
|
|
52
|
+
from sage.rings.padics.pow_computer cimport PowComputer_class
|
|
53
|
+
from sage.rings.padics.padic_generic_element cimport pAdicGenericElement
|
|
54
|
+
from sage.rings.padics.precision_error import PrecisionError
|
|
55
|
+
from sage.rings.padics.padic_relaxed_errors cimport *
|
|
56
|
+
from sage.rings.padics.padic_relaxed_errors import raise_error
|
|
57
|
+
|
|
58
|
+
cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) - 1
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
cdef cdigit tmp_digit
|
|
62
|
+
cdef celement tmp_poly
|
|
63
|
+
digit_init(tmp_digit)
|
|
64
|
+
element_init(tmp_poly)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
cdef class RelaxedElement(pAdicGenericElement):
|
|
68
|
+
r"""
|
|
69
|
+
Template class for relaxed `p`-adic elements.
|
|
70
|
+
|
|
71
|
+
EXAMPLES:
|
|
72
|
+
|
|
73
|
+
sage: from sage.rings.padics.padic_relaxed_element import RelaxedElement
|
|
74
|
+
sage: R = ZpER(5)
|
|
75
|
+
sage: a = R(1)
|
|
76
|
+
sage: isinstance(a, RelaxedElement)
|
|
77
|
+
True
|
|
78
|
+
"""
|
|
79
|
+
def __init__(self, parent):
|
|
80
|
+
r"""
|
|
81
|
+
Initialize this element.
|
|
82
|
+
|
|
83
|
+
TESTS::
|
|
84
|
+
|
|
85
|
+
sage: R = ZpER(5)
|
|
86
|
+
sage: a = R(1/2) # indirect doctest
|
|
87
|
+
sage: TestSuite(a).run()
|
|
88
|
+
"""
|
|
89
|
+
pAdicGenericElement.__init__(self, parent)
|
|
90
|
+
self.prime_pow = <PowComputer_class>self._parent.prime_pow
|
|
91
|
+
self._valuation = 0
|
|
92
|
+
self._precrel = 0
|
|
93
|
+
self._precbound = maxordp
|
|
94
|
+
|
|
95
|
+
def __reduce__(self):
|
|
96
|
+
r"""
|
|
97
|
+
Return a tuple of a function and data that can be used to unpickle
|
|
98
|
+
this element.
|
|
99
|
+
|
|
100
|
+
TESTS::
|
|
101
|
+
|
|
102
|
+
sage: R = ZpER(5)
|
|
103
|
+
sage: a = R(0)
|
|
104
|
+
sage: loads(dumps(a)) == a
|
|
105
|
+
True
|
|
106
|
+
"""
|
|
107
|
+
raise NotImplementedError("must be implemented in subclasses")
|
|
108
|
+
|
|
109
|
+
cpdef bint _is_base_elt(self, p) except -1:
|
|
110
|
+
r"""
|
|
111
|
+
Return ``True`` if this element is an element of Zp or Qp (rather than
|
|
112
|
+
an extension).
|
|
113
|
+
|
|
114
|
+
INPUT:
|
|
115
|
+
|
|
116
|
+
- ``p`` -- a prime, which is compared with the parent of this element
|
|
117
|
+
|
|
118
|
+
EXAMPLES::
|
|
119
|
+
|
|
120
|
+
sage: a = ZpER(5)(3)
|
|
121
|
+
sage: a._is_base_elt(5)
|
|
122
|
+
True
|
|
123
|
+
sage: a._is_base_elt(17)
|
|
124
|
+
False
|
|
125
|
+
"""
|
|
126
|
+
return p == self._parent.prime()
|
|
127
|
+
|
|
128
|
+
cdef cdigit_ptr _getdigit_relative(self, long i) noexcept:
|
|
129
|
+
r"""
|
|
130
|
+
Return a pointer on the `i`-th significant digit of this number.
|
|
131
|
+
|
|
132
|
+
.. NOTE::
|
|
133
|
+
|
|
134
|
+
This function does not check that the requested digit
|
|
135
|
+
has been already computed.
|
|
136
|
+
|
|
137
|
+
INPUT:
|
|
138
|
+
|
|
139
|
+
- ``i`` -- positive integer
|
|
140
|
+
"""
|
|
141
|
+
pass
|
|
142
|
+
|
|
143
|
+
cdef cdigit_ptr _getdigit_absolute(self, long i) noexcept:
|
|
144
|
+
r"""
|
|
145
|
+
Return a pointer on the digit in position `i` of
|
|
146
|
+
this number.
|
|
147
|
+
|
|
148
|
+
.. NOTE::
|
|
149
|
+
|
|
150
|
+
This function do not check that the requested digit
|
|
151
|
+
has been already computed.
|
|
152
|
+
|
|
153
|
+
INPUT:
|
|
154
|
+
|
|
155
|
+
- ``i`` -- integer
|
|
156
|
+
"""
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
cdef void _getslice_relative(self, celement slice, long start, long length) noexcept:
|
|
160
|
+
r"""
|
|
161
|
+
Select a slice of the digits of this number.
|
|
162
|
+
|
|
163
|
+
INPUT:
|
|
164
|
+
|
|
165
|
+
- ``slice`` -- a ``celement`` to store the slice
|
|
166
|
+
|
|
167
|
+
- ``start`` -- positive integer; the starting position of the slice
|
|
168
|
+
in relative precision
|
|
169
|
+
|
|
170
|
+
- ``length`` -- positive integer; the length of the slice
|
|
171
|
+
|
|
172
|
+
.. NOTE::
|
|
173
|
+
|
|
174
|
+
This methods only sets up a pointer to the requested slice
|
|
175
|
+
(the slice is not copied). Hence any future modification
|
|
176
|
+
of the slice ``slice`` will affect this number.
|
|
177
|
+
"""
|
|
178
|
+
pass
|
|
179
|
+
|
|
180
|
+
cdef int _next_c(self) noexcept:
|
|
181
|
+
r"""
|
|
182
|
+
Compute the next digit of this number.
|
|
183
|
+
|
|
184
|
+
OUTPUT: an error code which is a superposition of the following:
|
|
185
|
+
|
|
186
|
+
- ``0`` -- no error
|
|
187
|
+
- ``ERROR_ABANDON = 1`` -- computation has been abandoned
|
|
188
|
+
- ``ERROR_NOTDEFINED = 2`` -- a number is not defined
|
|
189
|
+
- ``ERROR_PRECISION = 4`` -- not enough precision
|
|
190
|
+
- ``ERROR_OVERFLOW = 8`` -- overflow
|
|
191
|
+
- ``ERROR_NOTSQUARE = 16`` -- not a square
|
|
192
|
+
- ``ERROR_INTEGRAL = 32`` -- not in the integer ring
|
|
193
|
+
- ``ERROR_DIVISION = 64`` -- division by zero (or something indistinguishable from zero)
|
|
194
|
+
- ``ERROR_CIRCULAR = 128`` -- circular definition
|
|
195
|
+
"""
|
|
196
|
+
raise NotImplementedError("must be implemented in subclasses")
|
|
197
|
+
|
|
198
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
199
|
+
r"""
|
|
200
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
201
|
+
|
|
202
|
+
INPUT:
|
|
203
|
+
|
|
204
|
+
- ``prec`` -- integer
|
|
205
|
+
|
|
206
|
+
OUTPUT:
|
|
207
|
+
|
|
208
|
+
An error code (see :meth:`_next_c` for details).
|
|
209
|
+
"""
|
|
210
|
+
cdef int error
|
|
211
|
+
cdef long pr = min(prec, self._precbound)
|
|
212
|
+
while self._precrel + self._valuation < pr:
|
|
213
|
+
error = self._next_c()
|
|
214
|
+
if error:
|
|
215
|
+
return error
|
|
216
|
+
if prec > self._precbound:
|
|
217
|
+
return ERROR_PRECISION
|
|
218
|
+
return 0
|
|
219
|
+
|
|
220
|
+
cdef int _jump_relative_c(self, long prec, long halt) noexcept:
|
|
221
|
+
r"""
|
|
222
|
+
Compute the digits of this number until the relative precision
|
|
223
|
+
``prec``.
|
|
224
|
+
|
|
225
|
+
INPUT:
|
|
226
|
+
|
|
227
|
+
- ``prec`` -- integer
|
|
228
|
+
|
|
229
|
+
- ``halt`` -- integer; the absolute precision after which the
|
|
230
|
+
computation is abandoned if the first significant digit has not
|
|
231
|
+
been found yet
|
|
232
|
+
|
|
233
|
+
OUTPUT:
|
|
234
|
+
|
|
235
|
+
An error code (see :meth:`_next_c` for details).
|
|
236
|
+
"""
|
|
237
|
+
if self._valuation >= maxordp:
|
|
238
|
+
return 0
|
|
239
|
+
cdef int error = 0
|
|
240
|
+
if self._valuation <= -maxordp:
|
|
241
|
+
error = self._next_c()
|
|
242
|
+
cdef long valhalt = min(halt, self._precbound)
|
|
243
|
+
while not error and self._valuation < valhalt and self._precrel == 0:
|
|
244
|
+
error = self._next_c()
|
|
245
|
+
if self._valuation >= self._precbound:
|
|
246
|
+
error |= ERROR_PRECISION
|
|
247
|
+
elif self._valuation >= halt:
|
|
248
|
+
error |= ERROR_ABANDON
|
|
249
|
+
if not error:
|
|
250
|
+
error = self._jump_c(self._valuation + prec)
|
|
251
|
+
return error
|
|
252
|
+
|
|
253
|
+
cdef int _init_jump(self) except -1:
|
|
254
|
+
r"""
|
|
255
|
+
Start the computation of the digits of this number.
|
|
256
|
+
This method should be called at initialization.
|
|
257
|
+
|
|
258
|
+
OUTPUT:
|
|
259
|
+
|
|
260
|
+
An error code (see :meth:`_next_c` for details).
|
|
261
|
+
"""
|
|
262
|
+
cdef int error = 0
|
|
263
|
+
if self._precbound < maxordp:
|
|
264
|
+
error = self._jump_c(self._precbound)
|
|
265
|
+
raise_error(error, True)
|
|
266
|
+
return error
|
|
267
|
+
|
|
268
|
+
def digit(self, i):
|
|
269
|
+
r"""
|
|
270
|
+
Return the coefficient of `p^i` in the `p`-adic expansion
|
|
271
|
+
of this number.
|
|
272
|
+
|
|
273
|
+
INPUT:
|
|
274
|
+
|
|
275
|
+
- ``i`` -- integer
|
|
276
|
+
|
|
277
|
+
EXAMPLES::
|
|
278
|
+
|
|
279
|
+
sage: R = ZpER(5, prec=10)
|
|
280
|
+
sage: a = R(20/21)
|
|
281
|
+
sage: a
|
|
282
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
283
|
+
sage: a.digit(0)
|
|
284
|
+
0
|
|
285
|
+
sage: a.digit(1)
|
|
286
|
+
4
|
|
287
|
+
sage: a.digit(7)
|
|
288
|
+
3
|
|
289
|
+
sage: a.digit(100)
|
|
290
|
+
1
|
|
291
|
+
|
|
292
|
+
As a shortcut, one can use the bracket operator::
|
|
293
|
+
|
|
294
|
+
sage: a[100]
|
|
295
|
+
1
|
|
296
|
+
|
|
297
|
+
If the digit is not known, an error is raised::
|
|
298
|
+
|
|
299
|
+
sage: b = a.add_bigoh(10)
|
|
300
|
+
sage: b.digit(20)
|
|
301
|
+
Traceback (most recent call last):
|
|
302
|
+
...
|
|
303
|
+
PrecisionError: not enough precision
|
|
304
|
+
|
|
305
|
+
TESTS::
|
|
306
|
+
|
|
307
|
+
sage: a.digit(-1)
|
|
308
|
+
0
|
|
309
|
+
"""
|
|
310
|
+
cdef int error = self._jump_c(i+1)
|
|
311
|
+
raise_error(error)
|
|
312
|
+
cdef cdigit_ptr coeff = self._getdigit_absolute(i)
|
|
313
|
+
return digit_get_sage(coeff)
|
|
314
|
+
|
|
315
|
+
def expansion(self, n=None, lift_mode='simple', start_val=None):
|
|
316
|
+
r"""
|
|
317
|
+
Return an iterator over the list of coefficients in a `p`-adic
|
|
318
|
+
expansion of this element, that is the list of `a_i` so that
|
|
319
|
+
this element can be expressed as
|
|
320
|
+
|
|
321
|
+
.. MATH::
|
|
322
|
+
|
|
323
|
+
\pi^v \cdot \sum_{i=0}^\infty a_i \pi^i
|
|
324
|
+
|
|
325
|
+
where `v` is the valuation of this element when the parent is
|
|
326
|
+
a field, and `v = 0` otherwise and the `a_i` are between `0`
|
|
327
|
+
and `p - 1`.
|
|
328
|
+
|
|
329
|
+
INPUT:
|
|
330
|
+
|
|
331
|
+
- ``n`` -- integer or ``None`` (default: ``None``); if
|
|
332
|
+
given, return the corresponding entries in the expansion
|
|
333
|
+
|
|
334
|
+
- ``lift_mode`` -- ``'simple'``, ``'smallest'`` or
|
|
335
|
+
``'teichmuller'`` (default: ``'simple'``)
|
|
336
|
+
|
|
337
|
+
- ``start_val`` -- start at this valuation rather than the
|
|
338
|
+
default (`0` or the valuation of this element)
|
|
339
|
+
|
|
340
|
+
OUTPUT:
|
|
341
|
+
|
|
342
|
+
- If ``n`` is ``None``, an iterable giving the `p`-adic expansion
|
|
343
|
+
of this element.
|
|
344
|
+
|
|
345
|
+
- If ``n`` is an integer, the coefficient of `p^n` in the
|
|
346
|
+
`p`-adic expansion of this element.
|
|
347
|
+
|
|
348
|
+
EXAMPLES::
|
|
349
|
+
|
|
350
|
+
sage: R = ZpER(7, print_mode='digits')
|
|
351
|
+
sage: a = R(1/2021); a
|
|
352
|
+
...23615224635636163463
|
|
353
|
+
|
|
354
|
+
Without any argument, this method returns an iterator over the
|
|
355
|
+
digits of this number::
|
|
356
|
+
|
|
357
|
+
sage: E = a.expansion()
|
|
358
|
+
sage: E
|
|
359
|
+
7-adic expansion of ...23615224635636163463
|
|
360
|
+
sage: next(E)
|
|
361
|
+
3
|
|
362
|
+
sage: next(E)
|
|
363
|
+
6
|
|
364
|
+
sage: next(E)
|
|
365
|
+
4
|
|
366
|
+
|
|
367
|
+
On the contrary, passing in an integer returns the digit at the
|
|
368
|
+
given position::
|
|
369
|
+
|
|
370
|
+
sage: a.expansion(5)
|
|
371
|
+
1
|
|
372
|
+
|
|
373
|
+
Over a field, the expansion starts at the valuation of the element::
|
|
374
|
+
|
|
375
|
+
sage: K = R.fraction_field()
|
|
376
|
+
sage: b = K(20/21); b
|
|
377
|
+
...2222222222222222223.2
|
|
378
|
+
sage: E = b.expansion()
|
|
379
|
+
sage: next(E)
|
|
380
|
+
2
|
|
381
|
+
sage: next(E)
|
|
382
|
+
3
|
|
383
|
+
|
|
384
|
+
sage: c = 1/b; c
|
|
385
|
+
...564356435643564356440
|
|
386
|
+
sage: E = c.expansion()
|
|
387
|
+
sage: next(E)
|
|
388
|
+
4
|
|
389
|
+
sage: next(E)
|
|
390
|
+
4
|
|
391
|
+
|
|
392
|
+
When ``start_val`` is given, the expansion starts at this position
|
|
393
|
+
instead:
|
|
394
|
+
|
|
395
|
+
sage: E = c.expansion(start_val=0)
|
|
396
|
+
sage: next(E)
|
|
397
|
+
0
|
|
398
|
+
sage: next(E)
|
|
399
|
+
4
|
|
400
|
+
|
|
401
|
+
sage: E = c.expansion(start_val=5)
|
|
402
|
+
sage: next(E)
|
|
403
|
+
3
|
|
404
|
+
sage: next(E)
|
|
405
|
+
4
|
|
406
|
+
"""
|
|
407
|
+
if lift_mode == 'simple':
|
|
408
|
+
mode = simple_mode
|
|
409
|
+
elif lift_mode == 'smallest':
|
|
410
|
+
mode = smallest_mode
|
|
411
|
+
elif lift_mode == 'teichmuller':
|
|
412
|
+
mode = teichmuller_mode
|
|
413
|
+
else:
|
|
414
|
+
raise ValueError("unknown lift mode")
|
|
415
|
+
if n is None:
|
|
416
|
+
if start_val is not None:
|
|
417
|
+
start = start_val
|
|
418
|
+
elif self.prime_pow.in_field:
|
|
419
|
+
start = self.valuation()
|
|
420
|
+
else:
|
|
421
|
+
start = 0
|
|
422
|
+
return ExpansionIter(self, mode, start, self._precbound)
|
|
423
|
+
else:
|
|
424
|
+
n = Integer(n)
|
|
425
|
+
if n >= self._precbound:
|
|
426
|
+
raise_error(ERROR_PRECISION)
|
|
427
|
+
if n >= maxordp:
|
|
428
|
+
raise OverflowError("beyond maximum precision (which is %s)" % maxordp)
|
|
429
|
+
if mode == simple_mode:
|
|
430
|
+
return self.digit(n)
|
|
431
|
+
else:
|
|
432
|
+
E = ExpansionIter(self, mode, n, n+1)
|
|
433
|
+
return next(E)
|
|
434
|
+
|
|
435
|
+
def __getitem__(self, n):
|
|
436
|
+
r"""
|
|
437
|
+
Return the `n`-th digit of this relaxed `p`-adic number if `n` is an integer
|
|
438
|
+
or return a bounded relaxed `p`-adic corresponding to the given slice if `n` is a slice.
|
|
439
|
+
|
|
440
|
+
INPUT:
|
|
441
|
+
|
|
442
|
+
- ``n`` -- integer or a slice
|
|
443
|
+
|
|
444
|
+
EXAMPLES::
|
|
445
|
+
|
|
446
|
+
sage: R = ZpER(7, 10)
|
|
447
|
+
sage: a = R(1/2021); a
|
|
448
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
449
|
+
|
|
450
|
+
sage: a[3]
|
|
451
|
+
3
|
|
452
|
+
sage: a[3:6]
|
|
453
|
+
3*7^3 + 6*7^4 + 7^5 + O(7^6)
|
|
454
|
+
|
|
455
|
+
Unbounded slices are allowed::
|
|
456
|
+
|
|
457
|
+
sage: a[:3]
|
|
458
|
+
3 + 6*7 + 4*7^2 + O(7^3)
|
|
459
|
+
sage: a[3:]
|
|
460
|
+
3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
461
|
+
|
|
462
|
+
.. SEEALSO::
|
|
463
|
+
|
|
464
|
+
:meth:`digit`, :meth:`slice`
|
|
465
|
+
|
|
466
|
+
TESTS::
|
|
467
|
+
|
|
468
|
+
sage: a[3:6:2]
|
|
469
|
+
Traceback (most recent call last):
|
|
470
|
+
...
|
|
471
|
+
NotImplementedError: step is not allowed
|
|
472
|
+
"""
|
|
473
|
+
if isinstance(n, slice):
|
|
474
|
+
if n.step is not None:
|
|
475
|
+
raise NotImplementedError("step is not allowed")
|
|
476
|
+
return self.slice(n.start, n.stop, True)
|
|
477
|
+
else:
|
|
478
|
+
n = Integer(n)
|
|
479
|
+
if n >= maxordp:
|
|
480
|
+
raise OverflowError("beyond maximum precision (which is %s)" % maxordp)
|
|
481
|
+
return self.digit(n)
|
|
482
|
+
|
|
483
|
+
def slice(self, start=None, stop=None, bound=False):
|
|
484
|
+
r"""
|
|
485
|
+
Return a slice of this number.
|
|
486
|
+
|
|
487
|
+
INPUT:
|
|
488
|
+
|
|
489
|
+
- ``start`` -- integer or ``None`` (default: ``None``);
|
|
490
|
+
the first position of the slice
|
|
491
|
+
|
|
492
|
+
- ``stop`` -- integer or ``None`` (default: ``None``);
|
|
493
|
+
the first position not included in the slice
|
|
494
|
+
|
|
495
|
+
- ``bound`` -- boolean (default: ``False``); whether the
|
|
496
|
+
precision on the output should be bounded or unbounded
|
|
497
|
+
|
|
498
|
+
EXAMPLES::
|
|
499
|
+
|
|
500
|
+
sage: K = QpER(7, prec=10)
|
|
501
|
+
sage: a = K(1/2021); a
|
|
502
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
503
|
+
|
|
504
|
+
sage: s = a.slice(3, 6)
|
|
505
|
+
sage: s
|
|
506
|
+
3*7^3 + 6*7^4 + 7^5 + ...
|
|
507
|
+
|
|
508
|
+
In the above example, the precision on `b` remains unbounded::
|
|
509
|
+
|
|
510
|
+
sage: s.precision_absolute()
|
|
511
|
+
+Infinity
|
|
512
|
+
|
|
513
|
+
Passing in ``bound=True`` changes this behaviour::
|
|
514
|
+
|
|
515
|
+
sage: a.slice(3, 6, bound=True)
|
|
516
|
+
3*7^3 + 6*7^4 + 7^5 + O(7^6)
|
|
517
|
+
|
|
518
|
+
When ``start`` is omitted, the slice starts at the beginning of the number:
|
|
519
|
+
|
|
520
|
+
sage: a.slice(stop=6)
|
|
521
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + ...
|
|
522
|
+
|
|
523
|
+
sage: b = K(20/21); b
|
|
524
|
+
2*7^-1 + 3 + 2*7 + 2*7^2 + 2*7^3 + 2*7^4 + 2*7^5 + 2*7^6 + 2*7^7 + 2*7^8 + ...
|
|
525
|
+
sage: b.slice(stop=6)
|
|
526
|
+
2*7^-1 + 3 + 2*7 + 2*7^2 + 2*7^3 + 2*7^4 + 2*7^5 + ...
|
|
527
|
+
|
|
528
|
+
As a shortcut, one can use the bracket operator.
|
|
529
|
+
However, in this case, the precision is bounded::
|
|
530
|
+
|
|
531
|
+
sage: a[3:6]
|
|
532
|
+
3*7^3 + 6*7^4 + 7^5 + O(7^6)
|
|
533
|
+
sage: b[:6]
|
|
534
|
+
2*7^-1 + 3 + 2*7 + 2*7^2 + 2*7^3 + 2*7^4 + 2*7^5 + O(7^6)
|
|
535
|
+
|
|
536
|
+
TESTS::
|
|
537
|
+
|
|
538
|
+
sage: x = a[:3]
|
|
539
|
+
sage: x.slice(stop=3)
|
|
540
|
+
3 + 6*7 + 4*7^2 + ...
|
|
541
|
+
sage: x.slice(stop=4)
|
|
542
|
+
3 + 6*7 + 4*7^2 + O(7^3)
|
|
543
|
+
|
|
544
|
+
Taking slices of slices work as expected::
|
|
545
|
+
|
|
546
|
+
sage: a1 = a.slice(5, 10); a1
|
|
547
|
+
7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
548
|
+
sage: a2 = a1.slice(3, 8); a2
|
|
549
|
+
7^5 + 6*7^6 + 3*7^7 + ...
|
|
550
|
+
sage: a2 == a.slice(5, 8)
|
|
551
|
+
True
|
|
552
|
+
"""
|
|
553
|
+
if start is None:
|
|
554
|
+
start = -maxordp
|
|
555
|
+
elif start >= maxordp:
|
|
556
|
+
raise OverflowError("beyond maximum precision (which is %s)" % maxordp)
|
|
557
|
+
if stop is None:
|
|
558
|
+
stop = maxordp
|
|
559
|
+
elif stop >= maxordp:
|
|
560
|
+
raise OverflowError("beyond maximum precision (which is %s)" % maxordp)
|
|
561
|
+
cdef RelaxedElement x = element_class_slice(self._parent, self, start, stop, 0)
|
|
562
|
+
if bound and x._precbound > stop:
|
|
563
|
+
x = element_class_bound(self._parent, x, stop)
|
|
564
|
+
return x
|
|
565
|
+
|
|
566
|
+
def _repr_(self):
|
|
567
|
+
r"""
|
|
568
|
+
Return a string representation of this element.
|
|
569
|
+
|
|
570
|
+
EXAMPLES:
|
|
571
|
+
|
|
572
|
+
For unbounded elements, the number of printed terms is given by
|
|
573
|
+
the default precision of the ring::
|
|
574
|
+
|
|
575
|
+
sage: R = ZpER(5, 10)
|
|
576
|
+
sage: a = R(1/2021)
|
|
577
|
+
sage: a # indirect doctest
|
|
578
|
+
1 + 5 + 3*5^3 + 3*5^4 + 5^5 + 4*5^6 + 4*5^7 + 2*5^8 + 3*5^9 + ...
|
|
579
|
+
|
|
580
|
+
sage: S = ZpER(5, 5)
|
|
581
|
+
sage: b = S(1/2021)
|
|
582
|
+
sage: b # indirect doctest
|
|
583
|
+
1 + 5 + 3*5^3 + 3*5^4 + ...
|
|
584
|
+
|
|
585
|
+
On the contrary, bounded elements are printed until their own
|
|
586
|
+
precision, regardless the default precision of the parent::
|
|
587
|
+
|
|
588
|
+
sage: a[:15] # indirect doctest
|
|
589
|
+
1 + 5 + 3*5^3 + 3*5^4 + 5^5 + 4*5^6 + 4*5^7 + 2*5^8 + 3*5^9 + 2*5^10 + 5^11 + 5^12 + 5^13 + O(5^15)
|
|
590
|
+
|
|
591
|
+
sage: b[:15] # indirect doctest
|
|
592
|
+
1 + 5 + 3*5^3 + 3*5^4 + 5^5 + 4*5^6 + 4*5^7 + 2*5^8 + 3*5^9 + 2*5^10 + 5^11 + 5^12 + 5^13 + O(5^15)
|
|
593
|
+
"""
|
|
594
|
+
# This code should be integrated to the p-adic printer
|
|
595
|
+
if self._valuation <= -maxordp:
|
|
596
|
+
return "O(%s^-Infinity)" % self._parent.prime()
|
|
597
|
+
if self._is_exact_zero():
|
|
598
|
+
return "0"
|
|
599
|
+
if self._precbound >= maxordp:
|
|
600
|
+
unbounded = True
|
|
601
|
+
try:
|
|
602
|
+
if self.prime_pow.in_field:
|
|
603
|
+
x = self.at_precision_relative(permissive=False)
|
|
604
|
+
else:
|
|
605
|
+
x = self.at_precision_absolute(permissive=False)
|
|
606
|
+
except (ValueError, PrecisionError, RecursionError):
|
|
607
|
+
unbounded = False
|
|
608
|
+
x = element_class_bound(self._parent, self, self._valuation + self._precrel)
|
|
609
|
+
else:
|
|
610
|
+
unbounded = False
|
|
611
|
+
x = self
|
|
612
|
+
s = pAdicGenericElement._repr_(x)
|
|
613
|
+
mode = self._parent._printer.dict()['mode']
|
|
614
|
+
if unbounded:
|
|
615
|
+
s = re.sub(r'O\(.*\)$', '...', s)
|
|
616
|
+
elif mode == "digits":
|
|
617
|
+
s = re.sub(r'^\.\.\.\??', '...?', s)
|
|
618
|
+
elif mode == "bars":
|
|
619
|
+
s = re.sub(r'^\.\.\.\|?', '...?|', s)
|
|
620
|
+
if s == "" or s == "...":
|
|
621
|
+
s = "0 + ..."
|
|
622
|
+
return s
|
|
623
|
+
|
|
624
|
+
cdef bint _is_equal(self, RelaxedElement right, long prec, bint permissive) except -1:
|
|
625
|
+
r"""
|
|
626
|
+
C function for checking equality at a given precision.
|
|
627
|
+
|
|
628
|
+
INPUT:
|
|
629
|
+
|
|
630
|
+
- ``right`` -- the second element involved in the comparison
|
|
631
|
+
|
|
632
|
+
- ``prec`` -- integer; the precision at which the equality is checked
|
|
633
|
+
|
|
634
|
+
- ``permissive`` -- boolean; if ``True``, be silent if the precision
|
|
635
|
+
on one input is less than ``prec``. Otherwise, raise an error.
|
|
636
|
+
"""
|
|
637
|
+
cdef int error
|
|
638
|
+
cdef long i
|
|
639
|
+
if self._valuation <= -maxordp:
|
|
640
|
+
error = self._next_c()
|
|
641
|
+
raise_error(error)
|
|
642
|
+
if right._valuation <= -maxordp:
|
|
643
|
+
error = right._next_c()
|
|
644
|
+
raise_error(error)
|
|
645
|
+
for i in range(min(self._valuation, right._valuation), prec):
|
|
646
|
+
error = self._jump_c(i+1)
|
|
647
|
+
raise_error(error, permissive)
|
|
648
|
+
if error: # not enough precision
|
|
649
|
+
return True
|
|
650
|
+
error = right._jump_c(i+1)
|
|
651
|
+
raise_error(error, permissive)
|
|
652
|
+
if error: # not enough precision
|
|
653
|
+
return True
|
|
654
|
+
if not digit_equal(self._getdigit_absolute(i), right._getdigit_absolute(i)):
|
|
655
|
+
return False
|
|
656
|
+
return True
|
|
657
|
+
|
|
658
|
+
@coerce_binop
|
|
659
|
+
def is_equal_at_precision(self, right, prec):
|
|
660
|
+
r"""
|
|
661
|
+
Compare this element with ``right`` at precision ``prec``.
|
|
662
|
+
|
|
663
|
+
INPUT:
|
|
664
|
+
|
|
665
|
+
- ``right`` -- a relaxed `p`-adic number
|
|
666
|
+
|
|
667
|
+
- ``prec`` -- integer
|
|
668
|
+
|
|
669
|
+
EXAMPLES::
|
|
670
|
+
|
|
671
|
+
sage: R = ZpER(7, prec=10)
|
|
672
|
+
sage: a = R(1/2); a
|
|
673
|
+
4 + 3*7 + 3*7^2 + 3*7^3 + 3*7^4 + 3*7^5 + 3*7^6 + 3*7^7 + 3*7^8 + 3*7^9 + ...
|
|
674
|
+
sage: b = R(99/2); b
|
|
675
|
+
4 + 3*7 + 4*7^2 + 3*7^3 + 3*7^4 + 3*7^5 + 3*7^6 + 3*7^7 + 3*7^8 + 3*7^9 + ...
|
|
676
|
+
|
|
677
|
+
sage: a.is_equal_at_precision(b, 1)
|
|
678
|
+
True
|
|
679
|
+
sage: a.is_equal_at_precision(b, 2)
|
|
680
|
+
True
|
|
681
|
+
sage: a.is_equal_at_precision(b, 3)
|
|
682
|
+
False
|
|
683
|
+
"""
|
|
684
|
+
return self._is_equal(right, min(prec, maxordp), False)
|
|
685
|
+
|
|
686
|
+
@coerce_binop
|
|
687
|
+
def is_equal_to(self, RelaxedElement right, prec=None, secure=None):
|
|
688
|
+
r"""
|
|
689
|
+
Compare this element with ``right``.
|
|
690
|
+
|
|
691
|
+
INPUT:
|
|
692
|
+
|
|
693
|
+
- ``right`` -- a relaxed `p`-adic number
|
|
694
|
+
|
|
695
|
+
- ``prec`` -- integer or ``None`` (default: ``None``); if
|
|
696
|
+
given, compare the two elements at this precision. Otherwise
|
|
697
|
+
use the default halting precision of the parent.
|
|
698
|
+
|
|
699
|
+
- ``secure`` -- boolean (default: ``False`` if ``prec`` is given,
|
|
700
|
+
``True`` otherwise); when the elements cannot be distinguished
|
|
701
|
+
at the given precision, raise an error if ``secure`` is ``True``,
|
|
702
|
+
return ``True`` otherwise.
|
|
703
|
+
|
|
704
|
+
EXAMPLES::
|
|
705
|
+
|
|
706
|
+
sage: R = ZpER(7)
|
|
707
|
+
sage: a = R(1/2)
|
|
708
|
+
sage: b = R(1/3)
|
|
709
|
+
sage: c = R(1/6)
|
|
710
|
+
|
|
711
|
+
sage: a.is_equal_to(b)
|
|
712
|
+
False
|
|
713
|
+
|
|
714
|
+
When equality indeed holds, it is not possible to conclude by
|
|
715
|
+
comparing more and more accurate approximations.
|
|
716
|
+
In this case, an error is raised::
|
|
717
|
+
|
|
718
|
+
sage: a.is_equal_to(b + c)
|
|
719
|
+
Traceback (most recent call last):
|
|
720
|
+
...
|
|
721
|
+
PrecisionError: unable to decide equality; try to bound precision
|
|
722
|
+
|
|
723
|
+
You can get around this behaviour by passing ``secure=False``::
|
|
724
|
+
|
|
725
|
+
sage: a.is_equal_to(b + c, secure=False)
|
|
726
|
+
True
|
|
727
|
+
|
|
728
|
+
Another option (which is actually recommended) is to provide an explicit
|
|
729
|
+
bound on the precision::
|
|
730
|
+
|
|
731
|
+
sage: s = b + c + 7^50
|
|
732
|
+
sage: a.is_equal_to(s, prec=20)
|
|
733
|
+
True
|
|
734
|
+
sage: a.is_equal_to(s, prec=100)
|
|
735
|
+
False
|
|
736
|
+
"""
|
|
737
|
+
cdef long halt
|
|
738
|
+
if self is right:
|
|
739
|
+
return True
|
|
740
|
+
if self._valuation >= maxordp and right._valuation >= maxordp:
|
|
741
|
+
return True
|
|
742
|
+
if prec is None:
|
|
743
|
+
if secure is None:
|
|
744
|
+
secure = True
|
|
745
|
+
prec = min(self._precbound, right._precbound)
|
|
746
|
+
else:
|
|
747
|
+
if secure is None:
|
|
748
|
+
secure = False
|
|
749
|
+
prec = Integer(prec)
|
|
750
|
+
if prec < maxordp:
|
|
751
|
+
return self._is_equal(right, prec, True)
|
|
752
|
+
prec = min(self._valuation + self._precrel, right._valuation + right._precrel)
|
|
753
|
+
halt = min(self._parent.halting_prec(), maxordp)
|
|
754
|
+
eq = self._is_equal(right, max(prec, halt), True)
|
|
755
|
+
if secure and eq:
|
|
756
|
+
raise PrecisionError("unable to decide equality; try to bound precision")
|
|
757
|
+
return eq
|
|
758
|
+
|
|
759
|
+
def __eq__(self, other):
|
|
760
|
+
r"""
|
|
761
|
+
Return ``True`` of this element is equal to ``other``.
|
|
762
|
+
|
|
763
|
+
TESTS::
|
|
764
|
+
|
|
765
|
+
sage: R = ZpER(5)
|
|
766
|
+
sage: x = R(1/2)
|
|
767
|
+
sage: y = R(1/3)
|
|
768
|
+
sage: z = R(1/6)
|
|
769
|
+
|
|
770
|
+
sage: x == y + z
|
|
771
|
+
True
|
|
772
|
+
|
|
773
|
+
We illustrate the effect of the keyword ``secure``::
|
|
774
|
+
|
|
775
|
+
sage: R.is_secure()
|
|
776
|
+
False
|
|
777
|
+
sage: s = y + z + 5^50
|
|
778
|
+
sage: x == s
|
|
779
|
+
True
|
|
780
|
+
|
|
781
|
+
sage: S = ZpER(5, secure=True)
|
|
782
|
+
sage: S(x) == S(s)
|
|
783
|
+
Traceback (most recent call last):
|
|
784
|
+
...
|
|
785
|
+
PrecisionError: unable to decide equality; try to bound precision
|
|
786
|
+
|
|
787
|
+
Note that, when ``secure=False``, once more digits have been
|
|
788
|
+
computed, the answer can change::
|
|
789
|
+
|
|
790
|
+
sage: x[:100] == s
|
|
791
|
+
False
|
|
792
|
+
sage: x == s
|
|
793
|
+
False
|
|
794
|
+
|
|
795
|
+
.. SEEALSO::
|
|
796
|
+
|
|
797
|
+
:meth:`is_equal_to`
|
|
798
|
+
"""
|
|
799
|
+
if not have_same_parent(self, other):
|
|
800
|
+
try:
|
|
801
|
+
a, b = coercion_model.canonical_coercion(self, other)
|
|
802
|
+
except TypeError:
|
|
803
|
+
return False
|
|
804
|
+
return a == b
|
|
805
|
+
return self.is_equal_to(other, secure=self._parent.is_secure())
|
|
806
|
+
|
|
807
|
+
def __bool__(self):
|
|
808
|
+
r"""
|
|
809
|
+
Return ``True`` if this element is distinguishable from zero.
|
|
810
|
+
|
|
811
|
+
TESTS::
|
|
812
|
+
|
|
813
|
+
sage: R = ZpER(5)
|
|
814
|
+
sage: x = R(1)
|
|
815
|
+
sage: bool(x)
|
|
816
|
+
True
|
|
817
|
+
|
|
818
|
+
In the next example, only `40` digits (which is the default halting
|
|
819
|
+
precision) are computed so `x` is considered as indistinguishable from
|
|
820
|
+
`0`::
|
|
821
|
+
|
|
822
|
+
sage: x = R(5^41)
|
|
823
|
+
sage: bool(x)
|
|
824
|
+
False
|
|
825
|
+
"""
|
|
826
|
+
cdef int error = 0
|
|
827
|
+
cdef long prec, halt
|
|
828
|
+
if self._precrel:
|
|
829
|
+
return True
|
|
830
|
+
prec = self._precbound
|
|
831
|
+
if prec >= maxordp:
|
|
832
|
+
halt = min(self._parent.halting_prec(), maxordp)
|
|
833
|
+
prec = max(self._valuation + self._precrel, halt)
|
|
834
|
+
while not error and self._precrel == 0 and self._valuation < prec:
|
|
835
|
+
error = self._next_c()
|
|
836
|
+
return bool(self._precrel)
|
|
837
|
+
|
|
838
|
+
cpdef bint _is_exact_zero(self) except -1:
|
|
839
|
+
r"""
|
|
840
|
+
Return ``True`` if this element is an exact zero.
|
|
841
|
+
|
|
842
|
+
EXAMPLES::
|
|
843
|
+
|
|
844
|
+
sage: R = ZpER(5)
|
|
845
|
+
sage: a = R(0); a
|
|
846
|
+
0
|
|
847
|
+
sage: a._is_exact_zero()
|
|
848
|
+
True
|
|
849
|
+
|
|
850
|
+
sage: b = a.add_bigoh(20)
|
|
851
|
+
sage: b
|
|
852
|
+
O(5^20)
|
|
853
|
+
sage: b._is_exact_zero()
|
|
854
|
+
False
|
|
855
|
+
"""
|
|
856
|
+
return self._valuation >= maxordp
|
|
857
|
+
|
|
858
|
+
cpdef bint _is_inexact_zero(self) except -1:
|
|
859
|
+
r"""
|
|
860
|
+
Return ``True`` if, at the current stage of computations, this
|
|
861
|
+
number cannot be distinguished from zero.
|
|
862
|
+
|
|
863
|
+
EXAMPLES::
|
|
864
|
+
|
|
865
|
+
sage: R = ZpER(5, print_mode='digits')
|
|
866
|
+
sage: a = R(20/21)
|
|
867
|
+
|
|
868
|
+
Computations have not started yet; hence we are not able
|
|
869
|
+
to distinguish `a` from zero so far::
|
|
870
|
+
|
|
871
|
+
sage: a._is_inexact_zero()
|
|
872
|
+
True
|
|
873
|
+
|
|
874
|
+
When we print `a`, the first digits are computed, after what
|
|
875
|
+
we know that `a` is not zero::
|
|
876
|
+
|
|
877
|
+
sage: a
|
|
878
|
+
...34010434010434010440
|
|
879
|
+
sage: a._is_inexact_zero()
|
|
880
|
+
False
|
|
881
|
+
"""
|
|
882
|
+
return self._precrel == 0
|
|
883
|
+
|
|
884
|
+
def is_exact(self):
|
|
885
|
+
r"""
|
|
886
|
+
Return ``True`` if this element is exact, that is if its
|
|
887
|
+
precision is unbounded.
|
|
888
|
+
|
|
889
|
+
EXAMPLES::
|
|
890
|
+
|
|
891
|
+
sage: R = ZpER(5, prec=10)
|
|
892
|
+
sage: a = R(20/21)
|
|
893
|
+
sage: a
|
|
894
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
895
|
+
sage: a.is_exact()
|
|
896
|
+
True
|
|
897
|
+
|
|
898
|
+
sage: b = a.add_bigoh(10)
|
|
899
|
+
sage: b
|
|
900
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + O(5^10)
|
|
901
|
+
sage: b.is_exact()
|
|
902
|
+
False
|
|
903
|
+
"""
|
|
904
|
+
return self._precbound >= maxordp
|
|
905
|
+
|
|
906
|
+
def precision_absolute(self):
|
|
907
|
+
r"""
|
|
908
|
+
Return the absolute precision of this element.
|
|
909
|
+
|
|
910
|
+
This is the power of `p` modulo which this element is known.
|
|
911
|
+
For unbounded elements, this methods return `+\infty`.
|
|
912
|
+
|
|
913
|
+
EXAMPLES::
|
|
914
|
+
|
|
915
|
+
sage: R = ZpER(5, prec=10)
|
|
916
|
+
sage: a = R(20/21)
|
|
917
|
+
sage: a
|
|
918
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
919
|
+
sage: a.precision_absolute()
|
|
920
|
+
+Infinity
|
|
921
|
+
|
|
922
|
+
sage: b = a.add_bigoh(10)
|
|
923
|
+
sage: b
|
|
924
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + O(5^10)
|
|
925
|
+
sage: b.precision_absolute()
|
|
926
|
+
10
|
|
927
|
+
|
|
928
|
+
TESTS::
|
|
929
|
+
|
|
930
|
+
sage: s = R.unknown()
|
|
931
|
+
sage: (1/s).precision_absolute()
|
|
932
|
+
Traceback (most recent call last):
|
|
933
|
+
...
|
|
934
|
+
PrecisionError: no lower bound on the valuation is known
|
|
935
|
+
"""
|
|
936
|
+
if self._is_exact_zero():
|
|
937
|
+
return Infinity
|
|
938
|
+
if self._valuation <= -maxordp:
|
|
939
|
+
raise PrecisionError("no lower bound on the valuation is known")
|
|
940
|
+
if self._precbound >= maxordp:
|
|
941
|
+
return Infinity
|
|
942
|
+
return Integer(self._precrel + self._valuation)
|
|
943
|
+
|
|
944
|
+
def precision_relative(self):
|
|
945
|
+
r"""
|
|
946
|
+
Return the relative precision of this element.
|
|
947
|
+
|
|
948
|
+
This is the power of `p` modulo which the unit part of this
|
|
949
|
+
element is known.
|
|
950
|
+
|
|
951
|
+
For unbounded nonzero elements, this methods return `+\infty`.
|
|
952
|
+
|
|
953
|
+
EXAMPLES::
|
|
954
|
+
|
|
955
|
+
sage: R = ZpER(5, prec=10)
|
|
956
|
+
sage: a = R(20/21)
|
|
957
|
+
sage: a
|
|
958
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
959
|
+
sage: a.precision_relative()
|
|
960
|
+
+Infinity
|
|
961
|
+
|
|
962
|
+
sage: b = a.add_bigoh(10)
|
|
963
|
+
sage: b
|
|
964
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + O(5^10)
|
|
965
|
+
sage: b.precision_relative()
|
|
966
|
+
9
|
|
967
|
+
|
|
968
|
+
The relative precision of (exact and inexact) `0` is `0`::
|
|
969
|
+
|
|
970
|
+
sage: x = R(0); x
|
|
971
|
+
0
|
|
972
|
+
sage: x.precision_relative()
|
|
973
|
+
0
|
|
974
|
+
|
|
975
|
+
sage: y = R(0, 10); y
|
|
976
|
+
O(5^10)
|
|
977
|
+
sage: y.precision_relative()
|
|
978
|
+
0
|
|
979
|
+
|
|
980
|
+
TESTS::
|
|
981
|
+
|
|
982
|
+
sage: s = R.unknown()
|
|
983
|
+
sage: (1/s).precision_relative()
|
|
984
|
+
Traceback (most recent call last):
|
|
985
|
+
...
|
|
986
|
+
PrecisionError: no lower bound on the valuation is known
|
|
987
|
+
"""
|
|
988
|
+
if self._valuation <= -maxordp:
|
|
989
|
+
raise PrecisionError("no lower bound on the valuation is known")
|
|
990
|
+
if self._precbound >= maxordp and self._valuation < maxordp:
|
|
991
|
+
return Infinity
|
|
992
|
+
return Integer(self._precrel)
|
|
993
|
+
|
|
994
|
+
def precision_current(self):
|
|
995
|
+
r"""
|
|
996
|
+
Return the internal absolute precision at which this relaxed `p`-adic
|
|
997
|
+
number is known at the current stage of the computation.
|
|
998
|
+
|
|
999
|
+
EXAMPLES::
|
|
1000
|
+
|
|
1001
|
+
sage: R = ZpER(5, prec=10)
|
|
1002
|
+
sage: x = R(20/21)
|
|
1003
|
+
sage: y = R(21/22)
|
|
1004
|
+
sage: z = x + y
|
|
1005
|
+
|
|
1006
|
+
When the elements are just defined, the computation has not started::
|
|
1007
|
+
|
|
1008
|
+
sage: x.precision_current()
|
|
1009
|
+
0
|
|
1010
|
+
sage: y.precision_current()
|
|
1011
|
+
0
|
|
1012
|
+
sage: z.precision_current()
|
|
1013
|
+
0
|
|
1014
|
+
|
|
1015
|
+
When elements are printed, the relevant digits are computed::
|
|
1016
|
+
|
|
1017
|
+
sage: x
|
|
1018
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1019
|
+
sage: x.precision_current()
|
|
1020
|
+
10
|
|
1021
|
+
|
|
1022
|
+
If we ask for more digits of `z`, the current precision of `z`
|
|
1023
|
+
increases accordingly::
|
|
1024
|
+
|
|
1025
|
+
sage: z[:15]
|
|
1026
|
+
3 + 2*5 + 2*5^3 + 5^4 + 2*5^5 + 2*5^6 + 4*5^7 + 5^9 + 3*5^10 + 3*5^11 + 4*5^12 + 4*5^13 + 4*5^14 + O(5^15)
|
|
1027
|
+
sage: z.precision_current()
|
|
1028
|
+
15
|
|
1029
|
+
|
|
1030
|
+
and similarly the current precision of `x` and `y` increases because
|
|
1031
|
+
those digits are needed to carry out the computation::
|
|
1032
|
+
|
|
1033
|
+
sage: x.precision_current()
|
|
1034
|
+
15
|
|
1035
|
+
sage: y.precision_current()
|
|
1036
|
+
15
|
|
1037
|
+
"""
|
|
1038
|
+
if self._valuation <= -maxordp:
|
|
1039
|
+
return -Infinity
|
|
1040
|
+
if self._valuation >= maxordp:
|
|
1041
|
+
return Infinity
|
|
1042
|
+
return Integer(self._valuation + self._precrel)
|
|
1043
|
+
|
|
1044
|
+
def at_precision_absolute(self, prec=None, permissive=None):
|
|
1045
|
+
r"""
|
|
1046
|
+
Return this element bounded at the given precision.
|
|
1047
|
+
|
|
1048
|
+
INPUT:
|
|
1049
|
+
|
|
1050
|
+
- ``prec`` -- integer or ``None`` (default: ``None``);
|
|
1051
|
+
if ``None``, use the default precision of the parent
|
|
1052
|
+
|
|
1053
|
+
- ``permissive`` -- boolean (default: ``False`` if ``prec``
|
|
1054
|
+
is given, ``True`` otherwise); if ``False``, raise an error
|
|
1055
|
+
if the precision of this element is not sufficient
|
|
1056
|
+
|
|
1057
|
+
EXAMPLES::
|
|
1058
|
+
|
|
1059
|
+
sage: R = ZpER(7, prec=10)
|
|
1060
|
+
sage: a = R(1/2021); a
|
|
1061
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
1062
|
+
sage: a.at_precision_absolute(5)
|
|
1063
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + O(7^5)
|
|
1064
|
+
sage: a.at_precision_absolute(10)
|
|
1065
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + O(7^10)
|
|
1066
|
+
|
|
1067
|
+
sage: b = a.add_bigoh(5)
|
|
1068
|
+
sage: b.at_precision_absolute(10)
|
|
1069
|
+
Traceback (most recent call last):
|
|
1070
|
+
...
|
|
1071
|
+
PrecisionError: not enough precision
|
|
1072
|
+
|
|
1073
|
+
sage: b.at_precision_absolute(10, permissive=True)
|
|
1074
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + O(7^5)
|
|
1075
|
+
|
|
1076
|
+
Bounding at a negative precision is not permitted over `\ZZ_p`::
|
|
1077
|
+
|
|
1078
|
+
sage: a.at_precision_absolute(-1)
|
|
1079
|
+
Traceback (most recent call last):
|
|
1080
|
+
...
|
|
1081
|
+
ValueError: precision must be nonnegative
|
|
1082
|
+
|
|
1083
|
+
but, of course, it is over `\QQ_p`::
|
|
1084
|
+
|
|
1085
|
+
sage: K = R.fraction_field()
|
|
1086
|
+
sage: K(a).at_precision_absolute(-1)
|
|
1087
|
+
O(7^-1)
|
|
1088
|
+
|
|
1089
|
+
.. SEEALSO::
|
|
1090
|
+
|
|
1091
|
+
:meth:`at_precision_relative`, :meth:`add_bigoh`
|
|
1092
|
+
"""
|
|
1093
|
+
if prec is Infinity:
|
|
1094
|
+
if not permissive and self._precbound < maxordp:
|
|
1095
|
+
raise_error(ERROR_PRECISION)
|
|
1096
|
+
return self
|
|
1097
|
+
if prec is None:
|
|
1098
|
+
if permissive is None:
|
|
1099
|
+
permissive = True
|
|
1100
|
+
prec = self._parent.default_prec()
|
|
1101
|
+
else:
|
|
1102
|
+
prec = Integer(prec)
|
|
1103
|
+
if not self.prime_pow.in_field and prec < 0:
|
|
1104
|
+
raise ValueError("precision must be nonnegative")
|
|
1105
|
+
if prec > maxordp:
|
|
1106
|
+
raise OverflowError("beyond maximal precision (which is %s)" % maxordp)
|
|
1107
|
+
error = self._jump_c(prec)
|
|
1108
|
+
if permissive is None:
|
|
1109
|
+
permissive = False
|
|
1110
|
+
raise_error(error, permissive)
|
|
1111
|
+
return element_class_bound((<RelaxedElement>self)._parent, self, prec)
|
|
1112
|
+
|
|
1113
|
+
def add_bigoh(self, absprec):
|
|
1114
|
+
r"""
|
|
1115
|
+
Return a new element with absolute precision decreased to ``absprec``.
|
|
1116
|
+
|
|
1117
|
+
INPUT:
|
|
1118
|
+
|
|
1119
|
+
- ``absprec`` -- integer or infinity
|
|
1120
|
+
|
|
1121
|
+
EXAMPLES::
|
|
1122
|
+
|
|
1123
|
+
sage: R = ZpER(7, prec=10)
|
|
1124
|
+
sage: a = R(1/2021); a
|
|
1125
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
1126
|
+
sage: a.add_bigoh(5)
|
|
1127
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + O(7^5)
|
|
1128
|
+
|
|
1129
|
+
When ``absprec`` is negative, we return an element in the fraction
|
|
1130
|
+
field::
|
|
1131
|
+
|
|
1132
|
+
sage: b = a.add_bigoh(-1)
|
|
1133
|
+
sage: b
|
|
1134
|
+
O(7^-1)
|
|
1135
|
+
sage: b.parent()
|
|
1136
|
+
7-adic Field handled with relaxed arithmetics
|
|
1137
|
+
|
|
1138
|
+
.. SEEALSO::
|
|
1139
|
+
|
|
1140
|
+
:meth:`at_precision_absolute`, :meth:`at_precision_relative`
|
|
1141
|
+
"""
|
|
1142
|
+
if absprec < 0 and (not self.prime_pow.in_field):
|
|
1143
|
+
self = element_class_bound(self._parent.fraction_field(), self)
|
|
1144
|
+
return self.at_precision_absolute(absprec, True)
|
|
1145
|
+
|
|
1146
|
+
def at_precision_relative(self, prec=None, halt=True, permissive=None):
|
|
1147
|
+
r"""
|
|
1148
|
+
Return this element bounded at the given precision.
|
|
1149
|
+
|
|
1150
|
+
INPUT:
|
|
1151
|
+
|
|
1152
|
+
- ``prec`` -- integer or ``None`` (default: ``None``);
|
|
1153
|
+
if ``None``, use the default precision of the parent
|
|
1154
|
+
|
|
1155
|
+
- ``halt`` -- integer or boolean (default: ``True``);
|
|
1156
|
+
the absolute precision after which the computation is abandoned
|
|
1157
|
+
if the first significant digit has not been found yet.
|
|
1158
|
+
If ``True``, the default halting precision of the parent is used.
|
|
1159
|
+
If ``False``, the computation is never abandoned.
|
|
1160
|
+
|
|
1161
|
+
- ``permissive`` -- boolean (default: ``False`` if ``prec``
|
|
1162
|
+
is given, ``True`` otherwise); if ``False``, raise an error
|
|
1163
|
+
if the precision of this element is not sufficient
|
|
1164
|
+
|
|
1165
|
+
EXAMPLES::
|
|
1166
|
+
|
|
1167
|
+
sage: R = ZpER(5, prec=10, halt=10)
|
|
1168
|
+
sage: a = R(20/21); a
|
|
1169
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1170
|
+
sage: a.at_precision_relative(5)
|
|
1171
|
+
4*5 + 4*5^2 + 5^4 + O(5^6)
|
|
1172
|
+
|
|
1173
|
+
We illustrate the behaviour of the parameter ``halt``.
|
|
1174
|
+
We create a very small number whose first significant is far beyond
|
|
1175
|
+
the default precision::
|
|
1176
|
+
|
|
1177
|
+
sage: b = R(5^20)
|
|
1178
|
+
sage: b
|
|
1179
|
+
0 + ...
|
|
1180
|
+
|
|
1181
|
+
Without any help, Sage does not run the computation far enough to determine
|
|
1182
|
+
the valuation and an error is raised::
|
|
1183
|
+
|
|
1184
|
+
sage: b.at_precision_relative(5)
|
|
1185
|
+
Traceback (most recent call last):
|
|
1186
|
+
...
|
|
1187
|
+
PrecisionError: computation has been abandoned; try to increase precision
|
|
1188
|
+
|
|
1189
|
+
By setting the argument ``halt``, one can force the computation to continue
|
|
1190
|
+
until a prescribed limit::
|
|
1191
|
+
|
|
1192
|
+
sage: b.at_precision_relative(5, halt=20) # not enough to find the valuation
|
|
1193
|
+
Traceback (most recent call last):
|
|
1194
|
+
...
|
|
1195
|
+
PrecisionError: computation has been abandoned; try to increase precision
|
|
1196
|
+
|
|
1197
|
+
sage: b.at_precision_relative(5, halt=21) # now, we're okay
|
|
1198
|
+
5^20 + O(5^25)
|
|
1199
|
+
|
|
1200
|
+
.. NOTE::
|
|
1201
|
+
|
|
1202
|
+
It is also possible to pass in ``halt=False`` but it is not recommended
|
|
1203
|
+
because the computation can hang forever if this element is `0`.
|
|
1204
|
+
|
|
1205
|
+
.. SEEALSO::
|
|
1206
|
+
|
|
1207
|
+
:meth:`at_precision_absolute`, :meth:`add_bigoh`
|
|
1208
|
+
|
|
1209
|
+
TESTS::
|
|
1210
|
+
|
|
1211
|
+
sage: a.at_precision_relative(-1)
|
|
1212
|
+
Traceback (most recent call last):
|
|
1213
|
+
...
|
|
1214
|
+
ValueError: precision must be nonnegative
|
|
1215
|
+
"""
|
|
1216
|
+
if prec is Infinity:
|
|
1217
|
+
if not permissive and self._precbound < maxordp:
|
|
1218
|
+
raise_error(ERROR_PRECISION)
|
|
1219
|
+
return self
|
|
1220
|
+
default_prec = self._parent.default_prec()
|
|
1221
|
+
if prec is None:
|
|
1222
|
+
if permissive is None:
|
|
1223
|
+
permissive = True
|
|
1224
|
+
prec = default_prec
|
|
1225
|
+
else:
|
|
1226
|
+
prec = Integer(prec)
|
|
1227
|
+
if prec < 0:
|
|
1228
|
+
raise ValueError("precision must be nonnegative")
|
|
1229
|
+
if prec > maxordp:
|
|
1230
|
+
raise OverflowError("beyond maximal precision (which is %s)" % maxordp)
|
|
1231
|
+
if halt is True:
|
|
1232
|
+
halt = self._parent.halting_prec()
|
|
1233
|
+
elif halt is False:
|
|
1234
|
+
halt = maxordp
|
|
1235
|
+
else:
|
|
1236
|
+
halt = min(maxordp, halt)
|
|
1237
|
+
error = self._jump_relative_c(prec, halt)
|
|
1238
|
+
if permissive is None:
|
|
1239
|
+
permissive = False
|
|
1240
|
+
raise_error(error, permissive)
|
|
1241
|
+
return element_class_bound((<RelaxedElement>self)._parent, self, self._valuation + prec)
|
|
1242
|
+
|
|
1243
|
+
def lift_to_precision(self, absprec=None):
|
|
1244
|
+
"""
|
|
1245
|
+
Return another element of the same parent, lifting this element
|
|
1246
|
+
and having absolute precision at least ``absprec``.
|
|
1247
|
+
|
|
1248
|
+
INPUT:
|
|
1249
|
+
|
|
1250
|
+
- ``absprec`` -- integer or ``None`` (default: ``None``); the
|
|
1251
|
+
absolute precision of the result. If ``None``, the default
|
|
1252
|
+
precision of the parent is used.
|
|
1253
|
+
|
|
1254
|
+
EXAMPLES::
|
|
1255
|
+
|
|
1256
|
+
sage: R = ZpER(5, prec=10)
|
|
1257
|
+
sage: a = R(20/21, 5); a
|
|
1258
|
+
4*5 + 4*5^2 + 5^4 + O(5^5)
|
|
1259
|
+
|
|
1260
|
+
sage: a.lift_to_precision(20)
|
|
1261
|
+
4*5 + 4*5^2 + 5^4 + O(5^20)
|
|
1262
|
+
|
|
1263
|
+
When the precision is omitted, the default precision of the parent
|
|
1264
|
+
is used::
|
|
1265
|
+
|
|
1266
|
+
sage: a.lift_to_precision()
|
|
1267
|
+
4*5 + 4*5^2 + 5^4 + O(5^10)
|
|
1268
|
+
|
|
1269
|
+
When the parent is a field, the behaviour is slightly different since
|
|
1270
|
+
the default precision of the parent becomes the relative precision
|
|
1271
|
+
of the lifted element::
|
|
1272
|
+
|
|
1273
|
+
sage: K = R.fraction_field()
|
|
1274
|
+
sage: K(a).lift_to_precision()
|
|
1275
|
+
4*5 + 4*5^2 + 5^4 + O(5^11)
|
|
1276
|
+
|
|
1277
|
+
Note that the precision never decreases::
|
|
1278
|
+
|
|
1279
|
+
sage: a.lift_to_precision(2)
|
|
1280
|
+
4*5 + 4*5^2 + 5^4 + O(5^5)
|
|
1281
|
+
|
|
1282
|
+
In particular, unbounded element are not affected by this method::
|
|
1283
|
+
|
|
1284
|
+
sage: b = R(20/21); b
|
|
1285
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1286
|
+
sage: b.lift_to_precision()
|
|
1287
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1288
|
+
sage: b.lift_to_precision(2)
|
|
1289
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1290
|
+
"""
|
|
1291
|
+
if self._precbound >= maxordp:
|
|
1292
|
+
return self
|
|
1293
|
+
cdef long prec
|
|
1294
|
+
cdef long default_prec = self._parent.default_prec()
|
|
1295
|
+
if absprec is None:
|
|
1296
|
+
if self.prime_pow.in_field:
|
|
1297
|
+
self._jump_relative_c(1, self._precbound)
|
|
1298
|
+
if self._precrel == 0:
|
|
1299
|
+
return self._parent.zero()
|
|
1300
|
+
prec = self._valuation + default_prec
|
|
1301
|
+
else:
|
|
1302
|
+
prec = default_prec
|
|
1303
|
+
else:
|
|
1304
|
+
if absprec > maxordp:
|
|
1305
|
+
raise OverflowError("beyond the maximal precision (which is %s)" % maxordp)
|
|
1306
|
+
prec = absprec
|
|
1307
|
+
if prec <= self._precbound:
|
|
1308
|
+
return self
|
|
1309
|
+
cdef RelaxedElement ans = element_class_slice(self._parent, self, -maxordp, self._precbound, 0)
|
|
1310
|
+
ans._precbound = prec
|
|
1311
|
+
ans._init_jump()
|
|
1312
|
+
return ans
|
|
1313
|
+
|
|
1314
|
+
cdef long valuation_c(self, long halt=-maxordp) noexcept:
|
|
1315
|
+
r"""
|
|
1316
|
+
Return the best lower bound we have on the valuation of
|
|
1317
|
+
this element at the current stage of the computation.
|
|
1318
|
+
|
|
1319
|
+
INPUT:
|
|
1320
|
+
|
|
1321
|
+
- ``halt`` -- integer; if given, allow to increase the
|
|
1322
|
+
absolute precision on this element up to ``halt`` in order
|
|
1323
|
+
to get a better lower bound
|
|
1324
|
+
"""
|
|
1325
|
+
cdef int error = 0
|
|
1326
|
+
while not error and self._precrel == 0 and self._valuation < halt:
|
|
1327
|
+
error = self._next_c()
|
|
1328
|
+
return self._valuation
|
|
1329
|
+
|
|
1330
|
+
def valuation(self, halt=True, secure=None):
|
|
1331
|
+
r"""
|
|
1332
|
+
Return the valuation of this element.
|
|
1333
|
+
|
|
1334
|
+
INPUT:
|
|
1335
|
+
|
|
1336
|
+
- ``halt`` -- integer or boolean (default: ``True``);
|
|
1337
|
+
the absolute precision after which the computation is abandoned
|
|
1338
|
+
if the first significant digit has not been found yet.
|
|
1339
|
+
If ``True``, the default halting precision of the parent is used.
|
|
1340
|
+
If ``False``, the computation is never abandoned.
|
|
1341
|
+
|
|
1342
|
+
- ``secure`` -- boolean (default: the value given at the creation
|
|
1343
|
+
of the parent); when the valuation cannot be determined for sure,
|
|
1344
|
+
raise an error if ``secure`` is ``True``, return the best known
|
|
1345
|
+
lower bound on the valuation otherwise
|
|
1346
|
+
|
|
1347
|
+
EXAMPLES::
|
|
1348
|
+
|
|
1349
|
+
sage: R = ZpER(5, prec=10, halt=10)
|
|
1350
|
+
sage: a = R(2001); a
|
|
1351
|
+
1 + 5^3 + 3*5^4 + ...
|
|
1352
|
+
sage: a.valuation()
|
|
1353
|
+
0
|
|
1354
|
+
|
|
1355
|
+
sage: b = a - 1/a; b
|
|
1356
|
+
2*5^3 + 5^4 + 5^5 + 4*5^6 + 3*5^7 + 4*5^8 + 3*5^9 + 3*5^10 + 3*5^11 + 5^12 + ...
|
|
1357
|
+
sage: b.valuation()
|
|
1358
|
+
3
|
|
1359
|
+
|
|
1360
|
+
The valuation of an exact zero is `+\infty`::
|
|
1361
|
+
|
|
1362
|
+
sage: R(0).valuation()
|
|
1363
|
+
+Infinity
|
|
1364
|
+
|
|
1365
|
+
The valuation of an inexact zero is its absolute precision::
|
|
1366
|
+
|
|
1367
|
+
sage: R(0, 20).valuation()
|
|
1368
|
+
20
|
|
1369
|
+
|
|
1370
|
+
We illustrate the behaviour of the parameter ``halt``.
|
|
1371
|
+
We create a very small number whose first significant is far beyond
|
|
1372
|
+
the default precision::
|
|
1373
|
+
|
|
1374
|
+
sage: z = R(5^20)
|
|
1375
|
+
sage: z
|
|
1376
|
+
0 + ...
|
|
1377
|
+
|
|
1378
|
+
Without any help, Sage does not run the computation far enough to determine
|
|
1379
|
+
the valuation and outputs only a lower bound::
|
|
1380
|
+
|
|
1381
|
+
sage: z.valuation()
|
|
1382
|
+
10
|
|
1383
|
+
|
|
1384
|
+
With ``secure=True``, an error is raised::
|
|
1385
|
+
|
|
1386
|
+
sage: z.valuation(secure=True)
|
|
1387
|
+
Traceback (most recent call last):
|
|
1388
|
+
...
|
|
1389
|
+
PrecisionError: cannot determine the valuation; try to increase the halting precision
|
|
1390
|
+
|
|
1391
|
+
By setting the argument ``halt``, one can force the computation to continue
|
|
1392
|
+
until a prescribed limit::
|
|
1393
|
+
|
|
1394
|
+
sage: z.valuation(halt=15) # not enough to find the correct valuation
|
|
1395
|
+
15
|
|
1396
|
+
sage: z.valuation(halt=20, secure=True)
|
|
1397
|
+
Traceback (most recent call last):
|
|
1398
|
+
...
|
|
1399
|
+
PrecisionError: cannot determine the valuation; try to increase the halting precision
|
|
1400
|
+
|
|
1401
|
+
sage: z.valuation(halt=21) # now, we're okay
|
|
1402
|
+
20
|
|
1403
|
+
|
|
1404
|
+
.. NOTE::
|
|
1405
|
+
|
|
1406
|
+
It is also possible to pass in ``halt=False`` but it is not recommended
|
|
1407
|
+
because the computation can hang forever if this element is `0`.
|
|
1408
|
+
|
|
1409
|
+
TESTS::
|
|
1410
|
+
|
|
1411
|
+
sage: x = R.unknown()
|
|
1412
|
+
sage: (~x).valuation()
|
|
1413
|
+
Traceback (most recent call last):
|
|
1414
|
+
...
|
|
1415
|
+
PrecisionError: no lower bound on the valuation is known
|
|
1416
|
+
"""
|
|
1417
|
+
if self._is_exact_zero():
|
|
1418
|
+
return Infinity
|
|
1419
|
+
if self._valuation <= -maxordp:
|
|
1420
|
+
raise PrecisionError("no lower bound on the valuation is known")
|
|
1421
|
+
if halt is True:
|
|
1422
|
+
halt = self._parent.halting_prec()
|
|
1423
|
+
elif halt is False:
|
|
1424
|
+
halt = maxordp
|
|
1425
|
+
else:
|
|
1426
|
+
halt = min(maxordp, halt)
|
|
1427
|
+
cdef val = self.valuation_c(halt)
|
|
1428
|
+
if secure is None:
|
|
1429
|
+
secure = self._parent.is_secure()
|
|
1430
|
+
if secure and self._precbound >= maxordp and self._precrel == 0:
|
|
1431
|
+
raise PrecisionError("cannot determine the valuation; try to increase the halting precision")
|
|
1432
|
+
return Integer(val)
|
|
1433
|
+
|
|
1434
|
+
def unit_part(self, halt=True):
|
|
1435
|
+
r"""
|
|
1436
|
+
Return the unit part of this element.
|
|
1437
|
+
|
|
1438
|
+
INPUT:
|
|
1439
|
+
|
|
1440
|
+
- ``halt`` -- integer or boolean (default: ``True``);
|
|
1441
|
+
the absolute precision after which the computation is abandoned
|
|
1442
|
+
if the first significant digit has not been found yet.
|
|
1443
|
+
If ``True``, the default halting precision of the parent is used.
|
|
1444
|
+
If ``False``, the computation is never abandoned.
|
|
1445
|
+
|
|
1446
|
+
EXAMPLES::
|
|
1447
|
+
|
|
1448
|
+
sage: R = ZpER(5, prec=10, halt=10)
|
|
1449
|
+
sage: a = R(20/21); a
|
|
1450
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1451
|
+
sage: a.unit_part()
|
|
1452
|
+
4 + 4*5 + 5^3 + 4*5^5 + 3*5^6 + 4*5^7 + 5^9 + ...
|
|
1453
|
+
|
|
1454
|
+
sage: b = 1/a; b
|
|
1455
|
+
4*5^-1 + 4 + 3*5 + 3*5^2 + 3*5^3 + 3*5^4 + 3*5^5 + 3*5^6 + 3*5^7 + 3*5^8 + ...
|
|
1456
|
+
sage: b.unit_part()
|
|
1457
|
+
4 + 4*5 + 3*5^2 + 3*5^3 + 3*5^4 + 3*5^5 + 3*5^6 + 3*5^7 + 3*5^8 + 3*5^9 + ...
|
|
1458
|
+
|
|
1459
|
+
The unit part of `0` is not defined::
|
|
1460
|
+
|
|
1461
|
+
sage: R(0).unit_part()
|
|
1462
|
+
Traceback (most recent call last):
|
|
1463
|
+
...
|
|
1464
|
+
ValueError: unit part of 0 not defined
|
|
1465
|
+
|
|
1466
|
+
sage: R(0, 20).unit_part()
|
|
1467
|
+
Traceback (most recent call last):
|
|
1468
|
+
...
|
|
1469
|
+
ValueError: unit part of 0 not defined
|
|
1470
|
+
|
|
1471
|
+
See :meth:`valuation` for more details on the parameter ``halt``.
|
|
1472
|
+
"""
|
|
1473
|
+
val = self.valuation(halt)
|
|
1474
|
+
if self._valuation >= self._precbound:
|
|
1475
|
+
raise ValueError("unit part of 0 not defined")
|
|
1476
|
+
return self >> val
|
|
1477
|
+
|
|
1478
|
+
def val_unit(self, halt=True):
|
|
1479
|
+
r"""
|
|
1480
|
+
Return the valuation and the unit part of this element.
|
|
1481
|
+
|
|
1482
|
+
INPUT:
|
|
1483
|
+
|
|
1484
|
+
- ``halt`` -- integer or boolean (default: ``True``);
|
|
1485
|
+
the absolute precision after which the computation is abandoned
|
|
1486
|
+
if the first significant digit has not been found yet.
|
|
1487
|
+
If ``True``, the default halting precision of the parent is used.
|
|
1488
|
+
If ``False``, the computation is never abandoned.
|
|
1489
|
+
|
|
1490
|
+
EXAMPLES::
|
|
1491
|
+
|
|
1492
|
+
sage: R = ZpER(5, 10)
|
|
1493
|
+
sage: a = R(20/21); a
|
|
1494
|
+
4*5 + 4*5^2 + 5^4 + 4*5^6 + 3*5^7 + 4*5^8 + ...
|
|
1495
|
+
sage: a.val_unit()
|
|
1496
|
+
(1, 4 + 4*5 + 5^3 + 4*5^5 + 3*5^6 + 4*5^7 + 5^9 + ...)
|
|
1497
|
+
|
|
1498
|
+
sage: b = 1/a; b
|
|
1499
|
+
4*5^-1 + 4 + 3*5 + 3*5^2 + 3*5^3 + 3*5^4 + 3*5^5 + 3*5^6 + 3*5^7 + 3*5^8 + ...
|
|
1500
|
+
sage: b.val_unit()
|
|
1501
|
+
(-1, 4 + 4*5 + 3*5^2 + 3*5^3 + 3*5^4 + 3*5^5 + 3*5^6 + 3*5^7 + 3*5^8 + 3*5^9 + ...)
|
|
1502
|
+
|
|
1503
|
+
If this element is indistinguishable from zero, an error is raised
|
|
1504
|
+
since the unit part of `0` is not defined::
|
|
1505
|
+
|
|
1506
|
+
sage: R(0).unit_part()
|
|
1507
|
+
Traceback (most recent call last):
|
|
1508
|
+
...
|
|
1509
|
+
ValueError: unit part of 0 not defined
|
|
1510
|
+
|
|
1511
|
+
sage: R(0, 20).unit_part()
|
|
1512
|
+
Traceback (most recent call last):
|
|
1513
|
+
...
|
|
1514
|
+
ValueError: unit part of 0 not defined
|
|
1515
|
+
|
|
1516
|
+
See :meth:`valuation` for more details on the parameter ``halt``.
|
|
1517
|
+
"""
|
|
1518
|
+
val = self.valuation(halt)
|
|
1519
|
+
if self._valuation >= self._precbound:
|
|
1520
|
+
raise ValueError("unit part of 0 not defined")
|
|
1521
|
+
return val, self >> val
|
|
1522
|
+
|
|
1523
|
+
def residue(self, absprec=1, field=True, check_prec=True):
|
|
1524
|
+
r"""
|
|
1525
|
+
Return the image of this element in the quotient
|
|
1526
|
+
`\ZZ/p^\mathrm{absprec}\ZZ`.
|
|
1527
|
+
|
|
1528
|
+
INPUT:
|
|
1529
|
+
|
|
1530
|
+
- ``absprec`` -- nonnegative integer (default: 1)
|
|
1531
|
+
|
|
1532
|
+
- ``field`` -- boolean (default: ``True``); when ``absprec`` is ``1``,
|
|
1533
|
+
whether to return an element of GF(p) or Zmod(p)
|
|
1534
|
+
|
|
1535
|
+
- ``check_prec`` -- boolean (default: ``True``); whether to raise an error
|
|
1536
|
+
if this element has insufficient precision to determine the reduction
|
|
1537
|
+
|
|
1538
|
+
EXAMPLES::
|
|
1539
|
+
|
|
1540
|
+
sage: R = ZpER(7, 10)
|
|
1541
|
+
sage: a = R(1/2021); a
|
|
1542
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + 7^5 + 6*7^6 + 3*7^7 + 6*7^8 + 5*7^9 + ...
|
|
1543
|
+
sage: a.residue()
|
|
1544
|
+
3
|
|
1545
|
+
sage: a.residue(2)
|
|
1546
|
+
45
|
|
1547
|
+
|
|
1548
|
+
If this element has negative valuation, an error is raised::
|
|
1549
|
+
|
|
1550
|
+
sage: K = R.fraction_field()
|
|
1551
|
+
sage: b = K(20/21)
|
|
1552
|
+
sage: b.residue()
|
|
1553
|
+
Traceback (most recent call last):
|
|
1554
|
+
...
|
|
1555
|
+
ValueError: element must have nonnegative valuation in order to compute residue
|
|
1556
|
+
"""
|
|
1557
|
+
if absprec >= maxordp:
|
|
1558
|
+
raise OverflowError
|
|
1559
|
+
if absprec < 0:
|
|
1560
|
+
raise ValueError("cannot reduce modulo a negative power of p")
|
|
1561
|
+
error = self._jump_c(absprec)
|
|
1562
|
+
raise_error(error, not check_prec)
|
|
1563
|
+
if self._valuation < 0:
|
|
1564
|
+
raise ValueError("element must have nonnegative valuation in order to compute residue")
|
|
1565
|
+
cdef celement digits
|
|
1566
|
+
cdef Integer ans
|
|
1567
|
+
if absprec <= self._valuation:
|
|
1568
|
+
ans = ZZ(0)
|
|
1569
|
+
else:
|
|
1570
|
+
self._getslice_relative(digits, 0, min(self._precrel, absprec - self._valuation))
|
|
1571
|
+
ans = element_get_sage(digits, self.prime_pow) * self.prime_pow(self._valuation)
|
|
1572
|
+
if field and absprec == 1:
|
|
1573
|
+
return self._parent.residue_class_field()(ans)
|
|
1574
|
+
else:
|
|
1575
|
+
return self._parent.residue_ring(absprec)(ans)
|
|
1576
|
+
|
|
1577
|
+
def lift(self, absprec=None):
|
|
1578
|
+
r"""
|
|
1579
|
+
Return a rational number which is congruent to this element modulo
|
|
1580
|
+
`p^\mathrm{prec}`.
|
|
1581
|
+
|
|
1582
|
+
INPUT:
|
|
1583
|
+
|
|
1584
|
+
- ``absprec`` -- integer or ``None`` (default: ``None``); if ``None``,
|
|
1585
|
+
the absolute precision of this element is used
|
|
1586
|
+
|
|
1587
|
+
EXAMPLES::
|
|
1588
|
+
|
|
1589
|
+
sage: R = ZpER(7, 10)
|
|
1590
|
+
sage: a = R(1/2021, 5); a
|
|
1591
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + O(7^5)
|
|
1592
|
+
sage: a.lift()
|
|
1593
|
+
15676
|
|
1594
|
+
sage: a.lift(2)
|
|
1595
|
+
45
|
|
1596
|
+
|
|
1597
|
+
Here is another example with an element of negative valuation::
|
|
1598
|
+
|
|
1599
|
+
sage: K = R.fraction_field()
|
|
1600
|
+
sage: b = K(20/21, 5); b
|
|
1601
|
+
2*7^-1 + 3 + 2*7 + 2*7^2 + 2*7^3 + 2*7^4 + O(7^5)
|
|
1602
|
+
sage: b.lift()
|
|
1603
|
+
39223/7
|
|
1604
|
+
|
|
1605
|
+
For unbounded elements, we must specify a precision::
|
|
1606
|
+
|
|
1607
|
+
sage: c = R(1/2021)
|
|
1608
|
+
sage: c.lift()
|
|
1609
|
+
Traceback (most recent call last):
|
|
1610
|
+
...
|
|
1611
|
+
ValueError: you must specify a precision for unbounded elements
|
|
1612
|
+
|
|
1613
|
+
sage: c.lift(5)
|
|
1614
|
+
15676
|
|
1615
|
+
"""
|
|
1616
|
+
if absprec is None:
|
|
1617
|
+
if self._precbound < maxordp:
|
|
1618
|
+
absprec = self._precbound
|
|
1619
|
+
else:
|
|
1620
|
+
raise ValueError("you must specify a precision for unbounded elements")
|
|
1621
|
+
else:
|
|
1622
|
+
absprec = Integer(absprec)
|
|
1623
|
+
cdef int error = self._jump_c(absprec)
|
|
1624
|
+
raise_error(error)
|
|
1625
|
+
if absprec < self._valuation:
|
|
1626
|
+
return Integer(0)
|
|
1627
|
+
cdef celement digits
|
|
1628
|
+
self._getslice_relative(digits, 0, absprec - self._valuation)
|
|
1629
|
+
ans = element_get_sage(digits, self.prime_pow)
|
|
1630
|
+
if self._valuation:
|
|
1631
|
+
ans *= self._parent.prime() ** self._valuation
|
|
1632
|
+
return ans
|
|
1633
|
+
|
|
1634
|
+
def __rshift__(self, s):
|
|
1635
|
+
r"""
|
|
1636
|
+
Return this element divided by `\pi^s`, and truncated
|
|
1637
|
+
if the parent is not a field.
|
|
1638
|
+
|
|
1639
|
+
EXAMPLES::
|
|
1640
|
+
|
|
1641
|
+
sage: R = ZpER(997)
|
|
1642
|
+
sage: K = R.fraction_field()
|
|
1643
|
+
sage: a = R(123456878908); a
|
|
1644
|
+
964*997 + 572*997^2 + 124*997^3 + ...
|
|
1645
|
+
|
|
1646
|
+
Shifting to the right divides by a power of `p`, but drops
|
|
1647
|
+
terms with negative valuation::
|
|
1648
|
+
|
|
1649
|
+
sage: a >> 3
|
|
1650
|
+
124 + ...
|
|
1651
|
+
|
|
1652
|
+
If the parent is a field no truncation is performed::
|
|
1653
|
+
|
|
1654
|
+
sage: K(a) >> 3
|
|
1655
|
+
964*997^-2 + 572*997^-1 + 124 + ...
|
|
1656
|
+
|
|
1657
|
+
A negative shift multiplies by that power of `p`::
|
|
1658
|
+
|
|
1659
|
+
sage: a >> -3
|
|
1660
|
+
964*997^4 + 572*997^5 + 124*997^6 + ...
|
|
1661
|
+
"""
|
|
1662
|
+
cdef long start
|
|
1663
|
+
cdef long shift = s
|
|
1664
|
+
if shift:
|
|
1665
|
+
if (<RelaxedElement>self)._parent.is_field():
|
|
1666
|
+
start = -maxordp
|
|
1667
|
+
else:
|
|
1668
|
+
start = shift
|
|
1669
|
+
return element_class_slice((<pAdicRelaxedElement>self)._parent, self, start, maxordp, shift)
|
|
1670
|
+
else:
|
|
1671
|
+
return self
|
|
1672
|
+
|
|
1673
|
+
def __lshift__(self, s):
|
|
1674
|
+
r"""
|
|
1675
|
+
Return this element multiplied by `\pi^s`.
|
|
1676
|
+
|
|
1677
|
+
If `s` is negative and this element does not lie in a field,
|
|
1678
|
+
digits may be truncated. See ``__rshift__`` for details.
|
|
1679
|
+
|
|
1680
|
+
EXAMPLES::
|
|
1681
|
+
|
|
1682
|
+
sage: R = ZpER(997)
|
|
1683
|
+
sage: K = R.fraction_field()
|
|
1684
|
+
sage: a = R(123456878908); a
|
|
1685
|
+
964*997 + 572*997^2 + 124*997^3 + ...
|
|
1686
|
+
|
|
1687
|
+
Shifting to the right divides by a power of `p`, but drops
|
|
1688
|
+
terms with negative valuation::
|
|
1689
|
+
|
|
1690
|
+
sage: a << 2
|
|
1691
|
+
964*997^3 + 572*997^4 + 124*997^5 + ...
|
|
1692
|
+
|
|
1693
|
+
A negative shift may result in a truncation when the base
|
|
1694
|
+
ring is not a field::
|
|
1695
|
+
|
|
1696
|
+
sage: a << -3
|
|
1697
|
+
124 + ...
|
|
1698
|
+
|
|
1699
|
+
sage: K(a) << -3
|
|
1700
|
+
964*997^-2 + 572*997^-1 + 124 + ...
|
|
1701
|
+
"""
|
|
1702
|
+
return self.__rshift__(-s)
|
|
1703
|
+
|
|
1704
|
+
cpdef _add_(self, other):
|
|
1705
|
+
r"""
|
|
1706
|
+
Return the sum of this element with ``other``.
|
|
1707
|
+
|
|
1708
|
+
TESTS::
|
|
1709
|
+
|
|
1710
|
+
sage: R = ZpER(7, 10)
|
|
1711
|
+
sage: R(1/3) + R(1/6)
|
|
1712
|
+
4 + 3*7 + 3*7^2 + 3*7^3 + 3*7^4 + 3*7^5 + 3*7^6 + 3*7^7 + 3*7^8 + 3*7^9 + ...
|
|
1713
|
+
|
|
1714
|
+
sage: R(1/3, 5) + R(1/6, 10)
|
|
1715
|
+
4 + 3*7 + 3*7^2 + 3*7^3 + 3*7^4 + O(7^5)
|
|
1716
|
+
"""
|
|
1717
|
+
if isinstance(self, RelaxedElement_zero):
|
|
1718
|
+
return other
|
|
1719
|
+
if isinstance(other, RelaxedElement_zero):
|
|
1720
|
+
return self
|
|
1721
|
+
return element_class_add(self._parent, self, <RelaxedElement>other)
|
|
1722
|
+
|
|
1723
|
+
cpdef _sub_(self, other):
|
|
1724
|
+
r"""
|
|
1725
|
+
Return the difference of this element and ``other``.
|
|
1726
|
+
|
|
1727
|
+
EXAMPLES::
|
|
1728
|
+
|
|
1729
|
+
sage: R = ZpER(7, 10)
|
|
1730
|
+
sage: R(1/3) - R(1/6)
|
|
1731
|
+
6 + 5*7 + 5*7^2 + 5*7^3 + 5*7^4 + 5*7^5 + 5*7^6 + 5*7^7 + 5*7^8 + 5*7^9 + ...
|
|
1732
|
+
|
|
1733
|
+
sage: R(1/3, 5) - R(1/6, 10)
|
|
1734
|
+
6 + 5*7 + 5*7^2 + 5*7^3 + 5*7^4 + O(7^5)
|
|
1735
|
+
"""
|
|
1736
|
+
if self is other:
|
|
1737
|
+
ans = self._parent.zero()
|
|
1738
|
+
if self._precbound < maxordp:
|
|
1739
|
+
ans = element_class_bound(self._parent, ans, self._precbound)
|
|
1740
|
+
return ans
|
|
1741
|
+
if isinstance(other, RelaxedElement_zero):
|
|
1742
|
+
return self
|
|
1743
|
+
return element_class_sub(self._parent, self, <RelaxedElement>other)
|
|
1744
|
+
|
|
1745
|
+
cpdef _neg_(self):
|
|
1746
|
+
r"""
|
|
1747
|
+
Return the opposite of this element.
|
|
1748
|
+
|
|
1749
|
+
EXAMPLES::
|
|
1750
|
+
|
|
1751
|
+
sage: R = ZpER(7, 10)
|
|
1752
|
+
sage: -R(1)
|
|
1753
|
+
6 + 6*7 + 6*7^2 + 6*7^3 + 6*7^4 + 6*7^5 + 6*7^6 + 6*7^7 + 6*7^8 + 6*7^9 + ...
|
|
1754
|
+
|
|
1755
|
+
sage: -R(1,5)
|
|
1756
|
+
6 + 6*7 + 6*7^2 + 6*7^3 + 6*7^4 + O(7^5)
|
|
1757
|
+
"""
|
|
1758
|
+
if isinstance(self, RelaxedElement_zero):
|
|
1759
|
+
return self
|
|
1760
|
+
return element_class_sub(self._parent, self._parent.zero(), self)
|
|
1761
|
+
|
|
1762
|
+
cpdef _mul_(self, other):
|
|
1763
|
+
r"""
|
|
1764
|
+
Return the product of this element with ``other``.
|
|
1765
|
+
|
|
1766
|
+
EXAMPLES::
|
|
1767
|
+
|
|
1768
|
+
sage: R = ZpER(7, 10)
|
|
1769
|
+
sage: R(1/2) * R(2/3)
|
|
1770
|
+
5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + 4*7^6 + 4*7^7 + 4*7^8 + 4*7^9 + ...
|
|
1771
|
+
|
|
1772
|
+
sage: R(1/2, 5) * R(2/3, 10)
|
|
1773
|
+
5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + O(7^5)
|
|
1774
|
+
|
|
1775
|
+
sage: R(49, 5) * R(14, 4)
|
|
1776
|
+
2*7^3 + O(7^6)
|
|
1777
|
+
"""
|
|
1778
|
+
if isinstance(self, RelaxedElement_zero) or isinstance(other, RelaxedElement_one):
|
|
1779
|
+
return self
|
|
1780
|
+
if isinstance(self, RelaxedElement_one) or isinstance(other, RelaxedElement_zero):
|
|
1781
|
+
return other
|
|
1782
|
+
return element_class_mul(self._parent, self, <RelaxedElement>other)
|
|
1783
|
+
|
|
1784
|
+
cpdef _div_(self, other):
|
|
1785
|
+
r"""
|
|
1786
|
+
Return the quotient if this element by ``other``.
|
|
1787
|
+
|
|
1788
|
+
.. NOTE::
|
|
1789
|
+
|
|
1790
|
+
The result always lives in the fraction field, even if ``other`` is
|
|
1791
|
+
a unit.
|
|
1792
|
+
|
|
1793
|
+
EXAMPLES::
|
|
1794
|
+
|
|
1795
|
+
sage: R = ZpER(7, 10)
|
|
1796
|
+
sage: x = R(2) / R(3)
|
|
1797
|
+
sage: x
|
|
1798
|
+
3 + 2*7 + 2*7^2 + 2*7^3 + 2*7^4 + 2*7^5 + 2*7^6 + 2*7^7 + 2*7^8 + 2*7^9 + ...
|
|
1799
|
+
sage: x.parent()
|
|
1800
|
+
7-adic Field handled with relaxed arithmetics
|
|
1801
|
+
|
|
1802
|
+
TESTS::
|
|
1803
|
+
|
|
1804
|
+
sage: x / R(0)
|
|
1805
|
+
Traceback (most recent call last):
|
|
1806
|
+
...
|
|
1807
|
+
ZeroDivisionError: cannot divide by zero
|
|
1808
|
+
|
|
1809
|
+
sage: x / R(0, 10)
|
|
1810
|
+
Traceback (most recent call last):
|
|
1811
|
+
...
|
|
1812
|
+
ZeroDivisionError: cannot divide by something indistinguishable from zero
|
|
1813
|
+
|
|
1814
|
+
sage: y = R.unknown()
|
|
1815
|
+
sage: x / y
|
|
1816
|
+
O(7^-Infinity)
|
|
1817
|
+
"""
|
|
1818
|
+
if isinstance(other, RelaxedElement_one):
|
|
1819
|
+
if self.prime_pow.in_field:
|
|
1820
|
+
return self
|
|
1821
|
+
else:
|
|
1822
|
+
return element_class_bound(self._parent.fraction_field(), self)
|
|
1823
|
+
return element_class_div(self._parent.fraction_field(), self, <RelaxedElement>other, -maxordp)
|
|
1824
|
+
|
|
1825
|
+
def __invert__(self):
|
|
1826
|
+
r"""
|
|
1827
|
+
Return the multiplicative inverse of this element.
|
|
1828
|
+
|
|
1829
|
+
.. NOTE::
|
|
1830
|
+
|
|
1831
|
+
The result always lives in the fraction field, even if this element
|
|
1832
|
+
is a unit.
|
|
1833
|
+
|
|
1834
|
+
EXAMPLES::
|
|
1835
|
+
|
|
1836
|
+
sage: R = ZpER(7, 10)
|
|
1837
|
+
sage: x = ~R(3)
|
|
1838
|
+
sage: x
|
|
1839
|
+
5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + 4*7^6 + 4*7^7 + 4*7^8 + 4*7^9 + ...
|
|
1840
|
+
sage: x.parent()
|
|
1841
|
+
7-adic Field handled with relaxed arithmetics
|
|
1842
|
+
|
|
1843
|
+
TESTS::
|
|
1844
|
+
|
|
1845
|
+
sage: ~R(0)
|
|
1846
|
+
Traceback (most recent call last):
|
|
1847
|
+
...
|
|
1848
|
+
ZeroDivisionError: cannot divide by zero
|
|
1849
|
+
|
|
1850
|
+
sage: ~R(0, 10)
|
|
1851
|
+
Traceback (most recent call last):
|
|
1852
|
+
...
|
|
1853
|
+
ZeroDivisionError: cannot divide by something indistinguishable from zero
|
|
1854
|
+
|
|
1855
|
+
sage: y = R.unknown()
|
|
1856
|
+
sage: ~y
|
|
1857
|
+
O(7^-Infinity)
|
|
1858
|
+
"""
|
|
1859
|
+
if isinstance(self, RelaxedElement_one):
|
|
1860
|
+
return self
|
|
1861
|
+
return element_class_div(self._parent.fraction_field(), self._parent.one(), self, -maxordp)
|
|
1862
|
+
|
|
1863
|
+
def inverse_of_unit(self):
|
|
1864
|
+
r"""
|
|
1865
|
+
Return the multiplicative inverse of this element if
|
|
1866
|
+
it is a unit.
|
|
1867
|
+
|
|
1868
|
+
EXAMPLES::
|
|
1869
|
+
|
|
1870
|
+
sage: R = ZpER(3, 5)
|
|
1871
|
+
sage: a = R(2)
|
|
1872
|
+
sage: b = a.inverse_of_unit()
|
|
1873
|
+
sage: b
|
|
1874
|
+
2 + 3 + 3^2 + 3^3 + 3^4 + ...
|
|
1875
|
+
|
|
1876
|
+
A :exc:`ZeroDivisionError` is raised if an element has no inverse in the
|
|
1877
|
+
ring::
|
|
1878
|
+
|
|
1879
|
+
sage: R(3).inverse_of_unit()
|
|
1880
|
+
Traceback (most recent call last):
|
|
1881
|
+
...
|
|
1882
|
+
ZeroDivisionError: denominator is not invertible
|
|
1883
|
+
|
|
1884
|
+
Unlike the usual inverse of an element, the result is in the same ring
|
|
1885
|
+
as this element and not in its fraction field (for fields this does of
|
|
1886
|
+
course not make any difference)::
|
|
1887
|
+
|
|
1888
|
+
sage: c = ~a; c
|
|
1889
|
+
2 + 3 + 3^2 + 3^3 + 3^4 + ...
|
|
1890
|
+
sage: a.parent()
|
|
1891
|
+
3-adic Ring handled with relaxed arithmetics
|
|
1892
|
+
sage: b.parent()
|
|
1893
|
+
3-adic Ring handled with relaxed arithmetics
|
|
1894
|
+
sage: c.parent()
|
|
1895
|
+
3-adic Field handled with relaxed arithmetics
|
|
1896
|
+
|
|
1897
|
+
This method also works for self-referent numbers
|
|
1898
|
+
(see :meth:`sage.rings.padics.generic_nodes.pAdicRelaxedGeneric.unknown`)::
|
|
1899
|
+
|
|
1900
|
+
sage: x = R.unknown(); x
|
|
1901
|
+
O(3^0)
|
|
1902
|
+
sage: x.inverse_of_unit()
|
|
1903
|
+
O(3^0)
|
|
1904
|
+
sage: x.set(1 + 3 * x.inverse_of_unit())
|
|
1905
|
+
True
|
|
1906
|
+
sage: x
|
|
1907
|
+
1 + 3 + 2*3^2 + 3^3 + 3^4 + ...
|
|
1908
|
+
|
|
1909
|
+
Actually, in many cases, it is preferable to use it than an actual
|
|
1910
|
+
division. Indeed, compare::
|
|
1911
|
+
|
|
1912
|
+
sage: y = R.unknown()
|
|
1913
|
+
sage: y.set(1 + 3/y)
|
|
1914
|
+
Traceback (most recent call last):
|
|
1915
|
+
...
|
|
1916
|
+
RecursionError: definition looks circular
|
|
1917
|
+
"""
|
|
1918
|
+
if isinstance(self, RelaxedElement_one):
|
|
1919
|
+
return self
|
|
1920
|
+
if self.prime_pow.in_field:
|
|
1921
|
+
return element_class_div(self._parent, self._parent.one(), self, -maxordp)
|
|
1922
|
+
else:
|
|
1923
|
+
return element_class_div(self._parent, self._parent.one(), self, 0)
|
|
1924
|
+
|
|
1925
|
+
def sqrt(self):
|
|
1926
|
+
r"""
|
|
1927
|
+
Return the square root of this element.
|
|
1928
|
+
|
|
1929
|
+
EXAMPLES::
|
|
1930
|
+
|
|
1931
|
+
sage: R = ZpER(7, 10)
|
|
1932
|
+
sage: x = R(8)
|
|
1933
|
+
sage: x.sqrt()
|
|
1934
|
+
1 + 4*7 + 2*7^2 + 7^3 + 3*7^4 + 2*7^5 + 4*7^6 + 2*7^7 + 5*7^8 + ...
|
|
1935
|
+
|
|
1936
|
+
When the element is not a square, an error is raised::
|
|
1937
|
+
|
|
1938
|
+
sage: x = R(10)
|
|
1939
|
+
sage: x.sqrt()
|
|
1940
|
+
Traceback (most recent call last):
|
|
1941
|
+
...
|
|
1942
|
+
ValueError: not a square
|
|
1943
|
+
|
|
1944
|
+
For bounded elements, the precision is tracked::
|
|
1945
|
+
|
|
1946
|
+
sage: x = R(8, 5); x
|
|
1947
|
+
1 + 7 + O(7^5)
|
|
1948
|
+
sage: x.sqrt()
|
|
1949
|
+
1 + 4*7 + 2*7^2 + 7^3 + 3*7^4 + O(7^5)
|
|
1950
|
+
|
|
1951
|
+
Note that, when `p = 2`, a digit of precision is lost::
|
|
1952
|
+
|
|
1953
|
+
sage: S = ZpER(2)
|
|
1954
|
+
sage: x = S(17, 5)
|
|
1955
|
+
sage: x.sqrt()
|
|
1956
|
+
1 + 2^3 + O(2^4)
|
|
1957
|
+
|
|
1958
|
+
This method also work for self-referent numbers
|
|
1959
|
+
(see :meth:`sage.rings.padics.generic_nodes.pAdicRelaxedGeneric.unknown`)::
|
|
1960
|
+
|
|
1961
|
+
sage: x = R.unknown(); x
|
|
1962
|
+
O(7^0)
|
|
1963
|
+
sage: x.sqrt()
|
|
1964
|
+
O(7^0)
|
|
1965
|
+
sage: x.set(1 + 7*sqrt(x))
|
|
1966
|
+
True
|
|
1967
|
+
sage: x
|
|
1968
|
+
1 + 7 + 4*7^2 + 4*7^3 + 2*7^4 + 3*7^8 + 3*7^9 + ...
|
|
1969
|
+
|
|
1970
|
+
TESTS::
|
|
1971
|
+
|
|
1972
|
+
sage: for p in [ 7, 11, 1009 ]:
|
|
1973
|
+
....: R = ZpER(p)
|
|
1974
|
+
....: x = 1 + p * R.random_element()
|
|
1975
|
+
....: y = x.sqrt()
|
|
1976
|
+
....: assert(x == y^2)
|
|
1977
|
+
"""
|
|
1978
|
+
return element_class_sqrt(self._parent, self)
|
|
1979
|
+
|
|
1980
|
+
def _test_pickling(self, **options):
|
|
1981
|
+
r"""
|
|
1982
|
+
Check that this object can be pickled and unpickled properly.
|
|
1983
|
+
|
|
1984
|
+
TESTS::
|
|
1985
|
+
|
|
1986
|
+
sage: R = ZpER(7)
|
|
1987
|
+
sage: x = R.random_element()
|
|
1988
|
+
sage: x._test_pickling()
|
|
1989
|
+
|
|
1990
|
+
sage: x[:20]._test_pickling()
|
|
1991
|
+
|
|
1992
|
+
.. SEEALSO::
|
|
1993
|
+
|
|
1994
|
+
:func:`dumps`, :func:`loads`
|
|
1995
|
+
"""
|
|
1996
|
+
tester = self._tester(**options)
|
|
1997
|
+
from sage.misc.persist import loads, dumps
|
|
1998
|
+
if self._precbound >= maxordp:
|
|
1999
|
+
tester.assertEqual(loads(dumps(self)), self.at_precision_relative())
|
|
2000
|
+
else:
|
|
2001
|
+
tester.assertEqual(loads(dumps(self)), self)
|
|
2002
|
+
|
|
2003
|
+
def _test_nonzero_equal(self, **options):
|
|
2004
|
+
r"""
|
|
2005
|
+
Test that ``.__bool__()`` behave consistently with `` == 0``.
|
|
2006
|
+
|
|
2007
|
+
TESTS::
|
|
2008
|
+
|
|
2009
|
+
sage: R = ZpER(5)
|
|
2010
|
+
sage: #R(0)._test_nonzero_equal()
|
|
2011
|
+
sage: #R(5^30)._test_nonzero_equal()
|
|
2012
|
+
sage: #R.unknown()._test_nonzero_equal()
|
|
2013
|
+
"""
|
|
2014
|
+
tester = self._tester(**options)
|
|
2015
|
+
try:
|
|
2016
|
+
tester.assertEqual(self != self.parent().zero(), bool(self))
|
|
2017
|
+
tester.assertEqual(self == self.parent().zero(), not self)
|
|
2018
|
+
except PrecisionError:
|
|
2019
|
+
pass
|
|
2020
|
+
|
|
2021
|
+
|
|
2022
|
+
cdef class RelaxedElement_abandon(RelaxedElement):
|
|
2023
|
+
r"""
|
|
2024
|
+
A special class for relaxed `p`-adic with all digits unknown.
|
|
2025
|
+
|
|
2026
|
+
This class is used for setting temporary definition of
|
|
2027
|
+
some self-referent numbers.
|
|
2028
|
+
"""
|
|
2029
|
+
def __init__(self):
|
|
2030
|
+
r"""
|
|
2031
|
+
Initialize this element.
|
|
2032
|
+
|
|
2033
|
+
TESTS::
|
|
2034
|
+
|
|
2035
|
+
sage: from sage.rings.padics.padic_relaxed_element import RelaxedElement_abandon
|
|
2036
|
+
sage: x = RelaxedElement_abandon()
|
|
2037
|
+
sage: x.valuation()
|
|
2038
|
+
Traceback (most recent call last):
|
|
2039
|
+
...
|
|
2040
|
+
PrecisionError: no lower bound on the valuation is known
|
|
2041
|
+
|
|
2042
|
+
sage: x[0]
|
|
2043
|
+
Traceback (most recent call last):
|
|
2044
|
+
...
|
|
2045
|
+
PrecisionError: computation has been abandoned; try to increase precision
|
|
2046
|
+
"""
|
|
2047
|
+
self._valuation = -maxordp
|
|
2048
|
+
|
|
2049
|
+
cdef int _next_c(self) noexcept:
|
|
2050
|
+
r"""
|
|
2051
|
+
Compute the next digit of this element.
|
|
2052
|
+
|
|
2053
|
+
Here, we just abandon the computation.
|
|
2054
|
+
"""
|
|
2055
|
+
return ERROR_ABANDON
|
|
2056
|
+
|
|
2057
|
+
cdef relaxedelement_abandon = RelaxedElement_abandon()
|
|
2058
|
+
|
|
2059
|
+
|
|
2060
|
+
cdef class RelaxedElementWithDigits(RelaxedElement):
|
|
2061
|
+
r"""
|
|
2062
|
+
A generic class for relaxed `p`-adic elements that stores
|
|
2063
|
+
the sequence of its digits.
|
|
2064
|
+
"""
|
|
2065
|
+
def __cinit__(self):
|
|
2066
|
+
r"""
|
|
2067
|
+
Allocate memory for storing digits.
|
|
2068
|
+
"""
|
|
2069
|
+
element_init(self._digits)
|
|
2070
|
+
|
|
2071
|
+
def __dealloc__(self):
|
|
2072
|
+
r"""
|
|
2073
|
+
Deallocate memory used for digits.
|
|
2074
|
+
"""
|
|
2075
|
+
element_clear(self._digits)
|
|
2076
|
+
|
|
2077
|
+
cdef cdigit_ptr _getdigit_relative(self, long i) noexcept:
|
|
2078
|
+
r"""
|
|
2079
|
+
Return a pointer on the `i`-th digit of this number
|
|
2080
|
+
in relative precision.
|
|
2081
|
+
"""
|
|
2082
|
+
return element_get_digit(self._digits, i)
|
|
2083
|
+
|
|
2084
|
+
cdef cdigit_ptr _getdigit_absolute(self, long i) noexcept:
|
|
2085
|
+
r"""
|
|
2086
|
+
Return a pointer on the `i`-th digit of this number
|
|
2087
|
+
in absolute precision.
|
|
2088
|
+
"""
|
|
2089
|
+
return element_get_digit(self._digits, i - self._valuation)
|
|
2090
|
+
|
|
2091
|
+
cdef void _getslice_relative(self, celement slice, long start, long length) noexcept:
|
|
2092
|
+
r"""
|
|
2093
|
+
Select a slice of the sequence of digits of this element.
|
|
2094
|
+
|
|
2095
|
+
INPUT:
|
|
2096
|
+
|
|
2097
|
+
- ``slice`` -- a ``celement`` to store the slice
|
|
2098
|
+
|
|
2099
|
+
- ``start`` -- integer; the start position of the slice
|
|
2100
|
+
|
|
2101
|
+
- ``length`` -- integer; the length of the slice
|
|
2102
|
+
|
|
2103
|
+
.. NOTE::
|
|
2104
|
+
|
|
2105
|
+
This function only sets up a pointer to the requested slice
|
|
2106
|
+
(the slice is not copied). Hence any future modification
|
|
2107
|
+
of the slice will modify this element as well.
|
|
2108
|
+
"""
|
|
2109
|
+
element_get_slice(slice, self._digits, start, length)
|
|
2110
|
+
|
|
2111
|
+
|
|
2112
|
+
# Assignment
|
|
2113
|
+
############
|
|
2114
|
+
|
|
2115
|
+
# Zero
|
|
2116
|
+
|
|
2117
|
+
cdef class RelaxedElement_zero(RelaxedElement):
|
|
2118
|
+
r"""
|
|
2119
|
+
A class for representation a relaxed `p`-adic number which is
|
|
2120
|
+
exactly zero.
|
|
2121
|
+
|
|
2122
|
+
TESTS::
|
|
2123
|
+
|
|
2124
|
+
sage: R = ZpER(7)
|
|
2125
|
+
sage: a = R.zero()
|
|
2126
|
+
sage: TestSuite(a).run()
|
|
2127
|
+
"""
|
|
2128
|
+
def __init__(self, parent):
|
|
2129
|
+
r"""
|
|
2130
|
+
Initialize this element.
|
|
2131
|
+
|
|
2132
|
+
INPUT:
|
|
2133
|
+
|
|
2134
|
+
- ``parent`` -- the parent of this element
|
|
2135
|
+
|
|
2136
|
+
TESTS::
|
|
2137
|
+
|
|
2138
|
+
sage: R = ZpER(5)
|
|
2139
|
+
sage: x = R(0) # indirect doctest
|
|
2140
|
+
sage: x
|
|
2141
|
+
0
|
|
2142
|
+
|
|
2143
|
+
sage: type(x)
|
|
2144
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_zero'>
|
|
2145
|
+
"""
|
|
2146
|
+
RelaxedElement.__init__(self, parent)
|
|
2147
|
+
self._valuation = maxordp
|
|
2148
|
+
|
|
2149
|
+
def __reduce__(self):
|
|
2150
|
+
r"""
|
|
2151
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2152
|
+
element.
|
|
2153
|
+
|
|
2154
|
+
TESTS::
|
|
2155
|
+
|
|
2156
|
+
sage: a = ZpER(5)(0)
|
|
2157
|
+
sage: type(a)
|
|
2158
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_zero'>
|
|
2159
|
+
sage: loads(dumps(a)) == a # indirect doctest
|
|
2160
|
+
True
|
|
2161
|
+
"""
|
|
2162
|
+
return self.__class__, (self._parent,)
|
|
2163
|
+
|
|
2164
|
+
cdef cdigit_ptr _getdigit_relative(self, long i) noexcept:
|
|
2165
|
+
r"""
|
|
2166
|
+
Return a pointer on the `i`-th digit of this number
|
|
2167
|
+
in relative precision.
|
|
2168
|
+
"""
|
|
2169
|
+
return digit_zero
|
|
2170
|
+
|
|
2171
|
+
cdef cdigit_ptr _getdigit_absolute(self, long i) noexcept:
|
|
2172
|
+
r"""
|
|
2173
|
+
Return a pointer on the `i`-th digit of this number
|
|
2174
|
+
in absolute precision.
|
|
2175
|
+
"""
|
|
2176
|
+
return digit_zero
|
|
2177
|
+
|
|
2178
|
+
cdef void _getslice_relative(self, celement slice, long start, long length) noexcept:
|
|
2179
|
+
r"""
|
|
2180
|
+
Select a slice of the sequence of digits of this element.
|
|
2181
|
+
|
|
2182
|
+
INPUT:
|
|
2183
|
+
|
|
2184
|
+
- ``slice`` -- a ``celement`` to store the slice
|
|
2185
|
+
|
|
2186
|
+
- ``start`` -- integer; the start position of the slice
|
|
2187
|
+
|
|
2188
|
+
- ``length`` -- integer; the length of the slice
|
|
2189
|
+
"""
|
|
2190
|
+
element_init(slice)
|
|
2191
|
+
|
|
2192
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2193
|
+
r"""
|
|
2194
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
2195
|
+
|
|
2196
|
+
INPUT:
|
|
2197
|
+
|
|
2198
|
+
- ``prec`` -- integer
|
|
2199
|
+
|
|
2200
|
+
OUTPUT:
|
|
2201
|
+
|
|
2202
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2203
|
+
"""
|
|
2204
|
+
return 0
|
|
2205
|
+
|
|
2206
|
+
cdef int _next_c(self) noexcept:
|
|
2207
|
+
r"""
|
|
2208
|
+
Compute the next digit of this number.
|
|
2209
|
+
|
|
2210
|
+
OUTPUT:
|
|
2211
|
+
|
|
2212
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2213
|
+
"""
|
|
2214
|
+
return 0
|
|
2215
|
+
|
|
2216
|
+
|
|
2217
|
+
# One
|
|
2218
|
+
|
|
2219
|
+
cdef class RelaxedElement_one(RelaxedElementWithDigits):
|
|
2220
|
+
r"""
|
|
2221
|
+
A class for representation a relaxed `p`-adic number which is
|
|
2222
|
+
exactly one.
|
|
2223
|
+
|
|
2224
|
+
TESTS::
|
|
2225
|
+
|
|
2226
|
+
sage: R = ZpER(7)
|
|
2227
|
+
sage: a = R.one()
|
|
2228
|
+
sage: TestSuite(a).run()
|
|
2229
|
+
"""
|
|
2230
|
+
def __init__(self, parent):
|
|
2231
|
+
r"""
|
|
2232
|
+
Initialize this element.
|
|
2233
|
+
|
|
2234
|
+
INPUT:
|
|
2235
|
+
|
|
2236
|
+
- ``parent`` -- the parent of this element
|
|
2237
|
+
|
|
2238
|
+
TESTS::
|
|
2239
|
+
|
|
2240
|
+
sage: R = ZpER(5)
|
|
2241
|
+
sage: x = R(1) # indirect doctest
|
|
2242
|
+
sage: x
|
|
2243
|
+
1 + ...
|
|
2244
|
+
|
|
2245
|
+
sage: type(x)
|
|
2246
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_one'>
|
|
2247
|
+
"""
|
|
2248
|
+
RelaxedElement.__init__(self, parent)
|
|
2249
|
+
element_set_digit_ui(self._digits, 1, 0)
|
|
2250
|
+
self._precrel = 1
|
|
2251
|
+
|
|
2252
|
+
def __reduce__(self):
|
|
2253
|
+
r"""
|
|
2254
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2255
|
+
element.
|
|
2256
|
+
|
|
2257
|
+
TESTS::
|
|
2258
|
+
|
|
2259
|
+
sage: a = ZpER(5)(1)
|
|
2260
|
+
sage: type(a)
|
|
2261
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_one'>
|
|
2262
|
+
sage: a[:20] == loads(dumps(a)) # indirect doctest
|
|
2263
|
+
True
|
|
2264
|
+
"""
|
|
2265
|
+
return self.__class__, (self._parent,)
|
|
2266
|
+
|
|
2267
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2268
|
+
r"""
|
|
2269
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
2270
|
+
|
|
2271
|
+
INPUT:
|
|
2272
|
+
|
|
2273
|
+
- ``prec`` -- integer
|
|
2274
|
+
|
|
2275
|
+
OUTPUT:
|
|
2276
|
+
|
|
2277
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2278
|
+
"""
|
|
2279
|
+
if prec > self._precrel:
|
|
2280
|
+
self._precrel = prec
|
|
2281
|
+
return 0
|
|
2282
|
+
|
|
2283
|
+
cdef int _next_c(self) noexcept:
|
|
2284
|
+
r"""
|
|
2285
|
+
Compute the next digit of this number.
|
|
2286
|
+
|
|
2287
|
+
OUTPUT:
|
|
2288
|
+
|
|
2289
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2290
|
+
"""
|
|
2291
|
+
self._precrel += 1
|
|
2292
|
+
return 0
|
|
2293
|
+
|
|
2294
|
+
|
|
2295
|
+
# Bound
|
|
2296
|
+
|
|
2297
|
+
cdef class RelaxedElement_bound(RelaxedElement):
|
|
2298
|
+
r"""
|
|
2299
|
+
A class for `p`-adic relaxed elements which are defined by bounding the
|
|
2300
|
+
precision of another `p`-adic relaxed element.
|
|
2301
|
+
|
|
2302
|
+
TESTS::
|
|
2303
|
+
|
|
2304
|
+
sage: R = ZpER(5)
|
|
2305
|
+
sage: x = R.random_element()
|
|
2306
|
+
sage: y = x[:20]
|
|
2307
|
+
sage: TestSuite(y).run()
|
|
2308
|
+
"""
|
|
2309
|
+
def __init__(self, parent, RelaxedElement x, precbound=None):
|
|
2310
|
+
r"""
|
|
2311
|
+
Initialize this element.
|
|
2312
|
+
|
|
2313
|
+
INPUT:
|
|
2314
|
+
|
|
2315
|
+
- ``parent`` -- the parent of this element
|
|
2316
|
+
|
|
2317
|
+
- ``x`` -- a relaxed `p`-adics, the element to bound
|
|
2318
|
+
|
|
2319
|
+
- ``precbound`` -- integer or ``None`` (default: ``None``);
|
|
2320
|
+
the bound on the precision
|
|
2321
|
+
|
|
2322
|
+
.. NOTE::
|
|
2323
|
+
|
|
2324
|
+
The digits of ``x`` are not copied!
|
|
2325
|
+
|
|
2326
|
+
TESTS::
|
|
2327
|
+
|
|
2328
|
+
sage: R = ZpER(5)
|
|
2329
|
+
sage: x = R(20/21)
|
|
2330
|
+
sage: y = x.add_bigoh(20)
|
|
2331
|
+
sage: type(y)
|
|
2332
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_bound'>
|
|
2333
|
+
"""
|
|
2334
|
+
RelaxedElement.__init__(self, parent)
|
|
2335
|
+
self._x = x
|
|
2336
|
+
if precbound is None:
|
|
2337
|
+
self._precbound = x._precbound
|
|
2338
|
+
else:
|
|
2339
|
+
self._precbound = min(x._precbound, precbound)
|
|
2340
|
+
self._valuation = min(x._valuation, self._precbound)
|
|
2341
|
+
self._precrel = min(x._precrel, self._precbound - self._valuation)
|
|
2342
|
+
self._init_jump()
|
|
2343
|
+
|
|
2344
|
+
def __reduce__(self):
|
|
2345
|
+
r"""
|
|
2346
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2347
|
+
element.
|
|
2348
|
+
|
|
2349
|
+
TESTS::
|
|
2350
|
+
|
|
2351
|
+
sage: a = ZpER(5)(1).add_bigoh(20)
|
|
2352
|
+
sage: type(a)
|
|
2353
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_bound'>
|
|
2354
|
+
sage: a == loads(dumps(a)) # indirect doctest
|
|
2355
|
+
True
|
|
2356
|
+
"""
|
|
2357
|
+
return self.__class__, (self._parent, self._x, self._precbound)
|
|
2358
|
+
|
|
2359
|
+
cdef cdigit_ptr _getdigit_relative(self, long i) noexcept:
|
|
2360
|
+
r"""
|
|
2361
|
+
Return a pointer on the `i`-th digit of this number
|
|
2362
|
+
in relative precision.
|
|
2363
|
+
"""
|
|
2364
|
+
return self._x._getdigit_relative(i)
|
|
2365
|
+
|
|
2366
|
+
cdef cdigit_ptr _getdigit_absolute(self, long i) noexcept:
|
|
2367
|
+
r"""
|
|
2368
|
+
Return a pointer on the `i`-th digit of this number
|
|
2369
|
+
in absolute precision.
|
|
2370
|
+
"""
|
|
2371
|
+
return self._x._getdigit_absolute(i)
|
|
2372
|
+
|
|
2373
|
+
cdef void _getslice_relative(self, celement slice, long start, long length) noexcept:
|
|
2374
|
+
r"""
|
|
2375
|
+
Select a slice of the digits of this number.
|
|
2376
|
+
|
|
2377
|
+
INPUT:
|
|
2378
|
+
|
|
2379
|
+
- ``slice`` -- a ``celement`` to store the slice
|
|
2380
|
+
|
|
2381
|
+
- ``start`` -- positive integer; the starting position of the slice
|
|
2382
|
+
in relative precision
|
|
2383
|
+
|
|
2384
|
+
- ``length`` -- positive integer; the length of the slice
|
|
2385
|
+
|
|
2386
|
+
.. NOTE::
|
|
2387
|
+
|
|
2388
|
+
This methods only sets up a pointer to the requested slice
|
|
2389
|
+
(the slice is not copied). Hence any future modification
|
|
2390
|
+
of the slice ``slice`` will affect this number.
|
|
2391
|
+
"""
|
|
2392
|
+
self._x._getslice_relative(slice, start, length)
|
|
2393
|
+
|
|
2394
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2395
|
+
r"""
|
|
2396
|
+
Jump to the absolute precision ``prec``.
|
|
2397
|
+
|
|
2398
|
+
INPUT:
|
|
2399
|
+
|
|
2400
|
+
- ``prec`` -- integer
|
|
2401
|
+
|
|
2402
|
+
OUTPUT:
|
|
2403
|
+
|
|
2404
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2405
|
+
"""
|
|
2406
|
+
cdef RelaxedElement x = self._x
|
|
2407
|
+
cdef int error
|
|
2408
|
+
if prec > self._precbound:
|
|
2409
|
+
error = ERROR_PRECISION | x._jump_c(self._precbound)
|
|
2410
|
+
else:
|
|
2411
|
+
error = x._jump_c(prec)
|
|
2412
|
+
self._precbound = min(self._precbound, x._precbound)
|
|
2413
|
+
self._valuation = min(x._valuation, self._precbound)
|
|
2414
|
+
self._precrel = min(x._precrel, self._precbound - self._valuation)
|
|
2415
|
+
return error
|
|
2416
|
+
|
|
2417
|
+
cdef int _next_c(self) noexcept:
|
|
2418
|
+
r"""
|
|
2419
|
+
Jump to the next digit.
|
|
2420
|
+
|
|
2421
|
+
OUTPUT:
|
|
2422
|
+
|
|
2423
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2424
|
+
"""
|
|
2425
|
+
cdef RelaxedElement x = self._x
|
|
2426
|
+
if self._valuation + self._precrel >= self._precbound:
|
|
2427
|
+
return ERROR_PRECISION
|
|
2428
|
+
cdef int error = x._next_c()
|
|
2429
|
+
self._precbound = min(self._precbound, x._precbound)
|
|
2430
|
+
self._valuation = min(x._valuation, self._precbound)
|
|
2431
|
+
self._precrel = min(x._precrel, self._precbound - self._valuation)
|
|
2432
|
+
return error
|
|
2433
|
+
|
|
2434
|
+
|
|
2435
|
+
# Value
|
|
2436
|
+
|
|
2437
|
+
cdef class RelaxedElement_value(RelaxedElementWithDigits):
|
|
2438
|
+
r"""
|
|
2439
|
+
A class for relaxed `p`-adics defined by the datum of a value in
|
|
2440
|
+
the exact subring.
|
|
2441
|
+
|
|
2442
|
+
TESTS::
|
|
2443
|
+
|
|
2444
|
+
sage: R = ZpER(5)
|
|
2445
|
+
sage: x = R(2)
|
|
2446
|
+
sage: TestSuite(x).run()
|
|
2447
|
+
"""
|
|
2448
|
+
def __init__(self, parent, value, long shift=0, precbound=None):
|
|
2449
|
+
r"""
|
|
2450
|
+
Initialize this element.
|
|
2451
|
+
|
|
2452
|
+
INPUT:
|
|
2453
|
+
|
|
2454
|
+
- ``parent`` -- the parent of this element
|
|
2455
|
+
|
|
2456
|
+
- ``value`` -- the value in the exact subring
|
|
2457
|
+
|
|
2458
|
+
- ``shift`` -- integer (default: `0`); the position at which
|
|
2459
|
+
the given value is written
|
|
2460
|
+
|
|
2461
|
+
- ``precbound`` -- integer or ``None`` (default: ``None``);
|
|
2462
|
+
the bound on the precision
|
|
2463
|
+
|
|
2464
|
+
TESTS::
|
|
2465
|
+
|
|
2466
|
+
sage: R = ZpER(5)
|
|
2467
|
+
sage: x = R(2)
|
|
2468
|
+
sage: type(x)
|
|
2469
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_value'>
|
|
2470
|
+
|
|
2471
|
+
sage: y = R(2, 10)
|
|
2472
|
+
sage: type(y)
|
|
2473
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_value'>
|
|
2474
|
+
"""
|
|
2475
|
+
RelaxedElement.__init__(self, parent)
|
|
2476
|
+
element_set_digit_sage(self._digits, value, 0)
|
|
2477
|
+
self._value = value
|
|
2478
|
+
self._shift = shift
|
|
2479
|
+
self._valuation = -shift
|
|
2480
|
+
if precbound is not None and precbound is not Infinity:
|
|
2481
|
+
self._precbound = min(maxordp, precbound)
|
|
2482
|
+
self._valuebound = maxordp
|
|
2483
|
+
self._init_jump()
|
|
2484
|
+
|
|
2485
|
+
def __reduce__(self):
|
|
2486
|
+
r"""
|
|
2487
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2488
|
+
element.
|
|
2489
|
+
|
|
2490
|
+
TESTS::
|
|
2491
|
+
|
|
2492
|
+
sage: a = ZpER(5)(2, 20)
|
|
2493
|
+
sage: type(a)
|
|
2494
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_value'>
|
|
2495
|
+
sage: a == loads(dumps(a)) # indirect doctest
|
|
2496
|
+
True
|
|
2497
|
+
"""
|
|
2498
|
+
return self.__class__, (self._parent, self._value, self._shift, self._precbound)
|
|
2499
|
+
|
|
2500
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2501
|
+
r"""
|
|
2502
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
2503
|
+
|
|
2504
|
+
INPUT:
|
|
2505
|
+
|
|
2506
|
+
- ``prec`` -- integer
|
|
2507
|
+
|
|
2508
|
+
OUTPUT:
|
|
2509
|
+
|
|
2510
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2511
|
+
"""
|
|
2512
|
+
if self._valuebound >= maxordp:
|
|
2513
|
+
return RelaxedElement._jump_c(self, prec)
|
|
2514
|
+
if (self._precbound is not None) and (prec > self._precbound):
|
|
2515
|
+
self._precrel = self._precbound - self._valuation
|
|
2516
|
+
return ERROR_PRECISION
|
|
2517
|
+
cdef long precrel = min(prec, maxordp) - self._valuation
|
|
2518
|
+
if precrel > self._precrel:
|
|
2519
|
+
self._precrel = precrel
|
|
2520
|
+
if prec >= maxordp:
|
|
2521
|
+
return ERROR_OVERFLOW
|
|
2522
|
+
return 0
|
|
2523
|
+
|
|
2524
|
+
cdef int _next_c(self) noexcept:
|
|
2525
|
+
r"""
|
|
2526
|
+
Compute the next digit of this number.
|
|
2527
|
+
|
|
2528
|
+
OUTPUT:
|
|
2529
|
+
|
|
2530
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2531
|
+
|
|
2532
|
+
.. NOTE::
|
|
2533
|
+
|
|
2534
|
+
The algorithm is not optimal (quadratic in the precision),
|
|
2535
|
+
but it sounds okay...
|
|
2536
|
+
"""
|
|
2537
|
+
if (self._precbound is not None) and (self._valuation + self._precrel >= self._precbound):
|
|
2538
|
+
return ERROR_PRECISION
|
|
2539
|
+
element_reduce_digit(self._digits, self._precrel, self.prime_pow)
|
|
2540
|
+
if self._precrel == 0 and digit_is_zero(self._getdigit_relative(0)):
|
|
2541
|
+
self._valuation += 1
|
|
2542
|
+
element_shift_right(self._digits)
|
|
2543
|
+
else:
|
|
2544
|
+
self._precrel += 1
|
|
2545
|
+
if digit_is_zero(self._getdigit_relative(self._precrel)):
|
|
2546
|
+
self._valuebound = self._valuation + self._precrel
|
|
2547
|
+
if self._precrel == 0:
|
|
2548
|
+
self._valuation = self._precbound
|
|
2549
|
+
elif self._precbound < maxordp:
|
|
2550
|
+
self._precrel = self._precbound - self._valuation
|
|
2551
|
+
return 0
|
|
2552
|
+
|
|
2553
|
+
|
|
2554
|
+
# Random
|
|
2555
|
+
|
|
2556
|
+
cdef class RelaxedElement_random(RelaxedElementWithDigits):
|
|
2557
|
+
r"""
|
|
2558
|
+
A class for random relaxed `p`-adic numbers.
|
|
2559
|
+
|
|
2560
|
+
TESTS::
|
|
2561
|
+
|
|
2562
|
+
sage: R = ZpER(5)
|
|
2563
|
+
sage: x = R.random_element()
|
|
2564
|
+
sage: TestSuite(x).run()
|
|
2565
|
+
"""
|
|
2566
|
+
def __init__(self, parent, valuation, precbound=None, seed=None):
|
|
2567
|
+
r"""
|
|
2568
|
+
Initialize this element.
|
|
2569
|
+
|
|
2570
|
+
INPUT:
|
|
2571
|
+
|
|
2572
|
+
- ``parent`` -- the parent of this element
|
|
2573
|
+
|
|
2574
|
+
- ``valuation`` -- integer or ``None``; the position from which
|
|
2575
|
+
random digits are picked;
|
|
2576
|
+
if ``None``, it is randomly chosen if the parent is a field and
|
|
2577
|
+
set to `0` otherwise
|
|
2578
|
+
|
|
2579
|
+
- ``precbound`` -- integer or ``None`` (default: ``None``);
|
|
2580
|
+
the bound on the precision
|
|
2581
|
+
|
|
2582
|
+
- ``seed`` -- integer or ``None`` (default: ``None``); the
|
|
2583
|
+
seed of the random generator
|
|
2584
|
+
|
|
2585
|
+
.. NOTE::
|
|
2586
|
+
|
|
2587
|
+
The argument ``valuation`` can be different from the real
|
|
2588
|
+
valuation of this number since the first randomly picked
|
|
2589
|
+
digit could vanish.
|
|
2590
|
+
|
|
2591
|
+
TESTS::
|
|
2592
|
+
|
|
2593
|
+
sage: R = ZpER(7)
|
|
2594
|
+
sage: x = R.random_element()
|
|
2595
|
+
sage: type(x)
|
|
2596
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_random'>
|
|
2597
|
+
"""
|
|
2598
|
+
RelaxedElement.__init__(self, parent)
|
|
2599
|
+
if seed is None:
|
|
2600
|
+
self._seed = randint(0, 2*maxordp)
|
|
2601
|
+
else:
|
|
2602
|
+
self._seed = seed
|
|
2603
|
+
digit_random_init(self._generator, self._seed)
|
|
2604
|
+
if valuation is None:
|
|
2605
|
+
self._initialvaluation = ZZ.random_element()
|
|
2606
|
+
else:
|
|
2607
|
+
self._initialvaluation = valuation
|
|
2608
|
+
self._valuation = self._initialvaluation
|
|
2609
|
+
if precbound is not None:
|
|
2610
|
+
self._precbound = min(maxordp, precbound)
|
|
2611
|
+
self._init_jump()
|
|
2612
|
+
|
|
2613
|
+
def __reduce__(self):
|
|
2614
|
+
r"""
|
|
2615
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2616
|
+
element.
|
|
2617
|
+
|
|
2618
|
+
TESTS::
|
|
2619
|
+
|
|
2620
|
+
sage: R = ZpER(5, print_mode='digits')
|
|
2621
|
+
sage: a = R.random_element()
|
|
2622
|
+
sage: a # random
|
|
2623
|
+
...32220241412003314311
|
|
2624
|
+
|
|
2625
|
+
sage: b = loads(dumps(a))
|
|
2626
|
+
sage: b # random
|
|
2627
|
+
...32220241412003314311
|
|
2628
|
+
|
|
2629
|
+
It is guaranteed that `a` and `b` are equal at any precision::
|
|
2630
|
+
|
|
2631
|
+
sage: a[:30] # random
|
|
2632
|
+
...?343214211432220241412003314311
|
|
2633
|
+
sage: b[:30] # random
|
|
2634
|
+
...?343214211432220241412003314311
|
|
2635
|
+
|
|
2636
|
+
sage: a == b
|
|
2637
|
+
True
|
|
2638
|
+
"""
|
|
2639
|
+
return self.__class__, (self._parent, self._initialvaluation, self._precbound, self._seed)
|
|
2640
|
+
|
|
2641
|
+
cdef int _next_c(self) noexcept:
|
|
2642
|
+
r"""
|
|
2643
|
+
Generate the next digit of this number at random.
|
|
2644
|
+
|
|
2645
|
+
OUTPUT:
|
|
2646
|
+
|
|
2647
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2648
|
+
"""
|
|
2649
|
+
cdef cdigit r
|
|
2650
|
+
digit_init(r)
|
|
2651
|
+
digit_random(r, self.prime_pow, self._generator)
|
|
2652
|
+
if self._precrel == 0 and digit_is_zero(r):
|
|
2653
|
+
self._valuation += 1
|
|
2654
|
+
else:
|
|
2655
|
+
element_set_digit(self._digits, r, self._precrel)
|
|
2656
|
+
self._precrel += 1
|
|
2657
|
+
digit_clear(r)
|
|
2658
|
+
return 0
|
|
2659
|
+
|
|
2660
|
+
|
|
2661
|
+
# Operations
|
|
2662
|
+
############
|
|
2663
|
+
|
|
2664
|
+
# Slice and shift
|
|
2665
|
+
|
|
2666
|
+
cdef class RelaxedElement_slice(RelaxedElement):
|
|
2667
|
+
r"""
|
|
2668
|
+
A class for relaxed `p`-adic numbers defined as slices.
|
|
2669
|
+
|
|
2670
|
+
TESTS::
|
|
2671
|
+
|
|
2672
|
+
sage: R = ZpER(5)
|
|
2673
|
+
sage: x = R(20/21)
|
|
2674
|
+
sage: y = x.slice(3, 6)
|
|
2675
|
+
sage: TestSuite(y).run()
|
|
2676
|
+
"""
|
|
2677
|
+
def __init__(self, parent, RelaxedElement x, long start, long stop, long shift):
|
|
2678
|
+
r"""
|
|
2679
|
+
Initialize this element.
|
|
2680
|
+
|
|
2681
|
+
INPUT:
|
|
2682
|
+
|
|
2683
|
+
- ``parent`` -- the parent of this element
|
|
2684
|
+
|
|
2685
|
+
- ``x`` -- a relaxed `p`-adic element, the element from which the
|
|
2686
|
+
slice is extracted
|
|
2687
|
+
|
|
2688
|
+
- ``start`` -- integer; the position of the first digit of `x`
|
|
2689
|
+
in the slice
|
|
2690
|
+
|
|
2691
|
+
- ``stop`` -- integer; the position of the first digit of `x`
|
|
2692
|
+
after the slice
|
|
2693
|
+
|
|
2694
|
+
- ``shift`` -- integer such that ``self[i] = x[i+shift]``
|
|
2695
|
+
|
|
2696
|
+
.. NOTE::
|
|
2697
|
+
|
|
2698
|
+
The digits of ``x`` are not copied!
|
|
2699
|
+
|
|
2700
|
+
TESTS::
|
|
2701
|
+
|
|
2702
|
+
sage: R = ZpER(5)
|
|
2703
|
+
sage: x = R(20/21)
|
|
2704
|
+
sage: y = x.slice(3, 6)
|
|
2705
|
+
sage: type(y)
|
|
2706
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_slice'>
|
|
2707
|
+
"""
|
|
2708
|
+
RelaxedElement.__init__(self, parent)
|
|
2709
|
+
self._x = x
|
|
2710
|
+
self._start = start
|
|
2711
|
+
self._shift = shift
|
|
2712
|
+
self._valuation = max(x._valuation, start) - shift
|
|
2713
|
+
self._precrel = min(x._precrel + x._valuation, stop) - self._valuation - shift
|
|
2714
|
+
if x._precbound < stop:
|
|
2715
|
+
self._precbound = min(maxordp, x._precbound - shift)
|
|
2716
|
+
self._stop = stop
|
|
2717
|
+
if self._precrel < 0:
|
|
2718
|
+
self._precrel = 0
|
|
2719
|
+
while self._precrel > 0 and digit_is_zero(self._getdigit_relative(0)):
|
|
2720
|
+
self._precrel -= 1
|
|
2721
|
+
self._valuation += 1
|
|
2722
|
+
self._init_jump()
|
|
2723
|
+
|
|
2724
|
+
def __reduce__(self):
|
|
2725
|
+
r"""
|
|
2726
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2727
|
+
element.
|
|
2728
|
+
|
|
2729
|
+
TESTS::
|
|
2730
|
+
|
|
2731
|
+
sage: R = ZpER(5, print_mode='digits')
|
|
2732
|
+
sage: x = R(20/21)
|
|
2733
|
+
sage: y = x.slice(3, 6)
|
|
2734
|
+
sage: y == loads(dumps(y)) # indirect doctest
|
|
2735
|
+
True
|
|
2736
|
+
"""
|
|
2737
|
+
return self.__class__, (self._parent, self._x, self._start, self._stop, self._shift)
|
|
2738
|
+
|
|
2739
|
+
cdef cdigit_ptr _getdigit_relative(self, long i) noexcept:
|
|
2740
|
+
r"""
|
|
2741
|
+
Return a pointer on the `i`-th digit of this number
|
|
2742
|
+
in relative precision.
|
|
2743
|
+
"""
|
|
2744
|
+
return self._getdigit_absolute(i + self._valuation)
|
|
2745
|
+
|
|
2746
|
+
cdef cdigit_ptr _getdigit_absolute(self, long i) noexcept:
|
|
2747
|
+
r"""
|
|
2748
|
+
Return a pointer on the `i`-th digit of this number
|
|
2749
|
+
in absolute precision.
|
|
2750
|
+
"""
|
|
2751
|
+
cdef long j = i + self._shift
|
|
2752
|
+
if j < self._start or j >= self._stop:
|
|
2753
|
+
return digit_zero
|
|
2754
|
+
else:
|
|
2755
|
+
return self._x._getdigit_absolute(j)
|
|
2756
|
+
|
|
2757
|
+
cdef void _getslice_relative(self, celement slice, long start, long length) noexcept:
|
|
2758
|
+
r"""
|
|
2759
|
+
Select a slice of the sequence of digits of this element.
|
|
2760
|
+
|
|
2761
|
+
INPUT:
|
|
2762
|
+
|
|
2763
|
+
- ``slice`` -- a ``celement`` to store the slice
|
|
2764
|
+
|
|
2765
|
+
- ``start`` -- integer; the start position of the slice
|
|
2766
|
+
|
|
2767
|
+
- ``length`` -- integer; the length of the slice
|
|
2768
|
+
|
|
2769
|
+
.. NOTE::
|
|
2770
|
+
|
|
2771
|
+
This function only sets up a pointer to the requested slice
|
|
2772
|
+
(the slice is not copied). Hence any future modification
|
|
2773
|
+
of the slice will modify this element as well.
|
|
2774
|
+
"""
|
|
2775
|
+
cdef RelaxedElement x = self._x
|
|
2776
|
+
cdef long s = start + self._valuation + self._shift
|
|
2777
|
+
cdef long start_absolute = max(self._start, s)
|
|
2778
|
+
cdef long stop_absolute = min(self._stop, s + length)
|
|
2779
|
+
x._getslice_relative(slice, start_absolute - x._valuation, stop_absolute - start_absolute)
|
|
2780
|
+
|
|
2781
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2782
|
+
r"""
|
|
2783
|
+
Jump to the absolute precision ``prec``.
|
|
2784
|
+
|
|
2785
|
+
INPUT:
|
|
2786
|
+
|
|
2787
|
+
- ``prec`` -- integer
|
|
2788
|
+
|
|
2789
|
+
OUTPUT:
|
|
2790
|
+
|
|
2791
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2792
|
+
"""
|
|
2793
|
+
cdef RelaxedElement x = self._x
|
|
2794
|
+
cdef int error = 0
|
|
2795
|
+
cdef long pr
|
|
2796
|
+
if prec <= self._valuation + self._precrel:
|
|
2797
|
+
return 0
|
|
2798
|
+
if prec > self._precbound:
|
|
2799
|
+
prec = self._precbound
|
|
2800
|
+
error = ERROR_PRECISION
|
|
2801
|
+
cdef int errorx = x._jump_c(min(prec + self._shift, self._stop))
|
|
2802
|
+
pr = max(self._valuation, x._valuation + x._precrel - self._shift)
|
|
2803
|
+
if self._precrel == 0:
|
|
2804
|
+
while self._valuation < pr and digit_is_zero(self._getdigit_relative(0)):
|
|
2805
|
+
self._valuation += 1
|
|
2806
|
+
if errorx:
|
|
2807
|
+
self._precrel = pr - self._valuation
|
|
2808
|
+
return errorx
|
|
2809
|
+
else:
|
|
2810
|
+
self._precrel = prec - self._valuation
|
|
2811
|
+
return error
|
|
2812
|
+
|
|
2813
|
+
cdef int _next_c(self) noexcept:
|
|
2814
|
+
r"""
|
|
2815
|
+
Jump to the next digit.
|
|
2816
|
+
|
|
2817
|
+
OUTPUT:
|
|
2818
|
+
|
|
2819
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2820
|
+
"""
|
|
2821
|
+
cdef int error
|
|
2822
|
+
cdef long n = self._precrel + self._valuation
|
|
2823
|
+
n += self._shift
|
|
2824
|
+
if n <= self._stop:
|
|
2825
|
+
error = self._x._jump_c(n+1)
|
|
2826
|
+
if error:
|
|
2827
|
+
return error
|
|
2828
|
+
if self._precrel == 0 and (n > self._stop or digit_is_zero(self._getdigit_relative(0))):
|
|
2829
|
+
self._valuation += 1
|
|
2830
|
+
else:
|
|
2831
|
+
self._precrel += 1
|
|
2832
|
+
return 0
|
|
2833
|
+
|
|
2834
|
+
|
|
2835
|
+
# Addition
|
|
2836
|
+
|
|
2837
|
+
cdef class RelaxedElement_add(RelaxedElementWithDigits):
|
|
2838
|
+
r"""
|
|
2839
|
+
A class for relaxed `p`-adic numbers defined as sums.
|
|
2840
|
+
|
|
2841
|
+
TESTS::
|
|
2842
|
+
|
|
2843
|
+
sage: R = ZpER(11)
|
|
2844
|
+
sage: x = R.random_element() + R.random_element()
|
|
2845
|
+
sage: TestSuite(x).run()
|
|
2846
|
+
"""
|
|
2847
|
+
def __init__(self, parent, RelaxedElement x, RelaxedElement y):
|
|
2848
|
+
r"""
|
|
2849
|
+
Initialize this element.
|
|
2850
|
+
|
|
2851
|
+
INPUT:
|
|
2852
|
+
|
|
2853
|
+
- ``parent`` -- the parent of this element
|
|
2854
|
+
|
|
2855
|
+
- ``x`` -- a relaxed `p`-adic element, the first summand
|
|
2856
|
+
|
|
2857
|
+
- ``y`` -- a relaxed `p`-adic element, the second summand
|
|
2858
|
+
|
|
2859
|
+
TESTS::
|
|
2860
|
+
|
|
2861
|
+
sage: R = ZpER(11)
|
|
2862
|
+
sage: x = R.random_element() + R.random_element()
|
|
2863
|
+
sage: type(x)
|
|
2864
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_add'>
|
|
2865
|
+
"""
|
|
2866
|
+
RelaxedElement.__init__(self, parent)
|
|
2867
|
+
self._x = x
|
|
2868
|
+
self._y = y
|
|
2869
|
+
cdef halt = self._parent.default_prec()
|
|
2870
|
+
self._valuation = min(x.valuation_c(0), y.valuation_c(0))
|
|
2871
|
+
self._precbound = min(x._precbound, y._precbound)
|
|
2872
|
+
self._init_jump()
|
|
2873
|
+
|
|
2874
|
+
def __reduce__(self):
|
|
2875
|
+
r"""
|
|
2876
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2877
|
+
element.
|
|
2878
|
+
|
|
2879
|
+
TESTS::
|
|
2880
|
+
|
|
2881
|
+
sage: R = ZpER(5)
|
|
2882
|
+
sage: x = R.random_element() + R.random_element()
|
|
2883
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
2884
|
+
True
|
|
2885
|
+
"""
|
|
2886
|
+
return self.__class__, (self._parent, self._x, self._y)
|
|
2887
|
+
|
|
2888
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2889
|
+
r"""
|
|
2890
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
2891
|
+
|
|
2892
|
+
INPUT:
|
|
2893
|
+
|
|
2894
|
+
- ``prec`` -- integer
|
|
2895
|
+
|
|
2896
|
+
OUTPUT:
|
|
2897
|
+
|
|
2898
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2899
|
+
"""
|
|
2900
|
+
# We reimplement _jump_c for better performance
|
|
2901
|
+
cdef long n = self._valuation + self._precrel
|
|
2902
|
+
cdef RelaxedElement x = self._x
|
|
2903
|
+
cdef RelaxedElement y = self._y
|
|
2904
|
+
cdef int error = x._jump_c(prec) | y._jump_c(prec)
|
|
2905
|
+
prec = min(prec, x._valuation + x._precrel, y._valuation + y._precrel)
|
|
2906
|
+
while n < prec:
|
|
2907
|
+
element_iadd_digit(self._digits, x._getdigit_absolute(n), self._precrel)
|
|
2908
|
+
element_iadd_digit(self._digits, y._getdigit_absolute(n), self._precrel)
|
|
2909
|
+
element_reducesmall_digit(self._digits, self._precrel, self.prime_pow)
|
|
2910
|
+
if self._precrel == 0 and digit_is_zero(self._getdigit_relative(0)):
|
|
2911
|
+
self._valuation += 1
|
|
2912
|
+
element_shift_right(self._digits)
|
|
2913
|
+
else:
|
|
2914
|
+
self._precrel += 1
|
|
2915
|
+
n += 1
|
|
2916
|
+
return error
|
|
2917
|
+
|
|
2918
|
+
cdef int _next_c(self) noexcept:
|
|
2919
|
+
r"""
|
|
2920
|
+
Compute the next digit of this number.
|
|
2921
|
+
|
|
2922
|
+
OUTPUT:
|
|
2923
|
+
|
|
2924
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
2925
|
+
"""
|
|
2926
|
+
cdef long n = self._valuation + self._precrel
|
|
2927
|
+
cdef RelaxedElement x = self._x
|
|
2928
|
+
cdef RelaxedElement y = self._y
|
|
2929
|
+
cdef int error = x._jump_c(n+1) | y._jump_c(n+1)
|
|
2930
|
+
if error:
|
|
2931
|
+
return error
|
|
2932
|
+
element_iadd_digit(self._digits, x._getdigit_absolute(n), self._precrel)
|
|
2933
|
+
element_iadd_digit(self._digits, y._getdigit_absolute(n), self._precrel)
|
|
2934
|
+
element_reducesmall_digit(self._digits, self._precrel, self.prime_pow)
|
|
2935
|
+
if self._precrel == 0 and digit_is_zero(self._getdigit_relative(0)):
|
|
2936
|
+
self._valuation += 1
|
|
2937
|
+
element_shift_right(self._digits)
|
|
2938
|
+
else:
|
|
2939
|
+
self._precrel += 1
|
|
2940
|
+
return 0
|
|
2941
|
+
|
|
2942
|
+
|
|
2943
|
+
# Subtraction
|
|
2944
|
+
|
|
2945
|
+
cdef class RelaxedElement_sub(RelaxedElementWithDigits):
|
|
2946
|
+
r"""
|
|
2947
|
+
A class for relaxed `p`-adic numbers defined as differences.
|
|
2948
|
+
|
|
2949
|
+
TESTS::
|
|
2950
|
+
|
|
2951
|
+
sage: R = ZpER(11)
|
|
2952
|
+
sage: x = R.random_element() - R.random_element()
|
|
2953
|
+
sage: TestSuite(x).run()
|
|
2954
|
+
"""
|
|
2955
|
+
def __init__(self, parent, RelaxedElement x, RelaxedElement y):
|
|
2956
|
+
r"""
|
|
2957
|
+
Initialize this element.
|
|
2958
|
+
|
|
2959
|
+
INPUT:
|
|
2960
|
+
|
|
2961
|
+
- ``parent`` -- the parent of this element
|
|
2962
|
+
|
|
2963
|
+
- ``x`` -- a relaxed `p`-adic element, the minuend
|
|
2964
|
+
|
|
2965
|
+
- ``y`` -- a relaxed `p`-adic element, the subtrahend
|
|
2966
|
+
|
|
2967
|
+
TESTS::
|
|
2968
|
+
|
|
2969
|
+
sage: R = ZpER(11)
|
|
2970
|
+
sage: x = R.random_element() - R.random_element()
|
|
2971
|
+
sage: type(x)
|
|
2972
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_sub'>
|
|
2973
|
+
"""
|
|
2974
|
+
RelaxedElement.__init__(self, parent)
|
|
2975
|
+
self._x = x
|
|
2976
|
+
self._y = y
|
|
2977
|
+
self._valuation = min(x.valuation_c(0), y.valuation_c(0))
|
|
2978
|
+
self._precbound = min(x._precbound, y._precbound)
|
|
2979
|
+
self._init_jump()
|
|
2980
|
+
|
|
2981
|
+
def __reduce__(self):
|
|
2982
|
+
r"""
|
|
2983
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
2984
|
+
element.
|
|
2985
|
+
|
|
2986
|
+
TESTS::
|
|
2987
|
+
|
|
2988
|
+
sage: R = ZpER(5)
|
|
2989
|
+
sage: x = R.random_element() - R.random_element()
|
|
2990
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
2991
|
+
True
|
|
2992
|
+
"""
|
|
2993
|
+
return self.__class__, (self._parent, self._x, self._y)
|
|
2994
|
+
|
|
2995
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
2996
|
+
r"""
|
|
2997
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
2998
|
+
|
|
2999
|
+
INPUT:
|
|
3000
|
+
|
|
3001
|
+
- ``prec`` -- integer
|
|
3002
|
+
|
|
3003
|
+
OUTPUT:
|
|
3004
|
+
|
|
3005
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3006
|
+
"""
|
|
3007
|
+
# We reimplement _jump_c for better performances
|
|
3008
|
+
cdef long n = self._valuation + self._precrel
|
|
3009
|
+
cdef RelaxedElement x = self._x
|
|
3010
|
+
cdef RelaxedElement y = self._y
|
|
3011
|
+
cdef int error = x._jump_c(prec) | y._jump_c(prec)
|
|
3012
|
+
prec = min(prec, x._valuation + x._precrel, y._valuation + y._precrel)
|
|
3013
|
+
while n < prec:
|
|
3014
|
+
element_iadd_digit(self._digits, x._getdigit_absolute(n), self._precrel)
|
|
3015
|
+
element_isub_digit(self._digits, y._getdigit_absolute(n), self._precrel)
|
|
3016
|
+
element_reduceneg_digit(self._digits, self._precrel, self.prime_pow)
|
|
3017
|
+
if self._precrel == 0 and digit_is_zero(self._getdigit_relative(0)):
|
|
3018
|
+
self._valuation += 1
|
|
3019
|
+
element_shift_right(self._digits)
|
|
3020
|
+
else:
|
|
3021
|
+
self._precrel += 1
|
|
3022
|
+
n += 1
|
|
3023
|
+
return error
|
|
3024
|
+
|
|
3025
|
+
cdef int _next_c(self) noexcept:
|
|
3026
|
+
r"""
|
|
3027
|
+
Compute the next digit of this number.
|
|
3028
|
+
|
|
3029
|
+
OUTPUT:
|
|
3030
|
+
|
|
3031
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3032
|
+
"""
|
|
3033
|
+
cdef long n = self._valuation + self._precrel
|
|
3034
|
+
cdef RelaxedElement x = self._x
|
|
3035
|
+
cdef RelaxedElement y = self._y
|
|
3036
|
+
cdef int error = x._jump_c(n+1) | y._jump_c(n+1)
|
|
3037
|
+
if error:
|
|
3038
|
+
return error
|
|
3039
|
+
element_iadd_digit(self._digits, x._getdigit_absolute(n), self._precrel)
|
|
3040
|
+
element_isub_digit(self._digits, y._getdigit_absolute(n), self._precrel)
|
|
3041
|
+
element_reduceneg_digit(self._digits, self._precrel, self.prime_pow)
|
|
3042
|
+
if self._precrel == 0 and digit_is_zero(self._getdigit_relative(0)):
|
|
3043
|
+
self._valuation += 1
|
|
3044
|
+
element_shift_right(self._digits)
|
|
3045
|
+
else:
|
|
3046
|
+
self._precrel += 1
|
|
3047
|
+
return 0
|
|
3048
|
+
|
|
3049
|
+
|
|
3050
|
+
# Multiplication
|
|
3051
|
+
|
|
3052
|
+
cdef class RelaxedElement_mul(RelaxedElementWithDigits):
|
|
3053
|
+
r"""
|
|
3054
|
+
A class for relaxed `p`-adic numbers defined as products.
|
|
3055
|
+
|
|
3056
|
+
ALGORITHM:
|
|
3057
|
+
|
|
3058
|
+
We compute digits using relaxed arithmetic by var der Hoeven et al.,
|
|
3059
|
+
whose cost is quasi-linear with respect to the precision.
|
|
3060
|
+
|
|
3061
|
+
The algorithm uses the entries behind the current position in the table
|
|
3062
|
+
``self._digits`` to store carries.
|
|
3063
|
+
|
|
3064
|
+
TESTS::
|
|
3065
|
+
|
|
3066
|
+
sage: R = ZpER(11)
|
|
3067
|
+
sage: x = R.random_element() * R.random_element()
|
|
3068
|
+
sage: TestSuite(x).run()
|
|
3069
|
+
"""
|
|
3070
|
+
def __cinit__(self):
|
|
3071
|
+
r"""
|
|
3072
|
+
Allocate memory for temporary variables.
|
|
3073
|
+
"""
|
|
3074
|
+
digit_init(self._lastdigit_x)
|
|
3075
|
+
digit_init(self._lastdigit_y)
|
|
3076
|
+
|
|
3077
|
+
def __dealloc__(self):
|
|
3078
|
+
r"""
|
|
3079
|
+
Deallocate memory for temporary variables.
|
|
3080
|
+
"""
|
|
3081
|
+
digit_clear(self._lastdigit_x)
|
|
3082
|
+
digit_clear(self._lastdigit_y)
|
|
3083
|
+
|
|
3084
|
+
def __init__(self, parent, RelaxedElement x, RelaxedElement y):
|
|
3085
|
+
r"""
|
|
3086
|
+
Initialize this element.
|
|
3087
|
+
|
|
3088
|
+
INPUT:
|
|
3089
|
+
|
|
3090
|
+
- ``parent`` -- the parent of this element
|
|
3091
|
+
|
|
3092
|
+
- ``x`` -- a relaxed `p`-adic element, the first factor
|
|
3093
|
+
|
|
3094
|
+
- ``y`` -- a relaxed `p`-adic element, the second factor
|
|
3095
|
+
|
|
3096
|
+
TESTS::
|
|
3097
|
+
|
|
3098
|
+
sage: R = ZpER(11)
|
|
3099
|
+
sage: x = R.random_element() * R.random_element()
|
|
3100
|
+
sage: type(x)
|
|
3101
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_mul'>
|
|
3102
|
+
"""
|
|
3103
|
+
RelaxedElement.__init__(self, parent)
|
|
3104
|
+
self._x = x
|
|
3105
|
+
self._y = y
|
|
3106
|
+
cdef halt = self._parent.default_prec()
|
|
3107
|
+
self._valuation = min(maxordp, x.valuation_c(0) + y.valuation_c(0))
|
|
3108
|
+
if x._precbound < maxordp:
|
|
3109
|
+
y._jump_relative_c(1, y._valuation + self._parent.default_prec())
|
|
3110
|
+
self._precbound = min(self._precbound, y._valuation + x._precbound)
|
|
3111
|
+
if y._precbound < maxordp:
|
|
3112
|
+
x._jump_relative_c(1, x._valuation + self._parent.default_prec())
|
|
3113
|
+
self._precbound = min(self._precbound, x._valuation + y._precbound)
|
|
3114
|
+
self._init_jump()
|
|
3115
|
+
|
|
3116
|
+
def __reduce__(self):
|
|
3117
|
+
r"""
|
|
3118
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
3119
|
+
element.
|
|
3120
|
+
|
|
3121
|
+
TESTS::
|
|
3122
|
+
|
|
3123
|
+
sage: R = ZpER(5)
|
|
3124
|
+
sage: x = R.random_element() * R.random_element()
|
|
3125
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
3126
|
+
True
|
|
3127
|
+
"""
|
|
3128
|
+
return self.__class__, (self._parent, self._x, self._y)
|
|
3129
|
+
|
|
3130
|
+
cdef int _next_c(self) noexcept:
|
|
3131
|
+
r"""
|
|
3132
|
+
Compute the next digit of this number.
|
|
3133
|
+
|
|
3134
|
+
OUTPUT:
|
|
3135
|
+
|
|
3136
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3137
|
+
"""
|
|
3138
|
+
global tmp_digit, tmp_poly
|
|
3139
|
+
cdef RelaxedElement x = self._x
|
|
3140
|
+
cdef RelaxedElement y = self._y
|
|
3141
|
+
cdef long n = self._valuation + self._precrel
|
|
3142
|
+
|
|
3143
|
+
cdef int errorx = x._jump_c(n - y._valuation + 1)
|
|
3144
|
+
cdef int errory = y._jump_c(n - x._valuation + 1)
|
|
3145
|
+
cdef int error = errorx | errory
|
|
3146
|
+
if self._precrel == 0:
|
|
3147
|
+
self._valuation = x._valuation + y._valuation
|
|
3148
|
+
if self._valuation > n:
|
|
3149
|
+
return 0
|
|
3150
|
+
if self._valuation < n or x._precrel == 0 or y._precrel == 0:
|
|
3151
|
+
return error | ERROR_PRECISION
|
|
3152
|
+
elif error:
|
|
3153
|
+
return error
|
|
3154
|
+
|
|
3155
|
+
n = self._precrel
|
|
3156
|
+
digit_set(self._lastdigit_x, x._getdigit_relative(n))
|
|
3157
|
+
digit_set(self._lastdigit_y, y._getdigit_relative(n))
|
|
3158
|
+
digit_mul(tmp_digit, x._getdigit_relative(0), self._lastdigit_y)
|
|
3159
|
+
element_iadd_digit(self._digits, tmp_digit, n)
|
|
3160
|
+
if n:
|
|
3161
|
+
digit_mul(tmp_digit, self._lastdigit_x, y._getdigit_relative(0))
|
|
3162
|
+
element_iadd_digit(self._digits, tmp_digit, n)
|
|
3163
|
+
|
|
3164
|
+
cdef long m = n + 2
|
|
3165
|
+
cdef long len = 1
|
|
3166
|
+
cdef celement slicex, slicey
|
|
3167
|
+
while (m & 1 == 0) and (m > 3):
|
|
3168
|
+
m >>= 1
|
|
3169
|
+
len <<= 1
|
|
3170
|
+
x._getslice_relative(slicex, len - 1, len)
|
|
3171
|
+
y._getslice_relative(slicey, (m-1)*len - 1, len)
|
|
3172
|
+
element_mul(tmp_poly, slicex, slicey)
|
|
3173
|
+
element_iadd_slice(self._digits, tmp_poly, n)
|
|
3174
|
+
if m > 2:
|
|
3175
|
+
x._getslice_relative(slicex, (m-1)*len - 1, len)
|
|
3176
|
+
y._getslice_relative(slicey, len - 1, len)
|
|
3177
|
+
element_mul(tmp_poly, slicex, slicey)
|
|
3178
|
+
element_iadd_slice(self._digits, tmp_poly, n)
|
|
3179
|
+
|
|
3180
|
+
element_reduce_digit(self._digits, n, self.prime_pow)
|
|
3181
|
+
self._precrel += 1
|
|
3182
|
+
return 0
|
|
3183
|
+
|
|
3184
|
+
cdef int _update_last_digit(self) noexcept:
|
|
3185
|
+
r"""
|
|
3186
|
+
Redo the computation of the last digit and update carries
|
|
3187
|
+
accordingly.
|
|
3188
|
+
|
|
3189
|
+
This method is used for computing Teichmüller representatives.
|
|
3190
|
+
"""
|
|
3191
|
+
if self._precrel == 0:
|
|
3192
|
+
return ERROR_UNEXPECTED
|
|
3193
|
+
cdef RelaxedElement x = self._x
|
|
3194
|
+
cdef RelaxedElement y = self._y
|
|
3195
|
+
cdef long n = self._precrel - 1
|
|
3196
|
+
cdef long m = n + 2
|
|
3197
|
+
cdef long len = 2
|
|
3198
|
+
cdef celement slice
|
|
3199
|
+
while (m & 1 == 0) and (m > 3):
|
|
3200
|
+
m >>= 1
|
|
3201
|
+
len <<= 1
|
|
3202
|
+
len -= 1
|
|
3203
|
+
|
|
3204
|
+
digit_sub(tmp_digit, x._getdigit_relative(n), self._lastdigit_x)
|
|
3205
|
+
y._getslice_relative(slice, 0, len)
|
|
3206
|
+
element_scalarmul(tmp_poly, slice, tmp_digit)
|
|
3207
|
+
element_iadd_slice(self._digits, tmp_poly, n)
|
|
3208
|
+
if m == 2:
|
|
3209
|
+
len -= 1
|
|
3210
|
+
digit_sub(tmp_digit, y._getdigit_relative(n), self._lastdigit_y)
|
|
3211
|
+
x._getslice_relative(slice, 0, len)
|
|
3212
|
+
element_scalarmul(tmp_poly, slice, tmp_digit)
|
|
3213
|
+
element_iadd_slice(self._digits, tmp_poly, n)
|
|
3214
|
+
if m == 2:
|
|
3215
|
+
digit_mul(tmp_digit, tmp_digit, self._lastdigit_x)
|
|
3216
|
+
element_iadd_digit(self._digits, tmp_digit, 2*len)
|
|
3217
|
+
element_reduce_digit(self._digits, n, self.prime_pow)
|
|
3218
|
+
|
|
3219
|
+
digit_set(self._lastdigit_x, x._getdigit_relative(n))
|
|
3220
|
+
digit_set(self._lastdigit_y, y._getdigit_relative(n))
|
|
3221
|
+
return 0
|
|
3222
|
+
|
|
3223
|
+
|
|
3224
|
+
cdef class RelaxedElement_muldigit(RelaxedElementWithDigits):
|
|
3225
|
+
r"""
|
|
3226
|
+
A class for relaxed `p`-adic numbers defined as products
|
|
3227
|
+
of a relaxed `p`-adic number by a digit.
|
|
3228
|
+
|
|
3229
|
+
This class is not exposed to the user; it is only used
|
|
3230
|
+
internally for division.
|
|
3231
|
+
"""
|
|
3232
|
+
def __init__(self, parent, RelaxedElement_div x, RelaxedElement y):
|
|
3233
|
+
r"""
|
|
3234
|
+
Initialize this element.
|
|
3235
|
+
|
|
3236
|
+
INPUT:
|
|
3237
|
+
|
|
3238
|
+
- ``parent`` -- the parent of this element
|
|
3239
|
+
|
|
3240
|
+
- ``x`` -- a relaxed `p`-adic element, whose first significant
|
|
3241
|
+
digit is the first factor
|
|
3242
|
+
|
|
3243
|
+
- ``y`` -- a relaxed `p`-adic element, the second factor
|
|
3244
|
+
"""
|
|
3245
|
+
RelaxedElement.__init__(self, parent)
|
|
3246
|
+
self._x = <cdigit_ptr>x._inverse
|
|
3247
|
+
self._y = y
|
|
3248
|
+
self._valuation = y._valuation
|
|
3249
|
+
self._init_jump()
|
|
3250
|
+
|
|
3251
|
+
cdef int _next_c(self) noexcept:
|
|
3252
|
+
r"""
|
|
3253
|
+
Compute the next digit of this number.
|
|
3254
|
+
|
|
3255
|
+
OUTPUT:
|
|
3256
|
+
|
|
3257
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3258
|
+
"""
|
|
3259
|
+
cdef long n = self._valuation + self._precrel
|
|
3260
|
+
cdef int error = self._y._jump_c(n+1)
|
|
3261
|
+
if error:
|
|
3262
|
+
return error
|
|
3263
|
+
digit_mul(tmp_digit, self._x, self._y._getdigit_absolute(n))
|
|
3264
|
+
element_iadd_digit(self._digits, tmp_digit, self._precrel)
|
|
3265
|
+
element_reduce_digit(self._digits, self._precrel, self.prime_pow)
|
|
3266
|
+
self._precrel += 1
|
|
3267
|
+
return 0
|
|
3268
|
+
|
|
3269
|
+
|
|
3270
|
+
# Division
|
|
3271
|
+
|
|
3272
|
+
cdef class RelaxedElement_div(RelaxedElementWithDigits):
|
|
3273
|
+
r"""
|
|
3274
|
+
A class for relaxed `p`-adic numbers defined as quotients.
|
|
3275
|
+
|
|
3276
|
+
ALGORITHM:
|
|
3277
|
+
|
|
3278
|
+
We compute the quotient `x = a/b` as the self-referent number defined by
|
|
3279
|
+
|
|
3280
|
+
.. MATH::
|
|
3281
|
+
|
|
3282
|
+
x = ac + (1 - bc) x
|
|
3283
|
+
|
|
3284
|
+
where `c` is congruent to `b^{-1}` modulo the uniformizer.
|
|
3285
|
+
|
|
3286
|
+
TESTS::
|
|
3287
|
+
|
|
3288
|
+
sage: R = ZpER(5)
|
|
3289
|
+
sage: x = R(20) / R(21)
|
|
3290
|
+
sage: TestSuite(x).run()
|
|
3291
|
+
"""
|
|
3292
|
+
def __cinit__(self):
|
|
3293
|
+
r"""
|
|
3294
|
+
Allocate memory for temporary variables.
|
|
3295
|
+
"""
|
|
3296
|
+
digit_init(self._inverse)
|
|
3297
|
+
|
|
3298
|
+
def __dealloc__(self):
|
|
3299
|
+
r"""
|
|
3300
|
+
Deallocate memory for temporary variables.
|
|
3301
|
+
"""
|
|
3302
|
+
digit_clear(self._inverse)
|
|
3303
|
+
|
|
3304
|
+
def __init__(self, parent, RelaxedElement num, RelaxedElement denom, long minval=-maxordp, precbound=None):
|
|
3305
|
+
r"""
|
|
3306
|
+
Initialize this element.
|
|
3307
|
+
|
|
3308
|
+
INPUT:
|
|
3309
|
+
|
|
3310
|
+
- ``parent`` -- the parent of this element
|
|
3311
|
+
|
|
3312
|
+
- ``num`` -- a relaxed `p`-adic element, the dividend
|
|
3313
|
+
|
|
3314
|
+
- ``denom`` -- a relaxed `p`-adic element, the divisor
|
|
3315
|
+
|
|
3316
|
+
- ``minval`` -- integer; the minimal valuation allowed for this element
|
|
3317
|
+
|
|
3318
|
+
- ``precbound`` -- integer or ``None`` (default: ``None``);
|
|
3319
|
+
the bound on the precision
|
|
3320
|
+
|
|
3321
|
+
TESTS::
|
|
3322
|
+
|
|
3323
|
+
sage: R = ZpER(5)
|
|
3324
|
+
sage: x = R(20) / R(21)
|
|
3325
|
+
sage: type(x)
|
|
3326
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_div'>
|
|
3327
|
+
|
|
3328
|
+
sage: y = R.unknown()
|
|
3329
|
+
sage: 1/y
|
|
3330
|
+
O(5^-Infinity)
|
|
3331
|
+
sage: y.inverse_of_unit()
|
|
3332
|
+
O(5^0)
|
|
3333
|
+
"""
|
|
3334
|
+
RelaxedElement.__init__(self, parent)
|
|
3335
|
+
if denom._valuation >= maxordp:
|
|
3336
|
+
raise ZeroDivisionError("cannot divide by zero")
|
|
3337
|
+
if denom._precbound < maxordp and denom._precrel == 0:
|
|
3338
|
+
raise ZeroDivisionError("cannot divide by something indistinguishable from zero")
|
|
3339
|
+
self._num = num
|
|
3340
|
+
self._denom = denom
|
|
3341
|
+
if denom._valuation <= -maxordp:
|
|
3342
|
+
self._maxprec = maxordp + 1
|
|
3343
|
+
else:
|
|
3344
|
+
self._maxprec = denom._valuation + max(1, self._parent.default_prec())
|
|
3345
|
+
self._valuation = minval
|
|
3346
|
+
cdef int error = self._bootstrap_c()
|
|
3347
|
+
if precbound is not None:
|
|
3348
|
+
self._precbound = min(maxordp, precbound)
|
|
3349
|
+
if num._precbound < maxordp:
|
|
3350
|
+
self._precbound = min(self._precbound, num._precbound - denom._valuation)
|
|
3351
|
+
if denom._precbound < maxordp:
|
|
3352
|
+
self._precbound = min(self._precbound, denom._precbound + num._valuation - 2*denom._valuation)
|
|
3353
|
+
raise_error(error, permissive=True)
|
|
3354
|
+
if not error:
|
|
3355
|
+
self._init_jump()
|
|
3356
|
+
|
|
3357
|
+
def __reduce__(self):
|
|
3358
|
+
r"""
|
|
3359
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
3360
|
+
element.
|
|
3361
|
+
|
|
3362
|
+
TESTS::
|
|
3363
|
+
|
|
3364
|
+
sage: R = ZpER(5)
|
|
3365
|
+
sage: x = R(20) / R(21)
|
|
3366
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
3367
|
+
True
|
|
3368
|
+
"""
|
|
3369
|
+
return self.__class__, (self._parent, self._num, self._denom, self._valuation, self._precbound)
|
|
3370
|
+
|
|
3371
|
+
cdef int _bootstrap_c(self) noexcept:
|
|
3372
|
+
r"""
|
|
3373
|
+
Bootstrap the computation of the digits of this element, that is:
|
|
3374
|
+
|
|
3375
|
+
- find the valuation
|
|
3376
|
+
- compute the first digit, and
|
|
3377
|
+
- set up the recursive definition of the next digits.
|
|
3378
|
+
|
|
3379
|
+
OUTPUT:
|
|
3380
|
+
|
|
3381
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3382
|
+
"""
|
|
3383
|
+
cdef int error
|
|
3384
|
+
cdef RelaxedElement num = self._num
|
|
3385
|
+
cdef RelaxedElement denom = self._denom
|
|
3386
|
+
|
|
3387
|
+
while denom._valuation < self._maxprec and denom._precrel == 0:
|
|
3388
|
+
error = denom._next_c()
|
|
3389
|
+
if error:
|
|
3390
|
+
if error & ERROR_PRECISION:
|
|
3391
|
+
error |= ERROR_DIVISION
|
|
3392
|
+
return error
|
|
3393
|
+
if self._maxprec < maxordp and denom._valuation > -maxordp:
|
|
3394
|
+
self._maxprec = denom._valuation + max(1, self._parent.default_prec())
|
|
3395
|
+
if denom._precrel == 0:
|
|
3396
|
+
return ERROR_ABANDON
|
|
3397
|
+
|
|
3398
|
+
cdef long valuation = num._valuation - denom._valuation
|
|
3399
|
+
if valuation < self._valuation:
|
|
3400
|
+
error = num._jump_c(self._valuation + denom._valuation)
|
|
3401
|
+
if error:
|
|
3402
|
+
return error
|
|
3403
|
+
valuation = num._valuation - denom._valuation
|
|
3404
|
+
if valuation < self._valuation:
|
|
3405
|
+
return ERROR_DIVISION
|
|
3406
|
+
self._valuation = valuation
|
|
3407
|
+
digit_inv(self._inverse, denom._getdigit_relative(0), self.prime_pow)
|
|
3408
|
+
self._definition = relaxedelement_abandon
|
|
3409
|
+
cdef parent = self._parent
|
|
3410
|
+
cdef RelaxedElement a = element_class_muldigit(parent, self, num)
|
|
3411
|
+
cdef RelaxedElement b = element_class_muldigit(parent, self, denom)
|
|
3412
|
+
cdef RelaxedElement c = element_class_slice(parent, b, denom._valuation + 1, maxordp, 0)
|
|
3413
|
+
cdef RelaxedElement d = element_class_mul(parent, c, self)
|
|
3414
|
+
self._definition = element_class_sub(parent, a, d)
|
|
3415
|
+
return 0
|
|
3416
|
+
|
|
3417
|
+
cdef int _next_c(self) noexcept:
|
|
3418
|
+
r"""
|
|
3419
|
+
Compute the next digit of this number.
|
|
3420
|
+
|
|
3421
|
+
OUTPUT:
|
|
3422
|
+
|
|
3423
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3424
|
+
"""
|
|
3425
|
+
cdef RelaxedElement definition = self._definition
|
|
3426
|
+
if definition is None:
|
|
3427
|
+
return self._bootstrap_c()
|
|
3428
|
+
cdef long val = self._valuation + self._denom._valuation
|
|
3429
|
+
cdef int error = definition._jump_c(val + self._precrel + 1)
|
|
3430
|
+
if error:
|
|
3431
|
+
return error
|
|
3432
|
+
if definition._valuation > val:
|
|
3433
|
+
self._valuation = min(self._precbound, definition._valuation - self._denom._valuation)
|
|
3434
|
+
if definition._precbound < maxordp:
|
|
3435
|
+
self._precbound = min(self._precbound, definition._precbound - self._denom._valuation)
|
|
3436
|
+
else:
|
|
3437
|
+
digit = definition._getdigit_relative(self._precrel)
|
|
3438
|
+
element_set_digit(self._digits, digit, self._precrel)
|
|
3439
|
+
self._precrel += 1
|
|
3440
|
+
return 0
|
|
3441
|
+
|
|
3442
|
+
|
|
3443
|
+
# Square root
|
|
3444
|
+
|
|
3445
|
+
cdef class RelaxedElement_sqrt(RelaxedElementWithDigits):
|
|
3446
|
+
r"""
|
|
3447
|
+
A class for relaxed `p`-adic numbers defined as square roots.
|
|
3448
|
+
|
|
3449
|
+
ALGORITHM:
|
|
3450
|
+
|
|
3451
|
+
When `p \neq 2`, we compute `y = \sqrt{x}` as the self-referent number
|
|
3452
|
+
defined by
|
|
3453
|
+
|
|
3454
|
+
.. MATH::
|
|
3455
|
+
|
|
3456
|
+
y = \frac{x - (y-a)^2 + a^2}{2a}
|
|
3457
|
+
|
|
3458
|
+
where `a^2` is congruent to `x` modulo the uniformizer.
|
|
3459
|
+
|
|
3460
|
+
When `p = 2`, we use a variant of this construction.
|
|
3461
|
+
|
|
3462
|
+
TESTS::
|
|
3463
|
+
|
|
3464
|
+
sage: R = ZpER(5)
|
|
3465
|
+
sage: x = R(6).sqrt()
|
|
3466
|
+
sage: TestSuite(x).run()
|
|
3467
|
+
"""
|
|
3468
|
+
def __init__(self, parent, RelaxedElement x):
|
|
3469
|
+
r"""
|
|
3470
|
+
Initialize this element.
|
|
3471
|
+
|
|
3472
|
+
INPUT:
|
|
3473
|
+
|
|
3474
|
+
- ``parent`` -- the parent of this element
|
|
3475
|
+
|
|
3476
|
+
- ``x`` -- a relaxed `p`-adic element
|
|
3477
|
+
|
|
3478
|
+
TESTS::
|
|
3479
|
+
|
|
3480
|
+
sage: R = ZpER(5)
|
|
3481
|
+
sage: x = R(6).sqrt()
|
|
3482
|
+
sage: type(x)
|
|
3483
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_sqrt'>
|
|
3484
|
+
"""
|
|
3485
|
+
RelaxedElement.__init__(self, parent)
|
|
3486
|
+
self._x = x
|
|
3487
|
+
if x._valuation <= -maxordp:
|
|
3488
|
+
self._valuation = -maxordp
|
|
3489
|
+
else:
|
|
3490
|
+
self._valuation = x._valuation >> 1
|
|
3491
|
+
cdef int error = self._bootstrap_c()
|
|
3492
|
+
if error & ERROR_NOTSQUARE:
|
|
3493
|
+
raise ValueError("not a square")
|
|
3494
|
+
if not error:
|
|
3495
|
+
if x._precbound < maxordp:
|
|
3496
|
+
self._precbound = x._precbound - x._valuation / 2
|
|
3497
|
+
if self._parent.prime() == 2:
|
|
3498
|
+
self._precbound -= 1
|
|
3499
|
+
self._precbound = min(maxordp, self._precbound)
|
|
3500
|
+
self._init_jump()
|
|
3501
|
+
|
|
3502
|
+
def __reduce__(self):
|
|
3503
|
+
r"""
|
|
3504
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
3505
|
+
element.
|
|
3506
|
+
|
|
3507
|
+
TESTS::
|
|
3508
|
+
|
|
3509
|
+
sage: R = ZpER(5)
|
|
3510
|
+
sage: x = R(6).sqrt()
|
|
3511
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
3512
|
+
True
|
|
3513
|
+
"""
|
|
3514
|
+
return self.__class__, (self._parent, self._x)
|
|
3515
|
+
|
|
3516
|
+
cdef int _bootstrap_c(self) noexcept:
|
|
3517
|
+
r"""
|
|
3518
|
+
Bootstrap the computation of the digits of this element, that is:
|
|
3519
|
+
|
|
3520
|
+
- find the valuation
|
|
3521
|
+
- compute the first digit, and
|
|
3522
|
+
- set up the recursive definition of the next digits.
|
|
3523
|
+
|
|
3524
|
+
OUTPUT:
|
|
3525
|
+
|
|
3526
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3527
|
+
|
|
3528
|
+
.. NOTE::
|
|
3529
|
+
|
|
3530
|
+
This code does not work for nontrivial extensions of `\QQ_2`.
|
|
3531
|
+
"""
|
|
3532
|
+
cdef RelaxedElement x = self._x
|
|
3533
|
+
cdef long maxprec
|
|
3534
|
+
if x._valuation <= -maxordp:
|
|
3535
|
+
return ERROR_ABANDON
|
|
3536
|
+
if self._valuation <= -maxordp:
|
|
3537
|
+
maxprec = x._valuation
|
|
3538
|
+
else:
|
|
3539
|
+
maxprec = (self._valuation + 1) << 1
|
|
3540
|
+
while x._valuation < maxprec and x._precrel == 0:
|
|
3541
|
+
error = x._next_c()
|
|
3542
|
+
if error:
|
|
3543
|
+
return error
|
|
3544
|
+
if x._valuation & 1:
|
|
3545
|
+
self._valuation = (x._valuation + 1) >> 1
|
|
3546
|
+
else:
|
|
3547
|
+
self._valuation = x._valuation >> 1
|
|
3548
|
+
if x._precrel == 0:
|
|
3549
|
+
return 0
|
|
3550
|
+
if x._valuation & 1 != 0:
|
|
3551
|
+
return ERROR_NOTSQUARE
|
|
3552
|
+
|
|
3553
|
+
cdef parent = self._parent
|
|
3554
|
+
cdef long val = self._valuation
|
|
3555
|
+
cdef cdigit digit
|
|
3556
|
+
cdef Integer zd, p = self.prime_pow.prime
|
|
3557
|
+
cdef RelaxedElement u, y, c, d
|
|
3558
|
+
|
|
3559
|
+
if p == 2:
|
|
3560
|
+
element_set_digit_ui(self._digits, 1, 0)
|
|
3561
|
+
self._precrel = 1
|
|
3562
|
+
if x._precrel == 1:
|
|
3563
|
+
error = x._next_c()
|
|
3564
|
+
if error:
|
|
3565
|
+
return error
|
|
3566
|
+
if not digit_equal_ui(x._getdigit_relative(1), 0):
|
|
3567
|
+
return ERROR_NOTSQUARE
|
|
3568
|
+
if x._precrel == 2:
|
|
3569
|
+
error = x._next_c()
|
|
3570
|
+
if error:
|
|
3571
|
+
return error
|
|
3572
|
+
if not digit_equal_ui(x._getdigit_relative(2), 0):
|
|
3573
|
+
return ERROR_NOTSQUARE
|
|
3574
|
+
zd = Integer(1)
|
|
3575
|
+
self._definition = relaxedelement_abandon
|
|
3576
|
+
u = element_class_slice(parent, self, val + 2, maxordp, val)
|
|
3577
|
+
y = element_class_slice(parent, x, -maxordp, maxordp, val + 1)
|
|
3578
|
+
c = element_class_value(parent, zd, shift=-val+1)
|
|
3579
|
+
d = element_class_slice(parent, u*u, -maxordp, maxordp, -val + 1)
|
|
3580
|
+
self._definition = y + c - d
|
|
3581
|
+
else:
|
|
3582
|
+
digit_init(digit)
|
|
3583
|
+
if digit_sqrt(digit, x._getdigit_relative(0), self.prime_pow):
|
|
3584
|
+
digit_clear(digit)
|
|
3585
|
+
return ERROR_NOTSQUARE
|
|
3586
|
+
element_set_digit(self._digits, digit, 0)
|
|
3587
|
+
self._precrel = 1
|
|
3588
|
+
zd = digit_get_sage(digit)
|
|
3589
|
+
self._definition = relaxedelement_abandon
|
|
3590
|
+
u = element_class_slice(parent, self, val + 1, maxordp, val)
|
|
3591
|
+
y = element_class_slice(parent, x, -maxordp, maxordp, 2*val)
|
|
3592
|
+
c = element_class_value(parent, zd*zd)
|
|
3593
|
+
d = element_class_value(parent, 2*zd, shift=val)
|
|
3594
|
+
self._definition = (y + c - u*u) / d
|
|
3595
|
+
return 0
|
|
3596
|
+
|
|
3597
|
+
cdef int _next_c(self) noexcept:
|
|
3598
|
+
r"""
|
|
3599
|
+
Compute the next digit of this number.
|
|
3600
|
+
|
|
3601
|
+
OUTPUT:
|
|
3602
|
+
|
|
3603
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3604
|
+
"""
|
|
3605
|
+
cdef RelaxedElement definition = self._definition
|
|
3606
|
+
if definition is None:
|
|
3607
|
+
return self._bootstrap_c()
|
|
3608
|
+
cdef long n = self._valuation + self._precrel
|
|
3609
|
+
cdef int error = definition._jump_c(n+1)
|
|
3610
|
+
if error:
|
|
3611
|
+
return error
|
|
3612
|
+
element_set_digit(self._digits, definition._getdigit_relative(self._precrel), self._precrel)
|
|
3613
|
+
self._precrel += 1
|
|
3614
|
+
return 0
|
|
3615
|
+
|
|
3616
|
+
|
|
3617
|
+
# Teichmüller lifts
|
|
3618
|
+
|
|
3619
|
+
cdef class RelaxedElement_teichmuller(RelaxedElementWithDigits):
|
|
3620
|
+
r"""
|
|
3621
|
+
A class for relaxed `p`-adic numbers defined as teichmüller representatives.
|
|
3622
|
+
|
|
3623
|
+
ALGORITHM:
|
|
3624
|
+
|
|
3625
|
+
We compute `x = [a]` as the unique self-referent number with last
|
|
3626
|
+
digit `a` and `x = x^p`.
|
|
3627
|
+
Note that `x^p` is known with one more digit than `x` itself.
|
|
3628
|
+
|
|
3629
|
+
TESTS::
|
|
3630
|
+
|
|
3631
|
+
sage: R = ZpER(7)
|
|
3632
|
+
sage: x = R.teichmuller(2)
|
|
3633
|
+
sage: TestSuite(x).run()
|
|
3634
|
+
"""
|
|
3635
|
+
def __init__(self, parent, xbar):
|
|
3636
|
+
r"""
|
|
3637
|
+
Initialize this element.
|
|
3638
|
+
|
|
3639
|
+
INPUT:
|
|
3640
|
+
|
|
3641
|
+
- ``parent`` -- the parent of this element
|
|
3642
|
+
|
|
3643
|
+
- ``xbar`` -- an element in the exact subring, which is congruent
|
|
3644
|
+
to this Teichmüller modulo this uniformizer
|
|
3645
|
+
|
|
3646
|
+
TESTS::
|
|
3647
|
+
|
|
3648
|
+
sage: R = ZpER(7)
|
|
3649
|
+
sage: x = R.teichmuller(2)
|
|
3650
|
+
sage: type(x)
|
|
3651
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_teichmuller'>
|
|
3652
|
+
"""
|
|
3653
|
+
RelaxedElement.__init__(self, parent)
|
|
3654
|
+
cdef cdigit digit
|
|
3655
|
+
digit_init(digit)
|
|
3656
|
+
digit_set_sage(digit, xbar)
|
|
3657
|
+
digit_mod(digit, digit, self.prime_pow)
|
|
3658
|
+
if digit_equal_ui(digit, 0):
|
|
3659
|
+
digit_clear(digit)
|
|
3660
|
+
self._trivial = True
|
|
3661
|
+
self._valuation = maxordp
|
|
3662
|
+
else:
|
|
3663
|
+
element_set_digit(self._digits, digit, 0)
|
|
3664
|
+
self._trivial = digit_equal_ui(digit, 1)
|
|
3665
|
+
self._precrel += 1
|
|
3666
|
+
|
|
3667
|
+
cdef RelaxedElement xn
|
|
3668
|
+
cdef Integer p
|
|
3669
|
+
cdef int size, i
|
|
3670
|
+
if not self._trivial:
|
|
3671
|
+
xn = self
|
|
3672
|
+
p = self.prime_pow.prime
|
|
3673
|
+
size = mpz_sizeinbase(p.value, 2)
|
|
3674
|
+
i = size - 2
|
|
3675
|
+
self._xns = []
|
|
3676
|
+
while i >= 0:
|
|
3677
|
+
xn = element_class_mul(parent, xn, xn)
|
|
3678
|
+
self._xns.append(xn)
|
|
3679
|
+
if mpz_tstbit(p.value, i):
|
|
3680
|
+
xn = element_class_mul(parent, xn, self)
|
|
3681
|
+
self._xns.append(xn)
|
|
3682
|
+
i -= 1
|
|
3683
|
+
self._xp = xn
|
|
3684
|
+
self._ready = True
|
|
3685
|
+
|
|
3686
|
+
def __reduce__(self):
|
|
3687
|
+
r"""
|
|
3688
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
3689
|
+
element.
|
|
3690
|
+
|
|
3691
|
+
TESTS::
|
|
3692
|
+
|
|
3693
|
+
sage: R = ZpER(7)
|
|
3694
|
+
sage: x = R.teichmuller(2)
|
|
3695
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
3696
|
+
True
|
|
3697
|
+
"""
|
|
3698
|
+
xbar = digit_get_sage(element_get_digit(self._digits, 0))
|
|
3699
|
+
return self.__class__, (self._parent, xbar)
|
|
3700
|
+
|
|
3701
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
3702
|
+
r"""
|
|
3703
|
+
Compute the digits of this number until the absolute precision ``prec``.
|
|
3704
|
+
|
|
3705
|
+
INPUT:
|
|
3706
|
+
|
|
3707
|
+
- ``prec`` -- integer
|
|
3708
|
+
|
|
3709
|
+
OUTPUT:
|
|
3710
|
+
|
|
3711
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3712
|
+
"""
|
|
3713
|
+
if not self._ready:
|
|
3714
|
+
return ERROR_ABANDON
|
|
3715
|
+
if self._trivial:
|
|
3716
|
+
if self._valuation == 0 and self._precrel < prec:
|
|
3717
|
+
self._precrel = prec
|
|
3718
|
+
return 0
|
|
3719
|
+
return RelaxedElement._jump_c(<RelaxedElement>self, prec)
|
|
3720
|
+
|
|
3721
|
+
cdef int _next_c(self) noexcept:
|
|
3722
|
+
r"""
|
|
3723
|
+
Compute the next digit of this number.
|
|
3724
|
+
|
|
3725
|
+
OUTPUT:
|
|
3726
|
+
|
|
3727
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3728
|
+
"""
|
|
3729
|
+
if self._trivial:
|
|
3730
|
+
if self._valuation:
|
|
3731
|
+
self._precrel += 1
|
|
3732
|
+
return 0
|
|
3733
|
+
cdef int error
|
|
3734
|
+
cdef RelaxedElement xp = self._xp
|
|
3735
|
+
cdef RelaxedElement_mul xn
|
|
3736
|
+
self._precrel += 1
|
|
3737
|
+
xp._jump_c(self._precrel)
|
|
3738
|
+
element_set_digit(self._digits, xp._getdigit_relative(self._precrel - 1), self._precrel - 1)
|
|
3739
|
+
for xn in self._xns:
|
|
3740
|
+
error = xn._update_last_digit()
|
|
3741
|
+
if error:
|
|
3742
|
+
return error | ERROR_UNEXPECTED
|
|
3743
|
+
return 0
|
|
3744
|
+
|
|
3745
|
+
|
|
3746
|
+
# Self-referent definitions
|
|
3747
|
+
###########################
|
|
3748
|
+
|
|
3749
|
+
cdef class RelaxedElement_unknown(RelaxedElementWithDigits):
|
|
3750
|
+
r"""
|
|
3751
|
+
A class for self-referent relaxed `p`-adic numbers.
|
|
3752
|
+
|
|
3753
|
+
TESTS::
|
|
3754
|
+
|
|
3755
|
+
sage: R = ZpER(7)
|
|
3756
|
+
sage: x = R.unknown()
|
|
3757
|
+
sage: TestSuite(x).run()
|
|
3758
|
+
|
|
3759
|
+
sage: x.set(1 + 7*x^2)
|
|
3760
|
+
True
|
|
3761
|
+
sage: TestSuite(x).run()
|
|
3762
|
+
"""
|
|
3763
|
+
def __init__(self, parent, long valuation, digits=None):
|
|
3764
|
+
r"""
|
|
3765
|
+
Initialize this element.
|
|
3766
|
+
|
|
3767
|
+
INPUT:
|
|
3768
|
+
|
|
3769
|
+
- ``parent`` -- the parent of this element
|
|
3770
|
+
|
|
3771
|
+
- ``valuation`` -- integer; a lower bound on the valuation of
|
|
3772
|
+
this number
|
|
3773
|
+
|
|
3774
|
+
- ``digits`` -- list or ``None`` (default: ``None``); the first
|
|
3775
|
+
significant digits of this number
|
|
3776
|
+
|
|
3777
|
+
TESTS::
|
|
3778
|
+
|
|
3779
|
+
sage: R = ZpER(7)
|
|
3780
|
+
sage: x = R.unknown()
|
|
3781
|
+
sage: type(x)
|
|
3782
|
+
<class 'sage.rings.padics.padic_relaxed_element.pAdicRelaxedElement_unknown'>
|
|
3783
|
+
"""
|
|
3784
|
+
RelaxedElement.__init__(self, parent)
|
|
3785
|
+
if valuation >= maxordp:
|
|
3786
|
+
raise OverflowError("valuation is too large (maximum is %s)" % maxordp)
|
|
3787
|
+
self._valuation = valuation
|
|
3788
|
+
self._definition = None
|
|
3789
|
+
self._next = maxordp
|
|
3790
|
+
cdef cdigit digit
|
|
3791
|
+
if digits is not None:
|
|
3792
|
+
digits = [Integer(d) for d in digits]
|
|
3793
|
+
for d in digits:
|
|
3794
|
+
digit_set_sage(digit, d)
|
|
3795
|
+
element_iadd_digit(self._digits, digit, self._precrel)
|
|
3796
|
+
element_reduce_digit(self._digits, self._precrel, self.prime_pow)
|
|
3797
|
+
if self._precrel == 0 and digit_is_zero(element_get_digit(self._digits, 0)):
|
|
3798
|
+
self._valuation += 1
|
|
3799
|
+
element_shift_right(self._digits)
|
|
3800
|
+
else:
|
|
3801
|
+
self._precrel += 1
|
|
3802
|
+
self._initialvaluation = self._valuation
|
|
3803
|
+
self._initialprecrel = self._precrel
|
|
3804
|
+
|
|
3805
|
+
def __reduce__(self):
|
|
3806
|
+
r"""
|
|
3807
|
+
Return a tuple of a function and data that can be used to unpickle this
|
|
3808
|
+
element.
|
|
3809
|
+
|
|
3810
|
+
TESTS::
|
|
3811
|
+
|
|
3812
|
+
sage: R = ZpER(7)
|
|
3813
|
+
sage: x = R.unknown()
|
|
3814
|
+
sage: x.set(1 + 7*x^2)
|
|
3815
|
+
True
|
|
3816
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
3817
|
+
True
|
|
3818
|
+
"""
|
|
3819
|
+
digits = []
|
|
3820
|
+
for i in range(self._initialprecrel):
|
|
3821
|
+
digits.append(digit_get_sage(element_get_digit(self._digits, i)))
|
|
3822
|
+
definition = None
|
|
3823
|
+
if id(self) not in persist.already_pickled:
|
|
3824
|
+
persist.already_pickled[id(self)] = True
|
|
3825
|
+
definition = self._definition
|
|
3826
|
+
return unpickle_unknown, (id(self), self.__class__, self._parent, self._initialvaluation, digits, definition)
|
|
3827
|
+
|
|
3828
|
+
cpdef set(self, RelaxedElement definition):
|
|
3829
|
+
r"""
|
|
3830
|
+
Set the recursive definition of this self-referent number.
|
|
3831
|
+
|
|
3832
|
+
INPUT:
|
|
3833
|
+
|
|
3834
|
+
- ``definition`` -- a relaxed `p`-adic number, to which this
|
|
3835
|
+
number is equal
|
|
3836
|
+
|
|
3837
|
+
OUTPUT:
|
|
3838
|
+
|
|
3839
|
+
A boolean indicating if the definition is coherent with the
|
|
3840
|
+
already known digits of this number.
|
|
3841
|
+
|
|
3842
|
+
EXAMPLES::
|
|
3843
|
+
|
|
3844
|
+
sage: R = ZpER(5, 10)
|
|
3845
|
+
sage: x = R.unknown()
|
|
3846
|
+
sage: x.set(1 + 5*x)
|
|
3847
|
+
True
|
|
3848
|
+
sage: x
|
|
3849
|
+
1 + 5 + 5^2 + 5^3 + 5^4 + 5^5 + 5^6 + 5^7 + 5^8 + 5^9 + ...
|
|
3850
|
+
|
|
3851
|
+
The previous construction works because the relation we gave defines
|
|
3852
|
+
the `n`-th digit of `x` in terms of its digits at precision strictly
|
|
3853
|
+
less than `n` (this is due to the multiplication by `5`).
|
|
3854
|
+
|
|
3855
|
+
On the contrary, the following does not work::
|
|
3856
|
+
|
|
3857
|
+
sage: y = R.unknown()
|
|
3858
|
+
sage: y.set(1 + 3*y)
|
|
3859
|
+
True
|
|
3860
|
+
sage: y
|
|
3861
|
+
O(5^0)
|
|
3862
|
+
sage: y[:20]
|
|
3863
|
+
Traceback (most recent call last):
|
|
3864
|
+
...
|
|
3865
|
+
RecursionError: definition looks circular
|
|
3866
|
+
|
|
3867
|
+
In the next example, we give explicit values for the first digits
|
|
3868
|
+
and then a recursive definition for the next digits. However, the
|
|
3869
|
+
recursive definition does not hold for the first digits; that is the
|
|
3870
|
+
reason why the call to :meth:`set` returns ``False``::
|
|
3871
|
+
|
|
3872
|
+
sage: z = R.unknown(digits=[2])
|
|
3873
|
+
sage: z
|
|
3874
|
+
2 + O(5)
|
|
3875
|
+
sage: z.set(1 + 5*z)
|
|
3876
|
+
False
|
|
3877
|
+
sage: z
|
|
3878
|
+
2 + 2*5 + 2*5^2 + 2*5^3 + 2*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 2*5^8 + 2*5^9 + ...
|
|
3879
|
+
|
|
3880
|
+
.. SEEALSO::
|
|
3881
|
+
|
|
3882
|
+
:meth:`sage.rings.padics.generic_nodes.pAdicRelaxedGeneric.unknown`
|
|
3883
|
+
"""
|
|
3884
|
+
if self._definition is not None:
|
|
3885
|
+
raise ValueError("this self-referent number is already defined")
|
|
3886
|
+
self._definition = definition
|
|
3887
|
+
self._precbound = max(self._valuation + self._precrel, definition._precbound)
|
|
3888
|
+
eq = self._is_equal(definition, self._valuation + self._precrel, True)
|
|
3889
|
+
self._init_jump()
|
|
3890
|
+
return eq
|
|
3891
|
+
|
|
3892
|
+
cdef int _next_c(self) noexcept:
|
|
3893
|
+
r"""
|
|
3894
|
+
Compute the next digit of this number.
|
|
3895
|
+
|
|
3896
|
+
OUTPUT:
|
|
3897
|
+
|
|
3898
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
3899
|
+
"""
|
|
3900
|
+
cdef RelaxedElement definition = self._definition
|
|
3901
|
+
cdef cdigit_ptr digit
|
|
3902
|
+
cdef long n = self._valuation + self._precrel
|
|
3903
|
+
cdef long diffval
|
|
3904
|
+
cdef int error
|
|
3905
|
+
|
|
3906
|
+
if definition is None:
|
|
3907
|
+
return ERROR_NOTDEFINED
|
|
3908
|
+
if n >= self._next:
|
|
3909
|
+
return ERROR_CIRCULAR
|
|
3910
|
+
|
|
3911
|
+
cdef long svenext = self._next
|
|
3912
|
+
self._next = n
|
|
3913
|
+
error = definition._jump_c(n+1)
|
|
3914
|
+
if not error:
|
|
3915
|
+
digit = definition._getdigit_absolute(n)
|
|
3916
|
+
if self._precrel == 0 and digit_is_zero(digit):
|
|
3917
|
+
self._valuation += 1
|
|
3918
|
+
else:
|
|
3919
|
+
element_set_digit(self._digits, digit, self._precrel)
|
|
3920
|
+
self._precrel += 1
|
|
3921
|
+
self._next = svenext
|
|
3922
|
+
return error
|
|
3923
|
+
|
|
3924
|
+
|
|
3925
|
+
def unpickle_unknown(uid, cls, parent, valuation, digits, definition):
|
|
3926
|
+
r"""
|
|
3927
|
+
Unpickle a self-referent relaxed `p`-adic number.
|
|
3928
|
+
|
|
3929
|
+
TESTS:
|
|
3930
|
+
|
|
3931
|
+
Cross definitions involving several self-referent numbers are
|
|
3932
|
+
handled correctly::
|
|
3933
|
+
|
|
3934
|
+
sage: R = ZpER(7)
|
|
3935
|
+
sage: x = R.unknown()
|
|
3936
|
+
sage: y = R.unknown()
|
|
3937
|
+
sage: x.set(1 + 2*y + 7*x*y)
|
|
3938
|
+
True
|
|
3939
|
+
sage: y.set(3 + 14*x^2)
|
|
3940
|
+
True
|
|
3941
|
+
|
|
3942
|
+
sage: x == loads(dumps(x)) # indirect doctest
|
|
3943
|
+
True
|
|
3944
|
+
sage: y == loads(dumps(y)) # indirect doctest
|
|
3945
|
+
True
|
|
3946
|
+
"""
|
|
3947
|
+
if uid in persist.already_unpickled:
|
|
3948
|
+
elt = persist.already_unpickled[uid]
|
|
3949
|
+
else:
|
|
3950
|
+
elt = cls(parent, valuation, digits)
|
|
3951
|
+
persist.already_unpickled[uid] = elt
|
|
3952
|
+
if definition is not None:
|
|
3953
|
+
elt.set(definition)
|
|
3954
|
+
return elt
|
|
3955
|
+
|
|
3956
|
+
|
|
3957
|
+
# Expansion
|
|
3958
|
+
###########
|
|
3959
|
+
|
|
3960
|
+
cdef class RelaxedElement_zeroone(RelaxedElementWithDigits):
|
|
3961
|
+
r"""
|
|
3962
|
+
A special class for `p`-adic relaxed elements with only
|
|
3963
|
+
`0` and `1` as digits.
|
|
3964
|
+
|
|
3965
|
+
This class is used for computing expansion in Teichmuller mode.
|
|
3966
|
+
It is not supposed to be instantiated in other situations.
|
|
3967
|
+
"""
|
|
3968
|
+
def __init__(self, parent, long valuation):
|
|
3969
|
+
r"""
|
|
3970
|
+
Instantiate this element.
|
|
3971
|
+
|
|
3972
|
+
INPUT:
|
|
3973
|
+
|
|
3974
|
+
- ``parent`` -- the parent of this element
|
|
3975
|
+
|
|
3976
|
+
- ``valuation`` -- the valuation of this number
|
|
3977
|
+
"""
|
|
3978
|
+
RelaxedElement.__init__(self, parent)
|
|
3979
|
+
self._valuation = valuation
|
|
3980
|
+
|
|
3981
|
+
cdef void _setdigit_to_zero(self) noexcept:
|
|
3982
|
+
r"""
|
|
3983
|
+
Append `0` to the list of digits of this element.
|
|
3984
|
+
"""
|
|
3985
|
+
self._precrel += 1
|
|
3986
|
+
|
|
3987
|
+
cdef void _setdigit_to_one(self) noexcept:
|
|
3988
|
+
r"""
|
|
3989
|
+
Append `1` to the list of digits of this element.
|
|
3990
|
+
"""
|
|
3991
|
+
element_set_digit_ui(self._digits, 1, self._precrel)
|
|
3992
|
+
self._precrel += 1
|
|
3993
|
+
|
|
3994
|
+
cdef int _jump_c(self, long prec) noexcept:
|
|
3995
|
+
r"""
|
|
3996
|
+
Jump to the absolute precision ``prec``.
|
|
3997
|
+
|
|
3998
|
+
INPUT:
|
|
3999
|
+
|
|
4000
|
+
- ``prec`` -- integer
|
|
4001
|
+
|
|
4002
|
+
OUTPUT:
|
|
4003
|
+
|
|
4004
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
4005
|
+
"""
|
|
4006
|
+
if prec > self._valuation + self._precrel:
|
|
4007
|
+
return ERROR_NOTDEFINED
|
|
4008
|
+
return 0
|
|
4009
|
+
|
|
4010
|
+
cdef int _next_c(self) noexcept:
|
|
4011
|
+
r"""
|
|
4012
|
+
Jump to the next digit.
|
|
4013
|
+
|
|
4014
|
+
OUTPUT:
|
|
4015
|
+
|
|
4016
|
+
An error code (see :meth:`RelaxedElement._next_c` for details).
|
|
4017
|
+
"""
|
|
4018
|
+
return ERROR_NOTDEFINED
|
|
4019
|
+
|
|
4020
|
+
|
|
4021
|
+
cdef class ExpansionIter():
|
|
4022
|
+
"""
|
|
4023
|
+
An iterator over a `p`-adic expansion.
|
|
4024
|
+
|
|
4025
|
+
This class should not be instantiated directly, but instead using
|
|
4026
|
+
:meth:`RelaxedElement.expansion`.
|
|
4027
|
+
"""
|
|
4028
|
+
def __cinit__(self):
|
|
4029
|
+
r"""
|
|
4030
|
+
Allocate memory for temporary variables.
|
|
4031
|
+
"""
|
|
4032
|
+
digit_init(self.carry)
|
|
4033
|
+
|
|
4034
|
+
def __dealloc__(self):
|
|
4035
|
+
r"""
|
|
4036
|
+
Deallocate memory for temporary variables.
|
|
4037
|
+
"""
|
|
4038
|
+
digit_clear(self.carry)
|
|
4039
|
+
|
|
4040
|
+
def __init__(self, RelaxedElement elt, expansion_mode mode, long start, long stop):
|
|
4041
|
+
r"""
|
|
4042
|
+
Initialize this iterator.
|
|
4043
|
+
|
|
4044
|
+
INPUT:
|
|
4045
|
+
|
|
4046
|
+
- ``elt`` -- a relaxed `p`-adic number
|
|
4047
|
+
|
|
4048
|
+
- ``mode`` -- either ``simple_mode``, ``smallest_mode`` or ``teichmuller_mode``
|
|
4049
|
+
|
|
4050
|
+
- ``start`` -- integer; the position where the expansion starts
|
|
4051
|
+
|
|
4052
|
+
- ``stop`` -- integer; the position where the expansion stops
|
|
4053
|
+
|
|
4054
|
+
TESTS::
|
|
4055
|
+
|
|
4056
|
+
sage: E = ZpER(5,4)(373).expansion()
|
|
4057
|
+
sage: I = iter(E) # indirect doctest
|
|
4058
|
+
sage: type(I)
|
|
4059
|
+
<class 'sage.rings.padics.padic_relaxed_element.ExpansionIter'>
|
|
4060
|
+
"""
|
|
4061
|
+
self.elt = elt
|
|
4062
|
+
self.mode = mode
|
|
4063
|
+
self.start = start
|
|
4064
|
+
self.stop = stop
|
|
4065
|
+
self.current = min(start, elt._valuation)
|
|
4066
|
+
digit_init(self.digit)
|
|
4067
|
+
# Compute first digits if needed
|
|
4068
|
+
if self.mode == simple_mode:
|
|
4069
|
+
self.current = self.start
|
|
4070
|
+
elif self.mode == smallest_mode:
|
|
4071
|
+
while self.current < self.start:
|
|
4072
|
+
self._next_smallest()
|
|
4073
|
+
elif self.mode == teichmuller_mode:
|
|
4074
|
+
self.tail = elt
|
|
4075
|
+
self.coefficients = {}
|
|
4076
|
+
while self.current < self.start:
|
|
4077
|
+
self._next_teichmuller()
|
|
4078
|
+
|
|
4079
|
+
def __repr__(self):
|
|
4080
|
+
r"""
|
|
4081
|
+
Return a string representation of this iterator.
|
|
4082
|
+
|
|
4083
|
+
EXAMPLES::
|
|
4084
|
+
|
|
4085
|
+
sage: R = ZpER(7, 5)
|
|
4086
|
+
sage: x = R(1/2021)
|
|
4087
|
+
sage: x.expansion() # indirect doctest
|
|
4088
|
+
7-adic expansion of 3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + ...
|
|
4089
|
+
|
|
4090
|
+
sage: x.expansion(lift_mode='smallest') # indirect doctest
|
|
4091
|
+
7-adic expansion of 3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + ... (balanced)
|
|
4092
|
+
|
|
4093
|
+
sage: x.expansion(lift_mode='teichmuller') # indirect doctest
|
|
4094
|
+
7-adic expansion of 3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + ... (teichmuller)
|
|
4095
|
+
"""
|
|
4096
|
+
s = "%s-adic expansion of %s" % (self.elt._parent.prime(), self.elt)
|
|
4097
|
+
if self.mode == smallest_mode:
|
|
4098
|
+
s += " (balanced)"
|
|
4099
|
+
elif self.mode == teichmuller_mode:
|
|
4100
|
+
s += " (teichmuller)"
|
|
4101
|
+
return s
|
|
4102
|
+
|
|
4103
|
+
def __len__(self):
|
|
4104
|
+
r"""
|
|
4105
|
+
Return the length of this expansion.
|
|
4106
|
+
|
|
4107
|
+
EXAMPLES::
|
|
4108
|
+
|
|
4109
|
+
sage: R = ZpER(7)
|
|
4110
|
+
sage: x = R(1/2021, 5)
|
|
4111
|
+
sage: x
|
|
4112
|
+
3 + 6*7 + 4*7^2 + 3*7^3 + 6*7^4 + O(7^5)
|
|
4113
|
+
sage: E = x.expansion()
|
|
4114
|
+
sage: len(E)
|
|
4115
|
+
5
|
|
4116
|
+
|
|
4117
|
+
For unbounded elements, the expansion is infinite and this method
|
|
4118
|
+
raises an error::
|
|
4119
|
+
|
|
4120
|
+
sage: y = R(1/2021)
|
|
4121
|
+
sage: E = y.expansion()
|
|
4122
|
+
sage: len(E)
|
|
4123
|
+
Traceback (most recent call last):
|
|
4124
|
+
...
|
|
4125
|
+
NotImplementedError: infinite sequence
|
|
4126
|
+
"""
|
|
4127
|
+
if self.stop >= maxordp:
|
|
4128
|
+
raise NotImplementedError("infinite sequence")
|
|
4129
|
+
return Integer(self.stop - self.start)
|
|
4130
|
+
|
|
4131
|
+
def __iter__(self):
|
|
4132
|
+
r"""
|
|
4133
|
+
Return itself (as any iterator is supposed to do).
|
|
4134
|
+
|
|
4135
|
+
TESTS::
|
|
4136
|
+
|
|
4137
|
+
sage: E = ZpER(5)(373).expansion()
|
|
4138
|
+
sage: I = iter(E)
|
|
4139
|
+
sage: I is iter(I)
|
|
4140
|
+
True
|
|
4141
|
+
"""
|
|
4142
|
+
return self
|
|
4143
|
+
|
|
4144
|
+
cdef _next_simple(self):
|
|
4145
|
+
r"""
|
|
4146
|
+
Return the next digit of this expansion (simple mode).
|
|
4147
|
+
"""
|
|
4148
|
+
cdef RelaxedElement elt = self.elt
|
|
4149
|
+
elt._jump_c(self.current + 1)
|
|
4150
|
+
digit_set(self.digit, elt._getdigit_absolute(self.current))
|
|
4151
|
+
self.current += 1
|
|
4152
|
+
return digit_get_sage(self.digit)
|
|
4153
|
+
|
|
4154
|
+
cdef _next_smallest(self):
|
|
4155
|
+
r"""
|
|
4156
|
+
Return the next digit of this expansion (smallest mode).
|
|
4157
|
+
"""
|
|
4158
|
+
cdef RelaxedElement elt = self.elt
|
|
4159
|
+
elt._jump_c(self.current + 1)
|
|
4160
|
+
digit_add(self.digit, elt._getdigit_absolute(self.current), self.carry)
|
|
4161
|
+
digit_smallest(self.digit, self.carry, self.digit, elt.prime_pow)
|
|
4162
|
+
self.current += 1
|
|
4163
|
+
return digit_get_sage(self.digit)
|
|
4164
|
+
|
|
4165
|
+
cdef _next_teichmuller(self):
|
|
4166
|
+
r"""
|
|
4167
|
+
Return the next digit of this expansion (Teichmüller mode).
|
|
4168
|
+
"""
|
|
4169
|
+
cdef RelaxedElement teichmuller, tail = self.tail
|
|
4170
|
+
cdef RelaxedElement_zeroone coeff
|
|
4171
|
+
cdef digit
|
|
4172
|
+
tail._jump_c(self.current + 1)
|
|
4173
|
+
digit_set(self.digit, tail._getdigit_absolute(self.current))
|
|
4174
|
+
digit = digit_get_sage(self.digit)
|
|
4175
|
+
if digit != 0 and digit != 1 and digit not in self.coefficients:
|
|
4176
|
+
parent = tail._parent
|
|
4177
|
+
self.coefficients[digit] = coeff = RelaxedElement_zeroone(parent, self.current)
|
|
4178
|
+
teichmuller = element_class_teichmuller(parent, digit)
|
|
4179
|
+
self.tail = tail - coeff * element_class_slice(parent, teichmuller, 1, maxordp, 0)
|
|
4180
|
+
for d, coeff in self.coefficients.items():
|
|
4181
|
+
if d == digit:
|
|
4182
|
+
coeff._setdigit_to_one()
|
|
4183
|
+
else:
|
|
4184
|
+
coeff._setdigit_to_zero()
|
|
4185
|
+
self.current += 1
|
|
4186
|
+
return digit
|
|
4187
|
+
|
|
4188
|
+
def __next__(self):
|
|
4189
|
+
r"""
|
|
4190
|
+
Return the next digit of this expansion.
|
|
4191
|
+
|
|
4192
|
+
EXAMPLES::
|
|
4193
|
+
|
|
4194
|
+
sage: R = ZpER(11, 10)
|
|
4195
|
+
sage: x = R(20/21); x
|
|
4196
|
+
2 + 2*11 + 4*11^2 + 8*11^3 + 5*11^4 + 11^6 + 2*11^7 + 4*11^8 + 8*11^9 + ...
|
|
4197
|
+
sage: E = x.expansion()
|
|
4198
|
+
sage: next(E)
|
|
4199
|
+
2
|
|
4200
|
+
sage: next(E)
|
|
4201
|
+
2
|
|
4202
|
+
|
|
4203
|
+
TESTS::
|
|
4204
|
+
|
|
4205
|
+
sage: def check_expansion(x, mode):
|
|
4206
|
+
....: R = x.parent()
|
|
4207
|
+
....: E = x.expansion(lift_mode=mode)
|
|
4208
|
+
....: y = 0
|
|
4209
|
+
....: for i in range(len(E)):
|
|
4210
|
+
....: digit = next(E)
|
|
4211
|
+
....: if mode == 'teichmuller':
|
|
4212
|
+
....: y += R.teichmuller(digit) << i
|
|
4213
|
+
....: else:
|
|
4214
|
+
....: y += R(digit) << i
|
|
4215
|
+
....: assert(x == y)
|
|
4216
|
+
|
|
4217
|
+
sage: for p in primes(100):
|
|
4218
|
+
....: x = ZpER(p).random_element()[:20]
|
|
4219
|
+
....: for mode in [ 'simple', 'smallest', 'teichmuller' ]:
|
|
4220
|
+
....: check_expansion(x, mode)
|
|
4221
|
+
"""
|
|
4222
|
+
if self.current >= self.stop:
|
|
4223
|
+
raise StopIteration
|
|
4224
|
+
if self.mode == simple_mode:
|
|
4225
|
+
return self._next_simple()
|
|
4226
|
+
elif self.mode == smallest_mode:
|
|
4227
|
+
return self._next_smallest()
|
|
4228
|
+
elif self.mode == teichmuller_mode:
|
|
4229
|
+
return self._next_teichmuller()
|