passagemath-ntl 10.6.36__cp314-cp314t-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.
- passagemath_ntl-10.6.36.dist-info/METADATA +122 -0
- passagemath_ntl-10.6.36.dist-info/RECORD +161 -0
- passagemath_ntl-10.6.36.dist-info/WHEEL +6 -0
- passagemath_ntl-10.6.36.dist-info/top_level.txt +2 -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-0043a3a2.so.44.0.1 +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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-aarch64-linux-gnu.so +0 -0
- sage/rings/bernmm.pyx +161 -0
- sage/rings/bernoulli_mod_p.cpython-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-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-314t-aarch64-linux-gnu.so +0 -0
- sage/schemes/hyperelliptic_curves/hypellfrob.pyx +252 -0
|
@@ -0,0 +1,3277 @@
|
|
|
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`` CR Element
|
|
11
|
+
|
|
12
|
+
This file implements elements of Eisenstein and unramified extensions
|
|
13
|
+
of `\ZZ_p` and `\QQ_p` with capped relative precision.
|
|
14
|
+
|
|
15
|
+
For the parent class see :mod:`sage.rings.padics.padic_extension_leaves`.
|
|
16
|
+
|
|
17
|
+
The underlying implementation is through NTL's ``ZZ_pX`` class. Each
|
|
18
|
+
element contains the following data:
|
|
19
|
+
|
|
20
|
+
- ``ordp`` -- ``long``; a power of the uniformizer to scale the unit
|
|
21
|
+
by. For unramified extensions this uniformizer is `p`, for Eisenstein
|
|
22
|
+
extensions it is not. A value equal to the maximum value of a ``long``
|
|
23
|
+
indicates that the element is an exact zero.
|
|
24
|
+
|
|
25
|
+
- ``relprec`` -- ``long``; a signed integer giving the precision to
|
|
26
|
+
which this element is defined. For nonzero ``relprec``, the
|
|
27
|
+
absolute value gives the power of the uniformizer modulo which the
|
|
28
|
+
unit is defined. A positive value indicates that the element is
|
|
29
|
+
normalized (ie ``unit`` is actually a unit: in the case of
|
|
30
|
+
Eisenstein extensions the constant term is not divisible by `p`, in
|
|
31
|
+
the case of unramified extensions that there is at least one
|
|
32
|
+
coefficient that is not divisible by `p`). A negative value
|
|
33
|
+
indicates that the element may or may not be normalized. A zero
|
|
34
|
+
value indicates that the element is zero to some precision. If so,
|
|
35
|
+
``ordp`` gives the absolute precision of the element. If ``ordp``
|
|
36
|
+
is greater than ``maxordp``, then the element is an exact zero.
|
|
37
|
+
|
|
38
|
+
- ``unit`` -- ``ZZ_pX_c``; an ntl ``ZZ_pX`` storing the unit part
|
|
39
|
+
The variable `x` is the uniformizer in the case of Eisenstein
|
|
40
|
+
extensions. If the element is not normalized, the ``unit`` may or
|
|
41
|
+
may not actually be a unit. This ``ZZ_pX`` is created with global
|
|
42
|
+
ntl modulus determined by the absolute value of ``relprec``. If
|
|
43
|
+
``relprec`` is 0, ``unit`` **is not initialized**, or destructed if
|
|
44
|
+
normalized and found to be zero. Otherwise, let `r` be ``relprec`` and
|
|
45
|
+
`e` be the ramification index over `\QQ_p` or `\ZZ_p`.
|
|
46
|
+
Then the modulus of unit is given by `p^{ceil(r/e)}`. Note that all
|
|
47
|
+
kinds of problems arise if you try to mix moduli.
|
|
48
|
+
``ZZ_pX_conv_modulus`` gives a semi-safe way to convert between
|
|
49
|
+
different moduli without having to pass through ``ZZX``.
|
|
50
|
+
|
|
51
|
+
- ``prime_pow`` (some subclass of :class:`PowComputer_ZZ_pX`) -- a class,
|
|
52
|
+
identical among all elements with the same parent, holding common
|
|
53
|
+
data.
|
|
54
|
+
|
|
55
|
+
+ ``prime_pow.deg`` -- the degree of the extension
|
|
56
|
+
|
|
57
|
+
+ ``prime_pow.e`` -- the ramification index
|
|
58
|
+
|
|
59
|
+
+ ``prime_pow.f`` -- the inertia degree
|
|
60
|
+
|
|
61
|
+
+ ``prime_pow.prec_cap`` -- the unramified precision cap. For
|
|
62
|
+
Eisenstein extensions this is the smallest power of `p` that is
|
|
63
|
+
zero.
|
|
64
|
+
|
|
65
|
+
+ ``prime_pow.ram_prec_cap`` -- the ramified precision cap. For
|
|
66
|
+
Eisenstein extensions this will be the smallest power of `x` that
|
|
67
|
+
is indistinguishable from zero.
|
|
68
|
+
|
|
69
|
+
+ ``prime_pow.pow_ZZ_tmp``, prime_pow.pow_mpz_t_tmp``,
|
|
70
|
+
``prime_pow.pow_Integer`` -- functions for accessing powers of
|
|
71
|
+
`p`. The first two return pointers. See
|
|
72
|
+
:mod:`sage.rings.padics.pow_computer_ext` for examples and important
|
|
73
|
+
warnings.
|
|
74
|
+
|
|
75
|
+
+ ``prime_pow.get_context``, ``prime_pow.get_context_capdiv``,
|
|
76
|
+
``prime_pow.get_top_context`` -- obtain an
|
|
77
|
+
``ntl_ZZ_pContext_class`` corresponding to `p^n`. The capdiv
|
|
78
|
+
version divides by ``prime_pow.e`` as appropriate.
|
|
79
|
+
``top_context`` corresponds to `p^{\texttt{prec\_cap}}`.
|
|
80
|
+
|
|
81
|
+
+ ``prime_pow.restore_context``,
|
|
82
|
+
``prime_pow.restore_context_capdiv``,
|
|
83
|
+
``prime_pow.restore_top_context`` -- restores the given context.
|
|
84
|
+
|
|
85
|
+
+ ``prime_pow.get_modulus``, ``get_modulus_capdiv``,
|
|
86
|
+
``get_top_modulus`` -- returns a ``ZZ_pX_Modulus_c*`` pointing to
|
|
87
|
+
a polynomial modulus defined modulo `p^n` (appropriately divided
|
|
88
|
+
by ``prime_pow.e`` in the capdiv case).
|
|
89
|
+
|
|
90
|
+
EXAMPLES:
|
|
91
|
+
|
|
92
|
+
An Eisenstein extension::
|
|
93
|
+
|
|
94
|
+
sage: R = Zp(5,5)
|
|
95
|
+
sage: S.<x> = R[]
|
|
96
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
97
|
+
sage: W.<w> = R.ext(f); W
|
|
98
|
+
5-adic Eisenstein Extension Ring in w defined by x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
99
|
+
sage: z = (1+w)^5; z
|
|
100
|
+
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 + O(w^25)
|
|
101
|
+
sage: y = z >> 1; y
|
|
102
|
+
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 + O(w^24)
|
|
103
|
+
sage: y.valuation()
|
|
104
|
+
4
|
|
105
|
+
sage: y.precision_relative()
|
|
106
|
+
20
|
|
107
|
+
sage: y.precision_absolute()
|
|
108
|
+
24
|
|
109
|
+
sage: z - (y << 1)
|
|
110
|
+
1 + O(w^25)
|
|
111
|
+
sage: (1/w)^12+w
|
|
112
|
+
w^-12 + w + O(w^13)
|
|
113
|
+
sage: (1/w).parent()
|
|
114
|
+
5-adic Eisenstein Extension Field in w defined by x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
115
|
+
|
|
116
|
+
Unramified extensions::
|
|
117
|
+
|
|
118
|
+
sage: g = x^3 + 3*x + 3
|
|
119
|
+
sage: A.<a> = R.ext(g)
|
|
120
|
+
sage: z = (1+a)^5; z
|
|
121
|
+
(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 + O(5^5)
|
|
122
|
+
sage: z - 1 - 5*a - 10*a^2 - 10*a^3 - 5*a^4 - a^5
|
|
123
|
+
O(5^5)
|
|
124
|
+
sage: y = z >> 1; y
|
|
125
|
+
(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 + O(5^4)
|
|
126
|
+
sage: 1/a
|
|
127
|
+
(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 + O(5^5)
|
|
128
|
+
sage: FFp = R.residue_field()
|
|
129
|
+
sage: R(FFp(3))
|
|
130
|
+
3 + O(5)
|
|
131
|
+
sage: QQq.<zz> = Qq(25,4)
|
|
132
|
+
sage: QQq(FFp(3))
|
|
133
|
+
3 + O(5)
|
|
134
|
+
sage: FFq = QQq.residue_field(); QQq(FFq(3))
|
|
135
|
+
3 + O(5)
|
|
136
|
+
sage: zz0 = FFq.gen(); QQq(zz0^2)
|
|
137
|
+
(zz + 3) + O(5)
|
|
138
|
+
|
|
139
|
+
Different printing modes::
|
|
140
|
+
|
|
141
|
+
sage: R = Zp(5, print_mode='digits'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
|
|
142
|
+
sage: z = (1+w)^5; repr(z)
|
|
143
|
+
'...4110403113210310442221311242000111011201102002023303214332011214403232013144001400444441030421100001'
|
|
144
|
+
sage: R = Zp(5, print_mode='bars'); S.<x> = R[]; g = x^3 + 3*x + 3; A.<a> = R.ext(g)
|
|
145
|
+
sage: z = (1+a)^5; repr(z)
|
|
146
|
+
'...[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]'
|
|
147
|
+
sage: R = Zp(5, print_mode='terse'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
|
|
148
|
+
sage: z = (1+w)^5; z
|
|
149
|
+
6 + 95367431640505*w + 25*w^2 + 95367431640560*w^3 + 5*w^4 + O(w^100)
|
|
150
|
+
sage: R = Zp(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)
|
|
151
|
+
sage: y = (1+w)^5 - 1; y
|
|
152
|
+
w^5 * (2090041 + 19073486126901*w + 1258902*w^2 + 674*w^3 + 16785*w^4) + O(w^100)
|
|
153
|
+
|
|
154
|
+
You can get at the underlying ntl unit::
|
|
155
|
+
|
|
156
|
+
sage: z._ntl_rep()
|
|
157
|
+
[6 95367431640505 25 95367431640560 5]
|
|
158
|
+
sage: y._ntl_rep()
|
|
159
|
+
[2090041 19073486126901 1258902 674 16785]
|
|
160
|
+
sage: y._ntl_rep_abs()
|
|
161
|
+
([5 95367431640505 25 95367431640560 5], 0)
|
|
162
|
+
|
|
163
|
+
.. NOTE::
|
|
164
|
+
|
|
165
|
+
If you get an error ``internal error: can't grow this _ntl_gbigint,``
|
|
166
|
+
it indicates that moduli are being mixed inappropriately somewhere.
|
|
167
|
+
|
|
168
|
+
For example, when calling a function with a ``ZZ_pX_c`` as an
|
|
169
|
+
argument, it copies. If the modulus is not
|
|
170
|
+
set to the modulus of the ``ZZ_pX_c``, you can get errors.
|
|
171
|
+
|
|
172
|
+
AUTHORS:
|
|
173
|
+
|
|
174
|
+
- David Roe (2008-01-01): initial version
|
|
175
|
+
|
|
176
|
+
- Robert Harron (2011-09): fixes/enhancements
|
|
177
|
+
|
|
178
|
+
- Julian Rueth (2014-05-09): enable caching through ``_cache_key``
|
|
179
|
+
"""
|
|
180
|
+
# ****************************************************************************
|
|
181
|
+
# Copyright (C) 2008 David Roe <roed.math@gmail.com>
|
|
182
|
+
# William Stein <wstein@gmail.com>
|
|
183
|
+
# 2014 Julian Rueth <julian.rueth@fsfe.org>
|
|
184
|
+
#
|
|
185
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
186
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
187
|
+
# the License, or (at your option) any later version.
|
|
188
|
+
#
|
|
189
|
+
# https://www.gnu.org/licenses/
|
|
190
|
+
# ****************************************************************************
|
|
191
|
+
|
|
192
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
193
|
+
from sage.ext.stdsage cimport PY_NEW
|
|
194
|
+
include "sage/libs/ntl/decl.pxi"
|
|
195
|
+
|
|
196
|
+
from sage.rings.integer cimport Integer
|
|
197
|
+
from sage.rings.rational cimport Rational
|
|
198
|
+
from sage.libs.gmp.mpz cimport *
|
|
199
|
+
from sage.libs.gmp.mpq cimport *
|
|
200
|
+
from sage.libs.ntl.ntl_ZZX cimport ntl_ZZX
|
|
201
|
+
from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
|
|
202
|
+
from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p
|
|
203
|
+
from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class
|
|
204
|
+
from sage.rings.padics.padic_generic_element cimport pAdicGenericElement
|
|
205
|
+
from cypari2.gen import Gen as pari_gen
|
|
206
|
+
from sage.interfaces.abc import GpElement
|
|
207
|
+
from sage.rings.finite_rings.integer_mod import IntegerMod_abstract
|
|
208
|
+
from sage.rings.padics.padic_ext_element cimport pAdicExtElement
|
|
209
|
+
from sage.rings.padics.precision_error import PrecisionError
|
|
210
|
+
|
|
211
|
+
from sage.rings.padics.pow_computer_ext cimport PowComputer_ZZ_pX_small_Eis
|
|
212
|
+
from sage.rings.padics.pow_computer_ext cimport PowComputer_ZZ_pX_big_Eis
|
|
213
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
214
|
+
|
|
215
|
+
cdef object infinity
|
|
216
|
+
from sage.rings.infinity import infinity
|
|
217
|
+
|
|
218
|
+
cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) -1
|
|
219
|
+
cdef long minusmaxordp = -maxordp
|
|
220
|
+
|
|
221
|
+
cdef inline int check_ordp(long a) except -1:
|
|
222
|
+
if a > maxordp or a < minusmaxordp:
|
|
223
|
+
raise ValueError("valuation overflow")
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
cdef class pAdicZZpXCRElement(pAdicZZpXElement):
|
|
227
|
+
def __init__(self, parent, x, absprec=infinity, relprec=infinity, empty=False):
|
|
228
|
+
r"""
|
|
229
|
+
Create an element of a capped relative precision, unramified
|
|
230
|
+
or Eisenstein extension of `\ZZ_p` or `\QQ_p`.
|
|
231
|
+
|
|
232
|
+
INPUT:
|
|
233
|
+
|
|
234
|
+
- ``parent`` -- either an ``EisensteinRingCappedRelative`` or
|
|
235
|
+
``UnramifiedRingCappedRelative``
|
|
236
|
+
|
|
237
|
+
- ``x`` -- integer; rational, `p`-adic element, polynomial,
|
|
238
|
+
list, integer_mod, pari int/frac/poly_t/pol_mod, an
|
|
239
|
+
``ntl_ZZ_pX``, an ``ntl_ZZ``, an ``ntl_ZZ_p``, an
|
|
240
|
+
``ntl_ZZX``, or something convertible into parent.residue_field()
|
|
241
|
+
|
|
242
|
+
- ``absprec`` -- an upper bound on the absolute precision of the
|
|
243
|
+
element created
|
|
244
|
+
|
|
245
|
+
- ``relprec`` -- an upper bound on the relative precision of
|
|
246
|
+
the element created
|
|
247
|
+
|
|
248
|
+
- ``empty`` -- whether to return after initializing to zero
|
|
249
|
+
(without setting the valuation)
|
|
250
|
+
|
|
251
|
+
EXAMPLES::
|
|
252
|
+
|
|
253
|
+
sage: R = Zp(5,5)
|
|
254
|
+
sage: S.<x> = R[]
|
|
255
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
256
|
+
sage: W.<w> = R.ext(f)
|
|
257
|
+
sage: z = (1+w)^5; z # indirect doctest
|
|
258
|
+
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 + O(w^25)
|
|
259
|
+
sage: W(pari('3 + O(5^3)'))
|
|
260
|
+
3 + O(w^15)
|
|
261
|
+
sage: W(R(3,3))
|
|
262
|
+
3 + O(w^15)
|
|
263
|
+
sage: W.<w> = R.ext(x^625 + 915*x^17 - 95)
|
|
264
|
+
sage: W(3)
|
|
265
|
+
3 + O(w^3125)
|
|
266
|
+
sage: W(w, 14)
|
|
267
|
+
w + O(w^14)
|
|
268
|
+
|
|
269
|
+
TESTS:
|
|
270
|
+
|
|
271
|
+
Check that :issue:`3865` is fixed::
|
|
272
|
+
|
|
273
|
+
sage: W(gp('3 + O(5^10)'))
|
|
274
|
+
3 + O(w^3125)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
Check that :issue:`13612` has been fixed::
|
|
278
|
+
|
|
279
|
+
sage: R = Zp(3)
|
|
280
|
+
sage: S.<a> = R[]
|
|
281
|
+
sage: W.<a> = R.extension(a^2 + 1)
|
|
282
|
+
sage: W(W.residue_field().zero())
|
|
283
|
+
O(3)
|
|
284
|
+
|
|
285
|
+
sage: K = Qp(3)
|
|
286
|
+
sage: S.<a> = K[]
|
|
287
|
+
sage: L.<a> = K.extension(a^2 + 1)
|
|
288
|
+
sage: L(L.residue_field().zero())
|
|
289
|
+
O(3)
|
|
290
|
+
"""
|
|
291
|
+
pAdicZZpXElement.__init__(self, parent)
|
|
292
|
+
self.relprec = 0
|
|
293
|
+
if empty:
|
|
294
|
+
return
|
|
295
|
+
cdef long aprec, rprec, ctx_prec, ltmp
|
|
296
|
+
if relprec is not infinity and not isinstance(relprec, Integer):
|
|
297
|
+
relprec = Integer(relprec)
|
|
298
|
+
if (relprec is infinity) or (relprec > parent.precision_cap()):
|
|
299
|
+
rprec = self.prime_pow.ram_prec_cap
|
|
300
|
+
else:
|
|
301
|
+
rprec = mpz_get_si((<Integer>relprec).value)
|
|
302
|
+
if rprec < 0:
|
|
303
|
+
rprec = 0
|
|
304
|
+
if absprec is not infinity:
|
|
305
|
+
if not isinstance(absprec, Integer):
|
|
306
|
+
absprec = Integer(absprec)
|
|
307
|
+
if mpz_fits_slong_p((<Integer>absprec).value) == 0:
|
|
308
|
+
absprec = infinity
|
|
309
|
+
else:
|
|
310
|
+
aprec = mpz_get_si((<Integer>absprec).value)
|
|
311
|
+
cdef mpz_t tmp
|
|
312
|
+
cdef ZZ_c tmp_z
|
|
313
|
+
cdef Py_ssize_t i
|
|
314
|
+
cdef Integer tmp_Int
|
|
315
|
+
cdef Rational xlift
|
|
316
|
+
if isinstance(x, pAdicGenericElement):
|
|
317
|
+
if self.prime_pow.in_field == 0 and x.valuation() < 0:
|
|
318
|
+
raise ValueError("element has negative valuation")
|
|
319
|
+
if x._is_base_elt(self.prime_pow.prime):
|
|
320
|
+
xlift = Rational(x.lift())
|
|
321
|
+
if mpq_sgn(xlift.value) == 0:
|
|
322
|
+
if (<pAdicGenericElement>x)._is_exact_zero():
|
|
323
|
+
if absprec is infinity:
|
|
324
|
+
self._set_exact_zero()
|
|
325
|
+
else:
|
|
326
|
+
self._set_inexact_zero(aprec)
|
|
327
|
+
return
|
|
328
|
+
ltmp = mpz_get_si((<Integer>x.precision_absolute()).value) * self.prime_pow.e
|
|
329
|
+
if absprec is infinity or ltmp < aprec:
|
|
330
|
+
aprec = ltmp
|
|
331
|
+
self._set_from_mpq_both(xlift.value, aprec, rprec)
|
|
332
|
+
return
|
|
333
|
+
if isinstance(x, GpElement):
|
|
334
|
+
x = x.__pari__()
|
|
335
|
+
if isinstance(x, pari_gen):
|
|
336
|
+
if x.type() == "t_PADIC":
|
|
337
|
+
if x.variable() != self.prime_pow.prime:
|
|
338
|
+
raise TypeError("cannot coerce a pari p-adic with the wrong prime")
|
|
339
|
+
ltmp = x.padicprec(self.prime_pow.prime) * self.prime_pow.e
|
|
340
|
+
if absprec is infinity or ltmp < aprec:
|
|
341
|
+
aprec = ltmp
|
|
342
|
+
absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
|
|
343
|
+
x = x.lift()
|
|
344
|
+
if x.type() == 't_INT':
|
|
345
|
+
x = Integer(x)
|
|
346
|
+
elif x.type() == 't_FRAC':
|
|
347
|
+
x = Rational(x)
|
|
348
|
+
elif x.type() == 't_POLMOD' or x.type == 't_POL':
|
|
349
|
+
# This code doesn't check to see if the primes are the same.
|
|
350
|
+
L = []
|
|
351
|
+
x = x.lift().lift()
|
|
352
|
+
for i from 0 <= i <= x.poldegree():
|
|
353
|
+
L.append(Integer(x.polcoef(i)))
|
|
354
|
+
x = L
|
|
355
|
+
else:
|
|
356
|
+
raise TypeError("unsupported coercion from pari: only p-adics, integers, rationals, polynomials and pol_mods allowed")
|
|
357
|
+
elif isinstance(x, IntegerMod_abstract):
|
|
358
|
+
mpz_init(tmp)
|
|
359
|
+
ctx_prec = mpz_remove(tmp, (<Integer>x.modulus()).value, self.prime_pow.prime.value)
|
|
360
|
+
if mpz_cmp_ui(tmp, 1) == 0:
|
|
361
|
+
mpz_clear(tmp)
|
|
362
|
+
x = x.lift()
|
|
363
|
+
if absprec is infinity or ctx_prec < aprec:
|
|
364
|
+
aprec = ctx_prec
|
|
365
|
+
absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
|
|
366
|
+
else:
|
|
367
|
+
mpz_clear(tmp)
|
|
368
|
+
raise TypeError("cannot coerce from the given integer mod ring (not a power of the same prime)")
|
|
369
|
+
elif isinstance(x, ntl_ZZ_p):
|
|
370
|
+
ctx_prec = ZZ_remove(tmp_z, (<ntl_ZZ>x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
371
|
+
if ZZ_IsOne(tmp_z):
|
|
372
|
+
x = x.lift()
|
|
373
|
+
tmp_Int = PY_NEW(Integer)
|
|
374
|
+
ZZ_to_mpz(tmp_Int.value, &(<ntl_ZZ>x).x)
|
|
375
|
+
x = tmp_Int
|
|
376
|
+
if absprec is infinity or ctx_prec < aprec:
|
|
377
|
+
aprec = ctx_prec
|
|
378
|
+
absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
|
|
379
|
+
else:
|
|
380
|
+
raise TypeError("cannot coerce the given ntl_ZZ_p (modulus not a power of the same prime)")
|
|
381
|
+
elif isinstance(x, ntl_ZZ):
|
|
382
|
+
tmp_Int = PY_NEW(Integer)
|
|
383
|
+
ZZ_to_mpz(tmp_Int.value, &(<ntl_ZZ>x).x)
|
|
384
|
+
x = tmp_Int
|
|
385
|
+
elif isinstance(x, int):
|
|
386
|
+
x = Integer(x)
|
|
387
|
+
elif x in parent.residue_field() and x.parent().is_finite():
|
|
388
|
+
# Should only reach here if x is not in F_p
|
|
389
|
+
z = parent.gen()
|
|
390
|
+
poly = x.polynomial().list()
|
|
391
|
+
x = sum([poly[i].lift() * (z ** i) for i in range(len(poly))], parent.zero())
|
|
392
|
+
if absprec is infinity or 1 < aprec:
|
|
393
|
+
aprec = 1
|
|
394
|
+
absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
|
|
395
|
+
cdef pAdicZZpXCRElement _x
|
|
396
|
+
if isinstance(x, Integer):
|
|
397
|
+
if absprec is infinity:
|
|
398
|
+
self._set_from_mpz_rel((<Integer>x).value, rprec)
|
|
399
|
+
else:
|
|
400
|
+
self._set_from_mpz_both((<Integer>x).value, aprec, rprec)
|
|
401
|
+
elif isinstance(x, Rational):
|
|
402
|
+
if absprec is infinity:
|
|
403
|
+
self._set_from_mpq_rel((<Rational>x).value, rprec)
|
|
404
|
+
else:
|
|
405
|
+
self._set_from_mpq_both((<Rational>x).value, aprec, rprec)
|
|
406
|
+
elif isinstance(x, ntl_ZZ_pX):
|
|
407
|
+
if absprec is infinity:
|
|
408
|
+
self._set_from_ZZ_pX_rel(&(<ntl_ZZ_pX>x).x, (<ntl_ZZ_pX>x).c, rprec)
|
|
409
|
+
else:
|
|
410
|
+
self._set_from_ZZ_pX_both(&(<ntl_ZZ_pX>x).x, (<ntl_ZZ_pX>x).c, aprec, rprec)
|
|
411
|
+
elif isinstance(x, ntl_ZZX):
|
|
412
|
+
if absprec is infinity:
|
|
413
|
+
self._set_from_ZZX_rel((<ntl_ZZX>x).x, rprec)
|
|
414
|
+
else:
|
|
415
|
+
self._set_from_ZZX_both((<ntl_ZZX>x).x, aprec, rprec)
|
|
416
|
+
elif isinstance(x, pAdicExtElement):
|
|
417
|
+
if x.parent() is parent:
|
|
418
|
+
_x = <pAdicZZpXCRElement>x
|
|
419
|
+
if _x.relprec == 0:
|
|
420
|
+
if absprec is infinity or aprec > _x.ordp:
|
|
421
|
+
self._set_inexact_zero(_x.ordp) # this works for exact zeros too.
|
|
422
|
+
else:
|
|
423
|
+
self._set_inexact_zero(aprec)
|
|
424
|
+
elif _x.relprec < 0:
|
|
425
|
+
if -_x.relprec < rprec:
|
|
426
|
+
rprec = _x.relprec
|
|
427
|
+
else:
|
|
428
|
+
rprec = -rprec
|
|
429
|
+
if absprec is infinity or aprec > _x.ordp - rprec:
|
|
430
|
+
self._set(&_x.unit, _x.ordp, rprec)
|
|
431
|
+
elif aprec > _x.ordp:
|
|
432
|
+
self._set(&_x.unit, _x.ordp, _x.ordp - aprec) #negating relprec to indicate non-normalized.
|
|
433
|
+
else:
|
|
434
|
+
self._set_inexact_zero(aprec)
|
|
435
|
+
else:
|
|
436
|
+
if _x.relprec < rprec:
|
|
437
|
+
rprec = _x.relprec
|
|
438
|
+
if absprec is infinity or aprec > _x.ordp + rprec:
|
|
439
|
+
self._set(&_x.unit, _x.ordp, rprec)
|
|
440
|
+
elif aprec > _x.ordp:
|
|
441
|
+
self._set(&_x.unit, _x.ordp, aprec - _x.ordp)
|
|
442
|
+
else:
|
|
443
|
+
self._set_inexact_zero(aprec)
|
|
444
|
+
elif x.parent().fraction_field() is parent:
|
|
445
|
+
if isinstance(x, pAdicZZpXCRElement):
|
|
446
|
+
_x = <pAdicZZpXCRElement>x
|
|
447
|
+
if _x.relprec < 0:
|
|
448
|
+
_x._normalize()
|
|
449
|
+
if _x._is_exact_zero():
|
|
450
|
+
self._set_exact_zero()
|
|
451
|
+
elif _x._is_inexact_zero():
|
|
452
|
+
self._set_inexact_zero(_x.ordp)
|
|
453
|
+
else:
|
|
454
|
+
if _x.relprec < rprec:
|
|
455
|
+
rprec = _x.relprec
|
|
456
|
+
self._set(&_x.unit, _x.ordp, rprec)
|
|
457
|
+
else:
|
|
458
|
+
# x is a pAdicZZpXCAElement
|
|
459
|
+
xordp = x.valuation()
|
|
460
|
+
xprec = x.precision_absolute()
|
|
461
|
+
if xordp == xprec:
|
|
462
|
+
self._set_inexact_zero(mpz_get_si((<Integer>xordp).value))
|
|
463
|
+
else:
|
|
464
|
+
poly = x._ntl_rep_abs()[0]
|
|
465
|
+
if absprec is infinity:
|
|
466
|
+
self._set_from_ZZ_pX_rel(&(<ntl_ZZ_pX>poly).x,(<ntl_ZZ_pX>poly).c, rprec)
|
|
467
|
+
else:
|
|
468
|
+
self._set_from_ZZ_pX_both(&(<ntl_ZZ_pX>poly).x,(<ntl_ZZ_pX>poly).c, aprec, rprec)
|
|
469
|
+
elif x.parent() is parent.fraction_field():
|
|
470
|
+
_x = <pAdicZZpXCRElement>x
|
|
471
|
+
if _x.relprec < 0:
|
|
472
|
+
_x._normalize()
|
|
473
|
+
if _x._is_exact_zero():
|
|
474
|
+
self._set_exact_zero()
|
|
475
|
+
elif _x._is_inexact_zero():
|
|
476
|
+
self._set_inexact_zero(_x.ordp)
|
|
477
|
+
else:
|
|
478
|
+
if _x.relprec < rprec:
|
|
479
|
+
rprec = _x.relprec
|
|
480
|
+
self._set(&_x.unit, _x.ordp, rprec)
|
|
481
|
+
else:
|
|
482
|
+
raise NotImplementedError("conversion from different p-adic extensions not yet supported")
|
|
483
|
+
else:
|
|
484
|
+
try:
|
|
485
|
+
x = list(x)
|
|
486
|
+
except TypeError:
|
|
487
|
+
try:
|
|
488
|
+
x = x.list()
|
|
489
|
+
except AttributeError:
|
|
490
|
+
raise TypeError("cannot convert x to a p-adic element")
|
|
491
|
+
if absprec is infinity:
|
|
492
|
+
self._set_from_list_rel(x, rprec)
|
|
493
|
+
else:
|
|
494
|
+
self._set_from_list_both(x, aprec, rprec)
|
|
495
|
+
|
|
496
|
+
def _cache_key(self):
|
|
497
|
+
r"""
|
|
498
|
+
Return a hashable key which identifies this element.
|
|
499
|
+
|
|
500
|
+
This makes it possible to use this element in caches such as
|
|
501
|
+
functions or methods decorated with ``@cached_function`` or
|
|
502
|
+
``@cached_method`` respectively.
|
|
503
|
+
|
|
504
|
+
EXAMPLES:
|
|
505
|
+
|
|
506
|
+
In the following example, ``a`` and ``b`` compare equal. They cannot
|
|
507
|
+
have a meaningful hash value since then their hash value would have to
|
|
508
|
+
be the same::
|
|
509
|
+
|
|
510
|
+
sage: K.<a> = Qq(9)
|
|
511
|
+
sage: b = a + O(3)
|
|
512
|
+
sage: a == b
|
|
513
|
+
True
|
|
514
|
+
sage: hash(a)
|
|
515
|
+
Traceback (most recent call last):
|
|
516
|
+
...
|
|
517
|
+
TypeError: ...unhashable type: 'sage.rings.padics.qadic_flint_CR.qAdicCappedRelativeElement'...
|
|
518
|
+
|
|
519
|
+
However, we want to cache computations which depend on them. Therefore
|
|
520
|
+
they define a ``_cache_key`` which is hashable and uniquely identifies
|
|
521
|
+
them::
|
|
522
|
+
|
|
523
|
+
sage: a._cache_key()
|
|
524
|
+
(..., ((0, 1),), 0, 20)
|
|
525
|
+
sage: b._cache_key()
|
|
526
|
+
(..., ((0, 1),), 0, 1)
|
|
527
|
+
|
|
528
|
+
TESTS:
|
|
529
|
+
|
|
530
|
+
Check that zero values are handled correctly::
|
|
531
|
+
|
|
532
|
+
sage: K.zero()._cache_key()
|
|
533
|
+
(..., 0)
|
|
534
|
+
sage: K(0,1)._cache_key()
|
|
535
|
+
(..., 1, 0)
|
|
536
|
+
"""
|
|
537
|
+
if self._is_exact_zero():
|
|
538
|
+
return (self.parent(), 0)
|
|
539
|
+
elif self._is_inexact_zero():
|
|
540
|
+
return (self.parent(), 0, self.valuation())
|
|
541
|
+
else:
|
|
542
|
+
return (self.parent(),
|
|
543
|
+
tuple(tuple(c) if isinstance(c, list) else c
|
|
544
|
+
for c in self.unit_part().expansion()),
|
|
545
|
+
self.valuation(), self.precision_relative())
|
|
546
|
+
|
|
547
|
+
cdef int _set_inexact_zero(self, long absprec) except -1:
|
|
548
|
+
"""
|
|
549
|
+
Set ``self`` to be zero with valuation absprec.
|
|
550
|
+
|
|
551
|
+
EXAMPLES::
|
|
552
|
+
|
|
553
|
+
sage: R = Zp(5,5)
|
|
554
|
+
sage: S.<x> = R[]
|
|
555
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
556
|
+
sage: W.<w> = R.ext(f)
|
|
557
|
+
sage: z = W(0,6); z # indirect doctest
|
|
558
|
+
O(w^6)
|
|
559
|
+
sage: z.valuation()
|
|
560
|
+
6
|
|
561
|
+
sage: z.precision_absolute()
|
|
562
|
+
6
|
|
563
|
+
sage: z.precision_relative()
|
|
564
|
+
0
|
|
565
|
+
|
|
566
|
+
TESTS::
|
|
567
|
+
|
|
568
|
+
sage: R = Zp(17, 3)
|
|
569
|
+
sage: S.<x> = R[]
|
|
570
|
+
sage: W.<w> = R.ext(x^34 - 289*x^5 + 17)
|
|
571
|
+
sage: z = W(0, 6); z
|
|
572
|
+
O(w^6)
|
|
573
|
+
sage: z.valuation()
|
|
574
|
+
6
|
|
575
|
+
sage: z.precision_absolute()
|
|
576
|
+
6
|
|
577
|
+
sage: z.precision_relative()
|
|
578
|
+
0
|
|
579
|
+
"""
|
|
580
|
+
self.ordp = absprec
|
|
581
|
+
self.relprec = 0
|
|
582
|
+
|
|
583
|
+
cdef int _set_exact_zero(self) except -1:
|
|
584
|
+
"""
|
|
585
|
+
Set ``self`` to be an exact zero.
|
|
586
|
+
|
|
587
|
+
EXAMPLES::
|
|
588
|
+
|
|
589
|
+
sage: R = Zp(5,5)
|
|
590
|
+
sage: S.<x> = R[]
|
|
591
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
592
|
+
sage: W.<w> = R.ext(f)
|
|
593
|
+
sage: z = R(0); z # indirect doctest
|
|
594
|
+
0
|
|
595
|
+
sage: z.valuation()
|
|
596
|
+
+Infinity
|
|
597
|
+
sage: z.precision_absolute()
|
|
598
|
+
+Infinity
|
|
599
|
+
sage: z.precision_relative()
|
|
600
|
+
0
|
|
601
|
+
|
|
602
|
+
TESTS::
|
|
603
|
+
|
|
604
|
+
sage: R = Zp(89, 3)
|
|
605
|
+
sage: S.<x> = R[]
|
|
606
|
+
sage: W.<w> = R.ext(x^34 - 2*89*x^5 + 89)
|
|
607
|
+
sage: z = R(0); z # indirect doctest
|
|
608
|
+
0
|
|
609
|
+
sage: z.valuation()
|
|
610
|
+
+Infinity
|
|
611
|
+
sage: z.precision_absolute()
|
|
612
|
+
+Infinity
|
|
613
|
+
sage: z.precision_relative()
|
|
614
|
+
0
|
|
615
|
+
"""
|
|
616
|
+
self.ordp = maxordp
|
|
617
|
+
self.relprec = 0
|
|
618
|
+
|
|
619
|
+
cpdef bint _is_exact_zero(self) except -1:
|
|
620
|
+
"""
|
|
621
|
+
Test if ``self`` is an exact zero.
|
|
622
|
+
|
|
623
|
+
EXAMPLES::
|
|
624
|
+
|
|
625
|
+
sage: R = Qp(3,5)
|
|
626
|
+
sage: S.<x> = R[]
|
|
627
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
628
|
+
sage: W.<w> = R.ext(f)
|
|
629
|
+
sage: z = W(0)
|
|
630
|
+
sage: z._is_exact_zero()
|
|
631
|
+
True
|
|
632
|
+
sage: z = W(0,6)
|
|
633
|
+
sage: z._is_exact_zero()
|
|
634
|
+
False
|
|
635
|
+
|
|
636
|
+
TESTS::
|
|
637
|
+
|
|
638
|
+
sage: R = Qp(53, 3)
|
|
639
|
+
sage: S.<x> = R[]
|
|
640
|
+
sage: W.<w> = R.ext(x^34 - 2*53^5*x^9 + 53)
|
|
641
|
+
sage: z = W(0)
|
|
642
|
+
sage: z._is_exact_zero()
|
|
643
|
+
True
|
|
644
|
+
sage: z = W(0,6)
|
|
645
|
+
sage: z._is_exact_zero()
|
|
646
|
+
False
|
|
647
|
+
"""
|
|
648
|
+
if self.ordp == maxordp:
|
|
649
|
+
return 1
|
|
650
|
+
else:
|
|
651
|
+
return 0
|
|
652
|
+
|
|
653
|
+
cpdef bint _is_inexact_zero(self) except -1:
|
|
654
|
+
"""
|
|
655
|
+
Test if ``self`` is an inexact zero.
|
|
656
|
+
|
|
657
|
+
EXAMPLES::
|
|
658
|
+
|
|
659
|
+
sage: R = Zp(7,5)
|
|
660
|
+
sage: S.<x> = R[]
|
|
661
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
662
|
+
sage: W.<w> = R.ext(f)
|
|
663
|
+
sage: z = W(0)
|
|
664
|
+
sage: z._is_inexact_zero()
|
|
665
|
+
False
|
|
666
|
+
sage: z = W(0,6)
|
|
667
|
+
sage: z._is_inexact_zero()
|
|
668
|
+
True
|
|
669
|
+
|
|
670
|
+
TESTS::
|
|
671
|
+
|
|
672
|
+
sage: R = Qp(29, 3)
|
|
673
|
+
sage: S.<x> = R[]
|
|
674
|
+
sage: W.<w> = R.ext(x^29 - 2*29^5*x - 29)
|
|
675
|
+
sage: z = W(0)
|
|
676
|
+
sage: z._is_inexact_zero()
|
|
677
|
+
False
|
|
678
|
+
sage: z = W(0,6)
|
|
679
|
+
sage: z._is_inexact_zero()
|
|
680
|
+
True
|
|
681
|
+
"""
|
|
682
|
+
self._normalize()
|
|
683
|
+
if self.relprec == 0:
|
|
684
|
+
return not self._is_exact_zero()
|
|
685
|
+
else:
|
|
686
|
+
return False
|
|
687
|
+
|
|
688
|
+
cdef int _set(self, ZZ_pX_c* unit, long ordp, long relprec) except -1:
|
|
689
|
+
"""
|
|
690
|
+
Set ``unit``, ``ordp`` and ``relprec`` directly.
|
|
691
|
+
|
|
692
|
+
EXAMPLES::
|
|
693
|
+
|
|
694
|
+
sage: R = Zp(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: F = W.fraction_field()
|
|
699
|
+
sage: z = F(1 + w); z # indirect doctest
|
|
700
|
+
1 + w + O(w^25)
|
|
701
|
+
|
|
702
|
+
TESTS::
|
|
703
|
+
|
|
704
|
+
sage: R = Zp(17,30)
|
|
705
|
+
sage: S.<x> = R[]
|
|
706
|
+
sage: f = x^51 - 34
|
|
707
|
+
sage: W.<w> = R.ext(f)
|
|
708
|
+
sage: F = W.fraction_field()
|
|
709
|
+
sage: z = F(1 + w); z # indirect doctest
|
|
710
|
+
1 + w + O(w^1530)
|
|
711
|
+
sage: z = F(w + w^2, relprec=0); z
|
|
712
|
+
O(w)
|
|
713
|
+
"""
|
|
714
|
+
self.ordp = ordp
|
|
715
|
+
self._set_prec_rel(relprec)
|
|
716
|
+
if self.relprec != 0:
|
|
717
|
+
ZZ_pX_conv_modulus(self.unit, unit[0], self.prime_pow.get_context_capdiv(relprec).x)
|
|
718
|
+
|
|
719
|
+
cdef int _set_from_mpz_rel(self, mpz_t x, long relprec) except -1:
|
|
720
|
+
"""
|
|
721
|
+
Set ``self`` from an ``mpz_t`` with relative precision bounded by ``relprec``.
|
|
722
|
+
|
|
723
|
+
EXAMPLES::
|
|
724
|
+
|
|
725
|
+
sage: R = Zp(5,5)
|
|
726
|
+
sage: S.<x> = R[]
|
|
727
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
728
|
+
sage: W.<w> = R.ext(f)
|
|
729
|
+
sage: W(70, relprec=8) # indirect doctest
|
|
730
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)
|
|
731
|
+
sage: W(70, relprec=0)
|
|
732
|
+
O(w^5)
|
|
733
|
+
|
|
734
|
+
TESTS::
|
|
735
|
+
|
|
736
|
+
sage: R = Qp(13,50)
|
|
737
|
+
sage: S.<x> = R[]
|
|
738
|
+
sage: f = x^169 - 13
|
|
739
|
+
sage: W.<w> = R.ext(f)
|
|
740
|
+
sage: a = W(65, relprec=8); a.valuation() # indirect doctest
|
|
741
|
+
169
|
|
742
|
+
sage: W(65, relprec=0)
|
|
743
|
+
O(w^169)
|
|
744
|
+
"""
|
|
745
|
+
if mpz_sgn(x) == 0:
|
|
746
|
+
self._set_exact_zero()
|
|
747
|
+
return 0
|
|
748
|
+
cdef mpz_t tmp_m
|
|
749
|
+
cdef ZZ_c tmp_z
|
|
750
|
+
cdef long shift
|
|
751
|
+
mpz_init(tmp_m)
|
|
752
|
+
sig_on()
|
|
753
|
+
shift = mpz_remove(tmp_m, x, self.prime_pow.prime.value)
|
|
754
|
+
sig_off()
|
|
755
|
+
self._set_prec_rel(relprec)
|
|
756
|
+
mpz_to_ZZ(&tmp_z, tmp_m)
|
|
757
|
+
mpz_clear(tmp_m)
|
|
758
|
+
if self.relprec != 0:
|
|
759
|
+
ZZ_pX_SetCoeff(self.unit, 0, ZZ_to_ZZ_p(tmp_z))
|
|
760
|
+
self.ordp = 0
|
|
761
|
+
self._pshift_self(shift)
|
|
762
|
+
else:
|
|
763
|
+
self.ordp = shift * self.prime_pow.e
|
|
764
|
+
|
|
765
|
+
cdef int _set_from_mpz_both(self, mpz_t x, long absprec, long relprec) except -1:
|
|
766
|
+
"""
|
|
767
|
+
Set ``self`` from an ``mpz_t`` with relative precision bounded by ``relprec``
|
|
768
|
+
and absolute precision bounded by ``absprec``.
|
|
769
|
+
|
|
770
|
+
EXAMPLES::
|
|
771
|
+
|
|
772
|
+
sage: R = Zp(5,5)
|
|
773
|
+
sage: S.<x> = R[]
|
|
774
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
775
|
+
sage: W.<w> = R.ext(f)
|
|
776
|
+
sage: W(70, 8) # indirect doctest
|
|
777
|
+
4*w^5 + 3*w^7 + O(w^8)
|
|
778
|
+
sage: W(70, absprec=4)
|
|
779
|
+
O(w^4)
|
|
780
|
+
|
|
781
|
+
TESTS::
|
|
782
|
+
|
|
783
|
+
sage: R = Zp(7,3)
|
|
784
|
+
sage: S.<x> = R[]
|
|
785
|
+
sage: f = x^49 + 7*x^21 - 14
|
|
786
|
+
sage: W.<w> = R.ext(f)
|
|
787
|
+
sage: W(70, 100) # indirect doctest
|
|
788
|
+
5*w^49 + 6*w^70 + 3*w^91 + O(w^100)
|
|
789
|
+
sage: W(70, absprec=4)
|
|
790
|
+
O(w^4)
|
|
791
|
+
"""
|
|
792
|
+
if mpz_sgn(x) == 0:
|
|
793
|
+
self._set_inexact_zero(absprec)
|
|
794
|
+
return 0
|
|
795
|
+
cdef mpz_t tmp_m
|
|
796
|
+
cdef ZZ_c tmp_z
|
|
797
|
+
cdef long shift
|
|
798
|
+
mpz_init(tmp_m)
|
|
799
|
+
sig_on()
|
|
800
|
+
shift = mpz_remove(tmp_m, x, self.prime_pow.prime.value)
|
|
801
|
+
sig_off()
|
|
802
|
+
self.ordp = shift * self.prime_pow.e
|
|
803
|
+
if self._set_prec_both(absprec, relprec) == 1:
|
|
804
|
+
# This indicates that self._set_inexact_zero was called
|
|
805
|
+
mpz_clear(tmp_m)
|
|
806
|
+
return 0
|
|
807
|
+
mpz_to_ZZ(&tmp_z, tmp_m)
|
|
808
|
+
mpz_clear(tmp_m)
|
|
809
|
+
if self.relprec != 0:
|
|
810
|
+
ZZ_pX_SetCoeff(self.unit, 0, ZZ_to_ZZ_p(tmp_z))
|
|
811
|
+
self.ordp = 0
|
|
812
|
+
self._pshift_self(shift)
|
|
813
|
+
|
|
814
|
+
cdef int _set_from_mpq_rel(self, mpq_t x, long relprec) except -1:
|
|
815
|
+
"""
|
|
816
|
+
Set ``self`` from an ``mpq_t`` with relative precision
|
|
817
|
+
bounded by ``relprec``.
|
|
818
|
+
|
|
819
|
+
EXAMPLES::
|
|
820
|
+
|
|
821
|
+
sage: R = Zp(5,5)
|
|
822
|
+
sage: S.<x> = R[]
|
|
823
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
824
|
+
sage: W.<w> = R.ext(f)
|
|
825
|
+
sage: z = W(70/3, relprec=9); z # indirect doctest
|
|
826
|
+
3*w^5 + w^7 + 2*w^9 + 2*w^10 + 4*w^11 + w^12 + 2*w^13 + O(w^14)
|
|
827
|
+
sage: z * 3
|
|
828
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + O(w^14)
|
|
829
|
+
sage: W(70)
|
|
830
|
+
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 + 3*w^25 + w^27 + O(w^30)
|
|
831
|
+
sage: F = W.fraction_field()
|
|
832
|
+
sage: y = F(3/700); y
|
|
833
|
+
w^-10 + w^-8 + 4*w^-6 + w^-3 + 4*w^-2 + 3*w^-1 + 3 + 4*w + w^3 + 4*w^4 + w^5 + 4*w^6 + 2*w^7 + 3*w^8 + 4*w^9 + 3*w^10 + 4*w^11 + w^12 + O(w^15)
|
|
834
|
+
sage: y * 700
|
|
835
|
+
3 + O(w^25)
|
|
836
|
+
sage: W(70/3, relprec=0)
|
|
837
|
+
O(w^5)
|
|
838
|
+
sage: c = F(5^-1 + O(5^2)); c
|
|
839
|
+
w^-5 + 3*w^-3 + 2*w^3 + 4*w^5 + 4*w^6 + 3*w^7 + w^9 + O(w^10)
|
|
840
|
+
sage: c * 5
|
|
841
|
+
1 + O(w^15)
|
|
842
|
+
|
|
843
|
+
TESTS::
|
|
844
|
+
|
|
845
|
+
sage: R = Zp(11, 8, print_mode='digits')
|
|
846
|
+
sage: S.<x> = R[]
|
|
847
|
+
sage: f = x^3 + 1331 * x^2 - 11 * x + 11
|
|
848
|
+
sage: W.<w> = R.ext(f)
|
|
849
|
+
sage: z = W(77/3, relprec=11); repr(z)[3:]
|
|
850
|
+
'304107A2555000'
|
|
851
|
+
sage: repr(z*3)[3:]
|
|
852
|
+
'56698765444000'
|
|
853
|
+
sage: repr(W(77))[3:]
|
|
854
|
+
'5800A6604678856698765444000'
|
|
855
|
+
sage: F = W.fraction_field()
|
|
856
|
+
sage: y = F(3/847); repr(y)[3:]
|
|
857
|
+
'5563A4105291255628.148272'
|
|
858
|
+
sage: repr(y*847)[3:]
|
|
859
|
+
'000000000000000000000003'
|
|
860
|
+
sage: repr(W(77/3, relprec=0))[3:]
|
|
861
|
+
'000'
|
|
862
|
+
sage: c = F(11^-1 + O(11^2)); repr(c)[3:]
|
|
863
|
+
'011111.01A'
|
|
864
|
+
sage: repr(c * 11)[3:]
|
|
865
|
+
'000000001'
|
|
866
|
+
"""
|
|
867
|
+
if mpq_sgn(x) == 0:
|
|
868
|
+
self._set_exact_zero()
|
|
869
|
+
return 0
|
|
870
|
+
cdef mpz_t num_unit, den_unit
|
|
871
|
+
self._set_from_mpq_part1(num_unit, den_unit, x)
|
|
872
|
+
self._set_prec_rel(relprec)
|
|
873
|
+
self._set_from_mpq_part2(num_unit, den_unit)
|
|
874
|
+
|
|
875
|
+
cdef int _set_from_mpq_both(self, mpq_t x, long absprec, long relprec) except -1:
|
|
876
|
+
"""
|
|
877
|
+
Set ``self`` from an ``mpq_t`` with relative precision
|
|
878
|
+
bounded by ``relprec`` and absolute precision bounded by
|
|
879
|
+
``absprec``.
|
|
880
|
+
|
|
881
|
+
EXAMPLES::
|
|
882
|
+
|
|
883
|
+
sage: R = Zp(5,5)
|
|
884
|
+
sage: S.<x> = R[]
|
|
885
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
886
|
+
sage: W.<w> = R.ext(f)
|
|
887
|
+
sage: z = W(70/3, 14); z # indirect doctest
|
|
888
|
+
3*w^5 + w^7 + 2*w^9 + 2*w^10 + 4*w^11 + w^12 + 2*w^13 + O(w^14)
|
|
889
|
+
sage: z * 3
|
|
890
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + O(w^14)
|
|
891
|
+
sage: W(70)
|
|
892
|
+
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 + 3*w^25 + w^27 + O(w^30)
|
|
893
|
+
sage: F = W.fraction_field()
|
|
894
|
+
sage: y = F(3/700,-2); y
|
|
895
|
+
w^-10 + w^-8 + 4*w^-6 + w^-3 + O(w^-2)
|
|
896
|
+
sage: y * 700
|
|
897
|
+
3 + O(w^8)
|
|
898
|
+
sage: W(70/3, absprec=4)
|
|
899
|
+
O(w^4)
|
|
900
|
+
"""
|
|
901
|
+
if mpq_sgn(x) == 0:
|
|
902
|
+
self._set_inexact_zero(absprec)
|
|
903
|
+
return 0
|
|
904
|
+
cdef mpz_t num_unit, den_unit
|
|
905
|
+
self._set_from_mpq_part1(num_unit, den_unit, x)
|
|
906
|
+
if self._set_prec_both(absprec, relprec) == 1:
|
|
907
|
+
# indicates an inexact zero
|
|
908
|
+
mpz_clear(num_unit)
|
|
909
|
+
mpz_clear(den_unit)
|
|
910
|
+
return 0
|
|
911
|
+
self._set_from_mpq_part2(num_unit, den_unit)
|
|
912
|
+
|
|
913
|
+
cdef int _set_from_mpq_part1(self, mpz_t num_unit, mpz_t den_unit, mpq_t x) except -1:
|
|
914
|
+
"""
|
|
915
|
+
Set ``num_unit`` to be the unit of the numerator, ``den_unit`` to be
|
|
916
|
+
the unit of the denominator and sets ``self.ordp`` correctly.
|
|
917
|
+
|
|
918
|
+
TESTS::
|
|
919
|
+
|
|
920
|
+
sage: R = Zp(5,5)
|
|
921
|
+
sage: S.<x> = R[]
|
|
922
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
923
|
+
sage: W.<w> = R.ext(f)
|
|
924
|
+
sage: z = W(7000/3, 23); z # indirect doctest
|
|
925
|
+
2*w^15 + 2*w^17 + 3*w^19 + w^22 + O(w^23)
|
|
926
|
+
"""
|
|
927
|
+
cdef long num_ordp, den_ordp
|
|
928
|
+
sig_on()
|
|
929
|
+
mpz_init(num_unit)
|
|
930
|
+
mpz_init(den_unit)
|
|
931
|
+
num_ordp = mpz_remove(num_unit, mpq_numref(x), self.prime_pow.prime.value)
|
|
932
|
+
den_ordp = mpz_remove(den_unit, mpq_denref(x), self.prime_pow.prime.value)
|
|
933
|
+
sig_off()
|
|
934
|
+
self.ordp = (num_ordp - den_ordp) * self.prime_pow.e
|
|
935
|
+
if self.ordp < 0 and self.prime_pow.in_field == 0:
|
|
936
|
+
mpz_clear(num_unit)
|
|
937
|
+
mpz_clear(den_unit)
|
|
938
|
+
raise ValueError("p divides the denominator")
|
|
939
|
+
|
|
940
|
+
cdef int _set_from_mpq_part2(self, mpz_t num_unit, mpz_t den_unit) except -1:
|
|
941
|
+
"""
|
|
942
|
+
Given that ``self.ordp`` and ``self.relprec`` have been set, takes
|
|
943
|
+
``num_unit`` and ``den_unit`` and sets ``self.unit``.
|
|
944
|
+
|
|
945
|
+
TESTS::
|
|
946
|
+
|
|
947
|
+
sage: R = Zp(5,5)
|
|
948
|
+
sage: S.<x> = R[]
|
|
949
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
950
|
+
sage: W.<w> = R.ext(f)
|
|
951
|
+
sage: W(QQ(0), 23) # indirect doctest
|
|
952
|
+
O(w^23)
|
|
953
|
+
sage: W(QQ(0))
|
|
954
|
+
0
|
|
955
|
+
"""
|
|
956
|
+
cdef ZZ_c num_zz, den_zz
|
|
957
|
+
cdef ZZ_p_c tmp_zp
|
|
958
|
+
cdef long val = self.ordp / self.prime_pow.e
|
|
959
|
+
cdef mpz_t tmp_m
|
|
960
|
+
if self.relprec != 0:
|
|
961
|
+
mpz_init(tmp_m)
|
|
962
|
+
mpz_set(tmp_m, num_unit)
|
|
963
|
+
mpz_to_ZZ(&num_zz, tmp_m)
|
|
964
|
+
mpz_set(tmp_m, den_unit)
|
|
965
|
+
mpz_to_ZZ(&den_zz, tmp_m)
|
|
966
|
+
mpz_clear(tmp_m)
|
|
967
|
+
#The context has been restored in setting self.relprec
|
|
968
|
+
ZZ_p_div(tmp_zp, ZZ_to_ZZ_p(num_zz), ZZ_to_ZZ_p(den_zz))
|
|
969
|
+
ZZ_pX_SetCoeff(self.unit, 0, tmp_zp)
|
|
970
|
+
self.ordp = 0
|
|
971
|
+
self._pshift_self(val)
|
|
972
|
+
|
|
973
|
+
cdef int _set_from_ZZX_rel(self, ZZX_c poly, long relprec) except -1:
|
|
974
|
+
"""
|
|
975
|
+
Set ``self`` from a ``ZZX`` with relative precision bounded by
|
|
976
|
+
``relprec``.
|
|
977
|
+
|
|
978
|
+
EXAMPLES::
|
|
979
|
+
|
|
980
|
+
sage: R = Zp(5,5)
|
|
981
|
+
sage: S.<x> = R[]
|
|
982
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
983
|
+
sage: W.<w> = R.ext(f)
|
|
984
|
+
sage: z = W(ntl.ZZX([4,1,16]), relprec=14); z # indirect doctest
|
|
985
|
+
4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + 4*w^13 + O(w^14)
|
|
986
|
+
sage: z._ntl_rep()
|
|
987
|
+
[4 1 16]
|
|
988
|
+
sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), relprec=14); z
|
|
989
|
+
w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + O(w^214)
|
|
990
|
+
sage: W(5)^40 + w*W(5)^42 + w^2 * W(3) * W(5)^41
|
|
991
|
+
w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + 2*w^215 + w^217 + 2*w^218 + w^220 + w^221 + w^222 + 3*w^224 + O(w^225)
|
|
992
|
+
sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), relprec=0); z
|
|
993
|
+
O(w^200)
|
|
994
|
+
"""
|
|
995
|
+
if ZZX_IsZero(poly):
|
|
996
|
+
self._set_exact_zero()
|
|
997
|
+
return 0
|
|
998
|
+
if ZZX_deg(poly) >= self.prime_pow.deg:
|
|
999
|
+
raise NotImplementedError
|
|
1000
|
+
# the -1 in the next line signals that there is no absprec specified
|
|
1001
|
+
self._set_from_ZZX_part1(poly, -1, relprec)
|
|
1002
|
+
# context was restored in _set_from_ZZX_part1
|
|
1003
|
+
if relprec == 0:
|
|
1004
|
+
self._set_prec_rel(relprec)
|
|
1005
|
+
return 0
|
|
1006
|
+
if self.relprec + self.ordp != 0:
|
|
1007
|
+
self.prime_pow.restore_context_capdiv(self.relprec + self.ordp)
|
|
1008
|
+
ZZX_to_ZZ_pX(self.unit, poly)
|
|
1009
|
+
self._internal_lshift(-self.ordp)
|
|
1010
|
+
|
|
1011
|
+
cdef int _set_from_ZZX_both(self, ZZX_c poly, long absprec, long relprec) except -1:
|
|
1012
|
+
"""
|
|
1013
|
+
Set ``self`` from a ``ZZX`` with relative precision bounded by
|
|
1014
|
+
``relprec`` and absolute precision bounded by ``absprec``.
|
|
1015
|
+
|
|
1016
|
+
EXAMPLES::
|
|
1017
|
+
|
|
1018
|
+
sage: R = Zp(5,5)
|
|
1019
|
+
sage: S.<x> = R[]
|
|
1020
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1021
|
+
sage: W.<w> = R.ext(f)
|
|
1022
|
+
sage: z = W(ntl.ZZX([4,1,16]), 12); z # indirect doctest
|
|
1023
|
+
4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + O(w^12)
|
|
1024
|
+
sage: z._ntl_rep()
|
|
1025
|
+
[4 1 16]
|
|
1026
|
+
sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), 212); z
|
|
1027
|
+
w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + O(w^212)
|
|
1028
|
+
sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), 197); z
|
|
1029
|
+
O(w^197)
|
|
1030
|
+
"""
|
|
1031
|
+
if ZZX_IsZero(poly) or absprec <= 0:
|
|
1032
|
+
self._set_inexact_zero(absprec)
|
|
1033
|
+
return 0
|
|
1034
|
+
if ZZX_deg(poly) >= self.prime_pow.deg:
|
|
1035
|
+
raise NotImplementedError
|
|
1036
|
+
if self._set_from_ZZX_part1(poly, absprec, relprec) == -2:
|
|
1037
|
+
# indicates _set_inexact_zero was called
|
|
1038
|
+
return 0
|
|
1039
|
+
# context was restored in _set_from_ZZX_part1
|
|
1040
|
+
if self.relprec + self.ordp != 0:
|
|
1041
|
+
self.prime_pow.restore_context_capdiv(self.relprec + self.ordp)
|
|
1042
|
+
ZZX_to_ZZ_pX(self.unit, poly)
|
|
1043
|
+
self._internal_lshift(-self.ordp)
|
|
1044
|
+
|
|
1045
|
+
cdef int _set_from_ZZX_part1(self, ZZX_c poly, long absprec, long relprec) except -1:
|
|
1046
|
+
"""
|
|
1047
|
+
Set ``self.ordp`` from ``poly`` and restores the context. ``poly`` must
|
|
1048
|
+
have degree less than ``self.prime_pow.deg``.
|
|
1049
|
+
|
|
1050
|
+
TESTS::
|
|
1051
|
+
|
|
1052
|
+
sage: R = Zp(5,5)
|
|
1053
|
+
sage: S.<x> = R[]
|
|
1054
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1055
|
+
sage: W.<w> = R.ext(f)
|
|
1056
|
+
sage: z = W(ntl.ZZX([4,1,16]), 12); z # indirect doctest
|
|
1057
|
+
4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + O(w^12)
|
|
1058
|
+
"""
|
|
1059
|
+
cdef long i = 0
|
|
1060
|
+
cdef long deg = ZZX_deg(poly)
|
|
1061
|
+
cdef long mini = -1
|
|
1062
|
+
cdef long minval
|
|
1063
|
+
cdef long curval
|
|
1064
|
+
cdef ZZ_c tmp_z
|
|
1065
|
+
while mini == -1:
|
|
1066
|
+
if not ZZ_IsZero(ZZX_coeff(poly,i)):
|
|
1067
|
+
minval = ZZ_remove(tmp_z, ZZX_coeff(poly, i), self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
1068
|
+
mini = i
|
|
1069
|
+
i += 1
|
|
1070
|
+
while i <= deg:
|
|
1071
|
+
if not ZZ_IsZero(ZZX_coeff(poly,i)):
|
|
1072
|
+
curval = ZZ_remove(tmp_z, ZZX_coeff(poly, i), self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
1073
|
+
if curval < minval:
|
|
1074
|
+
minval = curval
|
|
1075
|
+
mini = i
|
|
1076
|
+
i += 1
|
|
1077
|
+
if self.prime_pow.e == 1:
|
|
1078
|
+
self.ordp = minval
|
|
1079
|
+
else:
|
|
1080
|
+
self.ordp = minval * self.prime_pow.e + mini
|
|
1081
|
+
if absprec == -1: # indicates that _set_from_ZZX_rel is calling
|
|
1082
|
+
self._set_prec_rel(relprec)
|
|
1083
|
+
elif self._set_prec_both(absprec, relprec):
|
|
1084
|
+
# indicates self._set_inexact_zero was called
|
|
1085
|
+
return -2
|
|
1086
|
+
# _set_prec_rel or both has restored the context so that part2 works.
|
|
1087
|
+
|
|
1088
|
+
cdef int _set_from_ZZ_pX_rel(self, ZZ_pX_c* poly, ntl_ZZ_pContext_class ctx, long relprec) except -1:
|
|
1089
|
+
"""
|
|
1090
|
+
Set ``self`` from a ``ZZ_pX`` with relative precision bounded by
|
|
1091
|
+
``relprec``.
|
|
1092
|
+
|
|
1093
|
+
If ``ctx`` is ``None`` and ``poly`` is 0 this function will raise an
|
|
1094
|
+
error (a ``ZZ_pX`` cannot represent something with infinite absolute
|
|
1095
|
+
precision).
|
|
1096
|
+
|
|
1097
|
+
EXAMPLES::
|
|
1098
|
+
|
|
1099
|
+
sage: R = Zp(5,5)
|
|
1100
|
+
sage: S.<x> = R[]
|
|
1101
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1102
|
+
sage: W.<w> = R.ext(f)
|
|
1103
|
+
sage: z = W(ntl.ZZ_pX([4,1,16],5^2)); z # indirect doctest
|
|
1104
|
+
4 + w + w^2 + 3*w^7 + w^9 + O(w^10)
|
|
1105
|
+
sage: z._ntl_rep()
|
|
1106
|
+
[4 1 16]
|
|
1107
|
+
sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^44)); z
|
|
1108
|
+
w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + 2*w^215 + w^217 + 2*w^218 + O(w^220)
|
|
1109
|
+
sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^44), relprec=0); z
|
|
1110
|
+
O(w^200)
|
|
1111
|
+
"""
|
|
1112
|
+
cdef long ctx_prec = -1
|
|
1113
|
+
if ctx is not None:
|
|
1114
|
+
ctx_prec = self._check_ZZ_pContext(ctx) * self.prime_pow.e
|
|
1115
|
+
if ZZ_pX_IsZero(poly[0]):
|
|
1116
|
+
if ctx_prec == -1:
|
|
1117
|
+
raise ValueError("must specify either a context or an absolute precision bound")
|
|
1118
|
+
else:
|
|
1119
|
+
self._set_inexact_zero(ctx_prec)
|
|
1120
|
+
return 0
|
|
1121
|
+
self._set_from_ZZ_pX_part1(poly)
|
|
1122
|
+
if relprec == 0:
|
|
1123
|
+
self._set_prec_rel(relprec)
|
|
1124
|
+
return 0
|
|
1125
|
+
if ctx_prec == -1:
|
|
1126
|
+
self._set_prec_rel(self.ordp + relprec)
|
|
1127
|
+
else:
|
|
1128
|
+
self._set_prec_rel(min(ctx_prec, self.ordp + relprec))
|
|
1129
|
+
self._set_from_ZZ_pX_part2(poly)
|
|
1130
|
+
|
|
1131
|
+
cdef int _set_from_ZZ_pX_both(self, ZZ_pX_c* poly, ntl_ZZ_pContext_class ctx, long absprec, long relprec) except -1:
|
|
1132
|
+
"""
|
|
1133
|
+
Set ``self`` from a ``ZZ_pX`` with relative precision bounded by
|
|
1134
|
+
``relprec`` and absolute precision bounded by ``absprec``.
|
|
1135
|
+
|
|
1136
|
+
EXAMPLES::
|
|
1137
|
+
|
|
1138
|
+
sage: R = Zp(5,5)
|
|
1139
|
+
sage: S.<x> = R[]
|
|
1140
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1141
|
+
sage: W.<w> = R.ext(f)
|
|
1142
|
+
sage: z = W(ntl.ZZ_pX([4,1,16],5^2), absprec=8, relprec=12); z # indirect doctest
|
|
1143
|
+
4 + w + w^2 + 3*w^7 + O(w^8)
|
|
1144
|
+
sage: z._ntl_rep()
|
|
1145
|
+
[4 1 16]
|
|
1146
|
+
sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^50), 220); z
|
|
1147
|
+
w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + 2*w^215 + w^217 + 2*w^218 + O(w^220)
|
|
1148
|
+
sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^44), absprec=77); z
|
|
1149
|
+
O(w^77)
|
|
1150
|
+
"""
|
|
1151
|
+
cdef long ctx_prec
|
|
1152
|
+
if ctx is not None:
|
|
1153
|
+
ctx_prec = self._check_ZZ_pContext(ctx)
|
|
1154
|
+
if ctx_prec * self.prime_pow.e < absprec:
|
|
1155
|
+
absprec = ctx_prec * self.prime_pow.e
|
|
1156
|
+
if ZZ_pX_IsZero(poly[0]):
|
|
1157
|
+
self._set_inexact_zero(absprec)
|
|
1158
|
+
return 0
|
|
1159
|
+
self._set_from_ZZ_pX_part1(poly)
|
|
1160
|
+
if absprec <= self.ordp:
|
|
1161
|
+
self._set_inexact_zero(absprec)
|
|
1162
|
+
else:
|
|
1163
|
+
self._set_prec_rel(min(absprec, self.ordp + relprec))
|
|
1164
|
+
self._set_from_ZZ_pX_part2(poly)
|
|
1165
|
+
|
|
1166
|
+
cdef int _set_from_ZZ_pX_part1(self, ZZ_pX_c* poly) except -1:
|
|
1167
|
+
"""
|
|
1168
|
+
Set ``self.ordp`` based on ``poly``. ``poly`` must not be 0.
|
|
1169
|
+
|
|
1170
|
+
TESTS::
|
|
1171
|
+
|
|
1172
|
+
sage: R = Zp(5,5)
|
|
1173
|
+
sage: S.<x> = R[]
|
|
1174
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1175
|
+
sage: W.<w> = R.ext(f)
|
|
1176
|
+
sage: z = W(ntl.ZZ_pX([4,1,16],5^2), absprec=8, relprec=12); z # indirect doctest
|
|
1177
|
+
4 + w + w^2 + 3*w^7 + O(w^8)
|
|
1178
|
+
"""
|
|
1179
|
+
cdef long val = 0, index = 0
|
|
1180
|
+
ZZ_pX_min_val_coeff(val, index, poly[0], self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
1181
|
+
if self.prime_pow.e == 1:
|
|
1182
|
+
self.ordp = val
|
|
1183
|
+
else:
|
|
1184
|
+
self.ordp = val * self.prime_pow.e + index
|
|
1185
|
+
|
|
1186
|
+
cdef int _set_from_ZZ_pX_part2(self, ZZ_pX_c* poly) except -1:
|
|
1187
|
+
"""
|
|
1188
|
+
Assuming that ``self.ordp`` and ``self.relprec`` have been set, sets
|
|
1189
|
+
``self.unit`` to ``poly`` and then normalizes.
|
|
1190
|
+
|
|
1191
|
+
TESTS::
|
|
1192
|
+
|
|
1193
|
+
sage: R = Zp(5,5)
|
|
1194
|
+
sage: S.<x> = R[]
|
|
1195
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1196
|
+
sage: W.<w> = R.ext(f)
|
|
1197
|
+
sage: z = W(ntl.ZZ_pX([4,1,16],5^2), absprec=8, relprec=12); z # indirect doctest
|
|
1198
|
+
4 + w + w^2 + 3*w^7 + O(w^8)
|
|
1199
|
+
"""
|
|
1200
|
+
# We've set self.relprec to what is actually the absolute precision.
|
|
1201
|
+
if self.relprec != 0:
|
|
1202
|
+
ZZ_pX_conv_modulus(self.unit, poly[0], self.prime_pow.get_context_capdiv(self.relprec).x)
|
|
1203
|
+
self.relprec -= self.ordp
|
|
1204
|
+
self._internal_lshift(-self.ordp)
|
|
1205
|
+
|
|
1206
|
+
cdef bint _set_prec_rel(self, long relprec) except -1:
|
|
1207
|
+
"""
|
|
1208
|
+
Safely set the relative precision of ``self`` to be the absolute
|
|
1209
|
+
value of ``relprec``.
|
|
1210
|
+
|
|
1211
|
+
Returns ``True`` iff ``self.relprec`` was reset.
|
|
1212
|
+
|
|
1213
|
+
Note that this will wipe out anything in ``self.unit``. Be
|
|
1214
|
+
careful resetting ``self.unit`` directly: if you set it to a
|
|
1215
|
+
different modulus, NTL may have problems. The safest way to
|
|
1216
|
+
reset ``self.unit`` to a different modulus is::
|
|
1217
|
+
|
|
1218
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
1219
|
+
cdef ZZ_pX_c tmp = self.unit
|
|
1220
|
+
self._set_prec_rel(new_rel_prec)
|
|
1221
|
+
ZZ_pX_conv_modulus(self.unit, tmp, self.prime_pow.get_context_capdiv(self.relprec).x)
|
|
1222
|
+
|
|
1223
|
+
You may be able to just set ``self.relprec`` and
|
|
1224
|
+
``ZZ_pX_conv_modulus`` if you're decreasing precision. I'm
|
|
1225
|
+
not sure.
|
|
1226
|
+
|
|
1227
|
+
TESTS::
|
|
1228
|
+
|
|
1229
|
+
sage: R = Zp(5,5)
|
|
1230
|
+
sage: S.<x> = R[]
|
|
1231
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1232
|
+
sage: W.<w> = R.ext(f)
|
|
1233
|
+
sage: W(70, relprec=8) # indirect doctest
|
|
1234
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)
|
|
1235
|
+
"""
|
|
1236
|
+
if self.relprec == relprec:
|
|
1237
|
+
return False
|
|
1238
|
+
if relprec != 0:
|
|
1239
|
+
self.prime_pow.restore_context_capdiv(relprec)
|
|
1240
|
+
self.unit = ZZ_pX_c()
|
|
1241
|
+
self.relprec = relprec
|
|
1242
|
+
return True
|
|
1243
|
+
|
|
1244
|
+
cdef bint _set_prec_both(self, long absprec, long relprec) except -1:
|
|
1245
|
+
"""
|
|
1246
|
+
Assuming ``self.ordp`` is set, sets the relative precision of ``self``
|
|
1247
|
+
to the minimum of ``abs(relprec)`` and ``absprec-self.ordp``.
|
|
1248
|
+
|
|
1249
|
+
If ``relprec`` is negative, will set ``self.relprec`` to be negative
|
|
1250
|
+
(indicating unnormalized unit)
|
|
1251
|
+
|
|
1252
|
+
Returns ``True`` iff ``self.relprec = 0``, ie ``self`` was set to an
|
|
1253
|
+
inexact zero.
|
|
1254
|
+
|
|
1255
|
+
Note that this will wipe out anything in ``self.unit``. Be
|
|
1256
|
+
careful resetting ``self.unit`` directly: if you set it to a
|
|
1257
|
+
different modulus, NTL may have problems. The safest way to
|
|
1258
|
+
reset ``self.unit`` to a different modulus is:
|
|
1259
|
+
|
|
1260
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
1261
|
+
cdef ZZ_pX_c tmp = self.unit
|
|
1262
|
+
self._set_prec_rel(new_rel_prec)
|
|
1263
|
+
ZZ_pX_conv_modulus(self.unit, tmp, self.prime_pow.get_context_capdiv(self.relprec).x)
|
|
1264
|
+
|
|
1265
|
+
You may be able to just set ``self.relprec`` and
|
|
1266
|
+
``ZZ_pX_conv_modulus`` if you're decreasing precision. I'm
|
|
1267
|
+
not sure.
|
|
1268
|
+
|
|
1269
|
+
TESTS::
|
|
1270
|
+
|
|
1271
|
+
sage: R = Zp(5,5)
|
|
1272
|
+
sage: S.<x> = R[]
|
|
1273
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1274
|
+
sage: W.<w> = R.ext(f)
|
|
1275
|
+
sage: W(70, 8) # indirect doctest
|
|
1276
|
+
4*w^5 + 3*w^7 + O(w^8)
|
|
1277
|
+
"""
|
|
1278
|
+
self.relprec = absprec - self.ordp
|
|
1279
|
+
cdef long arelprec
|
|
1280
|
+
if relprec < 0:
|
|
1281
|
+
arelprec = -relprec
|
|
1282
|
+
else:
|
|
1283
|
+
arelprec = relprec
|
|
1284
|
+
if self.relprec <= 0:
|
|
1285
|
+
self._set_inexact_zero(absprec)
|
|
1286
|
+
else:
|
|
1287
|
+
if arelprec < self.relprec:
|
|
1288
|
+
self.relprec = arelprec
|
|
1289
|
+
if self.relprec != 0:
|
|
1290
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
1291
|
+
self.unit = ZZ_pX_c()
|
|
1292
|
+
if relprec < 0:
|
|
1293
|
+
self.relprec = -self.relprec
|
|
1294
|
+
return self.relprec == 0
|
|
1295
|
+
|
|
1296
|
+
cdef int _normalize(self) except -1:
|
|
1297
|
+
"""
|
|
1298
|
+
Normalize ``self``, adjusting ``self.ordp``, ``self.relprec``, and
|
|
1299
|
+
``self.unit`` so that ``self.unit`` actually represents a unit.
|
|
1300
|
+
|
|
1301
|
+
EXAMPLES::
|
|
1302
|
+
|
|
1303
|
+
sage: R = Zp(5,5)
|
|
1304
|
+
sage: S.<x> = R[]
|
|
1305
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1306
|
+
sage: W.<w> = R.ext(f)
|
|
1307
|
+
sage: z = (1+w)^5
|
|
1308
|
+
sage: y = z - 1
|
|
1309
|
+
sage: y._ntl_rep_unnormalized()
|
|
1310
|
+
[5 3005 25 3060 5]
|
|
1311
|
+
sage: y # indirect doctest
|
|
1312
|
+
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 + O(w^25)
|
|
1313
|
+
sage: y._ntl_rep_unnormalized()
|
|
1314
|
+
[41 26 152 49 535]
|
|
1315
|
+
"""
|
|
1316
|
+
cdef long minval = 0, mini = 0, shift
|
|
1317
|
+
if self.relprec < 0:
|
|
1318
|
+
if ZZ_pX_IsZero(self.unit):
|
|
1319
|
+
self.ordp -= self.relprec # note that self.relprec < 0
|
|
1320
|
+
self.relprec = 0
|
|
1321
|
+
else:
|
|
1322
|
+
ZZ_pX_min_val_coeff(minval, mini, self.unit, self.prime_pow.pow_ZZ_tmp(1)[0])
|
|
1323
|
+
if self.prime_pow.e == 1:
|
|
1324
|
+
shift = minval
|
|
1325
|
+
else:
|
|
1326
|
+
shift = minval * self.prime_pow.e + mini
|
|
1327
|
+
if shift >= -self.relprec:
|
|
1328
|
+
self.ordp -= self.relprec # note that self.relprec < 0
|
|
1329
|
+
self.relprec = 0
|
|
1330
|
+
elif shift > 0:
|
|
1331
|
+
self.relprec = -self.relprec - shift
|
|
1332
|
+
self.ordp += shift
|
|
1333
|
+
self._internal_lshift(-shift)
|
|
1334
|
+
else:
|
|
1335
|
+
self.relprec = -self.relprec
|
|
1336
|
+
|
|
1337
|
+
def _is_normalized(self):
|
|
1338
|
+
"""
|
|
1339
|
+
Whether this element is currently normalized.
|
|
1340
|
+
|
|
1341
|
+
EXAMPLES::
|
|
1342
|
+
|
|
1343
|
+
sage: R.<a> = ZqCR(125,implementation="NTL"); b = 5*a + 4; c = 10*a^2 + 6; d = b + c
|
|
1344
|
+
sage: d._is_normalized()
|
|
1345
|
+
False
|
|
1346
|
+
sage: d.valuation()
|
|
1347
|
+
1
|
|
1348
|
+
sage: d._is_normalized()
|
|
1349
|
+
True
|
|
1350
|
+
"""
|
|
1351
|
+
return self.relprec >= 0
|
|
1352
|
+
|
|
1353
|
+
cdef int _internal_lshift(self, long shift) except -1:
|
|
1354
|
+
"""
|
|
1355
|
+
Multiply ``self.unit`` by ``x^shift``.
|
|
1356
|
+
|
|
1357
|
+
Note that ``self.relprec`` must be set before calling this
|
|
1358
|
+
function and should not be 0, and self.unit must be defined to
|
|
1359
|
+
precision ``self.relprec - shift``
|
|
1360
|
+
|
|
1361
|
+
This function does not alter ``self.ordp`` even though it WILL
|
|
1362
|
+
change the valuation of ``self.unit``
|
|
1363
|
+
|
|
1364
|
+
Also note that if you call this function you should usually
|
|
1365
|
+
manually set ``self.relprec = -self.relprec`` since this function
|
|
1366
|
+
will usually unnormalize ``self``.
|
|
1367
|
+
|
|
1368
|
+
TESTS::
|
|
1369
|
+
|
|
1370
|
+
sage: R = Zp(5,5)
|
|
1371
|
+
sage: S.<x> = R[]
|
|
1372
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1373
|
+
sage: W.<w> = R.ext(f)
|
|
1374
|
+
sage: z = (1+w)^5
|
|
1375
|
+
sage: y = z - 1
|
|
1376
|
+
sage: y # indirect doctest
|
|
1377
|
+
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 + O(w^25)
|
|
1378
|
+
"""
|
|
1379
|
+
if self.relprec == 0:
|
|
1380
|
+
raise ValueError("p-adic Internal l-shift called with relative precision 0")
|
|
1381
|
+
cdef ZZ_pX_c tmpP
|
|
1382
|
+
cdef ZZ_pX_Modulus_c* mod
|
|
1383
|
+
if self.prime_pow.e == 1:
|
|
1384
|
+
if shift > 0:
|
|
1385
|
+
ZZ_pX_left_pshift(self.unit, self.unit, self.prime_pow.pow_ZZ_tmp(shift)[0], self.prime_pow.get_context(self.relprec).x)
|
|
1386
|
+
else:
|
|
1387
|
+
ZZ_pX_right_pshift(self.unit, self.unit, self.prime_pow.pow_ZZ_tmp(-shift)[0], self.prime_pow.get_context(self.relprec).x)
|
|
1388
|
+
else:
|
|
1389
|
+
if shift > 0:
|
|
1390
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
1391
|
+
mod = self.prime_pow.get_modulus_capdiv(self.relprec)
|
|
1392
|
+
ZZ_pX_PowerXMod_long_pre(tmpP, shift, mod[0])
|
|
1393
|
+
ZZ_pX_MulMod_pre(self.unit, self.unit, tmpP, mod[0])
|
|
1394
|
+
elif shift < 0:
|
|
1395
|
+
self.prime_pow.eis_shift_capdiv(&self.unit, &self.unit, -shift, self.relprec)
|
|
1396
|
+
|
|
1397
|
+
cdef int _pshift_self(self, long shift) except -1:
|
|
1398
|
+
"""
|
|
1399
|
+
Multiply ``self`` by ``p^shift``.
|
|
1400
|
+
|
|
1401
|
+
This function assumes that ``self.relprec``, ``self.ordp`` and
|
|
1402
|
+
``self.unit`` are already set (in the case ``self.prime_pow.e
|
|
1403
|
+
!= 1``), and is more reasonable to call externally than
|
|
1404
|
+
``_internal_lshift``
|
|
1405
|
+
|
|
1406
|
+
EXAMPLES::
|
|
1407
|
+
|
|
1408
|
+
sage: R = Qp(5,5)
|
|
1409
|
+
sage: S.<x> = R[]
|
|
1410
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1411
|
+
sage: W.<w> = R.ext(f)
|
|
1412
|
+
sage: z = W(3/25, relprec=6); z
|
|
1413
|
+
3*w^-10 + 3*w^-8 + 2*w^-6 + O(w^-4)
|
|
1414
|
+
sage: z * 25
|
|
1415
|
+
3 + O(w^6)
|
|
1416
|
+
"""
|
|
1417
|
+
cdef ZZ_pX_c high_shifter
|
|
1418
|
+
cdef ZZ_pX_Modulus_c *modulus
|
|
1419
|
+
cdef ntl_ZZ_pContext_class c
|
|
1420
|
+
cdef ZZ_pX_c* high_array
|
|
1421
|
+
cdef long i, high_length
|
|
1422
|
+
if self.prime_pow.e == 1:
|
|
1423
|
+
self.ordp += shift
|
|
1424
|
+
else:
|
|
1425
|
+
self.ordp += shift * self.prime_pow.e
|
|
1426
|
+
if shift < 0:
|
|
1427
|
+
shift = -shift
|
|
1428
|
+
c = self.prime_pow.get_context_capdiv(self.relprec)
|
|
1429
|
+
c.restore_c()
|
|
1430
|
+
modulus = self.prime_pow.get_modulus_capdiv(self.relprec)
|
|
1431
|
+
if isinstance(self.prime_pow, PowComputer_ZZ_pX_big_Eis):
|
|
1432
|
+
high_array = (<PowComputer_ZZ_pX_big_Eis>self.prime_pow).high_shifter
|
|
1433
|
+
elif isinstance(self.prime_pow, PowComputer_ZZ_pX_small_Eis):
|
|
1434
|
+
high_array = (<PowComputer_ZZ_pX_small_Eis>self.prime_pow).high_shifter
|
|
1435
|
+
else:
|
|
1436
|
+
raise TypeError("unrecognized PowComputer type")
|
|
1437
|
+
ZZ_pX_conv_modulus(high_shifter, high_array[0], c.x)
|
|
1438
|
+
ZZ_pX_InvMod_newton_ram(high_shifter, high_shifter, modulus[0], c.x)
|
|
1439
|
+
ZZ_pX_PowerMod_long_pre(high_shifter, high_shifter, shift, modulus[0])
|
|
1440
|
+
ZZ_pX_MulMod_pre(self.unit, self.unit, high_shifter, modulus[0])
|
|
1441
|
+
elif shift > 0:
|
|
1442
|
+
i = 0
|
|
1443
|
+
c = self.prime_pow.get_context_capdiv(self.relprec)
|
|
1444
|
+
c.restore_c()
|
|
1445
|
+
modulus = self.prime_pow.get_modulus_capdiv(self.relprec)
|
|
1446
|
+
if isinstance(self.prime_pow, PowComputer_ZZ_pX_big_Eis):
|
|
1447
|
+
high_array = (<PowComputer_ZZ_pX_big_Eis>self.prime_pow).high_shifter
|
|
1448
|
+
high_length = (<PowComputer_ZZ_pX_big_Eis>self.prime_pow).high_length
|
|
1449
|
+
elif isinstance(self.prime_pow, PowComputer_ZZ_pX_small_Eis):
|
|
1450
|
+
high_array = (<PowComputer_ZZ_pX_small_Eis>self.prime_pow).high_shifter
|
|
1451
|
+
high_length = (<PowComputer_ZZ_pX_small_Eis>self.prime_pow).high_length
|
|
1452
|
+
else:
|
|
1453
|
+
raise TypeError("unrecognized PowComputer type")
|
|
1454
|
+
if shift >= self.prime_pow.prec_cap:
|
|
1455
|
+
# high_shifter = p^(2^(high_length - 1))/x^(e*2^(high_length - 1))
|
|
1456
|
+
ZZ_pX_conv_modulus(high_shifter, high_array[high_length-1], c.x)
|
|
1457
|
+
# if shift = r + s * 2^(high_length - 1)
|
|
1458
|
+
# then high_shifter = p^(s*2^(high_length - 1))/x^(e*s*2^(high_length - 1))
|
|
1459
|
+
ZZ_pX_PowerMod_long_pre(high_shifter, high_shifter, (shift / (1L << (high_length - 1))), modulus[0])
|
|
1460
|
+
ZZ_pX_MulMod_pre(self.unit, self.unit, high_shifter, modulus[0])
|
|
1461
|
+
# Now we only need to multiply self.unit by p^r/x^(e*r) where r < 2^(high_length - 1), which is tractable.
|
|
1462
|
+
shift = shift % (1L << (high_length - 1))
|
|
1463
|
+
while shift > 0:
|
|
1464
|
+
if shift & 1:
|
|
1465
|
+
ZZ_pX_conv_modulus(high_shifter, high_array[i], c.x)
|
|
1466
|
+
ZZ_pX_MulMod_pre(self.unit, self.unit, high_shifter, modulus[0])
|
|
1467
|
+
shift = shift >> 1
|
|
1468
|
+
i += 1
|
|
1469
|
+
|
|
1470
|
+
cdef pAdicZZpXCRElement _new_c(self, long relprec):
|
|
1471
|
+
"""
|
|
1472
|
+
Return a new element with the same parent as ``self`` and
|
|
1473
|
+
relative precision ``relprec``
|
|
1474
|
+
|
|
1475
|
+
Note that if ``relprec`` is nonpositive, the convention is that
|
|
1476
|
+
``relprec = 0`` indicates an exact or inexact zero, ``relprec < 0``
|
|
1477
|
+
indicates an unnormalized element.
|
|
1478
|
+
|
|
1479
|
+
EXAMPLES::
|
|
1480
|
+
|
|
1481
|
+
sage: R = Qp(5,5)
|
|
1482
|
+
sage: S.<x> = R[]
|
|
1483
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1484
|
+
sage: W.<w> = R.ext(f)
|
|
1485
|
+
sage: w^5 + 1 # indirect doctest
|
|
1486
|
+
1 + w^5 + O(w^25)
|
|
1487
|
+
"""
|
|
1488
|
+
cdef pAdicZZpXCRElement ans = pAdicZZpXCRElement.__new__(pAdicZZpXCRElement)
|
|
1489
|
+
ans._parent = self._parent
|
|
1490
|
+
ans.prime_pow = self.prime_pow
|
|
1491
|
+
if relprec > 0:
|
|
1492
|
+
self.prime_pow.restore_context_capdiv(relprec)
|
|
1493
|
+
ans.relprec = relprec
|
|
1494
|
+
elif relprec == 0:
|
|
1495
|
+
ans._set_exact_zero()
|
|
1496
|
+
else:
|
|
1497
|
+
self.prime_pow.restore_context_capdiv(-relprec)
|
|
1498
|
+
ans.relprec = relprec
|
|
1499
|
+
return ans
|
|
1500
|
+
|
|
1501
|
+
def __reduce__(self):
|
|
1502
|
+
"""
|
|
1503
|
+
Pickles ``self``.
|
|
1504
|
+
|
|
1505
|
+
EXAMPLES::
|
|
1506
|
+
|
|
1507
|
+
sage: R = Qp(5,5)
|
|
1508
|
+
sage: S.<x> = R[]
|
|
1509
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1510
|
+
sage: W.<w> = R.ext(f)
|
|
1511
|
+
sage: z = (1 + w)^5 - 1
|
|
1512
|
+
sage: loads(dumps(z)) == z
|
|
1513
|
+
True
|
|
1514
|
+
"""
|
|
1515
|
+
cdef Integer relprec, ordp
|
|
1516
|
+
relprec = PY_NEW(Integer)
|
|
1517
|
+
ordp = PY_NEW(Integer)
|
|
1518
|
+
mpz_set_si(relprec.value, self.relprec)
|
|
1519
|
+
mpz_set_si(ordp.value, self.ordp)
|
|
1520
|
+
if self.relprec == 0:
|
|
1521
|
+
return make_ZZpXCRElement, (self.parent(), None, ordp, relprec, 0)
|
|
1522
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
1523
|
+
cdef ntl_ZZ_pX holder = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
|
|
1524
|
+
holder.c = self.prime_pow.get_context_capdiv(self.relprec)
|
|
1525
|
+
holder.x = self.unit
|
|
1526
|
+
return make_ZZpXCRElement, (self.parent(), holder, ordp, relprec, 0)
|
|
1527
|
+
|
|
1528
|
+
cdef int _cmp_units(left, pAdicGenericElement right) except -2:
|
|
1529
|
+
"""
|
|
1530
|
+
For units ``left`` and ``right``, return 0 if they are equal up to
|
|
1531
|
+
the lesser of the two precisions, or 1 if they are not.
|
|
1532
|
+
|
|
1533
|
+
EXAMPLES::
|
|
1534
|
+
|
|
1535
|
+
sage: R = Qp(5,5)
|
|
1536
|
+
sage: S.<x> = R[]
|
|
1537
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1538
|
+
sage: W.<w> = R.ext(f)
|
|
1539
|
+
sage: w == 1 # indirect doctest
|
|
1540
|
+
False
|
|
1541
|
+
sage: y = 1 + w + O(w^7)
|
|
1542
|
+
sage: z = 1 + w + w^10 + O(w^13)
|
|
1543
|
+
sage: y == z
|
|
1544
|
+
True
|
|
1545
|
+
"""
|
|
1546
|
+
# This function needs improvement. In particular, there are a lot of
|
|
1547
|
+
# speed improvements to be had, and it should be changed so that it
|
|
1548
|
+
# returns 1 only half the time (and -1 the other half) when left and
|
|
1549
|
+
# right are not equal.
|
|
1550
|
+
cdef pAdicZZpXCRElement diff = <pAdicZZpXCRElement> (left - right)
|
|
1551
|
+
diff._normalize()
|
|
1552
|
+
if diff.relprec == 0:
|
|
1553
|
+
return 0
|
|
1554
|
+
# for now, just return 1
|
|
1555
|
+
return 1
|
|
1556
|
+
|
|
1557
|
+
def __invert__(self):
|
|
1558
|
+
"""
|
|
1559
|
+
Return the inverse of this element.
|
|
1560
|
+
|
|
1561
|
+
EXAMPLES::
|
|
1562
|
+
|
|
1563
|
+
sage: R = Zp(5,5)
|
|
1564
|
+
sage: S.<x> = R[]
|
|
1565
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1566
|
+
sage: W.<w> = R.ext(f)
|
|
1567
|
+
sage: z = (1 + w)^5
|
|
1568
|
+
sage: y = ~z; y # indirect doctest
|
|
1569
|
+
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 + 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24 + O(w^25)
|
|
1570
|
+
sage: y.parent()
|
|
1571
|
+
5-adic Eisenstein Extension Field in w defined by x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1572
|
+
sage: z = z - 1
|
|
1573
|
+
sage: ~z
|
|
1574
|
+
w^-5 + 4*w^-4 + 4*w^-3 + 4*w^-2 + 2*w^-1 + 1 + w + 4*w^2 + 4*w^3 + 4*w^4 + w^5 + w^6 + w^7 + 4*w^8 + 4*w^9 + 2*w^10 + w^11 + 2*w^12 + 4*w^13 + 4*w^14 + O(w^15)
|
|
1575
|
+
sage: ~z * z
|
|
1576
|
+
1 + O(w^20)
|
|
1577
|
+
"""
|
|
1578
|
+
if self._is_exact_zero():
|
|
1579
|
+
raise ZeroDivisionError("cannot divide by zero")
|
|
1580
|
+
if self._is_inexact_zero(): # this calls _normalize
|
|
1581
|
+
raise PrecisionError("cannot divide by something indistinguishable from zero")
|
|
1582
|
+
cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
|
|
1583
|
+
if not ans.prime_pow.in_field:
|
|
1584
|
+
ans._parent = self._parent.fraction_field()
|
|
1585
|
+
ans.prime_pow = ans._parent.prime_pow
|
|
1586
|
+
ans.ordp = -self.ordp
|
|
1587
|
+
sig_on()
|
|
1588
|
+
if self.prime_pow.e == 1:
|
|
1589
|
+
ZZ_pX_InvMod_newton_unram(ans.unit, self.unit, self.prime_pow.get_modulus(ans.relprec)[0], self.prime_pow.get_context(ans.relprec).x, self.prime_pow.get_context(1).x)
|
|
1590
|
+
else:
|
|
1591
|
+
ZZ_pX_InvMod_newton_ram(ans.unit, self.unit, self.prime_pow.get_modulus_capdiv(ans.relprec)[0], self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
1592
|
+
sig_off()
|
|
1593
|
+
return ans
|
|
1594
|
+
|
|
1595
|
+
cdef pAdicZZpXCRElement _lshift_c(self, long n):
|
|
1596
|
+
"""
|
|
1597
|
+
Multiply ``self`` by the uniformizer raised to the power ``n``. If
|
|
1598
|
+
``n`` is negative, right shifts by ``-n``.
|
|
1599
|
+
|
|
1600
|
+
EXAMPLES::
|
|
1601
|
+
|
|
1602
|
+
sage: R = Zp(5,5)
|
|
1603
|
+
sage: S.<x> = R[]
|
|
1604
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1605
|
+
sage: W.<w> = R.ext(f)
|
|
1606
|
+
sage: z = (1 + w)^5
|
|
1607
|
+
sage: z
|
|
1608
|
+
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 + O(w^25)
|
|
1609
|
+
sage: z << 17 # indirect doctest
|
|
1610
|
+
w^17 + w^22 + w^23 + 2*w^24 + 4*w^25 + 3*w^27 + w^29 + 4*w^30 + 4*w^31 + 4*w^32 + 4*w^33 + 4*w^34 + 4*w^37 + w^38 + 4*w^41 + O(w^42)
|
|
1611
|
+
sage: z << (-1)
|
|
1612
|
+
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 + O(w^24)
|
|
1613
|
+
"""
|
|
1614
|
+
if not self.prime_pow.in_field and n < -self.ordp:
|
|
1615
|
+
return self._rshift_c(-n)
|
|
1616
|
+
check_ordp(n)
|
|
1617
|
+
cdef pAdicZZpXCRElement ans
|
|
1618
|
+
if self._is_exact_zero() or n == 0:
|
|
1619
|
+
return self
|
|
1620
|
+
elif self._is_inexact_zero():
|
|
1621
|
+
ans = self._new_c(0)
|
|
1622
|
+
else:
|
|
1623
|
+
ans = self._new_c(self.relprec)
|
|
1624
|
+
ans.unit = self.unit
|
|
1625
|
+
ans.ordp = self.ordp + n
|
|
1626
|
+
check_ordp(ans.ordp)
|
|
1627
|
+
return ans
|
|
1628
|
+
|
|
1629
|
+
def __lshift__(pAdicZZpXCRElement self, shift):
|
|
1630
|
+
"""
|
|
1631
|
+
Multiply ``self`` by the uniformizer raised to the power ``n``. If
|
|
1632
|
+
``n`` is negative, right shifts by ``-n``.
|
|
1633
|
+
|
|
1634
|
+
EXAMPLES::
|
|
1635
|
+
|
|
1636
|
+
sage: R = Zp(5,5)
|
|
1637
|
+
sage: S.<x> = R[]
|
|
1638
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1639
|
+
sage: W.<w> = R.ext(f)
|
|
1640
|
+
sage: z = (1 + w)^5
|
|
1641
|
+
sage: z
|
|
1642
|
+
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 + O(w^25)
|
|
1643
|
+
sage: z << 17 # indirect doctest
|
|
1644
|
+
w^17 + w^22 + w^23 + 2*w^24 + 4*w^25 + 3*w^27 + w^29 + 4*w^30 + 4*w^31 + 4*w^32 + 4*w^33 + 4*w^34 + 4*w^37 + w^38 + 4*w^41 + O(w^42)
|
|
1645
|
+
sage: z << (-1)
|
|
1646
|
+
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 + O(w^24)
|
|
1647
|
+
"""
|
|
1648
|
+
cdef pAdicZZpXCRElement ans
|
|
1649
|
+
if not isinstance(shift, Integer):
|
|
1650
|
+
shift = Integer(shift)
|
|
1651
|
+
if mpz_fits_slong_p((<Integer>shift).value) == 0:
|
|
1652
|
+
if self._is_exact_zero():
|
|
1653
|
+
return self
|
|
1654
|
+
if self.prime_pow.in_field or mpz_sgn((<Integer>shift).value) > 0:
|
|
1655
|
+
raise ValueError("shift does not fit in long")
|
|
1656
|
+
else:
|
|
1657
|
+
ans = self._new_c(0)
|
|
1658
|
+
ans.ordp = 0
|
|
1659
|
+
return ans
|
|
1660
|
+
return self._lshift_c(mpz_get_si((<Integer>shift).value))
|
|
1661
|
+
|
|
1662
|
+
cdef pAdicZZpXCRElement _rshift_c(self, long n):
|
|
1663
|
+
"""
|
|
1664
|
+
Divide ``self`` by the uniformizer raised to the power ``n``. If
|
|
1665
|
+
parent is not a field, throws away the nonpositive part of
|
|
1666
|
+
the series expansion. If ``n`` is negative, left shifts by ``-n``.
|
|
1667
|
+
|
|
1668
|
+
EXAMPLES::
|
|
1669
|
+
|
|
1670
|
+
sage: R = Zp(5,5,print_mode='digits')
|
|
1671
|
+
sage: S.<x> = R[]
|
|
1672
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1673
|
+
sage: W.<w> = R.ext(f)
|
|
1674
|
+
sage: z = (1 + w)^5
|
|
1675
|
+
sage: for m in range(26): repr(z >> m) # indirect doctest
|
|
1676
|
+
'...4001400444441030421100001'
|
|
1677
|
+
'...400140044444103042110000'
|
|
1678
|
+
'...40014004444410304211000'
|
|
1679
|
+
'...4001400444441030421100'
|
|
1680
|
+
'...400140044444103042110'
|
|
1681
|
+
'...40014004444410304211'
|
|
1682
|
+
'...4001400444441030421'
|
|
1683
|
+
'...400140044444103042'
|
|
1684
|
+
'...40014004444410304'
|
|
1685
|
+
'...4001400444441030'
|
|
1686
|
+
'...400140044444103'
|
|
1687
|
+
'...40014004444410'
|
|
1688
|
+
'...4001400444441'
|
|
1689
|
+
'...400140044444'
|
|
1690
|
+
'...40014004444'
|
|
1691
|
+
'...4001400444'
|
|
1692
|
+
'...400140044'
|
|
1693
|
+
'...40014004'
|
|
1694
|
+
'...4001400'
|
|
1695
|
+
'...400140'
|
|
1696
|
+
'...40014'
|
|
1697
|
+
'...4001'
|
|
1698
|
+
'...400'
|
|
1699
|
+
'...40'
|
|
1700
|
+
'...4'
|
|
1701
|
+
'...'
|
|
1702
|
+
sage: repr(z >> (-4))
|
|
1703
|
+
'...40014004444410304211000010000'
|
|
1704
|
+
"""
|
|
1705
|
+
if self.prime_pow.in_field or n <= self.ordp:
|
|
1706
|
+
return self._lshift_c(-n)
|
|
1707
|
+
if self._is_exact_zero() or n == 0:
|
|
1708
|
+
return self
|
|
1709
|
+
cdef long arelprec
|
|
1710
|
+
if self.relprec < 0:
|
|
1711
|
+
arelprec = -self.relprec
|
|
1712
|
+
else:
|
|
1713
|
+
arelprec = self.relprec
|
|
1714
|
+
cdef pAdicZZpXCRElement ans
|
|
1715
|
+
if arelprec > n - self.ordp:
|
|
1716
|
+
ans = self._new_c(arelprec - (n - self.ordp))
|
|
1717
|
+
if self.prime_pow.e == 1:
|
|
1718
|
+
ZZ_pX_right_pshift(ans.unit, self.unit, self.prime_pow.pow_ZZ_tmp(n - self.ordp)[0], self.prime_pow.get_context(ans.relprec).x)
|
|
1719
|
+
else:
|
|
1720
|
+
self.prime_pow.eis_shift_capdiv(&ans.unit, &self.unit, n - self.ordp, ans.relprec)
|
|
1721
|
+
else:
|
|
1722
|
+
ans = self._new_c(0)
|
|
1723
|
+
ans.ordp = 0
|
|
1724
|
+
ans.relprec = -ans.relprec
|
|
1725
|
+
return ans
|
|
1726
|
+
|
|
1727
|
+
def __rshift__(pAdicZZpXCRElement self, shift):
|
|
1728
|
+
"""
|
|
1729
|
+
Divide ``self`` by the uniformizer raised to the power ``n``. If
|
|
1730
|
+
parent is not a field, throws away the nonpositive part of
|
|
1731
|
+
the series expansion. If ``n`` is negative, left shifts by ``-n``.
|
|
1732
|
+
|
|
1733
|
+
EXAMPLES::
|
|
1734
|
+
|
|
1735
|
+
sage: R = Zp(5,5)
|
|
1736
|
+
sage: S.<x> = R[]
|
|
1737
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1738
|
+
sage: W.<w> = R.ext(f)
|
|
1739
|
+
sage: z = (1 + w)^5
|
|
1740
|
+
sage: z
|
|
1741
|
+
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 + O(w^25)
|
|
1742
|
+
sage: z >> (6) # indirect doctest
|
|
1743
|
+
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 + 4*w^14 + w^15 + 4*w^18 + O(w^19)
|
|
1744
|
+
sage: z >> (-4)
|
|
1745
|
+
w^4 + w^9 + w^10 + 2*w^11 + 4*w^12 + 3*w^14 + w^16 + 4*w^17 + 4*w^18 + 4*w^19 + 4*w^20 + 4*w^21 + 4*w^24 + w^25 + 4*w^28 + O(w^29)
|
|
1746
|
+
sage: F = W.fraction_field()
|
|
1747
|
+
sage: z = F(z)
|
|
1748
|
+
sage: z >> 7
|
|
1749
|
+
w^-7 + w^-2 + w^-1 + 2 + 4*w + 3*w^3 + w^5 + 4*w^6 + 4*w^7 + 4*w^8 + 4*w^9 + 4*w^10 + 4*w^13 + w^14 + 4*w^17 + O(w^18)
|
|
1750
|
+
"""
|
|
1751
|
+
cdef pAdicZZpXCRElement ans
|
|
1752
|
+
if not isinstance(shift, Integer):
|
|
1753
|
+
shift = Integer(shift)
|
|
1754
|
+
if mpz_fits_slong_p((<Integer>shift).value) == 0:
|
|
1755
|
+
if self._is_exact_zero():
|
|
1756
|
+
return self
|
|
1757
|
+
if self.prime_pow.in_field or mpz_sgn((<Integer>shift).value) < 0:
|
|
1758
|
+
raise ValueError("valuation overflow")
|
|
1759
|
+
else:
|
|
1760
|
+
ans = self._new_c(0)
|
|
1761
|
+
ans.ordp = 0
|
|
1762
|
+
return ans
|
|
1763
|
+
return self._rshift_c(mpz_get_si((<Integer>shift).value))
|
|
1764
|
+
|
|
1765
|
+
cpdef _neg_(self):
|
|
1766
|
+
"""
|
|
1767
|
+
Negation.
|
|
1768
|
+
|
|
1769
|
+
EXAMPLES::
|
|
1770
|
+
|
|
1771
|
+
sage: R = Zp(5,5)
|
|
1772
|
+
sage: S.<x> = R[]
|
|
1773
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1774
|
+
sage: W.<w> = R.ext(f)
|
|
1775
|
+
sage: z = (1 + w)^5; z
|
|
1776
|
+
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 + O(w^25)
|
|
1777
|
+
sage: -z # indirect doctest
|
|
1778
|
+
4 + 3*w^5 + 4*w^6 + w^7 + w^8 + w^9 + w^10 + w^11 + 2*w^12 + 4*w^13 + 4*w^15 + 3*w^16 + w^17 + 2*w^18 + 3*w^19 + 2*w^21 + 4*w^23 + 4*w^24 + O(w^25)
|
|
1779
|
+
sage: y = z + (-z); y
|
|
1780
|
+
O(w^25)
|
|
1781
|
+
sage: -y
|
|
1782
|
+
O(w^25)
|
|
1783
|
+
sage: -W(0)
|
|
1784
|
+
0
|
|
1785
|
+
"""
|
|
1786
|
+
cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
|
|
1787
|
+
ans.ordp = self.ordp
|
|
1788
|
+
if self.relprec != 0:
|
|
1789
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
1790
|
+
ZZ_pX_negate(ans.unit, self.unit)
|
|
1791
|
+
return ans
|
|
1792
|
+
|
|
1793
|
+
# / 1 + \alpha^p \pi_K^{p \lambda} mod \mathfrak{p}_K^{p \lambda + 1} if 1 \le \lambda < \frac{e_K}{p-1}
|
|
1794
|
+
# (1 + \alpha \pi^{\lambda})^p \equiv { 1 + (\alpha^p - \epsilon \alpha) \pi_K^{p \lambda} mod \mathfrak{p}_K^{p \lambda + 1} if \lambda = \frac{e_K}{p-1}
|
|
1795
|
+
# \ 1 - \epsilon \alpha \pi_K^{\lambda + e} mod \mathfrak{p}_K^{\lambda + e + 1} if \lambda > \frac{e_K}{p-1}
|
|
1796
|
+
|
|
1797
|
+
def __pow__(pAdicZZpXCRElement self, _right, m): # m ignored
|
|
1798
|
+
r"""
|
|
1799
|
+
Compute ``self^right``.
|
|
1800
|
+
|
|
1801
|
+
Note: when ``right`` is divisible by `p` then one can get more
|
|
1802
|
+
precision than expected.
|
|
1803
|
+
|
|
1804
|
+
Lemma 2.1 (Constructing Class Fields over Local Fields, Sebastian Pauli):
|
|
1805
|
+
|
|
1806
|
+
Let `\alpha` be in `\mathcal{O}_K`. Let
|
|
1807
|
+
|
|
1808
|
+
.. MATH::
|
|
1809
|
+
|
|
1810
|
+
p = -\pi_K^{e_K} \epsilon
|
|
1811
|
+
|
|
1812
|
+
be the factorization of `p` where `\epsilon` is a unit. Then
|
|
1813
|
+
the `p`-th power of `1 + \alpha \pi_K^{\lambda}` satisfies
|
|
1814
|
+
|
|
1815
|
+
.. MATH::
|
|
1816
|
+
|
|
1817
|
+
(1 + \alpha \pi^{\lambda})^p \equiv \left{ \begin{array}{lll}
|
|
1818
|
+
1 + \alpha^p \pi_K^{p \lambda} & \mod \mathfrak{p}_K^{p \lambda + 1} & \mbox{if $1 \le \lambda < \frac{e_K}{p-1}$} \\
|
|
1819
|
+
1 + (\alpha^p - \epsilon \alpha) \pi_K^{p \lambda} & \mod \mathfrak{p}_K^{p \lambda + 1} & \mbox{if $\lambda = \frac{e_K}{p-1}$} \\
|
|
1820
|
+
1 - \epsilon \alpha \pi_K^{\lambda + e} & \mod \mathfrak{p}_K^{\lambda + e + 1} & \mbox{if $\lambda > \frac{e_K}{p-1}$}
|
|
1821
|
+
\end{array} \right.
|
|
1822
|
+
|
|
1823
|
+
|
|
1824
|
+
So if ``right`` is divisible by `p^k` we can multiply the
|
|
1825
|
+
relative precision by `p` until we exceed `e/(p-1)`, then add
|
|
1826
|
+
`e` until we have done a total of `k` things: the precision of
|
|
1827
|
+
the result can therefore be greater than the precision of
|
|
1828
|
+
``self``.
|
|
1829
|
+
|
|
1830
|
+
There is also the issue of `p`-adic exponents, and determining
|
|
1831
|
+
how the precision of the exponent affects the precision of the
|
|
1832
|
+
result.
|
|
1833
|
+
|
|
1834
|
+
In computing `(a + O(\pi^k))^{b + O(p^m)}`, one needs that the
|
|
1835
|
+
reduction of `a` mod `\pi` is in the prime field
|
|
1836
|
+
`\GF{p}` (so that the `p^m` power of the Teichmuller
|
|
1837
|
+
part is constant as `m` increases). Given this restriction,
|
|
1838
|
+
we can factor out the Teichmuller part and use the above lemma
|
|
1839
|
+
to find the first spot where
|
|
1840
|
+
|
|
1841
|
+
.. MATH::
|
|
1842
|
+
|
|
1843
|
+
(1 + \alpha \pi^{\lambda})^{p^m}
|
|
1844
|
+
|
|
1845
|
+
differs from 1. We compare this with the precision bound
|
|
1846
|
+
given by computing `(a + O(\pi^k))^b` and take the lesser of
|
|
1847
|
+
the two.
|
|
1848
|
+
|
|
1849
|
+
In order to do this we need to compute the valuation of ``(self
|
|
1850
|
+
/ self.parent().teichmuller(self)) - 1``.
|
|
1851
|
+
|
|
1852
|
+
EXAMPLES::
|
|
1853
|
+
|
|
1854
|
+
sage: R = Zp(5,5)
|
|
1855
|
+
sage: S.<x> = R[]
|
|
1856
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1857
|
+
sage: W.<w> = R.ext(f)
|
|
1858
|
+
sage: (1 + w)^5 # indirect doctest
|
|
1859
|
+
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 + O(w^25)
|
|
1860
|
+
sage: (1 + w)^-5
|
|
1861
|
+
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 + 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24 + O(w^25)
|
|
1862
|
+
sage: (1 + w + O(w^19))^5
|
|
1863
|
+
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 + O(w^24)
|
|
1864
|
+
sage: (1 + O(w))^5
|
|
1865
|
+
1 + O(w^5)
|
|
1866
|
+
sage: (1 + w + O(w^3))^25
|
|
1867
|
+
1 + w^10 + w^11 + 4*w^12 + O(w^13)
|
|
1868
|
+
sage: (3 + 2*w + w^2 + O(w^6))^(15 + O(125))
|
|
1869
|
+
2 + 4*w^6 + w^7 + 3*w^8 + 3*w^9 + 4*w^10 + O(w^11)
|
|
1870
|
+
sage: (3 + 2*w + w^2 + O(w^6))^(15 + O(25))
|
|
1871
|
+
2 + 4*w^6 + w^7 + 3*w^8 + 3*w^9 + O(w^10)
|
|
1872
|
+
sage: (3 + w^2 + O(w^6))^(15+O(25))
|
|
1873
|
+
2 + w^5 + 4*w^7 + w^9 + 3*w^10 + O(w^11)
|
|
1874
|
+
sage: R = Zp(2, 10)
|
|
1875
|
+
sage: S.<x> = R[]
|
|
1876
|
+
sage: f = x^34 + 18*x^5 - 72*x^3 + 2
|
|
1877
|
+
sage: W.<w> = R.ext(f)
|
|
1878
|
+
sage: (1+w+O(w^2))^8
|
|
1879
|
+
1 + w^8 + O(w^16)
|
|
1880
|
+
sage: (1+w+O(w^2))^16
|
|
1881
|
+
1 + w^16 + O(w^32)
|
|
1882
|
+
sage: (1+w+O(w^2))^32
|
|
1883
|
+
1 + w^32 + w^50 + w^55 + w^60 + O(w^64)
|
|
1884
|
+
sage: (1+w+O(w^2))^64
|
|
1885
|
+
1 + w^64 + w^66 + w^71 + w^76 + w^81 + w^84 + w^86 + w^91 + w^94 + w^96 + O(w^98)
|
|
1886
|
+
|
|
1887
|
+
TESTS:
|
|
1888
|
+
|
|
1889
|
+
We define ``0^0`` to be unity, :issue:`13786`::
|
|
1890
|
+
|
|
1891
|
+
sage: R = Zp(5,5)
|
|
1892
|
+
sage: S.<x> = R[]
|
|
1893
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1894
|
+
sage: W.<w> = R.ext(f)
|
|
1895
|
+
sage: type(W(0))
|
|
1896
|
+
<class 'sage.rings.padics.padic_ZZ_pX_CR_element.pAdicZZpXCRElement'>
|
|
1897
|
+
sage: W(0)^0
|
|
1898
|
+
1 + O(w^25)
|
|
1899
|
+
sage: W(0)^0 == W(1)
|
|
1900
|
+
True
|
|
1901
|
+
|
|
1902
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
1903
|
+
|
|
1904
|
+
sage: R = Zp(5,5)
|
|
1905
|
+
sage: S.<x> = R[]
|
|
1906
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
1907
|
+
sage: W.<w> = R.ext(f)
|
|
1908
|
+
sage: type(W(0)^0) == type(W(0))
|
|
1909
|
+
True
|
|
1910
|
+
"""
|
|
1911
|
+
self._normalize()
|
|
1912
|
+
cdef Integer right
|
|
1913
|
+
cdef bint padic_exp
|
|
1914
|
+
cdef long exp_prec
|
|
1915
|
+
cdef long exp_val
|
|
1916
|
+
cdef long relprec
|
|
1917
|
+
cdef long threshold # e / (p-1)
|
|
1918
|
+
cdef mpz_t tmp, tmp2
|
|
1919
|
+
if mpz_fits_slong_p(self.prime_pow.prime.value) == 0:
|
|
1920
|
+
threshold = 0
|
|
1921
|
+
else:
|
|
1922
|
+
threshold = self.prime_pow.e / (mpz_get_si(self.prime_pow.prime.value) - 1)
|
|
1923
|
+
cdef Integer base_level
|
|
1924
|
+
cdef pAdicZZpXCRElement ans
|
|
1925
|
+
cdef long i
|
|
1926
|
+
if self._is_exact_zero():
|
|
1927
|
+
# Return 0 except for 0^0 error or type error on the exponent.
|
|
1928
|
+
if isinstance(_right, (Integer, Rational, int)) or (isinstance(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime)):
|
|
1929
|
+
if _right == 0:
|
|
1930
|
+
return self.parent(1)
|
|
1931
|
+
return self
|
|
1932
|
+
else:
|
|
1933
|
+
raise TypeError("exponent must be an integer, rational or base p-adic with the same prime")
|
|
1934
|
+
elif self._is_inexact_zero():
|
|
1935
|
+
# If an integer exponent, return an inexact zero of valuation right * self.ordp. Otherwise raise an error.
|
|
1936
|
+
if isinstance(_right, int):
|
|
1937
|
+
_right = Integer(_right)
|
|
1938
|
+
if isinstance(_right, Integer):
|
|
1939
|
+
ans = self._new_c(0)
|
|
1940
|
+
mpz_init_set_si(tmp, self.ordp)
|
|
1941
|
+
mpz_mul(tmp, tmp, (<Integer>_right).value)
|
|
1942
|
+
if mpz_cmp_si(tmp, maxordp) >= 0 or mpz_cmp_si(tmp, -maxordp) <= 0:
|
|
1943
|
+
raise ValueError("valuation overflow")
|
|
1944
|
+
ans.ordp = mpz_get_si(tmp)
|
|
1945
|
+
mpz_clear(tmp)
|
|
1946
|
+
return ans
|
|
1947
|
+
elif isinstance(_right, Rational) or (isinstance(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime)):
|
|
1948
|
+
raise ValueError("Need more precision")
|
|
1949
|
+
else:
|
|
1950
|
+
raise TypeError("exponent must be an integer, rational or base p-adic with the same prime")
|
|
1951
|
+
if isinstance(_right, int):
|
|
1952
|
+
_right = Integer(_right)
|
|
1953
|
+
if isinstance(_right, Integer):
|
|
1954
|
+
right = <Integer> _right
|
|
1955
|
+
if right == 0:
|
|
1956
|
+
# return 1 to maximum precision
|
|
1957
|
+
ans = self._new_c(self.prime_pow.ram_prec_cap)
|
|
1958
|
+
ans.ordp = 0
|
|
1959
|
+
ZZ_pX_SetCoeff_long(ans.unit, 0, 1)
|
|
1960
|
+
return ans
|
|
1961
|
+
padic_exp = False
|
|
1962
|
+
exp_val = _right.valuation(self.prime_pow.prime) ##
|
|
1963
|
+
elif isinstance(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime):
|
|
1964
|
+
if self.ordp != 0:
|
|
1965
|
+
raise ValueError("in order to raise to a p-adic exponent, base must be a unit")
|
|
1966
|
+
right = Integer(_right)
|
|
1967
|
+
padic_exp = True
|
|
1968
|
+
exp_prec = _right.precision_absolute() ##
|
|
1969
|
+
exp_val = _right.valuation() ##
|
|
1970
|
+
if exp_val < 0:
|
|
1971
|
+
raise NotImplementedError("negative valuation exponents not yet supported")
|
|
1972
|
+
# checks to see if the residue of self.unit is in the prime field.
|
|
1973
|
+
if self.prime_pow.e == 1:
|
|
1974
|
+
for i from 1 <= i <= ZZ_pX_deg(self.unit):
|
|
1975
|
+
if not ZZ_divide_test(ZZ_p_rep(ZZ_pX_coeff(self.unit, i)), self.prime_pow.pow_ZZ_tmp(1)[0]):
|
|
1976
|
+
raise ValueError("in order to raise to a p-adic exponent, base must reduce to an element of F_p mod the uniformizer")
|
|
1977
|
+
# compute the "level"
|
|
1978
|
+
teich_part = self.parent().teichmuller(self)
|
|
1979
|
+
base_level = (self / teich_part - 1).valuation() ##
|
|
1980
|
+
elif isinstance(_right, Rational):
|
|
1981
|
+
raise NotImplementedError
|
|
1982
|
+
else:
|
|
1983
|
+
raise TypeError("exponent must be an integer, rational or base p-adic with the same prime")
|
|
1984
|
+
# Now we compute the increased relprec due to the exponent having positive p-adic valuation
|
|
1985
|
+
if exp_val > 0:
|
|
1986
|
+
mpz_init_set_si(tmp, self.relprec)
|
|
1987
|
+
while mpz_cmp_si(tmp, threshold) <= 0 and exp_val > 0:
|
|
1988
|
+
mpz_mul(tmp, tmp, self.prime_pow.prime.value)
|
|
1989
|
+
exp_val -= 1
|
|
1990
|
+
if exp_val > 0:
|
|
1991
|
+
mpz_init_set_si(tmp2, self.prime_pow.e)
|
|
1992
|
+
mpz_addmul_ui(tmp, tmp2, exp_val)
|
|
1993
|
+
mpz_clear(tmp2)
|
|
1994
|
+
if mpz_cmp_si(tmp, self.prime_pow.ram_prec_cap) > 0:
|
|
1995
|
+
relprec = self.prime_pow.ram_prec_cap
|
|
1996
|
+
else:
|
|
1997
|
+
relprec = mpz_get_si(tmp)
|
|
1998
|
+
mpz_clear(tmp)
|
|
1999
|
+
else:
|
|
2000
|
+
relprec = self.relprec
|
|
2001
|
+
# Now we compute the limit on relprec due to a non-infinite precision on the exponent.
|
|
2002
|
+
if padic_exp:
|
|
2003
|
+
if exp_prec > 0:
|
|
2004
|
+
# I can freely change base_level, so I use it in place of tmp above.
|
|
2005
|
+
while mpz_cmp_si(base_level.value, threshold) <= 0 and exp_prec > 0:
|
|
2006
|
+
mpz_mul(base_level.value, base_level.value, self.prime_pow.prime.value)
|
|
2007
|
+
exp_prec -= 1
|
|
2008
|
+
if exp_prec > 0:
|
|
2009
|
+
mpz_init_set_si(tmp2, self.prime_pow.e)
|
|
2010
|
+
mpz_addmul_ui(base_level.value, tmp2, exp_prec)
|
|
2011
|
+
mpz_clear(tmp2)
|
|
2012
|
+
if mpz_cmp_si(base_level.value, relprec) < 0:
|
|
2013
|
+
relprec = mpz_get_si(base_level.value)
|
|
2014
|
+
else:
|
|
2015
|
+
ans = self._new_c(0)
|
|
2016
|
+
ans.ordp = 0
|
|
2017
|
+
return ans
|
|
2018
|
+
ans = self._new_c(relprec)
|
|
2019
|
+
if self.ordp == 0:
|
|
2020
|
+
ans.ordp = 0
|
|
2021
|
+
else:
|
|
2022
|
+
mpz_init_set(tmp, right.value)
|
|
2023
|
+
mpz_mul_si(tmp, tmp, self.ordp)
|
|
2024
|
+
if mpz_cmp_si(tmp, maxordp) >= 0 or mpz_cmp_si(tmp, -maxordp) <= 0:
|
|
2025
|
+
raise ValueError("valuation overflow")
|
|
2026
|
+
ans.ordp = mpz_get_si(tmp)
|
|
2027
|
+
mpz_clear(tmp)
|
|
2028
|
+
cdef ntl_ZZ rZZ = ntl_ZZ.__new__(ntl_ZZ)
|
|
2029
|
+
mpz_to_ZZ(&rZZ.x, right.value)
|
|
2030
|
+
sig_on()
|
|
2031
|
+
if mpz_sgn(right.value) < 0:
|
|
2032
|
+
if self.prime_pow.e == 1:
|
|
2033
|
+
ZZ_pX_InvMod_newton_unram(ans.unit, self.unit, self.prime_pow.get_modulus(ans.relprec)[0], self.prime_pow.get_context(ans.relprec).x, self.prime_pow.get_context(1).x)
|
|
2034
|
+
else:
|
|
2035
|
+
ZZ_pX_InvMod_newton_ram(ans.unit, self.unit, self.prime_pow.get_modulus_capdiv(ans.relprec)[0], self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2036
|
+
ZZ_negate(rZZ.x, rZZ.x)
|
|
2037
|
+
ZZ_pX_PowerMod_pre(ans.unit, ans.unit, rZZ.x, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
|
|
2038
|
+
else:
|
|
2039
|
+
ZZ_pX_PowerMod_pre(ans.unit, self.unit, rZZ.x, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
|
|
2040
|
+
sig_off()
|
|
2041
|
+
return ans
|
|
2042
|
+
|
|
2043
|
+
cpdef _add_(self, _right):
|
|
2044
|
+
"""
|
|
2045
|
+
Compute the sum of ``self`` and ``right``.
|
|
2046
|
+
|
|
2047
|
+
EXAMPLES::
|
|
2048
|
+
|
|
2049
|
+
sage: R = Zp(5,5)
|
|
2050
|
+
sage: S.<x> = R[]
|
|
2051
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2052
|
+
sage: W.<w> = R.ext(f)
|
|
2053
|
+
sage: (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)) - 69 # indirect doctest
|
|
2054
|
+
1 + O(w^13)
|
|
2055
|
+
sage: -69 + (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13))
|
|
2056
|
+
1 + O(w^13)
|
|
2057
|
+
sage: y = (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13))
|
|
2058
|
+
sage: y - 70
|
|
2059
|
+
O(w^13)
|
|
2060
|
+
sage: y + 0
|
|
2061
|
+
4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)
|
|
2062
|
+
"""
|
|
2063
|
+
cdef pAdicZZpXCRElement right = <pAdicZZpXCRElement>_right
|
|
2064
|
+
cdef pAdicZZpXCRElement ans
|
|
2065
|
+
cdef long tmpL
|
|
2066
|
+
cdef ZZ_pX_c tmpP
|
|
2067
|
+
if self.relprec == 0:
|
|
2068
|
+
if self.ordp >= right.ordp + right.relprec: # or self._is_exact_zero()
|
|
2069
|
+
return right
|
|
2070
|
+
elif self.ordp <= right.ordp:
|
|
2071
|
+
ans = self._new_c(0)
|
|
2072
|
+
ans.ordp = self.ordp
|
|
2073
|
+
else:
|
|
2074
|
+
ans = self._new_c(self.ordp - right.ordp)
|
|
2075
|
+
ZZ_pX_conv_modulus(ans.unit, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2076
|
+
if right.relprec < 0:
|
|
2077
|
+
ans.relprec = -ans.relprec
|
|
2078
|
+
ans.ordp = right.ordp
|
|
2079
|
+
return ans
|
|
2080
|
+
if right.relprec == 0:
|
|
2081
|
+
if right.ordp >= self.ordp + self.relprec: # or right._is_exact_zero()
|
|
2082
|
+
return self
|
|
2083
|
+
elif right.ordp <= self.ordp:
|
|
2084
|
+
ans = self._new_c(0)
|
|
2085
|
+
ans.ordp = right.ordp
|
|
2086
|
+
else:
|
|
2087
|
+
ans = self._new_c(right.ordp - self.ordp)
|
|
2088
|
+
ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2089
|
+
if self.relprec < 0:
|
|
2090
|
+
ans.relprec = -ans.relprec
|
|
2091
|
+
ans.ordp = self.ordp
|
|
2092
|
+
return ans
|
|
2093
|
+
cdef long srprec = self.relprec
|
|
2094
|
+
if srprec < 0:
|
|
2095
|
+
srprec = -srprec
|
|
2096
|
+
cdef long rrprec = right.relprec
|
|
2097
|
+
if rrprec < 0:
|
|
2098
|
+
rrprec = -rrprec
|
|
2099
|
+
if self.ordp == right.ordp:
|
|
2100
|
+
# The relative precision of the sum is the minimum of the relative precisions in this case, possibly decreasing if we got cancellation
|
|
2101
|
+
# Since the valuations are the same, we could just add the units, if they had the same modulus.
|
|
2102
|
+
# But they don't necessarily, so we may have to conv_modulus
|
|
2103
|
+
if srprec == rrprec:
|
|
2104
|
+
ans = self._new_c(-srprec) # -srprec indicates that ans is not normalized
|
|
2105
|
+
self.prime_pow.restore_context_capdiv(srprec)
|
|
2106
|
+
ZZ_pX_add(ans.unit, self.unit, right.unit)
|
|
2107
|
+
elif srprec < rrprec:
|
|
2108
|
+
ans = self._new_c(-srprec)
|
|
2109
|
+
ZZ_pX_conv_modulus(ans.unit, right.unit, self.prime_pow.get_context_capdiv(srprec).x)
|
|
2110
|
+
self.prime_pow.restore_context_capdiv(srprec)
|
|
2111
|
+
# conv_modulus should have restored the context, so we don't need to again.
|
|
2112
|
+
ZZ_pX_add(ans.unit, ans.unit, self.unit)
|
|
2113
|
+
else:
|
|
2114
|
+
ans = self._new_c(-rrprec)
|
|
2115
|
+
ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(rrprec).x)
|
|
2116
|
+
self.prime_pow.restore_context_capdiv(rrprec)
|
|
2117
|
+
# conv_modulus should have restored the context, so we don't need to again.
|
|
2118
|
+
ZZ_pX_add(ans.unit, ans.unit, right.unit)
|
|
2119
|
+
ans.ordp = self.ordp
|
|
2120
|
+
elif self.ordp < right.ordp:
|
|
2121
|
+
tmpL = right.ordp - self.ordp
|
|
2122
|
+
if tmpL >= srprec:
|
|
2123
|
+
return self
|
|
2124
|
+
if srprec <= tmpL + rrprec:
|
|
2125
|
+
ans = self._new_c(-srprec)
|
|
2126
|
+
else:
|
|
2127
|
+
ans = self._new_c(-tmpL - rrprec)
|
|
2128
|
+
ans.ordp = self.ordp
|
|
2129
|
+
ZZ_pX_conv_modulus(ans.unit, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2130
|
+
ans._internal_lshift(tmpL)
|
|
2131
|
+
if srprec <= tmpL + rrprec:
|
|
2132
|
+
ZZ_pX_add(ans.unit, ans.unit, self.unit)
|
|
2133
|
+
else:
|
|
2134
|
+
ZZ_pX_conv_modulus(tmpP, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2135
|
+
ZZ_pX_add(ans.unit, ans.unit, tmpP)
|
|
2136
|
+
# if self is normalized, then the valuations are actually different so the sum will be normalized.
|
|
2137
|
+
if self.relprec > 0:
|
|
2138
|
+
ans.relprec = -ans.relprec
|
|
2139
|
+
else:
|
|
2140
|
+
tmpL = self.ordp - right.ordp
|
|
2141
|
+
if tmpL >= rrprec:
|
|
2142
|
+
return right
|
|
2143
|
+
if rrprec <= tmpL + srprec:
|
|
2144
|
+
ans = self._new_c(-rrprec)
|
|
2145
|
+
else:
|
|
2146
|
+
ans = self._new_c(-tmpL - srprec)
|
|
2147
|
+
ans.ordp = right.ordp
|
|
2148
|
+
ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2149
|
+
ans._internal_lshift(tmpL)
|
|
2150
|
+
if rrprec <= tmpL + srprec:
|
|
2151
|
+
ZZ_pX_add(ans.unit, ans.unit, right.unit)
|
|
2152
|
+
else:
|
|
2153
|
+
ZZ_pX_conv_modulus(tmpP, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2154
|
+
ZZ_pX_add(ans.unit, ans.unit, tmpP)
|
|
2155
|
+
# if right is normalized, then the valuations are actually different so the sum will be normalized.
|
|
2156
|
+
if right.relprec > 0:
|
|
2157
|
+
ans.relprec = -ans.relprec
|
|
2158
|
+
return ans
|
|
2159
|
+
|
|
2160
|
+
cpdef _sub_(self, right):
|
|
2161
|
+
"""
|
|
2162
|
+
Return the difference of two elements.
|
|
2163
|
+
|
|
2164
|
+
EXAMPLES::
|
|
2165
|
+
|
|
2166
|
+
sage: R = Zp(5,5)
|
|
2167
|
+
sage: S.<x> = R[]
|
|
2168
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2169
|
+
sage: W.<w> = R.ext(f)
|
|
2170
|
+
sage: a = W(329)
|
|
2171
|
+
sage: b = W(111)
|
|
2172
|
+
sage: a - b # indirect doctest
|
|
2173
|
+
3 + 3*w^5 + w^7 + 2*w^9 + 3*w^10 + 4*w^11 + 2*w^13 + 2*w^14 + w^15 + 4*w^16 + 2*w^18 + 3*w^19 + 2*w^20 + 3*w^21 + w^22 + w^24 + O(w^25)
|
|
2174
|
+
sage: W(218)
|
|
2175
|
+
3 + 3*w^5 + w^7 + 2*w^9 + 3*w^10 + 4*w^11 + 2*w^13 + 2*w^14 + w^15 + 4*w^16 + 2*w^18 + 3*w^19 + 2*w^20 + 3*w^21 + w^22 + w^24 + O(w^25)
|
|
2176
|
+
sage: a - O(w^14)
|
|
2177
|
+
4 + 3*w^10 + 2*w^12 + O(w^14)
|
|
2178
|
+
sage: a - 0
|
|
2179
|
+
4 + 3*w^10 + 2*w^12 + w^14 + 2*w^15 + w^16 + 3*w^17 + 3*w^18 + w^19 + 2*w^21 + 4*w^22 + w^23 + 4*w^24 + O(w^25)
|
|
2180
|
+
sage: O(w^14) - a
|
|
2181
|
+
1 + 4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + O(w^14)
|
|
2182
|
+
"""
|
|
2183
|
+
# For now, a simple implementation
|
|
2184
|
+
return self + (-right)
|
|
2185
|
+
|
|
2186
|
+
cpdef _mul_(self, _right):
|
|
2187
|
+
"""
|
|
2188
|
+
Return the product of two elements.
|
|
2189
|
+
|
|
2190
|
+
EXAMPLES::
|
|
2191
|
+
|
|
2192
|
+
sage: R = Zp(5,5)
|
|
2193
|
+
sage: S.<x> = R[]
|
|
2194
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2195
|
+
sage: W.<w> = R.ext(f)
|
|
2196
|
+
sage: a = W(329)
|
|
2197
|
+
sage: b = W(111)
|
|
2198
|
+
sage: a*b # indirect doctest
|
|
2199
|
+
4 + 3*w^5 + w^7 + 2*w^9 + 4*w^11 + 3*w^12 + 2*w^13 + w^14 + 2*w^15 + 3*w^16 + 4*w^17 + 4*w^18 + 2*w^19 + 2*w^21 + 4*w^22 + 2*w^23 + w^24 + O(w^25)
|
|
2200
|
+
sage: a * 0
|
|
2201
|
+
0
|
|
2202
|
+
sage: a * O(w^14)
|
|
2203
|
+
O(w^14)
|
|
2204
|
+
"""
|
|
2205
|
+
cdef pAdicZZpXCRElement right = <pAdicZZpXCRElement>_right
|
|
2206
|
+
cdef ZZ_pX_c modulus_corrected
|
|
2207
|
+
cdef pAdicZZpXCRElement ans
|
|
2208
|
+
if self._is_exact_zero():
|
|
2209
|
+
return self
|
|
2210
|
+
if right._is_exact_zero():
|
|
2211
|
+
return right
|
|
2212
|
+
self._normalize()
|
|
2213
|
+
right._normalize()
|
|
2214
|
+
if self.relprec <= right.relprec:
|
|
2215
|
+
ans = self._new_c(self.relprec)
|
|
2216
|
+
else:
|
|
2217
|
+
ans = self._new_c(right.relprec)
|
|
2218
|
+
ans.ordp = self.ordp + right.ordp
|
|
2219
|
+
check_ordp(ans.ordp)
|
|
2220
|
+
if ans.relprec == 0:
|
|
2221
|
+
return ans
|
|
2222
|
+
if self.relprec == right.relprec:
|
|
2223
|
+
self.prime_pow.restore_context_capdiv(ans.relprec)
|
|
2224
|
+
sig_on()
|
|
2225
|
+
ZZ_pX_MulMod_pre(ans.unit, self.unit, right.unit, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
|
|
2226
|
+
sig_off()
|
|
2227
|
+
elif self.relprec < right.relprec:
|
|
2228
|
+
sig_on()
|
|
2229
|
+
ZZ_pX_conv_modulus(modulus_corrected, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2230
|
+
ZZ_pX_MulMod_pre(ans.unit, self.unit, modulus_corrected, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
|
|
2231
|
+
sig_off()
|
|
2232
|
+
else:
|
|
2233
|
+
sig_on()
|
|
2234
|
+
ZZ_pX_conv_modulus(modulus_corrected, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
|
|
2235
|
+
ZZ_pX_MulMod_pre(ans.unit, right.unit, modulus_corrected, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
|
|
2236
|
+
sig_off()
|
|
2237
|
+
return ans
|
|
2238
|
+
|
|
2239
|
+
cpdef _div_(self, right):
|
|
2240
|
+
"""
|
|
2241
|
+
Return the quotient of two elements.
|
|
2242
|
+
|
|
2243
|
+
EXAMPLES::
|
|
2244
|
+
|
|
2245
|
+
sage: R = Zp(5,5)
|
|
2246
|
+
sage: S.<x> = R[]
|
|
2247
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2248
|
+
sage: W.<w> = R.ext(f)
|
|
2249
|
+
sage: W(14) / W(125) # indirect doctest
|
|
2250
|
+
4*w^-15 + w^-13 + 3*w^-11 + 2*w^-10 + 3*w^-9 + 4*w^-8 + 4*w^-7 + 3*w^-6 + 2*w^-5 + 4*w^-4 + 3*w^-3 + 2*w^-2 + 4*w^-1 + 2 + w^2 + w^4 + 4*w^5 + w^6 + w^7 + 3*w^9 + O(w^10)
|
|
2251
|
+
sage: 1 / w
|
|
2252
|
+
w^-1 + O(w^24)
|
|
2253
|
+
sage: W.<w> = R.ext(x^25 - 165*x + 5)
|
|
2254
|
+
sage: a = (1 + w)^25 - 1
|
|
2255
|
+
sage: b = (1 + w)^5 - 1
|
|
2256
|
+
sage: c = (1 + w)^20 + (1 + w)^15 + (1 + w)^10 + (1 + w)^5 + 1
|
|
2257
|
+
sage: d = a / b; d == c
|
|
2258
|
+
True
|
|
2259
|
+
sage: d.precision_absolute()
|
|
2260
|
+
120
|
|
2261
|
+
sage: c.precision_absolute()
|
|
2262
|
+
125
|
|
2263
|
+
sage: 1 / a == ~a
|
|
2264
|
+
True
|
|
2265
|
+
"""
|
|
2266
|
+
# for now, a simple implementation
|
|
2267
|
+
return self * (~right)
|
|
2268
|
+
|
|
2269
|
+
def __copy__(self):
|
|
2270
|
+
"""
|
|
2271
|
+
Return a copy of this element.
|
|
2272
|
+
|
|
2273
|
+
EXAMPLES::
|
|
2274
|
+
|
|
2275
|
+
sage: R = Zp(5,5)
|
|
2276
|
+
sage: S.<x> = R[]
|
|
2277
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2278
|
+
sage: W.<w> = R.ext(f)
|
|
2279
|
+
sage: b = W(45, 17); b
|
|
2280
|
+
4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + 3*w^14 + w^16 + O(w^17)
|
|
2281
|
+
sage: c = copy(b); c
|
|
2282
|
+
4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + 3*w^14 + w^16 + O(w^17)
|
|
2283
|
+
sage: c is b
|
|
2284
|
+
False
|
|
2285
|
+
"""
|
|
2286
|
+
cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
|
|
2287
|
+
ans.ordp = self.ordp
|
|
2288
|
+
ans.unit = self.unit
|
|
2289
|
+
return ans
|
|
2290
|
+
|
|
2291
|
+
def _integer_(self, Z=None):
|
|
2292
|
+
r"""
|
|
2293
|
+
Return an integer congruent to this element modulo
|
|
2294
|
+
`\pi^{\mathrm{self.absolute_precision()}`, if possible.
|
|
2295
|
+
|
|
2296
|
+
EXAMPLES::
|
|
2297
|
+
|
|
2298
|
+
sage: ZZ(ZqCR(125,names='a')(-1)) # indirect doctest
|
|
2299
|
+
95367431640624
|
|
2300
|
+
sage: R = Zp(5); S.<x> = ZZ[]; f = x^5 + 25*x^3 - 5; W.<w> = R.ext(f)
|
|
2301
|
+
sage: ZZ(W(-1))
|
|
2302
|
+
95367431640624
|
|
2303
|
+
sage: ZZ(W(0))
|
|
2304
|
+
0
|
|
2305
|
+
sage: ZZ(W(0,7))
|
|
2306
|
+
0
|
|
2307
|
+
sage: ZZ(w)
|
|
2308
|
+
Traceback (most recent call last):
|
|
2309
|
+
...
|
|
2310
|
+
ValueError: this element not well approximated by an integer
|
|
2311
|
+
sage: ZZ(W(5)) # todo: this should be different...
|
|
2312
|
+
381469726562505
|
|
2313
|
+
"""
|
|
2314
|
+
cdef Integer ans
|
|
2315
|
+
cdef ZZ_c tmp_z
|
|
2316
|
+
if self._is_exact_zero() or self.relprec == 0:
|
|
2317
|
+
ans = PY_NEW(Integer)
|
|
2318
|
+
return ans
|
|
2319
|
+
if self.ordp < 0:
|
|
2320
|
+
self._normalize()
|
|
2321
|
+
if self.ordp < 0:
|
|
2322
|
+
raise ValueError("this element has negative valuation")
|
|
2323
|
+
cdef ntl_ZZ_pX f = <ntl_ZZ_pX>self._ntl_rep_abs()[0]
|
|
2324
|
+
if f.degree() > 0:
|
|
2325
|
+
raise ValueError("this element not well approximated by an integer")
|
|
2326
|
+
ans = PY_NEW(Integer)
|
|
2327
|
+
tmp_z = ZZ_p_rep(ZZ_pX_ConstTerm(f.x))
|
|
2328
|
+
ZZ_to_mpz(ans.value, &tmp_z)
|
|
2329
|
+
return ans
|
|
2330
|
+
|
|
2331
|
+
def is_zero(self, absprec=None):
|
|
2332
|
+
r"""
|
|
2333
|
+
Return whether the valuation of this element is at least
|
|
2334
|
+
``absprec``. If ``absprec`` is ``None``, checks if this element
|
|
2335
|
+
is indistinguishable from zero.
|
|
2336
|
+
|
|
2337
|
+
If this element is an inexact zero of valuation less than ``absprec``,
|
|
2338
|
+
raises a :exc:`PrecisionError`.
|
|
2339
|
+
|
|
2340
|
+
EXAMPLES::
|
|
2341
|
+
|
|
2342
|
+
sage: R = Zp(5,5)
|
|
2343
|
+
sage: S.<x> = R[]
|
|
2344
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2345
|
+
sage: W.<w> = R.ext(f)
|
|
2346
|
+
sage: O(w^189).is_zero()
|
|
2347
|
+
True
|
|
2348
|
+
sage: W(0).is_zero()
|
|
2349
|
+
True
|
|
2350
|
+
sage: a = W(675)
|
|
2351
|
+
sage: a.is_zero()
|
|
2352
|
+
False
|
|
2353
|
+
sage: a.is_zero(7)
|
|
2354
|
+
True
|
|
2355
|
+
sage: a.is_zero(21)
|
|
2356
|
+
False
|
|
2357
|
+
"""
|
|
2358
|
+
cdef bint ans
|
|
2359
|
+
cdef long aprec
|
|
2360
|
+
self._normalize()
|
|
2361
|
+
if self._is_exact_zero():
|
|
2362
|
+
ans = True
|
|
2363
|
+
elif absprec is None:
|
|
2364
|
+
ans = (self.relprec == 0)
|
|
2365
|
+
else:
|
|
2366
|
+
if not isinstance(absprec, Integer):
|
|
2367
|
+
absprec = Integer(absprec)
|
|
2368
|
+
if mpz_fits_slong_p((<Integer>absprec).value) == 0:
|
|
2369
|
+
if mpz_sgn((<Integer>absprec).value) < 0:
|
|
2370
|
+
ans = True
|
|
2371
|
+
elif self.relprec == 0:
|
|
2372
|
+
raise PrecisionError("not enough precision to determine if element is zero")
|
|
2373
|
+
else:
|
|
2374
|
+
ans = False
|
|
2375
|
+
else:
|
|
2376
|
+
aprec = mpz_get_si((<Integer>absprec).value)
|
|
2377
|
+
if self.relprec == 0 and aprec > self.ordp:
|
|
2378
|
+
raise PrecisionError("not enough precision to determine if element is zero")
|
|
2379
|
+
else:
|
|
2380
|
+
ans = (self.ordp >= aprec)
|
|
2381
|
+
return ans
|
|
2382
|
+
|
|
2383
|
+
cpdef ntl_ZZ_pX _ntl_rep_unnormalized(self):
|
|
2384
|
+
"""
|
|
2385
|
+
Return an ``ntl_ZZ_pX`` holding the current unit part of this element.
|
|
2386
|
+
|
|
2387
|
+
The element is not normalized before this operation, so the polynomial
|
|
2388
|
+
returned may not actually be a unit.
|
|
2389
|
+
|
|
2390
|
+
EXAMPLES::
|
|
2391
|
+
|
|
2392
|
+
sage: R = Zp(5,5)
|
|
2393
|
+
sage: S.<x> = R[]
|
|
2394
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2395
|
+
sage: W.<w> = R.ext(f)
|
|
2396
|
+
sage: a = W(566); b = W(209)
|
|
2397
|
+
sage: c = a + b; c._ntl_rep_unnormalized()
|
|
2398
|
+
[775]
|
|
2399
|
+
sage: c
|
|
2400
|
+
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 + O(w^25)
|
|
2401
|
+
sage: c._ntl_rep_unnormalized()
|
|
2402
|
+
[106 60 114 35 112]
|
|
2403
|
+
"""
|
|
2404
|
+
if self.relprec == 0:
|
|
2405
|
+
raise ValueError("self == 0")
|
|
2406
|
+
self.prime_pow.restore_context_capdiv(self.relprec)
|
|
2407
|
+
cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
|
|
2408
|
+
ans.c = self.prime_pow.get_context_capdiv(self.relprec)
|
|
2409
|
+
ans.x = self.unit
|
|
2410
|
+
return ans
|
|
2411
|
+
|
|
2412
|
+
cpdef ntl_ZZ_pX _ntl_rep(self):
|
|
2413
|
+
"""
|
|
2414
|
+
Return an ``ntl_ZZ_pX`` that holds the unit part of this element.
|
|
2415
|
+
|
|
2416
|
+
EXAMPLES::
|
|
2417
|
+
|
|
2418
|
+
sage: R = Zp(5,5)
|
|
2419
|
+
sage: S.<x> = R[]
|
|
2420
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2421
|
+
sage: W.<w> = R.ext(f)
|
|
2422
|
+
sage: a = W(566); b = W(209)
|
|
2423
|
+
sage: c = a + b; c._ntl_rep()
|
|
2424
|
+
[106 60 114 35 112]
|
|
2425
|
+
sage: c
|
|
2426
|
+
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 + O(w^25)
|
|
2427
|
+
sage: c._ntl_rep()
|
|
2428
|
+
[106 60 114 35 112]
|
|
2429
|
+
"""
|
|
2430
|
+
self._normalize()
|
|
2431
|
+
return self._ntl_rep_unnormalized()
|
|
2432
|
+
|
|
2433
|
+
cpdef _ntl_rep_abs(self):
|
|
2434
|
+
"""
|
|
2435
|
+
Return a pair ``(f, k)`` where ``f`` is an ``ntl_ZZ_pX`` and ``k`` is a
|
|
2436
|
+
nonpositive integer such that ``self = f(self.parent.gen())*p^k``.
|
|
2437
|
+
|
|
2438
|
+
EXAMPLES::
|
|
2439
|
+
|
|
2440
|
+
sage: R = Zp(5,5)
|
|
2441
|
+
sage: S.<x> = R[]
|
|
2442
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2443
|
+
sage: W.<w> = R.ext(f)
|
|
2444
|
+
sage: a = W(566); b = W(209)
|
|
2445
|
+
sage: c = a + b; c._ntl_rep_abs()
|
|
2446
|
+
([775], 0)
|
|
2447
|
+
sage: c
|
|
2448
|
+
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 + O(w^25)
|
|
2449
|
+
sage: c._ntl_rep_abs()
|
|
2450
|
+
([775], 0)
|
|
2451
|
+
sage: (~c)._ntl_rep_abs()
|
|
2452
|
+
([121], -2)
|
|
2453
|
+
sage: ~c
|
|
2454
|
+
w^-10 + w^-8 + 4*w^-6 + 4*w^-5 + 3*w^-3 + 4*w^-2 + 3*w^-1 + 4 + 4*w + 2*w^2 + 4*w^3 + 3*w^4 + O(w^5)
|
|
2455
|
+
sage: ~c * 25
|
|
2456
|
+
1 + 4*w^5 + 3*w^7 + w^9 + 4*w^10 + 2*w^11 + 3*w^12 + w^13 + 4*w^14 + O(w^15)
|
|
2457
|
+
sage: W(121)
|
|
2458
|
+
1 + 4*w^5 + 3*w^7 + w^9 + 4*w^10 + 2*w^11 + 3*w^12 + w^13 + 4*w^14 + 2*w^16 + 3*w^17 + 3*w^18 + 4*w^19 + 4*w^20 + 3*w^21 + w^22 + w^23 + 4*w^24 + O(w^25)
|
|
2459
|
+
"""
|
|
2460
|
+
self._normalize()
|
|
2461
|
+
if self.ordp == 0:
|
|
2462
|
+
return self._ntl_rep(), Integer(0)
|
|
2463
|
+
cdef ntl_ZZ_pContext_class ctx
|
|
2464
|
+
cdef long little_shift, ppow
|
|
2465
|
+
if self.ordp > 0:
|
|
2466
|
+
ctx = self.prime_pow.get_context_capdiv(self.ordp + self.relprec)
|
|
2467
|
+
else:
|
|
2468
|
+
little_shift = ((-self.ordp) % self.prime_pow.e)
|
|
2469
|
+
if little_shift != 0:
|
|
2470
|
+
little_shift = self.prime_pow.e - little_shift
|
|
2471
|
+
ctx = self.prime_pow.get_context_capdiv(self.relprec + little_shift)
|
|
2472
|
+
ctx.restore_c()
|
|
2473
|
+
cdef pAdicZZpXCRElement dummy = pAdicZZpXCRElement.__new__(pAdicZZpXCRElement)
|
|
2474
|
+
cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
|
|
2475
|
+
cdef Integer ans_k = PY_NEW(Integer)
|
|
2476
|
+
dummy.unit = self.unit
|
|
2477
|
+
dummy.prime_pow = self.prime_pow
|
|
2478
|
+
if self.ordp > 0:
|
|
2479
|
+
dummy.relprec = self.ordp + self.relprec
|
|
2480
|
+
dummy._internal_lshift(self.ordp)
|
|
2481
|
+
ans.x = dummy.unit
|
|
2482
|
+
else:
|
|
2483
|
+
ppow = (self.ordp - little_shift) / self.prime_pow.e
|
|
2484
|
+
mpz_set_si(ans_k.value, ppow)
|
|
2485
|
+
dummy.ordp = 0 # _pshift_self wants ordp set
|
|
2486
|
+
dummy.relprec = self.relprec + little_shift
|
|
2487
|
+
# self = x^(self.prime_pow.e * ppow) * x^(little_shift) * self.unit
|
|
2488
|
+
# so we want to _internal_lshift dummy.unit by little_shift
|
|
2489
|
+
dummy._internal_lshift(little_shift)
|
|
2490
|
+
# and then write
|
|
2491
|
+
# self = p^(ppow) * (x^e/p)^(ppow) * dummy.unit
|
|
2492
|
+
# so we need to multiply dummy.unit by (p/x^e)^(-ppow) in the Eisenstein case
|
|
2493
|
+
# which we can do by _pshift_self
|
|
2494
|
+
dummy._pshift_self(-ppow)
|
|
2495
|
+
ans.x = dummy.unit
|
|
2496
|
+
ans.c = ctx
|
|
2497
|
+
return ans, ans_k
|
|
2498
|
+
|
|
2499
|
+
def _polynomial_list(self, pad=False):
|
|
2500
|
+
"""
|
|
2501
|
+
Return the coefficient list for a polynomial over the base ring
|
|
2502
|
+
yielding this element.
|
|
2503
|
+
|
|
2504
|
+
INPUT:
|
|
2505
|
+
|
|
2506
|
+
- ``pad`` -- whether to pad the result with zeros of the appropriate precision
|
|
2507
|
+
|
|
2508
|
+
EXAMPLES::
|
|
2509
|
+
|
|
2510
|
+
sage: R.<x> = ZZ[]
|
|
2511
|
+
sage: W.<w> = Qp(5).extension(x^3 - 5)
|
|
2512
|
+
sage: (1 + w + O(w^11))._polynomial_list()
|
|
2513
|
+
[1 + O(5^4), 1 + O(5^4)]
|
|
2514
|
+
sage: (1 + w + O(w^11))._polynomial_list(pad=True)
|
|
2515
|
+
[1 + O(5^4), 1 + O(5^4), O(5^3)]
|
|
2516
|
+
sage: W(0)._polynomial_list()
|
|
2517
|
+
[]
|
|
2518
|
+
sage: W(0)._polynomial_list(pad=True)
|
|
2519
|
+
[0, 0, 0]
|
|
2520
|
+
sage: W(O(w^7))._polynomial_list()
|
|
2521
|
+
[]
|
|
2522
|
+
sage: W(O(w^7))._polynomial_list(pad=True)
|
|
2523
|
+
[O(5^3), O(5^2), O(5^2)]
|
|
2524
|
+
sage: T.<a> = Qp(5).extension(x^2 - 5)
|
|
2525
|
+
sage: T(1/5)._polynomial_list()
|
|
2526
|
+
[5^-1 + O(5^19)]
|
|
2527
|
+
sage: T(a^-800)._polynomial_list()
|
|
2528
|
+
[5^-400 + O(5^-380)]
|
|
2529
|
+
sage: T(O(a^-2))._polynomial_list()
|
|
2530
|
+
[]
|
|
2531
|
+
"""
|
|
2532
|
+
R = self.base_ring()
|
|
2533
|
+
if self.is_zero():
|
|
2534
|
+
L = []
|
|
2535
|
+
k = 0
|
|
2536
|
+
else:
|
|
2537
|
+
f, k = self._ntl_rep_abs()
|
|
2538
|
+
L = [Integer(c) for c in f.list()]
|
|
2539
|
+
if pad:
|
|
2540
|
+
n = self.parent().degree()
|
|
2541
|
+
L.extend([R.zero()] * (n - len(L)))
|
|
2542
|
+
if self._is_exact_zero():
|
|
2543
|
+
return L
|
|
2544
|
+
prec = self.relprec + self.ordp
|
|
2545
|
+
e = self.parent().e()
|
|
2546
|
+
if e == 1:
|
|
2547
|
+
return [R(c, prec-k) << k for c in L]
|
|
2548
|
+
else:
|
|
2549
|
+
return [R(c, (((prec - i - 1) // e) + 1) - k) << k for i, c in enumerate(L)]
|
|
2550
|
+
|
|
2551
|
+
def polynomial(self, var='x'):
|
|
2552
|
+
"""
|
|
2553
|
+
Return a polynomial over the base ring that yields this element
|
|
2554
|
+
when evaluated at the generator of the parent.
|
|
2555
|
+
|
|
2556
|
+
INPUT:
|
|
2557
|
+
|
|
2558
|
+
- ``var`` -- string, the variable name for the polynomial
|
|
2559
|
+
|
|
2560
|
+
EXAMPLES::
|
|
2561
|
+
|
|
2562
|
+
sage: S.<x> = ZZ[]
|
|
2563
|
+
sage: W.<w> = Zp(5).extension(x^2 - 5)
|
|
2564
|
+
sage: (w + W(5, 7)).polynomial()
|
|
2565
|
+
(1 + O(5^3))*x + 5 + O(5^4)
|
|
2566
|
+
"""
|
|
2567
|
+
R = self.base_ring()
|
|
2568
|
+
S = R[var]
|
|
2569
|
+
return S(self._polynomial_list())
|
|
2570
|
+
|
|
2571
|
+
cdef ZZ_p_c _const_term(self) noexcept:
|
|
2572
|
+
"""
|
|
2573
|
+
Return the constant term of ``self.unit``.
|
|
2574
|
+
|
|
2575
|
+
Note: this may be divisible by `p` if ``self`` is not normalized.
|
|
2576
|
+
|
|
2577
|
+
EXAMPLES::
|
|
2578
|
+
|
|
2579
|
+
sage: R = Zp(5,5)
|
|
2580
|
+
sage: S.<x> = R[]
|
|
2581
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2582
|
+
sage: W.<w> = R.ext(f)
|
|
2583
|
+
sage: a = W(566)
|
|
2584
|
+
sage: a._const_term_test() # indirect doctest
|
|
2585
|
+
566
|
|
2586
|
+
"""
|
|
2587
|
+
return ZZ_pX_ConstTerm((<pAdicZZpXCRElement>self).unit)
|
|
2588
|
+
|
|
2589
|
+
def is_equal_to(self, right, absprec=None):
|
|
2590
|
+
"""
|
|
2591
|
+
Return whether this element is equal to ``right`` modulo ``self.uniformizer()^absprec``.
|
|
2592
|
+
|
|
2593
|
+
If ``absprec`` is ``None``, checks whether this element is equal to ``right``
|
|
2594
|
+
modulo the lower of their two precisions.
|
|
2595
|
+
|
|
2596
|
+
EXAMPLES::
|
|
2597
|
+
|
|
2598
|
+
sage: R = Zp(5,5)
|
|
2599
|
+
sage: S.<x> = R[]
|
|
2600
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2601
|
+
sage: W.<w> = R.ext(f)
|
|
2602
|
+
sage: a = W(47); b = W(47 + 25)
|
|
2603
|
+
sage: a.is_equal_to(b)
|
|
2604
|
+
False
|
|
2605
|
+
sage: a.is_equal_to(b, 7)
|
|
2606
|
+
True
|
|
2607
|
+
"""
|
|
2608
|
+
# Should be sped up later
|
|
2609
|
+
return (self - right).is_zero(absprec)
|
|
2610
|
+
|
|
2611
|
+
# def lift(self):
|
|
2612
|
+
# """
|
|
2613
|
+
# Return an element of a number field defined by the same polynomial as
|
|
2614
|
+
# ``self``'s parent that is congruent to self modulo an appropriate ideal.
|
|
2615
|
+
|
|
2616
|
+
# Not currently implemented.
|
|
2617
|
+
# """
|
|
2618
|
+
# raise NotImplementedError
|
|
2619
|
+
|
|
2620
|
+
cpdef pAdicZZpXCRElement lift_to_precision(self, absprec=None):
|
|
2621
|
+
"""
|
|
2622
|
+
Return a ``pAdicZZpXCRElement`` congruent to this element but with
|
|
2623
|
+
absolute precision at least ``absprec``.
|
|
2624
|
+
|
|
2625
|
+
INPUT:
|
|
2626
|
+
|
|
2627
|
+
- ``absprec`` -- (default: ``None``) the absolute precision of
|
|
2628
|
+
the result. If ``None``, lifts to the maximum precision
|
|
2629
|
+
allowed.
|
|
2630
|
+
|
|
2631
|
+
.. NOTE::
|
|
2632
|
+
|
|
2633
|
+
If setting ``absprec`` that high would violate the
|
|
2634
|
+
precision cap, raises a precision error. If ``self`` is an
|
|
2635
|
+
inexact zero and ``absprec`` is greater than the maximum
|
|
2636
|
+
allowed valuation, raises an error.
|
|
2637
|
+
|
|
2638
|
+
Note that the new digits will not necessarily be zero.
|
|
2639
|
+
|
|
2640
|
+
EXAMPLES::
|
|
2641
|
+
|
|
2642
|
+
sage: R = Zp(5,5)
|
|
2643
|
+
sage: S.<x> = R[]
|
|
2644
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2645
|
+
sage: W.<w> = R.ext(f)
|
|
2646
|
+
sage: a = W(345, 17); a
|
|
2647
|
+
4*w^5 + 3*w^7 + w^9 + 3*w^10 + 2*w^11 + 4*w^12 + w^13 + 2*w^14 + 2*w^15 + O(w^17)
|
|
2648
|
+
sage: b = a.lift_to_precision(19); b
|
|
2649
|
+
4*w^5 + 3*w^7 + w^9 + 3*w^10 + 2*w^11 + 4*w^12 + w^13 + 2*w^14 + 2*w^15
|
|
2650
|
+
+ w^17 + 2*w^18 + O(w^19)
|
|
2651
|
+
sage: c = a.lift_to_precision(24); c
|
|
2652
|
+
4*w^5 + 3*w^7 + w^9 + 3*w^10 + 2*w^11 + 4*w^12 + w^13 + 2*w^14 + 2*w^15
|
|
2653
|
+
+ w^17 + 2*w^18 + 4*w^19 + 4*w^20 + 2*w^21 + 4*w^23 + O(w^24)
|
|
2654
|
+
sage: a._ntl_rep()
|
|
2655
|
+
[19 35 118 60 121]
|
|
2656
|
+
sage: b._ntl_rep()
|
|
2657
|
+
[19 35 118 60 121]
|
|
2658
|
+
sage: c._ntl_rep()
|
|
2659
|
+
[19 35 118 60 121]
|
|
2660
|
+
sage: a.lift_to_precision().precision_relative() == W.precision_cap()
|
|
2661
|
+
True
|
|
2662
|
+
"""
|
|
2663
|
+
cdef pAdicZZpXCRElement ans
|
|
2664
|
+
cdef long aprec, rprec
|
|
2665
|
+
self._normalize()
|
|
2666
|
+
if self._is_exact_zero():
|
|
2667
|
+
return self
|
|
2668
|
+
if absprec is not None and not isinstance(absprec, Integer):
|
|
2669
|
+
absprec = Integer(absprec)
|
|
2670
|
+
if absprec is None:
|
|
2671
|
+
if self.relprec == 0:
|
|
2672
|
+
# return an exact zero
|
|
2673
|
+
ans = self._new_c(0)
|
|
2674
|
+
ans._set_exact_zero()
|
|
2675
|
+
return ans
|
|
2676
|
+
aprec = self.prime_pow.ram_prec_cap + self.ordp
|
|
2677
|
+
elif mpz_fits_slong_p((<Integer>absprec).value) == 0:
|
|
2678
|
+
if mpz_sgn((<Integer>absprec).value) < 0 or self.relprec == self.prime_pow.ram_prec_cap:
|
|
2679
|
+
return self
|
|
2680
|
+
else:
|
|
2681
|
+
if self.relprec == 0:
|
|
2682
|
+
raise ValueError("absprec larger than maximum allowable valuation")
|
|
2683
|
+
else:
|
|
2684
|
+
raise PrecisionError("precision higher than allowed by the precision cap")
|
|
2685
|
+
else:
|
|
2686
|
+
aprec = mpz_get_si((<Integer>absprec).value)
|
|
2687
|
+
if aprec <= self.ordp + self.relprec:
|
|
2688
|
+
return self
|
|
2689
|
+
if self.relprec == 0:
|
|
2690
|
+
if self.ordp >= aprec:
|
|
2691
|
+
return self
|
|
2692
|
+
elif aprec >= maxordp:
|
|
2693
|
+
raise ValueError("absprec larger than maximum allowable valuation")
|
|
2694
|
+
else:
|
|
2695
|
+
ans = self._new_c(0)
|
|
2696
|
+
ans._set_inexact_zero(aprec)
|
|
2697
|
+
return ans
|
|
2698
|
+
# Now we're done handling all the special cases.
|
|
2699
|
+
rprec = aprec - self.ordp
|
|
2700
|
+
if rprec > self.prime_pow.ram_prec_cap:
|
|
2701
|
+
raise PrecisionError("precision higher than allowed by the precision cap")
|
|
2702
|
+
ans = self._new_c(rprec)
|
|
2703
|
+
ans.ordp = self.ordp
|
|
2704
|
+
ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(rprec).x)
|
|
2705
|
+
return ans
|
|
2706
|
+
|
|
2707
|
+
def expansion(self, n=None, lift_mode='simple'):
|
|
2708
|
+
"""
|
|
2709
|
+
Return a list giving a series representation of ``self``.
|
|
2710
|
+
|
|
2711
|
+
- If ``lift_mode == 'simple'`` or ``'smallest'``, the returned
|
|
2712
|
+
list will consist of integers (in the Eisenstein case) or a
|
|
2713
|
+
list of lists of integers (in the unramified case). ``self``
|
|
2714
|
+
can be reconstructed as a sum of elements of the list times
|
|
2715
|
+
powers of the uniformiser (in the Eisenstein case), or as a
|
|
2716
|
+
sum of powers of the `p` times polynomials in the generator
|
|
2717
|
+
(in the unramified case).
|
|
2718
|
+
|
|
2719
|
+
+ If ``lift_mode == 'simple'``, all integers will be in the interval
|
|
2720
|
+
`[0,p-1]`.
|
|
2721
|
+
|
|
2722
|
+
+ If ``lift_mode == 'smallest'`` they will be in the
|
|
2723
|
+
interval `[(1-p)/2, p/2]`.
|
|
2724
|
+
|
|
2725
|
+
- If ``lift_mode == 'teichmuller'``, returns a list of
|
|
2726
|
+
``pAdicZZpXCRElements``, all of which are Teichmuller
|
|
2727
|
+
representatives and such that ``self`` is the sum of that list
|
|
2728
|
+
times powers of the uniformizer.
|
|
2729
|
+
|
|
2730
|
+
Note that zeros are truncated from the returned list if
|
|
2731
|
+
``self.parent()`` is a field, so you must use the
|
|
2732
|
+
``valuation`` function to fully reconstruct ``self``.
|
|
2733
|
+
|
|
2734
|
+
INPUT:
|
|
2735
|
+
|
|
2736
|
+
- ``n`` -- integer (default: ``None``); if given, returns the
|
|
2737
|
+
corresponding entry in the expansion
|
|
2738
|
+
|
|
2739
|
+
EXAMPLES::
|
|
2740
|
+
|
|
2741
|
+
sage: R = Zp(5,5)
|
|
2742
|
+
sage: S.<x> = R[]
|
|
2743
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2744
|
+
sage: W.<w> = R.ext(f)
|
|
2745
|
+
sage: y = W(775, 19); y
|
|
2746
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
|
|
2747
|
+
sage: (y>>9).expansion()
|
|
2748
|
+
[0, 1, 0, 4, 0, 2, 1, 2, 4, 1]
|
|
2749
|
+
sage: (y>>9).expansion(lift_mode='smallest')
|
|
2750
|
+
[0, 1, 0, -1, 0, 2, 1, 2, 0, 1]
|
|
2751
|
+
sage: w^10 - w^12 + 2*w^14 + w^15 + 2*w^16 + w^18 + O(w^19)
|
|
2752
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
|
|
2753
|
+
sage: g = x^3 + 3*x + 3
|
|
2754
|
+
sage: A.<a> = R.ext(g)
|
|
2755
|
+
sage: y = 75 + 45*a + 1200*a^2; y
|
|
2756
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
|
|
2757
|
+
sage: E = y.expansion(); E
|
|
2758
|
+
5-adic expansion of 4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
|
|
2759
|
+
sage: list(E)
|
|
2760
|
+
[[], [0, 4], [3, 1, 3], [0, 0, 4], [0, 0, 1], []]
|
|
2761
|
+
sage: list(y.expansion(lift_mode='smallest'))
|
|
2762
|
+
[[], [0, -1], [-2, 2, -2], [1], [0, 0, 2], []]
|
|
2763
|
+
sage: 5*((-2*5 + 25) + (-1 + 2*5)*a + (-2*5 + 2*125)*a^2)
|
|
2764
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
|
|
2765
|
+
sage: list(W(0).expansion())
|
|
2766
|
+
[]
|
|
2767
|
+
sage: list(W(0,4).expansion())
|
|
2768
|
+
[]
|
|
2769
|
+
sage: list(A(0,4).expansion())
|
|
2770
|
+
[]
|
|
2771
|
+
|
|
2772
|
+
TESTS:
|
|
2773
|
+
|
|
2774
|
+
We check that :issue:`24949` is fixed::
|
|
2775
|
+
|
|
2776
|
+
sage: R = Zp(2)
|
|
2777
|
+
sage: S.<x> = R[]
|
|
2778
|
+
sage: A.<a> = R.extension(x^10 + 2)
|
|
2779
|
+
sage: u = a^4 + a^5
|
|
2780
|
+
sage: v = a^2 + a^3
|
|
2781
|
+
sage: w = u - v^2
|
|
2782
|
+
sage: w.expansion(4)
|
|
2783
|
+
0
|
|
2784
|
+
"""
|
|
2785
|
+
self._normalize()
|
|
2786
|
+
if lift_mode == 'teichmuller':
|
|
2787
|
+
zero = self.parent()(0)
|
|
2788
|
+
elif self.prime_pow.e == 1:
|
|
2789
|
+
zero = []
|
|
2790
|
+
else:
|
|
2791
|
+
zero = Integer(0)
|
|
2792
|
+
if isinstance(n, slice):
|
|
2793
|
+
return self.slice(n.start, n.stop, n.step)
|
|
2794
|
+
elif n is not None:
|
|
2795
|
+
if self._is_exact_zero() or n < self.ordp:
|
|
2796
|
+
return zero
|
|
2797
|
+
elif n >= self.ordp + self.relprec:
|
|
2798
|
+
raise PrecisionError
|
|
2799
|
+
if self.relprec == 0: # cannot have n = None
|
|
2800
|
+
return []
|
|
2801
|
+
if lift_mode == 'simple':
|
|
2802
|
+
ulist = self.ext_p_list(pos=True)
|
|
2803
|
+
elif lift_mode == 'smallest':
|
|
2804
|
+
ulist = self.ext_p_list(pos=False)
|
|
2805
|
+
elif lift_mode == 'teichmuller':
|
|
2806
|
+
if n is None:
|
|
2807
|
+
ulist = self.teichmuller_expansion()
|
|
2808
|
+
else:
|
|
2809
|
+
return self.teichmuller_expansion(n)
|
|
2810
|
+
else:
|
|
2811
|
+
raise ValueError("lift mode must be one of 'simple', 'smallest' or 'teichmuller'")
|
|
2812
|
+
if n is not None:
|
|
2813
|
+
try:
|
|
2814
|
+
return ulist[n - self.ordp]
|
|
2815
|
+
except IndexError:
|
|
2816
|
+
return zero
|
|
2817
|
+
if self.prime_pow.in_field == 0 and self.ordp > 0:
|
|
2818
|
+
ulist = [zero] * self.ordp + ulist
|
|
2819
|
+
return ulist
|
|
2820
|
+
|
|
2821
|
+
def matrix_mod_pn(self):
|
|
2822
|
+
r"""
|
|
2823
|
+
Return the matrix of right multiplication by the element on
|
|
2824
|
+
the power basis `1, x, x^2, \ldots, x^{d-1}` for this
|
|
2825
|
+
extension field. Thus the *rows* of this matrix give the
|
|
2826
|
+
images of each of the `x^i`. The entries of the matrices are
|
|
2827
|
+
:class:`IntegerMod` elements, defined modulo `p^{N / e}` where `N` is
|
|
2828
|
+
the absolute precision of this element (unless this element is
|
|
2829
|
+
zero to arbitrary precision; in that case the entries are
|
|
2830
|
+
integer zeros.)
|
|
2831
|
+
|
|
2832
|
+
Raises an error if this element has negative valuation.
|
|
2833
|
+
|
|
2834
|
+
EXAMPLES::
|
|
2835
|
+
|
|
2836
|
+
sage: R = ZpCR(5,5)
|
|
2837
|
+
sage: S.<x> = R[]
|
|
2838
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
2839
|
+
sage: W.<w> = R.ext(f)
|
|
2840
|
+
sage: a = (3+w)^7
|
|
2841
|
+
sage: a.matrix_mod_pn()
|
|
2842
|
+
[2757 333 1068 725 2510]
|
|
2843
|
+
[ 50 1507 483 318 725]
|
|
2844
|
+
[ 500 50 3007 2358 318]
|
|
2845
|
+
[1590 1375 1695 1032 2358]
|
|
2846
|
+
[2415 590 2370 2970 1032]
|
|
2847
|
+
|
|
2848
|
+
TESTS:
|
|
2849
|
+
|
|
2850
|
+
Check that :issue:`13617` has been fixed::
|
|
2851
|
+
|
|
2852
|
+
sage: W.zero().matrix_mod_pn()
|
|
2853
|
+
[0 0 0 0 0]
|
|
2854
|
+
[0 0 0 0 0]
|
|
2855
|
+
[0 0 0 0 0]
|
|
2856
|
+
[0 0 0 0 0]
|
|
2857
|
+
[0 0 0 0 0]
|
|
2858
|
+
"""
|
|
2859
|
+
if self.valuation_c() < 0:
|
|
2860
|
+
raise ValueError("self must be integral")
|
|
2861
|
+
n = self.prime_pow.deg
|
|
2862
|
+
from sage.matrix.constructor import matrix
|
|
2863
|
+
if self._is_exact_zero():
|
|
2864
|
+
from sage.rings.integer_ring import IntegerRing
|
|
2865
|
+
return matrix(IntegerRing(), n, n)
|
|
2866
|
+
R = IntegerModRing(self.prime_pow.pow_Integer(self.prime_pow.capdiv(self.ordp + self.relprec)))
|
|
2867
|
+
L = []
|
|
2868
|
+
cdef ntl_ZZ_pX cur = <ntl_ZZ_pX>self._ntl_rep_abs()[0]
|
|
2869
|
+
cur.c.restore_c()
|
|
2870
|
+
cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_modulus_capdiv(self.ordp + self.relprec)
|
|
2871
|
+
cdef ZZ_pX_c x
|
|
2872
|
+
ZZ_pX_SetX(x)
|
|
2873
|
+
cdef Py_ssize_t i
|
|
2874
|
+
zero = int(0)
|
|
2875
|
+
for i in range(n):
|
|
2876
|
+
curlist = cur.list()
|
|
2877
|
+
L.extend(curlist + [zero] * (n - len(curlist)))
|
|
2878
|
+
ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0])
|
|
2879
|
+
return matrix(R, n, n, L)
|
|
2880
|
+
|
|
2881
|
+
# def matrix(self, base=None):
|
|
2882
|
+
# """
|
|
2883
|
+
# If base is None, return the matrix of right multiplication by
|
|
2884
|
+
# the element on the power basis `1, x, x^2, \ldots, x^{d-1}`
|
|
2885
|
+
# for this extension field. Thus the \emph{rows} of this matrix
|
|
2886
|
+
# give the images of each of the `x^i`.
|
|
2887
|
+
|
|
2888
|
+
# If base is not None, then base must be either a field that
|
|
2889
|
+
# embeds in the parent of self or a morphism to the parent of
|
|
2890
|
+
# self, in which case this function returns the matrix of
|
|
2891
|
+
# multiplication by self on the power basis, where we view the
|
|
2892
|
+
# parent field as a field over base.
|
|
2893
|
+
|
|
2894
|
+
# INPUT:
|
|
2895
|
+
# base -- field or morphism
|
|
2896
|
+
# """
|
|
2897
|
+
# raise NotImplementedError
|
|
2898
|
+
|
|
2899
|
+
# def multiplicative_order(self, prec=None):
|
|
2900
|
+
# """
|
|
2901
|
+
# Return the multiplicative order of ``self``, ie the smallest
|
|
2902
|
+
# positive `n` so that there is an exact `p`-adic element congruent
|
|
2903
|
+
# to ``self`` modulo ``self``'s precision that is an `n`-th root of unity.
|
|
2904
|
+
|
|
2905
|
+
# Note: unlike the case for Qp and Zp, it is possible to have
|
|
2906
|
+
# non-teichmuller elements with finite orders. This can happen
|
|
2907
|
+
# only if (p-1) divides the ramification index (see the
|
|
2908
|
+
# documentation on __pow__).
|
|
2909
|
+
|
|
2910
|
+
# INPUT:
|
|
2911
|
+
|
|
2912
|
+
# - self -- a `p`-adic element
|
|
2913
|
+
# - ``prec`` -- integer
|
|
2914
|
+
|
|
2915
|
+
# OUTPUT: integer; the multiplicative order of ``self``
|
|
2916
|
+
# """
|
|
2917
|
+
# raise NotImplementedError
|
|
2918
|
+
|
|
2919
|
+
def teichmuller_expansion(self, n=None):
|
|
2920
|
+
r"""
|
|
2921
|
+
Return a list [`a_0`, `a_1`,..., `a_n`] such that:
|
|
2922
|
+
|
|
2923
|
+
- `a_i^q = a_i`
|
|
2924
|
+
- ``self.unit_part()`` = `\sum_{i = 0}^n a_i \pi^i`, where `\pi` is a
|
|
2925
|
+
uniformizer of ``self.parent()``
|
|
2926
|
+
- if `a_i \ne 0`, the absolute precision of `a_i` is
|
|
2927
|
+
``self.precision_relative() - i``
|
|
2928
|
+
|
|
2929
|
+
INPUT:
|
|
2930
|
+
|
|
2931
|
+
- ``n`` -- integer (default: ``None``); if given, returns the
|
|
2932
|
+
corresponding entry in the expansion
|
|
2933
|
+
|
|
2934
|
+
EXAMPLES::
|
|
2935
|
+
|
|
2936
|
+
sage: R.<a> = ZqCR(5^4,4)
|
|
2937
|
+
sage: E = a.teichmuller_expansion(); E
|
|
2938
|
+
5-adic expansion of a + O(5^4) (teichmuller)
|
|
2939
|
+
sage: list(E)
|
|
2940
|
+
[a + (2*a^3 + 2*a^2 + 3*a + 4)*5 + (4*a^3 + 3*a^2 + 3*a + 2)*5^2
|
|
2941
|
+
+ (4*a^2 + 2*a + 2)*5^3 + O(5^4),
|
|
2942
|
+
(3*a^3 + 3*a^2 + 2*a + 1) + (a^3 + 4*a^2 + 1)*5 + (a^2 + 4*a + 4)*5^2 + O(5^3),
|
|
2943
|
+
(4*a^3 + 2*a^2 + a + 1) + (2*a^3 + 2*a^2 + 2*a + 4)*5 + O(5^2),
|
|
2944
|
+
(a^3 + a^2 + a + 4) + O(5)]
|
|
2945
|
+
sage: sum([c * 5^i for i, c in enumerate(E)])
|
|
2946
|
+
a + O(5^4)
|
|
2947
|
+
sage: all(c^625 == c for c in E)
|
|
2948
|
+
True
|
|
2949
|
+
|
|
2950
|
+
sage: S.<x> = ZZ[]
|
|
2951
|
+
sage: f = x^3 - 98*x + 7
|
|
2952
|
+
sage: W.<w> = ZpCR(7,3).ext(f)
|
|
2953
|
+
sage: b = (1+w)^5; L = b.teichmuller_expansion(); L
|
|
2954
|
+
[1 + O(w^9), 5 + 5*w^3 + w^6 + 4*w^7 + O(w^8), 3 + 3*w^3 + O(w^7),
|
|
2955
|
+
3 + 3*w^3 + O(w^6), O(w^5), 4 + 5*w^3 + O(w^4), 3 + O(w^3),
|
|
2956
|
+
6 + O(w^2), 6 + O(w)]
|
|
2957
|
+
sage: sum([w^i*L[i] for i in range(9)]) == b
|
|
2958
|
+
True
|
|
2959
|
+
sage: all(L[i]^(7^3) == L[i] for i in range(9))
|
|
2960
|
+
True
|
|
2961
|
+
|
|
2962
|
+
sage: L = W(3).teichmuller_expansion(); L
|
|
2963
|
+
[3 + 3*w^3 + w^7 + O(w^9), O(w^8), O(w^7), 4 + 5*w^3 + O(w^6),
|
|
2964
|
+
O(w^5), O(w^4), 3 + O(w^3), 6 + O(w^2)]
|
|
2965
|
+
sage: sum([w^i*L[i] for i in range(len(L))])
|
|
2966
|
+
3 + O(w^9)
|
|
2967
|
+
"""
|
|
2968
|
+
cdef long rp = self.relprec
|
|
2969
|
+
cdef pAdicZZpXCRElement v
|
|
2970
|
+
if n is None:
|
|
2971
|
+
L = []
|
|
2972
|
+
if rp == 0:
|
|
2973
|
+
return L
|
|
2974
|
+
elif self._is_exact_zero() or n < self.ordp:
|
|
2975
|
+
return self.parent()(0)
|
|
2976
|
+
elif n >= self.ordp + rp:
|
|
2977
|
+
raise PrecisionError
|
|
2978
|
+
else:
|
|
2979
|
+
v = self._new_c(rp)
|
|
2980
|
+
cdef pAdicZZpXCRElement u = self.unit_part()
|
|
2981
|
+
cdef long goal
|
|
2982
|
+
if n is not None: goal = rp - n + self.ordp
|
|
2983
|
+
while u.relprec > 0:
|
|
2984
|
+
v = self._new_c(rp)
|
|
2985
|
+
self.prime_pow.teichmuller_set_c(&v.unit, &u.unit, rp)
|
|
2986
|
+
v.ordp = 0
|
|
2987
|
+
if n is None:
|
|
2988
|
+
L.append(v)
|
|
2989
|
+
elif rp == goal:
|
|
2990
|
+
return v
|
|
2991
|
+
if rp == 1: break
|
|
2992
|
+
ZZ_pX_sub(u.unit, u.unit, v.unit)
|
|
2993
|
+
u.relprec = -u.relprec
|
|
2994
|
+
u._normalize()
|
|
2995
|
+
if u.relprec == 0: break
|
|
2996
|
+
rp -= 1
|
|
2997
|
+
u.ordp -= 1
|
|
2998
|
+
while u.ordp > 0:
|
|
2999
|
+
if n is None:
|
|
3000
|
+
v = self._new_c(0)
|
|
3001
|
+
v._set_inexact_zero(rp)
|
|
3002
|
+
L.append(v)
|
|
3003
|
+
elif rp == goal:
|
|
3004
|
+
v = self._new_c(0)
|
|
3005
|
+
v._set_inexact_zero(rp)
|
|
3006
|
+
return v
|
|
3007
|
+
rp -= 1
|
|
3008
|
+
u.ordp -= 1
|
|
3009
|
+
if n is None:
|
|
3010
|
+
return L
|
|
3011
|
+
else:
|
|
3012
|
+
v = self._new_c(0)
|
|
3013
|
+
v._set_inexact_zero(rp)
|
|
3014
|
+
return v
|
|
3015
|
+
|
|
3016
|
+
def _teichmuller_set_unsafe(self):
|
|
3017
|
+
"""
|
|
3018
|
+
Set this element to the Teichmuller representative with the
|
|
3019
|
+
same residue.
|
|
3020
|
+
|
|
3021
|
+
.. WARNING::
|
|
3022
|
+
|
|
3023
|
+
This function modifies the element, which is not safe.
|
|
3024
|
+
Elements are supposed to be immutable.
|
|
3025
|
+
|
|
3026
|
+
EXAMPLES::
|
|
3027
|
+
|
|
3028
|
+
sage: R = Zp(7,5)
|
|
3029
|
+
sage: S.<x> = R[]
|
|
3030
|
+
sage: f = x^5 + 77*x^3 - 98*x^2 - 7
|
|
3031
|
+
sage: W.<w> = R.ext(f)
|
|
3032
|
+
sage: y = W.teichmuller(3, 15); y # indirect doctest
|
|
3033
|
+
3 + 4*w^5 + 2*w^8 + 6*w^10 + w^11 + 6*w^12 + 5*w^13 + 4*w^14 + O(w^15)
|
|
3034
|
+
|
|
3035
|
+
sage: y^7 == y
|
|
3036
|
+
True
|
|
3037
|
+
sage: g = x^3 + 3*x^2 + 4
|
|
3038
|
+
sage: A.<a> = R.ext(g)
|
|
3039
|
+
sage: b = A.teichmuller(1 + 2*a - a^2); b
|
|
3040
|
+
(6*a^2 + 2*a + 1) + (5*a + 3)*7 + (5*a + 5)*7^2 + (4*a^2 + 4*a + 2)*7^3 + (2*a + 1)*7^4 + O(7^5)
|
|
3041
|
+
sage: b^343 == b
|
|
3042
|
+
True
|
|
3043
|
+
|
|
3044
|
+
TESTS:
|
|
3045
|
+
|
|
3046
|
+
We check that :issue:`8239` is resolved::
|
|
3047
|
+
|
|
3048
|
+
sage: K.<a> = Qq(25)
|
|
3049
|
+
sage: K.teichmuller(K(2/5))
|
|
3050
|
+
Traceback (most recent call last):
|
|
3051
|
+
...
|
|
3052
|
+
ValueError: cannot set negative valuation element to Teichmuller representative
|
|
3053
|
+
"""
|
|
3054
|
+
self._normalize()
|
|
3055
|
+
if self.ordp > 0:
|
|
3056
|
+
self._set_exact_zero()
|
|
3057
|
+
elif self.ordp < 0:
|
|
3058
|
+
raise ValueError("cannot set negative valuation element to Teichmuller representative")
|
|
3059
|
+
elif self.relprec == 0:
|
|
3060
|
+
raise ValueError("not enough precision known")
|
|
3061
|
+
else:
|
|
3062
|
+
self.prime_pow.teichmuller_set_c(&self.unit, &self.unit, self.relprec)
|
|
3063
|
+
|
|
3064
|
+
# def padded_list(self, n, lift_mode='simple'):
|
|
3065
|
+
# """
|
|
3066
|
+
# Return a list of coefficients of pi starting with `pi^0` up to
|
|
3067
|
+
# `pi^n` exclusive (padded with zeros if needed)
|
|
3068
|
+
|
|
3069
|
+
# """
|
|
3070
|
+
# raise NotImplementedError
|
|
3071
|
+
|
|
3072
|
+
def precision_absolute(self):
|
|
3073
|
+
"""
|
|
3074
|
+
Return the absolute precision of this element, i.e., the power of the
|
|
3075
|
+
uniformizer modulo which this element is defined.
|
|
3076
|
+
|
|
3077
|
+
EXAMPLES::
|
|
3078
|
+
|
|
3079
|
+
sage: R = Zp(5,5)
|
|
3080
|
+
sage: S.<x> = R[]
|
|
3081
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
3082
|
+
sage: W.<w> = R.ext(f)
|
|
3083
|
+
sage: a = W(75, 19); a
|
|
3084
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
|
|
3085
|
+
sage: a.valuation()
|
|
3086
|
+
10
|
|
3087
|
+
sage: a.precision_absolute()
|
|
3088
|
+
19
|
|
3089
|
+
sage: a.precision_relative()
|
|
3090
|
+
9
|
|
3091
|
+
sage: a.unit_part()
|
|
3092
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
|
|
3093
|
+
sage: (a.unit_part() - 3).precision_absolute()
|
|
3094
|
+
9
|
|
3095
|
+
"""
|
|
3096
|
+
cdef Integer ans
|
|
3097
|
+
if self.ordp == maxordp:
|
|
3098
|
+
return infinity
|
|
3099
|
+
else:
|
|
3100
|
+
ans = PY_NEW(Integer)
|
|
3101
|
+
if self.relprec > 0:
|
|
3102
|
+
mpz_set_si(ans.value, self.relprec + self.ordp)
|
|
3103
|
+
else:
|
|
3104
|
+
mpz_set_si(ans.value, -self.relprec + self.ordp)
|
|
3105
|
+
return ans
|
|
3106
|
+
|
|
3107
|
+
def precision_relative(self):
|
|
3108
|
+
"""
|
|
3109
|
+
Return the relative precision of this element, i.e., the power of the
|
|
3110
|
+
uniformizer modulo which the unit part of ``self`` is defined.
|
|
3111
|
+
|
|
3112
|
+
EXAMPLES::
|
|
3113
|
+
|
|
3114
|
+
sage: R = Zp(5,5)
|
|
3115
|
+
sage: S.<x> = R[]
|
|
3116
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
3117
|
+
sage: W.<w> = R.ext(f)
|
|
3118
|
+
sage: a = W(75, 19); a
|
|
3119
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
|
|
3120
|
+
sage: a.valuation()
|
|
3121
|
+
10
|
|
3122
|
+
sage: a.precision_absolute()
|
|
3123
|
+
19
|
|
3124
|
+
sage: a.precision_relative()
|
|
3125
|
+
9
|
|
3126
|
+
sage: a.unit_part()
|
|
3127
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
|
|
3128
|
+
"""
|
|
3129
|
+
self._normalize()
|
|
3130
|
+
cdef Integer ans = PY_NEW(Integer)
|
|
3131
|
+
mpz_set_ui(ans.value, self.relprec)
|
|
3132
|
+
return ans
|
|
3133
|
+
|
|
3134
|
+
# def residue(self, n=1):
|
|
3135
|
+
# """
|
|
3136
|
+
# Reduces this element modulo pi^n.
|
|
3137
|
+
# """
|
|
3138
|
+
# raise NotImplementedError
|
|
3139
|
+
|
|
3140
|
+
cdef long valuation_c(self) noexcept:
|
|
3141
|
+
"""
|
|
3142
|
+
Return the valuation of this element.
|
|
3143
|
+
|
|
3144
|
+
EXAMPLES::
|
|
3145
|
+
|
|
3146
|
+
sage: R = Zp(5,5)
|
|
3147
|
+
sage: S.<x> = R[]
|
|
3148
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
3149
|
+
sage: W.<w> = R.ext(f)
|
|
3150
|
+
sage: a = W(75, 19); a
|
|
3151
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
|
|
3152
|
+
sage: a.valuation() # indirect doctest
|
|
3153
|
+
10
|
|
3154
|
+
sage: a.precision_absolute()
|
|
3155
|
+
19
|
|
3156
|
+
sage: a.precision_relative()
|
|
3157
|
+
9
|
|
3158
|
+
sage: a.unit_part()
|
|
3159
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
|
|
3160
|
+
"""
|
|
3161
|
+
self._normalize()
|
|
3162
|
+
return self.ordp
|
|
3163
|
+
|
|
3164
|
+
cpdef pAdicZZpXCRElement unit_part(self):
|
|
3165
|
+
"""
|
|
3166
|
+
Return the unit part of this element, ie ``self / uniformizer^(self.valuation())``.
|
|
3167
|
+
|
|
3168
|
+
EXAMPLES::
|
|
3169
|
+
|
|
3170
|
+
sage: R = Zp(5,5)
|
|
3171
|
+
sage: S.<x> = R[]
|
|
3172
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
3173
|
+
sage: W.<w> = R.ext(f)
|
|
3174
|
+
sage: a = W(75, 19); a
|
|
3175
|
+
3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
|
|
3176
|
+
sage: a.valuation()
|
|
3177
|
+
10
|
|
3178
|
+
sage: a.precision_absolute()
|
|
3179
|
+
19
|
|
3180
|
+
sage: a.precision_relative()
|
|
3181
|
+
9
|
|
3182
|
+
sage: a.unit_part()
|
|
3183
|
+
3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
|
|
3184
|
+
|
|
3185
|
+
TESTS:
|
|
3186
|
+
|
|
3187
|
+
We check that :issue:`13616` is resolved::
|
|
3188
|
+
|
|
3189
|
+
sage: z = (1+w)^5
|
|
3190
|
+
sage: y = z - 1
|
|
3191
|
+
sage: t = y - y
|
|
3192
|
+
sage: t.unit_part()
|
|
3193
|
+
O(w^0)
|
|
3194
|
+
"""
|
|
3195
|
+
self._normalize()
|
|
3196
|
+
cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
|
|
3197
|
+
ans.ordp = 0
|
|
3198
|
+
if self.relprec != 0:
|
|
3199
|
+
ans.unit = self.unit
|
|
3200
|
+
return ans
|
|
3201
|
+
|
|
3202
|
+
cdef ext_p_list(self, bint pos):
|
|
3203
|
+
"""
|
|
3204
|
+
Return a list of integers (in the Eisenstein case) or a list
|
|
3205
|
+
of lists of integers (in the unramified case). ``self`` can be
|
|
3206
|
+
reconstructed as a sum of elements of the list times powers of
|
|
3207
|
+
the uniformiser (in the Eisenstein case), or as a sum of
|
|
3208
|
+
powers of `p` times polynomials in the generator (in the
|
|
3209
|
+
unramified case).
|
|
3210
|
+
|
|
3211
|
+
If ``pos`` is ``True``, all integers will be in the interval `[0,p-1]`,
|
|
3212
|
+
otherwise they will be in the interval `[(1-p)/2, p/2]`.
|
|
3213
|
+
|
|
3214
|
+
Note that zeros are truncated from the returned list, so you
|
|
3215
|
+
must use the method :meth:`valuation` to completely recover ``self``.
|
|
3216
|
+
|
|
3217
|
+
EXAMPLES::
|
|
3218
|
+
|
|
3219
|
+
sage: R = Zp(5,5)
|
|
3220
|
+
sage: S.<x> = R[]
|
|
3221
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
3222
|
+
sage: W.<w> = R.ext(f)
|
|
3223
|
+
sage: y = W(775, 19); y
|
|
3224
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
|
|
3225
|
+
sage: y._ext_p_list(True)
|
|
3226
|
+
[1, 0, 4, 0, 2, 1, 2, 4, 1]
|
|
3227
|
+
sage: y._ext_p_list(False)
|
|
3228
|
+
[1, 0, -1, 0, 2, 1, 2, 0, 1]
|
|
3229
|
+
sage: w^10 - w^12 + 2*w^14 + w^15 + 2*w^16 + w^18 + O(w^19)
|
|
3230
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
|
|
3231
|
+
sage: g = x^3 + 3*x + 3
|
|
3232
|
+
sage: A.<a> = R.ext(g)
|
|
3233
|
+
sage: y = 75 + 45*a + 1200*a^2; y
|
|
3234
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
|
|
3235
|
+
sage: y._ext_p_list(True)
|
|
3236
|
+
[[0, 4], [3, 1, 3], [0, 0, 4], [0, 0, 1]]
|
|
3237
|
+
sage: y._ext_p_list(False)
|
|
3238
|
+
[[0, -1], [-2, 2, -2], [1], [0, 0, 2]]
|
|
3239
|
+
sage: 5*((-2*5 + 25) + (-1 + 2*5)*a + (-2*5 + 2*125)*a^2)
|
|
3240
|
+
4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
|
|
3241
|
+
"""
|
|
3242
|
+
self._normalize()
|
|
3243
|
+
return self.ext_p_list_precs(pos, self.relprec)
|
|
3244
|
+
|
|
3245
|
+
|
|
3246
|
+
def make_ZZpXCRElement(parent, unit, ordp, relprec, version):
|
|
3247
|
+
"""
|
|
3248
|
+
Unpickling.
|
|
3249
|
+
|
|
3250
|
+
EXAMPLES::
|
|
3251
|
+
|
|
3252
|
+
sage: R = Zp(5,5)
|
|
3253
|
+
sage: S.<x> = R[]
|
|
3254
|
+
sage: f = x^5 + 75*x^3 - 15*x^2 + 125*x - 5
|
|
3255
|
+
sage: W.<w> = R.ext(f)
|
|
3256
|
+
sage: y = W(775, 19); y
|
|
3257
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
|
|
3258
|
+
sage: loads(dumps(y)) # indirect doctest
|
|
3259
|
+
w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
|
|
3260
|
+
|
|
3261
|
+
sage: from sage.rings.padics.padic_ZZ_pX_CR_element import make_ZZpXCRElement
|
|
3262
|
+
sage: make_ZZpXCRElement(W, y._ntl_rep(), 3, 9, 0)
|
|
3263
|
+
w^3 + 4*w^5 + 2*w^7 + w^8 + 2*w^9 + 4*w^10 + w^11 + O(w^12)
|
|
3264
|
+
"""
|
|
3265
|
+
cdef pAdicZZpXCRElement ans
|
|
3266
|
+
cdef ZZ_pX_c poly
|
|
3267
|
+
if version == 0:
|
|
3268
|
+
ans = pAdicZZpXCRElement(parent, [], empty = True)
|
|
3269
|
+
if relprec == 0:
|
|
3270
|
+
ans._set_inexact_zero(mpz_get_si((<Integer>ordp).value))
|
|
3271
|
+
else:
|
|
3272
|
+
ans.prime_pow.restore_context_capdiv(mpz_get_si((<Integer>relprec).value))
|
|
3273
|
+
poly = (<ntl_ZZ_pX>unit).x
|
|
3274
|
+
ans._set(&poly, mpz_get_si((<Integer>ordp).value), mpz_get_si((<Integer>relprec).value))
|
|
3275
|
+
return ans
|
|
3276
|
+
else:
|
|
3277
|
+
raise ValueError("unknown unpickling version")
|