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,4642 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-pari
|
|
2
|
+
"""
|
|
3
|
+
`p`-adic Generic Element
|
|
4
|
+
|
|
5
|
+
Elements of `p`-adic Rings and Fields
|
|
6
|
+
|
|
7
|
+
AUTHORS:
|
|
8
|
+
|
|
9
|
+
- David Roe
|
|
10
|
+
|
|
11
|
+
- Genya Zaytman: documentation
|
|
12
|
+
|
|
13
|
+
- David Harvey: doctests
|
|
14
|
+
|
|
15
|
+
- Julian Rueth: fixes for exp() and log(), implemented gcd, xgcd
|
|
16
|
+
"""
|
|
17
|
+
# ****************************************************************************
|
|
18
|
+
# Copyright (C) 2007-2013 David Roe <roed@math.harvard.edu>
|
|
19
|
+
# 2007 William Stein <wstein@gmail.com>
|
|
20
|
+
# 2013-2014 Julian Rueth <julian.rueth@gmail.com>
|
|
21
|
+
#
|
|
22
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
23
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
24
|
+
# the License, or (at your option) any later version.
|
|
25
|
+
#
|
|
26
|
+
# https://www.gnu.org/licenses/
|
|
27
|
+
# ****************************************************************************
|
|
28
|
+
|
|
29
|
+
from sage.ext.stdsage cimport PY_NEW
|
|
30
|
+
|
|
31
|
+
cimport sage.rings.padics.local_generic_element
|
|
32
|
+
from sage.libs.gmp.mpz cimport mpz_set_si
|
|
33
|
+
from sage.arith.srange import srange
|
|
34
|
+
from sage.rings.padics.local_generic_element cimport LocalGenericElement
|
|
35
|
+
from sage.rings.padics.precision_error import PrecisionError
|
|
36
|
+
from sage.rings.rational cimport Rational
|
|
37
|
+
from sage.rings.integer cimport Integer
|
|
38
|
+
from sage.rings.integer_ring import ZZ
|
|
39
|
+
from sage.rings.infinity import infinity
|
|
40
|
+
from sage.structure.element import coerce_binop
|
|
41
|
+
from sage.structure.richcmp cimport rich_to_bool
|
|
42
|
+
|
|
43
|
+
cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) - 1
|
|
44
|
+
|
|
45
|
+
cdef class pAdicGenericElement(LocalGenericElement):
|
|
46
|
+
cpdef _richcmp_(left, right, int op):
|
|
47
|
+
r"""
|
|
48
|
+
First compare valuations, then compare normalized
|
|
49
|
+
residue of unit part.
|
|
50
|
+
|
|
51
|
+
EXAMPLES::
|
|
52
|
+
|
|
53
|
+
sage: R = Zp(19, 5,'capped-rel','series'); K = Qp(19, 5, 'capped-rel', 'series')
|
|
54
|
+
sage: a = R(2); a
|
|
55
|
+
2 + O(19^5)
|
|
56
|
+
sage: b = R(3); b
|
|
57
|
+
3 + O(19^5)
|
|
58
|
+
sage: a < b
|
|
59
|
+
True
|
|
60
|
+
sage: a = K(2); a
|
|
61
|
+
2 + O(19^5)
|
|
62
|
+
sage: b = K(3); b
|
|
63
|
+
3 + O(19^5)
|
|
64
|
+
sage: a < b
|
|
65
|
+
True
|
|
66
|
+
|
|
67
|
+
::
|
|
68
|
+
|
|
69
|
+
sage: R = Zp(5); a = R(5, 6); b = R(5 + 5^6, 8)
|
|
70
|
+
sage: a == b # indirect doctest
|
|
71
|
+
True
|
|
72
|
+
|
|
73
|
+
::
|
|
74
|
+
|
|
75
|
+
sage: R = Zp(5)
|
|
76
|
+
sage: a = R(17)
|
|
77
|
+
sage: b = R(21)
|
|
78
|
+
sage: a == b
|
|
79
|
+
False
|
|
80
|
+
sage: a < b
|
|
81
|
+
True
|
|
82
|
+
|
|
83
|
+
::
|
|
84
|
+
|
|
85
|
+
sage: R = ZpCA(5)
|
|
86
|
+
sage: a = R(17)
|
|
87
|
+
sage: b = R(21)
|
|
88
|
+
sage: a == b
|
|
89
|
+
False
|
|
90
|
+
sage: a < b
|
|
91
|
+
True
|
|
92
|
+
|
|
93
|
+
::
|
|
94
|
+
|
|
95
|
+
sage: R = ZpFM(5)
|
|
96
|
+
sage: a = R(17)
|
|
97
|
+
sage: b = R(21)
|
|
98
|
+
sage: a == b
|
|
99
|
+
False
|
|
100
|
+
sage: a < b
|
|
101
|
+
True
|
|
102
|
+
"""
|
|
103
|
+
# handle exact zeros
|
|
104
|
+
left_zero = left._is_exact_zero()
|
|
105
|
+
right_zero = right._is_exact_zero()
|
|
106
|
+
if left_zero and right_zero:
|
|
107
|
+
return rich_to_bool(op, 0)
|
|
108
|
+
elif left_zero:
|
|
109
|
+
if right.is_zero():
|
|
110
|
+
return rich_to_bool(op, 0)
|
|
111
|
+
return rich_to_bool(op, 1)
|
|
112
|
+
elif right_zero:
|
|
113
|
+
if left.is_zero():
|
|
114
|
+
return rich_to_bool(op, 0)
|
|
115
|
+
return rich_to_bool(op, -1)
|
|
116
|
+
|
|
117
|
+
m = min(left.precision_absolute(), right.precision_absolute())
|
|
118
|
+
x_ordp = left.valuation()
|
|
119
|
+
left_zero = bool(x_ordp >= m)
|
|
120
|
+
y_ordp = right.valuation()
|
|
121
|
+
right_zero = bool(y_ordp >= m)
|
|
122
|
+
# handle approximate zeros
|
|
123
|
+
if left_zero and right_zero:
|
|
124
|
+
return rich_to_bool(op, 0)
|
|
125
|
+
elif left_zero:
|
|
126
|
+
return rich_to_bool(op, 1)
|
|
127
|
+
elif right_zero:
|
|
128
|
+
return rich_to_bool(op, -1)
|
|
129
|
+
|
|
130
|
+
# no more zeros
|
|
131
|
+
if x_ordp < y_ordp:
|
|
132
|
+
return rich_to_bool(op, -1)
|
|
133
|
+
elif x_ordp > y_ordp:
|
|
134
|
+
return rich_to_bool(op, 1)
|
|
135
|
+
else: # equal ordp
|
|
136
|
+
test = (<pAdicGenericElement>left.unit_part())._cmp_units(right.unit_part())
|
|
137
|
+
return rich_to_bool(op, test)
|
|
138
|
+
|
|
139
|
+
cdef int _cmp_units(left, pAdicGenericElement right) except -2:
|
|
140
|
+
raise NotImplementedError
|
|
141
|
+
|
|
142
|
+
cdef int _set_from_Integer(self, Integer x, absprec, relprec) except -1:
|
|
143
|
+
raise NotImplementedError
|
|
144
|
+
cdef int _set_from_mpz(self, mpz_t x) except -1:
|
|
145
|
+
raise NotImplementedError
|
|
146
|
+
cdef int _set_from_mpz_rel(self, mpz_t x, long relprec) except -1:
|
|
147
|
+
raise NotImplementedError
|
|
148
|
+
cdef int _set_from_mpz_abs(self, mpz_t value, long absprec) except -1:
|
|
149
|
+
raise NotImplementedError
|
|
150
|
+
cdef int _set_from_mpz_both(self, mpz_t x, long absprec, long relprec) except -1:
|
|
151
|
+
raise NotImplementedError
|
|
152
|
+
|
|
153
|
+
cdef int _set_from_Rational(self, Rational x, absprec, relprec) except -1:
|
|
154
|
+
raise NotImplementedError
|
|
155
|
+
cdef int _set_from_mpq(self, mpq_t x) except -1:
|
|
156
|
+
raise NotImplementedError
|
|
157
|
+
cdef int _set_from_mpq_rel(self, mpq_t x, long relprec) except -1:
|
|
158
|
+
raise NotImplementedError
|
|
159
|
+
cdef int _set_from_mpq_abs(self, mpq_t value, long absprec) except -1:
|
|
160
|
+
raise NotImplementedError
|
|
161
|
+
cdef int _set_from_mpq_both(self, mpq_t x, long absprec, long relprec) except -1:
|
|
162
|
+
raise NotImplementedError
|
|
163
|
+
|
|
164
|
+
cdef int _pshift_self(self, long shift) except -1:
|
|
165
|
+
raise NotImplementedError
|
|
166
|
+
|
|
167
|
+
cdef int _set_inexact_zero(self, long absprec) except -1:
|
|
168
|
+
raise NotImplementedError
|
|
169
|
+
cdef int _set_exact_zero(self) except -1:
|
|
170
|
+
raise TypeError("this type of p-adic does not support exact zeros")
|
|
171
|
+
|
|
172
|
+
cpdef bint _is_exact_zero(self) except -1:
|
|
173
|
+
"""
|
|
174
|
+
Return ``True`` if ``self`` is exactly zero. Since
|
|
175
|
+
non-capped-relative elements cannot be exact, this function
|
|
176
|
+
always returns False.
|
|
177
|
+
|
|
178
|
+
EXAMPLES::
|
|
179
|
+
|
|
180
|
+
sage: ZpCA(17)(0)._is_exact_zero()
|
|
181
|
+
False
|
|
182
|
+
"""
|
|
183
|
+
return False
|
|
184
|
+
|
|
185
|
+
cpdef bint _is_inexact_zero(self) except -1:
|
|
186
|
+
"""
|
|
187
|
+
Return ``True`` if ``self`` is indistinguishable from zero, but not
|
|
188
|
+
exactly zero.
|
|
189
|
+
|
|
190
|
+
EXAMPLES::
|
|
191
|
+
|
|
192
|
+
sage: Zp(5)(0,5)._is_inexact_zero()
|
|
193
|
+
True
|
|
194
|
+
"""
|
|
195
|
+
raise NotImplementedError
|
|
196
|
+
|
|
197
|
+
cpdef bint _is_zero_rep(self) except -1:
|
|
198
|
+
"""
|
|
199
|
+
Return ``True`` if ``self`` is indistinguishable from zero.
|
|
200
|
+
|
|
201
|
+
EXAMPLES::
|
|
202
|
+
|
|
203
|
+
sage: ZpCA(17)(0,15)._is_zero_rep()
|
|
204
|
+
True
|
|
205
|
+
"""
|
|
206
|
+
return self._is_inexact_zero() or self._is_exact_zero()
|
|
207
|
+
|
|
208
|
+
cdef bint _set_prec_abs(self, long absprec) except -1:
|
|
209
|
+
self._set_prec_both(absprec, (<PowComputer_class>self.parent().prime_pow).prec_cap)
|
|
210
|
+
|
|
211
|
+
cdef bint _set_prec_rel(self, long relprec) except -1:
|
|
212
|
+
self._set_prec_both((<PowComputer_class>self.parent().prime_pow).prec_cap, relprec)
|
|
213
|
+
|
|
214
|
+
cdef bint _set_prec_both(self, long absprec, long relprec) except -1:
|
|
215
|
+
return 0
|
|
216
|
+
|
|
217
|
+
def _quo_rem(self, right):
|
|
218
|
+
"""
|
|
219
|
+
Quotient with remainder.
|
|
220
|
+
|
|
221
|
+
We choose the remainder to have the same `p`-adic expansion
|
|
222
|
+
as the numerator, but truncated at the valuation of the denominator.
|
|
223
|
+
|
|
224
|
+
EXAMPLES::
|
|
225
|
+
|
|
226
|
+
sage: R = Zp(3, 5)
|
|
227
|
+
sage: R(12).quo_rem(R(2))
|
|
228
|
+
(2*3 + O(3^6), 0)
|
|
229
|
+
sage: R(2).quo_rem(R(12))
|
|
230
|
+
(O(3^4), 2 + O(3^5))
|
|
231
|
+
sage: q, r = R(4).quo_rem(R(12)); q, r
|
|
232
|
+
(1 + 2*3 + 2*3^3 + O(3^4), 1 + O(3^5))
|
|
233
|
+
sage: 12*q + r == 4
|
|
234
|
+
True
|
|
235
|
+
|
|
236
|
+
In general, the remainder is returned with maximal precision.
|
|
237
|
+
However, it is not the case when the valuation of the divisor
|
|
238
|
+
is greater than the absolute precision on the numerator::
|
|
239
|
+
|
|
240
|
+
sage: R(1,2).quo_rem(R(81))
|
|
241
|
+
(O(3^0), 1 + O(3^2))
|
|
242
|
+
|
|
243
|
+
For fields the normal quotient always has remainder 0:
|
|
244
|
+
|
|
245
|
+
sage: K = Qp(3, 5)
|
|
246
|
+
sage: K(12).quo_rem(K(2))
|
|
247
|
+
(2*3 + O(3^6), 0)
|
|
248
|
+
sage: q, r = K(4).quo_rem(K(12)); q, r
|
|
249
|
+
(3^-1 + O(3^4), 0)
|
|
250
|
+
sage: 12*q + r == 4
|
|
251
|
+
True
|
|
252
|
+
|
|
253
|
+
You can get the same behavior for fields as for rings
|
|
254
|
+
by using this underscored method::
|
|
255
|
+
|
|
256
|
+
sage: K(12)._quo_rem(K(2))
|
|
257
|
+
(2*3 + O(3^6), 0)
|
|
258
|
+
sage: K(2)._quo_rem(K(12))
|
|
259
|
+
(O(3^4), 2 + O(3^5))
|
|
260
|
+
"""
|
|
261
|
+
if right._is_exact_zero():
|
|
262
|
+
raise ZeroDivisionError("cannot divide by zero")
|
|
263
|
+
if right.is_zero():
|
|
264
|
+
raise PrecisionError("cannot divide by something indistinguishable from zero")
|
|
265
|
+
K = self.parent()
|
|
266
|
+
R = K.integer_ring()
|
|
267
|
+
sval = self.valuation()
|
|
268
|
+
diff = sval - right.valuation()
|
|
269
|
+
srelprec = self.precision_relative()
|
|
270
|
+
if diff + srelprec < 0:
|
|
271
|
+
return K(0,0), self
|
|
272
|
+
if srelprec == 0:
|
|
273
|
+
return K(0,diff), K(0)
|
|
274
|
+
if diff >= 0: # remainder is 0
|
|
275
|
+
return K(self/right), K(0)
|
|
276
|
+
unit = R(self.unit_part())
|
|
277
|
+
high = (unit << diff) >> (diff - sval)
|
|
278
|
+
return K(high/right), K(self-high).lift_to_precision()
|
|
279
|
+
|
|
280
|
+
def __floordiv__(self, right):
|
|
281
|
+
"""
|
|
282
|
+
Divide ``self`` by ``right`` and throws away the nonintegral part if
|
|
283
|
+
``self.parent()`` is not a field.
|
|
284
|
+
|
|
285
|
+
There are a number of reasonable definitions for floor
|
|
286
|
+
division. Any definition should satisfy the following
|
|
287
|
+
identity:
|
|
288
|
+
|
|
289
|
+
(1) a = (a // b) * b + a % b
|
|
290
|
+
|
|
291
|
+
If a and b lie in a field, then setting a % b = 0 and a // b =
|
|
292
|
+
a / b provides a canonical way of satisfying this equation.
|
|
293
|
+
|
|
294
|
+
However, for elements of integer rings, there are many choices
|
|
295
|
+
of definitions for a // b and a % b that satisfy this
|
|
296
|
+
equation. Since `p`-adic rings in Sage come equipped with a
|
|
297
|
+
uniformizer pi, we can use the choice of uniformizer in our
|
|
298
|
+
definitions. Here are some other criteria we might ask for:
|
|
299
|
+
|
|
300
|
+
(2) If b = pi^k, the series expansion (in terms of pi) of a //
|
|
301
|
+
b is just the series expansion of a, shifted over by k terms.
|
|
302
|
+
|
|
303
|
+
(2') The series expansion of a % pi^k has no terms above
|
|
304
|
+
pi^(k-1).
|
|
305
|
+
|
|
306
|
+
The conditions (2) and (2') are equivalent. But when we
|
|
307
|
+
generalize these conditions to arbitrary b they diverge.
|
|
308
|
+
|
|
309
|
+
(3) For general b, the series expansion of a // b is just the
|
|
310
|
+
series expansion of a / b, truncating terms with negative
|
|
311
|
+
exponents of pi.
|
|
312
|
+
|
|
313
|
+
(4) For general b, the series expansion of a % b has no terms
|
|
314
|
+
above b.valuation() - 1.
|
|
315
|
+
|
|
316
|
+
In order to satisfy (3), one defines
|
|
317
|
+
|
|
318
|
+
a // b = (a / b.unit_part()) >> b.valuation()
|
|
319
|
+
a % b = a - (a // b) * b
|
|
320
|
+
|
|
321
|
+
In order to satisfy (4), one defines
|
|
322
|
+
|
|
323
|
+
a % b = a.lift() % pi.lift()^b.valuation()
|
|
324
|
+
a // b = ((a - a % b) >> b.valuation()) / b.unit_part()
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
In Sage we choose option (4) since it has better precision behavior.
|
|
328
|
+
|
|
329
|
+
EXAMPLES::
|
|
330
|
+
|
|
331
|
+
sage: R = ZpCA(5); a = R(129378); b = R(2398125)
|
|
332
|
+
sage: a // b # indirect doctest
|
|
333
|
+
1 + 2*5 + 2*5^3 + 4*5^4 + 5^6 + 5^7 + 5^8 + 4*5^9 + 2*5^10 + 4*5^11 + 4*5^12 + 2*5^13 + 3*5^14 + O(5^16)
|
|
334
|
+
sage: a / b
|
|
335
|
+
4*5^-4 + 3*5^-3 + 2*5^-2 + 5^-1 + 3 + 3*5 + 4*5^2 + 2*5^4 + 2*5^6 + 4*5^7 + 5^9 + 5^10 + 5^11 + O(5^12)
|
|
336
|
+
sage: a % b
|
|
337
|
+
3 + O(5^20)
|
|
338
|
+
sage: a
|
|
339
|
+
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
|
|
340
|
+
sage: (a // b) * b + a % b
|
|
341
|
+
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
|
|
342
|
+
|
|
343
|
+
The alternative definition::
|
|
344
|
+
|
|
345
|
+
sage: c = (a // b.unit_part()) >> b.valuation(); c
|
|
346
|
+
3 + 3*5 + 4*5^2 + 2*5^4 + 2*5^6 + 4*5^7 + 5^9 + 5^10 + 5^11 + O(5^12)
|
|
347
|
+
sage: othermod = a - c*b; othermod
|
|
348
|
+
3 + 5^4 + 3*5^5 + 2*5^6 + 4*5^7 + 5^8 + O(5^16)
|
|
349
|
+
"""
|
|
350
|
+
right = self.parent()(right)
|
|
351
|
+
if right._is_inexact_zero():
|
|
352
|
+
raise PrecisionError("cannot divide by something indistinguishable from zero")
|
|
353
|
+
elif right._is_exact_zero():
|
|
354
|
+
raise ZeroDivisionError("cannot divide by zero")
|
|
355
|
+
return self._floordiv_(right)
|
|
356
|
+
|
|
357
|
+
cpdef _floordiv_(self, right):
|
|
358
|
+
"""
|
|
359
|
+
Implement floor division.
|
|
360
|
+
|
|
361
|
+
EXAMPLES::
|
|
362
|
+
|
|
363
|
+
sage: R = Zp(5, 5); a = R(77)
|
|
364
|
+
sage: a // 15 # indirect doctest
|
|
365
|
+
5 + O(5^4)
|
|
366
|
+
"""
|
|
367
|
+
return self.quo_rem(right, integral=True)[0]
|
|
368
|
+
|
|
369
|
+
def __getitem__(self, n):
|
|
370
|
+
r"""
|
|
371
|
+
Return the coefficient of `p^n` in the series expansion of this
|
|
372
|
+
element, as an integer in the range `0` to `p-1`.
|
|
373
|
+
|
|
374
|
+
EXAMPLES::
|
|
375
|
+
|
|
376
|
+
sage: R = Zp(7,4,'capped-rel','series'); a = R(1/3); a
|
|
377
|
+
5 + 4*7 + 4*7^2 + 4*7^3 + O(7^4)
|
|
378
|
+
sage: a[0] # indirect doctest
|
|
379
|
+
doctest:warning
|
|
380
|
+
...
|
|
381
|
+
DeprecationWarning: __getitem__ is changing to match the behavior of number fields. Please use expansion instead.
|
|
382
|
+
See https://github.com/sagemath/sage/issues/14825 for details.
|
|
383
|
+
5
|
|
384
|
+
sage: a[1]
|
|
385
|
+
4
|
|
386
|
+
|
|
387
|
+
Negative indices do not have the special meaning they have for regular
|
|
388
|
+
python lists. In the following example, ``a[-1]`` is simply the
|
|
389
|
+
coefficient of `7^{-1}`::
|
|
390
|
+
|
|
391
|
+
sage: K = Qp(7,4,'capped-rel')
|
|
392
|
+
sage: b = K(1/7 + 7); b
|
|
393
|
+
7^-1 + 7 + O(7^3)
|
|
394
|
+
sage: b[-2]
|
|
395
|
+
0
|
|
396
|
+
sage: b[-1]
|
|
397
|
+
1
|
|
398
|
+
sage: b[0]
|
|
399
|
+
0
|
|
400
|
+
sage: b[1]
|
|
401
|
+
1
|
|
402
|
+
sage: b[2]
|
|
403
|
+
0
|
|
404
|
+
|
|
405
|
+
It is an error to access coefficients which are beyond the precision
|
|
406
|
+
bound::
|
|
407
|
+
|
|
408
|
+
sage: b[3]
|
|
409
|
+
Traceback (most recent call last):
|
|
410
|
+
...
|
|
411
|
+
PrecisionError
|
|
412
|
+
sage: b[-2]
|
|
413
|
+
0
|
|
414
|
+
|
|
415
|
+
Slices also work::
|
|
416
|
+
|
|
417
|
+
sage: a[0:2]
|
|
418
|
+
5 + 4*7 + O(7^2)
|
|
419
|
+
sage: a[-1:3:2]
|
|
420
|
+
5 + 4*7^2 + O(7^3)
|
|
421
|
+
sage: b[0:2]
|
|
422
|
+
7 + O(7^2)
|
|
423
|
+
sage: b[-1:3:2]
|
|
424
|
+
7^-1 + 7 + O(7^3)
|
|
425
|
+
|
|
426
|
+
If the slice includes coefficients which are beyond the precision
|
|
427
|
+
bound, they are ignored. This is similar to the behaviour of slices of
|
|
428
|
+
python lists::
|
|
429
|
+
|
|
430
|
+
sage: a[3:7]
|
|
431
|
+
4*7^3 + O(7^4)
|
|
432
|
+
sage: b[3:7]
|
|
433
|
+
O(7^3)
|
|
434
|
+
|
|
435
|
+
For extension elements, "zeros" match the behavior of
|
|
436
|
+
``list``::
|
|
437
|
+
|
|
438
|
+
sage: # needs sage.libs.ntl
|
|
439
|
+
sage: S.<a> = Qq(125)
|
|
440
|
+
sage: a[-2] # needs sage.rings.padics
|
|
441
|
+
[]
|
|
442
|
+
|
|
443
|
+
.. SEEALSO::
|
|
444
|
+
|
|
445
|
+
:meth:`sage.rings.padics.local_generic_element.LocalGenericElement.slice`
|
|
446
|
+
"""
|
|
447
|
+
from sage.misc.superseded import deprecation_cython as deprecation
|
|
448
|
+
deprecation(14825, "__getitem__ is changing to match the behavior of number fields. Please use expansion instead.")
|
|
449
|
+
return self.expansion(n)
|
|
450
|
+
|
|
451
|
+
def __invert__(self):
|
|
452
|
+
r"""
|
|
453
|
+
Return the multiplicative inverse of ``self``.
|
|
454
|
+
|
|
455
|
+
EXAMPLES::
|
|
456
|
+
|
|
457
|
+
sage: R = Zp(7,4,'capped-rel','series'); a = R(3); a
|
|
458
|
+
3 + O(7^4)
|
|
459
|
+
sage: ~a # indirect doctest
|
|
460
|
+
5 + 4*7 + 4*7^2 + 4*7^3 + O(7^4)
|
|
461
|
+
|
|
462
|
+
.. NOTE::
|
|
463
|
+
|
|
464
|
+
The element returned is an element of the fraction field.
|
|
465
|
+
"""
|
|
466
|
+
return ~self.parent().fraction_field()(self, relprec = self.precision_relative())
|
|
467
|
+
|
|
468
|
+
cpdef _mod_(self, right):
|
|
469
|
+
"""
|
|
470
|
+
If ``self`` is in a field, returns 0. If in a ring, returns a
|
|
471
|
+
`p`-adic integer such that
|
|
472
|
+
|
|
473
|
+
(1) a = (a // b) * b + a % b
|
|
474
|
+
|
|
475
|
+
holds.
|
|
476
|
+
|
|
477
|
+
WARNING: The series expansion of a % b continues above the
|
|
478
|
+
valuation of b.
|
|
479
|
+
|
|
480
|
+
The definitions of a // b and a % b are intertwined by
|
|
481
|
+
equation (1). If a and b lie in a field, then setting a % b =
|
|
482
|
+
0 and a // b = a / b provides a canonical way of satisfying
|
|
483
|
+
this equation.
|
|
484
|
+
|
|
485
|
+
However, for elements of integer rings, there are many choices
|
|
486
|
+
of definitions for a // b and a % b that satisfy this
|
|
487
|
+
equation. Since `p`-adic rings in Sage come equipped with a
|
|
488
|
+
uniformizer pi, we can use the choice of uniformizer in our
|
|
489
|
+
definitions. Here are some other criteria we might ask for:
|
|
490
|
+
|
|
491
|
+
(2) If b = pi^k, the series expansion (in terms of pi) of a //
|
|
492
|
+
b is just the series expansion of a, shifted over by k terms.
|
|
493
|
+
|
|
494
|
+
(2') The series expansion of a % pi^k has no terms above
|
|
495
|
+
pi^(k-1).
|
|
496
|
+
|
|
497
|
+
The conditions (2) and (2') are equivalent. But when we
|
|
498
|
+
generalize these conditions to arbitrary b they diverge.
|
|
499
|
+
|
|
500
|
+
(3) For general b, the series expansion of a // b is just the
|
|
501
|
+
series expansion of a / b, truncating terms with negative
|
|
502
|
+
exponents of pi.
|
|
503
|
+
|
|
504
|
+
(4) For general b, the series expansion of a % b has no terms
|
|
505
|
+
above b.valuation() - 1.
|
|
506
|
+
|
|
507
|
+
In order to satisfy (3), one defines
|
|
508
|
+
|
|
509
|
+
a // b = (a / b.unit_part()) >> b.valuation()
|
|
510
|
+
a % b = a - (a // b) * b
|
|
511
|
+
|
|
512
|
+
In order to satisfy (4), one defines
|
|
513
|
+
|
|
514
|
+
a % b = a.lift() % pi.lift()^b.valuation()
|
|
515
|
+
a // b = ((a - a % b) >> b.valuation()) / b.unit_part()
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
In Sage we choose option (4) because it has better precision behavior.
|
|
519
|
+
|
|
520
|
+
EXAMPLES::
|
|
521
|
+
|
|
522
|
+
sage: R = ZpCA(5); a = R(129378); b = R(2398125)
|
|
523
|
+
sage: a % b
|
|
524
|
+
3 + O(5^20)
|
|
525
|
+
"""
|
|
526
|
+
return self._quo_rem(right)[1]
|
|
527
|
+
|
|
528
|
+
#def _is_exact_zero(self):
|
|
529
|
+
# return False
|
|
530
|
+
|
|
531
|
+
#def _is_inexact_zero(self):
|
|
532
|
+
# return self.is_zero() and not self._is_exact_zero()
|
|
533
|
+
|
|
534
|
+
def str(self, mode=None):
|
|
535
|
+
"""
|
|
536
|
+
Return a string representation of ``self``.
|
|
537
|
+
|
|
538
|
+
EXAMPLES::
|
|
539
|
+
|
|
540
|
+
sage: Zp(5,5,print_mode='bars')(1/3).str()[3:]
|
|
541
|
+
'1|3|1|3|2'
|
|
542
|
+
"""
|
|
543
|
+
return self._repr_(mode=mode)
|
|
544
|
+
|
|
545
|
+
def _repr_(self, mode=None, do_latex=False):
|
|
546
|
+
r"""
|
|
547
|
+
Return a string representation of this element.
|
|
548
|
+
|
|
549
|
+
INPUT:
|
|
550
|
+
|
|
551
|
+
- ``mode`` -- allows one to override the default print mode of
|
|
552
|
+
the parent (default: ``None``)
|
|
553
|
+
|
|
554
|
+
- ``do_latex`` -- whether to return a latex representation or
|
|
555
|
+
a normal one
|
|
556
|
+
|
|
557
|
+
EXAMPLES::
|
|
558
|
+
|
|
559
|
+
sage: Zp(5,5)(1/3) # indirect doctest
|
|
560
|
+
2 + 3*5 + 5^2 + 3*5^3 + 5^4 + O(5^5)
|
|
561
|
+
|
|
562
|
+
We check that :issue:`26479` is fixed::
|
|
563
|
+
|
|
564
|
+
sage: # needs sage.libs.ntl
|
|
565
|
+
sage: x = polygen(ZZ, 'x')
|
|
566
|
+
sage: K.<pi> = Qp(2).extension(x^3 - 2)
|
|
567
|
+
sage: latex(pi) # needs sage.symbolic
|
|
568
|
+
\pi + O(\pi^{61})
|
|
569
|
+
"""
|
|
570
|
+
return self.parent()._printer.repr_gen(self, do_latex, mode=mode)
|
|
571
|
+
|
|
572
|
+
def additive_order(self, prec=None):
|
|
573
|
+
r"""
|
|
574
|
+
Return the additive order of this element truncated
|
|
575
|
+
at precision ``prec``.
|
|
576
|
+
|
|
577
|
+
INPUT:
|
|
578
|
+
|
|
579
|
+
- ``prec`` -- integer or ``None`` (default: ``None``)
|
|
580
|
+
|
|
581
|
+
OUTPUT: the additive order of this element
|
|
582
|
+
|
|
583
|
+
EXAMPLES::
|
|
584
|
+
|
|
585
|
+
sage: R = Zp(7, 4, 'capped-rel', 'series'); a = R(7^3); a.additive_order(3)
|
|
586
|
+
1
|
|
587
|
+
sage: a.additive_order(4)
|
|
588
|
+
+Infinity
|
|
589
|
+
sage: R = Zp(7, 4, 'fixed-mod', 'series'); a = R(7^5); a.additive_order(6)
|
|
590
|
+
1
|
|
591
|
+
"""
|
|
592
|
+
if self.is_zero(prec):
|
|
593
|
+
return Integer(1)
|
|
594
|
+
else:
|
|
595
|
+
return infinity
|
|
596
|
+
|
|
597
|
+
def artin_hasse_exp(self, prec=None, algorithm=None):
|
|
598
|
+
r"""
|
|
599
|
+
Return the Artin-Hasse exponential of this element.
|
|
600
|
+
|
|
601
|
+
INPUT:
|
|
602
|
+
|
|
603
|
+
- ``prec`` -- integer or ``None`` (default: ``None``);
|
|
604
|
+
the desired precision on the result; if ``None``, the
|
|
605
|
+
precision is derived from the precision on the input
|
|
606
|
+
|
|
607
|
+
- ``algorithm`` -- ``'direct'``, ``'series'``, ``'newton'`` or
|
|
608
|
+
``None`` (default)
|
|
609
|
+
|
|
610
|
+
The direct algorithm computes the Artin-Hasse exponential
|
|
611
|
+
of `x`, namely ``AH(x)`` as
|
|
612
|
+
|
|
613
|
+
.. MATH::
|
|
614
|
+
|
|
615
|
+
AH(x) = \exp(x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \dots
|
|
616
|
+
|
|
617
|
+
It runs roughly as fast as the computation of the exponential
|
|
618
|
+
(since the computation of the argument is not that costly).
|
|
619
|
+
|
|
620
|
+
The series algorithm computes the series defining the
|
|
621
|
+
Artin-Hasse exponential and evaluates it.
|
|
622
|
+
|
|
623
|
+
The ``'newton'`` algorithm solves the equation
|
|
624
|
+
|
|
625
|
+
.. MATH::
|
|
626
|
+
|
|
627
|
+
\log(AH(x)) = x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \dots
|
|
628
|
+
|
|
629
|
+
using a Newton scheme. It runs roughly as fast as the computation
|
|
630
|
+
of the logarithm.
|
|
631
|
+
|
|
632
|
+
By default, we use the ``'direct'`` algorithm if a fast algorithm for
|
|
633
|
+
computing the exponential is available.
|
|
634
|
+
If not, we use the ``'newton'`` algorithm if a fast algorithm for
|
|
635
|
+
computing the logarithm is available.
|
|
636
|
+
Otherwise we switch to the ``'series'`` algorithm.
|
|
637
|
+
|
|
638
|
+
OUTPUT: the Artin-Hasse exponential of this element
|
|
639
|
+
|
|
640
|
+
See :wikipedia:`Artin-Hasse_exponential` for more information.
|
|
641
|
+
|
|
642
|
+
EXAMPLES::
|
|
643
|
+
|
|
644
|
+
sage: x = Zp(5)(45/7)
|
|
645
|
+
sage: y = x.artin_hasse_exp(); y
|
|
646
|
+
1 + 2*5 + 4*5^2 + 3*5^3 + 5^7 + 2*5^8 + 3*5^10 + 2*5^11 + 2*5^12 +
|
|
647
|
+
2*5^13 + 5^14 + 3*5^17 + 2*5^18 + 2*5^19 + O(5^20)
|
|
648
|
+
|
|
649
|
+
sage: y * (-x).artin_hasse_exp()
|
|
650
|
+
1 + O(5^20)
|
|
651
|
+
|
|
652
|
+
The function respects your precision::
|
|
653
|
+
|
|
654
|
+
sage: x = Zp(3,30)(45/7)
|
|
655
|
+
sage: x.artin_hasse_exp()
|
|
656
|
+
1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 +
|
|
657
|
+
3^13 + 2*3^15 + 2*3^16 + 2*3^17 + 3^19 + 3^20 + 2*3^21 + 3^23 + 3^24 +
|
|
658
|
+
3^26 + 3^27 + 2*3^28 + O(3^30)
|
|
659
|
+
|
|
660
|
+
Unless you tell it not to::
|
|
661
|
+
|
|
662
|
+
sage: x = Zp(3,30)(45/7)
|
|
663
|
+
sage: x.artin_hasse_exp()
|
|
664
|
+
1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 +
|
|
665
|
+
3^13 + 2*3^15 + 2*3^16 + 2*3^17 + 3^19 + 3^20 + 2*3^21 + 3^23 + 3^24 +
|
|
666
|
+
3^26 + 3^27 + 2*3^28 + O(3^30)
|
|
667
|
+
sage: x.artin_hasse_exp(10)
|
|
668
|
+
1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + O(3^10)
|
|
669
|
+
|
|
670
|
+
For precision 1 the function just returns 1 since the
|
|
671
|
+
exponential is always a 1-unit::
|
|
672
|
+
|
|
673
|
+
sage: x = Zp(3).random_element()
|
|
674
|
+
sage: while x.dist(0) >= 1:
|
|
675
|
+
....: x = Zp(3).random_element()
|
|
676
|
+
sage: x.artin_hasse_exp(1)
|
|
677
|
+
1 + O(3)
|
|
678
|
+
|
|
679
|
+
TESTS:
|
|
680
|
+
|
|
681
|
+
Using Theorem 2.5 of [Conr]_::
|
|
682
|
+
|
|
683
|
+
sage: x1 = 5*Zp(5).random_element()
|
|
684
|
+
sage: x2 = 5*Zp(5).random_element()
|
|
685
|
+
sage: y1 = x1.artin_hasse_exp()
|
|
686
|
+
sage: y2 = x2.artin_hasse_exp()
|
|
687
|
+
sage: (y1 - y2).abs() == (x1 - x2).abs()
|
|
688
|
+
True
|
|
689
|
+
|
|
690
|
+
Comparing with the formal power series definition::
|
|
691
|
+
|
|
692
|
+
sage: x = PowerSeriesRing(QQ, 'x', default_prec=82).gen()
|
|
693
|
+
sage: AH = sum(x**(3**i)/(3**i) for i in range(5)).O(82).exp()
|
|
694
|
+
sage: z = Zp(3)(33/7)
|
|
695
|
+
sage: ahz = AH(z); ahz # needs sage.libs.ntl
|
|
696
|
+
1 + 2*3 + 3^2 + 3^3 + 2*3^5 + 3^6 + 2*3^7 + 3^9 + 3^11 + 3^12 +
|
|
697
|
+
3^13 + 3^14 + 2*3^15 + 3^16 + 2*3^18 + 2*3^19 + O(3^20)
|
|
698
|
+
sage: ahz - z.artin_hasse_exp() # needs sage.libs.ntl
|
|
699
|
+
O(3^20)
|
|
700
|
+
|
|
701
|
+
Out of convergence domain::
|
|
702
|
+
|
|
703
|
+
sage: Zp(5)(1).artin_hasse_exp()
|
|
704
|
+
Traceback (most recent call last):
|
|
705
|
+
...
|
|
706
|
+
ValueError: Artin-Hasse exponential does not converge on this input
|
|
707
|
+
|
|
708
|
+
AUTHORS:
|
|
709
|
+
|
|
710
|
+
- Mitchell Owen, Sebastian Pancrantz (2012-02): initial version.
|
|
711
|
+
|
|
712
|
+
- Xavier Caruso (2018-08): extend to any p-adic rings and fields
|
|
713
|
+
and implement several algorithms.
|
|
714
|
+
"""
|
|
715
|
+
if self.valuation() < 1:
|
|
716
|
+
raise ValueError("Artin-Hasse exponential does not converge on this input")
|
|
717
|
+
R = self.parent()
|
|
718
|
+
if prec is None:
|
|
719
|
+
prec = min(self.precision_absolute(), R.precision_cap())
|
|
720
|
+
else:
|
|
721
|
+
prec = min(prec, self.precision_absolute(), R.precision_cap())
|
|
722
|
+
|
|
723
|
+
if algorithm is None:
|
|
724
|
+
try:
|
|
725
|
+
R(0).exp(1, algorithm='binary_splitting') # we check that binary splitting is available
|
|
726
|
+
ans = self._AHE_direct(prec, exp_algorithm='binary_splitting')
|
|
727
|
+
except NotImplementedError:
|
|
728
|
+
try:
|
|
729
|
+
R(1).log(1, algorithm='binary_splitting') # we check that binary splitting is available
|
|
730
|
+
ans = self._AHE_newton(prec, log_algorithm='binary_splitting')
|
|
731
|
+
except NotImplementedError:
|
|
732
|
+
ans = self._AHE_series(prec)
|
|
733
|
+
elif algorithm == 'direct':
|
|
734
|
+
ans = self._AHE_direct(prec)
|
|
735
|
+
elif algorithm == 'series':
|
|
736
|
+
ans = self._AHE_series(prec)
|
|
737
|
+
elif algorithm == 'newton':
|
|
738
|
+
ans = self._AHE_newton(prec)
|
|
739
|
+
else:
|
|
740
|
+
raise ValueError("Algorithm must be 'direct', 'series', 'newton' or None")
|
|
741
|
+
return ans
|
|
742
|
+
|
|
743
|
+
def _AHE_direct(self, prec, exp_algorithm=None):
|
|
744
|
+
r"""
|
|
745
|
+
Return the Artin-Hasse exponential of this element.
|
|
746
|
+
|
|
747
|
+
If `x` denotes the input element, its Artin-Hasse
|
|
748
|
+
exponential is computed by taking the exponential of
|
|
749
|
+
|
|
750
|
+
.. MATH::
|
|
751
|
+
|
|
752
|
+
x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \cdots.
|
|
753
|
+
|
|
754
|
+
INPUT:
|
|
755
|
+
|
|
756
|
+
- ``prec`` -- integer; the precision at which the
|
|
757
|
+
result should be computed
|
|
758
|
+
|
|
759
|
+
- ``exp_algorithm`` -- string; the algorithm called
|
|
760
|
+
for computing the exponential
|
|
761
|
+
|
|
762
|
+
EXAMPLES::
|
|
763
|
+
|
|
764
|
+
sage: W = Zp(3,10)
|
|
765
|
+
sage: W(123456).artin_hasse_exp(algorithm='direct') # indirect doctest
|
|
766
|
+
1 + 3 + 2*3^3 + 2*3^4 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + O(3^10)
|
|
767
|
+
|
|
768
|
+
When `x^{p^i}/p^i` is not in the domain of convergence of the
|
|
769
|
+
exponential for some nonnegative integer `i`, an error is raised::
|
|
770
|
+
|
|
771
|
+
sage: # needs sage.libs.ntl
|
|
772
|
+
sage: S.<x> = W[]
|
|
773
|
+
sage: R.<pi> = W.extension(x^2 + 3)
|
|
774
|
+
sage: pi.artin_hasse_exp(algorithm='direct') # indirect doctest # needs sage.symbolic
|
|
775
|
+
Traceback (most recent call last):
|
|
776
|
+
...
|
|
777
|
+
NotImplementedError: one factor of the Artin-Hasse exponential does not converge
|
|
778
|
+
|
|
779
|
+
There is however an important exception.
|
|
780
|
+
When we are working over `\ZZ_2` or `\QQ_2` and `x` is congruent to `2`
|
|
781
|
+
modulo `4`, then `x` and `x^2/2` are not in the domain of convergence of
|
|
782
|
+
the exponential. However, `\exp(x + x^2/2)` does converge.
|
|
783
|
+
In this case, the Artin-Hasse exponential of `x`, denoted by `AH(x)`, is
|
|
784
|
+
|
|
785
|
+
.. MATH::
|
|
786
|
+
|
|
787
|
+
AH(x) = - \exp(x + \frac{x^2}{2} + \frac{x^4}{4} + \dots)
|
|
788
|
+
|
|
789
|
+
with a negative sign. This method knows about this fact and handles
|
|
790
|
+
the computation correctly::
|
|
791
|
+
|
|
792
|
+
sage: W = Zp(2,8)
|
|
793
|
+
sage: x = W(1234); x
|
|
794
|
+
2 + 2^4 + 2^6 + 2^7 + O(2^9)
|
|
795
|
+
sage: y1 = x.artin_hasse_exp(algorithm='direct'); y1
|
|
796
|
+
1 + 2 + 2^2 + 2^6 + O(2^8)
|
|
797
|
+
sage: y2 = exp(x + x^2/2 + x^4/4 + x^8/8); y2
|
|
798
|
+
1 + 2^3 + 2^4 + 2^5 + 2^7 + O(2^8)
|
|
799
|
+
sage: y1 == -y2
|
|
800
|
+
True
|
|
801
|
+
sage: y1 == x.artin_hasse_exp(algorithm='series') # needs sage.symbolic
|
|
802
|
+
True
|
|
803
|
+
|
|
804
|
+
.. SEEALSO::
|
|
805
|
+
|
|
806
|
+
:meth:`artin_hasse_exp`, :meth:`_AHE_series`, :meth:`_AHE_newton`
|
|
807
|
+
"""
|
|
808
|
+
R = self.parent()
|
|
809
|
+
p = R.prime()
|
|
810
|
+
pow = self.add_bigoh(prec)
|
|
811
|
+
arg = pow
|
|
812
|
+
denom = 1
|
|
813
|
+
trunc = prec
|
|
814
|
+
if R.absolute_degree() == 1:
|
|
815
|
+
# Special code for Zp and Qp
|
|
816
|
+
while pow != 0:
|
|
817
|
+
trunc += 1
|
|
818
|
+
pow = (pow**p).add_bigoh(trunc)
|
|
819
|
+
denom *= p
|
|
820
|
+
arg += pow/denom
|
|
821
|
+
AH = arg.exp(algorithm=exp_algorithm)
|
|
822
|
+
if p == 2 and self.add_bigoh(2) == 2:
|
|
823
|
+
AH = -AH
|
|
824
|
+
else:
|
|
825
|
+
e = R.absolute_e()
|
|
826
|
+
ep = e // (p-1)
|
|
827
|
+
while pow != 0:
|
|
828
|
+
trunc += e
|
|
829
|
+
pow = (pow**p).add_bigoh(trunc)
|
|
830
|
+
denom *= p
|
|
831
|
+
s = pow/denom
|
|
832
|
+
if s.valuation() <= ep:
|
|
833
|
+
raise NotImplementedError("one factor of the Artin-Hasse exponential does not converge")
|
|
834
|
+
arg += s
|
|
835
|
+
AH = arg.exp(algorithm=exp_algorithm)
|
|
836
|
+
return AH
|
|
837
|
+
|
|
838
|
+
def _AHE_series(self, prec):
|
|
839
|
+
r"""
|
|
840
|
+
Return the Artin-Hasse exponential of this element.
|
|
841
|
+
|
|
842
|
+
This method first evaluates the Artin-Hasse series
|
|
843
|
+
|
|
844
|
+
.. MATH::
|
|
845
|
+
|
|
846
|
+
AH(x) = \exp(x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \dots)
|
|
847
|
+
|
|
848
|
+
at enough precision and then plugs in the input element.
|
|
849
|
+
|
|
850
|
+
INPUT:
|
|
851
|
+
|
|
852
|
+
- ``prec`` -- integer; the precision at which the
|
|
853
|
+
result should be computed
|
|
854
|
+
|
|
855
|
+
EXAMPLES::
|
|
856
|
+
|
|
857
|
+
sage: W = Zp(3,10)
|
|
858
|
+
sage: W(123456).artin_hasse_exp(algorithm='series') # indirect doctest # needs sage.symbolic
|
|
859
|
+
1 + 3 + 2*3^3 + 2*3^4 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + O(3^10)
|
|
860
|
+
|
|
861
|
+
sage: # needs sage.libs.ntl
|
|
862
|
+
sage: S.<x> = W[]
|
|
863
|
+
sage: R.<pi> = W.extension(x^2 + 3)
|
|
864
|
+
sage: pi.artin_hasse_exp(algorithm='series') # indirect doctest # needs sage.symbolic
|
|
865
|
+
1 + pi + 2*pi^2 + 2*pi^3 + 2*pi^4 + 2*pi^10 + 2*pi^11 + pi^13 + pi^18 + pi^19 + O(pi^20)
|
|
866
|
+
|
|
867
|
+
.. SEEALSO::
|
|
868
|
+
|
|
869
|
+
:meth:`artin_hasse_exp`, :meth:`_AHE_direct`, :meth:`_AHE_newton`
|
|
870
|
+
"""
|
|
871
|
+
R = self.parent()
|
|
872
|
+
p = R.prime()
|
|
873
|
+
e = R.absolute_e()
|
|
874
|
+
|
|
875
|
+
# We compute the Artin-Hasse series at the requested precision
|
|
876
|
+
L = _AHE_coefficients(p, prec, 1 + (prec-1)//e)
|
|
877
|
+
# We evaluate it using Horner algorithm
|
|
878
|
+
y = R(0)
|
|
879
|
+
x = self.add_bigoh(prec)
|
|
880
|
+
for i in range(prec-1, -1, -1):
|
|
881
|
+
y = y*x + R(L[i])
|
|
882
|
+
|
|
883
|
+
return y
|
|
884
|
+
|
|
885
|
+
def _AHE_newton(self, prec, log_algorithm=None):
|
|
886
|
+
r"""
|
|
887
|
+
Return the Artin-Hasse exponential of this element.
|
|
888
|
+
|
|
889
|
+
If `x` denotes the input element, its Artin-Hasse exponential
|
|
890
|
+
is computed by solving the following equation in `y`
|
|
891
|
+
|
|
892
|
+
.. MATH::
|
|
893
|
+
|
|
894
|
+
\log(y) = x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \dots
|
|
895
|
+
|
|
896
|
+
using a Newton scheme.
|
|
897
|
+
|
|
898
|
+
The first approximation used for initializing the Newton iteration
|
|
899
|
+
is computed using the ``series`` algorithm (see :meth:`_AHE_series`).
|
|
900
|
+
|
|
901
|
+
INPUT:
|
|
902
|
+
|
|
903
|
+
- ``prec`` -- integer; the precision at which the
|
|
904
|
+
result should be computed
|
|
905
|
+
|
|
906
|
+
EXAMPLES::
|
|
907
|
+
|
|
908
|
+
sage: W = Zp(3,10)
|
|
909
|
+
sage: W(123456).artin_hasse_exp(algorithm='newton') # indirect doctest
|
|
910
|
+
1 + 3 + 2*3^3 + 2*3^4 + 3^5 + 2*3^6 + 2*3^7 + 3^8 + O(3^10)
|
|
911
|
+
|
|
912
|
+
sage: # needs sage.libs.ntl
|
|
913
|
+
sage: S.<x> = W[]
|
|
914
|
+
sage: R.<pi> = W.extension(x^2 + 3)
|
|
915
|
+
sage: pi.artin_hasse_exp(algorithm='newton') # indirect doctest # needs sage.symbolic
|
|
916
|
+
1 + pi + 2*pi^2 + 2*pi^3 + 2*pi^4 + 2*pi^10 + 2*pi^11 + pi^13 + pi^18 + pi^19 + O(pi^20)
|
|
917
|
+
|
|
918
|
+
.. SEEALSO::
|
|
919
|
+
|
|
920
|
+
:meth:`artin_hasse_exp`, :meth:`_AHE_direct`, :meth:`_AHE_series`
|
|
921
|
+
"""
|
|
922
|
+
R = self.parent()
|
|
923
|
+
p = R.prime()
|
|
924
|
+
e = R.absolute_e()
|
|
925
|
+
|
|
926
|
+
# Step 1:
|
|
927
|
+
# We compute a sufficiently good approximation of the result
|
|
928
|
+
# in order to bootstrap the Newton iteration
|
|
929
|
+
|
|
930
|
+
# We compute the Artin-Hasse series at the requested precision
|
|
931
|
+
ep = e // (p-1)
|
|
932
|
+
startprec = min(prec, ep+1)
|
|
933
|
+
L = _AHE_coefficients(p, startprec, 1)
|
|
934
|
+
# We evaluate it using Horner algorithm
|
|
935
|
+
y = R(0)
|
|
936
|
+
x = self.add_bigoh(startprec)
|
|
937
|
+
for i in range(startprec-1, -1, -1):
|
|
938
|
+
y = y*x + R(L[i])
|
|
939
|
+
|
|
940
|
+
# Step 2:
|
|
941
|
+
# We use Newton iteration to solve the equation
|
|
942
|
+
# log(AH(x)) = x + x^p/p + x^(p^2)/p^2 + ...
|
|
943
|
+
|
|
944
|
+
# We compute b = 1 + x + x^p/p + x^(p^2)/p^2 + ...
|
|
945
|
+
pow = self.add_bigoh(prec)
|
|
946
|
+
b = 1 + pow
|
|
947
|
+
denom = 1
|
|
948
|
+
trunc = prec
|
|
949
|
+
while pow != 0:
|
|
950
|
+
trunc += e
|
|
951
|
+
pow = (pow**p).add_bigoh(trunc)
|
|
952
|
+
denom *= p
|
|
953
|
+
b += pow/denom
|
|
954
|
+
# We iterate the Newton scheme: y_(n+1) = y_n * (b - log(y_n))
|
|
955
|
+
curprec = startprec
|
|
956
|
+
while curprec < prec:
|
|
957
|
+
if p == 2:
|
|
958
|
+
curprec = 2*curprec - e
|
|
959
|
+
else:
|
|
960
|
+
curprec = 2*curprec
|
|
961
|
+
y = y.lift_to_precision(min(prec,curprec))
|
|
962
|
+
y *= b - y.log(algorithm=log_algorithm)
|
|
963
|
+
|
|
964
|
+
return R(y)
|
|
965
|
+
|
|
966
|
+
def minimal_polynomial(self, name='x', base=None):
|
|
967
|
+
"""
|
|
968
|
+
Return the minimal polynomial of this element over ``base``.
|
|
969
|
+
|
|
970
|
+
INPUT:
|
|
971
|
+
|
|
972
|
+
- ``name`` -- string (default: ``'x'``); the name of the variable
|
|
973
|
+
|
|
974
|
+
- ``base`` -- a ring (default: the base ring of the parent);
|
|
975
|
+
the base ring over which the minimal polynomial is computed
|
|
976
|
+
|
|
977
|
+
EXAMPLES::
|
|
978
|
+
|
|
979
|
+
sage: Zp(5,5)(1/3).minimal_polynomial('x') # needs sage.libs.ntl
|
|
980
|
+
(1 + O(5^5))*x + 3 + 5 + 3*5^2 + 5^3 + 3*5^4 + O(5^5)
|
|
981
|
+
|
|
982
|
+
sage: Zp(5,5)(1/3).minimal_polynomial('foo') # needs sage.libs.ntl
|
|
983
|
+
(1 + O(5^5))*foo + 3 + 5 + 3*5^2 + 5^3 + 3*5^4 + O(5^5)
|
|
984
|
+
|
|
985
|
+
::
|
|
986
|
+
|
|
987
|
+
sage: # needs sage.libs.ntl
|
|
988
|
+
sage: K.<a> = QqCR(2^3,5)
|
|
989
|
+
sage: S.<x> = K[]
|
|
990
|
+
sage: L.<pi> = K.extension(x^4 - 2*a)
|
|
991
|
+
sage: pi.minimal_polynomial() # needs sage.symbolic
|
|
992
|
+
(1 + O(2^5))*x^4 + a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6)
|
|
993
|
+
sage: (pi^2).minimal_polynomial() # needs sage.symbolic
|
|
994
|
+
(1 + O(2^5))*x^2 + a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6)
|
|
995
|
+
sage: (1/pi).minimal_polynomial() # needs sage.symbolic
|
|
996
|
+
(1 + O(2^5))*x^4 + (a^2 + 1)*2^-1 + O(2^4)
|
|
997
|
+
sage: elt = L.random_element()
|
|
998
|
+
sage: P = elt.minimal_polynomial() # not tested, known bug (see :issue:`32111`)
|
|
999
|
+
sage: P(elt) == 0 # not tested
|
|
1000
|
+
True
|
|
1001
|
+
"""
|
|
1002
|
+
parent = self.parent()
|
|
1003
|
+
R = parent.base_ring()
|
|
1004
|
+
if base is None:
|
|
1005
|
+
base = R
|
|
1006
|
+
polring = base[name]
|
|
1007
|
+
if base is parent:
|
|
1008
|
+
return polring([-self,1])
|
|
1009
|
+
elif base is R:
|
|
1010
|
+
from sage.modules.free_module import VectorSpace
|
|
1011
|
+
L = parent.fraction_field()
|
|
1012
|
+
K = base.fraction_field()
|
|
1013
|
+
deg = L.relative_degree()
|
|
1014
|
+
V = VectorSpace(K, deg)
|
|
1015
|
+
vector = [K(1)] + (deg-1)*[K(0)]
|
|
1016
|
+
vectors = [vector]
|
|
1017
|
+
W = V.span(vectors)
|
|
1018
|
+
elt = self
|
|
1019
|
+
while True:
|
|
1020
|
+
poly = elt.polynomial()
|
|
1021
|
+
vector = V([ poly[i] for i in range(deg) ])
|
|
1022
|
+
if vector in W: break
|
|
1023
|
+
vectors.append(vector)
|
|
1024
|
+
W += V.span([vector])
|
|
1025
|
+
elt *= self
|
|
1026
|
+
W = V.span_of_basis(vectors)
|
|
1027
|
+
coeffs = [ -c for c in W.coordinate_vector(vector) ] + [K(1)]
|
|
1028
|
+
return polring(coeffs)
|
|
1029
|
+
else:
|
|
1030
|
+
raise NotImplementedError
|
|
1031
|
+
|
|
1032
|
+
def norm(self, base=None):
|
|
1033
|
+
"""
|
|
1034
|
+
Return the norm of this `p`-adic element over ``base``.
|
|
1035
|
+
|
|
1036
|
+
.. WARNING::
|
|
1037
|
+
|
|
1038
|
+
This is not the `p`-adic absolute value. This is a field
|
|
1039
|
+
theoretic norm down to a base ring. If you want the
|
|
1040
|
+
`p`-adic absolute value, use the method :meth:`abs`
|
|
1041
|
+
instead.
|
|
1042
|
+
|
|
1043
|
+
INPUT:
|
|
1044
|
+
|
|
1045
|
+
- ``base`` -- a subring of the parent (default: base ring)
|
|
1046
|
+
|
|
1047
|
+
OUTPUT: the norm of this `p`-adic element over the given base
|
|
1048
|
+
|
|
1049
|
+
EXAMPLES::
|
|
1050
|
+
|
|
1051
|
+
sage: Zp(5)(5).norm() # needs sage.libs.ntl
|
|
1052
|
+
5 + O(5^21)
|
|
1053
|
+
|
|
1054
|
+
::
|
|
1055
|
+
|
|
1056
|
+
sage: # needs sage.libs.ntl
|
|
1057
|
+
sage: K.<a> = QqCR(2^3,5)
|
|
1058
|
+
sage: S.<x> = K[]
|
|
1059
|
+
sage: L.<pi> = K.extension(x^4 - 2*a)
|
|
1060
|
+
sage: pi.norm() # norm over K # needs sage.symbolic
|
|
1061
|
+
a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6)
|
|
1062
|
+
sage: (pi^2).norm() # needs sage.symbolic
|
|
1063
|
+
a^2*2^2 + O(2^7)
|
|
1064
|
+
sage: pi.norm()^2 # needs sage.symbolic
|
|
1065
|
+
a^2*2^2 + O(2^7)
|
|
1066
|
+
|
|
1067
|
+
TESTS::
|
|
1068
|
+
|
|
1069
|
+
sage: x = L.random_element() # needs sage.libs.ntl
|
|
1070
|
+
sage: y = L.random_element() # needs sage.libs.ntl
|
|
1071
|
+
sage: (x*y).norm() == x.norm() * y.norm() # not tested, known bug (see :issue:`32085`)
|
|
1072
|
+
True
|
|
1073
|
+
"""
|
|
1074
|
+
parent = self.parent()
|
|
1075
|
+
if base is None:
|
|
1076
|
+
base = parent.base_ring()
|
|
1077
|
+
poly = self.minimal_polynomial(base=base)
|
|
1078
|
+
polydeg = poly.degree()
|
|
1079
|
+
extdeg = parent.absolute_degree() // (base.absolute_degree() * polydeg)
|
|
1080
|
+
return ((-1)**polydeg * poly[0]) ** extdeg
|
|
1081
|
+
|
|
1082
|
+
def trace(self, base=None):
|
|
1083
|
+
"""
|
|
1084
|
+
Return the trace of this `p`-adic element over the base ring.
|
|
1085
|
+
|
|
1086
|
+
INPUT:
|
|
1087
|
+
|
|
1088
|
+
- ``base`` -- a subring of the parent (default: base ring)
|
|
1089
|
+
|
|
1090
|
+
OUTPUT: the trace of this `p`-adic element over the given base
|
|
1091
|
+
|
|
1092
|
+
EXAMPLES::
|
|
1093
|
+
|
|
1094
|
+
sage: Zp(5,5)(5).trace() # needs sage.libs.ntl
|
|
1095
|
+
5 + O(5^6)
|
|
1096
|
+
|
|
1097
|
+
sage: # needs sage.libs.ntl
|
|
1098
|
+
sage: K.<a> = QqCR(2^3,7)
|
|
1099
|
+
sage: S.<x> = K[]
|
|
1100
|
+
sage: L.<pi> = K.extension(x^4 - 4*a*x^3 + 2*a)
|
|
1101
|
+
sage: pi.trace() # trace over K # needs sage.symbolic
|
|
1102
|
+
a*2^2 + O(2^8)
|
|
1103
|
+
sage: (pi+1).trace() # needs sage.symbolic
|
|
1104
|
+
(a + 1)*2^2 + O(2^7)
|
|
1105
|
+
|
|
1106
|
+
TESTS::
|
|
1107
|
+
|
|
1108
|
+
sage: x = L.random_element() # needs sage.libs.ntl
|
|
1109
|
+
sage: y = L.random_element() # needs sage.libs.ntl
|
|
1110
|
+
sage: (x+y).trace() == x.trace() + y.trace() # not tested, known bug (see :issue:`32085`)
|
|
1111
|
+
True
|
|
1112
|
+
"""
|
|
1113
|
+
parent = self.parent()
|
|
1114
|
+
if base is None:
|
|
1115
|
+
base = parent.base_ring()
|
|
1116
|
+
poly = self.minimal_polynomial(base=base)
|
|
1117
|
+
polydeg = poly.degree()
|
|
1118
|
+
extdeg = parent.absolute_degree() // (base.absolute_degree() * polydeg)
|
|
1119
|
+
return -extdeg * poly[polydeg-1]
|
|
1120
|
+
|
|
1121
|
+
def algebraic_dependency(self, n):
|
|
1122
|
+
"""
|
|
1123
|
+
Return a polynomial of degree at most `n` which is approximately
|
|
1124
|
+
satisfied by this number.
|
|
1125
|
+
|
|
1126
|
+
Note that the returned polynomial need not be irreducible, and
|
|
1127
|
+
indeed usually will not be if this number is a good
|
|
1128
|
+
approximation to an algebraic number of degree less than `n`.
|
|
1129
|
+
|
|
1130
|
+
ALGORITHM: Uses the PARI C-library :pari:`algdep` command.
|
|
1131
|
+
|
|
1132
|
+
INPUT:
|
|
1133
|
+
|
|
1134
|
+
- ``self`` -- a `p`-adic element
|
|
1135
|
+
- ``n`` -- integer
|
|
1136
|
+
|
|
1137
|
+
OUTPUT:
|
|
1138
|
+
|
|
1139
|
+
polynomial; degree `n` polynomial approximately satisfied by ``self``
|
|
1140
|
+
|
|
1141
|
+
EXAMPLES::
|
|
1142
|
+
|
|
1143
|
+
sage: K = Qp(3,20,'capped-rel','series'); R = Zp(3,20,'capped-rel','series')
|
|
1144
|
+
sage: a = K(7/19); a
|
|
1145
|
+
1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12
|
|
1146
|
+
+ 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20)
|
|
1147
|
+
sage: a.algebraic_dependency(1)
|
|
1148
|
+
19*x - 7
|
|
1149
|
+
sage: K2 = Qp(7,20,'capped-rel')
|
|
1150
|
+
sage: b = K2.zeta(); b.algebraic_dependency(2)
|
|
1151
|
+
x^2 - x + 1
|
|
1152
|
+
sage: K2 = Qp(11,20,'capped-rel')
|
|
1153
|
+
sage: b = K2.zeta(); b.algebraic_dependency(4)
|
|
1154
|
+
x^4 - x^3 + x^2 - x + 1
|
|
1155
|
+
sage: a = R(7/19); a
|
|
1156
|
+
1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12
|
|
1157
|
+
+ 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20)
|
|
1158
|
+
sage: a.algebraic_dependency(1)
|
|
1159
|
+
19*x - 7
|
|
1160
|
+
sage: R2 = Zp(7,20,'capped-rel')
|
|
1161
|
+
sage: b = R2.zeta(); b.algebraic_dependency(2)
|
|
1162
|
+
x^2 - x + 1
|
|
1163
|
+
sage: R2 = Zp(11,20,'capped-rel')
|
|
1164
|
+
sage: b = R2.zeta(); b.algebraic_dependency(4)
|
|
1165
|
+
x^4 - x^3 + x^2 - x + 1
|
|
1166
|
+
"""
|
|
1167
|
+
# TODO: figure out if this works for extension rings.
|
|
1168
|
+
# If not, move this to padic_base_generic_element.
|
|
1169
|
+
from sage.arith.misc import algebraic_dependency
|
|
1170
|
+
return algebraic_dependency(self, n)
|
|
1171
|
+
|
|
1172
|
+
algdep = algebraic_dependency
|
|
1173
|
+
|
|
1174
|
+
#def exp_artin_hasse(self):
|
|
1175
|
+
# """
|
|
1176
|
+
# Returns the Artin-Hasse exponential of self.
|
|
1177
|
+
|
|
1178
|
+
# This is defined by: E_p(x) = exp(x + x^p/p + x^(p^2)/p^2 + ...)
|
|
1179
|
+
# """
|
|
1180
|
+
# raise NotImplementedError
|
|
1181
|
+
|
|
1182
|
+
def dwork_expansion(self, bd=20, a=0):
|
|
1183
|
+
r"""
|
|
1184
|
+
Return the value of a function defined by Dwork.
|
|
1185
|
+
|
|
1186
|
+
Used to compute the `p`-adic Gamma function, see :meth:`gamma`.
|
|
1187
|
+
|
|
1188
|
+
INPUT:
|
|
1189
|
+
|
|
1190
|
+
- ``bd`` -- integer (default: 20); precision bound
|
|
1191
|
+
- ``a`` -- integer (default: 0); offset parameter
|
|
1192
|
+
|
|
1193
|
+
OUTPUT: a `p`-adic integer
|
|
1194
|
+
|
|
1195
|
+
.. NOTE::
|
|
1196
|
+
|
|
1197
|
+
This is based on GP code written by Fernando Rodriguez
|
|
1198
|
+
Villegas (http://www.ma.utexas.edu/cnt/cnt-frames.html).
|
|
1199
|
+
William Stein sped it up for GP
|
|
1200
|
+
(http://sage.math.washington.edu/home/wstein/www/home/wbhart/pari-2.4.2.alpha/src/basemath/trans2.c).
|
|
1201
|
+
The output is a `p`-adic integer from Dwork's expansion,
|
|
1202
|
+
used to compute the `p`-adic gamma function as in [RV2007]_
|
|
1203
|
+
section 6.2.
|
|
1204
|
+
The coefficients of the expansion are now cached to speed up
|
|
1205
|
+
multiple evaluation, as in the trace formula for hypergeometric
|
|
1206
|
+
motives.
|
|
1207
|
+
|
|
1208
|
+
EXAMPLES::
|
|
1209
|
+
|
|
1210
|
+
sage: R = Zp(17)
|
|
1211
|
+
sage: x = R(5+3*17+13*17^2+6*17^3+12*17^5+10*17^(14)+5*17^(17)+O(17^(19)))
|
|
1212
|
+
sage: x.dwork_expansion(18)
|
|
1213
|
+
16 + 7*17 + 11*17^2 + 4*17^3 + 8*17^4 + 10*17^5 + 11*17^6 + 6*17^7
|
|
1214
|
+
+ 17^8 + 8*17^10 + 13*17^11 + 9*17^12 + 15*17^13 + 2*17^14 + 6*17^15
|
|
1215
|
+
+ 7*17^16 + 6*17^17 + O(17^18)
|
|
1216
|
+
|
|
1217
|
+
sage: R = Zp(5)
|
|
1218
|
+
sage: x = R(3*5^2+4*5^3+1*5^4+2*5^5+1*5^(10)+O(5^(20)))
|
|
1219
|
+
sage: x.dwork_expansion()
|
|
1220
|
+
4 + 4*5 + 4*5^2 + 4*5^3 + 2*5^4 + 4*5^5 + 5^7 + 3*5^9 + 4*5^10 + 3*5^11
|
|
1221
|
+
+ 5^13 + 4*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 3*5^18 + O(5^20)
|
|
1222
|
+
|
|
1223
|
+
TESTS:
|
|
1224
|
+
|
|
1225
|
+
This test was added in :issue:`24433`::
|
|
1226
|
+
|
|
1227
|
+
sage: F = Qp(7)
|
|
1228
|
+
sage: F(4).gamma()
|
|
1229
|
+
6 + O(7^20)
|
|
1230
|
+
sage: -F(1).dwork_expansion(a=3)
|
|
1231
|
+
6 + 4*7^19 + O(7^20)
|
|
1232
|
+
"""
|
|
1233
|
+
R = self.parent()
|
|
1234
|
+
p = R.prime()
|
|
1235
|
+
|
|
1236
|
+
# If p == 2, must work in Qp rather than Zp.
|
|
1237
|
+
if p == 2 and not R.is_field():
|
|
1238
|
+
S = R.fraction_field()
|
|
1239
|
+
return R(S(self).dwork_expansion(bd, a))
|
|
1240
|
+
try:
|
|
1241
|
+
v = R.dwork_coeffs
|
|
1242
|
+
if len(v) < p*bd:
|
|
1243
|
+
raise AttributeError
|
|
1244
|
+
except AttributeError:
|
|
1245
|
+
v = dwork_mahler_coeffs(R, bd)
|
|
1246
|
+
return evaluate_dwork_mahler(v, self, p, bd, a)
|
|
1247
|
+
|
|
1248
|
+
def gamma(self, algorithm='pari'):
|
|
1249
|
+
r"""
|
|
1250
|
+
Return the value of the `p`-adic Gamma function.
|
|
1251
|
+
|
|
1252
|
+
INPUT:
|
|
1253
|
+
|
|
1254
|
+
- ``algorithm`` -- string. Can be set to ``'pari'`` to call
|
|
1255
|
+
the PARI function, or ``'sage'`` to call the function
|
|
1256
|
+
implemented in Sage. The default is ``'pari'`` since
|
|
1257
|
+
PARI is about 10 times faster than Sage.
|
|
1258
|
+
|
|
1259
|
+
OUTPUT: a `p`-adic integer
|
|
1260
|
+
|
|
1261
|
+
.. NOTE::
|
|
1262
|
+
|
|
1263
|
+
This is based on GP code written by Fernando Rodriguez
|
|
1264
|
+
Villegas (http://www.ma.utexas.edu/cnt/cnt-frames.html).
|
|
1265
|
+
William Stein sped it up for GP
|
|
1266
|
+
(http://sage.math.washington.edu/home/wstein/www/home/wbhart/pari-2.4.2.alpha/src/basemath/trans2.c).
|
|
1267
|
+
The ``'sage'`` version uses dwork_expansion() to compute the
|
|
1268
|
+
`p`-adic gamma function of ``self`` as in [RV2007]_ section 6.2.
|
|
1269
|
+
|
|
1270
|
+
EXAMPLES:
|
|
1271
|
+
|
|
1272
|
+
This example illustrates ``x.gamma()`` for `x` a `p`-adic unit::
|
|
1273
|
+
|
|
1274
|
+
sage: R = Zp(7)
|
|
1275
|
+
sage: x = R(2+3*7^2+4*7^3+O(7^20))
|
|
1276
|
+
sage: x.gamma('pari')
|
|
1277
|
+
1 + 2*7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^8 + 7^9 + 4*7^10 + 3*7^12
|
|
1278
|
+
+ 7^13 + 5*7^14 + 3*7^15 + 2*7^16 + 2*7^17 + 5*7^18 + 4*7^19 + O(7^20)
|
|
1279
|
+
sage: x.gamma('sage')
|
|
1280
|
+
1 + 2*7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^8 + 7^9 + 4*7^10 + 3*7^12
|
|
1281
|
+
+ 7^13 + 5*7^14 + 3*7^15 + 2*7^16 + 2*7^17 + 5*7^18 + 4*7^19 + O(7^20)
|
|
1282
|
+
sage: x.gamma('pari') == x.gamma('sage')
|
|
1283
|
+
True
|
|
1284
|
+
|
|
1285
|
+
Now ``x.gamma()`` for `x` a `p`-adic integer but not a unit::
|
|
1286
|
+
|
|
1287
|
+
sage: R = Zp(17)
|
|
1288
|
+
sage: x = R(17+17^2+3*17^3+12*17^8+O(17^13))
|
|
1289
|
+
sage: x.gamma('pari')
|
|
1290
|
+
1 + 12*17 + 13*17^2 + 13*17^3 + 10*17^4 + 7*17^5 + 16*17^7
|
|
1291
|
+
+ 13*17^9 + 4*17^10 + 9*17^11 + 17^12 + O(17^13)
|
|
1292
|
+
sage: x.gamma('sage')
|
|
1293
|
+
1 + 12*17 + 13*17^2 + 13*17^3 + 10*17^4 + 7*17^5 + 16*17^7
|
|
1294
|
+
+ 13*17^9 + 4*17^10 + 9*17^11 + 17^12 + O(17^13)
|
|
1295
|
+
sage: x.gamma('pari') == x.gamma('sage')
|
|
1296
|
+
True
|
|
1297
|
+
|
|
1298
|
+
Finally, this function is not defined if `x` is not a `p`-adic integer::
|
|
1299
|
+
|
|
1300
|
+
sage: K = Qp(7)
|
|
1301
|
+
sage: x = K(7^-5 + 2*7^-4 + 5*7^-3 + 2*7^-2 + 3*7^-1 + 3 + 3*7
|
|
1302
|
+
....: + 7^3 + 4*7^4 + 5*7^5 + 6*7^8 + 3*7^9 + 6*7^10 + 5*7^11 + 6*7^12
|
|
1303
|
+
....: + 3*7^13 + 5*7^14 + O(7^15))
|
|
1304
|
+
sage: x.gamma()
|
|
1305
|
+
Traceback (most recent call last):
|
|
1306
|
+
...
|
|
1307
|
+
ValueError: The p-adic gamma function only works on elements of Zp
|
|
1308
|
+
|
|
1309
|
+
TESTS:
|
|
1310
|
+
|
|
1311
|
+
We check that :issue:`23784` is resolved::
|
|
1312
|
+
|
|
1313
|
+
sage: Zp(5)(0).gamma()
|
|
1314
|
+
1 + O(5^20)
|
|
1315
|
+
|
|
1316
|
+
Check the cached version of ``dwork_expansion`` from :issue:`24433`::
|
|
1317
|
+
|
|
1318
|
+
sage: p = next_prime(200)
|
|
1319
|
+
sage: F = Qp(p)
|
|
1320
|
+
sage: l1 = [F(a/(p-1)).gamma(algorithm='pari') for a in range(p-1)] # long time
|
|
1321
|
+
sage: l2 = [F(a/(p-1)).gamma(algorithm='sage') for a in range(p-1)] # long time
|
|
1322
|
+
sage: all(l1[i] == l2[i] for i in range(p-1)) # long time
|
|
1323
|
+
True
|
|
1324
|
+
|
|
1325
|
+
The `p`-adic Gamma function has anomalous behavior for the prime 2::
|
|
1326
|
+
|
|
1327
|
+
sage: F = Qp(2)
|
|
1328
|
+
sage: x = F(-1) + O(2^2)
|
|
1329
|
+
sage: x.gamma(algorithm='pari')
|
|
1330
|
+
1 + O(2)
|
|
1331
|
+
sage: x.gamma(algorithm='sage')
|
|
1332
|
+
1 + O(2)
|
|
1333
|
+
sage: x = F(-1) + O(2^3)
|
|
1334
|
+
sage: x.gamma(algorithm='pari')
|
|
1335
|
+
1 + O(2^3)
|
|
1336
|
+
sage: x.gamma(algorithm='sage')
|
|
1337
|
+
1 + O(2^3)
|
|
1338
|
+
"""
|
|
1339
|
+
if self.parent().absolute_degree() > 1 or self.valuation() < 0:
|
|
1340
|
+
raise ValueError('The p-adic gamma function only works '
|
|
1341
|
+
'on elements of Zp')
|
|
1342
|
+
parent = self.parent()
|
|
1343
|
+
n = self.precision_absolute()
|
|
1344
|
+
if n is infinity:
|
|
1345
|
+
# Have to deal with exact zeros separately
|
|
1346
|
+
return parent(1)
|
|
1347
|
+
if algorithm == 'pari':
|
|
1348
|
+
return parent(self.__pari__().gamma())
|
|
1349
|
+
elif algorithm == 'sage':
|
|
1350
|
+
p = parent.prime()
|
|
1351
|
+
bd = -((-n*p) // (p-1))
|
|
1352
|
+
k = (-self) % p
|
|
1353
|
+
x = (self+k) >> 1
|
|
1354
|
+
return -x.dwork_expansion(bd, k.lift())
|
|
1355
|
+
|
|
1356
|
+
@coerce_binop
|
|
1357
|
+
def gcd(self, other):
|
|
1358
|
+
r"""
|
|
1359
|
+
Return a greatest common divisor of ``self`` and ``other``.
|
|
1360
|
+
|
|
1361
|
+
INPUT:
|
|
1362
|
+
|
|
1363
|
+
- ``other`` -- an element in the same ring as ``self``
|
|
1364
|
+
|
|
1365
|
+
AUTHORS:
|
|
1366
|
+
|
|
1367
|
+
- Julian Rueth (2012-10-19): initial version
|
|
1368
|
+
|
|
1369
|
+
.. NOTE::
|
|
1370
|
+
|
|
1371
|
+
Since the elements are only given with finite precision,
|
|
1372
|
+
their greatest common divisor is in general not unique (not even up
|
|
1373
|
+
to units). For example `O(3)` is a representative for the elements
|
|
1374
|
+
0 and 3 in the 3-adic ring `\ZZ_3`. The greatest common
|
|
1375
|
+
divisor of `O(3)` and `O(3)` could be (among others) 3 or 0 which
|
|
1376
|
+
have different valuation. The algorithm implemented here, will
|
|
1377
|
+
return an element of minimal valuation among the possible greatest
|
|
1378
|
+
common divisors.
|
|
1379
|
+
|
|
1380
|
+
EXAMPLES:
|
|
1381
|
+
|
|
1382
|
+
The greatest common divisor is either zero or a power of the
|
|
1383
|
+
uniformizing parameter::
|
|
1384
|
+
|
|
1385
|
+
sage: R = Zp(3)
|
|
1386
|
+
sage: R.zero().gcd(R.zero())
|
|
1387
|
+
0
|
|
1388
|
+
sage: R(3).gcd(9)
|
|
1389
|
+
3 + O(3^21)
|
|
1390
|
+
|
|
1391
|
+
A nonzero result is always lifted to the maximal precision possible in
|
|
1392
|
+
the ring::
|
|
1393
|
+
|
|
1394
|
+
sage: a = R(3,2); a
|
|
1395
|
+
3 + O(3^2)
|
|
1396
|
+
sage: b = R(9,3); b
|
|
1397
|
+
3^2 + O(3^3)
|
|
1398
|
+
sage: a.gcd(b)
|
|
1399
|
+
3 + O(3^21)
|
|
1400
|
+
sage: a.gcd(0)
|
|
1401
|
+
3 + O(3^21)
|
|
1402
|
+
|
|
1403
|
+
If both elements are zero, then the result is zero with the precision
|
|
1404
|
+
set to the smallest of their precisions::
|
|
1405
|
+
|
|
1406
|
+
sage: a = R.zero(); a
|
|
1407
|
+
0
|
|
1408
|
+
sage: b = R(0,2); b
|
|
1409
|
+
O(3^2)
|
|
1410
|
+
sage: a.gcd(b)
|
|
1411
|
+
O(3^2)
|
|
1412
|
+
|
|
1413
|
+
One could argue that it is mathematically correct to return `9 +
|
|
1414
|
+
O(3^{22})` instead. However, this would lead to some confusing
|
|
1415
|
+
behaviour::
|
|
1416
|
+
|
|
1417
|
+
sage: alternative_gcd = R(9,22); alternative_gcd
|
|
1418
|
+
3^2 + O(3^22)
|
|
1419
|
+
sage: a.is_zero()
|
|
1420
|
+
True
|
|
1421
|
+
sage: b.is_zero()
|
|
1422
|
+
True
|
|
1423
|
+
sage: alternative_gcd.is_zero()
|
|
1424
|
+
False
|
|
1425
|
+
|
|
1426
|
+
If exactly one element is zero, then the result depends on the
|
|
1427
|
+
valuation of the other element::
|
|
1428
|
+
|
|
1429
|
+
sage: R(0,3).gcd(3^4)
|
|
1430
|
+
O(3^3)
|
|
1431
|
+
sage: R(0,4).gcd(3^4)
|
|
1432
|
+
O(3^4)
|
|
1433
|
+
sage: R(0,5).gcd(3^4)
|
|
1434
|
+
3^4 + O(3^24)
|
|
1435
|
+
|
|
1436
|
+
Over a field, the greatest common divisor is either zero (possibly with
|
|
1437
|
+
finite precision) or one::
|
|
1438
|
+
|
|
1439
|
+
sage: K = Qp(3)
|
|
1440
|
+
sage: K(3).gcd(0)
|
|
1441
|
+
1 + O(3^20)
|
|
1442
|
+
sage: K.zero().gcd(0)
|
|
1443
|
+
0
|
|
1444
|
+
sage: K.zero().gcd(K(0,2))
|
|
1445
|
+
O(3^2)
|
|
1446
|
+
sage: K(3).gcd(4)
|
|
1447
|
+
1 + O(3^20)
|
|
1448
|
+
|
|
1449
|
+
TESTS:
|
|
1450
|
+
|
|
1451
|
+
The implementation also works over extensions::
|
|
1452
|
+
|
|
1453
|
+
sage: # needs sage.libs.ntl
|
|
1454
|
+
sage: K = Qp(3)
|
|
1455
|
+
sage: R.<a> = K[]
|
|
1456
|
+
sage: L.<a> = K.extension(a^3-3)
|
|
1457
|
+
sage: (a+3).gcd(3)
|
|
1458
|
+
1 + O(a^60)
|
|
1459
|
+
sage: R = Zp(3)
|
|
1460
|
+
sage: S.<a> = R[]
|
|
1461
|
+
sage: S.<a> = R.extension(a^3-3)
|
|
1462
|
+
sage: (a+3).gcd(3)
|
|
1463
|
+
a + O(a^61)
|
|
1464
|
+
sage: K = Qp(3)
|
|
1465
|
+
sage: R.<a> = K[]
|
|
1466
|
+
sage: L.<a> = K.extension(a^2-2)
|
|
1467
|
+
sage: (a+3).gcd(3)
|
|
1468
|
+
1 + O(3^20)
|
|
1469
|
+
sage: R = Zp(3)
|
|
1470
|
+
sage: S.<a> = R[]
|
|
1471
|
+
sage: S.<a> = R.extension(a^2-2)
|
|
1472
|
+
sage: (a+3).gcd(3)
|
|
1473
|
+
1 + O(3^20)
|
|
1474
|
+
|
|
1475
|
+
For elements with a fixed modulus::
|
|
1476
|
+
|
|
1477
|
+
sage: R = ZpFM(3)
|
|
1478
|
+
sage: R(3).gcd(9)
|
|
1479
|
+
3
|
|
1480
|
+
|
|
1481
|
+
And elements with a capped absolute precision::
|
|
1482
|
+
|
|
1483
|
+
sage: R = ZpCA(3)
|
|
1484
|
+
sage: R(3).gcd(9)
|
|
1485
|
+
3 + O(3^20)
|
|
1486
|
+
"""
|
|
1487
|
+
if self.is_zero() and other.is_zero():
|
|
1488
|
+
if self.valuation() < other.valuation():
|
|
1489
|
+
return self
|
|
1490
|
+
else:
|
|
1491
|
+
return other
|
|
1492
|
+
|
|
1493
|
+
if self.parent().is_field():
|
|
1494
|
+
return self.parent().one()
|
|
1495
|
+
|
|
1496
|
+
if min(self.valuation(),other.valuation()) >= min(self.precision_absolute(),other.precision_absolute()):
|
|
1497
|
+
return self.parent().zero().add_bigoh(min(self.precision_absolute(),other.precision_absolute()))
|
|
1498
|
+
|
|
1499
|
+
return self.parent().uniformiser_pow( min(self.valuation(),other.valuation()) )
|
|
1500
|
+
|
|
1501
|
+
@coerce_binop
|
|
1502
|
+
def xgcd(self, other):
|
|
1503
|
+
r"""
|
|
1504
|
+
Compute the extended gcd of this element and ``other``.
|
|
1505
|
+
|
|
1506
|
+
INPUT:
|
|
1507
|
+
|
|
1508
|
+
- ``other`` -- an element in the same ring
|
|
1509
|
+
|
|
1510
|
+
OUTPUT:
|
|
1511
|
+
|
|
1512
|
+
A tuple ``r``, ``s``, ``t`` such that ``r`` is a greatest common
|
|
1513
|
+
divisor of this element and ``other`` and ``r = s*self + t*other``.
|
|
1514
|
+
|
|
1515
|
+
AUTHORS:
|
|
1516
|
+
|
|
1517
|
+
- Julian Rueth (2012-10-19): initial version
|
|
1518
|
+
|
|
1519
|
+
.. NOTE::
|
|
1520
|
+
|
|
1521
|
+
Since the elements are only given with finite precision, their
|
|
1522
|
+
greatest common divisor is in general not unique (not even up to
|
|
1523
|
+
units). For example `O(3)` is a representative for the elements 0
|
|
1524
|
+
and 3 in the 3-adic ring `\ZZ_3`. The greatest common
|
|
1525
|
+
divisor of `O(3)` and `O(3)` could be (among others) 3 or 0 which
|
|
1526
|
+
have different valuation. The algorithm implemented here, will
|
|
1527
|
+
return an element of minimal valuation among the possible greatest
|
|
1528
|
+
common divisors.
|
|
1529
|
+
|
|
1530
|
+
EXAMPLES:
|
|
1531
|
+
|
|
1532
|
+
The greatest common divisor is either zero or a power of the
|
|
1533
|
+
uniformizing parameter::
|
|
1534
|
+
|
|
1535
|
+
sage: R = Zp(3)
|
|
1536
|
+
sage: R.zero().xgcd(R.zero())
|
|
1537
|
+
(0, 1 + O(3^20), 0)
|
|
1538
|
+
sage: R(3).xgcd(9)
|
|
1539
|
+
(3 + O(3^21), 1 + O(3^20), 0)
|
|
1540
|
+
|
|
1541
|
+
Unlike for :meth:`gcd`, the result is not lifted to the maximal
|
|
1542
|
+
precision possible in the ring; it is such that ``r = s*self +
|
|
1543
|
+
t*other`` holds true::
|
|
1544
|
+
|
|
1545
|
+
sage: a = R(3,2); a
|
|
1546
|
+
3 + O(3^2)
|
|
1547
|
+
sage: b = R(9,3); b
|
|
1548
|
+
3^2 + O(3^3)
|
|
1549
|
+
sage: a.xgcd(b)
|
|
1550
|
+
(3 + O(3^2), 1 + O(3), 0)
|
|
1551
|
+
sage: a.xgcd(0)
|
|
1552
|
+
(3 + O(3^2), 1 + O(3), 0)
|
|
1553
|
+
|
|
1554
|
+
If both elements are zero, then the result is zero with
|
|
1555
|
+
the precision set to the smallest of their precisions::
|
|
1556
|
+
|
|
1557
|
+
sage: a = R.zero(); a
|
|
1558
|
+
0
|
|
1559
|
+
sage: b = R(0,2); b
|
|
1560
|
+
O(3^2)
|
|
1561
|
+
sage: a.xgcd(b)
|
|
1562
|
+
(O(3^2), 0, 1 + O(3^20))
|
|
1563
|
+
|
|
1564
|
+
If only one element is zero, then the result depends on its precision::
|
|
1565
|
+
|
|
1566
|
+
sage: # needs sage.rings.padics
|
|
1567
|
+
sage: R(9).xgcd(R(0,1))
|
|
1568
|
+
(O(3), 0, 1 + O(3^20))
|
|
1569
|
+
sage: R(9).xgcd(R(0,2))
|
|
1570
|
+
(O(3^2), 0, 1 + O(3^20))
|
|
1571
|
+
sage: R(9).xgcd(R(0,3))
|
|
1572
|
+
(3^2 + O(3^22), 1 + O(3^20), 0)
|
|
1573
|
+
sage: R(9).xgcd(R(0,4))
|
|
1574
|
+
(3^2 + O(3^22), 1 + O(3^20), 0)
|
|
1575
|
+
|
|
1576
|
+
Over a field, the greatest common divisor is either zero (possibly with
|
|
1577
|
+
finite precision) or one::
|
|
1578
|
+
|
|
1579
|
+
sage: K = Qp(3)
|
|
1580
|
+
sage: K(3).xgcd(0)
|
|
1581
|
+
(1 + O(3^20), 3^-1 + O(3^19), 0)
|
|
1582
|
+
sage: K.zero().xgcd(0)
|
|
1583
|
+
(0, 1 + O(3^20), 0)
|
|
1584
|
+
sage: K.zero().xgcd(K(0,2))
|
|
1585
|
+
(O(3^2), 0, 1 + O(3^20))
|
|
1586
|
+
sage: K(3).xgcd(4)
|
|
1587
|
+
(1 + O(3^20), 3^-1 + O(3^19), 0)
|
|
1588
|
+
|
|
1589
|
+
TESTS:
|
|
1590
|
+
|
|
1591
|
+
The implementation also works over extensions::
|
|
1592
|
+
|
|
1593
|
+
sage: # needs sage.libs.ntl
|
|
1594
|
+
sage: K = Qp(3)
|
|
1595
|
+
sage: R.<a> = K[]
|
|
1596
|
+
sage: L.<a> = K.extension(a^3-3)
|
|
1597
|
+
sage: (a+3).xgcd(3)
|
|
1598
|
+
(1 + O(a^60),
|
|
1599
|
+
a^-1 + 2*a + a^3 + 2*a^4 + 2*a^5 + 2*a^8 + 2*a^9
|
|
1600
|
+
+ 2*a^12 + 2*a^13 + 2*a^16 + 2*a^17 + 2*a^20 + 2*a^21 + 2*a^24
|
|
1601
|
+
+ 2*a^25 + 2*a^28 + 2*a^29 + 2*a^32 + 2*a^33 + 2*a^36 + 2*a^37
|
|
1602
|
+
+ 2*a^40 + 2*a^41 + 2*a^44 + 2*a^45 + 2*a^48 + 2*a^49 + 2*a^52
|
|
1603
|
+
+ 2*a^53 + 2*a^56 + 2*a^57 + O(a^59),
|
|
1604
|
+
0)
|
|
1605
|
+
sage: R = Zp(3)
|
|
1606
|
+
sage: S.<a> = R[]
|
|
1607
|
+
sage: S.<a> = R.extension(a^3-3)
|
|
1608
|
+
sage: (a+3).xgcd(3)
|
|
1609
|
+
(a + O(a^61),
|
|
1610
|
+
1 + 2*a^2 + a^4 + 2*a^5 + 2*a^6 + 2*a^9 + 2*a^10
|
|
1611
|
+
+ 2*a^13 + 2*a^14 + 2*a^17 + 2*a^18 + 2*a^21 + 2*a^22 + 2*a^25
|
|
1612
|
+
+ 2*a^26 + 2*a^29 + 2*a^30 + 2*a^33 + 2*a^34 + 2*a^37 + 2*a^38
|
|
1613
|
+
+ 2*a^41 + 2*a^42 + 2*a^45 + 2*a^46 + 2*a^49 + 2*a^50 + 2*a^53
|
|
1614
|
+
+ 2*a^54 + 2*a^57 + 2*a^58 + O(a^60),
|
|
1615
|
+
0)
|
|
1616
|
+
sage: K = Qp(3)
|
|
1617
|
+
sage: R.<a> = K[]
|
|
1618
|
+
sage: L.<a> = K.extension(a^2-2)
|
|
1619
|
+
sage: (a+3).xgcd(3)
|
|
1620
|
+
(1 + O(3^20),
|
|
1621
|
+
2*a + (a + 1)*3 + (2*a + 1)*3^2 + (a + 2)*3^4 + 3^5
|
|
1622
|
+
+ (2*a + 2)*3^6 + a*3^7 + (2*a + 1)*3^8 + (a + 2)*3^10 + 3^11
|
|
1623
|
+
+ (2*a + 2)*3^12 + a*3^13 + (2*a + 1)*3^14 + (a + 2)*3^16
|
|
1624
|
+
+ 3^17 + (2*a + 2)*3^18 + a*3^19 + O(3^20),
|
|
1625
|
+
0)
|
|
1626
|
+
sage: R = Zp(3)
|
|
1627
|
+
sage: S.<a> = R[]
|
|
1628
|
+
sage: S.<a> = R.extension(a^2-2)
|
|
1629
|
+
sage: (a+3).xgcd(3)
|
|
1630
|
+
(1 + O(3^20),
|
|
1631
|
+
2*a + (a + 1)*3 + (2*a + 1)*3^2 + (a + 2)*3^4 + 3^5
|
|
1632
|
+
+ (2*a + 2)*3^6 + a*3^7 + (2*a + 1)*3^8 + (a + 2)*3^10 + 3^11
|
|
1633
|
+
+ (2*a + 2)*3^12 + a*3^13 + (2*a + 1)*3^14 + (a + 2)*3^16 + 3^17
|
|
1634
|
+
+ (2*a + 2)*3^18 + a*3^19 + O(3^20),
|
|
1635
|
+
0)
|
|
1636
|
+
|
|
1637
|
+
For elements with a fixed modulus::
|
|
1638
|
+
|
|
1639
|
+
sage: R = ZpFM(3)
|
|
1640
|
+
sage: R(3).xgcd(9)
|
|
1641
|
+
(3, 1, 0)
|
|
1642
|
+
|
|
1643
|
+
And elements with a capped absolute precision::
|
|
1644
|
+
|
|
1645
|
+
sage: R = ZpCA(3)
|
|
1646
|
+
sage: R(3).xgcd(9)
|
|
1647
|
+
(3 + O(3^20), 1 + O(3^19), O(3^20))
|
|
1648
|
+
"""
|
|
1649
|
+
s,t = self.parent().zero(), self.parent().zero()
|
|
1650
|
+
if self.is_zero() and other.is_zero():
|
|
1651
|
+
if self.valuation() <= other.valuation():
|
|
1652
|
+
s = self.parent().one()
|
|
1653
|
+
else:
|
|
1654
|
+
t = self.parent().one()
|
|
1655
|
+
elif self.parent().is_field():
|
|
1656
|
+
if not self.is_zero():
|
|
1657
|
+
s = ~self
|
|
1658
|
+
else:
|
|
1659
|
+
t = ~other
|
|
1660
|
+
elif self.valuation() < other.valuation():
|
|
1661
|
+
if self.is_zero():
|
|
1662
|
+
s = self.parent().one()
|
|
1663
|
+
else:
|
|
1664
|
+
s = self.unit_part().inverse_of_unit()
|
|
1665
|
+
else:
|
|
1666
|
+
if other.is_zero():
|
|
1667
|
+
t = self.parent().one()
|
|
1668
|
+
else:
|
|
1669
|
+
t = other.unit_part().inverse_of_unit()
|
|
1670
|
+
|
|
1671
|
+
return s*self+t*other,s,t
|
|
1672
|
+
|
|
1673
|
+
def is_square(self):
|
|
1674
|
+
"""
|
|
1675
|
+
Return whether this element is a square.
|
|
1676
|
+
|
|
1677
|
+
INPUT:
|
|
1678
|
+
|
|
1679
|
+
- ``self`` -- a `p`-adic element
|
|
1680
|
+
|
|
1681
|
+
EXAMPLES::
|
|
1682
|
+
|
|
1683
|
+
sage: R = Zp(3,20,'capped-rel')
|
|
1684
|
+
sage: R(0).is_square()
|
|
1685
|
+
True
|
|
1686
|
+
sage: R(1).is_square()
|
|
1687
|
+
True
|
|
1688
|
+
sage: R(2).is_square()
|
|
1689
|
+
False
|
|
1690
|
+
|
|
1691
|
+
TESTS::
|
|
1692
|
+
|
|
1693
|
+
sage: R(3).is_square()
|
|
1694
|
+
False
|
|
1695
|
+
sage: R(4).is_square()
|
|
1696
|
+
True
|
|
1697
|
+
sage: R(6).is_square()
|
|
1698
|
+
False
|
|
1699
|
+
sage: R(9).is_square()
|
|
1700
|
+
True
|
|
1701
|
+
|
|
1702
|
+
sage: R2 = Zp(2,20,'capped-rel')
|
|
1703
|
+
sage: R2(0).is_square()
|
|
1704
|
+
True
|
|
1705
|
+
sage: R2(1).is_square()
|
|
1706
|
+
True
|
|
1707
|
+
sage: R2(2).is_square()
|
|
1708
|
+
False
|
|
1709
|
+
sage: R2(3).is_square()
|
|
1710
|
+
False
|
|
1711
|
+
sage: R2(4).is_square()
|
|
1712
|
+
True
|
|
1713
|
+
sage: R2(5).is_square()
|
|
1714
|
+
False
|
|
1715
|
+
sage: R2(6).is_square()
|
|
1716
|
+
False
|
|
1717
|
+
sage: R2(7).is_square()
|
|
1718
|
+
False
|
|
1719
|
+
sage: R2(8).is_square()
|
|
1720
|
+
False
|
|
1721
|
+
sage: R2(9).is_square()
|
|
1722
|
+
True
|
|
1723
|
+
|
|
1724
|
+
sage: K = Qp(3,20,'capped-rel')
|
|
1725
|
+
sage: K(0).is_square()
|
|
1726
|
+
True
|
|
1727
|
+
sage: K(1).is_square()
|
|
1728
|
+
True
|
|
1729
|
+
sage: K(2).is_square()
|
|
1730
|
+
False
|
|
1731
|
+
sage: K(3).is_square()
|
|
1732
|
+
False
|
|
1733
|
+
sage: K(4).is_square()
|
|
1734
|
+
True
|
|
1735
|
+
sage: K(6).is_square()
|
|
1736
|
+
False
|
|
1737
|
+
sage: K(9).is_square()
|
|
1738
|
+
True
|
|
1739
|
+
sage: K(1/3).is_square()
|
|
1740
|
+
False
|
|
1741
|
+
sage: K(1/9).is_square()
|
|
1742
|
+
True
|
|
1743
|
+
|
|
1744
|
+
sage: K2 = Qp(2,20,'capped-rel')
|
|
1745
|
+
sage: K2(0).is_square()
|
|
1746
|
+
True
|
|
1747
|
+
sage: K2(1).is_square()
|
|
1748
|
+
True
|
|
1749
|
+
sage: K2(2).is_square()
|
|
1750
|
+
False
|
|
1751
|
+
sage: K2(3).is_square()
|
|
1752
|
+
False
|
|
1753
|
+
sage: K2(4).is_square()
|
|
1754
|
+
True
|
|
1755
|
+
sage: K2(5).is_square()
|
|
1756
|
+
False
|
|
1757
|
+
sage: K2(6).is_square()
|
|
1758
|
+
False
|
|
1759
|
+
sage: K2(7).is_square()
|
|
1760
|
+
False
|
|
1761
|
+
sage: K2(8).is_square()
|
|
1762
|
+
False
|
|
1763
|
+
sage: K2(9).is_square()
|
|
1764
|
+
True
|
|
1765
|
+
sage: K2(1/2).is_square()
|
|
1766
|
+
False
|
|
1767
|
+
sage: K2(1/4).is_square()
|
|
1768
|
+
True
|
|
1769
|
+
"""
|
|
1770
|
+
if self._is_exact_zero():
|
|
1771
|
+
return True
|
|
1772
|
+
parent = self.parent()
|
|
1773
|
+
if parent.prime() != 2:
|
|
1774
|
+
if self.is_zero():
|
|
1775
|
+
raise PrecisionError("not enough precision to be sure that this element has a square root")
|
|
1776
|
+
return (self.valuation() % 2 == 0) and (self.unit_part().residue(1).is_square())
|
|
1777
|
+
else:
|
|
1778
|
+
e = parent.absolute_e()
|
|
1779
|
+
try:
|
|
1780
|
+
self.add_bigoh(self.valuation() + 2*e + 1).nth_root(2)
|
|
1781
|
+
except ValueError:
|
|
1782
|
+
return False
|
|
1783
|
+
except PrecisionError:
|
|
1784
|
+
raise PrecisionError("not enough precision to be sure that this element has a square root")
|
|
1785
|
+
return True
|
|
1786
|
+
|
|
1787
|
+
def is_squarefree(self):
|
|
1788
|
+
r"""
|
|
1789
|
+
Return whether this element is squarefree, i.e., whether there exists
|
|
1790
|
+
no non-unit `g` such that `g^2` divides this element.
|
|
1791
|
+
|
|
1792
|
+
EXAMPLES:
|
|
1793
|
+
|
|
1794
|
+
The zero element is never squarefree::
|
|
1795
|
+
|
|
1796
|
+
sage: K = Qp(2)
|
|
1797
|
+
sage: K.zero().is_squarefree()
|
|
1798
|
+
False
|
|
1799
|
+
|
|
1800
|
+
In `p`-adic rings, only elements of valuation at most 1 are
|
|
1801
|
+
squarefree::
|
|
1802
|
+
|
|
1803
|
+
sage: R = Zp(2)
|
|
1804
|
+
sage: R(1).is_squarefree()
|
|
1805
|
+
True
|
|
1806
|
+
sage: R(2).is_squarefree()
|
|
1807
|
+
True
|
|
1808
|
+
sage: R(4).is_squarefree()
|
|
1809
|
+
False
|
|
1810
|
+
|
|
1811
|
+
This works only if the precision is known sufficiently well::
|
|
1812
|
+
|
|
1813
|
+
sage: R(0,1).is_squarefree()
|
|
1814
|
+
Traceback (most recent call last):
|
|
1815
|
+
...
|
|
1816
|
+
PrecisionError: element not known to sufficient precision to decide squarefreeness
|
|
1817
|
+
sage: R(0,2).is_squarefree()
|
|
1818
|
+
False
|
|
1819
|
+
sage: R(1,1).is_squarefree()
|
|
1820
|
+
True
|
|
1821
|
+
|
|
1822
|
+
For fields we are not so strict about the precision and treat inexact
|
|
1823
|
+
zeros as the zero element::
|
|
1824
|
+
|
|
1825
|
+
K(0,0).is_squarefree()
|
|
1826
|
+
False
|
|
1827
|
+
"""
|
|
1828
|
+
if self.parent().is_field():
|
|
1829
|
+
if self.is_zero():
|
|
1830
|
+
return False
|
|
1831
|
+
return True
|
|
1832
|
+
else:
|
|
1833
|
+
v = self.valuation()
|
|
1834
|
+
if v >= 2:
|
|
1835
|
+
return False
|
|
1836
|
+
elif self.is_zero():
|
|
1837
|
+
raise PrecisionError("element not known to sufficient precision to decide squarefreeness")
|
|
1838
|
+
else:
|
|
1839
|
+
return True
|
|
1840
|
+
|
|
1841
|
+
#def log_artin_hasse(self):
|
|
1842
|
+
# raise NotImplementedError
|
|
1843
|
+
|
|
1844
|
+
def multiplicative_order(self, prec=None):
|
|
1845
|
+
r"""
|
|
1846
|
+
Return the multiplicative order of ``self``, where ``self`` is
|
|
1847
|
+
considered to be one if it is one modulo `p^{\mbox{prec}}`.
|
|
1848
|
+
|
|
1849
|
+
INPUT:
|
|
1850
|
+
|
|
1851
|
+
- ``self`` -- a `p`-adic element
|
|
1852
|
+
- ``prec`` -- integer
|
|
1853
|
+
|
|
1854
|
+
OUTPUT: integer; the multiplicative order of ``self``
|
|
1855
|
+
|
|
1856
|
+
EXAMPLES::
|
|
1857
|
+
|
|
1858
|
+
sage: K = Qp(5,20,'capped-rel')
|
|
1859
|
+
sage: K(-1).multiplicative_order(20)
|
|
1860
|
+
2
|
|
1861
|
+
sage: K(1).multiplicative_order(20)
|
|
1862
|
+
1
|
|
1863
|
+
sage: K(2).multiplicative_order(20)
|
|
1864
|
+
+Infinity
|
|
1865
|
+
sage: K(5).multiplicative_order(20)
|
|
1866
|
+
+Infinity
|
|
1867
|
+
sage: K(1/5).multiplicative_order(20)
|
|
1868
|
+
+Infinity
|
|
1869
|
+
sage: K.zeta().multiplicative_order(20)
|
|
1870
|
+
4
|
|
1871
|
+
|
|
1872
|
+
Over unramified extensions::
|
|
1873
|
+
|
|
1874
|
+
sage: # needs sage.libs.ntl
|
|
1875
|
+
sage: L1.<a> = Qq(5^3)
|
|
1876
|
+
sage: c = L1.teichmuller(a)
|
|
1877
|
+
sage: c.multiplicative_order()
|
|
1878
|
+
124
|
|
1879
|
+
sage: c^124
|
|
1880
|
+
1 + O(5^20)
|
|
1881
|
+
|
|
1882
|
+
Over totally ramified extensions::
|
|
1883
|
+
|
|
1884
|
+
sage: # needs sage.libs.ntl
|
|
1885
|
+
sage: x = polygen(ZZ, 'x')
|
|
1886
|
+
sage: L2.<pi> = Qp(5).extension(x^4 + 5*x^3 + 10*x^2 + 10*x + 5)
|
|
1887
|
+
sage: u = 1 + pi
|
|
1888
|
+
sage: u.multiplicative_order()
|
|
1889
|
+
5
|
|
1890
|
+
sage: v = L2.teichmuller(2)
|
|
1891
|
+
sage: v.multiplicative_order()
|
|
1892
|
+
4
|
|
1893
|
+
sage: (u*v).multiplicative_order()
|
|
1894
|
+
20
|
|
1895
|
+
|
|
1896
|
+
TESTS::
|
|
1897
|
+
|
|
1898
|
+
sage: R = Zp(5,20,'capped-rel')
|
|
1899
|
+
sage: R(-1).multiplicative_order(20)
|
|
1900
|
+
2
|
|
1901
|
+
sage: R(1).multiplicative_order(20)
|
|
1902
|
+
1
|
|
1903
|
+
sage: R(2).multiplicative_order(20)
|
|
1904
|
+
+Infinity
|
|
1905
|
+
sage: R(3).multiplicative_order(20)
|
|
1906
|
+
+Infinity
|
|
1907
|
+
sage: R(4).multiplicative_order(20)
|
|
1908
|
+
+Infinity
|
|
1909
|
+
sage: R(5).multiplicative_order(20)
|
|
1910
|
+
+Infinity
|
|
1911
|
+
sage: R(25).multiplicative_order(20)
|
|
1912
|
+
+Infinity
|
|
1913
|
+
sage: R.zeta().multiplicative_order(20)
|
|
1914
|
+
4
|
|
1915
|
+
"""
|
|
1916
|
+
if prec is not None:
|
|
1917
|
+
self = self.add_bigoh(prec)
|
|
1918
|
+
if self == 0 or self.valuation() != 0:
|
|
1919
|
+
return infinity
|
|
1920
|
+
parent = self.parent()
|
|
1921
|
+
p = parent.prime()
|
|
1922
|
+
|
|
1923
|
+
# Compute the multiplicative order outside p
|
|
1924
|
+
res = self.residue()
|
|
1925
|
+
order = res.multiplicative_order()
|
|
1926
|
+
self /= parent.teichmuller(self)
|
|
1927
|
+
if self == 1:
|
|
1928
|
+
return order
|
|
1929
|
+
|
|
1930
|
+
# Compute multiplicative order at p
|
|
1931
|
+
e = parent.absolute_e()
|
|
1932
|
+
if not (p-1).divides(e):
|
|
1933
|
+
return infinity
|
|
1934
|
+
n = e.valuation(p)
|
|
1935
|
+
for _ in range(n+1):
|
|
1936
|
+
order *= p
|
|
1937
|
+
self = self**p
|
|
1938
|
+
if self == 1:
|
|
1939
|
+
return order
|
|
1940
|
+
return infinity
|
|
1941
|
+
|
|
1942
|
+
def valuation(self, p=None):
|
|
1943
|
+
r"""
|
|
1944
|
+
Return the valuation of this element.
|
|
1945
|
+
|
|
1946
|
+
INPUT:
|
|
1947
|
+
|
|
1948
|
+
- ``self`` -- a `p`-adic element
|
|
1949
|
+
- ``p`` -- a prime (default: ``None``); if specified, will make sure
|
|
1950
|
+
that ``p == self.parent().prime()``
|
|
1951
|
+
|
|
1952
|
+
.. NOTE::
|
|
1953
|
+
|
|
1954
|
+
The optional argument `p` is used for consistency with the valuation
|
|
1955
|
+
methods on integers and rationals.
|
|
1956
|
+
|
|
1957
|
+
OUTPUT: integer; the valuation of ``self``
|
|
1958
|
+
|
|
1959
|
+
EXAMPLES::
|
|
1960
|
+
|
|
1961
|
+
sage: R = Zp(17, 4,'capped-rel')
|
|
1962
|
+
sage: a = R(2*17^2)
|
|
1963
|
+
sage: a.valuation()
|
|
1964
|
+
2
|
|
1965
|
+
sage: R = Zp(5, 4,'capped-rel')
|
|
1966
|
+
sage: R(0).valuation()
|
|
1967
|
+
+Infinity
|
|
1968
|
+
|
|
1969
|
+
TESTS::
|
|
1970
|
+
|
|
1971
|
+
sage: R(1).valuation()
|
|
1972
|
+
0
|
|
1973
|
+
sage: R(2).valuation()
|
|
1974
|
+
0
|
|
1975
|
+
sage: R(5).valuation()
|
|
1976
|
+
1
|
|
1977
|
+
sage: R(10).valuation()
|
|
1978
|
+
1
|
|
1979
|
+
sage: R(25).valuation()
|
|
1980
|
+
2
|
|
1981
|
+
sage: R(50).valuation()
|
|
1982
|
+
2
|
|
1983
|
+
sage: R = Qp(17, 4)
|
|
1984
|
+
sage: a = R(2*17^2)
|
|
1985
|
+
sage: a.valuation()
|
|
1986
|
+
2
|
|
1987
|
+
sage: R = Qp(5, 4)
|
|
1988
|
+
sage: R(0).valuation()
|
|
1989
|
+
+Infinity
|
|
1990
|
+
sage: R(1).valuation()
|
|
1991
|
+
0
|
|
1992
|
+
sage: R(2).valuation()
|
|
1993
|
+
0
|
|
1994
|
+
sage: R(5).valuation()
|
|
1995
|
+
1
|
|
1996
|
+
sage: R(10).valuation()
|
|
1997
|
+
1
|
|
1998
|
+
sage: R(25).valuation()
|
|
1999
|
+
2
|
|
2000
|
+
sage: R(50).valuation()
|
|
2001
|
+
2
|
|
2002
|
+
sage: R(1/2).valuation()
|
|
2003
|
+
0
|
|
2004
|
+
sage: R(1/5).valuation()
|
|
2005
|
+
-1
|
|
2006
|
+
sage: R(1/10).valuation()
|
|
2007
|
+
-1
|
|
2008
|
+
sage: R(1/25).valuation()
|
|
2009
|
+
-2
|
|
2010
|
+
sage: R(1/50).valuation()
|
|
2011
|
+
-2
|
|
2012
|
+
|
|
2013
|
+
sage: K.<a> = Qq(25) # needs sage.libs.ntl
|
|
2014
|
+
sage: K(0).valuation() # needs sage.libs.ntl
|
|
2015
|
+
+Infinity
|
|
2016
|
+
|
|
2017
|
+
sage: R(1/50).valuation(5)
|
|
2018
|
+
-2
|
|
2019
|
+
sage: R(1/50).valuation(3)
|
|
2020
|
+
Traceback (most recent call last):
|
|
2021
|
+
...
|
|
2022
|
+
ValueError: Ring (5-adic Field with capped relative precision 4) residue field of the wrong characteristic.
|
|
2023
|
+
"""
|
|
2024
|
+
if p is not None and p != self.parent().prime():
|
|
2025
|
+
raise ValueError('Ring (%s) residue field of the wrong characteristic.' % self.parent())
|
|
2026
|
+
cdef long v = self.valuation_c()
|
|
2027
|
+
if v == maxordp:
|
|
2028
|
+
return infinity
|
|
2029
|
+
if v == -maxordp:
|
|
2030
|
+
return -infinity
|
|
2031
|
+
cdef Integer ans = PY_NEW(Integer)
|
|
2032
|
+
mpz_set_si(ans.value, v)
|
|
2033
|
+
return ans
|
|
2034
|
+
|
|
2035
|
+
cdef long valuation_c(self) noexcept:
|
|
2036
|
+
"""
|
|
2037
|
+
This function is overridden in subclasses to provide an
|
|
2038
|
+
actual implementation of valuation.
|
|
2039
|
+
|
|
2040
|
+
For exact zeros, ``maxordp`` is returned, rather than infinity.
|
|
2041
|
+
|
|
2042
|
+
EXAMPLES:
|
|
2043
|
+
|
|
2044
|
+
For example, the valuation function on pAdicCappedRelativeElements
|
|
2045
|
+
uses an overridden version of this function.
|
|
2046
|
+
|
|
2047
|
+
::
|
|
2048
|
+
|
|
2049
|
+
sage: Zp(5)(5).valuation() # indirect doctest
|
|
2050
|
+
1
|
|
2051
|
+
"""
|
|
2052
|
+
raise NotImplementedError
|
|
2053
|
+
|
|
2054
|
+
cpdef val_unit(self):
|
|
2055
|
+
r"""
|
|
2056
|
+
Return ``(self.valuation(), self.unit_part())``. To be overridden in
|
|
2057
|
+
derived classes.
|
|
2058
|
+
|
|
2059
|
+
EXAMPLES::
|
|
2060
|
+
|
|
2061
|
+
sage: Zp(5,5)(5).val_unit()
|
|
2062
|
+
(1, 1 + O(5^5))
|
|
2063
|
+
"""
|
|
2064
|
+
raise NotImplementedError
|
|
2065
|
+
|
|
2066
|
+
def ordp(self, p=None):
|
|
2067
|
+
r"""
|
|
2068
|
+
Return the valuation of ``self``, normalized so that the valuation of `p` is 1.
|
|
2069
|
+
|
|
2070
|
+
INPUT:
|
|
2071
|
+
|
|
2072
|
+
- ``self`` -- a `p`-adic element
|
|
2073
|
+
- ``p`` -- a prime (default: ``None``); if specified, will make sure
|
|
2074
|
+
that ``p == self.parent().prime()``
|
|
2075
|
+
|
|
2076
|
+
.. NOTE::
|
|
2077
|
+
|
|
2078
|
+
The optional argument `p` is used for consistency with the valuation
|
|
2079
|
+
methods on integers and rationals.
|
|
2080
|
+
|
|
2081
|
+
OUTPUT:
|
|
2082
|
+
|
|
2083
|
+
integer -- the valuation of ``self``, normalized so that the valuation of `p` is 1
|
|
2084
|
+
|
|
2085
|
+
EXAMPLES::
|
|
2086
|
+
|
|
2087
|
+
sage: R = Zp(5,20,'capped-rel')
|
|
2088
|
+
sage: R(0).ordp()
|
|
2089
|
+
+Infinity
|
|
2090
|
+
sage: R(1).ordp()
|
|
2091
|
+
0
|
|
2092
|
+
sage: R(2).ordp()
|
|
2093
|
+
0
|
|
2094
|
+
sage: R(5).ordp()
|
|
2095
|
+
1
|
|
2096
|
+
sage: R(10).ordp()
|
|
2097
|
+
1
|
|
2098
|
+
sage: R(25).ordp()
|
|
2099
|
+
2
|
|
2100
|
+
sage: R(50).ordp()
|
|
2101
|
+
2
|
|
2102
|
+
sage: R(1/2).ordp()
|
|
2103
|
+
0
|
|
2104
|
+
"""
|
|
2105
|
+
return self.valuation(p) / self.parent().absolute_e()
|
|
2106
|
+
|
|
2107
|
+
def is_prime(self):
|
|
2108
|
+
"""
|
|
2109
|
+
Return whether this element is prime in its parent.
|
|
2110
|
+
|
|
2111
|
+
EXAMPLES::
|
|
2112
|
+
|
|
2113
|
+
sage: A = Zp(2)
|
|
2114
|
+
sage: A(1).is_prime()
|
|
2115
|
+
False
|
|
2116
|
+
sage: A(2).is_prime()
|
|
2117
|
+
True
|
|
2118
|
+
|
|
2119
|
+
sage: K = A.fraction_field()
|
|
2120
|
+
sage: K(2).is_prime()
|
|
2121
|
+
False
|
|
2122
|
+
|
|
2123
|
+
::
|
|
2124
|
+
|
|
2125
|
+
sage: # needs sage.libs.ntl
|
|
2126
|
+
sage: x = polygen(ZZ, 'x')
|
|
2127
|
+
sage: B.<pi> = A.extension(x^5 - 2)
|
|
2128
|
+
sage: pi.is_prime() # needs sage.symbolic
|
|
2129
|
+
True
|
|
2130
|
+
sage: B(2).is_prime()
|
|
2131
|
+
False
|
|
2132
|
+
"""
|
|
2133
|
+
if self.is_zero():
|
|
2134
|
+
return True
|
|
2135
|
+
if self.parent().is_field():
|
|
2136
|
+
return False
|
|
2137
|
+
return self.valuation() == 1
|
|
2138
|
+
|
|
2139
|
+
def rational_reconstruction(self):
|
|
2140
|
+
r"""
|
|
2141
|
+
Return a rational approximation to this `p`-adic number.
|
|
2142
|
+
|
|
2143
|
+
This will raise an :exc:`ArithmeticError` if there are no valid
|
|
2144
|
+
approximations to the unit part with numerator and
|
|
2145
|
+
denominator bounded by ``sqrt(p^absprec / 2)``.
|
|
2146
|
+
|
|
2147
|
+
.. SEEALSO::
|
|
2148
|
+
|
|
2149
|
+
:meth:`_rational_`
|
|
2150
|
+
|
|
2151
|
+
OUTPUT: rational; an approximation to ``self``
|
|
2152
|
+
|
|
2153
|
+
EXAMPLES::
|
|
2154
|
+
|
|
2155
|
+
sage: R = Zp(5,20,'capped-rel')
|
|
2156
|
+
sage: for i in range(11):
|
|
2157
|
+
....: for j in range(1,10):
|
|
2158
|
+
....: if j == 5:
|
|
2159
|
+
....: continue
|
|
2160
|
+
....: assert i/j == R(i/j).rational_reconstruction()
|
|
2161
|
+
"""
|
|
2162
|
+
if self.is_zero(self.precision_absolute()):
|
|
2163
|
+
return Rational(0)
|
|
2164
|
+
p = self.parent().prime()
|
|
2165
|
+
alpha = self.unit_part().lift()
|
|
2166
|
+
m = Integer(p**self.precision_relative())
|
|
2167
|
+
from sage.arith.misc import rational_reconstruction
|
|
2168
|
+
r = rational_reconstruction(alpha, m)
|
|
2169
|
+
return (Rational(p)**self.valuation())*r
|
|
2170
|
+
|
|
2171
|
+
def _rational_(self):
|
|
2172
|
+
r"""
|
|
2173
|
+
Return a rational approximation to this `p`-adic number.
|
|
2174
|
+
|
|
2175
|
+
If there is no good rational approximation to the unit part,
|
|
2176
|
+
will just return the integer approximation.
|
|
2177
|
+
|
|
2178
|
+
EXAMPLES::
|
|
2179
|
+
|
|
2180
|
+
sage: R = Zp(7,5)
|
|
2181
|
+
sage: QQ(R(125)) # indirect doctest
|
|
2182
|
+
125
|
|
2183
|
+
"""
|
|
2184
|
+
try:
|
|
2185
|
+
return self.rational_reconstruction()
|
|
2186
|
+
except ArithmeticError:
|
|
2187
|
+
p = self.parent().prime()
|
|
2188
|
+
return Rational(p**self.valuation() * self.unit_part().lift())
|
|
2189
|
+
|
|
2190
|
+
def _number_field_(self, K):
|
|
2191
|
+
r"""
|
|
2192
|
+
Return an element of `K` approximating this `p`-adic number.
|
|
2193
|
+
|
|
2194
|
+
INPUT:
|
|
2195
|
+
|
|
2196
|
+
- ``K`` -- a number field
|
|
2197
|
+
|
|
2198
|
+
EXAMPLES::
|
|
2199
|
+
|
|
2200
|
+
sage: R.<a> = Zq(125) # needs sage.libs.ntl
|
|
2201
|
+
sage: K = R.exact_field() # needs sage.libs.ntl
|
|
2202
|
+
sage: a._number_field_(K) # needs sage.libs.ntl
|
|
2203
|
+
a
|
|
2204
|
+
"""
|
|
2205
|
+
Kbase = K.base_ring()
|
|
2206
|
+
if K.defining_polynomial() != self.parent().defining_polynomial(exact=True):
|
|
2207
|
+
# Might convert to K's base ring.
|
|
2208
|
+
return Kbase(self)
|
|
2209
|
+
L = [Kbase(c) for c in self.polynomial().list()]
|
|
2210
|
+
if len(L) < K.relative_degree():
|
|
2211
|
+
L += [Kbase(0)] * (K.relative_degree() - len(L))
|
|
2212
|
+
return K(L)
|
|
2213
|
+
|
|
2214
|
+
def _im_gens_(self, codomain, im_gens, base_map=None):
|
|
2215
|
+
"""
|
|
2216
|
+
Return the image of this element under the morphism defined by
|
|
2217
|
+
``im_gens`` in ``codomain``, where elements of the
|
|
2218
|
+
base ring are mapped by ``base_map``.
|
|
2219
|
+
|
|
2220
|
+
EXAMPLES::
|
|
2221
|
+
|
|
2222
|
+
sage: # needs sage.libs.ntl
|
|
2223
|
+
sage: R.<x> = ZZ[]
|
|
2224
|
+
sage: K.<a> = Qq(25, modulus=x^2-2)
|
|
2225
|
+
sage: L.<b> = Qq(625, modulus=x^4-2)
|
|
2226
|
+
sage: phi = K.hom([b^2]); phi(a+1)
|
|
2227
|
+
(b^2 + 1) + O(5^20)
|
|
2228
|
+
sage: z = L(-1).sqrt()
|
|
2229
|
+
sage: psi = L.hom([z*b]); psi(phi(a) + 5*b) == psi(phi(a)) + 5*psi(b)
|
|
2230
|
+
True
|
|
2231
|
+
sage: z = (1+5*b).log()
|
|
2232
|
+
sage: w = (5 - 5*b).exp()
|
|
2233
|
+
sage: psi(z*w) == psi(z) * psi(w)
|
|
2234
|
+
True
|
|
2235
|
+
|
|
2236
|
+
sage: # needs sage.libs.ntl
|
|
2237
|
+
sage: P.<pi> = K.extension(x^2 - 5)
|
|
2238
|
+
sage: cc = K.hom([-a])
|
|
2239
|
+
sage: alpha = P.hom([pi], base_map=cc); alpha(a) + a
|
|
2240
|
+
O(pi^40)
|
|
2241
|
+
sage: zz = (1 + a*pi).log()
|
|
2242
|
+
sage: ww = pi.exp() # needs sage.symbolic
|
|
2243
|
+
sage: beta = P.hom([-pi], base_map=cc)
|
|
2244
|
+
sage: beta(ww*zz) == beta(ww)*beta(zz) # needs sage.symbolic
|
|
2245
|
+
True
|
|
2246
|
+
"""
|
|
2247
|
+
L = self.parent()
|
|
2248
|
+
K = L.base_ring()
|
|
2249
|
+
if L is K:
|
|
2250
|
+
# Qp or Zp, so there is a unique map
|
|
2251
|
+
if base_map is None:
|
|
2252
|
+
return codomain.coerce(self)
|
|
2253
|
+
else:
|
|
2254
|
+
return base_map(self)
|
|
2255
|
+
f = self.polynomial()
|
|
2256
|
+
if base_map is not None:
|
|
2257
|
+
f = f.change_ring(base_map)
|
|
2258
|
+
return f(im_gens[0])
|
|
2259
|
+
|
|
2260
|
+
def _log_generic(self, aprec, mina=0):
|
|
2261
|
+
r"""
|
|
2262
|
+
Return ``\log(self)`` for ``self`` equal to 1 in the residue field.
|
|
2263
|
+
|
|
2264
|
+
This is a helper method for :meth:`log`.
|
|
2265
|
+
|
|
2266
|
+
INPUT:
|
|
2267
|
+
|
|
2268
|
+
- ``aprec`` -- integer; the precision to which the result is
|
|
2269
|
+
correct. ``aprec`` must not exceed the precision cap of the ring over
|
|
2270
|
+
which this element is defined.
|
|
2271
|
+
|
|
2272
|
+
- ``mina`` -- integer (default: 0); the series will check `n` up to
|
|
2273
|
+
this valuation (and beyond) to see if they can contribute to the
|
|
2274
|
+
series
|
|
2275
|
+
|
|
2276
|
+
ALGORITHM:
|
|
2277
|
+
|
|
2278
|
+
The computation uses the series
|
|
2279
|
+
|
|
2280
|
+
.. MATH::
|
|
2281
|
+
|
|
2282
|
+
-\log(1-x)=\sum_{n=1}^\infty \frac{x^n}{n}.
|
|
2283
|
+
|
|
2284
|
+
For the result to be correct to precision ``aprec``, we sum all terms
|
|
2285
|
+
for which the valuation of `x^n/n` is strictly smaller than ``aprec``.
|
|
2286
|
+
|
|
2287
|
+
EXAMPLES::
|
|
2288
|
+
|
|
2289
|
+
sage: r = Qp(5,prec=4)(6)
|
|
2290
|
+
sage: r._log_generic(2)
|
|
2291
|
+
5 + O(5^2)
|
|
2292
|
+
sage: r._log_generic(4)
|
|
2293
|
+
5 + 2*5^2 + 4*5^3 + O(5^4)
|
|
2294
|
+
sage: r._log_generic(100)
|
|
2295
|
+
5 + 2*5^2 + 4*5^3 + O(5^4)
|
|
2296
|
+
|
|
2297
|
+
sage: r = Zp(5,prec=4,type='fixed-mod')(6)
|
|
2298
|
+
sage: r._log_generic(5)
|
|
2299
|
+
5 + 2*5^2 + 4*5^3
|
|
2300
|
+
|
|
2301
|
+
Only implemented for elements congruent to 1 modulo the maximal ideal::
|
|
2302
|
+
|
|
2303
|
+
sage: r = Zp(5,prec=4,type='fixed-mod')(2)
|
|
2304
|
+
sage: r._log_generic(5)
|
|
2305
|
+
Traceback (most recent call last):
|
|
2306
|
+
...
|
|
2307
|
+
ValueError: Input value (=2) must be 1 in the residue field
|
|
2308
|
+
"""
|
|
2309
|
+
x = 1-self
|
|
2310
|
+
R = self.parent()
|
|
2311
|
+
# to get the precision right over capped-absolute rings, we have to
|
|
2312
|
+
# work over the capped-relative fraction field
|
|
2313
|
+
if R.is_capped_absolute():
|
|
2314
|
+
R = R.fraction_field()
|
|
2315
|
+
x = R(x)
|
|
2316
|
+
|
|
2317
|
+
alpha=x.valuation()
|
|
2318
|
+
if alpha<=0:
|
|
2319
|
+
raise ValueError('Input value (=%s) must be 1 in the residue field' % self)
|
|
2320
|
+
|
|
2321
|
+
e=R.absolute_e()
|
|
2322
|
+
p=R.prime()
|
|
2323
|
+
|
|
2324
|
+
# we sum all terms of the power series of log into total
|
|
2325
|
+
total=R.zero()
|
|
2326
|
+
|
|
2327
|
+
# pre-compute x^p/p into x2p_p
|
|
2328
|
+
if mina == 0 and alpha*p - e > aprec:
|
|
2329
|
+
# The value of x^p/p is not needed in that case
|
|
2330
|
+
x2p_p = R(0)
|
|
2331
|
+
elif R.is_capped_relative():
|
|
2332
|
+
if p*alpha >= e:
|
|
2333
|
+
x2p_p = x**p/p
|
|
2334
|
+
else:
|
|
2335
|
+
# x^p/p has negative valuation, so we need to be much
|
|
2336
|
+
# more careful about precision.
|
|
2337
|
+
x = x.lift_to_precision()
|
|
2338
|
+
x2p_p = x**p/p
|
|
2339
|
+
else:
|
|
2340
|
+
xu=x.unit_part()
|
|
2341
|
+
pu=R(p).unit_part()
|
|
2342
|
+
x2p_p=((xu**p)*pu.inverse_of_unit())*R.uniformizer_pow(p*alpha-e)
|
|
2343
|
+
|
|
2344
|
+
# To get result right to precision aprec, we need all terms for which
|
|
2345
|
+
# the valuation of x^n/n is strictly smaller than aprec.
|
|
2346
|
+
# If we rewrite n=u*p^a with u a p-adic unit, then these are the terms
|
|
2347
|
+
# for which u<(aprec+a*v(p))/(v(x)*p^a).
|
|
2348
|
+
# Two sum over these terms, we run two nested loops, the outer one
|
|
2349
|
+
# iterates over the possible values for a, the inner one iterates over
|
|
2350
|
+
# the possible values for u.
|
|
2351
|
+
upper_u = (aprec/alpha).floor()
|
|
2352
|
+
if mina > 0 or upper_u > 0:
|
|
2353
|
+
a=0
|
|
2354
|
+
p2a=1 # p^a
|
|
2355
|
+
x2pa = x # x^(p^a)
|
|
2356
|
+
|
|
2357
|
+
# In the unramified case, we can stop summing terms as soon as
|
|
2358
|
+
# there are no u for a given a to sum over. In the ramified case,
|
|
2359
|
+
# it can happen that for some initial a there are no such u but
|
|
2360
|
+
# later in the series there are such u again. mina can be set to
|
|
2361
|
+
# take care of this by summing at least to a=mina-1
|
|
2362
|
+
while True:
|
|
2363
|
+
# we compute the sum for the possible values for u using Horner's method
|
|
2364
|
+
inner_sum = R.zero()
|
|
2365
|
+
for u in range(upper_u,0,-1):
|
|
2366
|
+
# We want u to be a p-adic unit
|
|
2367
|
+
if u % p == 0:
|
|
2368
|
+
new_term = R.zero()
|
|
2369
|
+
else:
|
|
2370
|
+
new_term = ~R(u)
|
|
2371
|
+
|
|
2372
|
+
# This hack is to deal with rings that don't lift to fields
|
|
2373
|
+
if u > 1 or x2p_p.is_zero():
|
|
2374
|
+
inner_sum = (inner_sum+new_term)*x2pa
|
|
2375
|
+
else:
|
|
2376
|
+
inner_sum = (inner_sum+new_term)*(x2p_p**a)*(x**(p2a-a*p))
|
|
2377
|
+
|
|
2378
|
+
total -= inner_sum
|
|
2379
|
+
|
|
2380
|
+
# Now increase a and check if a new iteration of the loop is needed
|
|
2381
|
+
a += 1
|
|
2382
|
+
p2a = p2a*p
|
|
2383
|
+
upper_u = ((aprec+a*e)/(alpha*p2a)).floor()
|
|
2384
|
+
if a >= mina and upper_u <= 0: break
|
|
2385
|
+
|
|
2386
|
+
# We perform this last operation after the test
|
|
2387
|
+
# because it is costly and may raise OverflowError
|
|
2388
|
+
x2pa = x2pa**p
|
|
2389
|
+
|
|
2390
|
+
return total.add_bigoh(aprec)
|
|
2391
|
+
|
|
2392
|
+
def _log_binary_splitting(self, aprec, mina=0):
|
|
2393
|
+
r"""
|
|
2394
|
+
Return ``\log(self)`` for ``self`` equal to 1 in the residue field.
|
|
2395
|
+
|
|
2396
|
+
This is a helper method for :meth:`log`.
|
|
2397
|
+
It uses a fast binary splitting algorithm.
|
|
2398
|
+
|
|
2399
|
+
INPUT:
|
|
2400
|
+
|
|
2401
|
+
- ``aprec`` -- integer; the precision to which the result is
|
|
2402
|
+
correct. ``aprec`` must not exceed the precision cap of the ring over
|
|
2403
|
+
which this element is defined.
|
|
2404
|
+
|
|
2405
|
+
- ``mina`` -- integer (default: 0); the series will check `n` up to
|
|
2406
|
+
this valuation (and beyond) to see if they can contribute to the
|
|
2407
|
+
series
|
|
2408
|
+
|
|
2409
|
+
.. NOTE::
|
|
2410
|
+
|
|
2411
|
+
The function does not check that its argument ``self`` is
|
|
2412
|
+
1 in the residue field. If this assumption is not fulfilled
|
|
2413
|
+
the behaviour of the function is not specified.
|
|
2414
|
+
|
|
2415
|
+
ALGORITHM:
|
|
2416
|
+
|
|
2417
|
+
1. Raise `u` to the power `p^v` for a suitable `v` in order
|
|
2418
|
+
to make it closer to 1. (`v` is chosen such that `p^v` is
|
|
2419
|
+
close to the precision.)
|
|
2420
|
+
|
|
2421
|
+
2. Write
|
|
2422
|
+
|
|
2423
|
+
.. MATH::
|
|
2424
|
+
|
|
2425
|
+
u^{p-1} = \prod_{i=1}^\infty (1 - a_i p^{(v+1)*2^i})
|
|
2426
|
+
|
|
2427
|
+
with `0 \leq a_i < p^{(v+1)*2^i}` and compute
|
|
2428
|
+
`\log(1 - a_i p^{(v+1)*2^i})` using the standard Taylor expansion
|
|
2429
|
+
|
|
2430
|
+
.. MATH::
|
|
2431
|
+
|
|
2432
|
+
\log(1 - x) = -x - 1/2 x^2 - 1/3 x^3 - 1/4 x^4 - 1/5 x^5 - \cdots
|
|
2433
|
+
|
|
2434
|
+
together with a binary splitting method.
|
|
2435
|
+
|
|
2436
|
+
3. Divide the result by `p^v`
|
|
2437
|
+
|
|
2438
|
+
The complexity of this algorithm is quasi-linear.
|
|
2439
|
+
|
|
2440
|
+
EXAMPLES::
|
|
2441
|
+
|
|
2442
|
+
sage: r = Qp(5,prec=4)(6)
|
|
2443
|
+
sage: r._log_binary_splitting(2)
|
|
2444
|
+
5 + O(5^2)
|
|
2445
|
+
sage: r._log_binary_splitting(4)
|
|
2446
|
+
5 + 2*5^2 + 4*5^3 + O(5^4)
|
|
2447
|
+
sage: r._log_binary_splitting(100)
|
|
2448
|
+
5 + 2*5^2 + 4*5^3 + O(5^4)
|
|
2449
|
+
|
|
2450
|
+
sage: r = Zp(5,prec=4,type='fixed-mod')(6)
|
|
2451
|
+
sage: r._log_binary_splitting(5)
|
|
2452
|
+
5 + 2*5^2 + 4*5^3
|
|
2453
|
+
"""
|
|
2454
|
+
raise NotImplementedError
|
|
2455
|
+
|
|
2456
|
+
def log(self, p_branch=None, pi_branch=None, aprec=None, change_frac=False, algorithm=None):
|
|
2457
|
+
r"""
|
|
2458
|
+
Compute the `p`-adic logarithm of this element.
|
|
2459
|
+
|
|
2460
|
+
The usual power series for the logarithm with values in the additive
|
|
2461
|
+
group of a `p`-adic ring only converges for 1-units (units congruent to
|
|
2462
|
+
1 modulo `p`). However, there is a unique extension of the logarithm
|
|
2463
|
+
to a homomorphism defined on all the units: If `u = a \cdot v` is a
|
|
2464
|
+
unit with `v \equiv 1 \pmod{p}` and `a` a Teichmuller representative,
|
|
2465
|
+
then we define `log(u) = log(v)`. This is the correct extension
|
|
2466
|
+
because the units `U` split as a product `U = V \times \langle w
|
|
2467
|
+
\rangle`, where `V` is the subgroup of 1-units and `w` is a fundamental
|
|
2468
|
+
root of unity. The `\langle w \rangle` factor is torsion, so must go
|
|
2469
|
+
to 0 under any homomorphism to the fraction field, which is a torsion
|
|
2470
|
+
free group.
|
|
2471
|
+
|
|
2472
|
+
INPUT:
|
|
2473
|
+
|
|
2474
|
+
- ``p_branch`` -- an element in the base ring or its fraction
|
|
2475
|
+
field; the implementation will choose the branch of the
|
|
2476
|
+
logarithm which sends `p` to ``branch``
|
|
2477
|
+
|
|
2478
|
+
- ``pi_branch`` -- an element in the base ring or its fraction
|
|
2479
|
+
field; the implementation will choose the branch of the
|
|
2480
|
+
logarithm which sends the uniformizer to ``branch``; you
|
|
2481
|
+
may specify at most one of ``p_branch`` and ``pi_branch``,
|
|
2482
|
+
and must specify one of them if this element is not a unit
|
|
2483
|
+
|
|
2484
|
+
- ``aprec`` -- integer or ``None`` (default: ``None``); if not
|
|
2485
|
+
``None``, then the result will only be correct to precision
|
|
2486
|
+
``aprec``
|
|
2487
|
+
|
|
2488
|
+
- ``change_frac`` -- in general the codomain of the logarithm should be
|
|
2489
|
+
in the `p`-adic field, however, for most neighborhoods of 1, it lies
|
|
2490
|
+
in the ring of integers. This flag decides if the codomain should be
|
|
2491
|
+
the same as the input (default) or if it should change to the
|
|
2492
|
+
fraction field of the input.
|
|
2493
|
+
|
|
2494
|
+
- ``algorithm`` -- ``'generic'``, ``'binary_splitting'`` or ``None`` (default)
|
|
2495
|
+
The generic algorithm evaluates naively the series defining the log,
|
|
2496
|
+
namely
|
|
2497
|
+
|
|
2498
|
+
.. MATH::
|
|
2499
|
+
|
|
2500
|
+
\log(1-x) = -x - 1/2 x^2 - 1/3 x^3 - 1/4 x^4 - 1/5 x^5 - \cdots.
|
|
2501
|
+
|
|
2502
|
+
Its binary complexity is quadratic with respect to the precision.
|
|
2503
|
+
|
|
2504
|
+
The ``'binary_splitting'`` algorithm is faster, it has a quasi-linear
|
|
2505
|
+
complexity.
|
|
2506
|
+
By default, we use ``'binary_splitting'`` if it is available. Otherwise
|
|
2507
|
+
we switch to the ``'generic'`` algorithm.
|
|
2508
|
+
|
|
2509
|
+
.. NOTE::
|
|
2510
|
+
|
|
2511
|
+
What some other systems do:
|
|
2512
|
+
|
|
2513
|
+
- PARI: Seems to define the logarithm for units not congruent
|
|
2514
|
+
to 1 as we do.
|
|
2515
|
+
|
|
2516
|
+
- MAGMA: Only implements logarithm for 1-units (version 2.19-2)
|
|
2517
|
+
|
|
2518
|
+
.. TODO::
|
|
2519
|
+
|
|
2520
|
+
There is a soft-linear time algorithm for logarithm described
|
|
2521
|
+
by Dan Bernstein at
|
|
2522
|
+
http://cr.yp.to/lineartime/multapps-20041007.pdf
|
|
2523
|
+
|
|
2524
|
+
EXAMPLES::
|
|
2525
|
+
|
|
2526
|
+
sage: Z13 = Zp(13, 10)
|
|
2527
|
+
sage: a = Z13(14); a
|
|
2528
|
+
1 + 13 + O(13^10)
|
|
2529
|
+
sage: a.log()
|
|
2530
|
+
13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10)
|
|
2531
|
+
|
|
2532
|
+
sage: Q13 = Qp(13, 10)
|
|
2533
|
+
sage: a = Q13(14); a
|
|
2534
|
+
1 + 13 + O(13^10)
|
|
2535
|
+
sage: a.log()
|
|
2536
|
+
13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10)
|
|
2537
|
+
|
|
2538
|
+
Note that the relative precision decreases when we take log.
|
|
2539
|
+
Precisely the absolute precision on ``log(a)`` agrees with the relative
|
|
2540
|
+
precision on ``a`` thanks to the relation `d\log(a) = da/a`.
|
|
2541
|
+
|
|
2542
|
+
The call ``log(a)`` works as well::
|
|
2543
|
+
|
|
2544
|
+
sage: log(a)
|
|
2545
|
+
13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10)
|
|
2546
|
+
sage: log(a) == a.log()
|
|
2547
|
+
True
|
|
2548
|
+
|
|
2549
|
+
The logarithm is not only defined for 1-units::
|
|
2550
|
+
|
|
2551
|
+
sage: R = Zp(5,10)
|
|
2552
|
+
sage: a = R(2)
|
|
2553
|
+
sage: a.log()
|
|
2554
|
+
2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
|
|
2555
|
+
|
|
2556
|
+
If you want to take the logarithm of a non-unit you must specify either
|
|
2557
|
+
``p_branch`` or ``pi_branch``::
|
|
2558
|
+
|
|
2559
|
+
sage: b = R(5)
|
|
2560
|
+
sage: b.log()
|
|
2561
|
+
Traceback (most recent call last):
|
|
2562
|
+
...
|
|
2563
|
+
ValueError: you must specify a branch of the logarithm for non-units
|
|
2564
|
+
sage: b.log(p_branch=4)
|
|
2565
|
+
4 + O(5^10)
|
|
2566
|
+
sage: c = R(10)
|
|
2567
|
+
sage: c.log(p_branch=4)
|
|
2568
|
+
4 + 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
|
|
2569
|
+
|
|
2570
|
+
The branch parameters are only relevant for elements of nonzero
|
|
2571
|
+
valuation::
|
|
2572
|
+
|
|
2573
|
+
sage: a.log(p_branch=0)
|
|
2574
|
+
2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
|
|
2575
|
+
sage: a.log(p_branch=1)
|
|
2576
|
+
2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
|
|
2577
|
+
|
|
2578
|
+
Logarithms can also be computed in extension fields. First, in an
|
|
2579
|
+
Eisenstein extension::
|
|
2580
|
+
|
|
2581
|
+
sage: R = Zp(5,5)
|
|
2582
|
+
sage: S.<x> = ZZ[]
|
|
2583
|
+
sage: f = x^4 + 15*x^2 + 625*x - 5
|
|
2584
|
+
sage: W.<w> = R.ext(f) # needs sage.libs.ntl
|
|
2585
|
+
sage: z = 1 + w^2 + 4*w^7; z # needs sage.libs.ntl
|
|
2586
|
+
1 + w^2 + 4*w^7 + O(w^20)
|
|
2587
|
+
sage: z.log() # needs sage.libs.ntl
|
|
2588
|
+
w^2 + 2*w^4 + 3*w^6 + 4*w^7 + w^9 + 4*w^10 + 4*w^11 + 4*w^12
|
|
2589
|
+
+ 3*w^14 + w^15 + w^17 + 3*w^18 + 3*w^19 + O(w^20)
|
|
2590
|
+
|
|
2591
|
+
In an extension, there will usually be a difference between
|
|
2592
|
+
specifying ``p_branch`` and ``pi_branch``::
|
|
2593
|
+
|
|
2594
|
+
sage: # needs sage.libs.ntl
|
|
2595
|
+
sage: b = W(5)
|
|
2596
|
+
sage: b.log()
|
|
2597
|
+
Traceback (most recent call last):
|
|
2598
|
+
...
|
|
2599
|
+
ValueError: you must specify a branch of the logarithm for non-units
|
|
2600
|
+
sage: b.log(p_branch=0)
|
|
2601
|
+
O(w^20)
|
|
2602
|
+
sage: b.log(p_branch=w)
|
|
2603
|
+
w + O(w^20)
|
|
2604
|
+
sage: b.log(pi_branch=0)
|
|
2605
|
+
3*w^2 + 2*w^4 + 2*w^6 + 3*w^8 + 4*w^10 + w^13 + w^14 + 2*w^15
|
|
2606
|
+
+ 2*w^16 + w^18 + 4*w^19 + O(w^20)
|
|
2607
|
+
sage: b.unit_part().log()
|
|
2608
|
+
3*w^2 + 2*w^4 + 2*w^6 + 3*w^8 + 4*w^10 + w^13 + w^14 + 2*w^15
|
|
2609
|
+
+ 2*w^16 + w^18 + 4*w^19 + O(w^20)
|
|
2610
|
+
sage: y = w^2 * 4*w^7; y
|
|
2611
|
+
4*w^9 + O(w^29)
|
|
2612
|
+
sage: y.log(p_branch=0)
|
|
2613
|
+
2*w^2 + 2*w^4 + 2*w^6 + 2*w^8 + w^10 + w^12 + 4*w^13 + 4*w^14 + 3*w^15
|
|
2614
|
+
+ 4*w^16 + 4*w^17 + w^18 + 4*w^19 + O(w^20)
|
|
2615
|
+
sage: y.log(p_branch=w)
|
|
2616
|
+
w + 2*w^2 + 2*w^4 + 4*w^5 + 2*w^6 + 2*w^7 + 2*w^8 + 4*w^9 + w^10
|
|
2617
|
+
+ 3*w^11 + w^12 + 4*w^14 + 4*w^16 + 2*w^17 + w^19 + O(w^20)
|
|
2618
|
+
|
|
2619
|
+
Check that log is multiplicative::
|
|
2620
|
+
|
|
2621
|
+
sage: y.log(p_branch=0) + z.log() - (y*z).log(p_branch=0) # needs sage.libs.ntl
|
|
2622
|
+
O(w^20)
|
|
2623
|
+
|
|
2624
|
+
Now an unramified example::
|
|
2625
|
+
|
|
2626
|
+
sage: # needs sage.libs.ntl
|
|
2627
|
+
sage: g = x^3 + 3*x + 3
|
|
2628
|
+
sage: A.<a> = R.ext(g)
|
|
2629
|
+
sage: b = 1 + 5*(1 + a^2) + 5^3*(3 + 2*a)
|
|
2630
|
+
sage: b.log()
|
|
2631
|
+
(a^2 + 1)*5 + (3*a^2 + 4*a + 2)*5^2 + (3*a^2 + 2*a)*5^3
|
|
2632
|
+
+ (3*a^2 + 2*a + 2)*5^4 + O(5^5)
|
|
2633
|
+
|
|
2634
|
+
Check that log is multiplicative::
|
|
2635
|
+
|
|
2636
|
+
sage: # needs sage.libs.ntl
|
|
2637
|
+
sage: c = 3 + 5^2*(2 + 4*a)
|
|
2638
|
+
sage: b.log() + c.log() - (b*c).log()
|
|
2639
|
+
O(5^5)
|
|
2640
|
+
|
|
2641
|
+
We illustrate the effect of the ``precision`` argument::
|
|
2642
|
+
|
|
2643
|
+
sage: R = ZpCA(7,10)
|
|
2644
|
+
sage: x = R(41152263); x
|
|
2645
|
+
5 + 3*7^2 + 4*7^3 + 3*7^4 + 5*7^5 + 6*7^6 + 7^9 + O(7^10)
|
|
2646
|
+
sage: x.log(aprec = 5)
|
|
2647
|
+
7 + 3*7^2 + 4*7^3 + 3*7^4 + O(7^5)
|
|
2648
|
+
sage: x.log(aprec = 7)
|
|
2649
|
+
7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + O(7^7)
|
|
2650
|
+
sage: x.log()
|
|
2651
|
+
7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + 7^7 + 3*7^8 + 4*7^9 + O(7^10)
|
|
2652
|
+
|
|
2653
|
+
The logarithm is not defined for zero::
|
|
2654
|
+
|
|
2655
|
+
sage: R.zero().log()
|
|
2656
|
+
Traceback (most recent call last):
|
|
2657
|
+
...
|
|
2658
|
+
ValueError: logarithm is not defined at zero
|
|
2659
|
+
|
|
2660
|
+
For elements in a `p`-adic ring, the logarithm will be returned in the
|
|
2661
|
+
same ring::
|
|
2662
|
+
|
|
2663
|
+
sage: x = R(2)
|
|
2664
|
+
sage: x.log().parent()
|
|
2665
|
+
7-adic Ring with capped absolute precision 10
|
|
2666
|
+
sage: x = R(14)
|
|
2667
|
+
sage: x.log(p_branch=0).parent()
|
|
2668
|
+
7-adic Ring with capped absolute precision 10
|
|
2669
|
+
|
|
2670
|
+
This is not possible if the logarithm has negative valuation::
|
|
2671
|
+
|
|
2672
|
+
sage: R = ZpCA(3,10)
|
|
2673
|
+
sage: S.<x> = R[]
|
|
2674
|
+
sage: f = x^3 - 3
|
|
2675
|
+
sage: W.<w> = R.ext(f) # needs sage.libs.ntl sage.rings.padics
|
|
2676
|
+
sage: w.log(p_branch=2) # needs sage.libs.ntl sage.rings.padics
|
|
2677
|
+
Traceback (most recent call last):
|
|
2678
|
+
...
|
|
2679
|
+
ValueError: logarithm is not integral, use change_frac=True
|
|
2680
|
+
to obtain a result in the fraction field
|
|
2681
|
+
sage: w.log(p_branch=2, change_frac=True) # needs sage.libs.ntl sage.rings.padics
|
|
2682
|
+
2*w^-3 + O(w^24)
|
|
2683
|
+
|
|
2684
|
+
TESTS:
|
|
2685
|
+
|
|
2686
|
+
Check that the generic algorithm and the binary splitting algorithm
|
|
2687
|
+
returns the same answers::
|
|
2688
|
+
|
|
2689
|
+
sage: p = 17
|
|
2690
|
+
sage: R = Zp(p)
|
|
2691
|
+
sage: a = 1 + p*R.random_element()
|
|
2692
|
+
sage: l1 = a.log(algorithm='generic')
|
|
2693
|
+
sage: l2 = a.log(algorithm='binary_splitting')
|
|
2694
|
+
sage: l1 == l2
|
|
2695
|
+
True
|
|
2696
|
+
sage: l1.precision_absolute() == l2.precision_absolute()
|
|
2697
|
+
True
|
|
2698
|
+
|
|
2699
|
+
Check multiplicativity::
|
|
2700
|
+
|
|
2701
|
+
sage: p = 11
|
|
2702
|
+
sage: R = Zp(p, prec=1000)
|
|
2703
|
+
|
|
2704
|
+
sage: x = 1 + p*R.random_element()
|
|
2705
|
+
sage: y = 1 + p*R.random_element()
|
|
2706
|
+
sage: log(x*y) == log(x) + log(y)
|
|
2707
|
+
True
|
|
2708
|
+
|
|
2709
|
+
sage: x = y = 0
|
|
2710
|
+
sage: while x == 0:
|
|
2711
|
+
....: x = R.random_element()
|
|
2712
|
+
sage: while y == 0:
|
|
2713
|
+
....: y = R.random_element()
|
|
2714
|
+
sage: branch = R.random_element()
|
|
2715
|
+
sage: (x*y).log(p_branch=branch) == x.log(p_branch=branch) + y.log(p_branch=branch)
|
|
2716
|
+
True
|
|
2717
|
+
|
|
2718
|
+
Note that multiplicativity may fail in the fixed modulus setting
|
|
2719
|
+
due to rounding errors::
|
|
2720
|
+
|
|
2721
|
+
sage: R = ZpFM(2, prec=5)
|
|
2722
|
+
sage: R(180).log(p_branch=0) == R(30).log(p_branch=0) + R(6).log(p_branch=0)
|
|
2723
|
+
False
|
|
2724
|
+
|
|
2725
|
+
Check that log is the inverse of exp::
|
|
2726
|
+
|
|
2727
|
+
sage: p = 11
|
|
2728
|
+
sage: R = Zp(p, prec=1000)
|
|
2729
|
+
sage: a = 1 + p*R.random_element()
|
|
2730
|
+
sage: exp(log(a)) == a
|
|
2731
|
+
True
|
|
2732
|
+
|
|
2733
|
+
sage: a = p*R.random_element()
|
|
2734
|
+
sage: log(exp(a)) == a
|
|
2735
|
+
True
|
|
2736
|
+
|
|
2737
|
+
Check that results are consistent over a range of precision::
|
|
2738
|
+
|
|
2739
|
+
sage: max_prec = 40
|
|
2740
|
+
sage: p = 3
|
|
2741
|
+
sage: K = Zp(p, max_prec)
|
|
2742
|
+
sage: full_log = (K(1 + p)).log()
|
|
2743
|
+
sage: for prec in range(2, max_prec):
|
|
2744
|
+
....: ll1 = (K(1+p).add_bigoh(prec)).log()
|
|
2745
|
+
....: ll2 = K(1+p).log(prec)
|
|
2746
|
+
....: assert ll1 == full_log
|
|
2747
|
+
....: assert ll2 == full_log
|
|
2748
|
+
....: assert ll1.precision_absolute() == prec
|
|
2749
|
+
|
|
2750
|
+
Check that ``aprec`` works for fixed-mod elements::
|
|
2751
|
+
|
|
2752
|
+
sage: R = ZpFM(7,10)
|
|
2753
|
+
sage: x = R(41152263); x
|
|
2754
|
+
5 + 3*7^2 + 4*7^3 + 3*7^4 + 5*7^5 + 6*7^6 + 7^9
|
|
2755
|
+
sage: x.log(aprec = 5)
|
|
2756
|
+
7 + 3*7^2 + 4*7^3 + 3*7^4
|
|
2757
|
+
sage: x.log(aprec = 7)
|
|
2758
|
+
7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6
|
|
2759
|
+
sage: x.log() # needs sage.symbolic
|
|
2760
|
+
7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + 7^7 + 3*7^8 + 4*7^9
|
|
2761
|
+
|
|
2762
|
+
Check that precision is computed correctly in highly ramified
|
|
2763
|
+
extensions::
|
|
2764
|
+
|
|
2765
|
+
sage: S.<x> = ZZ[]
|
|
2766
|
+
sage: K = Qp(5,5)
|
|
2767
|
+
sage: f = x^625 - 5*x - 5
|
|
2768
|
+
|
|
2769
|
+
sage: # needs sage.libs.ntl sage.rings.padics
|
|
2770
|
+
sage: W.<w> = K.extension(f)
|
|
2771
|
+
sage: z = 1 - w^2 + O(w^11)
|
|
2772
|
+
sage: x = 1 - z
|
|
2773
|
+
sage: z.log().precision_absolute()
|
|
2774
|
+
-975
|
|
2775
|
+
sage: (x^5/5).precision_absolute()
|
|
2776
|
+
-570
|
|
2777
|
+
sage: (x^25/25).precision_absolute()
|
|
2778
|
+
-975
|
|
2779
|
+
sage: (x^125/125).precision_absolute()
|
|
2780
|
+
-775
|
|
2781
|
+
|
|
2782
|
+
sage: # needs sage.libs.ntl sage.rings.padics
|
|
2783
|
+
sage: z = 1 - w + O(w^2)
|
|
2784
|
+
sage: x = 1 - z
|
|
2785
|
+
sage: z.log().precision_absolute()
|
|
2786
|
+
-1625
|
|
2787
|
+
sage: (x^5/5).precision_absolute()
|
|
2788
|
+
-615
|
|
2789
|
+
sage: (x^25/25).precision_absolute()
|
|
2790
|
+
-1200
|
|
2791
|
+
sage: (x^125/125).precision_absolute()
|
|
2792
|
+
-1625
|
|
2793
|
+
sage: (x^625/625).precision_absolute()
|
|
2794
|
+
-1250
|
|
2795
|
+
|
|
2796
|
+
sage: z.log().precision_relative() # needs sage.libs.ntl sage.rings.padics
|
|
2797
|
+
250
|
|
2798
|
+
|
|
2799
|
+
Performances::
|
|
2800
|
+
|
|
2801
|
+
sage: R = Zp(17, prec=10^5)
|
|
2802
|
+
sage: a = R.random_element()
|
|
2803
|
+
sage: b = a.log(p_branch=0) # should be rather fast
|
|
2804
|
+
|
|
2805
|
+
AUTHORS:
|
|
2806
|
+
|
|
2807
|
+
- William Stein: initial version
|
|
2808
|
+
|
|
2809
|
+
- David Harvey (2006-09-13): corrected subtle precision bug (need to
|
|
2810
|
+
take denominators into account! -- see :issue:`53`)
|
|
2811
|
+
|
|
2812
|
+
- Genya Zaytman (2007-02-14): adapted to new `p`-adic class
|
|
2813
|
+
|
|
2814
|
+
- Amnon Besser, Marc Masdeu (2012-02-21): complete rewrite, valid for
|
|
2815
|
+
generic `p`-adic rings.
|
|
2816
|
+
|
|
2817
|
+
- Soroosh Yazdani (2013-02-1): Fixed a precision issue in
|
|
2818
|
+
:meth:`_log_generic`. This should really fix the issue with
|
|
2819
|
+
divisions.
|
|
2820
|
+
|
|
2821
|
+
- Julian Rueth (2013-02-14): Added doctests, some changes for
|
|
2822
|
+
capped-absolute implementations.
|
|
2823
|
+
|
|
2824
|
+
- Xavier Caruso (2017-06): Added binary splitting type algorithms
|
|
2825
|
+
over Qp
|
|
2826
|
+
"""
|
|
2827
|
+
if self.is_zero():
|
|
2828
|
+
raise ValueError('logarithm is not defined at zero')
|
|
2829
|
+
if p_branch is not None and pi_branch is not None:
|
|
2830
|
+
raise ValueError("you may only specify a branch of the logarithm in one way")
|
|
2831
|
+
R = self.parent()
|
|
2832
|
+
p = R.prime()
|
|
2833
|
+
q = p**R.absolute_f()
|
|
2834
|
+
e = R.absolute_e()
|
|
2835
|
+
|
|
2836
|
+
if self.is_padic_unit():
|
|
2837
|
+
total = R.zero()
|
|
2838
|
+
else:
|
|
2839
|
+
if pi_branch is None:
|
|
2840
|
+
if p_branch is None:
|
|
2841
|
+
raise ValueError("you must specify a branch of the logarithm for non-units")
|
|
2842
|
+
pi_branch = (p_branch - R._log_unit_part_p()) / e
|
|
2843
|
+
# Be careful: in ramified extensions, R._log_unit_part_p() is theoretically known at higher precision than the cap
|
|
2844
|
+
# In some cases, this may result in a loss of precision on pi_branch, and then on the final result
|
|
2845
|
+
total = self.valuation() * pi_branch
|
|
2846
|
+
y = self.unit_part()
|
|
2847
|
+
x = 1 - y
|
|
2848
|
+
|
|
2849
|
+
if x.valuation()>0:
|
|
2850
|
+
denom=Integer(1)
|
|
2851
|
+
else:
|
|
2852
|
+
y=y**(q-1) # Is it better to multiply it by Teichmuller element?
|
|
2853
|
+
denom=Integer(q-1)
|
|
2854
|
+
x = 1 - y
|
|
2855
|
+
|
|
2856
|
+
minaprec = y.precision_absolute()
|
|
2857
|
+
minn = 0
|
|
2858
|
+
if e != 1:
|
|
2859
|
+
xval = x.valuation()
|
|
2860
|
+
lamb = minaprec - xval
|
|
2861
|
+
if lamb > 0 and lamb*(p-1) <= e:
|
|
2862
|
+
# This is the precision region where the absolute
|
|
2863
|
+
# precision of the answer might be less than the
|
|
2864
|
+
# absolute precision of the input
|
|
2865
|
+
|
|
2866
|
+
# kink is the number of times we multiply the relative
|
|
2867
|
+
# precision by p before starting to add e instead.
|
|
2868
|
+
kink = (e // (lamb * (p-1))).exact_log(p) + 1
|
|
2869
|
+
|
|
2870
|
+
# deriv0 is within 1 of the n yielding the minimal
|
|
2871
|
+
# absolute precision
|
|
2872
|
+
tmp = (e / (minaprec * p.log(prec=53))).floor()
|
|
2873
|
+
if tmp > 0:
|
|
2874
|
+
deriv0 = tmp.exact_log(p)
|
|
2875
|
+
else:
|
|
2876
|
+
deriv0 = 0
|
|
2877
|
+
|
|
2878
|
+
# These are the absolute precisions of x^(p^n) at potential minimum points
|
|
2879
|
+
L = [(minaprec * p**n - n * e, n) for n in [0, kink, deriv0, deriv0+1]]
|
|
2880
|
+
L.sort()
|
|
2881
|
+
minaprec = L[0][0]
|
|
2882
|
+
minn = L[0][1]
|
|
2883
|
+
|
|
2884
|
+
if aprec is None or aprec > minaprec:
|
|
2885
|
+
aprec=minaprec
|
|
2886
|
+
|
|
2887
|
+
if algorithm is None:
|
|
2888
|
+
try:
|
|
2889
|
+
# The binary splitting algorithm is supposed to be faster
|
|
2890
|
+
log_unit = y._log_binary_splitting(aprec, minn)
|
|
2891
|
+
except NotImplementedError:
|
|
2892
|
+
log_unit = y._log_generic(aprec, minn)
|
|
2893
|
+
elif algorithm == "generic":
|
|
2894
|
+
log_unit = y._log_generic(aprec, minn)
|
|
2895
|
+
elif algorithm == "binary_splitting":
|
|
2896
|
+
log_unit = y._log_binary_splitting(aprec, minn)
|
|
2897
|
+
else:
|
|
2898
|
+
raise ValueError("algorithm must be either 'generic', 'binary_splitting' or None")
|
|
2899
|
+
|
|
2900
|
+
retval = total + log_unit*R(denom).inverse_of_unit()
|
|
2901
|
+
if not change_frac:
|
|
2902
|
+
if retval.valuation() < 0 and not R.is_field():
|
|
2903
|
+
raise ValueError("logarithm is not integral, use change_frac=True to obtain a result in the fraction field")
|
|
2904
|
+
retval = R(retval)
|
|
2905
|
+
return retval.add_bigoh(aprec)
|
|
2906
|
+
|
|
2907
|
+
def _exp_generic(self, aprec):
|
|
2908
|
+
r"""
|
|
2909
|
+
Compute the exponential power series of this element, using Horner's
|
|
2910
|
+
evaluation and only one division.
|
|
2911
|
+
|
|
2912
|
+
This is a helper method for :meth:`exp`.
|
|
2913
|
+
|
|
2914
|
+
INPUT:
|
|
2915
|
+
|
|
2916
|
+
- ``aprec`` -- integer; the precision to which to compute the
|
|
2917
|
+
exponential
|
|
2918
|
+
|
|
2919
|
+
EXAMPLES::
|
|
2920
|
+
|
|
2921
|
+
sage: R.<w> = Zq(7^2,5) # needs sage.libs.ntl
|
|
2922
|
+
sage: x = R(7*w) # needs sage.libs.ntl
|
|
2923
|
+
sage: x.exp(algorithm='generic') # indirect doctest # needs sage.libs.ntl
|
|
2924
|
+
1 + w*7 + (4*w + 2)*7^2 + (w + 6)*7^3 + 5*7^4 + O(7^5)
|
|
2925
|
+
|
|
2926
|
+
TESTS:
|
|
2927
|
+
|
|
2928
|
+
Verify that :issue:`38037` is fixed::
|
|
2929
|
+
|
|
2930
|
+
sage: # needs sage.libs.ntl
|
|
2931
|
+
sage: R.<a> = Zq(9)
|
|
2932
|
+
sage: exp(R.zero())
|
|
2933
|
+
1 + O(3^20)
|
|
2934
|
+
|
|
2935
|
+
AUTHORS:
|
|
2936
|
+
|
|
2937
|
+
- Genya Zaytman (2007-02-15)
|
|
2938
|
+
|
|
2939
|
+
- Amnon Besser, Marc Masdeu (2012-02-23): Complete rewrite
|
|
2940
|
+
|
|
2941
|
+
- Soroosh Yazdani (2013-02-01): Added the code for capped relative
|
|
2942
|
+
|
|
2943
|
+
- Julian Rueth (2013-02-14): Rewrite to solve some precision problems
|
|
2944
|
+
in the capped-absolute case
|
|
2945
|
+
"""
|
|
2946
|
+
R=self.parent()
|
|
2947
|
+
p=self.parent().prime()
|
|
2948
|
+
e=self.parent().absolute_e()
|
|
2949
|
+
if self._is_exact_zero():
|
|
2950
|
+
return R.one()
|
|
2951
|
+
x_unit=self.unit_part()
|
|
2952
|
+
p_unit=R(p).unit_part().lift_to_precision()
|
|
2953
|
+
x_val=self.valuation()
|
|
2954
|
+
|
|
2955
|
+
# the valuation of n! is bounded by e*n/(p-1), therefore the valuation
|
|
2956
|
+
# of self^n/n! is bigger or equal to n*x_val - e*n/(p-1). So, we only
|
|
2957
|
+
# have to sum terms for which n does not exceed N
|
|
2958
|
+
N = (aprec // (x_val - e/(p-1))).floor()
|
|
2959
|
+
|
|
2960
|
+
# We evaluate the exponential series:
|
|
2961
|
+
# First, we compute the value of x^N+N*x^(N-1)+...+x*N!+N! using
|
|
2962
|
+
# Horner's method. Then, we divide by N!.
|
|
2963
|
+
# This would only work for capped relative elements since for other
|
|
2964
|
+
# elements, we would lose too much precision in the multiplications
|
|
2965
|
+
# with natural numbers. Therefore, we emulate the behaviour of
|
|
2966
|
+
# capped-relative elements and keep track of the unit part and the
|
|
2967
|
+
# valuation separately.
|
|
2968
|
+
|
|
2969
|
+
# the value of x^N + N*x^(N-1) + ... + (N-1)!*x + N!
|
|
2970
|
+
series_unit,series_val = R.one(), 0
|
|
2971
|
+
|
|
2972
|
+
# we compute the value of N! as we go through the loop
|
|
2973
|
+
nfactorial_unit,nfactorial_val = R.one(),0
|
|
2974
|
+
|
|
2975
|
+
nmodp = N % p
|
|
2976
|
+
for n in range(N, 0, -1):
|
|
2977
|
+
# multiply everything by x
|
|
2978
|
+
series_val += x_val
|
|
2979
|
+
series_unit *= x_unit
|
|
2980
|
+
|
|
2981
|
+
# compute the new value of N*(N-1)*...
|
|
2982
|
+
if nmodp == 0:
|
|
2983
|
+
n_pval, n_punit = Integer(n).val_unit(p)
|
|
2984
|
+
nfactorial_unit *= R(n_punit) * p_unit**n_pval
|
|
2985
|
+
nfactorial_val += n_pval*e
|
|
2986
|
+
nmodp = p
|
|
2987
|
+
else:
|
|
2988
|
+
nfactorial_unit *= n
|
|
2989
|
+
nmodp -= 1
|
|
2990
|
+
|
|
2991
|
+
# now add N*(N-1)*...
|
|
2992
|
+
common_val = min(nfactorial_val, series_val)
|
|
2993
|
+
series_unit = (series_unit<<(series_val-common_val)) + (nfactorial_unit<<(nfactorial_val-common_val))
|
|
2994
|
+
series_val = common_val
|
|
2995
|
+
|
|
2996
|
+
# multiply the result by N!
|
|
2997
|
+
return series_unit*nfactorial_unit.inverse_of_unit()<<(series_val-nfactorial_val)
|
|
2998
|
+
|
|
2999
|
+
def _exp_binary_splitting(self, aprec):
|
|
3000
|
+
r"""
|
|
3001
|
+
Compute the exponential power series of this element.
|
|
3002
|
+
|
|
3003
|
+
This is a helper method for :meth:`exp`.
|
|
3004
|
+
|
|
3005
|
+
INPUT:
|
|
3006
|
+
|
|
3007
|
+
- ``aprec`` -- integer; the precision to which to compute the
|
|
3008
|
+
exponential
|
|
3009
|
+
|
|
3010
|
+
.. NOTE::
|
|
3011
|
+
|
|
3012
|
+
The function does not check that its argument ``self`` is
|
|
3013
|
+
the disk of convergence of ``exp``. If this assumption is not
|
|
3014
|
+
fulfilled the behaviour of the function is not specified.
|
|
3015
|
+
|
|
3016
|
+
ALGORITHM:
|
|
3017
|
+
|
|
3018
|
+
Write
|
|
3019
|
+
|
|
3020
|
+
.. MATH::
|
|
3021
|
+
|
|
3022
|
+
self = \sum_{i=1}^\infty a_i p^{2^i}
|
|
3023
|
+
|
|
3024
|
+
with `0 \leq a_i < p^{2^i}` and compute
|
|
3025
|
+
`\exp(a_i p^{2^i})` using the standard Taylor expansion
|
|
3026
|
+
|
|
3027
|
+
.. MATH::
|
|
3028
|
+
|
|
3029
|
+
\exp(x) = 1 + x + x^2/2 + x^3/6 + x^4/24 + \cdots
|
|
3030
|
+
|
|
3031
|
+
together with a binary splitting method.
|
|
3032
|
+
|
|
3033
|
+
The binary complexity of this algorithm is quasi-linear.
|
|
3034
|
+
|
|
3035
|
+
EXAMPLES::
|
|
3036
|
+
|
|
3037
|
+
sage: R = Zp(7,5)
|
|
3038
|
+
sage: x = R(7)
|
|
3039
|
+
sage: x.exp(algorithm='binary_splitting') # indirect doctest
|
|
3040
|
+
1 + 7 + 4*7^2 + 2*7^3 + O(7^5)
|
|
3041
|
+
"""
|
|
3042
|
+
raise NotImplementedError("the binary splitting algorithm is not implemented for the parent: %s" % self.parent())
|
|
3043
|
+
|
|
3044
|
+
def _exp_newton(self, aprec, log_algorithm=None):
|
|
3045
|
+
r"""
|
|
3046
|
+
Compute the exponential power series of this element.
|
|
3047
|
+
|
|
3048
|
+
This is a helper method for :meth:`exp`.
|
|
3049
|
+
|
|
3050
|
+
INPUT:
|
|
3051
|
+
|
|
3052
|
+
- ``aprec`` -- integer; the precision to which to compute the
|
|
3053
|
+
exponential
|
|
3054
|
+
|
|
3055
|
+
- ``log_algorithm`` -- (default: ``None``) the algorithm used for
|
|
3056
|
+
computing the logarithm. This attribute is passed to the log
|
|
3057
|
+
method. See :meth:`log` for more details about the possible
|
|
3058
|
+
algorithms.
|
|
3059
|
+
|
|
3060
|
+
.. NOTE::
|
|
3061
|
+
|
|
3062
|
+
The function does not check that its argument ``self`` is
|
|
3063
|
+
the disk of convergence of ``exp``. If this assumption is not
|
|
3064
|
+
fulfilled the behaviour of the function is not specified.
|
|
3065
|
+
|
|
3066
|
+
ALGORITHM:
|
|
3067
|
+
|
|
3068
|
+
Solve the equation `\log(x) = self` using the Newton scheme::
|
|
3069
|
+
|
|
3070
|
+
.. MATH::
|
|
3071
|
+
|
|
3072
|
+
x_{i+1} = x_i \cdot (1 + self - \log(x_i))
|
|
3073
|
+
|
|
3074
|
+
The binary complexity of this algorithm is roughly the same
|
|
3075
|
+
than that of the computation of the logarithm.
|
|
3076
|
+
|
|
3077
|
+
EXAMPLES::
|
|
3078
|
+
|
|
3079
|
+
sage: R.<w> = Zq(7^2,5) # needs sage.libs.ntl
|
|
3080
|
+
sage: x = R(7*w) # needs sage.libs.ntl
|
|
3081
|
+
sage: x.exp(algorithm='newton') # indirect doctest # needs sage.libs.ntl
|
|
3082
|
+
1 + w*7 + (4*w + 2)*7^2 + (w + 6)*7^3 + 5*7^4 + O(7^5)
|
|
3083
|
+
"""
|
|
3084
|
+
R = self.parent()
|
|
3085
|
+
e = R.absolute_e()
|
|
3086
|
+
a = R(1,aprec)
|
|
3087
|
+
l = R(0,aprec)
|
|
3088
|
+
if R.prime() == 2:
|
|
3089
|
+
trunc = e + 1
|
|
3090
|
+
while trunc < aprec:
|
|
3091
|
+
trunc = 2*trunc - e
|
|
3092
|
+
b = (self-l).add_bigoh(trunc).lift_to_precision(aprec)
|
|
3093
|
+
a *= 1+b
|
|
3094
|
+
l += (1+b).log(aprec, algorithm=log_algorithm)
|
|
3095
|
+
else:
|
|
3096
|
+
trunc = 1
|
|
3097
|
+
while trunc < aprec:
|
|
3098
|
+
trunc = 2*trunc
|
|
3099
|
+
b = (self-l).add_bigoh(trunc).lift_to_precision(aprec)
|
|
3100
|
+
a *= 1+b
|
|
3101
|
+
l += (1+b).log(aprec, algorithm=log_algorithm)
|
|
3102
|
+
return a
|
|
3103
|
+
|
|
3104
|
+
def exp(self, aprec=None, algorithm=None):
|
|
3105
|
+
r"""
|
|
3106
|
+
Compute the `p`-adic exponential of this element if the exponential
|
|
3107
|
+
series converges.
|
|
3108
|
+
|
|
3109
|
+
INPUT:
|
|
3110
|
+
|
|
3111
|
+
- ``aprec`` -- integer or ``None`` (default: ``None``); if
|
|
3112
|
+
specified, computes only up to the indicated precision
|
|
3113
|
+
|
|
3114
|
+
- ``algorithm`` -- ``'generic'``, ``'binary_splitting'``, ``'newton'``
|
|
3115
|
+
or ``None`` (default)
|
|
3116
|
+
|
|
3117
|
+
The ``'generic'`` algorithm evaluates naively the series defining the
|
|
3118
|
+
exponential, namely
|
|
3119
|
+
|
|
3120
|
+
.. MATH::
|
|
3121
|
+
|
|
3122
|
+
\exp(x) = 1 + x + x^2/2 + x^3/6 + x^4/24 + \cdots.
|
|
3123
|
+
|
|
3124
|
+
Its binary complexity is quadratic with respect to the precision.
|
|
3125
|
+
|
|
3126
|
+
The ``'binary_splitting'`` algorithm is faster, it has a quasi-linear
|
|
3127
|
+
complexity.
|
|
3128
|
+
|
|
3129
|
+
The ``'newton'`` algorithms solve the equation `\log(x) =` ``self``
|
|
3130
|
+
using a Newton scheme. It runs roughly as fast as the computation
|
|
3131
|
+
of the logarithm.
|
|
3132
|
+
|
|
3133
|
+
By default, we use the ``'binary_splitting'`` if it is available.
|
|
3134
|
+
If it is not, we use the ``'newton'`` algorithm if a fast algorithm for
|
|
3135
|
+
computing the logarithm is available.
|
|
3136
|
+
Otherwise we switch to the ``'generic'`` algorithm.
|
|
3137
|
+
|
|
3138
|
+
EXAMPLES:
|
|
3139
|
+
|
|
3140
|
+
:meth:`log` and :meth:`exp` are inverse to each other::
|
|
3141
|
+
|
|
3142
|
+
sage: Z13 = Zp(13, 10)
|
|
3143
|
+
sage: a = Z13(14); a
|
|
3144
|
+
1 + 13 + O(13^10)
|
|
3145
|
+
sage: a.log().exp()
|
|
3146
|
+
1 + 13 + O(13^10)
|
|
3147
|
+
|
|
3148
|
+
An error occurs if this is called with an element for which the
|
|
3149
|
+
exponential series does not converge::
|
|
3150
|
+
|
|
3151
|
+
sage: Z13.one().exp()
|
|
3152
|
+
Traceback (most recent call last):
|
|
3153
|
+
...
|
|
3154
|
+
ValueError: Exponential does not converge for that input.
|
|
3155
|
+
|
|
3156
|
+
The next few examples illustrate precision when computing `p`-adic
|
|
3157
|
+
exponentials::
|
|
3158
|
+
|
|
3159
|
+
sage: R = Zp(5,10)
|
|
3160
|
+
sage: e = R(2*5 + 2*5**2 + 4*5**3 + 3*5**4
|
|
3161
|
+
....: + 5**5 + 3*5**7 + 2*5**8 + 4*5**9).add_bigoh(10); e
|
|
3162
|
+
2*5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^5 + 3*5^7 + 2*5^8 + 4*5^9 + O(5^10)
|
|
3163
|
+
sage: e.exp()*R.teichmuller(4)
|
|
3164
|
+
4 + 2*5 + 3*5^3 + O(5^10)
|
|
3165
|
+
|
|
3166
|
+
::
|
|
3167
|
+
|
|
3168
|
+
sage: K = Qp(5,10)
|
|
3169
|
+
sage: e = K(2*5 + 2*5**2 + 4*5**3 + 3*5**4
|
|
3170
|
+
....: + 5**5 + 3*5**7 + 2*5**8 + 4*5**9).add_bigoh(10); e
|
|
3171
|
+
2*5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^5 + 3*5^7 + 2*5^8 + 4*5^9 + O(5^10)
|
|
3172
|
+
sage: e.exp()*K.teichmuller(4)
|
|
3173
|
+
4 + 2*5 + 3*5^3 + O(5^10)
|
|
3174
|
+
|
|
3175
|
+
Logarithms and exponentials in extension fields. First, in an
|
|
3176
|
+
Eisenstein extension::
|
|
3177
|
+
|
|
3178
|
+
sage: # needs sage.libs.ntl
|
|
3179
|
+
sage: R = Zp(5,5)
|
|
3180
|
+
sage: S.<x> = R[]
|
|
3181
|
+
sage: f = x^4 + 15*x^2 + 625*x - 5
|
|
3182
|
+
sage: W.<w> = R.ext(f)
|
|
3183
|
+
sage: z = 1 + w^2 + 4*w^7; z
|
|
3184
|
+
1 + w^2 + 4*w^7 + O(w^20)
|
|
3185
|
+
sage: z.log().exp()
|
|
3186
|
+
1 + w^2 + 4*w^7 + O(w^20)
|
|
3187
|
+
|
|
3188
|
+
Now an unramified example::
|
|
3189
|
+
|
|
3190
|
+
sage: # needs sage.libs.ntl
|
|
3191
|
+
sage: R = Zp(5,5)
|
|
3192
|
+
sage: S.<x> = R[]
|
|
3193
|
+
sage: g = x^3 + 3*x + 3
|
|
3194
|
+
sage: A.<a> = R.ext(g)
|
|
3195
|
+
sage: b = 1 + 5*(1 + a^2) + 5^3*(3 + 2*a); b
|
|
3196
|
+
1 + (a^2 + 1)*5 + (2*a + 3)*5^3 + O(5^5)
|
|
3197
|
+
sage: b.log().exp()
|
|
3198
|
+
1 + (a^2 + 1)*5 + (2*a + 3)*5^3 + O(5^5)
|
|
3199
|
+
|
|
3200
|
+
TESTS:
|
|
3201
|
+
|
|
3202
|
+
Check that results are consistent over a range of precision::
|
|
3203
|
+
|
|
3204
|
+
sage: max_prec = 40
|
|
3205
|
+
sage: p = 3
|
|
3206
|
+
sage: K = Zp(p, max_prec)
|
|
3207
|
+
sage: full_exp = (K(p)).exp()
|
|
3208
|
+
sage: for prec in range(2, max_prec):
|
|
3209
|
+
....: ll = (K(p).add_bigoh(prec)).exp()
|
|
3210
|
+
....: assert ll == full_exp
|
|
3211
|
+
....: assert ll.precision_absolute() == prec
|
|
3212
|
+
sage: K = Qp(p, max_prec)
|
|
3213
|
+
sage: full_exp = (K(p)).exp()
|
|
3214
|
+
sage: for prec in range(2, max_prec):
|
|
3215
|
+
....: ll = (K(p).add_bigoh(prec)).exp()
|
|
3216
|
+
....: assert ll == full_exp
|
|
3217
|
+
....: assert ll.precision_absolute() == prec
|
|
3218
|
+
|
|
3219
|
+
Check that this also works for capped-absolute implementations::
|
|
3220
|
+
|
|
3221
|
+
sage: Z13 = ZpCA(13, 10)
|
|
3222
|
+
sage: a = Z13(14); a
|
|
3223
|
+
1 + 13 + O(13^10)
|
|
3224
|
+
sage: a.log().exp()
|
|
3225
|
+
1 + 13 + O(13^10)
|
|
3226
|
+
|
|
3227
|
+
sage: # needs sage.libs.ntl
|
|
3228
|
+
sage: R = ZpCA(5,5)
|
|
3229
|
+
sage: S.<x> = R[]
|
|
3230
|
+
sage: f = x^4 + 15*x^2 + 625*x - 5
|
|
3231
|
+
sage: W.<w> = R.ext(f)
|
|
3232
|
+
sage: z = 1 + w^2 + 4*w^7; z
|
|
3233
|
+
1 + w^2 + 4*w^7 + O(w^20)
|
|
3234
|
+
sage: z.log().exp()
|
|
3235
|
+
1 + w^2 + 4*w^7 + O(w^20)
|
|
3236
|
+
|
|
3237
|
+
Check that this also works for fixed-mod implementations::
|
|
3238
|
+
|
|
3239
|
+
sage: Z13 = ZpFM(13, 10)
|
|
3240
|
+
sage: a = Z13(14); a
|
|
3241
|
+
1 + 13
|
|
3242
|
+
sage: a.log().exp()
|
|
3243
|
+
1 + 13
|
|
3244
|
+
|
|
3245
|
+
sage: # needs sage.libs.ntl
|
|
3246
|
+
sage: R = ZpFM(5,5)
|
|
3247
|
+
sage: S.<x> = R[]
|
|
3248
|
+
sage: f = x^4 + 15*x^2 + 625*x - 5
|
|
3249
|
+
sage: W.<w> = R.ext(f)
|
|
3250
|
+
sage: z = 1 + w^2 + 4*w^7; z
|
|
3251
|
+
1 + w^2 + 4*w^7
|
|
3252
|
+
sage: z.log().exp()
|
|
3253
|
+
1 + w^2 + 4*w^7
|
|
3254
|
+
|
|
3255
|
+
Some corner cases::
|
|
3256
|
+
|
|
3257
|
+
sage: Z2 = Zp(2, 5)
|
|
3258
|
+
sage: Z2(2).exp()
|
|
3259
|
+
Traceback (most recent call last):
|
|
3260
|
+
...
|
|
3261
|
+
ValueError: Exponential does not converge for that input.
|
|
3262
|
+
|
|
3263
|
+
sage: # needs sage.libs.ntl
|
|
3264
|
+
sage: S.<x> = Z2[]
|
|
3265
|
+
sage: W.<w> = Z2.ext(x^3-2)
|
|
3266
|
+
sage: (w^2).exp()
|
|
3267
|
+
Traceback (most recent call last):
|
|
3268
|
+
...
|
|
3269
|
+
ValueError: Exponential does not converge for that input.
|
|
3270
|
+
sage: (w^3).exp()
|
|
3271
|
+
Traceback (most recent call last):
|
|
3272
|
+
...
|
|
3273
|
+
ValueError: Exponential does not converge for that input.
|
|
3274
|
+
sage: (w^4).exp()
|
|
3275
|
+
1 + w^4 + w^5 + w^7 + w^9 + w^10 + w^14 + O(w^15)
|
|
3276
|
+
|
|
3277
|
+
Check that all algorithms output the same result::
|
|
3278
|
+
|
|
3279
|
+
sage: R = Zp(5,50)
|
|
3280
|
+
sage: a = 5 * R.random_element()
|
|
3281
|
+
sage: bg = a.exp(algorithm='generic')
|
|
3282
|
+
sage: bbs = a.exp(algorithm='binary_splitting')
|
|
3283
|
+
sage: bn = a.exp(algorithm='newton')
|
|
3284
|
+
sage: bg == bbs
|
|
3285
|
+
True
|
|
3286
|
+
sage: bg == bn
|
|
3287
|
+
True
|
|
3288
|
+
|
|
3289
|
+
Performances::
|
|
3290
|
+
|
|
3291
|
+
sage: R = Zp(17,10^5)
|
|
3292
|
+
sage: a = 17 * R.random_element()
|
|
3293
|
+
sage: b = a.exp() # should be rather fast
|
|
3294
|
+
|
|
3295
|
+
AUTHORS:
|
|
3296
|
+
|
|
3297
|
+
- Genya Zaytman (2007-02-15)
|
|
3298
|
+
|
|
3299
|
+
- Amnon Besser, Marc Masdeu (2012-02-23): Complete rewrite
|
|
3300
|
+
|
|
3301
|
+
- Julian Rueth (2013-02-14): Added doctests, fixed some corner cases
|
|
3302
|
+
|
|
3303
|
+
- Xavier Caruso (2017-06): Added binary splitting and Newton algorithms
|
|
3304
|
+
"""
|
|
3305
|
+
p = self.parent().prime()
|
|
3306
|
+
|
|
3307
|
+
if (p-1)*self.valuation() <= self.parent().absolute_e():
|
|
3308
|
+
raise ValueError('Exponential does not converge for that input.')
|
|
3309
|
+
|
|
3310
|
+
# The optimal absolute precision on exp(self)
|
|
3311
|
+
# is the absolution precision on self
|
|
3312
|
+
maxprec = min(self.precision_absolute(), self.parent().precision_cap())
|
|
3313
|
+
if aprec is None or aprec > maxprec:
|
|
3314
|
+
aprec = maxprec
|
|
3315
|
+
|
|
3316
|
+
if algorithm is None:
|
|
3317
|
+
try:
|
|
3318
|
+
ans = self._exp_binary_splitting(aprec)
|
|
3319
|
+
except NotImplementedError:
|
|
3320
|
+
try:
|
|
3321
|
+
ans = self._exp_newton(aprec, log_algorithm='binary_splitting')
|
|
3322
|
+
except NotImplementedError:
|
|
3323
|
+
ans = self._exp_generic(aprec)
|
|
3324
|
+
elif algorithm == 'generic':
|
|
3325
|
+
ans = self._exp_generic(aprec)
|
|
3326
|
+
elif algorithm == 'binary_splitting':
|
|
3327
|
+
ans = self._exp_binary_splitting(aprec)
|
|
3328
|
+
elif algorithm == 'newton':
|
|
3329
|
+
ans = self._exp_newton(aprec)
|
|
3330
|
+
else:
|
|
3331
|
+
raise ValueError("algorithm must be 'generic', 'binary_splitting', 'newton' or None")
|
|
3332
|
+
return ans.add_bigoh(aprec)
|
|
3333
|
+
|
|
3334
|
+
def square_root(self, extend=True, all=False, algorithm=None):
|
|
3335
|
+
r"""
|
|
3336
|
+
Return the square root of this `p`-adic number.
|
|
3337
|
+
|
|
3338
|
+
INPUT:
|
|
3339
|
+
|
|
3340
|
+
- ``self`` -- a `p`-adic element
|
|
3341
|
+
|
|
3342
|
+
- ``extend`` -- boolean (default: ``True``); if ``True``, return a
|
|
3343
|
+
square root in an extension if necessary; if ``False`` and no root
|
|
3344
|
+
exists in the given ring or field, raise a :exc:`ValueError`.
|
|
3345
|
+
|
|
3346
|
+
- ``all`` -- boolean (default: ``False``); if ``True``, return a
|
|
3347
|
+
list of all square roots
|
|
3348
|
+
|
|
3349
|
+
- ``algorithm`` -- ``'pari'``, ``'sage'`` or ``None`` (default:
|
|
3350
|
+
``None``); Sage provides an implementation for any extension of
|
|
3351
|
+
`\QQ_p`, whereas only square roots over `\QQ_p` are implemented in
|
|
3352
|
+
PARI. The default is ``'pari'`` if the ground field is `\QQ_p`,
|
|
3353
|
+
``'sage'`` otherwise.
|
|
3354
|
+
|
|
3355
|
+
OUTPUT:
|
|
3356
|
+
|
|
3357
|
+
The square root or the list of all square roots of this `p`-adic
|
|
3358
|
+
number.
|
|
3359
|
+
|
|
3360
|
+
NOTE:
|
|
3361
|
+
|
|
3362
|
+
The square root is chosen (resp. the square roots are ordered) in
|
|
3363
|
+
a deterministic way.
|
|
3364
|
+
|
|
3365
|
+
EXAMPLES::
|
|
3366
|
+
|
|
3367
|
+
sage: R = Zp(3, 20)
|
|
3368
|
+
sage: R(0).square_root()
|
|
3369
|
+
0
|
|
3370
|
+
|
|
3371
|
+
sage: R(1).square_root()
|
|
3372
|
+
1 + O(3^20)
|
|
3373
|
+
|
|
3374
|
+
sage: R(2).square_root(extend=False)
|
|
3375
|
+
Traceback (most recent call last):
|
|
3376
|
+
...
|
|
3377
|
+
ValueError: element is not a square
|
|
3378
|
+
|
|
3379
|
+
sage: -R(4).square_root()
|
|
3380
|
+
2 + O(3^20)
|
|
3381
|
+
|
|
3382
|
+
sage: R(9).square_root()
|
|
3383
|
+
3 + O(3^21)
|
|
3384
|
+
|
|
3385
|
+
When `p = 2`, the precision of the square root is less
|
|
3386
|
+
than the input::
|
|
3387
|
+
|
|
3388
|
+
sage: R2 = Zp(2, 20)
|
|
3389
|
+
sage: R2(1).square_root()
|
|
3390
|
+
1 + O(2^19)
|
|
3391
|
+
sage: R2(4).square_root()
|
|
3392
|
+
2 + O(2^20)
|
|
3393
|
+
|
|
3394
|
+
sage: R.<t> = Zq(2^10, 10) # needs sage.libs.ntl
|
|
3395
|
+
sage: u = 1 + 8*t # needs sage.libs.ntl
|
|
3396
|
+
sage: u.square_root() # needs sage.libs.ntl
|
|
3397
|
+
1 + t*2^2 + t^2*2^3 + t^2*2^4 + (t^4 + t^3 + t^2)*2^5 + (t^4 + t^2)*2^6
|
|
3398
|
+
+ (t^5 + t^2)*2^7 + (t^6 + t^5 + t^4 + t^2)*2^8 + O(2^9)
|
|
3399
|
+
|
|
3400
|
+
sage: # needs sage.libs.ntl
|
|
3401
|
+
sage: x = polygen(ZZ, 'x')
|
|
3402
|
+
sage: R.<a> = Zp(2).extension(x^3 - 2)
|
|
3403
|
+
sage: u = R(1 + a^4 + a^5 + a^7 + a^8, 10); u
|
|
3404
|
+
1 + a^4 + a^5 + a^7 + a^8 + O(a^10)
|
|
3405
|
+
sage: v = u.square_root(); v
|
|
3406
|
+
1 + a^2 + a^4 + a^6 + O(a^7)
|
|
3407
|
+
|
|
3408
|
+
However, observe that the precision increases to its original value
|
|
3409
|
+
when we recompute the square of the square root::
|
|
3410
|
+
|
|
3411
|
+
sage: v^2 # needs sage.libs.ntl
|
|
3412
|
+
1 + a^4 + a^5 + a^7 + a^8 + O(a^10)
|
|
3413
|
+
|
|
3414
|
+
If the input does not have enough precision in order to determine if
|
|
3415
|
+
the given element has a square root in the ground field, an error is
|
|
3416
|
+
raised::
|
|
3417
|
+
|
|
3418
|
+
sage: # needs sage.libs.ntl
|
|
3419
|
+
sage: R(1, 6).square_root()
|
|
3420
|
+
Traceback (most recent call last):
|
|
3421
|
+
...
|
|
3422
|
+
PrecisionError: not enough precision to be sure that this element has a square root
|
|
3423
|
+
sage: R(1, 7).square_root()
|
|
3424
|
+
1 + O(a^4)
|
|
3425
|
+
sage: R(1+a^6, 7).square_root(extend=False)
|
|
3426
|
+
Traceback (most recent call last):
|
|
3427
|
+
...
|
|
3428
|
+
ValueError: element is not a square
|
|
3429
|
+
|
|
3430
|
+
In particular, an error is raised when we try to compute the square
|
|
3431
|
+
root of an inexact zero.
|
|
3432
|
+
|
|
3433
|
+
TESTS::
|
|
3434
|
+
|
|
3435
|
+
sage: R = Qp(5, 100)
|
|
3436
|
+
sage: c = R.random_element()
|
|
3437
|
+
sage: s = (c^2).square_root()
|
|
3438
|
+
sage: s == c or s == -c
|
|
3439
|
+
True
|
|
3440
|
+
|
|
3441
|
+
sage: Q2 = Qp(2,20,'capped-rel')
|
|
3442
|
+
sage: Q2(1).square_root()
|
|
3443
|
+
1 + O(2^19)
|
|
3444
|
+
sage: Q2(4).square_root()
|
|
3445
|
+
2 + O(2^20)
|
|
3446
|
+
|
|
3447
|
+
sage: Q5 = Qp(5,20,'capped-rel')
|
|
3448
|
+
sage: Q5(1).square_root()
|
|
3449
|
+
1 + O(5^20)
|
|
3450
|
+
sage: Q5(-1).square_root() == Q5.teichmuller(2) or Q5(-1).square_root() == Q5.teichmuller(3)
|
|
3451
|
+
True
|
|
3452
|
+
|
|
3453
|
+
sage: Z3 = Zp(3,20,'capped-abs')
|
|
3454
|
+
sage: Z3(1).square_root()
|
|
3455
|
+
1 + O(3^20)
|
|
3456
|
+
sage: Z3(4).square_root() in [ Z3(2), -Z3(2) ]
|
|
3457
|
+
True
|
|
3458
|
+
sage: Z3(9).square_root()
|
|
3459
|
+
3 + O(3^19)
|
|
3460
|
+
|
|
3461
|
+
sage: Z2 = Zp(2,20,'capped-abs')
|
|
3462
|
+
sage: Z2(1).square_root()
|
|
3463
|
+
1 + O(2^19)
|
|
3464
|
+
sage: Z2(4).square_root()
|
|
3465
|
+
2 + O(2^18)
|
|
3466
|
+
sage: Z2(9).square_root() in [ Z2(3), -Z2(3) ]
|
|
3467
|
+
True
|
|
3468
|
+
sage: Z2(17).square_root()
|
|
3469
|
+
1 + 2^3 + 2^5 + 2^6 + 2^7 + 2^9 + 2^10 + 2^13 + 2^16 + 2^17 + O(2^19)
|
|
3470
|
+
|
|
3471
|
+
sage: Z5 = Zp(5,20,'capped-abs')
|
|
3472
|
+
sage: Z5(1).square_root()
|
|
3473
|
+
1 + O(5^20)
|
|
3474
|
+
sage: Z5(-1).square_root() == Z5.teichmuller(2) or Z5(-1).square_root() == Z5.teichmuller(3)
|
|
3475
|
+
True
|
|
3476
|
+
"""
|
|
3477
|
+
# We first check trivial cases and precision
|
|
3478
|
+
if self._is_exact_zero():
|
|
3479
|
+
return self
|
|
3480
|
+
parent = self.parent()
|
|
3481
|
+
if self.is_zero() or (parent.prime() == 2 and self.precision_relative() < 1 + 2*parent.absolute_e()):
|
|
3482
|
+
raise PrecisionError("not enough precision to be sure that this element has a square root")
|
|
3483
|
+
|
|
3484
|
+
if algorithm is None:
|
|
3485
|
+
if parent.absolute_degree() == 1:
|
|
3486
|
+
algorithm = "pari"
|
|
3487
|
+
else:
|
|
3488
|
+
algorithm = "sage"
|
|
3489
|
+
|
|
3490
|
+
ans = None
|
|
3491
|
+
if algorithm == "pari":
|
|
3492
|
+
from cypari2.handle_error import PariError
|
|
3493
|
+
try:
|
|
3494
|
+
# use pari
|
|
3495
|
+
ans = parent(self.__pari__().sqrt())
|
|
3496
|
+
except PariError:
|
|
3497
|
+
# todo: should eventually change to return an element of
|
|
3498
|
+
# an extension field
|
|
3499
|
+
pass
|
|
3500
|
+
elif algorithm == "sage":
|
|
3501
|
+
try:
|
|
3502
|
+
ans = self.nth_root(2)
|
|
3503
|
+
except ValueError:
|
|
3504
|
+
pass
|
|
3505
|
+
if ans is not None:
|
|
3506
|
+
ans2 = -ans
|
|
3507
|
+
E1 = ans.expansion()
|
|
3508
|
+
E2 = ans2.expansion()
|
|
3509
|
+
if ans.parent().is_field():
|
|
3510
|
+
i = 0
|
|
3511
|
+
else:
|
|
3512
|
+
i = ans.valuation()
|
|
3513
|
+
while True:
|
|
3514
|
+
try:
|
|
3515
|
+
d1 = E1[i]
|
|
3516
|
+
d2 = E2[i]
|
|
3517
|
+
except (PrecisionError, IndexError):
|
|
3518
|
+
break
|
|
3519
|
+
if d1 > d2:
|
|
3520
|
+
ans, ans2 = ans2, ans
|
|
3521
|
+
break
|
|
3522
|
+
if d1 < d2:
|
|
3523
|
+
break
|
|
3524
|
+
i += 1
|
|
3525
|
+
if all:
|
|
3526
|
+
return [ans, ans2]
|
|
3527
|
+
else:
|
|
3528
|
+
return ans
|
|
3529
|
+
if extend:
|
|
3530
|
+
raise NotImplementedError("extending using the sqrt function not yet implemented")
|
|
3531
|
+
elif all:
|
|
3532
|
+
return []
|
|
3533
|
+
else:
|
|
3534
|
+
raise ValueError("element is not a square")
|
|
3535
|
+
|
|
3536
|
+
def nth_root(self, n, all=False):
|
|
3537
|
+
"""
|
|
3538
|
+
Return the `n`-th root of this element.
|
|
3539
|
+
|
|
3540
|
+
INPUT:
|
|
3541
|
+
|
|
3542
|
+
- ``n`` -- integer
|
|
3543
|
+
|
|
3544
|
+
- ``all`` -- boolean (default: ``False``); if ``True``,
|
|
3545
|
+
return all `n`-th roots of this element, instead of just one
|
|
3546
|
+
|
|
3547
|
+
EXAMPLES::
|
|
3548
|
+
|
|
3549
|
+
sage: A = Zp(5,10)
|
|
3550
|
+
sage: x = A(61376); x
|
|
3551
|
+
1 + 5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^10)
|
|
3552
|
+
sage: y = x.nth_root(4); y
|
|
3553
|
+
2 + 5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^6 + O(5^10)
|
|
3554
|
+
sage: y^4 == x
|
|
3555
|
+
True
|
|
3556
|
+
|
|
3557
|
+
sage: x.nth_root(4, all=True)
|
|
3558
|
+
[2 + 5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^6 + O(5^10),
|
|
3559
|
+
4 + 4*5 + 4*5^2 + 4*5^4 + 3*5^5 + 5^6 + 3*5^7 + 5^8 + 5^9 + O(5^10),
|
|
3560
|
+
3 + 3*5 + 2*5^2 + 5^4 + 4*5^5 + 3*5^6 + 4*5^7 + 4*5^8 + 4*5^9 + O(5^10),
|
|
3561
|
+
1 + 4*5^3 + 5^5 + 3*5^6 + 5^7 + 3*5^8 + 3*5^9 + O(5^10)]
|
|
3562
|
+
|
|
3563
|
+
When `n` is divisible by the underlying prime `p`, we
|
|
3564
|
+
are losing precision (which is consistent with the fact
|
|
3565
|
+
that raising to the `p`-th power increases precision)::
|
|
3566
|
+
|
|
3567
|
+
sage: z = x.nth_root(5); z
|
|
3568
|
+
1 + 5^2 + 3*5^3 + 2*5^4 + 5^5 + 3*5^7 + 2*5^8 + O(5^9)
|
|
3569
|
+
sage: z^5
|
|
3570
|
+
1 + 5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^10)
|
|
3571
|
+
|
|
3572
|
+
Everything works over extensions as well::
|
|
3573
|
+
|
|
3574
|
+
sage: # needs sage.libs.ntl
|
|
3575
|
+
sage: W.<a> = Zq(5^3)
|
|
3576
|
+
sage: S.<x> = W[]
|
|
3577
|
+
sage: R.<pi> = W.extension(x^7 - 5)
|
|
3578
|
+
sage: R(5).nth_root(7)
|
|
3579
|
+
pi + O(pi^141)
|
|
3580
|
+
sage: R(5).nth_root(7, all=True)
|
|
3581
|
+
[pi + O(pi^141)]
|
|
3582
|
+
|
|
3583
|
+
An error is raised if the given element is not an `n`-th power
|
|
3584
|
+
in the ring::
|
|
3585
|
+
|
|
3586
|
+
sage: R(5).nth_root(11) # needs sage.libs.ntl
|
|
3587
|
+
Traceback (most recent call last):
|
|
3588
|
+
...
|
|
3589
|
+
ValueError: this element is not a nth power
|
|
3590
|
+
|
|
3591
|
+
Similarly, when precision on the input is too small, an error
|
|
3592
|
+
is raised::
|
|
3593
|
+
|
|
3594
|
+
sage: # needs sage.libs.ntl
|
|
3595
|
+
sage: x = R(1,6); x
|
|
3596
|
+
1 + O(pi^6)
|
|
3597
|
+
sage: x.nth_root(5)
|
|
3598
|
+
Traceback (most recent call last):
|
|
3599
|
+
...
|
|
3600
|
+
PrecisionError: not enough precision to be sure that this element is a nth power
|
|
3601
|
+
|
|
3602
|
+
Check that :issue:`30314` is fixed::
|
|
3603
|
+
|
|
3604
|
+
sage: # needs sage.libs.ntl
|
|
3605
|
+
sage: K = Qp(29)
|
|
3606
|
+
sage: x = polygen(K)
|
|
3607
|
+
sage: L.<a> = K.extension(x^2 - 29)
|
|
3608
|
+
sage: L(4).nth_root(2)
|
|
3609
|
+
2 + O(a^40)
|
|
3610
|
+
|
|
3611
|
+
TESTS:
|
|
3612
|
+
|
|
3613
|
+
We check that it works over different fields::
|
|
3614
|
+
|
|
3615
|
+
sage: # needs sage.libs.ntl
|
|
3616
|
+
sage: K.<a> = Qq(2^3)
|
|
3617
|
+
sage: S.<x> = K[]
|
|
3618
|
+
sage: L.<pi> = K.extension(x^2 + 2*x + 2)
|
|
3619
|
+
sage: elt = L.random_element()
|
|
3620
|
+
sage: elt in (elt^8).nth_root(8, all=True)
|
|
3621
|
+
True
|
|
3622
|
+
sage: elt = L.random_element()
|
|
3623
|
+
sage: elt in (elt^16).nth_root(16, all=True)
|
|
3624
|
+
True
|
|
3625
|
+
sage: elt = L.random_element()
|
|
3626
|
+
sage: elt in (elt^56).nth_root(56, all=True)
|
|
3627
|
+
True
|
|
3628
|
+
|
|
3629
|
+
sage: # needs sage.libs.ntl
|
|
3630
|
+
sage: K.<a> = Qq(3^2)
|
|
3631
|
+
sage: S.<x> = K[]
|
|
3632
|
+
sage: Z = (1+x)^3
|
|
3633
|
+
sage: E = Z^2 + Z + 1
|
|
3634
|
+
sage: L.<pi> = K.extension(E)
|
|
3635
|
+
sage: elt = L.random_element()
|
|
3636
|
+
sage: elt in (elt^9).nth_root(9, all=True)
|
|
3637
|
+
True
|
|
3638
|
+
sage: elt = L.random_element()
|
|
3639
|
+
sage: elt in (elt^27).nth_root(27, all=True)
|
|
3640
|
+
True
|
|
3641
|
+
sage: elt = L.random_element()
|
|
3642
|
+
sage: elt in (elt^108).nth_root(108, all=True)
|
|
3643
|
+
True
|
|
3644
|
+
|
|
3645
|
+
sage: # needs sage.libs.flint sage.libs.ntl
|
|
3646
|
+
sage: K.<a> = ZqCA(3^2)
|
|
3647
|
+
sage: S.<x> = K[]
|
|
3648
|
+
sage: Z = (1+x)^3 + 3*x^2
|
|
3649
|
+
sage: E = Z^2 + Z + 1
|
|
3650
|
+
sage: L.<pi> = K.extension(E)
|
|
3651
|
+
sage: elt = L.random_element()
|
|
3652
|
+
sage: elt in (elt^9).nth_root(9, all=True)
|
|
3653
|
+
True
|
|
3654
|
+
sage: elt = L.random_element()
|
|
3655
|
+
sage: try: # needs sage.rings.real_double
|
|
3656
|
+
....: assert elt in (elt^27).nth_root(27, all=True)
|
|
3657
|
+
....: except sage.rings.padics.precision_error.PrecisionError:
|
|
3658
|
+
....: pass
|
|
3659
|
+
sage: elt = L.random_element()
|
|
3660
|
+
sage: try: # needs sage.rings.real_double
|
|
3661
|
+
....: assert elt in (elt^108).nth_root(108, all=True)
|
|
3662
|
+
....: except sage.rings.padics.precision_error.PrecisionError:
|
|
3663
|
+
....: pass
|
|
3664
|
+
|
|
3665
|
+
sage: # needs sage.libs.ntl
|
|
3666
|
+
sage: K.<a> = Qq(3^2)
|
|
3667
|
+
sage: S.<x> = K[]
|
|
3668
|
+
sage: Z = (1+x)^3 + 3*x^3
|
|
3669
|
+
sage: E = (Z^2 + Z + 1)(a*x).monic()
|
|
3670
|
+
sage: L.<pi> = K.extension(E)
|
|
3671
|
+
sage: elt = L.random_element()
|
|
3672
|
+
sage: elt in (elt^9).nth_root(9, all=True)
|
|
3673
|
+
True
|
|
3674
|
+
sage: elt = L.random_element()
|
|
3675
|
+
sage: elt in (elt^27).nth_root(27, all=True)
|
|
3676
|
+
True
|
|
3677
|
+
sage: elt = L.random_element()
|
|
3678
|
+
sage: elt in (elt^108).nth_root(108, all=True)
|
|
3679
|
+
True
|
|
3680
|
+
"""
|
|
3681
|
+
n = ZZ(n)
|
|
3682
|
+
if n == 0:
|
|
3683
|
+
raise ValueError("n must be a nonzero integer")
|
|
3684
|
+
elif n == 1:
|
|
3685
|
+
return self
|
|
3686
|
+
elif n < 0:
|
|
3687
|
+
return (~self).nth_root(-n)
|
|
3688
|
+
parent = self.parent()
|
|
3689
|
+
K = parent.fraction_field() # due to conversion issues
|
|
3690
|
+
p = parent.prime()
|
|
3691
|
+
e = parent.absolute_e()
|
|
3692
|
+
ep = e // (p-1)
|
|
3693
|
+
|
|
3694
|
+
# We first check trivial cases
|
|
3695
|
+
if self._is_exact_zero():
|
|
3696
|
+
return self
|
|
3697
|
+
if self.is_zero():
|
|
3698
|
+
raise PrecisionError("not enough precision to be sure that this element is a nth power")
|
|
3699
|
+
|
|
3700
|
+
v = n.valuation(p)
|
|
3701
|
+
m = n // (p**v)
|
|
3702
|
+
|
|
3703
|
+
# We check the valuation
|
|
3704
|
+
val = self.valuation()
|
|
3705
|
+
if val % n != 0:
|
|
3706
|
+
raise ValueError("this element is not a nth power")
|
|
3707
|
+
# and the residue
|
|
3708
|
+
a = K(self) >> val
|
|
3709
|
+
abar = a.residue()
|
|
3710
|
+
try:
|
|
3711
|
+
xbar = abar.nth_root(m)
|
|
3712
|
+
except ValueError:
|
|
3713
|
+
raise ValueError("this element is not a nth power")
|
|
3714
|
+
|
|
3715
|
+
# We take the inverse mth root at small precision
|
|
3716
|
+
prec = a.precision_absolute()
|
|
3717
|
+
minprec = v*e + ep + 1
|
|
3718
|
+
if m == 1:
|
|
3719
|
+
parity = 0
|
|
3720
|
+
root = a.add_bigoh(minprec)
|
|
3721
|
+
else:
|
|
3722
|
+
parity = 1
|
|
3723
|
+
root = K(~xbar)
|
|
3724
|
+
invm = K(1/m)
|
|
3725
|
+
curprec = 1
|
|
3726
|
+
while curprec < min(minprec,prec):
|
|
3727
|
+
curprec *= 2
|
|
3728
|
+
root = root.lift_to_precision(min(minprec,prec,curprec))
|
|
3729
|
+
root += invm * root * (1 - a*(root**m))
|
|
3730
|
+
|
|
3731
|
+
# We now extract the `(p^v)`-th root
|
|
3732
|
+
zeta, s, nextzeta = K._primitive_qth_root_of_unity(v)
|
|
3733
|
+
if v:
|
|
3734
|
+
nextzeta = (parent(nextzeta[0]), nextzeta[1]) # nextzeta[0] may have a wrong parent (with more precision)
|
|
3735
|
+
for i in range(v):
|
|
3736
|
+
if s > 0 and i >= s:
|
|
3737
|
+
root, accuracy = root._inverse_pth_root(twist=zeta, hint=nextzeta)
|
|
3738
|
+
else:
|
|
3739
|
+
root, accuracy = root._inverse_pth_root()
|
|
3740
|
+
if accuracy is not infinity and accuracy is not None:
|
|
3741
|
+
raise ValueError("this element is not a nth power")
|
|
3742
|
+
|
|
3743
|
+
# We check the precision
|
|
3744
|
+
if v > 0 and prec < minprec:
|
|
3745
|
+
raise PrecisionError("not enough precision to be sure that this element is a nth power")
|
|
3746
|
+
|
|
3747
|
+
# We lift the root using Newton iteration
|
|
3748
|
+
if v % 2 == parity:
|
|
3749
|
+
root = ~root
|
|
3750
|
+
invn = K(1/n)
|
|
3751
|
+
curprec = minprec
|
|
3752
|
+
while curprec < prec:
|
|
3753
|
+
curprec -= v*e
|
|
3754
|
+
curprec = min(2*curprec + v*e, p*curprec + (v-1)*e)
|
|
3755
|
+
root = root.lift_to_precision(min(prec,curprec))
|
|
3756
|
+
root += invn * root * (1 - a*(root**n))
|
|
3757
|
+
root = (~root) << (val // n)
|
|
3758
|
+
|
|
3759
|
+
if all:
|
|
3760
|
+
return [ parent(root*zeta) for zeta in K.roots_of_unity(n) ]
|
|
3761
|
+
else:
|
|
3762
|
+
return parent(root)
|
|
3763
|
+
|
|
3764
|
+
def _inverse_pth_root(self, twist=None, hint=None):
|
|
3765
|
+
r"""
|
|
3766
|
+
In its simplest form, computes the inverse of
|
|
3767
|
+
``p``-th root of this element.
|
|
3768
|
+
|
|
3769
|
+
This is a helper function used in :meth:`nth_root`
|
|
3770
|
+
and :meth:`primitive_root_of_unity`.
|
|
3771
|
+
|
|
3772
|
+
INPUT:
|
|
3773
|
+
|
|
3774
|
+
- ``twist`` -- an element in the same parent or ``None``
|
|
3775
|
+
(default: ``None``)
|
|
3776
|
+
|
|
3777
|
+
- ``hint`` -- tuple or ``None`` (default: ``None``); if not
|
|
3778
|
+
``None``, it has to be the output of ``twist._inverse_pth_root()``
|
|
3779
|
+
|
|
3780
|
+
OUTPUT:
|
|
3781
|
+
|
|
3782
|
+
When ``twist`` is ``None``, the output is a couple
|
|
3783
|
+
``(invroot, accuracy)`` where:
|
|
3784
|
+
|
|
3785
|
+
- ``accuracy`` is the highest valuation of an element of
|
|
3786
|
+
the form ``self * x^p - 1`` for `x` varying in the
|
|
3787
|
+
parent of this element, and
|
|
3788
|
+
|
|
3789
|
+
- ``invroot`` is an element realizing this maximum.
|
|
3790
|
+
|
|
3791
|
+
If the precision on the element is not enough to determine
|
|
3792
|
+
``accuracy``, the value ``None`` is returned.
|
|
3793
|
+
|
|
3794
|
+
When ``twist`` is not ``None``, the maximum is taken over
|
|
3795
|
+
all elements of the form ``self * x^p * twist^i - 1`` for
|
|
3796
|
+
for `x` varying in the parent of this element and `i`
|
|
3797
|
+
varying in the range `\{0, 1, \ldots, p-1\}`
|
|
3798
|
+
|
|
3799
|
+
.. NOTE::
|
|
3800
|
+
|
|
3801
|
+
This function assumes that the input element and ``twist``
|
|
3802
|
+
(if given) are units in the integer ring.
|
|
3803
|
+
|
|
3804
|
+
TESTS::
|
|
3805
|
+
|
|
3806
|
+
sage: R = Zp(11)
|
|
3807
|
+
sage: [ R.teichmuller(x).nth_root(11) == R.teichmuller(x) for x in range(1,11) ] # indirect doctest
|
|
3808
|
+
[True, True, True, True, True, True, True, True, True, True]
|
|
3809
|
+
|
|
3810
|
+
sage: # needs sage.libs.ntl
|
|
3811
|
+
sage: W.<a> = Zq(5^3)
|
|
3812
|
+
sage: S.<x> = W[]
|
|
3813
|
+
sage: R.<pi> = W.extension(x^8 + 15*a*x - 5)
|
|
3814
|
+
sage: y = R.random_element()
|
|
3815
|
+
sage: for n in [5, 10, 15]: # indirect doctest
|
|
3816
|
+
....: z = y**n
|
|
3817
|
+
....: assert z.nth_root(n)**n == z
|
|
3818
|
+
"""
|
|
3819
|
+
ring = self.parent()
|
|
3820
|
+
p = ring.prime()
|
|
3821
|
+
e = ring.absolute_e()
|
|
3822
|
+
ep = e // (p-1)
|
|
3823
|
+
|
|
3824
|
+
if twist is None:
|
|
3825
|
+
accuracy = None
|
|
3826
|
+
else:
|
|
3827
|
+
if hint is None:
|
|
3828
|
+
invroottwist, accuracy = twist._inverse_pth_root()
|
|
3829
|
+
else:
|
|
3830
|
+
invroottwist, accuracy = hint
|
|
3831
|
+
if accuracy is None:
|
|
3832
|
+
raise NotImplementedError("try to increase the precision cap of the parent...")
|
|
3833
|
+
|
|
3834
|
+
a = self
|
|
3835
|
+
prec = a.precision_absolute()
|
|
3836
|
+
|
|
3837
|
+
# We will need 1/a at higher precision
|
|
3838
|
+
ainv = ~(a.add_bigoh(e+ep+1))
|
|
3839
|
+
|
|
3840
|
+
# We lift modulo pi^(e // (p-1))
|
|
3841
|
+
k = ring.residue_field()
|
|
3842
|
+
x = ring(0)
|
|
3843
|
+
curprec = 0 # curprec is the valuation of (ainv - x^p)
|
|
3844
|
+
while curprec < min(prec, e+ep):
|
|
3845
|
+
# recomputing x^p is not necessary:
|
|
3846
|
+
# we can alternatively update it after each update of x
|
|
3847
|
+
# (which is theoretically a bit faster)
|
|
3848
|
+
b = ainv - x**p
|
|
3849
|
+
if b == 0: break
|
|
3850
|
+
curprec = b.valuation()
|
|
3851
|
+
bexp = iter(b.unit_part().expansion())
|
|
3852
|
+
maxprec = prec
|
|
3853
|
+
while curprec < maxprec:
|
|
3854
|
+
try:
|
|
3855
|
+
coeff = k(next(bexp))
|
|
3856
|
+
except StopIteration:
|
|
3857
|
+
coeff = k(0)
|
|
3858
|
+
if coeff != 0:
|
|
3859
|
+
if curprec % p == 0:
|
|
3860
|
+
cbar = coeff.nth_root(p)
|
|
3861
|
+
c = ring(cbar).lift_to_precision()
|
|
3862
|
+
exponent = curprec // p
|
|
3863
|
+
x += c << exponent
|
|
3864
|
+
maxprec = min(maxprec, exponent + e)
|
|
3865
|
+
elif accuracy == curprec:
|
|
3866
|
+
alpha = (twist * invroottwist.add_bigoh(1 + curprec // p)**p - 1) >> curprec
|
|
3867
|
+
exponent = coeff / (ainv.residue() * alpha.residue())
|
|
3868
|
+
try:
|
|
3869
|
+
exponent = ZZ(exponent)
|
|
3870
|
+
except TypeError:
|
|
3871
|
+
return x, curprec
|
|
3872
|
+
else:
|
|
3873
|
+
ainv //= twist**exponent
|
|
3874
|
+
a *= twist**exponent
|
|
3875
|
+
x *= invroottwist**exponent
|
|
3876
|
+
break
|
|
3877
|
+
else:
|
|
3878
|
+
return x, curprec
|
|
3879
|
+
curprec += 1
|
|
3880
|
+
|
|
3881
|
+
# We check if the precision was enough
|
|
3882
|
+
# We didn't do it before because we could have proved
|
|
3883
|
+
# that there is no pth root in the previous step.
|
|
3884
|
+
if prec < e + ep + 1:
|
|
3885
|
+
x = x.add_bigoh((prec+p-1) // p)
|
|
3886
|
+
return x, None
|
|
3887
|
+
|
|
3888
|
+
# We lift one step further
|
|
3889
|
+
curprec = e + ep
|
|
3890
|
+
if e % (p-1) == 0:
|
|
3891
|
+
rho = k(ring(p).expansion(e))
|
|
3892
|
+
b = ainv - x**p
|
|
3893
|
+
b >>= curprec
|
|
3894
|
+
coeff = -a.residue()*b.residue()
|
|
3895
|
+
if accuracy == curprec:
|
|
3896
|
+
sigma = rho * (-rho).nth_root(p-1) # should never fail
|
|
3897
|
+
alpha = (twist * invroottwist.add_bigoh(ep+1)**p - 1) >> curprec
|
|
3898
|
+
alpha = alpha.residue()
|
|
3899
|
+
tr = (alpha/sigma).trace()
|
|
3900
|
+
if tr != 0:
|
|
3901
|
+
exponent = ZZ(-(coeff/sigma).trace() / tr)
|
|
3902
|
+
coeff += exponent*alpha
|
|
3903
|
+
ainv //= twist**exponent
|
|
3904
|
+
a *= twist**exponent
|
|
3905
|
+
x *= invroottwist**exponent
|
|
3906
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
3907
|
+
S = PolynomialRing(k, name='x')
|
|
3908
|
+
AS = S([ coeff, rho ] + (p-2)*[0] + [1])
|
|
3909
|
+
roots = AS.roots()
|
|
3910
|
+
if len(roots) == 0:
|
|
3911
|
+
return x, curprec
|
|
3912
|
+
x += ring(roots[0][0] * x.residue()) << ep
|
|
3913
|
+
|
|
3914
|
+
# We perform Newton iteration
|
|
3915
|
+
curprec += 1
|
|
3916
|
+
while curprec < prec:
|
|
3917
|
+
curprec -= e
|
|
3918
|
+
curprec = min(2*curprec + e, p*curprec)
|
|
3919
|
+
x = x.lift_to_precision(min(prec,curprec))
|
|
3920
|
+
x += x * (1 - a*x**p) / p
|
|
3921
|
+
|
|
3922
|
+
return x, infinity
|
|
3923
|
+
|
|
3924
|
+
def __abs__(self):
|
|
3925
|
+
"""
|
|
3926
|
+
Return the `p`-adic absolute value of ``self``.
|
|
3927
|
+
|
|
3928
|
+
This is normalized so that the absolute value of `p` is `1/p`.
|
|
3929
|
+
|
|
3930
|
+
EXAMPLES::
|
|
3931
|
+
|
|
3932
|
+
sage: abs(Qp(5)(15))
|
|
3933
|
+
1/5
|
|
3934
|
+
sage: abs(Qp(7)(0))
|
|
3935
|
+
0
|
|
3936
|
+
|
|
3937
|
+
An unramified extension::
|
|
3938
|
+
|
|
3939
|
+
sage: # needs sage.libs.ntl
|
|
3940
|
+
sage: R = Zp(5,5)
|
|
3941
|
+
sage: P.<x> = PolynomialRing(R)
|
|
3942
|
+
sage: Z25.<u> = R.ext(x^2 - 3)
|
|
3943
|
+
sage: abs(u)
|
|
3944
|
+
1
|
|
3945
|
+
sage: abs(u^24-1)
|
|
3946
|
+
1/5
|
|
3947
|
+
|
|
3948
|
+
A ramified extension::
|
|
3949
|
+
|
|
3950
|
+
sage: # needs sage.libs.ntl
|
|
3951
|
+
sage: W.<w> = R.ext(x^5 + 75*x^3 - 15*x^2 + 125*x - 5)
|
|
3952
|
+
sage: abs(w)
|
|
3953
|
+
0.724779663677696
|
|
3954
|
+
sage: abs(W(0))
|
|
3955
|
+
0.000000000000000
|
|
3956
|
+
"""
|
|
3957
|
+
return self.abs()
|
|
3958
|
+
|
|
3959
|
+
cpdef abs(self, prec=None):
|
|
3960
|
+
"""
|
|
3961
|
+
Return the `p`-adic absolute value of ``self``.
|
|
3962
|
+
|
|
3963
|
+
This is normalized so that the absolute value of `p` is `1/p`.
|
|
3964
|
+
|
|
3965
|
+
INPUT:
|
|
3966
|
+
|
|
3967
|
+
- ``prec`` -- integer; the precision of the real field in which
|
|
3968
|
+
the answer is returned. If ``None``, returns a rational for
|
|
3969
|
+
absolutely unramified fields, or a real with 53 bits of
|
|
3970
|
+
precision for ramified fields.
|
|
3971
|
+
|
|
3972
|
+
EXAMPLES::
|
|
3973
|
+
|
|
3974
|
+
sage: a = Qp(5)(15); a.abs()
|
|
3975
|
+
1/5
|
|
3976
|
+
sage: a.abs(53) # needs sage.rings.real_mpfr
|
|
3977
|
+
0.200000000000000
|
|
3978
|
+
sage: Qp(7)(0).abs()
|
|
3979
|
+
0
|
|
3980
|
+
sage: Qp(7)(0).abs(prec=20) # needs sage.rings.real_mpfr
|
|
3981
|
+
0.00000
|
|
3982
|
+
|
|
3983
|
+
An unramified extension::
|
|
3984
|
+
|
|
3985
|
+
sage: # needs sage.libs.ntl
|
|
3986
|
+
sage: R = Zp(5,5)
|
|
3987
|
+
sage: P.<x> = PolynomialRing(R)
|
|
3988
|
+
sage: Z25.<u> = R.ext(x^2 - 3)
|
|
3989
|
+
sage: u.abs()
|
|
3990
|
+
1
|
|
3991
|
+
sage: (u^24-1).abs()
|
|
3992
|
+
1/5
|
|
3993
|
+
|
|
3994
|
+
A ramified extension::
|
|
3995
|
+
|
|
3996
|
+
sage: # needs sage.libs.ntl
|
|
3997
|
+
sage: W.<w> = R.ext(x^5 + 75*x^3 - 15*x^2 + 125*x - 5)
|
|
3998
|
+
sage: w.abs()
|
|
3999
|
+
0.724779663677696
|
|
4000
|
+
sage: W(0).abs()
|
|
4001
|
+
0.000000000000000
|
|
4002
|
+
"""
|
|
4003
|
+
K = self.parent()
|
|
4004
|
+
if not prec and K.absolute_e() > 1:
|
|
4005
|
+
prec = 53
|
|
4006
|
+
if prec:
|
|
4007
|
+
from sage.rings.real_mpfr import RealField
|
|
4008
|
+
if self.is_zero():
|
|
4009
|
+
return RealField(prec).zero()
|
|
4010
|
+
return RealField(prec)(K.prime())**(-self.ordp())
|
|
4011
|
+
else:
|
|
4012
|
+
if self.is_zero():
|
|
4013
|
+
return Rational(0)
|
|
4014
|
+
return Rational(K.prime())**(-self.valuation())
|
|
4015
|
+
|
|
4016
|
+
cpdef bint _is_base_elt(self, p) except -1:
|
|
4017
|
+
r"""
|
|
4018
|
+
Return ``True`` if this element is an element of `\ZZ_p` or `\QQ_p` (rather than
|
|
4019
|
+
an extension).
|
|
4020
|
+
|
|
4021
|
+
INPUT:
|
|
4022
|
+
|
|
4023
|
+
- ``p`` -- a prime, which is compared with the parent of this element
|
|
4024
|
+
|
|
4025
|
+
EXAMPLES::
|
|
4026
|
+
|
|
4027
|
+
sage: a = Zp(5)(3); a._is_base_elt(5)
|
|
4028
|
+
True
|
|
4029
|
+
sage: a._is_base_elt(17)
|
|
4030
|
+
False
|
|
4031
|
+
"""
|
|
4032
|
+
raise NotImplementedError
|
|
4033
|
+
|
|
4034
|
+
def _polylog_res_1(self, n, p_branch=0):
|
|
4035
|
+
r"""
|
|
4036
|
+
Return `Li_n(`self`)`, the `n`-th `p`-adic polylogarithm of ``self``,
|
|
4037
|
+
assuming that ``self`` is congruent to `1 \pmod p`.
|
|
4038
|
+
|
|
4039
|
+
This is an internal function, used by :meth:`polylog`.
|
|
4040
|
+
|
|
4041
|
+
INPUT:
|
|
4042
|
+
|
|
4043
|
+
- ``n`` -- nonnegative integer
|
|
4044
|
+
|
|
4045
|
+
OUTPUT: `Li_n(`self`)`
|
|
4046
|
+
|
|
4047
|
+
EXAMPLES::
|
|
4048
|
+
|
|
4049
|
+
sage: Qp(2)(-1)._polylog_res_1(6) == 0 # needs sage.symbolic
|
|
4050
|
+
True
|
|
4051
|
+
|
|
4052
|
+
sage: Qp(5)(1)._polylog_res_1(1)
|
|
4053
|
+
Traceback (most recent call last):
|
|
4054
|
+
...
|
|
4055
|
+
ValueError: Polylogarithm is not defined for 1.
|
|
4056
|
+
|
|
4057
|
+
Only polylogarithms for `n` at least two are defined by this function ::
|
|
4058
|
+
|
|
4059
|
+
sage: Qp(11)(2)._polylog_res_1(1)
|
|
4060
|
+
Traceback (most recent call last):
|
|
4061
|
+
...
|
|
4062
|
+
ValueError: Polylogarithm only implemented for n at least 2.
|
|
4063
|
+
"""
|
|
4064
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
4065
|
+
from sage.arith.misc import integer_ceil as ceil, integer_floor as floor
|
|
4066
|
+
from sage.rings.padics.factory import Qp
|
|
4067
|
+
from sage.misc.verbose import verbose
|
|
4068
|
+
|
|
4069
|
+
if self == 1:
|
|
4070
|
+
raise ValueError('Polylogarithm is not defined for 1.')
|
|
4071
|
+
if n <= 1:
|
|
4072
|
+
raise ValueError('Polylogarithm only implemented for n at least 2.')
|
|
4073
|
+
|
|
4074
|
+
p = self.parent().prime()
|
|
4075
|
+
prec = self.precision_absolute()
|
|
4076
|
+
|
|
4077
|
+
K = self.parent().fraction_field()
|
|
4078
|
+
z = K(self)
|
|
4079
|
+
|
|
4080
|
+
hsl = max(prec / ((z - 1).valuation()) + 1, prec*(p == 2), 2)
|
|
4081
|
+
N = floor(prec - n*(hsl - 1).log(p).n())
|
|
4082
|
+
|
|
4083
|
+
verbose(hsl, level=3)
|
|
4084
|
+
|
|
4085
|
+
def bound(m):
|
|
4086
|
+
return prec - m + Integer(1-2**(m-1)).valuation(p) - m*(hsl - 1).log(p).n()
|
|
4087
|
+
|
|
4088
|
+
gsl = max(_findprec(1/(p-1), 1, _polylog_c(m,p) + bound(m), p) for m in range(2,n+1))
|
|
4089
|
+
gsl = max(gsl, 2)
|
|
4090
|
+
verbose(gsl, level=3)
|
|
4091
|
+
g = _compute_g(p, n, max(bound(m) + m*floor((gsl-1).log(p).n()) for m in range(2, n+1)), gsl)
|
|
4092
|
+
verbose(g, level=3)
|
|
4093
|
+
S = PowerSeriesRing(K, default_prec = ceil(hsl), names='t')
|
|
4094
|
+
t = S.gen()
|
|
4095
|
+
log1plust = (1+t).log()
|
|
4096
|
+
log1plusti = 1
|
|
4097
|
+
|
|
4098
|
+
G = (n+1)*[0]
|
|
4099
|
+
for i in range(n+1):
|
|
4100
|
+
G[i] = (log1plusti)/Integer(i).factorial()
|
|
4101
|
+
log1plusti *= log1plust
|
|
4102
|
+
|
|
4103
|
+
verbose(G, level=3)
|
|
4104
|
+
|
|
4105
|
+
H = (n+1)*[0]
|
|
4106
|
+
H[2] = -sum([((-t)**i)/i**2 for i in srange(1,hsl+2)])
|
|
4107
|
+
for i in range(2, n):
|
|
4108
|
+
H[i+1] = (H[i]/(1+t) + G[i]/t).integral()
|
|
4109
|
+
if (i + 1) % 2 == 1:
|
|
4110
|
+
if p != 2:
|
|
4111
|
+
H[i+1] += (2**i*p**(i+1)*g[i+1](1/K(2)))/((1-2**i)*(p**(i+1) - 1))
|
|
4112
|
+
else:
|
|
4113
|
+
H[i+1] += (2**i*H[i+1](K(-2)))/(1 - 2**(i+1))
|
|
4114
|
+
|
|
4115
|
+
verbose(H, level=3)
|
|
4116
|
+
return (H[n](z - 1) - ((z.log(p_branch))**(n-1)*(1 - z).log(p_branch))/Integer(n-1).factorial()).add_bigoh(N)
|
|
4117
|
+
|
|
4118
|
+
def polylog(self, n, p_branch=0):
|
|
4119
|
+
r"""
|
|
4120
|
+
Return `Li_n(\mathrm{self})`, the `n`-th `p`-adic polylogarithm
|
|
4121
|
+
of this element.
|
|
4122
|
+
|
|
4123
|
+
INPUT:
|
|
4124
|
+
|
|
4125
|
+
- ``n`` -- nonnegative integer
|
|
4126
|
+
- ``p_branch`` -- an element in the base ring or its fraction
|
|
4127
|
+
field; the implementation will choose the branch of the
|
|
4128
|
+
logarithm which sends `p` to ``p_branch``
|
|
4129
|
+
|
|
4130
|
+
EXAMPLES:
|
|
4131
|
+
|
|
4132
|
+
The `n`-th polylogarithm of `-1` is `0` for even `n`::
|
|
4133
|
+
|
|
4134
|
+
sage: Qp(13)(-1).polylog(6) == 0 # needs sage.rings.real_mpfr sage.symbolic
|
|
4135
|
+
True
|
|
4136
|
+
|
|
4137
|
+
We can check some identities, for example those mentioned in [DCW2016]_::
|
|
4138
|
+
|
|
4139
|
+
sage: x = Qp(7, prec=30)(1/3)
|
|
4140
|
+
sage: (x^2).polylog(4) - 8*x.polylog(4) - 8*(-x).polylog(4) == 0 # needs sage.symbolic
|
|
4141
|
+
True
|
|
4142
|
+
|
|
4143
|
+
::
|
|
4144
|
+
|
|
4145
|
+
sage: x = Qp(5, prec=30)(4)
|
|
4146
|
+
sage: x.polylog(2) + (1/x).polylog(2) + x.log(0)**2/2 == 0 # needs sage.symbolic
|
|
4147
|
+
True
|
|
4148
|
+
|
|
4149
|
+
::
|
|
4150
|
+
|
|
4151
|
+
sage: x = Qp(11, prec=30)(2)
|
|
4152
|
+
sage: x.polylog(2) + (1-x).polylog(2) + x.log(0)**2*(1-x).log(0) == 0 # needs sage.symbolic
|
|
4153
|
+
True
|
|
4154
|
+
|
|
4155
|
+
`Li_1(z) = -\log(1-z)` for `|z| < 1`::
|
|
4156
|
+
|
|
4157
|
+
sage: Qp(5)(10).polylog(1) == -Qp(5)(1-10).log(0)
|
|
4158
|
+
True
|
|
4159
|
+
|
|
4160
|
+
The dilogarithm of 1 is zero::
|
|
4161
|
+
|
|
4162
|
+
sage: Qp(5)(1).polylog(2) # needs sage.rings.real_mpfr sage.symbolic
|
|
4163
|
+
O(5^20)
|
|
4164
|
+
|
|
4165
|
+
The cubing relation holds for the trilogarithm at 1::
|
|
4166
|
+
|
|
4167
|
+
sage: K = Qp(7)
|
|
4168
|
+
sage: z = K.zeta(3)
|
|
4169
|
+
sage: -8*K(1).polylog(3) == 9*(K(z).polylog(3) + K(z^2).polylog(3)) # needs sage.rings.padics sage.rings.real_mpfr sage.symbolic
|
|
4170
|
+
True
|
|
4171
|
+
|
|
4172
|
+
The polylogarithm of 0 is 0::
|
|
4173
|
+
|
|
4174
|
+
sage: Qp(11)(0).polylog(7)
|
|
4175
|
+
0
|
|
4176
|
+
|
|
4177
|
+
Only polylogarithms for positive `n` are defined::
|
|
4178
|
+
|
|
4179
|
+
sage: Qp(11)(2).polylog(-1)
|
|
4180
|
+
Traceback (most recent call last):
|
|
4181
|
+
...
|
|
4182
|
+
ValueError: polylogarithm only implemented for n at least 0
|
|
4183
|
+
|
|
4184
|
+
Check that :issue:`29222` is fixed::
|
|
4185
|
+
|
|
4186
|
+
sage: K = Qp(7)
|
|
4187
|
+
sage: print(K(1 + 7^11).polylog(4)) # needs sage.symbolic
|
|
4188
|
+
6*7^14 + 3*7^15 + 7^16 + 7^17 + O(7^18)
|
|
4189
|
+
|
|
4190
|
+
ALGORITHM:
|
|
4191
|
+
|
|
4192
|
+
The algorithm of Besser-de Jeu, as described in [BdJ2008]_ is used.
|
|
4193
|
+
|
|
4194
|
+
AUTHORS:
|
|
4195
|
+
|
|
4196
|
+
- Jennifer Balakrishnan - Initial implementation
|
|
4197
|
+
- Alex J. Best (2017-07-21) - Extended to other residue disks
|
|
4198
|
+
|
|
4199
|
+
.. TODO::
|
|
4200
|
+
|
|
4201
|
+
- Implement for extensions.
|
|
4202
|
+
- Use the change method to create K from ``self.parent()``.
|
|
4203
|
+
"""
|
|
4204
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
4205
|
+
from sage.rings.padics.factory import Qp
|
|
4206
|
+
from sage.misc.verbose import verbose
|
|
4207
|
+
from sage.arith.misc import integer_ceil as ceil, integer_floor as floor
|
|
4208
|
+
from sage.rings.infinity import PlusInfinity
|
|
4209
|
+
|
|
4210
|
+
if self.parent().absolute_degree() != 1:
|
|
4211
|
+
raise NotImplementedError("polylogarithms are not currently implemented for elements of extensions")
|
|
4212
|
+
# TODO implement this (possibly after the change method for padic generic elements is added).
|
|
4213
|
+
if n == 0:
|
|
4214
|
+
return self/(1-self)
|
|
4215
|
+
if n == 1:
|
|
4216
|
+
return -(1-self).log(p_branch)
|
|
4217
|
+
if n < 0:
|
|
4218
|
+
raise ValueError('polylogarithm only implemented for n at least 0')
|
|
4219
|
+
|
|
4220
|
+
prec = self.precision_absolute()
|
|
4221
|
+
|
|
4222
|
+
p = self.parent().prime()
|
|
4223
|
+
K = self.parent().fraction_field()
|
|
4224
|
+
|
|
4225
|
+
z = K(self)
|
|
4226
|
+
n = Integer(n)
|
|
4227
|
+
|
|
4228
|
+
if z.valuation() < 0:
|
|
4229
|
+
verbose("residue oo, using functional equation for reciprocal. %d %s" % (n, str(self)), level=2)
|
|
4230
|
+
return (-1)**(n+1)*(1/z).polylog(n)-(z.log(p_branch)**n)/K(n.factorial())
|
|
4231
|
+
|
|
4232
|
+
zeta = K.teichmuller(z)
|
|
4233
|
+
|
|
4234
|
+
# Which residue disk are we in?
|
|
4235
|
+
if zeta == 0:
|
|
4236
|
+
if z.precision_absolute() == PlusInfinity():
|
|
4237
|
+
return K(0)
|
|
4238
|
+
verbose("residue 0, using series. %d %s" % (n, str(self)), level=2)
|
|
4239
|
+
M = ceil((prec/z.valuation()).log(p).n())
|
|
4240
|
+
N = prec - n*M
|
|
4241
|
+
ret = K(0)
|
|
4242
|
+
for m in range(M + 1):
|
|
4243
|
+
zpm = z**(p**m)
|
|
4244
|
+
ret += p**(-m*n)*sum(zpm**k/Integer(k)**n for k in
|
|
4245
|
+
range(1, _findprec(p**m*z.valuation(), 0, N + n*m, p)) if k % p != 0)
|
|
4246
|
+
|
|
4247
|
+
return ret.add_bigoh(N)
|
|
4248
|
+
|
|
4249
|
+
if zeta == 1:
|
|
4250
|
+
if z == 1:
|
|
4251
|
+
return Integer(2)**(n-1)*K(-1).polylog(n, p_branch=p_branch)/(1-Integer(2)**(n-1))
|
|
4252
|
+
verbose("residue 1, using _polylog_res_1. %d %s" % (n, str(self)), level=2)
|
|
4253
|
+
return self._polylog_res_1(n, p_branch)
|
|
4254
|
+
|
|
4255
|
+
# Set up precision bounds
|
|
4256
|
+
tsl = prec / (z - zeta).valuation() + 1
|
|
4257
|
+
N = floor(prec - n*(tsl - 1).log(p).n())
|
|
4258
|
+
gsl = max(_findprec(1/(p-1), 1, prec - m + _polylog_c(m,p) - m*(tsl - 1).log(p).n(), p) for m in range(1,n+1))
|
|
4259
|
+
gsl = max(gsl,2)
|
|
4260
|
+
|
|
4261
|
+
gtr = _compute_g(p, n, prec + n*(gsl - 1).log(p).n(), gsl)
|
|
4262
|
+
|
|
4263
|
+
K = Qp(p, prec)
|
|
4264
|
+
|
|
4265
|
+
# Residue disk around zeta
|
|
4266
|
+
verbose("general case. %d %s" % (n, str(self)), level=2)
|
|
4267
|
+
Li_i_zeta = [0] + [p**i/(p**i-1)*gtr[i](1/(1-zeta)) for i in range(1,n+1)]
|
|
4268
|
+
|
|
4269
|
+
T = PowerSeriesRing(K, default_prec=ceil(tsl), names='t')
|
|
4270
|
+
t = T.gen()
|
|
4271
|
+
F = (n+1)*[0]
|
|
4272
|
+
F[0] = (zeta+t)/(1-zeta-t)
|
|
4273
|
+
for i in range(n):
|
|
4274
|
+
F[i+1] = Li_i_zeta[i+1] + (F[i]/(zeta + t)).integral()
|
|
4275
|
+
|
|
4276
|
+
return (F[n](z - zeta)).add_bigoh(N)
|
|
4277
|
+
|
|
4278
|
+
|
|
4279
|
+
# Artin-Hasse exponential
|
|
4280
|
+
_AHE_coefficients_cache = {}
|
|
4281
|
+
|
|
4282
|
+
|
|
4283
|
+
def _AHE_coefficients(p, N, prec):
|
|
4284
|
+
r"""
|
|
4285
|
+
Compute the first ``N`` coefficients of the ``p``-adic
|
|
4286
|
+
Artin-Hasse exponential series at precision ``prec``.
|
|
4287
|
+
|
|
4288
|
+
The output is a list of coefficients. The common parent
|
|
4289
|
+
of these coefficients is the ring of ``p``-adic integers
|
|
4290
|
+
with fixed modulus (with some internal precision which
|
|
4291
|
+
could be strictly higher than ``prec``).
|
|
4292
|
+
|
|
4293
|
+
The result is cached.
|
|
4294
|
+
|
|
4295
|
+
EXAMPLES::
|
|
4296
|
+
|
|
4297
|
+
sage: from sage.rings.padics.padic_generic_element import _AHE_coefficients
|
|
4298
|
+
|
|
4299
|
+
sage: L = _AHE_coefficients(101, 10, 3); L
|
|
4300
|
+
[1,
|
|
4301
|
+
1,
|
|
4302
|
+
51 + 50*101 + 50*101^2,
|
|
4303
|
+
17 + 84*101 + 16*101^2,
|
|
4304
|
+
80 + 96*101 + 79*101^2,
|
|
4305
|
+
16 + 100*101 + 15*101^2,
|
|
4306
|
+
70 + 16*101 + 53*101^2,
|
|
4307
|
+
10 + 60*101 + 7*101^2,
|
|
4308
|
+
77 + 32*101 + 89*101^2,
|
|
4309
|
+
31 + 37*101 + 32*101^2]
|
|
4310
|
+
sage: L == [ 1/factorial(i) for i in range(10) ]
|
|
4311
|
+
True
|
|
4312
|
+
|
|
4313
|
+
We check the parent::
|
|
4314
|
+
|
|
4315
|
+
sage: [ elt.parent() for elt in L ]
|
|
4316
|
+
[101-adic Ring of fixed modulus 101^3,
|
|
4317
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4318
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4319
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4320
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4321
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4322
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4323
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4324
|
+
101-adic Ring of fixed modulus 101^3,
|
|
4325
|
+
101-adic Ring of fixed modulus 101^3]
|
|
4326
|
+
|
|
4327
|
+
Sometimes the precision on the result seems to be higher
|
|
4328
|
+
that the requested precision.
|
|
4329
|
+
However, the result is *not* guaranteed to be correct
|
|
4330
|
+
beyond the requested precision::
|
|
4331
|
+
|
|
4332
|
+
sage: L = _AHE_coefficients(2, 513, 1); L # needs sage.symbolic
|
|
4333
|
+
[1,
|
|
4334
|
+
1,
|
|
4335
|
+
1,
|
|
4336
|
+
2 + 2^2 + 2^4 + 2^6 + 2^8,
|
|
4337
|
+
...
|
|
4338
|
+
1 + 2 + 2^2 + 2^5 + 2^8,
|
|
4339
|
+
2^2 + 2^6 + 2^9,
|
|
4340
|
+
1]
|
|
4341
|
+
|
|
4342
|
+
We check that the result is correct modulo `2^1`::
|
|
4343
|
+
|
|
4344
|
+
sage: S.<x> = PowerSeriesRing(QQ, 513)
|
|
4345
|
+
sage: AH = exp(sum(x^(2^i) / 2^i for i in range(10)))
|
|
4346
|
+
sage: R = ZpFM(2, 1)
|
|
4347
|
+
sage: [ R(c) for c in L ] == [ R(c) for c in AH.list() ] # needs sage.rings.padics sage.symbolic
|
|
4348
|
+
True
|
|
4349
|
+
|
|
4350
|
+
But it is not modulo `2^{10}`::
|
|
4351
|
+
|
|
4352
|
+
sage: R = ZpFM(2, 10)
|
|
4353
|
+
sage: [ R(c) for c in L ] == [ R(c) for c in AH.list() ] # needs sage.rings.padics sage.symbolic
|
|
4354
|
+
False
|
|
4355
|
+
"""
|
|
4356
|
+
from sage.rings.padics.factory import ZpFM
|
|
4357
|
+
from sage.arith.misc import integer_floor as floor
|
|
4358
|
+
|
|
4359
|
+
if N < p:
|
|
4360
|
+
internal_prec = prec
|
|
4361
|
+
else:
|
|
4362
|
+
internal_prec = prec + floor((N-1).log()/p.log())
|
|
4363
|
+
if p in _AHE_coefficients_cache:
|
|
4364
|
+
cache_internal_prec, values = _AHE_coefficients_cache[p]
|
|
4365
|
+
else:
|
|
4366
|
+
cache_internal_prec = 0
|
|
4367
|
+
if cache_internal_prec < internal_prec:
|
|
4368
|
+
parent = ZpFM(p, internal_prec)
|
|
4369
|
+
values = [ parent(1) ]
|
|
4370
|
+
for i in range(len(values), N):
|
|
4371
|
+
c = 0
|
|
4372
|
+
dec = 1
|
|
4373
|
+
while dec <= i:
|
|
4374
|
+
c += values[i-dec]
|
|
4375
|
+
dec *= p
|
|
4376
|
+
values.append(c // i)
|
|
4377
|
+
_AHE_coefficients_cache[p] = (internal_prec, values)
|
|
4378
|
+
return values
|
|
4379
|
+
|
|
4380
|
+
|
|
4381
|
+
# Module functions used by polylog
|
|
4382
|
+
def _polylog_c(n, p):
|
|
4383
|
+
"""
|
|
4384
|
+
Return c(n, p) = p/(p-1) - (n-1)/log(p) + (n-1)*log(n*(p-1)/log(p),p) + log(2*p*(p-1)*n/log(p), p)
|
|
4385
|
+
as defined in Prop 6.1 of [BdJ2008]_ which is used as a precision bound.
|
|
4386
|
+
This is an internal function, used by :meth:`polylog`.
|
|
4387
|
+
|
|
4388
|
+
EXAMPLES::
|
|
4389
|
+
|
|
4390
|
+
sage: sage.rings.padics.padic_generic_element._polylog_c(1, 2) # needs sage.symbolic
|
|
4391
|
+
4.52876637294490
|
|
4392
|
+
"""
|
|
4393
|
+
return p/(p-1) - (n-1)/p.log().n() + (n-1)*(n*(p-1)/p.log().n()).log(p).n() + (2*p*(p-1)*n/p.log().n()).log(p).n()
|
|
4394
|
+
|
|
4395
|
+
|
|
4396
|
+
def _findprec(c_1, c_2, c_3, p):
|
|
4397
|
+
r"""
|
|
4398
|
+
Return an integer k such that c_1*k - c_2*log_p(k) > c_3.
|
|
4399
|
+
This is an internal function, used by :meth:`polylog`.
|
|
4400
|
+
|
|
4401
|
+
INPUT:
|
|
4402
|
+
|
|
4403
|
+
- `c_1`, `c_2`, `c_3` -- positive integers
|
|
4404
|
+
- ``p`` -- prime
|
|
4405
|
+
|
|
4406
|
+
OUTPUT:
|
|
4407
|
+
|
|
4408
|
+
``sl`` such that `kc_1 - c_2 \log_p(k) > c_3` for all `k \ge sl`
|
|
4409
|
+
|
|
4410
|
+
EXAMPLES::
|
|
4411
|
+
|
|
4412
|
+
sage: sage.rings.padics.padic_generic_element._findprec(1, 1, 2, 2) # needs sage.rings.real_double sage.rings.real_mpfr sage.symbolic
|
|
4413
|
+
5
|
|
4414
|
+
sage: 5*1 - 5*log(1, 2) > 2
|
|
4415
|
+
True
|
|
4416
|
+
|
|
4417
|
+
See Remark 7.11 of [BdJ2008]_.
|
|
4418
|
+
"""
|
|
4419
|
+
from sage.arith.misc import integer_ceil as ceil
|
|
4420
|
+
|
|
4421
|
+
k = Integer(max(ceil(c_2/c_1), 2))
|
|
4422
|
+
while True:
|
|
4423
|
+
if c_1*k - c_2*k.log(p).n() > c_3:
|
|
4424
|
+
return k
|
|
4425
|
+
k += 1
|
|
4426
|
+
|
|
4427
|
+
|
|
4428
|
+
def _compute_g(p, n, prec, terms):
|
|
4429
|
+
r"""
|
|
4430
|
+
Return the list of power series `g_i = \int(-g_{i-1}/(v-v^2))` used in the computation of polylogarithms.
|
|
4431
|
+
|
|
4432
|
+
This is an internal function, used by :meth:`polylog`.
|
|
4433
|
+
|
|
4434
|
+
EXAMPLES::
|
|
4435
|
+
|
|
4436
|
+
sage: sage.rings.padics.padic_generic_element._compute_g(7, 3, 3, 3)[0] # needs sage.libs.ntl sage.rings.real_double
|
|
4437
|
+
O(7^3)*v^2 + (1 + O(7^3))*v + O(7^3)
|
|
4438
|
+
"""
|
|
4439
|
+
from sage.rings.power_series_ring import PowerSeriesRing
|
|
4440
|
+
from sage.arith.misc import integer_ceil as ceil
|
|
4441
|
+
from sage.rings.padics.factory import Qp
|
|
4442
|
+
|
|
4443
|
+
# Compute the sequence of power series g
|
|
4444
|
+
R = PowerSeriesRing(Qp(p, ceil(prec)), default_prec=terms, names='v')
|
|
4445
|
+
v = R.gen()
|
|
4446
|
+
g = (n+1)*[0]
|
|
4447
|
+
g[0] = v - 1 - ((v-1)**p)/(v**p-(v-1)**p)
|
|
4448
|
+
for i in range(n):
|
|
4449
|
+
g[i+1] = -(g[i]/(v-v**2)).integral()
|
|
4450
|
+
return [x.truncate(terms) for x in g]
|
|
4451
|
+
|
|
4452
|
+
|
|
4453
|
+
cpdef dwork_mahler_coeffs(R, int bd=20):
|
|
4454
|
+
r"""
|
|
4455
|
+
Compute Dwork's formula for Mahler coefficients of `p`-adic Gamma.
|
|
4456
|
+
|
|
4457
|
+
This is called internally when one computes Gamma for a `p`-adic
|
|
4458
|
+
integer. Normally there is no need to call it directly.
|
|
4459
|
+
|
|
4460
|
+
INPUT:
|
|
4461
|
+
|
|
4462
|
+
- ``R`` -- `p`-adic ring in which to compute
|
|
4463
|
+
- ``bd`` -- integer; number of terms in the expansion to use
|
|
4464
|
+
|
|
4465
|
+
OUTPUT: a list of `p`-adic integers
|
|
4466
|
+
|
|
4467
|
+
EXAMPLES::
|
|
4468
|
+
|
|
4469
|
+
sage: from sage.rings.padics.padic_generic_element import dwork_mahler_coeffs, evaluate_dwork_mahler
|
|
4470
|
+
sage: R = Zp(3)
|
|
4471
|
+
sage: v = dwork_mahler_coeffs(R)
|
|
4472
|
+
sage: x = R(1/7)
|
|
4473
|
+
sage: evaluate_dwork_mahler(v, x, 3, 20, 1)
|
|
4474
|
+
2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11
|
|
4475
|
+
+ 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
|
|
4476
|
+
sage: x.dwork_expansion(a=1) # Same result
|
|
4477
|
+
2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11
|
|
4478
|
+
+ 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
|
|
4479
|
+
"""
|
|
4480
|
+
from sage.rings.padics.factory import Qp
|
|
4481
|
+
cdef int i
|
|
4482
|
+
cdef long k, p
|
|
4483
|
+
|
|
4484
|
+
v = [R.one()]
|
|
4485
|
+
p = R.prime()
|
|
4486
|
+
for k in range(1, p):
|
|
4487
|
+
v.append(v[-1] / R(k))
|
|
4488
|
+
if bd > 1:
|
|
4489
|
+
R1 = Qp(p, prec=bd) # Need divisions in this calculation
|
|
4490
|
+
u = [R1(x) for x in v]
|
|
4491
|
+
for i in range(1, bd):
|
|
4492
|
+
u[0] = ((u[-1] + u[0]) / i) >> 1
|
|
4493
|
+
for j in range(1, p):
|
|
4494
|
+
u[j] = (u[j-1] + u[j]) / (j + i * p)
|
|
4495
|
+
for x in u:
|
|
4496
|
+
v.append(R(x << i))
|
|
4497
|
+
return v
|
|
4498
|
+
|
|
4499
|
+
cpdef evaluate_dwork_mahler(v, x, long long p, int bd, long long a):
|
|
4500
|
+
"""
|
|
4501
|
+
Evaluate Dwork's Mahler series for `p`-adic Gamma.
|
|
4502
|
+
|
|
4503
|
+
EXAMPLES::
|
|
4504
|
+
|
|
4505
|
+
sage: from sage.rings.padics.padic_generic_element import dwork_mahler_coeffs, evaluate_dwork_mahler
|
|
4506
|
+
sage: R = Zp(3)
|
|
4507
|
+
sage: v = dwork_mahler_coeffs(R)
|
|
4508
|
+
sage: x = R(1/7)
|
|
4509
|
+
sage: evaluate_dwork_mahler(v, x, 3, 20, 1)
|
|
4510
|
+
2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11
|
|
4511
|
+
+ 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
|
|
4512
|
+
sage: x.dwork_expansion(a=1) # Same result
|
|
4513
|
+
2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11
|
|
4514
|
+
+ 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
|
|
4515
|
+
"""
|
|
4516
|
+
cdef int k
|
|
4517
|
+
bd -= 1
|
|
4518
|
+
a1 = a + bd*p
|
|
4519
|
+
s = v[a1]
|
|
4520
|
+
u = x + bd
|
|
4521
|
+
one = x.parent().one()
|
|
4522
|
+
for k in range(bd):
|
|
4523
|
+
a1 -= p
|
|
4524
|
+
u -= one
|
|
4525
|
+
s = s*u + v[a1]
|
|
4526
|
+
return -s
|
|
4527
|
+
|
|
4528
|
+
cdef long long evaluate_dwork_mahler_long(array.array v, long long x, long long p, int bd,
|
|
4529
|
+
long long a, long long q) noexcept:
|
|
4530
|
+
cdef int k
|
|
4531
|
+
cdef long long a1, s, u
|
|
4532
|
+
bd -= 1
|
|
4533
|
+
a1 = a + bd*p
|
|
4534
|
+
s = v[a1]
|
|
4535
|
+
u = x + bd
|
|
4536
|
+
for k in range(bd):
|
|
4537
|
+
a1 -= p
|
|
4538
|
+
u -= 1
|
|
4539
|
+
s = s*u + v[a1] # force cast to long long
|
|
4540
|
+
s = s % q
|
|
4541
|
+
return -s
|
|
4542
|
+
|
|
4543
|
+
cpdef gauss_table(long long p, int f, int prec, bint use_longs):
|
|
4544
|
+
r"""
|
|
4545
|
+
Compute a table of Gauss sums using the Gross-Koblitz formula.
|
|
4546
|
+
|
|
4547
|
+
This is used in the computation of `L`-functions of hypergeometric motives.
|
|
4548
|
+
The Gross-Koblitz formula is used as in `sage.rings.padics.misc.gauss_sum`,
|
|
4549
|
+
but further unpacked for efficiency.
|
|
4550
|
+
|
|
4551
|
+
INPUT:
|
|
4552
|
+
|
|
4553
|
+
- ``p`` -- prime
|
|
4554
|
+
- ``f``, ``prec`` -- positive integers
|
|
4555
|
+
- ``use_longs`` -- boolean; if ``True``, computations are done in C ``long long``
|
|
4556
|
+
integers rather than Sage `p`-adics, and the results are returned
|
|
4557
|
+
as a Python array rather than a list.
|
|
4558
|
+
|
|
4559
|
+
OUTPUT:
|
|
4560
|
+
|
|
4561
|
+
A list of length `q-1=p^f-1`. The entries are `p`-adic units created with
|
|
4562
|
+
absolute precision ``prec``.
|
|
4563
|
+
|
|
4564
|
+
EXAMPLES::
|
|
4565
|
+
|
|
4566
|
+
sage: from sage.rings.padics.padic_generic_element import gauss_table
|
|
4567
|
+
sage: gauss_table(2,2,4,False)
|
|
4568
|
+
[1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3]
|
|
4569
|
+
sage: gauss_table(3,2,4,False)[3]
|
|
4570
|
+
2 + 3 + 2*3^2
|
|
4571
|
+
"""
|
|
4572
|
+
from sage.rings.padics.factory import Zp, Qp
|
|
4573
|
+
|
|
4574
|
+
cdef int i, j, bd
|
|
4575
|
+
cdef long long q, q1, q3, r, r1, r2, s1, s2, k
|
|
4576
|
+
cdef array.array vv, ans1
|
|
4577
|
+
|
|
4578
|
+
if (f == 1 and prec == 1): # Shortcut for this key special case
|
|
4579
|
+
ans1 = array.array('l', [0]) * p
|
|
4580
|
+
ans1[0] = p-1
|
|
4581
|
+
for r in range(1, p-1):
|
|
4582
|
+
k = ans1[r-1]
|
|
4583
|
+
ans1[r] = k * r % p
|
|
4584
|
+
return ans1
|
|
4585
|
+
|
|
4586
|
+
q = p ** f
|
|
4587
|
+
q1 = q - 1
|
|
4588
|
+
bd = (p*prec+p-2) // (p-1) - 1
|
|
4589
|
+
R = Zp(p, prec, 'fixed-mod')
|
|
4590
|
+
if p == 2: # Dwork expansion has denominators when p = 2
|
|
4591
|
+
R1 = Qp(p, prec)
|
|
4592
|
+
use_longs = False
|
|
4593
|
+
else:
|
|
4594
|
+
R1 = R
|
|
4595
|
+
d = ~R1(q1)
|
|
4596
|
+
v = dwork_mahler_coeffs(R1, bd)
|
|
4597
|
+
if use_longs:
|
|
4598
|
+
q3 = p ** prec
|
|
4599
|
+
r2 = d.lift() % q3
|
|
4600
|
+
vv = array.array('l', [0]) * len(v)
|
|
4601
|
+
for k in range(len(v)):
|
|
4602
|
+
vv[k] = v[k].lift() % q3
|
|
4603
|
+
ans1 = array.array('l', [0]) * q1
|
|
4604
|
+
ans1[0] = -1
|
|
4605
|
+
ans = ans1
|
|
4606
|
+
else:
|
|
4607
|
+
u = R1.one()
|
|
4608
|
+
ans = [0 for r in range(q1)]
|
|
4609
|
+
ans[0] = -u
|
|
4610
|
+
for r in range(1, q1):
|
|
4611
|
+
if ans[r]: continue
|
|
4612
|
+
if use_longs:
|
|
4613
|
+
s1 = 1
|
|
4614
|
+
else:
|
|
4615
|
+
s = u
|
|
4616
|
+
r1 = r
|
|
4617
|
+
for j in range(1, f+1):
|
|
4618
|
+
k = r1 % p
|
|
4619
|
+
r1 = (r1 + k * q1) // p
|
|
4620
|
+
if use_longs: # Use Dwork expansion to compute p-adic Gamma
|
|
4621
|
+
s1 *= -evaluate_dwork_mahler_long(vv, r1*r2 % q3,
|
|
4622
|
+
p, bd, k, q3)
|
|
4623
|
+
s1 %= q3
|
|
4624
|
+
else:
|
|
4625
|
+
s *= -evaluate_dwork_mahler(v, R1(r1)*d, p, bd, k)
|
|
4626
|
+
if r1 == r:
|
|
4627
|
+
break
|
|
4628
|
+
if use_longs:
|
|
4629
|
+
if j < f:
|
|
4630
|
+
s2 = s1
|
|
4631
|
+
for i in range(f//j-1):
|
|
4632
|
+
s1 = s1 * s2 % q3
|
|
4633
|
+
ans1[r] = -s1
|
|
4634
|
+
else:
|
|
4635
|
+
if j < f:
|
|
4636
|
+
s **= f // j
|
|
4637
|
+
ans[r] = -s
|
|
4638
|
+
for i in range(j-1):
|
|
4639
|
+
r1 = r1 * p % q1 # Initially r1 == r
|
|
4640
|
+
ans[r1] = ans[r]
|
|
4641
|
+
if p != 2: return ans
|
|
4642
|
+
return [R(x) for x in ans]
|