passagemath-ntl 10.6.38__cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.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-ntl might be problematic. Click here for more details.
- passagemath_ntl/__init__.py +3 -0
- passagemath_ntl-10.6.38.dist-info/METADATA +122 -0
- passagemath_ntl-10.6.38.dist-info/RECORD +162 -0
- passagemath_ntl-10.6.38.dist-info/WHEEL +6 -0
- passagemath_ntl-10.6.38.dist-info/top_level.txt +3 -0
- passagemath_ntl.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
- passagemath_ntl.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_ntl.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
- passagemath_ntl.libs/libmpfr-9d41ebf1.so.6.2.1 +0 -0
- passagemath_ntl.libs/libntl-1bc30f7e.so.45.0.0 +0 -0
- sage/all__sagemath_ntl.py +7 -0
- sage/libs/all__sagemath_ntl.py +3 -0
- sage/libs/mpfi/__init__.pxd +287 -0
- sage/libs/mpfi/types.pxd +10 -0
- sage/libs/ntl/GF2.pxd +18 -0
- sage/libs/ntl/GF2E.pxd +28 -0
- sage/libs/ntl/GF2EX.pxd +12 -0
- sage/libs/ntl/GF2X.pxd +81 -0
- sage/libs/ntl/ZZ.pxd +93 -0
- sage/libs/ntl/ZZX.pxd +85 -0
- sage/libs/ntl/ZZ_p.pxd +28 -0
- sage/libs/ntl/ZZ_pE.pxd +37 -0
- sage/libs/ntl/ZZ_pEX.pxd +106 -0
- sage/libs/ntl/ZZ_pX.pxd +122 -0
- sage/libs/ntl/__init__.py +4 -0
- sage/libs/ntl/all.py +72 -0
- sage/libs/ntl/conversion.pxd +106 -0
- sage/libs/ntl/convert.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/convert.pxd +7 -0
- sage/libs/ntl/convert.pyx +38 -0
- sage/libs/ntl/decl.pxi +18 -0
- sage/libs/ntl/error.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/error.pyx +63 -0
- sage/libs/ntl/lzz_p.pxd +20 -0
- sage/libs/ntl/lzz_pX.pxd +59 -0
- sage/libs/ntl/mat_GF2.pxd +30 -0
- sage/libs/ntl/mat_GF2E.pxd +30 -0
- sage/libs/ntl/mat_ZZ.pxd +59 -0
- sage/libs/ntl/misc.pxi +33 -0
- sage/libs/ntl/ntl_GF2.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2.pxd +5 -0
- sage/libs/ntl/ntl_GF2.pyx +281 -0
- sage/libs/ntl/ntl_GF2E.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2E.pxd +8 -0
- sage/libs/ntl/ntl_GF2E.pyx +488 -0
- sage/libs/ntl/ntl_GF2EContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2EContext.pxd +9 -0
- sage/libs/ntl/ntl_GF2EContext.pyx +134 -0
- sage/libs/ntl/ntl_GF2EX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2EX.pxd +10 -0
- sage/libs/ntl/ntl_GF2EX.pyx +251 -0
- sage/libs/ntl/ntl_GF2X.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2X.pxd +5 -0
- sage/libs/ntl/ntl_GF2X.pyx +771 -0
- sage/libs/ntl/ntl_GF2X_linkage.pxi +404 -0
- sage/libs/ntl/ntl_ZZ.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ.pxd +7 -0
- sage/libs/ntl/ntl_ZZ.pyx +541 -0
- sage/libs/ntl/ntl_ZZX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZX.pxd +7 -0
- sage/libs/ntl/ntl_ZZX.pyx +1206 -0
- sage/libs/ntl/ntl_ZZ_p.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_p.pxd +10 -0
- sage/libs/ntl/ntl_ZZ_p.pyx +509 -0
- sage/libs/ntl/ntl_ZZ_pContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pContext.pxd +22 -0
- sage/libs/ntl/ntl_ZZ_pContext.pyx +201 -0
- sage/libs/ntl/ntl_ZZ_pE.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pE.pxd +11 -0
- sage/libs/ntl/ntl_ZZ_pE.pyx +349 -0
- sage/libs/ntl/ntl_ZZ_pEContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pEContext.pxd +23 -0
- sage/libs/ntl/ntl_ZZ_pEContext.pyx +226 -0
- sage/libs/ntl/ntl_ZZ_pEX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pEX.pxd +10 -0
- sage/libs/ntl/ntl_ZZ_pEX.pyx +1255 -0
- sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi +420 -0
- sage/libs/ntl/ntl_ZZ_pX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pX.pxd +17 -0
- sage/libs/ntl/ntl_ZZ_pX.pyx +1532 -0
- sage/libs/ntl/ntl_lzz_p.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_lzz_p.pxd +8 -0
- sage/libs/ntl/ntl_lzz_p.pyx +440 -0
- sage/libs/ntl/ntl_lzz_pContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_lzz_pContext.pxd +7 -0
- sage/libs/ntl/ntl_lzz_pContext.pyx +137 -0
- sage/libs/ntl/ntl_lzz_pX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_lzz_pX.pxd +10 -0
- sage/libs/ntl/ntl_lzz_pX.pyx +902 -0
- sage/libs/ntl/ntl_mat_GF2.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_mat_GF2.pxd +8 -0
- sage/libs/ntl/ntl_mat_GF2.pyx +612 -0
- sage/libs/ntl/ntl_mat_GF2E.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_mat_GF2E.pxd +10 -0
- sage/libs/ntl/ntl_mat_GF2E.pyx +752 -0
- sage/libs/ntl/ntl_mat_ZZ.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_mat_ZZ.pxd +6 -0
- sage/libs/ntl/ntl_mat_ZZ.pyx +1523 -0
- sage/libs/ntl/ntl_tools.pxd +3 -0
- sage/libs/ntl/ntlwrap.h +53 -0
- sage/libs/ntl/ntlwrap_impl.h +743 -0
- sage/libs/ntl/types.pxd +157 -0
- sage/libs/ntl/vec_GF2.pxd +26 -0
- sage/libs/ntl/vec_GF2E.pxd +2 -0
- sage/matrix/all__sagemath_ntl.py +1 -0
- sage/matrix/matrix_modn_dense_double.pxd +10 -0
- sage/matrix/matrix_modn_dense_float.pxd +9 -0
- sage/matrix/matrix_modn_dense_template.pxi +3257 -0
- sage/matrix/matrix_modn_dense_template_header.pxi +15 -0
- sage/matrix/matrix_modn_sparse.pxd +8 -0
- sage/misc/all__sagemath_ntl.py +1 -0
- sage/rings/all__sagemath_ntl.py +7 -0
- sage/rings/bernmm.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/bernmm.pyx +161 -0
- sage/rings/bernoulli_mod_p.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/bernoulli_mod_p.pyx +313 -0
- sage/rings/finite_rings/all__sagemath_ntl.py +1 -0
- sage/rings/finite_rings/finite_field_ntl_gf2e.py +305 -0
- sage/rings/finite_rings/residue_field_ntl_gf2e.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/finite_rings/residue_field_ntl_gf2e.pyx +140 -0
- sage/rings/padics/all__sagemath_ntl.py +5 -0
- sage/rings/padics/padic_ZZ_pX_CA_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_CA_element.pxd +25 -0
- sage/rings/padics/padic_ZZ_pX_CA_element.pyx +2368 -0
- sage/rings/padics/padic_ZZ_pX_CR_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_CR_element.pxd +33 -0
- sage/rings/padics/padic_ZZ_pX_CR_element.pyx +3277 -0
- sage/rings/padics/padic_ZZ_pX_FM_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_FM_element.pxd +12 -0
- sage/rings/padics/padic_ZZ_pX_FM_element.pyx +1739 -0
- sage/rings/padics/padic_ZZ_pX_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_element.pxd +6 -0
- sage/rings/padics/padic_ZZ_pX_element.pyx +919 -0
- sage/rings/padics/padic_ext_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ext_element.pxd +38 -0
- sage/rings/padics/padic_ext_element.pyx +512 -0
- sage/rings/padics/pow_computer_ext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/pow_computer_ext.pxd +107 -0
- sage/rings/padics/pow_computer_ext.pyx +2401 -0
- sage/rings/polynomial/all__sagemath_ntl.py +1 -0
- sage/rings/polynomial/evaluation_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/evaluation_ntl.pxd +7 -0
- sage/rings/polynomial/evaluation_ntl.pyx +70 -0
- sage/rings/polynomial/polynomial_gf2x.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_gf2x.pxd +10 -0
- sage/rings/polynomial/polynomial_gf2x.pyx +364 -0
- sage/rings/polynomial/polynomial_integer_dense_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_integer_dense_ntl.pxd +8 -0
- sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +1128 -0
- sage/rings/polynomial/polynomial_modn_dense_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_modn_dense_ntl.pxd +36 -0
- sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +2049 -0
- sage/rings/polynomial/polynomial_template.pxi +842 -0
- sage/rings/polynomial/polynomial_template_header.pxi +11 -0
- sage/rings/polynomial/polynomial_zz_pex.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_zz_pex.pxd +12 -0
- sage/rings/polynomial/polynomial_zz_pex.pyx +778 -0
- sage/rings/real_mpfi.pxd +50 -0
- sage/schemes/all__sagemath_ntl.py +1 -0
- sage/schemes/hyperelliptic_curves/all__sagemath_ntl.py +1 -0
- sage/schemes/hyperelliptic_curves/hypellfrob.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/schemes/hyperelliptic_curves/hypellfrob.pyx +252 -0
|
@@ -0,0 +1,1739 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
# distutils: libraries = NTL_LIBRARIES gmp M_LIBRARIES
|
|
3
|
+
# distutils: extra_compile_args = NTL_CFLAGS
|
|
4
|
+
# distutils: include_dirs = NTL_INCDIR
|
|
5
|
+
# distutils: library_dirs = NTL_LIBDIR
|
|
6
|
+
# distutils: extra_link_args = NTL_LIBEXTRA
|
|
7
|
+
# distutils: language = c++
|
|
8
|
+
# sage.doctest: needs sage.rings.padics
|
|
9
|
+
r"""
|
|
10
|
+
`p`-adic ``ZZ_pX`` FM Element
|
|
11
|
+
|
|
12
|
+
This file implements elements of Eisenstein and unramified extensions
|
|
13
|
+
of `\ZZ_p` with fixed modulus precision.
|
|
14
|
+
|
|
15
|
+
For the parent class see ``padic_extension_leaves.pyx``.
|
|
16
|
+
|
|
17
|
+
The underlying implementation is through NTL's ``ZZ_pX`` class. Each
|
|
18
|
+
element contains the following data:
|
|
19
|
+
|
|
20
|
+
- ``value`` (``ZZ_pX_c``) -- an ntl ``ZZ_pX`` storing the value. The
|
|
21
|
+
variable `x` is the uniformizer in the case of Eisenstein extensions.
|
|
22
|
+
This ``ZZ_pX`` is created with global ntl modulus determined by the
|
|
23
|
+
parent's precision cap and shared among all elements.
|
|
24
|
+
|
|
25
|
+
- ``prime_pow`` (some subclass of :class:`PowComputer_ZZ_pX`) -- a class,
|
|
26
|
+
identical among all elements with the same parent, holding common
|
|
27
|
+
data.
|
|
28
|
+
|
|
29
|
+
* ``prime_pow.deg`` -- the degree of the extension
|
|
30
|
+
|
|
31
|
+
* ``prime_pow.e`` -- the ramification index
|
|
32
|
+
|
|
33
|
+
* ``prime_pow.f`` -- the inertia degree
|
|
34
|
+
|
|
35
|
+
* ``prime_pow.prec_cap`` -- the unramified precision cap: for
|
|
36
|
+
Eisenstein extensions this is the smallest power of `p` that is
|
|
37
|
+
zero
|
|
38
|
+
|
|
39
|
+
* ``prime_pow.ram_prec_cap`` -- the ramified precision cap: for
|
|
40
|
+
Eisenstein extensions this will be the smallest power of `x` that
|
|
41
|
+
is indistinguishable from zero
|
|
42
|
+
|
|
43
|
+
* ``prime_pow.pow_ZZ_tmp``, prime_pow.pow_mpz_t_tmp``,
|
|
44
|
+
``prime_pow.pow_Integer`` -- functions for accessing powers of
|
|
45
|
+
`p`. The first two return pointers. See
|
|
46
|
+
``sage/rings/padics/pow_computer_ext`` for examples and important
|
|
47
|
+
warnings.
|
|
48
|
+
|
|
49
|
+
* ``prime_pow.get_context``, ``prime_pow.get_context_capdiv``,
|
|
50
|
+
``prime_pow.get_top_context`` -- obtain an
|
|
51
|
+
``ntl_ZZ_pContext_class`` corresponding to `p^n`. The capdiv
|
|
52
|
+
version divides by ``prime_pow.e`` as appropriate.
|
|
53
|
+
``top_context`` corresponds to `p^{\texttt{prec\_cap}}`.
|
|
54
|
+
|
|
55
|
+
* ``prime_pow.restore_context``,
|
|
56
|
+
``prime_pow.restore_context_capdiv``,
|
|
57
|
+
``prime_pow.restore_top_context`` -- restores the given context
|
|
58
|
+
|
|
59
|
+
* ``prime_pow.get_modulus``, ``get_modulus_capdiv``,
|
|
60
|
+
``get_top_modulus`` -- returns a ``ZZ_pX_Modulus_c*`` pointing to
|
|
61
|
+
a polynomial modulus defined modulo `p^n` (appropriately divided
|
|
62
|
+
by ``prime_pow.e`` in the capdiv case).
|
|
63
|
+
|
|
64
|
+
EXAMPLES:
|
|
65
|
+
|
|
66
|
+
An Eisenstein extension::
|
|
67
|
+
|
|
68
|
+
sage: R = ZpFM(5,5)
|
|
69
|
+
sage: S.<x> = R[]
|
|
70
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
71
|
+
sage: W.<w> = R.ext(f); W
|
|
72
|
+
5-adic Eisenstein Extension Ring in w defined by x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
73
|
+
sage: z = (1+w)^5; z
|
|
74
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
75
|
+
sage: y = z >> 1; y
|
|
76
|
+
w^4 + w^5 + 2*w^6 + 4*w^7 + 3*w^9 + w^11 + 4*w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^19 + w^20 + 4*w^23 + 4*w^24
|
|
77
|
+
sage: y.valuation()
|
|
78
|
+
4
|
|
79
|
+
sage: y.precision_relative()
|
|
80
|
+
21
|
|
81
|
+
sage: y.precision_absolute()
|
|
82
|
+
25
|
|
83
|
+
sage: z - (y << 1)
|
|
84
|
+
1
|
|
85
|
+
|
|
86
|
+
An unramified extension::
|
|
87
|
+
|
|
88
|
+
sage: # needs sage.libs.flint
|
|
89
|
+
sage: g = x^3 + 3*x + 3
|
|
90
|
+
sage: A.<a> = R.ext(g)
|
|
91
|
+
sage: z = (1+a)^5; z
|
|
92
|
+
(2*a^2 + 4*a) + (3*a^2 + 3*a + 1)*5 + (4*a^2 + 3*a + 4)*5^2 + (4*a^2 + 4*a + 4)*5^3 + (4*a^2 + 4*a + 4)*5^4
|
|
93
|
+
sage: z - 1 - 5*a - 10*a^2 - 10*a^3 - 5*a^4 - a^5
|
|
94
|
+
0
|
|
95
|
+
sage: y = z >> 1; y
|
|
96
|
+
(3*a^2 + 3*a + 1) + (4*a^2 + 3*a + 4)*5 + (4*a^2 + 4*a + 4)*5^2 + (4*a^2 + 4*a + 4)*5^3
|
|
97
|
+
sage: 1/a
|
|
98
|
+
(3*a^2 + 4) + (a^2 + 4)*5 + (3*a^2 + 4)*5^2 + (a^2 + 4)*5^3 + (3*a^2 + 4)*5^4
|
|
99
|
+
|
|
100
|
+
Different printing modes::
|
|
101
|
+
|
|
102
|
+
sage: # needs sage.libs.flint
|
|
103
|
+
sage: R = ZpFM(5, print_mode='digits'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
|
|
104
|
+
sage: z = (1+w)^5; repr(z)
|
|
105
|
+
'...4110403113210310442221311242000111011201102002023303214332011214403232013144001400444441030421100001'
|
|
106
|
+
sage: R = ZpFM(5, print_mode='bars'); S.<x> = R[]; g = x^3 + 3*x + 3; A.<a> = R.ext(g)
|
|
107
|
+
sage: z = (1+a)^5; repr(z)
|
|
108
|
+
'...[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 3, 4]|[1, 3, 3]|[0, 4, 2]'
|
|
109
|
+
sage: R = ZpFM(5, print_mode='terse'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
|
|
110
|
+
sage: z = (1+w)^5; z
|
|
111
|
+
6 + 95367431640505*w + 25*w^2 + 95367431640560*w^3 + 5*w^4
|
|
112
|
+
sage: R = ZpFM(5, print_mode='val-unit'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
|
|
113
|
+
sage: y = (1+w)^5 - 1; y
|
|
114
|
+
w^5 * (2090041 + 19073486126901*w + 1258902*w^2 + 57220458985049*w^3 + 16785*w^4)
|
|
115
|
+
|
|
116
|
+
AUTHORS:
|
|
117
|
+
|
|
118
|
+
- David Roe (2008-01-01) initial version
|
|
119
|
+
"""
|
|
120
|
+
# ****************************************************************************
|
|
121
|
+
# Copyright (C) 2008 David Roe <roed.math@gmail.com>
|
|
122
|
+
# William Stein <wstein@gmail.com>
|
|
123
|
+
#
|
|
124
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
125
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
126
|
+
# the License, or (at your option) any later version.
|
|
127
|
+
#
|
|
128
|
+
# https://www.gnu.org/licenses/
|
|
129
|
+
# ****************************************************************************
|
|
130
|
+
|
|
131
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
132
|
+
|
|
133
|
+
include "sage/libs/ntl/decl.pxi"
|
|
134
|
+
|
|
135
|
+
from sage.structure.richcmp cimport rich_to_bool
|
|
136
|
+
from sage.rings.integer cimport Integer
|
|
137
|
+
from sage.rings.padics.padic_generic_element cimport pAdicGenericElement
|
|
138
|
+
from sage.rings.padics.padic_ext_element cimport pAdicExtElement
|
|
139
|
+
from sage.libs.gmp.mpz cimport *
|
|
140
|
+
from sage.libs.gmp.mpq cimport *
|
|
141
|
+
from sage.libs.ntl.ntl_ZZ_pX cimport ntl_ZZ_pX
|
|
142
|
+
from sage.libs.ntl.ntl_ZZX cimport ntl_ZZX
|
|
143
|
+
from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
|
|
144
|
+
from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p
|
|
145
|
+
from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class
|
|
146
|
+
from sage.rings.rational cimport Rational
|
|
147
|
+
from cypari2.gen import Gen as pari_gen
|
|
148
|
+
from sage.interfaces.abc import GpElement
|
|
149
|
+
from sage.rings.finite_rings.integer_mod import IntegerMod_abstract
|
|
150
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
cdef class pAdicZZpXFMElement(pAdicZZpXElement):
|
|
154
|
+
def __init__(self, parent, x, absprec=None, relprec=None, empty=False):
|
|
155
|
+
r"""
|
|
156
|
+
Create an element of a fixed modulus, unramified or
|
|
157
|
+
eisenstein extension of `\ZZ_p` or `\QQ_p`.
|
|
158
|
+
|
|
159
|
+
INPUT:
|
|
160
|
+
|
|
161
|
+
- ``parent`` -- either an ``EisensteinRingFixedMod`` or
|
|
162
|
+
``UnramifiedRingFixedMod``
|
|
163
|
+
|
|
164
|
+
- ``x`` -- integer, rational, `p`-adic element, polynomial,
|
|
165
|
+
list, integer_mod, pari int/frac/poly_t/pol_mod, an
|
|
166
|
+
``ntl_ZZ_pX``, an ``ntl_ZZX``, an ``ntl_ZZ``, or an
|
|
167
|
+
``ntl_ZZ_p``
|
|
168
|
+
|
|
169
|
+
- ``absprec`` -- not used
|
|
170
|
+
|
|
171
|
+
- ``relprec`` -- not used
|
|
172
|
+
|
|
173
|
+
- ``empty`` -- whether to return after initializing to zero
|
|
174
|
+
(without setting anything)
|
|
175
|
+
|
|
176
|
+
EXAMPLES::
|
|
177
|
+
|
|
178
|
+
sage: R = ZpFM(5,5)
|
|
179
|
+
sage: S.<x> = R[]
|
|
180
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
181
|
+
sage: W.<w> = R.ext(f)
|
|
182
|
+
sage: z = (1+w)^5; z # indirect doctest
|
|
183
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
184
|
+
|
|
185
|
+
TESTS:
|
|
186
|
+
|
|
187
|
+
Check that :issue:`3865` is fixed::
|
|
188
|
+
|
|
189
|
+
sage: W(gp('2 + O(5^2)'))
|
|
190
|
+
2
|
|
191
|
+
|
|
192
|
+
Check that :issue:`13612` has been fixed::
|
|
193
|
+
|
|
194
|
+
sage: # needs sage.libs.flint
|
|
195
|
+
sage: R = ZpFM(3)
|
|
196
|
+
sage: S.<a> = R[]
|
|
197
|
+
sage: W.<a> = R.extension(a^2 + 1)
|
|
198
|
+
sage: W(W.residue_field().zero())
|
|
199
|
+
0
|
|
200
|
+
"""
|
|
201
|
+
pAdicZZpXElement.__init__(self, parent)
|
|
202
|
+
if empty:
|
|
203
|
+
return
|
|
204
|
+
cdef ZZ_c tmp_z
|
|
205
|
+
cdef Integer tmp_Int
|
|
206
|
+
cdef Py_ssize_t i
|
|
207
|
+
if isinstance(x, pAdicGenericElement):
|
|
208
|
+
if x.valuation() < 0:
|
|
209
|
+
raise ValueError("element has negative valuation")
|
|
210
|
+
if x._is_base_elt(self.prime_pow.prime):
|
|
211
|
+
xlift = <Integer>x.lift()
|
|
212
|
+
self._set_from_mpz(xlift.value)
|
|
213
|
+
return
|
|
214
|
+
if parent.prime() != x.parent().prime():
|
|
215
|
+
raise TypeError("Cannot coerce between p-adic parents with different primes.")
|
|
216
|
+
if isinstance(x, GpElement):
|
|
217
|
+
x = x.__pari__()
|
|
218
|
+
if isinstance(x, pari_gen):
|
|
219
|
+
if x.type() == "t_PADIC":
|
|
220
|
+
if x.variable() != self.prime_pow.prime:
|
|
221
|
+
raise TypeError("Cannot coerce a pari p-adic with the wrong prime.")
|
|
222
|
+
x = x.lift()
|
|
223
|
+
if x.type() == 't_INT':
|
|
224
|
+
x = Integer(x)
|
|
225
|
+
elif x.type() == 't_FRAC':
|
|
226
|
+
x = Rational(x)
|
|
227
|
+
elif x.type() == 't_POLMOD' or x.type == 't_POL':
|
|
228
|
+
# This code doesn't check to see if the primes are the same.
|
|
229
|
+
L = []
|
|
230
|
+
x = x.lift().lift()
|
|
231
|
+
for i from 0 <= i <= x.poldegree():
|
|
232
|
+
L.append(Integer(x.polcoef(i)))
|
|
233
|
+
x = L
|
|
234
|
+
else:
|
|
235
|
+
raise TypeError("unsupported coercion from pari: only p-adics, integers, rationals, polynomials and pol_mods allowed")
|
|
236
|
+
elif isinstance(x, IntegerMod_abstract):
|
|
237
|
+
if (<Integer>x.modulus())._is_power_of(<Integer>parent.prime()):
|
|
238
|
+
x = x.lift()
|
|
239
|
+
else:
|
|
240
|
+
raise TypeError("cannot coerce from the given integer mod ring (not a power of the same prime)")
|
|
241
|
+
elif x in parent.residue_field() and x.parent().is_finite():
|
|
242
|
+
# Should only reach here if x is not in F_p
|
|
243
|
+
z = parent.gen()
|
|
244
|
+
poly = x.polynomial().list()
|
|
245
|
+
x = sum([poly[i].lift() * (z ** i) for i in range(len(poly))], parent.zero())
|
|
246
|
+
elif isinstance(x, ntl_ZZ_p):
|
|
247
|
+
ZZ_remove(tmp_z, (<ntl_ZZ>x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
248
|
+
if ZZ_IsOne(tmp_z):
|
|
249
|
+
x = x.lift()
|
|
250
|
+
tmp_Int = Integer.__new__(Integer)
|
|
251
|
+
ZZ_to_mpz(tmp_Int.value, &(<ntl_ZZ>x).x)
|
|
252
|
+
x = tmp_Int
|
|
253
|
+
else:
|
|
254
|
+
raise TypeError("cannot coerce the given ntl_ZZ_p (modulus not a power of the same prime)")
|
|
255
|
+
elif isinstance(x, ntl_ZZ):
|
|
256
|
+
tmp_Int = Integer.__new__(Integer)
|
|
257
|
+
ZZ_to_mpz(tmp_Int.value, &(<ntl_ZZ>x).x)
|
|
258
|
+
x = tmp_Int
|
|
259
|
+
elif isinstance(x, int):
|
|
260
|
+
x = Integer(x)
|
|
261
|
+
if isinstance(x, Integer):
|
|
262
|
+
self._set_from_mpz((<Integer>x).value)
|
|
263
|
+
elif isinstance(x, Rational):
|
|
264
|
+
self._set_from_mpq((<Rational>x).value)
|
|
265
|
+
elif isinstance(x, ntl_ZZ_pX):
|
|
266
|
+
self._set_from_ZZ_pX(&(<ntl_ZZ_pX>x).x, (<ntl_ZZ_pX>x).c)
|
|
267
|
+
elif isinstance(x, ntl_ZZX):
|
|
268
|
+
self._set_from_ZZX((<ntl_ZZX>x).x)
|
|
269
|
+
elif isinstance(x, pAdicExtElement):
|
|
270
|
+
if x.parent() is parent:
|
|
271
|
+
self._set_from_ZZ_pX(&(<pAdicZZpXFMElement>x).value, self.prime_pow.get_top_context())
|
|
272
|
+
else:
|
|
273
|
+
raise NotImplementedError("Conversion from different p-adic extensions not yet supported")
|
|
274
|
+
else:
|
|
275
|
+
try:
|
|
276
|
+
x = list(x)
|
|
277
|
+
except TypeError:
|
|
278
|
+
try:
|
|
279
|
+
x = x.list()
|
|
280
|
+
except AttributeError:
|
|
281
|
+
raise TypeError("cannot convert x to a p-adic element")
|
|
282
|
+
self._set_from_list(x)
|
|
283
|
+
|
|
284
|
+
cdef int _set_from_mpz(self, mpz_t x) except -1:
|
|
285
|
+
"""
|
|
286
|
+
Set ``self`` from an ``mpz_t``.
|
|
287
|
+
|
|
288
|
+
EXAMPLES::
|
|
289
|
+
|
|
290
|
+
sage: R = ZpFM(5,5)
|
|
291
|
+
sage: S.<x> = R[]
|
|
292
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
293
|
+
sage: W.<w> = R.ext(f)
|
|
294
|
+
sage: W(70) # indirect doctest
|
|
295
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + 3*w^16 + w^17 + w^18 + 4*w^20 + 4*w^21 + w^22 + 2*w^23
|
|
296
|
+
"""
|
|
297
|
+
self.prime_pow.restore_top_context()
|
|
298
|
+
cdef ZZ_c tmp
|
|
299
|
+
cdef mpz_t tmp_m
|
|
300
|
+
sig_on()
|
|
301
|
+
mpz_init(tmp_m)
|
|
302
|
+
mpz_set(tmp_m, x)
|
|
303
|
+
mpz_to_ZZ(&tmp, tmp_m)
|
|
304
|
+
mpz_clear(tmp_m)
|
|
305
|
+
ZZ_pX_SetCoeff(self.value, 0, ZZ_to_ZZ_p(tmp))
|
|
306
|
+
sig_off()
|
|
307
|
+
|
|
308
|
+
cdef int _set_from_mpq(self, mpq_t x) except -1:
|
|
309
|
+
"""
|
|
310
|
+
Set ``self`` from an ``mpq_t``.
|
|
311
|
+
|
|
312
|
+
EXAMPLES::
|
|
313
|
+
|
|
314
|
+
sage: R = ZpFM(5,5)
|
|
315
|
+
sage: S.<x> = R[]
|
|
316
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
317
|
+
sage: W.<w> = R.ext(f)
|
|
318
|
+
sage: z = W(70/3); z # indirect doctest
|
|
319
|
+
3*w^5 + w^7 + 2*w^9 + 2*w^10 + 4*w^11 + w^12 + 2*w^13 + 3*w^15 + 2*w^16
|
|
320
|
+
+ 3*w^17 + w^18 + 3*w^19 + 3*w^20 + 2*w^21 + 2*w^22 + 3*w^23 + 4*w^24
|
|
321
|
+
sage: z * 3
|
|
322
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + 3*w^16 + w^17 + w^18 + 4*w^20 + 4*w^21 + w^22 + 2*w^23
|
|
323
|
+
sage: W(70)
|
|
324
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + 3*w^16 + w^17 + w^18 + 4*w^20 + 4*w^21 + w^22 + 2*w^23
|
|
325
|
+
"""
|
|
326
|
+
self.prime_pow.restore_top_context()
|
|
327
|
+
if mpz_divisible_p(mpq_denref(x), self.prime_pow.prime.value):
|
|
328
|
+
raise ValueError("p divides denominator")
|
|
329
|
+
cdef mpz_t tmp_m
|
|
330
|
+
cdef ZZ_c tmp_z
|
|
331
|
+
sig_on()
|
|
332
|
+
mpz_init(tmp_m)
|
|
333
|
+
mpz_invert(tmp_m, mpq_denref(x), self.prime_pow.pow_mpz_t_top())
|
|
334
|
+
mpz_mul(tmp_m, tmp_m, mpq_numref(x))
|
|
335
|
+
mpz_mod(tmp_m, tmp_m, self.prime_pow.pow_mpz_t_top())
|
|
336
|
+
mpz_to_ZZ(&tmp_z, tmp_m)
|
|
337
|
+
ZZ_pX_SetCoeff(self.value, 0, ZZ_to_ZZ_p(tmp_z))
|
|
338
|
+
mpz_clear(tmp_m)
|
|
339
|
+
sig_off()
|
|
340
|
+
return 0
|
|
341
|
+
|
|
342
|
+
cdef int _set_from_ZZ_pX(self, ZZ_pX_c* poly, ntl_ZZ_pContext_class ctx) except -1:
|
|
343
|
+
"""
|
|
344
|
+
Set ``self`` from a ``ZZ_pX_c``.
|
|
345
|
+
|
|
346
|
+
EXAMPLES::
|
|
347
|
+
|
|
348
|
+
sage: R = ZpFM(5,5)
|
|
349
|
+
sage: S.<x> = R[]
|
|
350
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
351
|
+
sage: W.<w> = R.ext(f)
|
|
352
|
+
sage: z = W(ntl.ZZ_pX([4,1,16],5^2)); z # indirect doctest
|
|
353
|
+
4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + 4*w^13 + 3*w^14 + 2*w^15 + w^16
|
|
354
|
+
+ 3*w^18 + 2*w^19 + 4*w^20 + 4*w^21 + 2*w^22 + 2*w^23 + 4*w^24
|
|
355
|
+
sage: z._ntl_rep()
|
|
356
|
+
[4 1 16]
|
|
357
|
+
"""
|
|
358
|
+
self.prime_pow.restore_top_context()
|
|
359
|
+
self._check_ZZ_pContext(ctx)
|
|
360
|
+
ZZ_pX_conv_modulus(self.value, poly[0], self.prime_pow.get_top_context().x)
|
|
361
|
+
|
|
362
|
+
cdef int _set_from_ZZX(self, ZZX_c poly) except -1:
|
|
363
|
+
"""
|
|
364
|
+
Set ``self`` from a ``ZZX`` with relative precision bounded
|
|
365
|
+
by ``relprec`` and absolute precision bounded by ``absprec``.
|
|
366
|
+
|
|
367
|
+
EXAMPLES::
|
|
368
|
+
|
|
369
|
+
sage: R = ZpFM(5,5)
|
|
370
|
+
sage: S.<x> = R[]
|
|
371
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
372
|
+
sage: W.<w> = R.ext(f)
|
|
373
|
+
sage: z = W(ntl.ZZX([4,1,16])); z # indirect doctest
|
|
374
|
+
4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + 4*w^13 + 3*w^14 + 2*w^15 + w^16
|
|
375
|
+
+ 3*w^18 + 2*w^19 + 4*w^20 + 4*w^21 + 2*w^22 + 2*w^23 + 4*w^24
|
|
376
|
+
sage: z._ntl_rep()
|
|
377
|
+
[4 1 16]
|
|
378
|
+
"""
|
|
379
|
+
self.prime_pow.restore_top_context()
|
|
380
|
+
ZZX_to_ZZ_pX(self.value, poly)
|
|
381
|
+
|
|
382
|
+
cpdef bint _is_inexact_zero(self) except -1:
|
|
383
|
+
"""
|
|
384
|
+
Test if ``self`` is an inexact zero.
|
|
385
|
+
|
|
386
|
+
EXAMPLES::
|
|
387
|
+
|
|
388
|
+
sage: R = ZpFM(5,5)
|
|
389
|
+
sage: S.<x> = R[]
|
|
390
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
391
|
+
sage: W.<w> = R.ext(f)
|
|
392
|
+
sage: z = W(0)
|
|
393
|
+
sage: z._is_inexact_zero()
|
|
394
|
+
True
|
|
395
|
+
sage: z = W(5^6)
|
|
396
|
+
sage: z._is_inexact_zero()
|
|
397
|
+
True
|
|
398
|
+
"""
|
|
399
|
+
return ZZ_pX_IsZero(self.value) or (self.prime_pow.e * self.prime_pow.prec_cap != self.prime_pow.ram_prec_cap
|
|
400
|
+
and self.valuation_c() >= self.prime_pow.ram_prec_cap)
|
|
401
|
+
|
|
402
|
+
def __reduce__(self):
|
|
403
|
+
"""
|
|
404
|
+
Pickle ``self``.
|
|
405
|
+
|
|
406
|
+
EXAMPLES::
|
|
407
|
+
|
|
408
|
+
sage: R = ZpFM(5,5)
|
|
409
|
+
sage: S.<x> = R[]
|
|
410
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
411
|
+
sage: W.<w> = R.ext(f)
|
|
412
|
+
sage: z = (1 + w)^5 - 1
|
|
413
|
+
sage: loads(dumps(z)) == z # indirect doctest
|
|
414
|
+
True
|
|
415
|
+
"""
|
|
416
|
+
self.prime_pow.restore_top_context()
|
|
417
|
+
cdef ntl_ZZ_pX holder = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
|
|
418
|
+
holder.c = self.prime_pow.get_top_context()
|
|
419
|
+
holder.x = self.value
|
|
420
|
+
return make_ZZpXFMElement, (self.parent(), holder)
|
|
421
|
+
|
|
422
|
+
cdef pAdicZZpXFMElement _new_c(self):
|
|
423
|
+
"""
|
|
424
|
+
Return a new element with the same parent as ``self``.
|
|
425
|
+
|
|
426
|
+
EXAMPLES::
|
|
427
|
+
|
|
428
|
+
sage: R = ZpFM(5,5)
|
|
429
|
+
sage: S.<x> = R[]
|
|
430
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
431
|
+
sage: W.<w> = R.ext(f)
|
|
432
|
+
sage: w^5 + 1 # indirect doctest
|
|
433
|
+
1 + w^5
|
|
434
|
+
"""
|
|
435
|
+
self.prime_pow.restore_top_context()
|
|
436
|
+
cdef pAdicZZpXFMElement ans = pAdicZZpXFMElement.__new__(pAdicZZpXFMElement)
|
|
437
|
+
ans._parent = self._parent
|
|
438
|
+
ans.prime_pow = self.prime_pow
|
|
439
|
+
return ans
|
|
440
|
+
|
|
441
|
+
cpdef _richcmp_(left, right, int op):
|
|
442
|
+
"""
|
|
443
|
+
First compare valuations, then compare the values.
|
|
444
|
+
|
|
445
|
+
EXAMPLES::
|
|
446
|
+
|
|
447
|
+
sage: R = ZpFM(5,5)
|
|
448
|
+
sage: S.<x> = R[]
|
|
449
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
450
|
+
sage: W.<w> = R.ext(f)
|
|
451
|
+
sage: w == 1 # indirect doctest
|
|
452
|
+
False
|
|
453
|
+
sage: y = 1 + w
|
|
454
|
+
sage: z = 1 + w + w^27
|
|
455
|
+
sage: y == z
|
|
456
|
+
True
|
|
457
|
+
"""
|
|
458
|
+
cdef pAdicZZpXFMElement _left = <pAdicZZpXFMElement>left
|
|
459
|
+
cdef pAdicZZpXFMElement _right = <pAdicZZpXFMElement>right
|
|
460
|
+
cdef long x_ordp = _left.valuation_c()
|
|
461
|
+
cdef long y_ordp = _right.valuation_c()
|
|
462
|
+
if x_ordp < y_ordp:
|
|
463
|
+
return rich_to_bool(op, -1)
|
|
464
|
+
elif x_ordp > y_ordp:
|
|
465
|
+
return rich_to_bool(op, 1)
|
|
466
|
+
else: # equal ordp
|
|
467
|
+
_left.prime_pow.restore_top_context()
|
|
468
|
+
if x_ordp == left.prime_pow.ram_prec_cap:
|
|
469
|
+
return rich_to_bool(op, 0) # since both are zero
|
|
470
|
+
elif _left.value == _right.value:
|
|
471
|
+
return rich_to_bool(op, 0)
|
|
472
|
+
else:
|
|
473
|
+
# for now just return 1
|
|
474
|
+
return rich_to_bool(op, 1)
|
|
475
|
+
|
|
476
|
+
def __invert__(self):
|
|
477
|
+
"""
|
|
478
|
+
Return the inverse of ``self``, as long as ``self`` is a unit.
|
|
479
|
+
|
|
480
|
+
If ``self`` is not a unit, raises a :exc:`ValueError`.
|
|
481
|
+
|
|
482
|
+
EXAMPLES::
|
|
483
|
+
|
|
484
|
+
sage: R = ZpFM(5,5)
|
|
485
|
+
sage: S.<x> = R[]
|
|
486
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
487
|
+
sage: W.<w> = R.ext(f)
|
|
488
|
+
sage: z = (1 + w)^5
|
|
489
|
+
sage: y = ~z; y # indirect doctest
|
|
490
|
+
1 + 4*w^5 + 4*w^6 + 3*w^7 + w^8 + 2*w^10 + w^11 + w^12 + 2*w^14 + 3*w^16
|
|
491
|
+
+ 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24
|
|
492
|
+
sage: y.parent()
|
|
493
|
+
5-adic Eisenstein Extension Ring in w defined by x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
494
|
+
sage: z = z - 1
|
|
495
|
+
sage: ~z
|
|
496
|
+
Traceback (most recent call last):
|
|
497
|
+
...
|
|
498
|
+
ValueError: cannot invert non-unit
|
|
499
|
+
"""
|
|
500
|
+
if self.valuation_c() > 0:
|
|
501
|
+
raise ValueError("cannot invert non-unit")
|
|
502
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
503
|
+
sig_on()
|
|
504
|
+
if self.prime_pow.e == 1:
|
|
505
|
+
ZZ_pX_InvMod_newton_unram(ans.value, self.value, self.prime_pow.get_top_modulus()[0], self.prime_pow.get_top_context().x, self.prime_pow.get_context(1).x)
|
|
506
|
+
else:
|
|
507
|
+
ZZ_pX_InvMod_newton_ram(ans.value, self.value, self.prime_pow.get_top_modulus()[0], self.prime_pow.get_top_context().x)
|
|
508
|
+
sig_off()
|
|
509
|
+
return ans
|
|
510
|
+
|
|
511
|
+
cdef pAdicZZpXFMElement _lshift_c(self, long n):
|
|
512
|
+
"""
|
|
513
|
+
Multiply ``self`` by the uniformizer raised to the power ``n``.
|
|
514
|
+
|
|
515
|
+
If ``n`` is negative, right shifts by ``-n``.
|
|
516
|
+
|
|
517
|
+
EXAMPLES::
|
|
518
|
+
|
|
519
|
+
sage: R = ZpFM(5,5)
|
|
520
|
+
sage: S.<x> = R[]
|
|
521
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
522
|
+
sage: W.<w> = R.ext(f)
|
|
523
|
+
sage: z = (1 + w)^5
|
|
524
|
+
sage: z
|
|
525
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
526
|
+
sage: z << 17 # indirect doctest
|
|
527
|
+
w^17 + w^22 + w^23 + 2*w^24
|
|
528
|
+
sage: z << (-1)
|
|
529
|
+
w^4 + w^5 + 2*w^6 + 4*w^7 + 3*w^9 + w^11 + 4*w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^19 + w^20 + 4*w^23 + 4*w^24
|
|
530
|
+
"""
|
|
531
|
+
if n < 0:
|
|
532
|
+
return self._rshift_c(-n)
|
|
533
|
+
elif n == 0:
|
|
534
|
+
return self
|
|
535
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
536
|
+
if n < self.prime_pow.ram_prec_cap:
|
|
537
|
+
if self.prime_pow.e == 1:
|
|
538
|
+
ZZ_pX_left_pshift(ans.value, self.value, self.prime_pow.pow_ZZ_tmp(n)[0], self.prime_pow.get_top_context().x)
|
|
539
|
+
else:
|
|
540
|
+
self.prime_pow.eis_shift(&ans.value, &self.value, -n, self.prime_pow.prec_cap)
|
|
541
|
+
return ans
|
|
542
|
+
|
|
543
|
+
def __lshift__(pAdicZZpXFMElement self, shift):
|
|
544
|
+
"""
|
|
545
|
+
Multiply ``self`` by the uniformizer raised to the power ``n``.
|
|
546
|
+
|
|
547
|
+
If ``n`` is negative, right shifts by ``-n``.
|
|
548
|
+
|
|
549
|
+
EXAMPLES::
|
|
550
|
+
|
|
551
|
+
sage: R = ZpFM(5,5)
|
|
552
|
+
sage: S.<x> = R[]
|
|
553
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
554
|
+
sage: W.<w> = R.ext(f)
|
|
555
|
+
sage: z = (1 + w)^5
|
|
556
|
+
sage: z
|
|
557
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
558
|
+
sage: z << 17 # indirect doctest
|
|
559
|
+
w^17 + w^22 + w^23 + 2*w^24
|
|
560
|
+
sage: z << (-1)
|
|
561
|
+
w^4 + w^5 + 2*w^6 + 4*w^7 + 3*w^9 + w^11 + 4*w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^19 + w^20 + 4*w^23 + 4*w^24
|
|
562
|
+
"""
|
|
563
|
+
cdef pAdicZZpXFMElement ans
|
|
564
|
+
if not isinstance(shift, Integer):
|
|
565
|
+
shift = Integer(shift)
|
|
566
|
+
if mpz_fits_slong_p((<Integer>shift).value) == 0:
|
|
567
|
+
ans = self._new_c()
|
|
568
|
+
#Assuming that _new_c() initializes to zero.
|
|
569
|
+
return ans
|
|
570
|
+
return self._lshift_c(mpz_get_si((<Integer>shift).value))
|
|
571
|
+
|
|
572
|
+
cdef pAdicZZpXFMElement _rshift_c(self, long n):
|
|
573
|
+
"""
|
|
574
|
+
Divide ``self`` by the uniformizer raised to the power ``n``.
|
|
575
|
+
|
|
576
|
+
Throws away the nonpositive part of the series expansion.
|
|
577
|
+
The top digits will be garbage. If ``n`` is negative, left
|
|
578
|
+
shifts by ``-n``.
|
|
579
|
+
|
|
580
|
+
EXAMPLES::
|
|
581
|
+
|
|
582
|
+
sage: R = ZpFM(5,5,print_mode='digits')
|
|
583
|
+
sage: S.<x> = R[]
|
|
584
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
585
|
+
sage: W.<w> = R.ext(f)
|
|
586
|
+
sage: z = (1 + w)^5
|
|
587
|
+
sage: for m in range(26): '...' + repr(z >> m)[len(repr(z >> m)) - 25 + m:] # indirect doctest
|
|
588
|
+
'...4001400444441030421100001'
|
|
589
|
+
'...400140044444103042110000'
|
|
590
|
+
'...40014004444410304211000'
|
|
591
|
+
'...4001400444441030421100'
|
|
592
|
+
'...400140044444103042110'
|
|
593
|
+
'...40014004444410304211'
|
|
594
|
+
'...4001400444441030421'
|
|
595
|
+
'...400140044444103042'
|
|
596
|
+
'...40014004444410304'
|
|
597
|
+
'...4001400444441030'
|
|
598
|
+
'...400140044444103'
|
|
599
|
+
'...40014004444410'
|
|
600
|
+
'...4001400444441'
|
|
601
|
+
'...400140044444'
|
|
602
|
+
'...40014004444'
|
|
603
|
+
'...4001400444'
|
|
604
|
+
'...400140044'
|
|
605
|
+
'...40014004'
|
|
606
|
+
'...4001400'
|
|
607
|
+
'...400140'
|
|
608
|
+
'...40014'
|
|
609
|
+
'...4001'
|
|
610
|
+
'...400'
|
|
611
|
+
'...40'
|
|
612
|
+
'...4'
|
|
613
|
+
'...'
|
|
614
|
+
sage: repr(z >> (-4))
|
|
615
|
+
'...4004444410304211000010000'
|
|
616
|
+
"""
|
|
617
|
+
if n < 0:
|
|
618
|
+
return self._lshift_c(-n)
|
|
619
|
+
if n == 0:
|
|
620
|
+
return self
|
|
621
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
622
|
+
if n < self.prime_pow.ram_prec_cap:
|
|
623
|
+
if self.prime_pow.e == 1:
|
|
624
|
+
ZZ_pX_right_pshift(ans.value, self.value, self.prime_pow.pow_ZZ_tmp(n)[0], self.prime_pow.get_top_context().x)
|
|
625
|
+
else:
|
|
626
|
+
# Why is this not eis_shift_capdiv?!!
|
|
627
|
+
self.prime_pow.eis_shift(&ans.value, &self.value, n, self.prime_pow.prec_cap)
|
|
628
|
+
return ans
|
|
629
|
+
|
|
630
|
+
def __rshift__(pAdicZZpXFMElement self, shift):
|
|
631
|
+
"""
|
|
632
|
+
Divide ``self`` by the uniformizer raised to the power ``n``.
|
|
633
|
+
|
|
634
|
+
Throws away the nonpositive part of the series expansion.
|
|
635
|
+
The top digits will be garbage. If ``n`` is negative, left
|
|
636
|
+
shifts by ``-n``.
|
|
637
|
+
|
|
638
|
+
EXAMPLES::
|
|
639
|
+
|
|
640
|
+
sage: R = ZpFM(5,5)
|
|
641
|
+
sage: S.<x> = R[]
|
|
642
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
643
|
+
sage: W.<w> = R.ext(f)
|
|
644
|
+
sage: z = (1 + w)^5
|
|
645
|
+
sage: z
|
|
646
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14
|
|
647
|
+
+ 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
648
|
+
sage: z >> (6) # indirect doctest
|
|
649
|
+
1 + 2*w + 4*w^2 + 3*w^4 + w^6 + 4*w^7 + 4*w^8 + 4*w^9 + 4*w^10 + 4*w^11
|
|
650
|
+
+ 4*w^14 + w^15 + 4*w^18 + 4*w^19 + 2*w^20 + 3*w^21 + 2*w^22 + 3*w^24
|
|
651
|
+
sage: z >> (-4)
|
|
652
|
+
w^4 + w^9 + w^10 + 2*w^11 + 4*w^12 + 3*w^14 + w^16 + 4*w^17
|
|
653
|
+
+ 4*w^18 + 4*w^19 + 4*w^20 + 4*w^21 + 4*w^24
|
|
654
|
+
"""
|
|
655
|
+
cdef pAdicZZpXFMElement ans
|
|
656
|
+
if not isinstance(shift, Integer):
|
|
657
|
+
shift = Integer(shift)
|
|
658
|
+
if mpz_fits_slong_p((<Integer>shift).value) == 0:
|
|
659
|
+
ans = self._new_c()
|
|
660
|
+
return ans
|
|
661
|
+
return self._rshift_c(mpz_get_si((<Integer>shift).value))
|
|
662
|
+
|
|
663
|
+
cpdef _neg_(self):
|
|
664
|
+
"""
|
|
665
|
+
Return ``-self``.
|
|
666
|
+
|
|
667
|
+
EXAMPLES::
|
|
668
|
+
|
|
669
|
+
sage: R = ZpFM(5,5)
|
|
670
|
+
sage: S.<x> = R[]
|
|
671
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
672
|
+
sage: W.<w> = R.ext(f)
|
|
673
|
+
sage: z = (1 + w)^5; z
|
|
674
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14
|
|
675
|
+
+ 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
676
|
+
sage: -z # indirect doctest
|
|
677
|
+
4 + 3*w^5 + 4*w^6 + w^7 + w^8 + w^9 + w^10 + w^11 + 2*w^12 + 4*w^13
|
|
678
|
+
+ 4*w^15 + 3*w^16 + w^17 + 2*w^18 + 3*w^19 + 2*w^21 + 4*w^23 + 4*w^24
|
|
679
|
+
sage: y = z + (-z); y
|
|
680
|
+
0
|
|
681
|
+
sage: -y
|
|
682
|
+
0
|
|
683
|
+
"""
|
|
684
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
685
|
+
ZZ_pX_negate(ans.value, self.value)
|
|
686
|
+
return ans
|
|
687
|
+
|
|
688
|
+
def __pow__(pAdicZZpXFMElement self, right, m): # m ignored
|
|
689
|
+
"""
|
|
690
|
+
Compute ``self`` ^ ``right``.
|
|
691
|
+
|
|
692
|
+
EXAMPLES::
|
|
693
|
+
|
|
694
|
+
sage: R = ZpFM(5,5)
|
|
695
|
+
sage: S.<x> = R[]
|
|
696
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
697
|
+
sage: W.<w> = R.ext(f)
|
|
698
|
+
sage: (1 + w)^5 # indirect doctest
|
|
699
|
+
1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14
|
|
700
|
+
+ 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24
|
|
701
|
+
sage: (1 + w)^-5
|
|
702
|
+
1 + 4*w^5 + 4*w^6 + 3*w^7 + w^8 + 2*w^10 + w^11 + w^12 + 2*w^14
|
|
703
|
+
+ 3*w^16 + 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24
|
|
704
|
+
|
|
705
|
+
TESTS:
|
|
706
|
+
|
|
707
|
+
We define ``0^0`` to be unity, :issue:`13786`::
|
|
708
|
+
|
|
709
|
+
sage: R = ZpFM(5,5)
|
|
710
|
+
sage: S.<x> = R[]
|
|
711
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
712
|
+
sage: W.<w> = R.ext(f)
|
|
713
|
+
sage: type(W(0))
|
|
714
|
+
<class 'sage.rings.padics.padic_ZZ_pX_FM_element.pAdicZZpXFMElement'>
|
|
715
|
+
sage: W(0)^0
|
|
716
|
+
1
|
|
717
|
+
sage: W(0)^0 == W(1)
|
|
718
|
+
True
|
|
719
|
+
|
|
720
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
721
|
+
|
|
722
|
+
sage: R = ZpFM(5,5)
|
|
723
|
+
sage: S.<x> = R[]
|
|
724
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
725
|
+
sage: W.<w> = R.ext(f)
|
|
726
|
+
sage: type(W(0)^0) == type(W(0))
|
|
727
|
+
True
|
|
728
|
+
"""
|
|
729
|
+
if not isinstance(right, Integer):
|
|
730
|
+
right = Integer(right)
|
|
731
|
+
if right == 0 and self == 0:
|
|
732
|
+
return self.parent(1)
|
|
733
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
734
|
+
cdef ntl_ZZ rZZ = ntl_ZZ.__new__(ntl_ZZ)
|
|
735
|
+
mpz_to_ZZ(&rZZ.x, (<Integer>right).value)
|
|
736
|
+
if mpz_sgn((<Integer>right).value) < 0:
|
|
737
|
+
if self.valuation_c() > 0:
|
|
738
|
+
raise ValueError("cannot invert non-unit")
|
|
739
|
+
sig_on()
|
|
740
|
+
if self.prime_pow.e == 1:
|
|
741
|
+
ZZ_pX_InvMod_newton_unram(ans.value, self.value, self.prime_pow.get_top_modulus()[0], self.prime_pow.get_top_context().x, self.prime_pow.get_context(1).x)
|
|
742
|
+
else:
|
|
743
|
+
ZZ_pX_InvMod_newton_ram(ans.value, self.value, self.prime_pow.get_top_modulus()[0], self.prime_pow.get_top_context().x)
|
|
744
|
+
ZZ_negate(rZZ.x, rZZ.x)
|
|
745
|
+
ZZ_pX_PowerMod_pre(ans.value, ans.value, rZZ.x, self.prime_pow.get_top_modulus()[0])
|
|
746
|
+
sig_off()
|
|
747
|
+
else:
|
|
748
|
+
sig_on()
|
|
749
|
+
ZZ_pX_PowerMod_pre(ans.value, self.value, rZZ.x, self.prime_pow.get_top_modulus()[0])
|
|
750
|
+
sig_off()
|
|
751
|
+
return ans
|
|
752
|
+
|
|
753
|
+
cpdef _add_(self, right):
|
|
754
|
+
"""
|
|
755
|
+
Return ``self`` + ``right``.
|
|
756
|
+
|
|
757
|
+
EXAMPLES::
|
|
758
|
+
|
|
759
|
+
sage: R = ZpFM(5,5)
|
|
760
|
+
sage: S.<x> = R[]
|
|
761
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
762
|
+
sage: W.<w> = R.ext(f)
|
|
763
|
+
sage: (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11) - 69 # indirect doctest
|
|
764
|
+
1 + 4*w^13 + 2*w^16 + 4*w^17 + 3*w^18 + 4*w^20 + 4*w^22
|
|
765
|
+
sage: -69 + (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11)
|
|
766
|
+
1 + 4*w^13 + 2*w^16 + 4*w^17 + 3*w^18 + 4*w^20 + 4*w^22
|
|
767
|
+
"""
|
|
768
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
769
|
+
ZZ_pX_add(ans.value, self.value, (<pAdicZZpXFMElement>right).value)
|
|
770
|
+
return ans
|
|
771
|
+
|
|
772
|
+
cpdef _mul_(self, right):
|
|
773
|
+
"""
|
|
774
|
+
Return the product of ``self`` and ``right``.
|
|
775
|
+
|
|
776
|
+
EXAMPLES::
|
|
777
|
+
|
|
778
|
+
sage: R = ZpFM(5,5)
|
|
779
|
+
sage: S.<x> = R[]
|
|
780
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
781
|
+
sage: W.<w> = R.ext(f)
|
|
782
|
+
sage: a = W(329)
|
|
783
|
+
sage: b = W(111)
|
|
784
|
+
sage: a*b # indirect doctest
|
|
785
|
+
4 + 3*w^5 + w^7 + 2*w^9 + 4*w^11 + 3*w^12 + 2*w^13 + w^14 + 2*w^15
|
|
786
|
+
+ 3*w^16 + 4*w^17 + 4*w^18 + 2*w^19 + 2*w^21 + 4*w^22 + 2*w^23 + w^24
|
|
787
|
+
sage: a * 0
|
|
788
|
+
0
|
|
789
|
+
sage: W(125) * W(375)
|
|
790
|
+
0
|
|
791
|
+
"""
|
|
792
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
793
|
+
ZZ_pX_MulMod_pre(ans.value, self.value, (<pAdicZZpXFMElement>right).value, self.prime_pow.get_top_modulus()[0])
|
|
794
|
+
return ans
|
|
795
|
+
|
|
796
|
+
cpdef _sub_(self, right):
|
|
797
|
+
"""
|
|
798
|
+
Return the difference of ``self`` and ``right``.
|
|
799
|
+
|
|
800
|
+
EXAMPLES::
|
|
801
|
+
|
|
802
|
+
sage: R = ZpFM(5,5)
|
|
803
|
+
sage: S.<x> = R[]
|
|
804
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
805
|
+
sage: W.<w> = R.ext(f)
|
|
806
|
+
sage: a = W(329)
|
|
807
|
+
sage: b = W(111)
|
|
808
|
+
sage: a - b # indirect doctest
|
|
809
|
+
3 + 3*w^5 + w^7 + 2*w^9 + 3*w^10 + 4*w^11 + 2*w^13 + 2*w^14 + w^15
|
|
810
|
+
+ 4*w^16 + 2*w^18 + 3*w^19 + 2*w^20 + 3*w^21 + w^22 + w^24
|
|
811
|
+
sage: W(218)
|
|
812
|
+
3 + 3*w^5 + w^7 + 2*w^9 + 3*w^10 + 4*w^11 + 2*w^13 + 2*w^14 + w^15
|
|
813
|
+
+ 4*w^16 + 2*w^18 + 3*w^19 + 2*w^20 + 3*w^21 + w^22 + w^24
|
|
814
|
+
"""
|
|
815
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
816
|
+
ZZ_pX_sub(ans.value, self.value, (<pAdicZZpXFMElement>right).value)
|
|
817
|
+
return ans
|
|
818
|
+
|
|
819
|
+
cpdef _div_(self, _right):
|
|
820
|
+
"""
|
|
821
|
+
Return the quotient of ``self`` by ``right``.
|
|
822
|
+
|
|
823
|
+
If ``right`` is not a unit, raises a :exc:`ValueError`.
|
|
824
|
+
|
|
825
|
+
EXAMPLES::
|
|
826
|
+
|
|
827
|
+
sage: R = ZpFM(5,5)
|
|
828
|
+
sage: S.<x> = R[]
|
|
829
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
830
|
+
sage: W.<w> = R.ext(f)
|
|
831
|
+
sage: W(125) / W(14) # indirect doctest
|
|
832
|
+
4*w^15 + 4*w^17 + w^19 + w^20 + w^23 + 2*w^24
|
|
833
|
+
sage: 1 / W(14) == ~W(14)
|
|
834
|
+
True
|
|
835
|
+
sage: 1 / w
|
|
836
|
+
Traceback (most recent call last):
|
|
837
|
+
...
|
|
838
|
+
ValueError: cannot invert non-unit
|
|
839
|
+
|
|
840
|
+
We check that :issue:`11403` has been resolved::
|
|
841
|
+
|
|
842
|
+
sage: R.<t> = Zq(8,2,'fixed-mod')
|
|
843
|
+
sage: 1/(t+t^2)
|
|
844
|
+
(t + 1) + t^2*2
|
|
845
|
+
"""
|
|
846
|
+
cdef pAdicZZpXFMElement right = <pAdicZZpXFMElement>_right
|
|
847
|
+
if right.valuation_c() > 0:
|
|
848
|
+
raise ValueError("cannot invert non-unit")
|
|
849
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
850
|
+
sig_on()
|
|
851
|
+
if self.prime_pow.e == 1:
|
|
852
|
+
ZZ_pX_InvMod_newton_unram(ans.value, right.value, self.prime_pow.get_top_modulus()[0],
|
|
853
|
+
self.prime_pow.get_top_context().x, self.prime_pow.get_context(1).x)
|
|
854
|
+
else:
|
|
855
|
+
ZZ_pX_InvMod_newton_ram(ans.value, right.value, self.prime_pow.get_top_modulus()[0], self.prime_pow.get_top_context().x)
|
|
856
|
+
ZZ_pX_MulMod_pre(ans.value, self.value, ans.value, self.prime_pow.get_top_modulus()[0])
|
|
857
|
+
sig_off()
|
|
858
|
+
return ans
|
|
859
|
+
|
|
860
|
+
def __copy__(self):
|
|
861
|
+
"""
|
|
862
|
+
Return a copy of ``self``.
|
|
863
|
+
|
|
864
|
+
EXAMPLES::
|
|
865
|
+
|
|
866
|
+
sage: R = ZpFM(5,5)
|
|
867
|
+
sage: S.<x> = R[]
|
|
868
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
869
|
+
sage: W.<w> = R.ext(f)
|
|
870
|
+
sage: b = W(45); b
|
|
871
|
+
4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + 3*w^14 + w^16
|
|
872
|
+
+ 2*w^17 + w^19 + 4*w^20 + w^21 + 3*w^22 + 3*w^23 + 4*w^24
|
|
873
|
+
sage: c = copy(b); c
|
|
874
|
+
4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + 3*w^14 + w^16
|
|
875
|
+
+ 2*w^17 + w^19 + 4*w^20 + w^21 + 3*w^22 + 3*w^23 + 4*w^24
|
|
876
|
+
sage: c is b
|
|
877
|
+
False
|
|
878
|
+
"""
|
|
879
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
880
|
+
ans.value = self.value # does this actually copy correctly
|
|
881
|
+
return ans
|
|
882
|
+
|
|
883
|
+
def is_zero(self, absprec=None):
|
|
884
|
+
"""
|
|
885
|
+
Return whether the valuation of ``self`` is at least
|
|
886
|
+
``absprec``; if ``absprec`` is ``None``, return whether
|
|
887
|
+
``self`` is indistinguishable from zero.
|
|
888
|
+
|
|
889
|
+
EXAMPLES::
|
|
890
|
+
|
|
891
|
+
sage: R = ZpFM(5,5)
|
|
892
|
+
sage: S.<x> = R[]
|
|
893
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
894
|
+
sage: W.<w> = R.ext(f)
|
|
895
|
+
sage: O(w^189).is_zero()
|
|
896
|
+
True
|
|
897
|
+
sage: W(0).is_zero()
|
|
898
|
+
True
|
|
899
|
+
sage: a = W(675)
|
|
900
|
+
sage: a.is_zero()
|
|
901
|
+
False
|
|
902
|
+
sage: a.is_zero(7)
|
|
903
|
+
True
|
|
904
|
+
sage: a.is_zero(21)
|
|
905
|
+
False
|
|
906
|
+
"""
|
|
907
|
+
cdef bint ans
|
|
908
|
+
if absprec is None:
|
|
909
|
+
ans = ZZ_pX_IsZero(self.value)
|
|
910
|
+
else:
|
|
911
|
+
if not isinstance(absprec, Integer):
|
|
912
|
+
absprec = Integer(absprec)
|
|
913
|
+
if mpz_fits_slong_p((<Integer>absprec).value) == 0:
|
|
914
|
+
if mpz_sgn((<Integer>absprec).value) < 0:
|
|
915
|
+
return True
|
|
916
|
+
else:
|
|
917
|
+
ans = ZZ_pX_IsZero(self.value)
|
|
918
|
+
else:
|
|
919
|
+
ans = (self.valuation_c() >= mpz_get_si((<Integer>absprec).value))
|
|
920
|
+
return ans
|
|
921
|
+
|
|
922
|
+
def add_bigoh(self, absprec):
|
|
923
|
+
r"""
|
|
924
|
+
Return a new element truncated modulo `\pi^{\text{absprec}}`.
|
|
925
|
+
|
|
926
|
+
This is only implemented for unramified extension at
|
|
927
|
+
this point.
|
|
928
|
+
|
|
929
|
+
INPUT:
|
|
930
|
+
|
|
931
|
+
- ``absprec`` -- integer
|
|
932
|
+
|
|
933
|
+
OUTPUT: a new element truncated modulo `\pi^{\mbox{absprec}}`
|
|
934
|
+
|
|
935
|
+
EXAMPLES::
|
|
936
|
+
|
|
937
|
+
sage: R = Zp(7,4,'fixed-mod')
|
|
938
|
+
sage: a = R(1 + 7 + 7^2)
|
|
939
|
+
sage: a.add_bigoh(1)
|
|
940
|
+
1
|
|
941
|
+
"""
|
|
942
|
+
if not isinstance(absprec, Integer):
|
|
943
|
+
absprec = Integer(absprec)
|
|
944
|
+
if mpz_cmp_ui((<Integer>absprec).value, self.prime_pow.prec_cap) >= 0:
|
|
945
|
+
return self
|
|
946
|
+
|
|
947
|
+
cdef pAdicZZpXFMElement ans = self._new_c()
|
|
948
|
+
cdef ZZ_pX_c tmp
|
|
949
|
+
cdef ntl_ZZ_pContext_class c
|
|
950
|
+
cdef unsigned long aprec
|
|
951
|
+
if self.prime_pow.e == 1:
|
|
952
|
+
if mpz_fits_ulong_p((<Integer>absprec).value) == 0:
|
|
953
|
+
if mpz_sgn((<Integer>absprec).value) < 0:
|
|
954
|
+
return ans # assumes _new_c() initializes to 0
|
|
955
|
+
return self # absprec > prec_cap
|
|
956
|
+
aprec = mpz_get_ui((<Integer>absprec).value)
|
|
957
|
+
if aprec >= self.prime_pow.prec_cap:
|
|
958
|
+
return self
|
|
959
|
+
c = self.prime_pow.get_context(aprec)
|
|
960
|
+
c.restore_c()
|
|
961
|
+
ZZ_pX_conv_modulus(tmp, self.value, c.x)
|
|
962
|
+
ZZ_pX_conv_modulus(ans.value, tmp, (<ntl_ZZ_pContext_class>self.prime_pow.get_top_context()).x)
|
|
963
|
+
else:
|
|
964
|
+
raise NotImplementedError
|
|
965
|
+
return ans
|
|
966
|
+
|
|
967
|
+
def _integer_(self, Z=None):
|
|
968
|
+
r"""
|
|
969
|
+
Return an integer congruent to this element modulo
|
|
970
|
+
`\pi^a`, where `a` is ``self.absolute_precision()``, if possible.
|
|
971
|
+
|
|
972
|
+
EXAMPLES::
|
|
973
|
+
|
|
974
|
+
sage: # needs sage.libs.flint
|
|
975
|
+
sage: ZZ(ZqFM(125,names='a')(-1)) # indirect doctest
|
|
976
|
+
95367431640624
|
|
977
|
+
sage: R = ZpFM(5); S.<x> = ZZ[]; f = x^5 + 25*x^3 - 5; W.<w> = R.ext(f)
|
|
978
|
+
sage: ZZ(W(-1))
|
|
979
|
+
95367431640624
|
|
980
|
+
sage: ZZ(W(0))
|
|
981
|
+
0
|
|
982
|
+
sage: ZZ(W(0,7))
|
|
983
|
+
0
|
|
984
|
+
sage: ZZ(w)
|
|
985
|
+
Traceback (most recent call last):
|
|
986
|
+
...
|
|
987
|
+
ValueError: This element not well approximated by an integer.
|
|
988
|
+
sage: ZZ(W(5))
|
|
989
|
+
5
|
|
990
|
+
"""
|
|
991
|
+
cdef ZZ_c tmp_z
|
|
992
|
+
if ZZ_pX_deg(self.value) > 0:
|
|
993
|
+
raise ValueError("This element not well approximated by an integer.")
|
|
994
|
+
cdef Integer ans = Integer.__new__(Integer)
|
|
995
|
+
tmp_z = ZZ_p_rep(ZZ_pX_ConstTerm(self.value))
|
|
996
|
+
ZZ_to_mpz(ans.value, &tmp_z)
|
|
997
|
+
return ans
|
|
998
|
+
|
|
999
|
+
def matrix_mod_pn(self):
|
|
1000
|
+
r"""
|
|
1001
|
+
Return the matrix of right multiplication by the element on
|
|
1002
|
+
the power basis `1, x, x^2, \ldots, x^{d-1}` for this
|
|
1003
|
+
extension field.
|
|
1004
|
+
|
|
1005
|
+
The **rows** of this matrix give the images of each of the `x^i`.
|
|
1006
|
+
The entries of the matrices are ``IntegerMod`` elements,
|
|
1007
|
+
defined modulo ``p^(self.absprec() / e)``.
|
|
1008
|
+
|
|
1009
|
+
Raises an error if ``self`` has negative valuation.
|
|
1010
|
+
|
|
1011
|
+
EXAMPLES::
|
|
1012
|
+
|
|
1013
|
+
sage: R = ZpFM(5,5)
|
|
1014
|
+
sage: S.<x> = R[]
|
|
1015
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1016
|
+
sage: W.<w> = R.ext(f)
|
|
1017
|
+
sage: a = (3+w)^7
|
|
1018
|
+
sage: a.matrix_mod_pn() # needs sage.geometry.polyhedron
|
|
1019
|
+
[2757 333 1068 725 2510]
|
|
1020
|
+
[ 50 1507 483 318 725]
|
|
1021
|
+
[ 500 50 3007 2358 318]
|
|
1022
|
+
[1590 1375 1695 1032 2358]
|
|
1023
|
+
[2415 590 2370 2970 1032]
|
|
1024
|
+
"""
|
|
1025
|
+
from sage.matrix.constructor import matrix
|
|
1026
|
+
R = IntegerModRing(self.prime_pow.pow_Integer(self.prime_pow.prec_cap))
|
|
1027
|
+
n = self.prime_pow.deg
|
|
1028
|
+
L = []
|
|
1029
|
+
cdef ntl_ZZ_pX cur = <ntl_ZZ_pX>self._ntl_rep()
|
|
1030
|
+
cur.c.restore_c()
|
|
1031
|
+
cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_top_modulus()
|
|
1032
|
+
cdef ZZ_pX_c x
|
|
1033
|
+
ZZ_pX_SetX(x)
|
|
1034
|
+
cdef Py_ssize_t i
|
|
1035
|
+
zero = int(0)
|
|
1036
|
+
for i in range(n):
|
|
1037
|
+
curlist = cur.list()
|
|
1038
|
+
L.extend(curlist + [zero]*(n - len(curlist)))
|
|
1039
|
+
ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0])
|
|
1040
|
+
return matrix(R, n, n, L)
|
|
1041
|
+
|
|
1042
|
+
# def matrix(self, base=None):
|
|
1043
|
+
# """
|
|
1044
|
+
# If base is None, return the matrix of right multiplication by
|
|
1045
|
+
# the element on the power basis `1, x, x^2, \ldots, x^{d-1}`
|
|
1046
|
+
# for this extension field. Thus the \emph{rows} of this matrix
|
|
1047
|
+
# give the images of each of the `x^i`.
|
|
1048
|
+
|
|
1049
|
+
# If base is not None, then base must be either a field that
|
|
1050
|
+
# embeds in the parent of self or a morphism to the parent of
|
|
1051
|
+
# self, in which case this function returns the matrix of
|
|
1052
|
+
# multiplication by self on the power basis, where we view the
|
|
1053
|
+
# parent field as a field over base.
|
|
1054
|
+
|
|
1055
|
+
# INPUT:
|
|
1056
|
+
|
|
1057
|
+
# base -- field or morphism
|
|
1058
|
+
# """
|
|
1059
|
+
# raise NotImplementedError
|
|
1060
|
+
|
|
1061
|
+
def norm(self, base=None):
|
|
1062
|
+
r"""
|
|
1063
|
+
Return the absolute or relative norm of this element.
|
|
1064
|
+
|
|
1065
|
+
.. NOTE::
|
|
1066
|
+
|
|
1067
|
+
This is not the `p`-adic absolute value. This is a
|
|
1068
|
+
field theoretic norm down to a ground ring.
|
|
1069
|
+
|
|
1070
|
+
If you want the `p`-adic absolute value, use the :func:`abs()`
|
|
1071
|
+
function instead.
|
|
1072
|
+
|
|
1073
|
+
If `K` is given then `K` must be a subfield of the parent `L` of
|
|
1074
|
+
``self``, in which case the norm is the relative norm from `L` to `K`.
|
|
1075
|
+
In all other cases, the norm is the absolute norm down to `\QQ_p`
|
|
1076
|
+
or `\ZZ_p`.
|
|
1077
|
+
|
|
1078
|
+
EXAMPLES::
|
|
1079
|
+
|
|
1080
|
+
sage: R = ZpCR(5,5)
|
|
1081
|
+
sage: S.<x> = R[]
|
|
1082
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1083
|
+
sage: W.<w> = R.ext(f)
|
|
1084
|
+
sage: ((1+2*w)^5).norm()
|
|
1085
|
+
1 + 5^2 + O(5^5)
|
|
1086
|
+
sage: ((1+2*w)).norm()^5
|
|
1087
|
+
1 + 5^2 + O(5^5)
|
|
1088
|
+
"""
|
|
1089
|
+
if base is not None:
|
|
1090
|
+
if base is self.parent():
|
|
1091
|
+
return self
|
|
1092
|
+
else:
|
|
1093
|
+
raise NotImplementedError
|
|
1094
|
+
if self._is_exact_zero():
|
|
1095
|
+
return self.parent().ground_ring()(0)
|
|
1096
|
+
elif self._is_inexact_zero():
|
|
1097
|
+
return self.ground_ring(0, self.valuation())
|
|
1098
|
+
norm_of_uniformizer = (-1)**self.parent().degree() * self.parent().defining_polynomial()[0]
|
|
1099
|
+
return self.parent().ground_ring()(self.unit_part().matrix_mod_pn().det()) * norm_of_uniformizer**self.valuation()
|
|
1100
|
+
|
|
1101
|
+
def trace(self, base=None):
|
|
1102
|
+
r"""
|
|
1103
|
+
Return the absolute or relative trace of this element.
|
|
1104
|
+
|
|
1105
|
+
If `K` is given then `K` must be a subfield of the parent `L` of
|
|
1106
|
+
``self``, in which case the norm is the relative norm from `L` to `K`.
|
|
1107
|
+
In all other cases, the norm is the absolute norm down to `\QQ_p`
|
|
1108
|
+
or `\ZZ_p`.
|
|
1109
|
+
|
|
1110
|
+
EXAMPLES::
|
|
1111
|
+
|
|
1112
|
+
sage: R = ZpCR(5,5)
|
|
1113
|
+
sage: S.<x> = R[]
|
|
1114
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1115
|
+
sage: W.<w> = R.ext(f)
|
|
1116
|
+
sage: a = (2+3*w)^7
|
|
1117
|
+
sage: b = (6+w^3)^5
|
|
1118
|
+
sage: a.trace()
|
|
1119
|
+
3*5 + 2*5^2 + 3*5^3 + 2*5^4 + O(5^5)
|
|
1120
|
+
sage: a.trace() + b.trace()
|
|
1121
|
+
4*5 + 5^2 + 5^3 + 2*5^4 + O(5^5)
|
|
1122
|
+
sage: (a+b).trace()
|
|
1123
|
+
4*5 + 5^2 + 5^3 + 2*5^4 + O(5^5)
|
|
1124
|
+
"""
|
|
1125
|
+
if base is not None:
|
|
1126
|
+
if base is self.parent():
|
|
1127
|
+
return self
|
|
1128
|
+
else:
|
|
1129
|
+
raise NotImplementedError
|
|
1130
|
+
if self._is_exact_zero():
|
|
1131
|
+
return self.parent().ground_ring()(0)
|
|
1132
|
+
elif self._is_inexact_zero():
|
|
1133
|
+
return self.ground_ring(0, (self.valuation() - 1) // self.parent().e() + 1)
|
|
1134
|
+
if self.valuation() >= 0:
|
|
1135
|
+
return self.parent().ground_ring()(self.matrix_mod_pn().trace())
|
|
1136
|
+
else:
|
|
1137
|
+
shift = -(self.valuation() // self.parent().e())
|
|
1138
|
+
return self.parent().ground_ring()((self * self.parent().prime() ** shift).matrix_mod_pn().trace()) / self.parent().prime()**shift
|
|
1139
|
+
|
|
1140
|
+
def _ntl_rep(self):
|
|
1141
|
+
"""
|
|
1142
|
+
Return an ``ntl_ZZ_pX`` holding ``self.value``.
|
|
1143
|
+
|
|
1144
|
+
EXAMPLES::
|
|
1145
|
+
|
|
1146
|
+
sage: R = Zp(5,5)
|
|
1147
|
+
sage: S.<x> = R[]
|
|
1148
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1149
|
+
sage: W.<w> = R.ext(f)
|
|
1150
|
+
sage: a = 72 + 4*w^2; b = 17 + 9*w + w^3; c = a + b
|
|
1151
|
+
sage: c._ntl_rep()
|
|
1152
|
+
[89 9 4 1]
|
|
1153
|
+
"""
|
|
1154
|
+
self.prime_pow.restore_top_context()
|
|
1155
|
+
cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
|
|
1156
|
+
ans.c = self.prime_pow.get_top_context()
|
|
1157
|
+
ans.x = self.value
|
|
1158
|
+
return ans
|
|
1159
|
+
|
|
1160
|
+
def _polynomial_list(self, pad=False):
|
|
1161
|
+
"""
|
|
1162
|
+
Return the coefficient list for a polynomial over the base ring
|
|
1163
|
+
yielding this element.
|
|
1164
|
+
|
|
1165
|
+
INPUT:
|
|
1166
|
+
|
|
1167
|
+
- ``pad`` -- whether to pad the result with zeros of the
|
|
1168
|
+
appropriate precision
|
|
1169
|
+
|
|
1170
|
+
EXAMPLES::
|
|
1171
|
+
|
|
1172
|
+
sage: R.<x> = ZZ[]
|
|
1173
|
+
sage: W.<w> = ZpFM(5).extension(x^3 - 5)
|
|
1174
|
+
sage: (1 + w)._polynomial_list()
|
|
1175
|
+
[1, 1]
|
|
1176
|
+
sage: (1 + w + O(w^11))._polynomial_list(pad=True)
|
|
1177
|
+
[1, 1, 0]
|
|
1178
|
+
"""
|
|
1179
|
+
R = self.base_ring()
|
|
1180
|
+
if self.is_zero():
|
|
1181
|
+
L = []
|
|
1182
|
+
else:
|
|
1183
|
+
L = [Integer(c) for c in self._ntl_rep().list()]
|
|
1184
|
+
if pad:
|
|
1185
|
+
n = self.parent().degree()
|
|
1186
|
+
L.extend([R.zero()] * (n - len(L)))
|
|
1187
|
+
return L
|
|
1188
|
+
|
|
1189
|
+
def polynomial(self, var='x'):
|
|
1190
|
+
"""
|
|
1191
|
+
Return a polynomial over the base ring that yields this element
|
|
1192
|
+
when evaluated at the generator of the parent.
|
|
1193
|
+
|
|
1194
|
+
INPUT:
|
|
1195
|
+
|
|
1196
|
+
- ``var`` -- string, the variable name for the polynomial
|
|
1197
|
+
|
|
1198
|
+
EXAMPLES::
|
|
1199
|
+
|
|
1200
|
+
sage: S.<x> = ZZ[]
|
|
1201
|
+
sage: W.<w> = ZpFM(5).extension(x^2 - 5)
|
|
1202
|
+
sage: (w + 5).polynomial()
|
|
1203
|
+
x + 5
|
|
1204
|
+
"""
|
|
1205
|
+
R = self.base_ring()
|
|
1206
|
+
S = R[var]
|
|
1207
|
+
return S(self._polynomial_list())
|
|
1208
|
+
|
|
1209
|
+
cdef ZZ_p_c _const_term(self) noexcept:
|
|
1210
|
+
"""
|
|
1211
|
+
Return the constant term of ``self.unit``.
|
|
1212
|
+
|
|
1213
|
+
.. NOTE::
|
|
1214
|
+
|
|
1215
|
+
This may be divisible by `p` if ``self`` is not normalized.
|
|
1216
|
+
|
|
1217
|
+
EXAMPLES::
|
|
1218
|
+
|
|
1219
|
+
sage: R = ZpFM(5,5)
|
|
1220
|
+
sage: S.<x> = R[]
|
|
1221
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1222
|
+
sage: W.<w> = R.ext(f)
|
|
1223
|
+
sage: a = W(566)
|
|
1224
|
+
sage: a._const_term_test() # indirect doctest
|
|
1225
|
+
566
|
|
1226
|
+
"""
|
|
1227
|
+
return ZZ_pX_ConstTerm(self.value)
|
|
1228
|
+
|
|
1229
|
+
def is_equal_to(self, right, absprec=None):
|
|
1230
|
+
"""
|
|
1231
|
+
Return whether ``self`` is equal to ``right`` modulo
|
|
1232
|
+
``self.uniformizer()^absprec``.
|
|
1233
|
+
|
|
1234
|
+
If ``absprec`` is ``None``, returns if ``self`` is equal to
|
|
1235
|
+
``right`` modulo the precision cap.
|
|
1236
|
+
|
|
1237
|
+
EXAMPLES::
|
|
1238
|
+
|
|
1239
|
+
sage: R = Zp(5,5)
|
|
1240
|
+
sage: S.<x> = R[]
|
|
1241
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1242
|
+
sage: W.<w> = R.ext(f)
|
|
1243
|
+
sage: a = W(47); b = W(47 + 25)
|
|
1244
|
+
sage: a.is_equal_to(b)
|
|
1245
|
+
False
|
|
1246
|
+
sage: a.is_equal_to(b, 7)
|
|
1247
|
+
True
|
|
1248
|
+
"""
|
|
1249
|
+
# Should be sped up later
|
|
1250
|
+
return (self - right).is_zero(absprec)
|
|
1251
|
+
|
|
1252
|
+
# def lift(self):
|
|
1253
|
+
# """
|
|
1254
|
+
# Returns an element of a number field defined by the same polynomial as
|
|
1255
|
+
# ``self``'s parent that is congruent to self modulo an appropriate ideal.
|
|
1256
|
+
|
|
1257
|
+
# Not currently implemented.
|
|
1258
|
+
# """
|
|
1259
|
+
# raise NotImplementedError
|
|
1260
|
+
|
|
1261
|
+
def lift_to_precision(self, absprec=None):
|
|
1262
|
+
"""
|
|
1263
|
+
Return ``self``.
|
|
1264
|
+
|
|
1265
|
+
EXAMPLES::
|
|
1266
|
+
|
|
1267
|
+
sage: R = ZpFM(5,5)
|
|
1268
|
+
sage: S.<x> = R[]
|
|
1269
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1270
|
+
sage: W.<w> = R.ext(f)
|
|
1271
|
+
sage: w.lift_to_precision(10000)
|
|
1272
|
+
w
|
|
1273
|
+
"""
|
|
1274
|
+
return self
|
|
1275
|
+
|
|
1276
|
+
def expansion(self, n=None, lift_mode='simple'):
|
|
1277
|
+
r"""
|
|
1278
|
+
Return a list giving a series representation of this element.
|
|
1279
|
+
|
|
1280
|
+
- If ``lift_mode == 'simple' or 'smallest'``, the returned list will
|
|
1281
|
+
consist of
|
|
1282
|
+
|
|
1283
|
+
* integers (in the eisenstein case) or
|
|
1284
|
+
|
|
1285
|
+
* lists of integers (in the unramified case).
|
|
1286
|
+
|
|
1287
|
+
- this element can be reconstructed as
|
|
1288
|
+
|
|
1289
|
+
* a sum of elements of the list times powers of the
|
|
1290
|
+
uniformiser (in the eisenstein case), or
|
|
1291
|
+
|
|
1292
|
+
* as a sum of powers of the `p` times polynomials in the
|
|
1293
|
+
generator (in the unramified case).
|
|
1294
|
+
|
|
1295
|
+
- If ``lift_mode == 'simple'``, all integers will be in the range
|
|
1296
|
+
`[0,p-1]`,
|
|
1297
|
+
|
|
1298
|
+
- If ``lift_mode == 'smallest'`` they will be in the range `[(1-p)/2,
|
|
1299
|
+
p/2]`.
|
|
1300
|
+
|
|
1301
|
+
- If ``lift_mode == 'teichmuller'``, returns a list of
|
|
1302
|
+
``pAdicZZpXCRElements``, all of which are Teichmuller representatives
|
|
1303
|
+
and such that this element is the sum of that list times powers of the
|
|
1304
|
+
uniformizer.
|
|
1305
|
+
|
|
1306
|
+
INPUT:
|
|
1307
|
+
|
|
1308
|
+
- ``n`` -- integer (default: ``None``); if given, returns the
|
|
1309
|
+
corresponding entry in the expansion
|
|
1310
|
+
|
|
1311
|
+
EXAMPLES::
|
|
1312
|
+
|
|
1313
|
+
sage: R = ZpFM(5,5)
|
|
1314
|
+
sage: S.<x> = R[]
|
|
1315
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1316
|
+
sage: W.<w> = R.ext(f)
|
|
1317
|
+
sage: y = W(775); y
|
|
1318
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24
|
|
1319
|
+
sage: (y>>9).expansion()
|
|
1320
|
+
[0, 1, 0, 4, 0, 2, 1, 2, 4, 1, 0, 1, 2, 3, 1, 1, 4, 1, 2, 4, 1, 0, 0, 3]
|
|
1321
|
+
sage: (y>>9).expansion(lift_mode='smallest')
|
|
1322
|
+
[0, 1, 0, -1, 0, 2, 1, 2, 0, 1, 2, 1, 1, -1, -1, 2, -2, 0, -2, -2, -2, 0, -2, -2, 2]
|
|
1323
|
+
sage: w^10 - w^12 + 2*w^14 + w^15 + 2*w^16 + w^18 + 2*w^19 + w^20 + w^21 - w^22 - w^23 + 2*w^24
|
|
1324
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24
|
|
1325
|
+
sage: g = x^3 + 3*x + 3
|
|
1326
|
+
|
|
1327
|
+
sage: # needs sage.libs.flint
|
|
1328
|
+
sage: A.<a> = R.ext(g)
|
|
1329
|
+
sage: y = 75 + 45*a + 1200*a^2; y
|
|
1330
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4
|
|
1331
|
+
sage: E = y.expansion(); E
|
|
1332
|
+
5-adic expansion of 4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4
|
|
1333
|
+
sage: list(E)
|
|
1334
|
+
[[], [0, 4], [3, 1, 3], [0, 0, 4], [0, 0, 1]]
|
|
1335
|
+
sage: list(y.expansion(lift_mode='smallest'))
|
|
1336
|
+
[[], [0, -1], [-2, 2, -2], [1], [0, 0, 2]]
|
|
1337
|
+
sage: 5*((-2*5 + 25) + (-1 + 2*5)*a + (-2*5 + 2*125)*a^2)
|
|
1338
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4
|
|
1339
|
+
sage: W(0).expansion()
|
|
1340
|
+
[]
|
|
1341
|
+
sage: list(A(0,4).expansion())
|
|
1342
|
+
[]
|
|
1343
|
+
|
|
1344
|
+
Check that :issue:`25879` has been resolved::
|
|
1345
|
+
|
|
1346
|
+
sage: K = ZpCA(3,5)
|
|
1347
|
+
sage: R.<a> = K[]
|
|
1348
|
+
sage: L.<a> = K.extension(a^2 - 3)
|
|
1349
|
+
sage: a.residue()
|
|
1350
|
+
0
|
|
1351
|
+
"""
|
|
1352
|
+
if lift_mode == 'teichmuller':
|
|
1353
|
+
zero = self.parent()(0)
|
|
1354
|
+
elif self.prime_pow.e == 1:
|
|
1355
|
+
zero = []
|
|
1356
|
+
else:
|
|
1357
|
+
zero = Integer(0)
|
|
1358
|
+
ordp = self.valuation()
|
|
1359
|
+
if isinstance(n, slice):
|
|
1360
|
+
return self.slice(n.start, n.stop, n.step)
|
|
1361
|
+
elif n is not None:
|
|
1362
|
+
if self.is_zero() or n >= self.prime_pow.ram_prec_cap or n < ordp:
|
|
1363
|
+
return zero
|
|
1364
|
+
if self.is_zero():
|
|
1365
|
+
return []
|
|
1366
|
+
if lift_mode == 'simple':
|
|
1367
|
+
ulist = self.ext_p_list(pos=True)
|
|
1368
|
+
elif lift_mode == 'smallest':
|
|
1369
|
+
ulist = self.ext_p_list(pos=False)
|
|
1370
|
+
elif lift_mode == 'teichmuller':
|
|
1371
|
+
if n is None:
|
|
1372
|
+
ulist = self.teichmuller_list()
|
|
1373
|
+
else:
|
|
1374
|
+
return self.teichmuller_expansion(n)
|
|
1375
|
+
else:
|
|
1376
|
+
raise ValueError("lift mode must be one of 'simple', 'smallest' or 'teichmuller'")
|
|
1377
|
+
if n is not None:
|
|
1378
|
+
try:
|
|
1379
|
+
return ulist[n - ordp]
|
|
1380
|
+
except IndexError:
|
|
1381
|
+
return zero
|
|
1382
|
+
return [zero] * ordp + ulist
|
|
1383
|
+
|
|
1384
|
+
def teichmuller_expansion(self, n=None):
|
|
1385
|
+
r"""
|
|
1386
|
+
Return a list `[a_0, a_1, \ldots, a_n]` such that.
|
|
1387
|
+
|
|
1388
|
+
- `a_i^q = a_i`
|
|
1389
|
+
- ``self.unit_part()`` = `\sum_{i = 0}^n a_i \pi^i`, where `\pi` is a
|
|
1390
|
+
uniformizer of ``self.parent()``
|
|
1391
|
+
|
|
1392
|
+
INPUT:
|
|
1393
|
+
|
|
1394
|
+
- ``n`` -- integer (default: ``None``); if given, returns the corresponding
|
|
1395
|
+
entry in the expansion
|
|
1396
|
+
|
|
1397
|
+
EXAMPLES::
|
|
1398
|
+
|
|
1399
|
+
sage: # needs sage.libs.flint
|
|
1400
|
+
sage: R.<a> = ZqFM(5^4,4)
|
|
1401
|
+
sage: E = a.teichmuller_expansion(); E
|
|
1402
|
+
5-adic expansion of a (teichmuller)
|
|
1403
|
+
sage: list(E)
|
|
1404
|
+
[a + (2*a^3 + 2*a^2 + 3*a + 4)*5 + (4*a^3 + 3*a^2 + 3*a + 2)*5^2 + (4*a^2 + 2*a + 2)*5^3,
|
|
1405
|
+
(3*a^3 + 3*a^2 + 2*a + 1) + (a^3 + 4*a^2 + 1)*5 + (a^2 + 4*a + 4)*5^2 + (4*a^2 + a + 3)*5^3,
|
|
1406
|
+
(4*a^3 + 2*a^2 + a + 1) + (2*a^3 + 2*a^2 + 2*a + 4)*5 + (3*a^3 + 2*a^2 + a + 1)*5^2 + (a^3 + a^2 + 2)*5^3,
|
|
1407
|
+
(a^3 + a^2 + a + 4) + (3*a^3 + 1)*5 + (3*a^3 + a + 2)*5^2 + (3*a^3 + 3*a^2 + 3*a + 1)*5^3]
|
|
1408
|
+
sage: sum([c * 5^i for i, c in enumerate(E)])
|
|
1409
|
+
a
|
|
1410
|
+
sage: all(c^625 == c for c in E)
|
|
1411
|
+
True
|
|
1412
|
+
|
|
1413
|
+
sage: S.<x> = ZZ[]
|
|
1414
|
+
sage: f = x^3 - 98*x + 7
|
|
1415
|
+
sage: W.<w> = ZpFM(7,3).ext(f)
|
|
1416
|
+
sage: b = (1+w)^5; L = b.teichmuller_expansion(); L
|
|
1417
|
+
[1,
|
|
1418
|
+
5 + 5*w^3 + w^6 + 4*w^7,
|
|
1419
|
+
3 + 3*w^3 + w^7,
|
|
1420
|
+
3 + 3*w^3 + w^7,
|
|
1421
|
+
0,
|
|
1422
|
+
4 + 5*w^3 + w^6 + 4*w^7,
|
|
1423
|
+
3 + 3*w^3 + w^7,
|
|
1424
|
+
6 + w^3 + 5*w^7,
|
|
1425
|
+
6 + w^3 + 5*w^7]
|
|
1426
|
+
sage: sum([w^i*L[i] for i in range(len(L))]) == b
|
|
1427
|
+
True
|
|
1428
|
+
sage: all(L[i]^(7^3) == L[i] for i in range(9))
|
|
1429
|
+
True
|
|
1430
|
+
|
|
1431
|
+
sage: L = W(3).teichmuller_expansion(); L
|
|
1432
|
+
[3 + 3*w^3 + w^7,
|
|
1433
|
+
0,
|
|
1434
|
+
0,
|
|
1435
|
+
4 + 5*w^3 + w^6 + 4*w^7,
|
|
1436
|
+
0,
|
|
1437
|
+
0,
|
|
1438
|
+
3 + 3*w^3 + w^7,
|
|
1439
|
+
6 + w^3 + 5*w^7]
|
|
1440
|
+
sage: sum([w^i*L[i] for i in range(len(L))])
|
|
1441
|
+
3
|
|
1442
|
+
"""
|
|
1443
|
+
cdef long ordp = self.valuation_c()
|
|
1444
|
+
cdef long rp = self.prime_pow.ram_prec_cap - ordp
|
|
1445
|
+
cdef long goal
|
|
1446
|
+
if n is not None:
|
|
1447
|
+
goal = self.ram_prec_cap - n
|
|
1448
|
+
cdef pAdicZZpXFMElement v
|
|
1449
|
+
if n is None:
|
|
1450
|
+
L = []
|
|
1451
|
+
if ZZ_pX_IsZero(self.value):
|
|
1452
|
+
return L
|
|
1453
|
+
elif n < ordp or n >= self.prime_pow.ram_prec_cap:
|
|
1454
|
+
return self.parent()(0)
|
|
1455
|
+
else:
|
|
1456
|
+
v = self._new_c()
|
|
1457
|
+
cdef pAdicZZpXFMElement u = self.unit_part()
|
|
1458
|
+
if u is self:
|
|
1459
|
+
u = self.__copy__()
|
|
1460
|
+
while u.valuation_c() < rp:
|
|
1461
|
+
if n is None:
|
|
1462
|
+
v = self._new_c()
|
|
1463
|
+
self.prime_pow.teichmuller_set_c(&v.value, &u.value, self.prime_pow.ram_prec_cap)
|
|
1464
|
+
if n is None:
|
|
1465
|
+
L.append(v)
|
|
1466
|
+
elif rp == goal:
|
|
1467
|
+
return v
|
|
1468
|
+
if rp == 1:
|
|
1469
|
+
break
|
|
1470
|
+
ZZ_pX_sub(u.value, u.value, v.value)
|
|
1471
|
+
rp -= 1
|
|
1472
|
+
if self.prime_pow.e == 1:
|
|
1473
|
+
ZZ_pX_right_pshift(u.value, u.value, self.prime_pow.pow_ZZ_tmp(1)[0], self.prime_pow.get_top_context().x)
|
|
1474
|
+
else:
|
|
1475
|
+
self.prime_pow.eis_shift(&u.value, &u.value, 1, self.prime_pow.ram_prec_cap)
|
|
1476
|
+
if n is None:
|
|
1477
|
+
return L
|
|
1478
|
+
else:
|
|
1479
|
+
return self.parent()(0)
|
|
1480
|
+
|
|
1481
|
+
def _teichmuller_set_unsafe(self):
|
|
1482
|
+
"""
|
|
1483
|
+
Set this element to the Teichmuller representative with the
|
|
1484
|
+
same residue.
|
|
1485
|
+
|
|
1486
|
+
.. WARNING::
|
|
1487
|
+
|
|
1488
|
+
This function modifies the element, which is not safe.
|
|
1489
|
+
Elements are supposed to be immutable.
|
|
1490
|
+
|
|
1491
|
+
EXAMPLES::
|
|
1492
|
+
|
|
1493
|
+
sage: R = ZpFM(5,5)
|
|
1494
|
+
sage: S.<x> = R[]
|
|
1495
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1496
|
+
sage: W.<w> = R.ext(f)
|
|
1497
|
+
sage: y = W.teichmuller(3); y # indirect doctest
|
|
1498
|
+
3 + 3*w^5 + w^7 + 2*w^9 + 2*w^10 + 4*w^11 + w^12 + 2*w^13 + 3*w^15
|
|
1499
|
+
+ 2*w^16 + 3*w^17 + w^18 + 3*w^19 + 3*w^20 + 2*w^21 + 2*w^22 + 3*w^23 + 4*w^24
|
|
1500
|
+
sage: y^5 == y
|
|
1501
|
+
True
|
|
1502
|
+
|
|
1503
|
+
sage: # needs sage.libs.flint
|
|
1504
|
+
sage: g = x^3 + 3*x + 3
|
|
1505
|
+
sage: A.<a> = R.ext(g)
|
|
1506
|
+
sage: b = A.teichmuller(1 + 2*a - a^2); b
|
|
1507
|
+
(4*a^2 + 2*a + 1) + 2*a*5 + (3*a^2 + 1)*5^2 + (a + 4)*5^3 + (a^2 + a + 1)*5^4
|
|
1508
|
+
sage: b^125 == b
|
|
1509
|
+
True
|
|
1510
|
+
"""
|
|
1511
|
+
if self.valuation_c() > 0:
|
|
1512
|
+
ZZ_pX_clear(self.value)
|
|
1513
|
+
else:
|
|
1514
|
+
self.prime_pow.teichmuller_set_c(&self.value, &self.value, self.prime_pow.ram_prec_cap)
|
|
1515
|
+
|
|
1516
|
+
# def multiplicative_order(self):
|
|
1517
|
+
# """
|
|
1518
|
+
# Returns the multiplicative order of self, ie the smallest
|
|
1519
|
+
# positive `n` so that there is an exact `p`-adic element congruent
|
|
1520
|
+
# to self modulo ``self``'s precision that is an `n`-th root of unity.
|
|
1521
|
+
|
|
1522
|
+
# Note: unlike the case for Qp and Zp, it is possible to have
|
|
1523
|
+
# non-teichmuller elements with finite orders. This can happen
|
|
1524
|
+
# only if (p-1) divides the ramification index (see the
|
|
1525
|
+
# documentation on __pow__).
|
|
1526
|
+
|
|
1527
|
+
# INPUT:
|
|
1528
|
+
|
|
1529
|
+
# - ``self`` -- a `p`-adic element
|
|
1530
|
+
# - ``prec`` -- integer
|
|
1531
|
+
|
|
1532
|
+
# OUTPUT: integer; the multiplicative order of self
|
|
1533
|
+
# """
|
|
1534
|
+
# raise NotImplementedError
|
|
1535
|
+
|
|
1536
|
+
# def padded_list(self, n, lift_mode='simple'):
|
|
1537
|
+
# """
|
|
1538
|
+
# Returns a list of coefficients of pi starting with `pi^0` up to
|
|
1539
|
+
# `pi^n` exclusive (padded with zeros if needed)
|
|
1540
|
+
|
|
1541
|
+
# """
|
|
1542
|
+
# raise NotImplementedError
|
|
1543
|
+
|
|
1544
|
+
def precision_absolute(self):
|
|
1545
|
+
"""
|
|
1546
|
+
Return the absolute precision of ``self``, ie the precision cap
|
|
1547
|
+
of ``self.parent()``.
|
|
1548
|
+
|
|
1549
|
+
EXAMPLES::
|
|
1550
|
+
|
|
1551
|
+
sage: R = ZpFM(5,5)
|
|
1552
|
+
sage: S.<x> = R[]
|
|
1553
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1554
|
+
sage: W.<w> = R.ext(f)
|
|
1555
|
+
sage: a = W(75); a
|
|
1556
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + 3*w^19 + 2*w^21 + 3*w^22 + 3*w^23
|
|
1557
|
+
sage: a.valuation()
|
|
1558
|
+
10
|
|
1559
|
+
sage: a.precision_absolute()
|
|
1560
|
+
25
|
|
1561
|
+
sage: a.precision_relative()
|
|
1562
|
+
15
|
|
1563
|
+
sage: a.unit_part()
|
|
1564
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + 3*w^9 + 2*w^11 + 3*w^12
|
|
1565
|
+
+ 3*w^13 + w^15 + 4*w^16 + 2*w^17 + w^18 + 3*w^21 + w^22 + 3*w^24
|
|
1566
|
+
"""
|
|
1567
|
+
cdef Integer ans = Integer.__new__(Integer)
|
|
1568
|
+
mpz_set_ui(ans.value, self.prime_pow.ram_prec_cap)
|
|
1569
|
+
return ans
|
|
1570
|
+
|
|
1571
|
+
def precision_relative(self):
|
|
1572
|
+
"""
|
|
1573
|
+
Return the relative precision of ``self``, ie the precision cap
|
|
1574
|
+
of ``self.parent()`` minus the ``valuation of self``.
|
|
1575
|
+
|
|
1576
|
+
EXAMPLES::
|
|
1577
|
+
|
|
1578
|
+
sage: R = ZpFM(5,5)
|
|
1579
|
+
sage: S.<x> = R[]
|
|
1580
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1581
|
+
sage: W.<w> = R.ext(f)
|
|
1582
|
+
sage: a = W(75); a
|
|
1583
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + 3*w^19 + 2*w^21 + 3*w^22 + 3*w^23
|
|
1584
|
+
sage: a.valuation()
|
|
1585
|
+
10
|
|
1586
|
+
sage: a.precision_absolute()
|
|
1587
|
+
25
|
|
1588
|
+
sage: a.precision_relative()
|
|
1589
|
+
15
|
|
1590
|
+
sage: a.unit_part()
|
|
1591
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + 3*w^9 + 2*w^11 + 3*w^12
|
|
1592
|
+
+ 3*w^13 + w^15 + 4*w^16 + 2*w^17 + w^18 + 3*w^21 + w^22 + 3*w^24
|
|
1593
|
+
"""
|
|
1594
|
+
cdef Integer ans = Integer.__new__(Integer)
|
|
1595
|
+
mpz_set_ui(ans.value, self.prime_pow.ram_prec_cap - self.valuation_c())
|
|
1596
|
+
return ans
|
|
1597
|
+
|
|
1598
|
+
cpdef pAdicZZpXFMElement unit_part(self):
|
|
1599
|
+
"""
|
|
1600
|
+
Return the unit part of ``self``, ie
|
|
1601
|
+
``self / uniformizer^(self.valuation())``
|
|
1602
|
+
|
|
1603
|
+
.. WARNING::
|
|
1604
|
+
|
|
1605
|
+
If this element has positive valuation then the unit part
|
|
1606
|
+
is not defined to the full precision of the ring. Asking
|
|
1607
|
+
for the unit part of ``ZpFM(5)(0)`` will not raise an error,
|
|
1608
|
+
but rather return itself.
|
|
1609
|
+
|
|
1610
|
+
EXAMPLES::
|
|
1611
|
+
|
|
1612
|
+
sage: R = ZpFM(5,5)
|
|
1613
|
+
sage: S.<x> = R[]
|
|
1614
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1615
|
+
sage: W.<w> = R.ext(f)
|
|
1616
|
+
sage: a = W(75); a
|
|
1617
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + 3*w^19 + 2*w^21 + 3*w^22 + 3*w^23
|
|
1618
|
+
sage: a.valuation()
|
|
1619
|
+
10
|
|
1620
|
+
sage: a.precision_absolute()
|
|
1621
|
+
25
|
|
1622
|
+
sage: a.precision_relative()
|
|
1623
|
+
15
|
|
1624
|
+
sage: a.unit_part()
|
|
1625
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + 3*w^9 + 2*w^11 + 3*w^12
|
|
1626
|
+
+ 3*w^13 + w^15 + 4*w^16 + 2*w^17 + w^18 + 3*w^21 + w^22 + 3*w^24
|
|
1627
|
+
|
|
1628
|
+
The unit part inserts nonsense digits if this element has
|
|
1629
|
+
positive valuation::
|
|
1630
|
+
|
|
1631
|
+
sage: (a-a).unit_part()
|
|
1632
|
+
0
|
|
1633
|
+
"""
|
|
1634
|
+
return self._rshift_c(self.valuation_c())
|
|
1635
|
+
|
|
1636
|
+
cdef long valuation_c(self) noexcept:
|
|
1637
|
+
"""
|
|
1638
|
+
Return the valuation of ``self``.
|
|
1639
|
+
|
|
1640
|
+
EXAMPLES::
|
|
1641
|
+
|
|
1642
|
+
sage: R = ZpFM(5,5)
|
|
1643
|
+
sage: S.<x> = R[]
|
|
1644
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1645
|
+
sage: W.<w> = R.ext(f)
|
|
1646
|
+
sage: a = W(75); a
|
|
1647
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + 3*w^19 + 2*w^21 + 3*w^22 + 3*w^23
|
|
1648
|
+
sage: a.valuation()
|
|
1649
|
+
10
|
|
1650
|
+
sage: a.precision_absolute()
|
|
1651
|
+
25
|
|
1652
|
+
sage: a.precision_relative()
|
|
1653
|
+
15
|
|
1654
|
+
sage: a.unit_part()
|
|
1655
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + 3*w^9 + 2*w^11 + 3*w^12
|
|
1656
|
+
+ 3*w^13 + w^15 + 4*w^16 + 2*w^17 + w^18 + 3*w^21 + w^22 + 3*w^24
|
|
1657
|
+
"""
|
|
1658
|
+
cdef long valuation = 0, index = 0
|
|
1659
|
+
ZZ_pX_min_val_coeff(valuation, index, self.value, self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
1660
|
+
if index == -1: # self == 0
|
|
1661
|
+
return self.prime_pow.ram_prec_cap
|
|
1662
|
+
if self.prime_pow.e == 1:
|
|
1663
|
+
return valuation
|
|
1664
|
+
else:
|
|
1665
|
+
if index + valuation * self.prime_pow.e >= self.prime_pow.ram_prec_cap:
|
|
1666
|
+
return self.prime_pow.ram_prec_cap
|
|
1667
|
+
else:
|
|
1668
|
+
return index + valuation * self.prime_pow.e
|
|
1669
|
+
|
|
1670
|
+
cdef ext_p_list(self, bint pos):
|
|
1671
|
+
r"""
|
|
1672
|
+
Return a list giving a series representation of ``self``.
|
|
1673
|
+
|
|
1674
|
+
- The returned list will consist of
|
|
1675
|
+
|
|
1676
|
+
* integers (in the eisenstein case) or
|
|
1677
|
+
|
|
1678
|
+
* a lists of integers (in the unramified case).
|
|
1679
|
+
|
|
1680
|
+
- ``self`` can be reconstructed
|
|
1681
|
+
|
|
1682
|
+
* as a sum of elements of the list times powers of the
|
|
1683
|
+
uniformiser (in the eisenstein case), or
|
|
1684
|
+
|
|
1685
|
+
* as a sum of powers of `p` times polynomials in the
|
|
1686
|
+
generator (in the unramified case).
|
|
1687
|
+
|
|
1688
|
+
- If ``pos`` is ``True``, all integers will be in the range `[0,p-1]`,
|
|
1689
|
+
otherwise they will be in the range `[(1-p)/2, p/2]`.
|
|
1690
|
+
|
|
1691
|
+
Note that zeros are truncated from the returned list, so you
|
|
1692
|
+
must use the valuation function to fully reconstruct ``self``.
|
|
1693
|
+
|
|
1694
|
+
EXAMPLES::
|
|
1695
|
+
|
|
1696
|
+
sage: R = ZpFM(5,5)
|
|
1697
|
+
sage: S.<x> = R[]
|
|
1698
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1699
|
+
sage: W.<w> = R.ext(f)
|
|
1700
|
+
sage: y = W(775); y
|
|
1701
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24
|
|
1702
|
+
sage: (y>>9).expansion() # indirect doctest
|
|
1703
|
+
[0, 1, 0, 4, 0, 2, 1, 2, 4, 1, 0, 1, 2, 3, 1, 1, 4, 1, 2, 4, 1, 0, 0, 3]
|
|
1704
|
+
sage: (y>>9).expansion(lift_mode='smallest') # indirect doctest
|
|
1705
|
+
[0, 1, 0, -1, 0, 2, 1, 2, 0, 1, 2, 1, 1, -1, -1, 2, -2, 0, -2, -2, -2, 0, -2, -2, 2]
|
|
1706
|
+
sage: w^10 - w^12 + 2*w^14 + w^15 + 2*w^16 + w^18 + 2*w^19 + w^20 + w^21 - w^22 - w^23 + 2*w^24
|
|
1707
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24
|
|
1708
|
+
sage: g = x^3 + 3*x + 3
|
|
1709
|
+
|
|
1710
|
+
sage: # needs sage.libs.flint
|
|
1711
|
+
sage: A.<a> = R.ext(g)
|
|
1712
|
+
sage: y = 75 + 45*a + 1200*a^2; y
|
|
1713
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4
|
|
1714
|
+
sage: list(y.expansion()) # indirect doctest
|
|
1715
|
+
[[], [0, 4], [3, 1, 3], [0, 0, 4], [0, 0, 1]]
|
|
1716
|
+
sage: list(y.expansion(lift_mode='smallest')) # indirect doctest
|
|
1717
|
+
[[], [0, -1], [-2, 2, -2], [1], [0, 0, 2]]
|
|
1718
|
+
sage: 5*((-2*5 + 25) + (-1 + 2*5)*a + (-2*5 + 2*125)*a^2)
|
|
1719
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4
|
|
1720
|
+
"""
|
|
1721
|
+
return self.ext_p_list_precs(pos, self.prime_pow.ram_prec_cap)
|
|
1722
|
+
|
|
1723
|
+
|
|
1724
|
+
def make_ZZpXFMElement(parent, f):
|
|
1725
|
+
"""
|
|
1726
|
+
Create a new ``pAdicZZpXFMElement`` out of an ``ntl_ZZ_pX`` ``f``, with
|
|
1727
|
+
parent ``parent``. For use with pickling.
|
|
1728
|
+
|
|
1729
|
+
EXAMPLES::
|
|
1730
|
+
|
|
1731
|
+
sage: R = ZpFM(5,5)
|
|
1732
|
+
sage: S.<x> = R[]
|
|
1733
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1734
|
+
sage: W.<w> = R.ext(f)
|
|
1735
|
+
sage: z = (1 + w)^5 - 1
|
|
1736
|
+
sage: loads(dumps(z)) == z # indirect doctest
|
|
1737
|
+
True
|
|
1738
|
+
"""
|
|
1739
|
+
return pAdicZZpXFMElement(parent, f)
|