passagemath-ntl 10.6.33__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.
Potentially problematic release.
This version of passagemath-ntl might be problematic. Click here for more details.
- passagemath_ntl-10.6.33.dist-info/METADATA +122 -0
- passagemath_ntl-10.6.33.dist-info/RECORD +161 -0
- passagemath_ntl-10.6.33.dist-info/WHEEL +6 -0
- passagemath_ntl-10.6.33.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-e0f11cf3.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,778 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
# sage.doctest: needs sage.libs.ntl sage.rings.finite_rings
|
|
3
|
+
# distutils: libraries = NTL_LIBRARIES gmp
|
|
4
|
+
# distutils: extra_compile_args = NTL_CFLAGS
|
|
5
|
+
# distutils: include_dirs = NTL_INCDIR
|
|
6
|
+
# distutils: library_dirs = NTL_LIBDIR
|
|
7
|
+
# distutils: extra_link_args = NTL_LIBEXTRA
|
|
8
|
+
# distutils: language = c++
|
|
9
|
+
"""
|
|
10
|
+
Univariate Polynomials over GF(p^e) via NTL's ZZ_pEX
|
|
11
|
+
|
|
12
|
+
AUTHOR:
|
|
13
|
+
|
|
14
|
+
- Yann Laigle-Chapuy (2010-01) initial implementation
|
|
15
|
+
- Lorenz Panny (2023-01): :meth:`minpoly_mod`
|
|
16
|
+
- Giacomo Pope (2023-08): :meth:`reverse`, :meth:`inverse_series_trunc`
|
|
17
|
+
"""
|
|
18
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
19
|
+
|
|
20
|
+
from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class
|
|
21
|
+
from sage.libs.ntl.ZZ_pE cimport ZZ_pE_to_ZZ_pX
|
|
22
|
+
from sage.libs.ntl.ZZ_pX cimport ZZ_pX_deg, ZZ_pX_coeff
|
|
23
|
+
from sage.libs.ntl.ZZ_p cimport ZZ_p_rep
|
|
24
|
+
from sage.libs.ntl.convert cimport ZZ_to_mpz, mpz_to_ZZ
|
|
25
|
+
|
|
26
|
+
from sage.structure.element import have_same_parent, canonical_coercion
|
|
27
|
+
|
|
28
|
+
# We need to define this stuff before including the templating stuff
|
|
29
|
+
# to make sure the function get_cparent is found since it is used in
|
|
30
|
+
# 'polynomial_template.pxi'.
|
|
31
|
+
|
|
32
|
+
cdef cparent get_cparent(parent) except? NULL:
|
|
33
|
+
if parent is None:
|
|
34
|
+
return NULL
|
|
35
|
+
cdef ntl_ZZ_pEContext_class pec
|
|
36
|
+
try:
|
|
37
|
+
pec = parent._modulus
|
|
38
|
+
except AttributeError:
|
|
39
|
+
return NULL
|
|
40
|
+
return &(pec.ptrs)
|
|
41
|
+
|
|
42
|
+
# first we include the definitions
|
|
43
|
+
include "sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi"
|
|
44
|
+
|
|
45
|
+
# and then the interface
|
|
46
|
+
include "polynomial_template.pxi"
|
|
47
|
+
|
|
48
|
+
from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE
|
|
49
|
+
|
|
50
|
+
cdef inline ZZ_pE_c_to_list(ZZ_pE_c x):
|
|
51
|
+
cdef list L = []
|
|
52
|
+
cdef ZZ_pX_c c_pX
|
|
53
|
+
cdef ZZ_p_c c_p
|
|
54
|
+
cdef ZZ_c c_c
|
|
55
|
+
cdef Integer ans
|
|
56
|
+
|
|
57
|
+
c_pX = ZZ_pE_to_ZZ_pX(x)
|
|
58
|
+
d = ZZ_pX_deg(c_pX)
|
|
59
|
+
if d>=0:
|
|
60
|
+
for 0 <= j <= d:
|
|
61
|
+
c_p = ZZ_pX_coeff(c_pX, j)
|
|
62
|
+
c_c = ZZ_p_rep(c_p)
|
|
63
|
+
ans = Integer.__new__(Integer)
|
|
64
|
+
ZZ_to_mpz(ans.value, &c_c)
|
|
65
|
+
L.append(ans)
|
|
66
|
+
return L
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
cdef class Polynomial_ZZ_pEX(Polynomial_template):
|
|
70
|
+
r"""
|
|
71
|
+
Univariate Polynomials over `\GF{p^n}` via NTL's ``ZZ_pEX``.
|
|
72
|
+
|
|
73
|
+
EXAMPLES::
|
|
74
|
+
|
|
75
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
76
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
77
|
+
sage: (x^3 + a*x^2 + 1) * (x + a)
|
|
78
|
+
x^4 + 2*a*x^3 + a^2*x^2 + x + a
|
|
79
|
+
"""
|
|
80
|
+
def __init__(self, parent, x=None, check=True, is_gen=False, construct=False):
|
|
81
|
+
r"""
|
|
82
|
+
Create a new univariate polynomials over `\GF{p^n}`.
|
|
83
|
+
|
|
84
|
+
EXAMPLES::
|
|
85
|
+
|
|
86
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
87
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
88
|
+
sage: x^2+a
|
|
89
|
+
x^2 + a
|
|
90
|
+
|
|
91
|
+
TESTS:
|
|
92
|
+
|
|
93
|
+
The following tests against a bug that was fixed in :issue:`9944`.
|
|
94
|
+
With the ring definition above, we now have::
|
|
95
|
+
|
|
96
|
+
sage: R([3,'1234'])
|
|
97
|
+
1234*x + 3
|
|
98
|
+
sage: R([3,'12e34'])
|
|
99
|
+
Traceback (most recent call last):
|
|
100
|
+
...
|
|
101
|
+
TypeError: unable to convert '12e34' to an integer
|
|
102
|
+
sage: R([3,x])
|
|
103
|
+
Traceback (most recent call last):
|
|
104
|
+
...
|
|
105
|
+
TypeError: x is not a constant polynomial
|
|
106
|
+
|
|
107
|
+
Check that NTL contexts are correctly restored and that
|
|
108
|
+
:issue:`9524` has been fixed::
|
|
109
|
+
|
|
110
|
+
sage: x = polygen(GF(9, 'a'))
|
|
111
|
+
sage: x = polygen(GF(49, 'a'))
|
|
112
|
+
sage: -x
|
|
113
|
+
6*x
|
|
114
|
+
sage: 5*x
|
|
115
|
+
5*x
|
|
116
|
+
|
|
117
|
+
Check that :issue:`11239` is fixed::
|
|
118
|
+
|
|
119
|
+
sage: Fq.<a> = GF(2^4); Fqq.<b> = GF(3^7)
|
|
120
|
+
sage: PFq.<x> = Fq[]; PFqq.<y> = Fqq[]
|
|
121
|
+
sage: f = x^3 + (a^3 + 1)*x
|
|
122
|
+
sage: sage.rings.polynomial.polynomial_zz_pex.Polynomial_ZZ_pEX(PFqq, f)
|
|
123
|
+
Traceback (most recent call last):
|
|
124
|
+
...
|
|
125
|
+
TypeError: unable to coerce from a finite field other than the prime subfield
|
|
126
|
+
"""
|
|
127
|
+
cdef ntl_ZZ_pE d
|
|
128
|
+
try:
|
|
129
|
+
if (x.parent() is parent.base_ring()) or (x.parent() == parent.base_ring()):
|
|
130
|
+
Polynomial.__init__(self, parent, is_gen=is_gen)
|
|
131
|
+
(<Polynomial_template>self)._cparent = get_cparent(parent)
|
|
132
|
+
celement_construct(&self.x, (<Polynomial_template>self)._cparent)
|
|
133
|
+
d = parent._modulus.ZZ_pE(list(x.polynomial()))
|
|
134
|
+
ZZ_pEX_SetCoeff(self.x, 0, d.x)
|
|
135
|
+
return
|
|
136
|
+
except AttributeError:
|
|
137
|
+
pass
|
|
138
|
+
|
|
139
|
+
if isinstance(x, Polynomial):
|
|
140
|
+
x = x.list()
|
|
141
|
+
|
|
142
|
+
if isinstance(x, (list, tuple)):
|
|
143
|
+
Polynomial.__init__(self, parent, is_gen=is_gen)
|
|
144
|
+
(<Polynomial_template>self)._cparent = get_cparent(parent)
|
|
145
|
+
celement_construct(&self.x, (<Polynomial_template>self)._cparent)
|
|
146
|
+
K = parent.base_ring()
|
|
147
|
+
for i,e in enumerate(x):
|
|
148
|
+
# self(x) is supposed to be a conversion,
|
|
149
|
+
# not necessarily a coercion. So, we must
|
|
150
|
+
# not do K.coerce(e) but K(e).
|
|
151
|
+
e = K(e)
|
|
152
|
+
d = parent._modulus.ZZ_pE(list(e.polynomial()))
|
|
153
|
+
ZZ_pEX_SetCoeff(self.x, i, d.x)
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
Polynomial_template.__init__(self, parent, x, check, is_gen, construct)
|
|
157
|
+
|
|
158
|
+
cdef get_unsafe(self, Py_ssize_t i):
|
|
159
|
+
r"""
|
|
160
|
+
Return the `i`-th coefficient of ``self``.
|
|
161
|
+
|
|
162
|
+
EXAMPLES::
|
|
163
|
+
|
|
164
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
165
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
166
|
+
sage: f = x^3 + (2*a+1)*x + a
|
|
167
|
+
sage: f[0]
|
|
168
|
+
a
|
|
169
|
+
sage: f[1]
|
|
170
|
+
2*a + 1
|
|
171
|
+
sage: f[2]
|
|
172
|
+
0
|
|
173
|
+
sage: f[:2]
|
|
174
|
+
(2*a + 1)*x + a
|
|
175
|
+
sage: f[:50] == f
|
|
176
|
+
True
|
|
177
|
+
"""
|
|
178
|
+
self._parent._modulus.restore()
|
|
179
|
+
cdef ZZ_pE_c c_pE = ZZ_pEX_coeff(self.x, i)
|
|
180
|
+
return self._parent._base(ZZ_pE_c_to_list(c_pE))
|
|
181
|
+
|
|
182
|
+
cpdef list list(self, bint copy=True):
|
|
183
|
+
r"""
|
|
184
|
+
Return the list of coefficients.
|
|
185
|
+
|
|
186
|
+
EXAMPLES::
|
|
187
|
+
|
|
188
|
+
sage: K.<a> = GF(5^3)
|
|
189
|
+
sage: P = PolynomialRing(K, 'x')
|
|
190
|
+
sage: f = P.random_element(100)
|
|
191
|
+
sage: f.list() == [f[i] for i in range(f.degree()+1)]
|
|
192
|
+
True
|
|
193
|
+
sage: P.0.list()
|
|
194
|
+
[0, 1]
|
|
195
|
+
"""
|
|
196
|
+
cdef Py_ssize_t i
|
|
197
|
+
|
|
198
|
+
self._parent._modulus.restore()
|
|
199
|
+
|
|
200
|
+
K = self._parent.base_ring()
|
|
201
|
+
return [K(ZZ_pE_c_to_list(ZZ_pEX_coeff(self.x, i)))
|
|
202
|
+
for i in range(celement_len(&self.x, (<Polynomial_template>self)._cparent))]
|
|
203
|
+
|
|
204
|
+
cpdef _lmul_(self, Element left):
|
|
205
|
+
r"""
|
|
206
|
+
EXAMPLES::
|
|
207
|
+
|
|
208
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
209
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
210
|
+
sage: (2*a+1)*x # indirect doctest
|
|
211
|
+
(2*a + 1)*x
|
|
212
|
+
sage: x*(2*a+1) # indirect doctest
|
|
213
|
+
(2*a + 1)*x
|
|
214
|
+
"""
|
|
215
|
+
cdef ntl_ZZ_pE d
|
|
216
|
+
cdef Polynomial_ZZ_pEX r
|
|
217
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
218
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
219
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
220
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
221
|
+
d = self._parent._modulus.ZZ_pE(list(left.polynomial()))
|
|
222
|
+
ZZ_pEX_mul_ZZ_pE(r.x, self.x, d.x)
|
|
223
|
+
return r
|
|
224
|
+
|
|
225
|
+
def __call__(self, *x, **kwds):
|
|
226
|
+
r"""
|
|
227
|
+
Evaluate polynomial at `a`.
|
|
228
|
+
|
|
229
|
+
EXAMPLES::
|
|
230
|
+
|
|
231
|
+
sage: K.<u> = GF(next_prime(2**60)**3)
|
|
232
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
233
|
+
sage: P = (x-u)*(x+u+1)
|
|
234
|
+
sage: P(u)
|
|
235
|
+
0
|
|
236
|
+
sage: P(u+1)
|
|
237
|
+
2*u + 2
|
|
238
|
+
|
|
239
|
+
TESTS:
|
|
240
|
+
|
|
241
|
+
The work around provided in :issue:`10475` is superseded by :issue:`24072`::
|
|
242
|
+
|
|
243
|
+
sage: F.<x> = GF(4)
|
|
244
|
+
sage: P.<y> = F[]
|
|
245
|
+
sage: p = y^4 + x*y^3 + y^2 + (x + 1)*y + x + 1
|
|
246
|
+
sage: SR(p) # needs sage.symbolic
|
|
247
|
+
Traceback (most recent call last):
|
|
248
|
+
...
|
|
249
|
+
TypeError: positive characteristic not allowed in symbolic computations
|
|
250
|
+
|
|
251
|
+
Check that polynomial evaluation works when using logarithmic
|
|
252
|
+
representation of finite field elements (:issue:`16383`)::
|
|
253
|
+
|
|
254
|
+
sage: for i in range(10):
|
|
255
|
+
....: F = FiniteField(random_prime(15) ** ZZ.random_element(2, 5), 'a', repr='log')
|
|
256
|
+
....: b = F.random_element()
|
|
257
|
+
....: P = PolynomialRing(F, 'x')
|
|
258
|
+
....: f = P.random_element(8)
|
|
259
|
+
....: assert f(b) == sum(c * b^i for i, c in enumerate(f))
|
|
260
|
+
"""
|
|
261
|
+
cdef ntl_ZZ_pE _a
|
|
262
|
+
cdef ZZ_pE_c c_b
|
|
263
|
+
|
|
264
|
+
K = self._parent.base_ring()
|
|
265
|
+
|
|
266
|
+
if kwds:
|
|
267
|
+
if x:
|
|
268
|
+
raise TypeError("%s__call__() takes exactly 1 argument" % type(self))
|
|
269
|
+
try:
|
|
270
|
+
x = [kwds.pop(self.variable_name())]
|
|
271
|
+
except KeyError:
|
|
272
|
+
pass
|
|
273
|
+
if kwds:
|
|
274
|
+
raise TypeError("%s__call__() accepts no named argument except '%s'" % (type(self), self.variable_name()))
|
|
275
|
+
if len(x)!=1:
|
|
276
|
+
raise TypeError("%s__call__() takes exactly 1 positional argument" % type(self))
|
|
277
|
+
|
|
278
|
+
a = x[0]
|
|
279
|
+
try:
|
|
280
|
+
if a.parent() is not K:
|
|
281
|
+
a = K.coerce(a)
|
|
282
|
+
except (TypeError, AttributeError, NotImplementedError):
|
|
283
|
+
return Polynomial.__call__(self, a)
|
|
284
|
+
|
|
285
|
+
_a = self._parent._modulus.ZZ_pE(list(a.polynomial()))
|
|
286
|
+
ZZ_pEX_eval(c_b, self.x, _a.x)
|
|
287
|
+
return K(ZZ_pE_c_to_list(c_b))
|
|
288
|
+
|
|
289
|
+
def resultant(self, other):
|
|
290
|
+
r"""
|
|
291
|
+
Return the resultant of ``self`` and ``other``, which must lie in the same
|
|
292
|
+
polynomial ring.
|
|
293
|
+
|
|
294
|
+
INPUT:
|
|
295
|
+
|
|
296
|
+
- ``other`` -- a polynomial
|
|
297
|
+
|
|
298
|
+
OUTPUT: an element of the base ring of the polynomial ring
|
|
299
|
+
|
|
300
|
+
EXAMPLES::
|
|
301
|
+
|
|
302
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
303
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
304
|
+
sage: f = (x-a)*(x-a**2)*(x+1)
|
|
305
|
+
sage: g = (x-a**3)*(x-a**4)*(x+a)
|
|
306
|
+
sage: r = f.resultant(g)
|
|
307
|
+
sage: r == prod(u - v for (u,eu) in f.roots() for (v,ev) in g.roots())
|
|
308
|
+
True
|
|
309
|
+
"""
|
|
310
|
+
cdef ZZ_pE_c r
|
|
311
|
+
self._parent._modulus.restore()
|
|
312
|
+
|
|
313
|
+
if other.parent() is not self._parent:
|
|
314
|
+
other = self._parent.coerce(other)
|
|
315
|
+
|
|
316
|
+
ZZ_pEX_resultant(r, self.x, (<Polynomial_ZZ_pEX>other).x)
|
|
317
|
+
|
|
318
|
+
K = self._parent.base_ring()
|
|
319
|
+
return K(K.polynomial_ring()(ZZ_pE_c_to_list(r)))
|
|
320
|
+
|
|
321
|
+
def is_irreducible(self, algorithm='fast_when_false', iter=1):
|
|
322
|
+
r"""
|
|
323
|
+
Return ``True`` precisely when ``self`` is irreducible over its base ring.
|
|
324
|
+
|
|
325
|
+
INPUT:
|
|
326
|
+
|
|
327
|
+
- ``algorithm`` -- string (default: ``'fast_when_false'``);
|
|
328
|
+
there are 3 available algorithms:
|
|
329
|
+
``'fast_when_true'``, ``'fast_when_false'``, and ``'probabilistic'``
|
|
330
|
+
|
|
331
|
+
- ``iter`` -- (default: 1) if the algorithm is ``'probabilistic'``,
|
|
332
|
+
defines the number of iterations. The error probability is bounded
|
|
333
|
+
by `q^{\text{-iter}}` for polynomials in `\GF{q}[x]`.
|
|
334
|
+
|
|
335
|
+
EXAMPLES::
|
|
336
|
+
|
|
337
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
338
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
339
|
+
sage: P = x^3 + (2-a)*x + 1
|
|
340
|
+
sage: P.is_irreducible(algorithm='fast_when_false')
|
|
341
|
+
True
|
|
342
|
+
sage: P.is_irreducible(algorithm='fast_when_true')
|
|
343
|
+
True
|
|
344
|
+
sage: P.is_irreducible(algorithm='probabilistic')
|
|
345
|
+
True
|
|
346
|
+
sage: Q = (x^2+a)*(x+a^3)
|
|
347
|
+
sage: Q.is_irreducible(algorithm='fast_when_false')
|
|
348
|
+
False
|
|
349
|
+
sage: Q.is_irreducible(algorithm='fast_when_true')
|
|
350
|
+
False
|
|
351
|
+
sage: Q.is_irreducible(algorithm='probabilistic')
|
|
352
|
+
False
|
|
353
|
+
"""
|
|
354
|
+
self._parent._modulus.restore()
|
|
355
|
+
if algorithm=="fast_when_false":
|
|
356
|
+
sig_on()
|
|
357
|
+
res = ZZ_pEX_IterIrredTest(self.x)
|
|
358
|
+
sig_off()
|
|
359
|
+
elif algorithm=="fast_when_true":
|
|
360
|
+
sig_on()
|
|
361
|
+
res = ZZ_pEX_DetIrredTest(self.x)
|
|
362
|
+
sig_off()
|
|
363
|
+
elif algorithm=="probabilistic":
|
|
364
|
+
sig_on()
|
|
365
|
+
res = ZZ_pEX_ProbIrredTest(self.x, iter)
|
|
366
|
+
sig_off()
|
|
367
|
+
else:
|
|
368
|
+
raise ValueError("unknown algorithm")
|
|
369
|
+
return res != 0
|
|
370
|
+
|
|
371
|
+
def minpoly_mod(self, other):
|
|
372
|
+
r"""
|
|
373
|
+
Compute the minimal polynomial of this polynomial modulo another
|
|
374
|
+
polynomial in the same ring.
|
|
375
|
+
|
|
376
|
+
ALGORITHM:
|
|
377
|
+
|
|
378
|
+
NTL's ``MinPolyMod()``, which uses Shoup's algorithm [Sho1999]_.
|
|
379
|
+
|
|
380
|
+
EXAMPLES::
|
|
381
|
+
|
|
382
|
+
sage: R.<x> = GF(101^2)[]
|
|
383
|
+
sage: f = x^17 + x^2 - 1
|
|
384
|
+
sage: (x^2).minpoly_mod(f)
|
|
385
|
+
x^17 + 100*x^2 + 2*x + 100
|
|
386
|
+
|
|
387
|
+
TESTS:
|
|
388
|
+
|
|
389
|
+
Random testing::
|
|
390
|
+
|
|
391
|
+
sage: p = random_prime(50)
|
|
392
|
+
sage: e = randrange(2,10)
|
|
393
|
+
sage: R.<x> = GF((p,e),'a')[]
|
|
394
|
+
sage: d = randrange(1,50)
|
|
395
|
+
sage: f = R.random_element(d)
|
|
396
|
+
sage: g = R.random_element((-1,5*d))
|
|
397
|
+
sage: poly = g.minpoly_mod(f)
|
|
398
|
+
sage: poly(R.quotient(f)(g))
|
|
399
|
+
0
|
|
400
|
+
"""
|
|
401
|
+
self._parent._modulus.restore()
|
|
402
|
+
|
|
403
|
+
if other.parent() is not self._parent:
|
|
404
|
+
other = self._parent.coerce(other)
|
|
405
|
+
|
|
406
|
+
cdef Polynomial_ZZ_pEX r
|
|
407
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
408
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
409
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
410
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
411
|
+
|
|
412
|
+
ZZ_pEX_MinPolyMod(r.x, (<Polynomial_ZZ_pEX>(self % other)).x, (<Polynomial_ZZ_pEX>other).x)
|
|
413
|
+
return r
|
|
414
|
+
|
|
415
|
+
cpdef _richcmp_(self, other, int op):
|
|
416
|
+
r"""
|
|
417
|
+
EXAMPLES::
|
|
418
|
+
|
|
419
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
420
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
421
|
+
sage: P1 = (a**2+a+1)*x^2 + a*x + 1
|
|
422
|
+
sage: P2 = ( a+1)*x^2 + a*x + 1
|
|
423
|
+
sage: P1 < P2 # indirect doctests
|
|
424
|
+
False
|
|
425
|
+
|
|
426
|
+
TESTS::
|
|
427
|
+
|
|
428
|
+
sage: P3 = (a**2+a+1)*x^2 + x + 1
|
|
429
|
+
sage: P4 = x + 1
|
|
430
|
+
sage: P1 < P3
|
|
431
|
+
False
|
|
432
|
+
sage: P1 < P4
|
|
433
|
+
False
|
|
434
|
+
sage: P1 > P2
|
|
435
|
+
True
|
|
436
|
+
sage: P1 > P3
|
|
437
|
+
True
|
|
438
|
+
sage: P1 > P4
|
|
439
|
+
True
|
|
440
|
+
"""
|
|
441
|
+
return Polynomial._richcmp_(self, other, op)
|
|
442
|
+
|
|
443
|
+
def shift(self, int n):
|
|
444
|
+
r"""
|
|
445
|
+
EXAMPLES::
|
|
446
|
+
|
|
447
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
448
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
449
|
+
sage: f = x^3 + x^2 + 1
|
|
450
|
+
sage: f.shift(1)
|
|
451
|
+
x^4 + x^3 + x
|
|
452
|
+
sage: f.shift(-1)
|
|
453
|
+
x^2 + x
|
|
454
|
+
"""
|
|
455
|
+
self._parent._modulus.restore()
|
|
456
|
+
cdef Polynomial_ZZ_pEX r
|
|
457
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
458
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
459
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
460
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
461
|
+
ZZ_pEX_LeftShift(r.x, self.x, n)
|
|
462
|
+
return r
|
|
463
|
+
|
|
464
|
+
def __lshift__(self, int n):
|
|
465
|
+
r"""
|
|
466
|
+
EXAMPLES::
|
|
467
|
+
|
|
468
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
469
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
470
|
+
sage: f = x^3 + x^2 + 1
|
|
471
|
+
sage: f << 1
|
|
472
|
+
x^4 + x^3 + x
|
|
473
|
+
sage: f << -1
|
|
474
|
+
x^2 + x
|
|
475
|
+
"""
|
|
476
|
+
return self.shift(n)
|
|
477
|
+
|
|
478
|
+
def __rshift__(self, int n):
|
|
479
|
+
r"""
|
|
480
|
+
EXAMPLES::
|
|
481
|
+
|
|
482
|
+
sage: K.<a> = GF(next_prime(2**60)**3)
|
|
483
|
+
sage: R.<x> = PolynomialRing(K, implementation='NTL')
|
|
484
|
+
sage: f = x^3 + x^2 + 1
|
|
485
|
+
sage: f >> 1
|
|
486
|
+
x^2 + x
|
|
487
|
+
sage: f >> -1
|
|
488
|
+
x^4 + x^3 + x
|
|
489
|
+
"""
|
|
490
|
+
return self.shift(-n)
|
|
491
|
+
|
|
492
|
+
def reverse(self, degree=None):
|
|
493
|
+
r"""
|
|
494
|
+
Return the polynomial obtained by reversing the coefficients
|
|
495
|
+
of this polynomial. If degree is set then this function behaves
|
|
496
|
+
as if this polynomial has degree ``degree``.
|
|
497
|
+
|
|
498
|
+
EXAMPLES::
|
|
499
|
+
|
|
500
|
+
sage: R.<x> = GF(101^2)[]
|
|
501
|
+
sage: f = x^13 + 11*x^10 + 32*x^6 + 4
|
|
502
|
+
sage: f.reverse()
|
|
503
|
+
4*x^13 + 32*x^7 + 11*x^3 + 1
|
|
504
|
+
sage: f.reverse(degree=15)
|
|
505
|
+
4*x^15 + 32*x^9 + 11*x^5 + x^2
|
|
506
|
+
sage: f.reverse(degree=2)
|
|
507
|
+
4*x^2
|
|
508
|
+
|
|
509
|
+
TESTS::
|
|
510
|
+
|
|
511
|
+
sage: R.<x> = GF(163^2)[]
|
|
512
|
+
sage: f = R([p for p in primes(20)])
|
|
513
|
+
sage: f.reverse()
|
|
514
|
+
2*x^7 + 3*x^6 + 5*x^5 + 7*x^4 + 11*x^3 + 13*x^2 + 17*x + 19
|
|
515
|
+
sage: f.reverse(degree=200)
|
|
516
|
+
2*x^200 + 3*x^199 + 5*x^198 + 7*x^197 + 11*x^196 + 13*x^195 + 17*x^194 + 19*x^193
|
|
517
|
+
sage: f.reverse(degree=0)
|
|
518
|
+
2
|
|
519
|
+
sage: f.reverse(degree=-5)
|
|
520
|
+
Traceback (most recent call last):
|
|
521
|
+
...
|
|
522
|
+
ValueError: degree argument must be a nonnegative integer, got -5
|
|
523
|
+
|
|
524
|
+
Check that this implementation is compatible with the generic one::
|
|
525
|
+
|
|
526
|
+
sage: p = R([0,1,0,2])
|
|
527
|
+
sage: all(p.reverse(d) == Polynomial.reverse(p, d)
|
|
528
|
+
....: for d in [None, 0, 1, 2, 3, 4])
|
|
529
|
+
True
|
|
530
|
+
"""
|
|
531
|
+
self._parent._modulus.restore()
|
|
532
|
+
|
|
533
|
+
# Construct output polynomial
|
|
534
|
+
cdef Polynomial_ZZ_pEX r
|
|
535
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
536
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
537
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
538
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
539
|
+
|
|
540
|
+
# When a degree has been supplied, ensure it is a valid input
|
|
541
|
+
cdef unsigned long d
|
|
542
|
+
if degree is not None:
|
|
543
|
+
if degree < 0:
|
|
544
|
+
raise ValueError("degree argument must be a nonnegative integer, got %s" % (degree))
|
|
545
|
+
d = degree
|
|
546
|
+
if d != degree:
|
|
547
|
+
raise ValueError("degree argument must be a nonnegative integer, got %s" % (degree))
|
|
548
|
+
ZZ_pEX_reverse_hi(r.x, (<Polynomial_ZZ_pEX> self).x, d)
|
|
549
|
+
else:
|
|
550
|
+
ZZ_pEX_reverse(r.x, (<Polynomial_ZZ_pEX> self).x)
|
|
551
|
+
return r
|
|
552
|
+
|
|
553
|
+
def inverse_series_trunc(self, prec):
|
|
554
|
+
r"""
|
|
555
|
+
Compute and return the inverse of ``self`` modulo `x^{prec}`.
|
|
556
|
+
|
|
557
|
+
The constant term of ``self`` must be invertible.
|
|
558
|
+
|
|
559
|
+
EXAMPLES::
|
|
560
|
+
|
|
561
|
+
sage: R.<x> = GF(101^2)[]
|
|
562
|
+
sage: z2 = R.base_ring().gen()
|
|
563
|
+
sage: f = (3*z2 + 57)*x^3 + (13*z2 + 94)*x^2 + (7*z2 + 2)*x + 66*z2 + 15
|
|
564
|
+
sage: f.inverse_series_trunc(1)
|
|
565
|
+
51*z2 + 92
|
|
566
|
+
sage: f.inverse_series_trunc(2)
|
|
567
|
+
(30*z2 + 30)*x + 51*z2 + 92
|
|
568
|
+
sage: f.inverse_series_trunc(3)
|
|
569
|
+
(42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92
|
|
570
|
+
sage: f.inverse_series_trunc(4)
|
|
571
|
+
(99*z2 + 96)*x^3 + (42*z2 + 94)*x^2 + (30*z2 + 30)*x + 51*z2 + 92
|
|
572
|
+
|
|
573
|
+
TESTS::
|
|
574
|
+
|
|
575
|
+
sage: R.<x> = GF(163^2)[]
|
|
576
|
+
sage: f = R([p for p in primes(20)])
|
|
577
|
+
sage: f.inverse_series_trunc(1)
|
|
578
|
+
82
|
|
579
|
+
sage: f.inverse_series_trunc(2)
|
|
580
|
+
40*x + 82
|
|
581
|
+
sage: f.inverse_series_trunc(3)
|
|
582
|
+
61*x^2 + 40*x + 82
|
|
583
|
+
sage: f.inverse_series_trunc(0)
|
|
584
|
+
Traceback (most recent call last):
|
|
585
|
+
...
|
|
586
|
+
ValueError: the precision must be positive, got 0
|
|
587
|
+
sage: f.inverse_series_trunc(-1)
|
|
588
|
+
Traceback (most recent call last):
|
|
589
|
+
...
|
|
590
|
+
ValueError: the precision must be positive, got -1
|
|
591
|
+
sage: f = x + x^2 + x^3
|
|
592
|
+
sage: f.inverse_series_trunc(5)
|
|
593
|
+
Traceback (most recent call last):
|
|
594
|
+
...
|
|
595
|
+
ValueError: constant term 0 is not a unit
|
|
596
|
+
"""
|
|
597
|
+
self._parent._modulus.restore()
|
|
598
|
+
|
|
599
|
+
# Ensure precision is nonnegative
|
|
600
|
+
if prec <= 0:
|
|
601
|
+
raise ValueError("the precision must be positive, got {}".format(prec))
|
|
602
|
+
|
|
603
|
+
# Ensure we can invert the constant term
|
|
604
|
+
const_term = self.get_coeff_c(0)
|
|
605
|
+
if not const_term.is_unit():
|
|
606
|
+
raise ValueError("constant term {} is not a unit".format(const_term))
|
|
607
|
+
|
|
608
|
+
# Construct output polynomial
|
|
609
|
+
cdef Polynomial_ZZ_pEX r
|
|
610
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
611
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
612
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
613
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
614
|
+
|
|
615
|
+
# Call to NTL for the inverse truncation
|
|
616
|
+
if prec > 0:
|
|
617
|
+
sig_on()
|
|
618
|
+
ZZ_pEX_InvTrunc(r.x, self.x, prec)
|
|
619
|
+
sig_off()
|
|
620
|
+
return r
|
|
621
|
+
|
|
622
|
+
def __pow__(self, exp, modulus):
|
|
623
|
+
r"""
|
|
624
|
+
Exponentiation of ``self``.
|
|
625
|
+
|
|
626
|
+
If ``modulus`` is not ``None``, the exponentiation is performed
|
|
627
|
+
modulo the polynomial ``modulus``.
|
|
628
|
+
|
|
629
|
+
EXAMPLES::
|
|
630
|
+
|
|
631
|
+
sage: K.<a> = GF(101^2, 'a', modulus=[1,1,1])
|
|
632
|
+
sage: R.<x> = PolynomialRing(K, implementation="NTL")
|
|
633
|
+
sage: pow(x, 100)
|
|
634
|
+
x^100
|
|
635
|
+
sage: pow(x + 3, 5)
|
|
636
|
+
x^5 + 15*x^4 + 90*x^3 + 68*x^2 + x + 41
|
|
637
|
+
|
|
638
|
+
If modulus is not ``None``, performs modular exponentiation::
|
|
639
|
+
|
|
640
|
+
sage: K.<a> = GF(101^2, 'a', modulus=[1,1,1])
|
|
641
|
+
sage: R.<x> = PolynomialRing(K, implementation="NTL")
|
|
642
|
+
sage: pow(x, 100, x^2 + x + a)
|
|
643
|
+
(19*a + 64)*x + 30*a + 2
|
|
644
|
+
sage: pow(x, 100 * 101**200, x^2 + x + a)
|
|
645
|
+
(19*a + 64)*x + 30*a + 2
|
|
646
|
+
|
|
647
|
+
The modulus can have smaller degree than ``self``::
|
|
648
|
+
|
|
649
|
+
sage: K.<a> = GF(101^2, 'a', modulus=[1,1,1])
|
|
650
|
+
sage: R.<x> = PolynomialRing(K, implementation="NTL")
|
|
651
|
+
sage: pow(x^4, 25, x^2 + x + a)
|
|
652
|
+
(19*a + 64)*x + 30*a + 2
|
|
653
|
+
|
|
654
|
+
TESTS:
|
|
655
|
+
|
|
656
|
+
Canonical coercion should apply::
|
|
657
|
+
|
|
658
|
+
sage: xx = GF(101)["x"].gen()
|
|
659
|
+
sage: pow(x+1, 25, 2)
|
|
660
|
+
0
|
|
661
|
+
sage: pow(x + a, 101**2, xx^3 + xx + 1)
|
|
662
|
+
4*x^2 + 44*x + a + 70
|
|
663
|
+
sage: pow(x + a, int(101**2), xx^3 + xx + 1)
|
|
664
|
+
4*x^2 + 44*x + a + 70
|
|
665
|
+
sage: xx = polygen(GF(97))
|
|
666
|
+
sage: _ = pow(x + a, 101**2, xx^3 + xx + 1)
|
|
667
|
+
Traceback (most recent call last):
|
|
668
|
+
...
|
|
669
|
+
TypeError: no common canonical parent for objects with parents: ...
|
|
670
|
+
"""
|
|
671
|
+
exp = Integer(exp)
|
|
672
|
+
if modulus is not None:
|
|
673
|
+
# Handle when modulus is zero
|
|
674
|
+
if modulus.is_zero():
|
|
675
|
+
raise ZeroDivisionError("modulus must be nonzero")
|
|
676
|
+
|
|
677
|
+
# Similar to coerce_binop
|
|
678
|
+
if not have_same_parent(self, modulus):
|
|
679
|
+
a, m = canonical_coercion(self, modulus)
|
|
680
|
+
if a is not self:
|
|
681
|
+
return pow(a, exp, m)
|
|
682
|
+
modulus = m
|
|
683
|
+
self = self % modulus
|
|
684
|
+
if exp > 0 and exp.bit_length() >= 32:
|
|
685
|
+
return (<Polynomial_ZZ_pEX>self)._powmod_bigexp(Integer(exp), modulus)
|
|
686
|
+
return Polynomial_template.__pow__(self, exp, modulus)
|
|
687
|
+
|
|
688
|
+
cdef _powmod_bigexp(Polynomial_ZZ_pEX self, Integer exp, Polynomial_ZZ_pEX modulus):
|
|
689
|
+
"""
|
|
690
|
+
Modular exponentiation for large exponents.
|
|
691
|
+
"""
|
|
692
|
+
self._parent._modulus.restore()
|
|
693
|
+
cdef Polynomial_ZZ_pEX r
|
|
694
|
+
cdef ZZ_c e_ZZ
|
|
695
|
+
cdef ZZ_pEX_c y
|
|
696
|
+
cdef ZZ_pEX_Modulus_c mod
|
|
697
|
+
|
|
698
|
+
mpz_to_ZZ(&e_ZZ, exp.value)
|
|
699
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
700
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
701
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
702
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
703
|
+
ZZ_pEX_Modulus_build(mod, modulus.x)
|
|
704
|
+
|
|
705
|
+
sig_on()
|
|
706
|
+
if ZZ_pEX_IsX(self.x):
|
|
707
|
+
ZZ_pEX_PowerXMod_ZZ_pre(r.x, e_ZZ, mod)
|
|
708
|
+
elif ZZ_pEX_deg(self.x) < ZZ_pEX_deg(modulus.x):
|
|
709
|
+
ZZ_pEX_PowerMod_ZZ_pre(r.x, self.x, e_ZZ, mod)
|
|
710
|
+
else:
|
|
711
|
+
ZZ_pEX_rem_pre(y, self.x, mod)
|
|
712
|
+
ZZ_pEX_PowerMod_ZZ_pre(r.x, y, e_ZZ, mod)
|
|
713
|
+
sig_off()
|
|
714
|
+
return r
|
|
715
|
+
|
|
716
|
+
def compose_mod(self, other, modulus):
|
|
717
|
+
r"""
|
|
718
|
+
Compute `f(g) \bmod h`.
|
|
719
|
+
|
|
720
|
+
To be precise about the order fo compostion, given ``self``, ``other``
|
|
721
|
+
and ``modulus`` as `f(x)`, `g(x)` and `h(x)` compute `f(g(x)) \bmod h(x)`.
|
|
722
|
+
|
|
723
|
+
INPUT:
|
|
724
|
+
|
|
725
|
+
- ``other`` -- a polynomial `g(x)`
|
|
726
|
+
- ``modulus`` -- a polynomial `h(x)`
|
|
727
|
+
|
|
728
|
+
EXAMPLES::
|
|
729
|
+
|
|
730
|
+
sage: R.<x> = GF(3**6)[]
|
|
731
|
+
sage: f = R.random_element()
|
|
732
|
+
sage: g = R.random_element()
|
|
733
|
+
sage: g.compose_mod(g, f) == g(g) % f
|
|
734
|
+
True
|
|
735
|
+
|
|
736
|
+
sage: F.<z3> = GF(3**6)
|
|
737
|
+
sage: R.<x> = F[]
|
|
738
|
+
sage: f = 2*z3^2*x^2 + (z3 + 1)*x + z3^2 + 2
|
|
739
|
+
sage: g = (z3^2 + 2*z3)*x^2 + (2*z3 + 2)*x + 2*z3^2 + z3 + 2
|
|
740
|
+
sage: h = (2*z3 + 2)*x^2 + (2*z3^2 + 1)*x + 2*z3^2 + z3 + 2
|
|
741
|
+
sage: f.compose_mod(g, h)
|
|
742
|
+
(z3^5 + z3^4 + z3^3 + z3^2 + z3)*x + z3^5 + z3^3 + 2*z3 + 2
|
|
743
|
+
sage: f.compose_mod(g, h) == f(g) % h
|
|
744
|
+
True
|
|
745
|
+
|
|
746
|
+
AUTHORS:
|
|
747
|
+
|
|
748
|
+
- Giacomo Pope (2024-08) initial implementation
|
|
749
|
+
"""
|
|
750
|
+
self._parent._modulus.restore()
|
|
751
|
+
|
|
752
|
+
# Ensure all the parents match
|
|
753
|
+
if other.parent() is not self._parent:
|
|
754
|
+
other = self._parent.coerce(other)
|
|
755
|
+
if modulus.parent() is not self._parent:
|
|
756
|
+
modulus = self._parent.coerce(modulus)
|
|
757
|
+
|
|
758
|
+
# Create the output polynomial
|
|
759
|
+
cdef Polynomial_ZZ_pEX r
|
|
760
|
+
r = Polynomial_ZZ_pEX.__new__(Polynomial_ZZ_pEX)
|
|
761
|
+
celement_construct(&r.x, (<Polynomial_template>self)._cparent)
|
|
762
|
+
r._parent = (<Polynomial_template>self)._parent
|
|
763
|
+
r._cparent = (<Polynomial_template>self)._cparent
|
|
764
|
+
|
|
765
|
+
# Create ZZ_pEX_Modulus type from modulus input
|
|
766
|
+
cdef ZZ_pEX_Modulus_c mod
|
|
767
|
+
ZZ_pEX_Modulus_build(mod, (<Polynomial_ZZ_pEX>modulus).x)
|
|
768
|
+
|
|
769
|
+
# Compute f(g) mod h
|
|
770
|
+
sig_on()
|
|
771
|
+
ZZ_pEX_CompMod(r.x, (<Polynomial_ZZ_pEX>self).x, (<Polynomial_ZZ_pEX>(other % modulus)).x, mod)
|
|
772
|
+
sig_off()
|
|
773
|
+
|
|
774
|
+
return r
|
|
775
|
+
|
|
776
|
+
# compose_mod is the natural name from the NTL bindings, but polynomial_gf2x
|
|
777
|
+
# has modular_composition as the method name so here we allow both
|
|
778
|
+
modular_composition = compose_mod
|