passagemath-ntl 10.6.37__cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passagemath-ntl might be problematic. Click here for more details.
- passagemath_ntl/__init__.py +3 -0
- passagemath_ntl-10.6.37.dist-info/METADATA +122 -0
- passagemath_ntl-10.6.37.dist-info/RECORD +162 -0
- passagemath_ntl-10.6.37.dist-info/WHEEL +6 -0
- passagemath_ntl-10.6.37.dist-info/top_level.txt +3 -0
- passagemath_ntl.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
- passagemath_ntl.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_ntl.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
- passagemath_ntl.libs/libmpfr-9d41ebf1.so.6.2.1 +0 -0
- passagemath_ntl.libs/libntl-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-aarch64-linux-gnu.so +0 -0
- sage/rings/bernmm.pyx +161 -0
- sage/rings/bernoulli_mod_p.cpython-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-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-311-aarch64-linux-gnu.so +0 -0
- sage/schemes/hyperelliptic_curves/hypellfrob.pyx +252 -0
|
@@ -0,0 +1,2049 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
# distutils: libraries = NTL_LIBRARIES gmp
|
|
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.libs.pari
|
|
9
|
+
r"""
|
|
10
|
+
Dense univariate polynomials over `\ZZ/n\ZZ`, implemented using NTL
|
|
11
|
+
|
|
12
|
+
This implementation is generally slower than the FLINT implementation in
|
|
13
|
+
:mod:`~sage.rings.polynomial.polynomial_zmod_flint`, so we use FLINT by
|
|
14
|
+
default when the modulus is small enough; but NTL does not require that `n` be
|
|
15
|
+
``int``-sized, so we use it as default when `n` is too large for FLINT.
|
|
16
|
+
|
|
17
|
+
Note that the classes :class:`Polynomial_dense_modn_ntl_zz` and
|
|
18
|
+
:class:`Polynomial_dense_modn_ntl_ZZ` are different; the former is limited to
|
|
19
|
+
moduli less than a certain bound, while the latter supports arbitrarily large
|
|
20
|
+
moduli.
|
|
21
|
+
|
|
22
|
+
AUTHORS:
|
|
23
|
+
|
|
24
|
+
- Robert Bradshaw: Split off from polynomial_element_generic.py (2007-09)
|
|
25
|
+
- Robert Bradshaw: Major rewrite to use NTL directly (2007-09)
|
|
26
|
+
"""
|
|
27
|
+
# ****************************************************************************
|
|
28
|
+
# Copyright (C) 2007 William Stein <wstein@gmail.com>
|
|
29
|
+
#
|
|
30
|
+
# This program is free software: you can redistribute it and/or modify
|
|
31
|
+
# it under the terms of the GNU General Public License as published by
|
|
32
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
33
|
+
# (at your option) any later version.
|
|
34
|
+
# https://www.gnu.org/licenses/
|
|
35
|
+
# ****************************************************************************
|
|
36
|
+
|
|
37
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
38
|
+
|
|
39
|
+
from sage.rings.polynomial.polynomial_element cimport Polynomial, _dict_to_list
|
|
40
|
+
|
|
41
|
+
from sage.rings.integer cimport smallInteger
|
|
42
|
+
|
|
43
|
+
from sage.libs.ntl.all import ZZX, ZZ_pX
|
|
44
|
+
from sage.rings.integer_ring import ZZ
|
|
45
|
+
|
|
46
|
+
from sage.rings.fraction_field_element import FractionFieldElement
|
|
47
|
+
|
|
48
|
+
from sage.rings.infinity import infinity
|
|
49
|
+
|
|
50
|
+
from sage.structure.element import canonical_coercion, coerce_binop, have_same_parent
|
|
51
|
+
|
|
52
|
+
from sage.libs.ntl.types cimport NTL_SP_BOUND
|
|
53
|
+
from sage.libs.ntl.ZZ_p cimport *
|
|
54
|
+
from sage.libs.ntl.lzz_p cimport *
|
|
55
|
+
from sage.libs.ntl.lzz_pX cimport *
|
|
56
|
+
from sage.libs.ntl.ZZ_pX cimport *
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
from sage.libs.pari import pari
|
|
60
|
+
from cypari2.gen import Gen as pari_gen
|
|
61
|
+
except ImportError:
|
|
62
|
+
pari_gen = ()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def make_element(parent, args):
|
|
66
|
+
return parent(*args)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
zz_p_max = NTL_SP_BOUND
|
|
70
|
+
|
|
71
|
+
cdef class Polynomial_dense_mod_n(Polynomial):
|
|
72
|
+
"""
|
|
73
|
+
A dense polynomial over the integers modulo n, where n is composite, with
|
|
74
|
+
the underlying arithmetic done using NTL.
|
|
75
|
+
|
|
76
|
+
EXAMPLES::
|
|
77
|
+
|
|
78
|
+
sage: R.<x> = PolynomialRing(Integers(16), implementation='NTL')
|
|
79
|
+
sage: f = x^3 - x + 17
|
|
80
|
+
sage: f^2
|
|
81
|
+
x^6 + 14*x^4 + 2*x^3 + x^2 + 14*x + 1
|
|
82
|
+
|
|
83
|
+
sage: loads(f.dumps()) == f
|
|
84
|
+
True
|
|
85
|
+
|
|
86
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
87
|
+
sage: p = 3*x
|
|
88
|
+
sage: q = 7*x
|
|
89
|
+
sage: p + q
|
|
90
|
+
10*x
|
|
91
|
+
sage: R.<x> = PolynomialRing(Integers(8), implementation='NTL')
|
|
92
|
+
sage: parent(p)
|
|
93
|
+
Univariate Polynomial Ring in x over Ring of integers modulo 100 (using NTL)
|
|
94
|
+
sage: p + q
|
|
95
|
+
10*x
|
|
96
|
+
sage: R({10:-1})
|
|
97
|
+
7*x^10
|
|
98
|
+
|
|
99
|
+
TESTS::
|
|
100
|
+
|
|
101
|
+
sage: # needs sage.libs.pari
|
|
102
|
+
sage: f = Integers(5*2^100)['x'].random_element()
|
|
103
|
+
sage: from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_mod_n
|
|
104
|
+
sage: isinstance(f, Polynomial_dense_mod_n)
|
|
105
|
+
True
|
|
106
|
+
"""
|
|
107
|
+
def __init__(self, parent, x=None, check=True,
|
|
108
|
+
is_gen=False, construct=False):
|
|
109
|
+
Polynomial.__init__(self, parent, is_gen=is_gen)
|
|
110
|
+
cdef Polynomial_dense_mod_n numer, denom
|
|
111
|
+
|
|
112
|
+
if construct:
|
|
113
|
+
if isinstance(x, ZZ_pX):
|
|
114
|
+
self._poly = x
|
|
115
|
+
return
|
|
116
|
+
self._poly = ZZ_pX(x, parent.modulus())
|
|
117
|
+
return
|
|
118
|
+
|
|
119
|
+
self._poly = ZZ_pX([], parent.modulus())
|
|
120
|
+
|
|
121
|
+
if x is None:
|
|
122
|
+
return # leave initialized to 0 polynomial.
|
|
123
|
+
|
|
124
|
+
if isinstance(x, Polynomial):
|
|
125
|
+
if x.parent() == self.parent():
|
|
126
|
+
self._poly = (<Polynomial_dense_modn_ntl_zz>x)._poly.__copy__()
|
|
127
|
+
return
|
|
128
|
+
else:
|
|
129
|
+
R = parent.base_ring()
|
|
130
|
+
x = [ZZ(R(a)) for a in x.list()]
|
|
131
|
+
check = False
|
|
132
|
+
|
|
133
|
+
elif isinstance(x, dict):
|
|
134
|
+
R = parent.base_ring()
|
|
135
|
+
x = _dict_to_list(x, R(0))
|
|
136
|
+
|
|
137
|
+
elif isinstance(x, ZZX):
|
|
138
|
+
self._poly = x.copy()
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
elif isinstance(x, pari_gen):
|
|
142
|
+
x = [ZZ(w) for w in x.list()]
|
|
143
|
+
check = False
|
|
144
|
+
|
|
145
|
+
elif isinstance(x, FractionFieldElement) and \
|
|
146
|
+
isinstance(x.numerator(), Polynomial_dense_mod_n):
|
|
147
|
+
if x.denominator().is_unit():
|
|
148
|
+
numer = x.numerator()
|
|
149
|
+
denom = x.denominator().inverse_of_unit()
|
|
150
|
+
x = numer._poly * denom._poly
|
|
151
|
+
check = False
|
|
152
|
+
else:
|
|
153
|
+
raise TypeError("Denominator not a unit.")
|
|
154
|
+
|
|
155
|
+
elif not isinstance(x, list) and not isinstance(x, tuple):
|
|
156
|
+
x = [x] # constant polynomials
|
|
157
|
+
|
|
158
|
+
if check:
|
|
159
|
+
R = parent.base_ring()
|
|
160
|
+
x = [ZZ(R(a)) for a in x]
|
|
161
|
+
|
|
162
|
+
self._poly = ZZ_pX(x, parent.modulus())
|
|
163
|
+
|
|
164
|
+
def __reduce__(self):
|
|
165
|
+
return make_element, (self.parent(), (self.list(), False, self.is_gen()))
|
|
166
|
+
|
|
167
|
+
def int_list(self):
|
|
168
|
+
return eval(str(self._poly).replace(' ',','))
|
|
169
|
+
|
|
170
|
+
def __pari__(self, variable=None):
|
|
171
|
+
"""
|
|
172
|
+
EXAMPLES::
|
|
173
|
+
|
|
174
|
+
sage: t = PolynomialRing(IntegerModRing(17), "t", implementation='NTL').gen()
|
|
175
|
+
sage: f = t^3 + 3*t - 17
|
|
176
|
+
sage: pari(f) # needs sage.libs.pari
|
|
177
|
+
Mod(1, 17)*t^3 + Mod(3, 17)*t
|
|
178
|
+
"""
|
|
179
|
+
if variable is None:
|
|
180
|
+
variable = self.parent().variable_name()
|
|
181
|
+
return pari(self.int_list()).Polrev(variable) * \
|
|
182
|
+
pari(1).Mod(self.parent().base_ring().order())
|
|
183
|
+
|
|
184
|
+
def ntl_ZZ_pX(self):
|
|
185
|
+
r"""
|
|
186
|
+
Return underlying NTL representation of this polynomial. Additional
|
|
187
|
+
''bonus'' functionality is available through this function.
|
|
188
|
+
|
|
189
|
+
.. warning::
|
|
190
|
+
|
|
191
|
+
You must call ``ntl.set_modulus(ntl.ZZ(n))`` before doing
|
|
192
|
+
arithmetic with this object!
|
|
193
|
+
"""
|
|
194
|
+
return self._poly
|
|
195
|
+
|
|
196
|
+
cdef get_unsafe(self, Py_ssize_t n):
|
|
197
|
+
"""
|
|
198
|
+
Return the `n`-th coefficient of ``self``.
|
|
199
|
+
|
|
200
|
+
EXAMPLES::
|
|
201
|
+
|
|
202
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
203
|
+
sage: from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_mod_n
|
|
204
|
+
sage: f = Polynomial_dense_mod_n(R, [5,10,13,1,4]); f
|
|
205
|
+
4*x^4 + x^3 + 13*x^2 + 10*x + 5
|
|
206
|
+
sage: f[2]
|
|
207
|
+
13
|
|
208
|
+
sage: f[:3]
|
|
209
|
+
13*x^2 + 10*x + 5
|
|
210
|
+
"""
|
|
211
|
+
return self._parent._base((<ntl_ZZ_pX> self._poly)[n]._integer_())
|
|
212
|
+
|
|
213
|
+
def _unsafe_mutate(self, n, value):
|
|
214
|
+
n = int(n)
|
|
215
|
+
if n < 0:
|
|
216
|
+
raise IndexError("n must be >= 0")
|
|
217
|
+
self._poly[n] = int(value)
|
|
218
|
+
|
|
219
|
+
def _pow(self, n):
|
|
220
|
+
n = int(n)
|
|
221
|
+
if self.degree() <= 0:
|
|
222
|
+
return self.parent()(self[0]**n)
|
|
223
|
+
if n < 0:
|
|
224
|
+
return (~self)**(-n)
|
|
225
|
+
return self.parent()(self._poly**n, construct=True)
|
|
226
|
+
|
|
227
|
+
cpdef _add_(self, right):
|
|
228
|
+
return self.parent()(self._poly + (<Polynomial_dense_mod_n>right)._poly, construct=True)
|
|
229
|
+
|
|
230
|
+
cpdef _mul_(self, right):
|
|
231
|
+
"""
|
|
232
|
+
EXAMPLES::
|
|
233
|
+
|
|
234
|
+
sage: x = PolynomialRing(Integers(100), 'x', implementation='NTL').0
|
|
235
|
+
sage: (x - 2)*(x^2 - 8*x + 16)
|
|
236
|
+
x^3 + 90*x^2 + 32*x + 68
|
|
237
|
+
"""
|
|
238
|
+
return self.parent()(self._poly * (<Polynomial_dense_mod_n>right)._poly, construct=True)
|
|
239
|
+
|
|
240
|
+
cpdef _lmul_(self, Element c):
|
|
241
|
+
try:
|
|
242
|
+
return self.parent()(ZZ_pX([c], self.parent().modulus()) * self._poly, construct=True)
|
|
243
|
+
except RuntimeError as msg: # should this really be a TypeError
|
|
244
|
+
raise TypeError(msg)
|
|
245
|
+
|
|
246
|
+
@coerce_binop
|
|
247
|
+
def quo_rem(self, right):
|
|
248
|
+
"""
|
|
249
|
+
Return a tuple ``(quotient, remainder)`` where ``self = quotient*other +
|
|
250
|
+
remainder``.
|
|
251
|
+
"""
|
|
252
|
+
v = self._poly.quo_rem((<Polynomial_dense_mod_n>right)._poly)
|
|
253
|
+
P = self.parent()
|
|
254
|
+
return (P(v[0], construct=True), P(v[1], construct=True) )
|
|
255
|
+
|
|
256
|
+
def shift(self, n):
|
|
257
|
+
r"""
|
|
258
|
+
Return this polynomial multiplied by the power `x^n`. If `n` is negative,
|
|
259
|
+
terms below `x^n` will be discarded. Does not change this polynomial.
|
|
260
|
+
|
|
261
|
+
EXAMPLES::
|
|
262
|
+
|
|
263
|
+
sage: R.<x> = PolynomialRing(Integers(12345678901234567890), implementation='NTL')
|
|
264
|
+
sage: p = x^2 + 2*x + 4
|
|
265
|
+
sage: p.shift(0)
|
|
266
|
+
x^2 + 2*x + 4
|
|
267
|
+
sage: p.shift(-1)
|
|
268
|
+
x + 2
|
|
269
|
+
sage: p.shift(-5)
|
|
270
|
+
0
|
|
271
|
+
sage: p.shift(2)
|
|
272
|
+
x^4 + 2*x^3 + 4*x^2
|
|
273
|
+
|
|
274
|
+
TESTS::
|
|
275
|
+
|
|
276
|
+
sage: p = R(0)
|
|
277
|
+
sage: p.shift(3).is_zero()
|
|
278
|
+
True
|
|
279
|
+
sage: p.shift(-3).is_zero()
|
|
280
|
+
True
|
|
281
|
+
|
|
282
|
+
AUTHOR:
|
|
283
|
+
|
|
284
|
+
- David Harvey (2006-08-06)
|
|
285
|
+
"""
|
|
286
|
+
if n == 0 or self.degree() < 0:
|
|
287
|
+
return self
|
|
288
|
+
return self.parent()(self._poly.left_shift(n),
|
|
289
|
+
construct=True)
|
|
290
|
+
|
|
291
|
+
cpdef _sub_(self, right):
|
|
292
|
+
return self.parent()(self._poly - (<Polynomial_dense_mod_n>right)._poly, construct=True)
|
|
293
|
+
|
|
294
|
+
def __floordiv__(self, right):
|
|
295
|
+
q, _ = self.quo_rem(right)
|
|
296
|
+
return q
|
|
297
|
+
|
|
298
|
+
def degree(self, gen=None):
|
|
299
|
+
"""
|
|
300
|
+
Return the degree of this polynomial.
|
|
301
|
+
|
|
302
|
+
The zero polynomial has degree -1.
|
|
303
|
+
|
|
304
|
+
EXAMPLES::
|
|
305
|
+
|
|
306
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
307
|
+
sage: (x^3 + 3*x - 17).degree()
|
|
308
|
+
3
|
|
309
|
+
sage: R.zero().degree()
|
|
310
|
+
-1
|
|
311
|
+
|
|
312
|
+
TESTS:
|
|
313
|
+
|
|
314
|
+
Check output type (see :issue:`25182`)::
|
|
315
|
+
|
|
316
|
+
sage: R.<x> = PolynomialRing(Integers(3), implementation='NTL')
|
|
317
|
+
sage: isinstance(x.degree(), Integer)
|
|
318
|
+
True
|
|
319
|
+
"""
|
|
320
|
+
return smallInteger(max(self._poly.degree(), -1))
|
|
321
|
+
|
|
322
|
+
cpdef list list(self, bint copy=True):
|
|
323
|
+
"""
|
|
324
|
+
Return a new copy of the list of the underlying
|
|
325
|
+
elements of ``self``.
|
|
326
|
+
|
|
327
|
+
EXAMPLES::
|
|
328
|
+
|
|
329
|
+
sage: _.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
330
|
+
sage: f = x^3 + 3*x - 17
|
|
331
|
+
sage: f.list()
|
|
332
|
+
[83, 3, 0, 1]
|
|
333
|
+
"""
|
|
334
|
+
return [self.get_unsafe(n) for n from 0 <= n <= self.degree()]
|
|
335
|
+
|
|
336
|
+
def ntl_set_directly(self, v):
|
|
337
|
+
r"""
|
|
338
|
+
Set the value of this polynomial directly from a vector or string.
|
|
339
|
+
|
|
340
|
+
Polynomials over the integers modulo n are stored internally using
|
|
341
|
+
NTL's ``ZZ_pX`` class. Use this function to set the value of this
|
|
342
|
+
polynomial using the NTL constructor, which is potentially *very* fast.
|
|
343
|
+
The input v is either a vector of ints or a string of the form ``[ n1
|
|
344
|
+
n2 n3 ... ]`` where the ni are integers and there are no commas between
|
|
345
|
+
them. The optimal input format is the string format, since that's what
|
|
346
|
+
NTL uses by default.
|
|
347
|
+
|
|
348
|
+
EXAMPLES::
|
|
349
|
+
|
|
350
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
351
|
+
sage: from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_mod_n as poly_modn_dense
|
|
352
|
+
sage: poly_modn_dense(R, ([1,-2,3]))
|
|
353
|
+
3*x^2 + 98*x + 1
|
|
354
|
+
sage: f = poly_modn_dense(R, 0)
|
|
355
|
+
sage: f.ntl_set_directly([1,-2,3])
|
|
356
|
+
sage: f
|
|
357
|
+
3*x^2 + 98*x + 1
|
|
358
|
+
sage: f.ntl_set_directly('[1 -2 3 4]')
|
|
359
|
+
sage: f
|
|
360
|
+
4*x^3 + 3*x^2 + 98*x + 1
|
|
361
|
+
"""
|
|
362
|
+
if self.is_gen():
|
|
363
|
+
raise TypeError("Cannot change the value of the generator.")
|
|
364
|
+
self._poly = ZZ_pX(v, self.parent().modulus())
|
|
365
|
+
|
|
366
|
+
# Polynomial_singular_repr stuff, copied due to lack of multiple inheritance
|
|
367
|
+
def _singular_(self, singular=None, force=False):
|
|
368
|
+
self.parent()._singular_(singular, force=force).set_ring() # this is expensive
|
|
369
|
+
if self.__singular is not None:
|
|
370
|
+
try:
|
|
371
|
+
self.__singular._check_valid()
|
|
372
|
+
if self.__singular.parent() is singular:
|
|
373
|
+
return self.__singular
|
|
374
|
+
except (AttributeError, ValueError):
|
|
375
|
+
pass
|
|
376
|
+
return self._singular_init_(singular)
|
|
377
|
+
|
|
378
|
+
def _singular_init_(self, singular=None, force=False):
|
|
379
|
+
self.parent()._singular_(singular, force=force).set_ring() # this is expensive
|
|
380
|
+
self.__singular = singular(str(self))
|
|
381
|
+
return self.__singular
|
|
382
|
+
|
|
383
|
+
@coerce_binop
|
|
384
|
+
def minpoly_mod(self, other):
|
|
385
|
+
r"""
|
|
386
|
+
Compute the minimal polynomial of this polynomial modulo another
|
|
387
|
+
polynomial in the same ring.
|
|
388
|
+
|
|
389
|
+
ALGORITHM:
|
|
390
|
+
|
|
391
|
+
NTL's ``MinPolyMod()``, which uses Shoup's algorithm [Sho1999]_.
|
|
392
|
+
|
|
393
|
+
EXAMPLES::
|
|
394
|
+
|
|
395
|
+
sage: R.<x> = PolynomialRing(GF(101), implementation='NTL')
|
|
396
|
+
sage: f = x^17 + x^2 - 1
|
|
397
|
+
sage: (x^2).minpoly_mod(f)
|
|
398
|
+
x^17 + 100*x^2 + 2*x + 100
|
|
399
|
+
|
|
400
|
+
TESTS:
|
|
401
|
+
|
|
402
|
+
Random testing::
|
|
403
|
+
|
|
404
|
+
sage: # needs sage.libs.pari
|
|
405
|
+
sage: p = random_prime(2^99)
|
|
406
|
+
sage: R.<x> = PolynomialRing(GF(p), implementation='NTL')
|
|
407
|
+
sage: d = randrange(1,50)
|
|
408
|
+
sage: f = R.random_element(d)
|
|
409
|
+
sage: g = R.random_element((-1,5*d))
|
|
410
|
+
sage: poly = g.minpoly_mod(f)
|
|
411
|
+
sage: poly(R.quotient(f)(g))
|
|
412
|
+
0
|
|
413
|
+
"""
|
|
414
|
+
mod = other.ntl_ZZ_pX()
|
|
415
|
+
elt = self.ntl_ZZ_pX() % mod
|
|
416
|
+
res = elt.minpoly_mod(mod)
|
|
417
|
+
return self.parent()(res, construct=True)
|
|
418
|
+
|
|
419
|
+
def small_roots(self, *args, **kwds):
|
|
420
|
+
r"""
|
|
421
|
+
See :func:`sage.rings.polynomial.polynomial_modn_dense_ntl.small_roots`
|
|
422
|
+
for the documentation of this function.
|
|
423
|
+
|
|
424
|
+
EXAMPLES::
|
|
425
|
+
|
|
426
|
+
sage: # needs sage.libs.pari
|
|
427
|
+
sage: N = 10001
|
|
428
|
+
sage: K = Zmod(10001)
|
|
429
|
+
sage: P.<x> = PolynomialRing(K, implementation='NTL')
|
|
430
|
+
sage: f = x^3 + 10*x^2 + 5000*x - 222
|
|
431
|
+
sage: f.small_roots() # needs fpylll
|
|
432
|
+
[4]
|
|
433
|
+
"""
|
|
434
|
+
return small_roots(self, *args, **kwds)
|
|
435
|
+
|
|
436
|
+
def compose_mod(self, other, modulus):
|
|
437
|
+
r"""
|
|
438
|
+
Compute `f(g) \pmod h`.
|
|
439
|
+
|
|
440
|
+
To be precise about the order fo compostion, given ``self``, ``other``
|
|
441
|
+
and ``modulus`` as `f(x)`, `g(x)` and `h(x)` compute `f(g(x)) \bmod h(x)`.
|
|
442
|
+
|
|
443
|
+
INPUT:
|
|
444
|
+
|
|
445
|
+
- ``other`` -- a polynomial `g(x)`
|
|
446
|
+
- ``modulus`` -- a polynomial `h(x)`
|
|
447
|
+
|
|
448
|
+
EXAMPLES::
|
|
449
|
+
|
|
450
|
+
sage: # needs sage.rings.finite_rings
|
|
451
|
+
sage: R.<x> = GF(2**127 - 1)[]
|
|
452
|
+
sage: f = R.random_element()
|
|
453
|
+
sage: g = R.random_element()
|
|
454
|
+
sage: g.compose_mod(g, f) == g(g) % f
|
|
455
|
+
True
|
|
456
|
+
|
|
457
|
+
sage: R.<x> = GF(163)[]
|
|
458
|
+
sage: f = R([i for i in range(100)])
|
|
459
|
+
sage: g = R([i**2 for i in range(100)])
|
|
460
|
+
sage: h = 1 + x + x**5
|
|
461
|
+
sage: f.compose_mod(g, h)
|
|
462
|
+
82*x^4 + 56*x^3 + 45*x^2 + 60*x + 127
|
|
463
|
+
sage: f.compose_mod(g, h) == f(g) % h
|
|
464
|
+
True
|
|
465
|
+
|
|
466
|
+
AUTHORS:
|
|
467
|
+
|
|
468
|
+
- Giacomo Pope (2024-08) initial implementation
|
|
469
|
+
"""
|
|
470
|
+
elt = self.ntl_ZZ_pX()
|
|
471
|
+
mod = modulus.ntl_ZZ_pX()
|
|
472
|
+
other = other.ntl_ZZ_pX()
|
|
473
|
+
res = elt.compose_mod(other, mod)
|
|
474
|
+
return self.parent()(res, construct=True)
|
|
475
|
+
|
|
476
|
+
# compose_mod is the natural name from the NTL bindings, but polynomial_gf2x
|
|
477
|
+
# has modular_composition as the method name so here we allow both
|
|
478
|
+
modular_composition = compose_mod
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def small_roots(self, X=None, beta=1.0, epsilon=None, **kwds):
|
|
482
|
+
r"""
|
|
483
|
+
Let `N` be the characteristic of the base ring this polynomial
|
|
484
|
+
is defined over: ``N = self.base_ring().characteristic()``.
|
|
485
|
+
This method returns small roots of this polynomial modulo some
|
|
486
|
+
factor `b` of `N` with the constraint that `b >= N^\beta`.
|
|
487
|
+
Small in this context means that if `x` is a root of `f`
|
|
488
|
+
modulo `b` then `|x| < X`. This `X` is either provided by the
|
|
489
|
+
user or the maximum `X` is chosen such that this algorithm
|
|
490
|
+
terminates in polynomial time. If `X` is chosen automatically
|
|
491
|
+
it is `X = ceil(1/2 N^{\beta^2/\delta - \epsilon})`.
|
|
492
|
+
The algorithm may also return some roots which are larger than `X`.
|
|
493
|
+
'This algorithm' in this context means Coppersmith's algorithm for finding
|
|
494
|
+
small roots using the LLL algorithm. The implementation of this algorithm
|
|
495
|
+
follows Alexander May's PhD thesis referenced below.
|
|
496
|
+
|
|
497
|
+
INPUT:
|
|
498
|
+
|
|
499
|
+
- ``X`` -- an absolute bound for the root (default: see above)
|
|
500
|
+
- ``beta`` -- compute a root mod `b` where `b` is a factor of `N` and `b
|
|
501
|
+
\ge N^\beta` (default: 1.0, so `b = N`.)
|
|
502
|
+
- ``epsilon`` -- the parameter `\epsilon` described above. (default: `\beta/8`)
|
|
503
|
+
- ``**kwds`` -- passed through to method :meth:`Matrix_integer_dense.LLL() <sage.matrix.matrix_integer_dense.Matrix_integer_dense.LLL>`
|
|
504
|
+
|
|
505
|
+
EXAMPLES:
|
|
506
|
+
|
|
507
|
+
First consider a small example::
|
|
508
|
+
|
|
509
|
+
sage: # needs sage.libs.pari
|
|
510
|
+
sage: N = 10001
|
|
511
|
+
sage: K = Zmod(10001)
|
|
512
|
+
sage: P.<x> = PolynomialRing(K, implementation='NTL')
|
|
513
|
+
sage: f = x^3 + 10*x^2 + 5000*x - 222
|
|
514
|
+
|
|
515
|
+
This polynomial has no roots without modular reduction (i.e. over `\ZZ`)::
|
|
516
|
+
|
|
517
|
+
sage: f.change_ring(ZZ).roots() # needs sage.libs.pari
|
|
518
|
+
[]
|
|
519
|
+
|
|
520
|
+
To compute its roots we need to factor the modulus `N` and use the Chinese
|
|
521
|
+
remainder theorem::
|
|
522
|
+
|
|
523
|
+
sage: # needs sage.libs.pari
|
|
524
|
+
sage: p, q = N.prime_divisors()
|
|
525
|
+
sage: f.change_ring(GF(p)).roots()
|
|
526
|
+
[(4, 1)]
|
|
527
|
+
sage: f.change_ring(GF(q)).roots()
|
|
528
|
+
[(4, 1)]
|
|
529
|
+
sage: crt(4, 4, p, q)
|
|
530
|
+
4
|
|
531
|
+
|
|
532
|
+
This root is quite small compared to `N`, so we can attempt to
|
|
533
|
+
recover it without factoring `N` using Coppersmith's small root
|
|
534
|
+
method::
|
|
535
|
+
|
|
536
|
+
sage: f.small_roots() # needs fpylll sage.libs.pari
|
|
537
|
+
[4]
|
|
538
|
+
|
|
539
|
+
An application of this method is to consider RSA. We are using 512-bit RSA
|
|
540
|
+
with public exponent `e=3` to encrypt a 56-bit DES key. Because it would be
|
|
541
|
+
easy to attack this setting if no padding was used we pad the key `K` with
|
|
542
|
+
1s to get a large number::
|
|
543
|
+
|
|
544
|
+
sage: Nbits, Kbits = 512, 56
|
|
545
|
+
sage: e = 3
|
|
546
|
+
|
|
547
|
+
We choose two primes of size 256-bit each::
|
|
548
|
+
|
|
549
|
+
sage: p = 2^256 + 2^8 + 2^5 + 2^3 + 1
|
|
550
|
+
sage: q = 2^256 + 2^8 + 2^5 + 2^3 + 2^2 + 1
|
|
551
|
+
sage: N = p*q
|
|
552
|
+
sage: ZmodN = Zmod( N )
|
|
553
|
+
|
|
554
|
+
We choose a random key::
|
|
555
|
+
|
|
556
|
+
sage: K = ZZ.random_element(0, 2^Kbits)
|
|
557
|
+
|
|
558
|
+
and pad it with `512-56=456` 1s::
|
|
559
|
+
|
|
560
|
+
sage: Kdigits = K.digits(2)
|
|
561
|
+
sage: M = [0]*Kbits + [1]*(Nbits-Kbits)
|
|
562
|
+
sage: for i in range(len(Kdigits)): M[i] = Kdigits[i]
|
|
563
|
+
|
|
564
|
+
sage: M = ZZ(M, 2)
|
|
565
|
+
|
|
566
|
+
Now we encrypt the resulting message::
|
|
567
|
+
|
|
568
|
+
sage: C = ZmodN(M)^e
|
|
569
|
+
|
|
570
|
+
To recover `K` we consider the following polynomial modulo `N`::
|
|
571
|
+
|
|
572
|
+
sage: P.<x> = PolynomialRing(ZmodN, implementation='NTL') # needs sage.libs.pari
|
|
573
|
+
sage: f = (2^Nbits - 2^Kbits + x)^e - C # needs sage.libs.pari
|
|
574
|
+
|
|
575
|
+
and recover its small roots::
|
|
576
|
+
|
|
577
|
+
sage: Kbar = f.small_roots()[0] # needs fpylll sage.libs.pari
|
|
578
|
+
sage: K == Kbar # needs fpylll sage.libs.pari
|
|
579
|
+
True
|
|
580
|
+
|
|
581
|
+
The same algorithm can be used to factor `N = pq` if partial
|
|
582
|
+
knowledge about `q` is available. This example is from the
|
|
583
|
+
Magma handbook:
|
|
584
|
+
|
|
585
|
+
First, we set up `p`, `q` and `N`::
|
|
586
|
+
|
|
587
|
+
sage: length = 512
|
|
588
|
+
sage: hidden = 110
|
|
589
|
+
sage: p = next_prime(2^int(round(length/2)))
|
|
590
|
+
sage: q = next_prime(round(pi.n()*p)) # needs sage.symbolic
|
|
591
|
+
sage: N = p*q # needs sage.symbolic
|
|
592
|
+
|
|
593
|
+
Now we disturb the low 110 bits of `q`::
|
|
594
|
+
|
|
595
|
+
sage: qbar = q + ZZ.random_element(0, 2^hidden - 1) # needs sage.symbolic
|
|
596
|
+
|
|
597
|
+
And try to recover `q` from it::
|
|
598
|
+
|
|
599
|
+
sage: F.<x> = PolynomialRing(Zmod(N), implementation='NTL') # needs sage.symbolic
|
|
600
|
+
sage: f = x - qbar # needs sage.symbolic
|
|
601
|
+
|
|
602
|
+
We know that the error is `\le 2^{\text{hidden}}-1` and that the modulus
|
|
603
|
+
we are looking for is `\ge \sqrt{N}`::
|
|
604
|
+
|
|
605
|
+
sage: from sage.misc.verbose import set_verbose
|
|
606
|
+
sage: set_verbose(2)
|
|
607
|
+
sage: d = f.small_roots(X=2^hidden-1, beta=0.5)[0] # time random # needs fpylll sage.symbolic
|
|
608
|
+
verbose 2 (<module>) m = 4
|
|
609
|
+
verbose 2 (<module>) t = 4
|
|
610
|
+
verbose 2 (<module>) X = 1298074214633706907132624082305023
|
|
611
|
+
verbose 1 (<module>) LLL of 8x8 matrix (algorithm fpLLL:wrapper)
|
|
612
|
+
verbose 1 (<module>) LLL finished (time = 0.006998)
|
|
613
|
+
sage: q == qbar - d # needs fpylll sage.symbolic
|
|
614
|
+
True
|
|
615
|
+
|
|
616
|
+
REFERENCES:
|
|
617
|
+
|
|
618
|
+
Don Coppersmith. *Finding a small root of a univariate modular equation.*
|
|
619
|
+
In Advances in Cryptology, EuroCrypt 1996, volume 1070 of Lecture
|
|
620
|
+
Notes in Computer Science, p. 155--165. Springer, 1996.
|
|
621
|
+
http://cr.yp.to/bib/2001/coppersmith.pdf
|
|
622
|
+
|
|
623
|
+
Alexander May. *New RSA Vulnerabilities Using Lattice Reduction Methods.*
|
|
624
|
+
PhD thesis, University of Paderborn, 2003.
|
|
625
|
+
http://www.cs.uni-paderborn.de/uploads/tx_sibibtex/bp.pdf
|
|
626
|
+
"""
|
|
627
|
+
from sage.misc.verbose import verbose
|
|
628
|
+
from sage.matrix.constructor import Matrix
|
|
629
|
+
from sage.rings.real_mpfr import RR
|
|
630
|
+
|
|
631
|
+
N = self.parent().characteristic()
|
|
632
|
+
|
|
633
|
+
if not self.is_monic():
|
|
634
|
+
raise ArithmeticError("Polynomial must be monic.")
|
|
635
|
+
|
|
636
|
+
beta = RR(beta)
|
|
637
|
+
if beta <= 0.0 or beta > 1.0:
|
|
638
|
+
raise ValueError("0.0 < beta <= 1.0 not satisfied.")
|
|
639
|
+
|
|
640
|
+
f = self.change_ring(ZZ)
|
|
641
|
+
|
|
642
|
+
_, (x,) = f.parent().objgens()
|
|
643
|
+
|
|
644
|
+
delta = f.degree()
|
|
645
|
+
|
|
646
|
+
if epsilon is None:
|
|
647
|
+
epsilon = beta/8
|
|
648
|
+
verbose("epsilon = %f" % epsilon, level=2)
|
|
649
|
+
|
|
650
|
+
m = max(beta**2/(delta * epsilon), 7*beta/delta).ceil()
|
|
651
|
+
verbose("m = %d" % m, level=2)
|
|
652
|
+
|
|
653
|
+
t = int( ( delta*m*(1/beta -1) ).floor() )
|
|
654
|
+
verbose("t = %d" % t, level=2)
|
|
655
|
+
|
|
656
|
+
if X is None:
|
|
657
|
+
X = (0.5 * N**(beta**2/delta - epsilon)).ceil()
|
|
658
|
+
verbose("X = %s" % X, level=2)
|
|
659
|
+
|
|
660
|
+
# we could do this much faster, but this is a cheap step
|
|
661
|
+
# compared to LLL
|
|
662
|
+
g = [x**j * N**(m-i) * f**i for i in range(m) for j in range(delta)]
|
|
663
|
+
g.extend([x**i * f**m for i in range(t)]) # h
|
|
664
|
+
|
|
665
|
+
B = Matrix(ZZ, len(g), delta*m + max(delta,t) )
|
|
666
|
+
for i in range(B.nrows()):
|
|
667
|
+
for j in range( g[i].degree()+1 ):
|
|
668
|
+
B[i, j] = g[i][j]*X**j
|
|
669
|
+
|
|
670
|
+
B = B.LLL(**kwds)
|
|
671
|
+
|
|
672
|
+
f = sum([ZZ(B[0, i]//X**i)*x**i for i in range(B.ncols())])
|
|
673
|
+
R = f.roots()
|
|
674
|
+
|
|
675
|
+
ZmodN = self.base_ring()
|
|
676
|
+
roots = set(ZmodN(r) for r, m in R if abs(r) <= X)
|
|
677
|
+
Nbeta = N**beta
|
|
678
|
+
return [root for root in roots if N.gcd(ZZ(self(root))) >= Nbeta]
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n):
|
|
682
|
+
r"""
|
|
683
|
+
Polynomial on `\ZZ/n\ZZ` implemented via NTL.
|
|
684
|
+
|
|
685
|
+
.. automethod:: _add_
|
|
686
|
+
.. automethod:: _sub_
|
|
687
|
+
.. automethod:: _lmul_
|
|
688
|
+
.. automethod:: _rmul_
|
|
689
|
+
.. automethod:: _mul_
|
|
690
|
+
.. automethod:: _mul_trunc_
|
|
691
|
+
"""
|
|
692
|
+
def __init__(self, parent, v=None, check=True, is_gen=False, construct=False):
|
|
693
|
+
r"""
|
|
694
|
+
EXAMPLES::
|
|
695
|
+
|
|
696
|
+
sage: R = Integers(5**21)
|
|
697
|
+
sage: S.<x> = PolynomialRing(R, implementation='NTL') # needs sage.libs.pari
|
|
698
|
+
sage: S(1/4) # needs sage.libs.pari
|
|
699
|
+
357627868652344
|
|
700
|
+
"""
|
|
701
|
+
if isinstance(v, Polynomial):
|
|
702
|
+
if (<Element>v)._parent == parent:
|
|
703
|
+
Polynomial.__init__(self, parent, is_gen=is_gen)
|
|
704
|
+
self.x = (<Polynomial_dense_modn_ntl_zz>v).x
|
|
705
|
+
self.c = (<Polynomial_dense_modn_ntl_zz>v).c
|
|
706
|
+
return
|
|
707
|
+
|
|
708
|
+
Polynomial_dense_mod_n.__init__(self, parent, v, check=check, is_gen=is_gen, construct=construct)
|
|
709
|
+
v = [a for a in self._poly.list()]
|
|
710
|
+
self._poly = None # this will eventually go away
|
|
711
|
+
cdef ntl_zz_pX ntl = ntl_zz_pX(v, parent.modulus()) # let it handle the hard work
|
|
712
|
+
self.x = ntl.x
|
|
713
|
+
self.c = ntl.c
|
|
714
|
+
|
|
715
|
+
def __dealloc__(self):
|
|
716
|
+
if <object>self.c is not None:
|
|
717
|
+
self.c.restore_c()
|
|
718
|
+
|
|
719
|
+
def ntl_set_directly(self, v):
|
|
720
|
+
# TODO: Get rid of this
|
|
721
|
+
Polynomial_dense_mod_n.ntl_set_directly(self, v)
|
|
722
|
+
# verbatim from __init__
|
|
723
|
+
v = [int(a) for a in self._poly.list()]
|
|
724
|
+
self._poly = None # this will eventually go away
|
|
725
|
+
cdef ntl_zz_pX ntl = ntl_zz_pX(v, self._parent.modulus()) # let it handle the hard work
|
|
726
|
+
self.x = ntl.x
|
|
727
|
+
self.c = ntl.c
|
|
728
|
+
|
|
729
|
+
cdef Polynomial_dense_modn_ntl_zz _new(self):
|
|
730
|
+
cdef Polynomial_dense_modn_ntl_zz y = <Polynomial_dense_modn_ntl_zz>Polynomial_dense_modn_ntl_zz.__new__(Polynomial_dense_modn_ntl_zz)
|
|
731
|
+
y.c = self.c
|
|
732
|
+
y._parent = self._parent
|
|
733
|
+
return y
|
|
734
|
+
|
|
735
|
+
def int_list(self):
|
|
736
|
+
"""
|
|
737
|
+
Return the coefficients of ``self`` as efficiently as possible as a
|
|
738
|
+
list of python ints.
|
|
739
|
+
|
|
740
|
+
EXAMPLES::
|
|
741
|
+
|
|
742
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
743
|
+
sage: from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_mod_n as poly_modn_dense
|
|
744
|
+
sage: f = poly_modn_dense(R,[5,0,0,1])
|
|
745
|
+
sage: f.int_list()
|
|
746
|
+
[5, 0, 0, 1]
|
|
747
|
+
sage: [type(a) for a in f.int_list()]
|
|
748
|
+
[<... 'int'>, <... 'int'>, <... 'int'>, <... 'int'>]
|
|
749
|
+
"""
|
|
750
|
+
cdef long i
|
|
751
|
+
return [ zz_p_rep(zz_pX_GetCoeff(self.x, i)) for i from 0 <= i <= zz_pX_deg(self.x) ]
|
|
752
|
+
|
|
753
|
+
cdef get_unsafe(self, Py_ssize_t n):
|
|
754
|
+
"""
|
|
755
|
+
Return the `n`-th coefficient of ``self``.
|
|
756
|
+
|
|
757
|
+
EXAMPLES::
|
|
758
|
+
|
|
759
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
760
|
+
sage: from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_modn_ntl_zz
|
|
761
|
+
sage: f = Polynomial_dense_modn_ntl_zz(R,[2, 1])^7
|
|
762
|
+
sage: f[3]
|
|
763
|
+
60
|
|
764
|
+
sage: f[:6]
|
|
765
|
+
84*x^5 + 80*x^4 + 60*x^3 + 72*x^2 + 48*x + 28
|
|
766
|
+
sage: f[:50] == f
|
|
767
|
+
True
|
|
768
|
+
"""
|
|
769
|
+
return self._parent._base(zz_p_rep(zz_pX_GetCoeff(self.x, n)))
|
|
770
|
+
|
|
771
|
+
def _unsafe_mutate(self, n, value):
|
|
772
|
+
self.c.restore_c()
|
|
773
|
+
zz_pX_SetCoeff_long(self.x, n, value)
|
|
774
|
+
|
|
775
|
+
cpdef _add_(self, _right):
|
|
776
|
+
"""
|
|
777
|
+
TESTS::
|
|
778
|
+
|
|
779
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
780
|
+
sage: (x + 5) + (x^2 - 6)
|
|
781
|
+
x^2 + x + 99
|
|
782
|
+
"""
|
|
783
|
+
cdef Polynomial_dense_modn_ntl_zz right = <Polynomial_dense_modn_ntl_zz>_right
|
|
784
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
785
|
+
cdef bint do_sig = zz_pX_deg(self.x) + zz_pX_deg(right.x) > 1000000
|
|
786
|
+
if do_sig: sig_on()
|
|
787
|
+
self.c.restore_c()
|
|
788
|
+
zz_pX_add(r.x, self.x, right.x)
|
|
789
|
+
if do_sig: sig_off()
|
|
790
|
+
return r
|
|
791
|
+
|
|
792
|
+
cpdef _sub_(self, _right):
|
|
793
|
+
"""
|
|
794
|
+
TESTS::
|
|
795
|
+
|
|
796
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
797
|
+
sage: (x + 5) - (x^2 - 6)
|
|
798
|
+
99*x^2 + x + 11
|
|
799
|
+
"""
|
|
800
|
+
cdef Polynomial_dense_modn_ntl_zz right = <Polynomial_dense_modn_ntl_zz>_right
|
|
801
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
802
|
+
cdef bint do_sig = zz_pX_deg(self.x) + zz_pX_deg(right.x) > 1000000
|
|
803
|
+
if do_sig: sig_on()
|
|
804
|
+
self.c.restore_c()
|
|
805
|
+
zz_pX_sub(r.x, self.x, right.x)
|
|
806
|
+
if do_sig: sig_off()
|
|
807
|
+
return r
|
|
808
|
+
|
|
809
|
+
cpdef _mul_(self, _right):
|
|
810
|
+
"""
|
|
811
|
+
TESTS::
|
|
812
|
+
|
|
813
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
814
|
+
sage: (x + 5) * (x^2 - 1)
|
|
815
|
+
x^3 + 5*x^2 + 99*x + 95
|
|
816
|
+
"""
|
|
817
|
+
cdef Polynomial_dense_modn_ntl_zz right = <Polynomial_dense_modn_ntl_zz>_right
|
|
818
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
819
|
+
cdef bint do_sig = zz_pX_deg(self.x) + zz_pX_deg(right.x) > 10000
|
|
820
|
+
if do_sig: sig_on()
|
|
821
|
+
self.c.restore_c()
|
|
822
|
+
if self is right:
|
|
823
|
+
zz_pX_sqr(r.x, self.x)
|
|
824
|
+
else:
|
|
825
|
+
zz_pX_mul(r.x, self.x, right.x)
|
|
826
|
+
if do_sig: sig_off()
|
|
827
|
+
return r
|
|
828
|
+
|
|
829
|
+
cpdef Polynomial _mul_trunc_(self, Polynomial right, long n):
|
|
830
|
+
r"""
|
|
831
|
+
Return the product of ``self`` and ``right`` truncated to the
|
|
832
|
+
given length `n`
|
|
833
|
+
|
|
834
|
+
EXAMPLES::
|
|
835
|
+
|
|
836
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation="NTL")
|
|
837
|
+
sage: f = x - 2
|
|
838
|
+
sage: g = x^2 - 8*x + 16
|
|
839
|
+
sage: f*g
|
|
840
|
+
x^3 + 90*x^2 + 32*x + 68
|
|
841
|
+
sage: f._mul_trunc_(g, 42)
|
|
842
|
+
x^3 + 90*x^2 + 32*x + 68
|
|
843
|
+
sage: f._mul_trunc_(g, 3)
|
|
844
|
+
90*x^2 + 32*x + 68
|
|
845
|
+
sage: f._mul_trunc_(g, 2)
|
|
846
|
+
32*x + 68
|
|
847
|
+
sage: f._mul_trunc_(g, 1)
|
|
848
|
+
68
|
|
849
|
+
sage: f._mul_trunc_(g, 0)
|
|
850
|
+
0
|
|
851
|
+
sage: f = x^2 - 8*x + 16
|
|
852
|
+
sage: f._mul_trunc_(f, 2)
|
|
853
|
+
44*x + 56
|
|
854
|
+
"""
|
|
855
|
+
cdef Polynomial_dense_modn_ntl_zz op2 = <Polynomial_dense_modn_ntl_zz> right
|
|
856
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
857
|
+
cdef bint do_sig = zz_pX_deg(self.x) + zz_pX_deg(op2.x) > 10000
|
|
858
|
+
if do_sig: sig_on()
|
|
859
|
+
self.c.restore_c()
|
|
860
|
+
if self is op2:
|
|
861
|
+
zz_pX_SqrTrunc(r.x, self.x, n)
|
|
862
|
+
else:
|
|
863
|
+
zz_pX_MulTrunc(r.x, self.x, op2.x, n)
|
|
864
|
+
if do_sig: sig_off()
|
|
865
|
+
return r
|
|
866
|
+
|
|
867
|
+
cpdef _rmul_(self, Element c):
|
|
868
|
+
"""
|
|
869
|
+
TESTS::
|
|
870
|
+
|
|
871
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
872
|
+
sage: (x+5) * 3
|
|
873
|
+
3*x + 15
|
|
874
|
+
"""
|
|
875
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
876
|
+
cdef bint do_sig = zz_pX_deg(self.x) > 100000
|
|
877
|
+
if do_sig: sig_on()
|
|
878
|
+
self.c.restore_c()
|
|
879
|
+
zz_pX_rmul(r.x, self.x, c)
|
|
880
|
+
if do_sig: sig_off()
|
|
881
|
+
return r
|
|
882
|
+
|
|
883
|
+
cpdef _lmul_(self, Element c):
|
|
884
|
+
"""
|
|
885
|
+
TESTS::
|
|
886
|
+
|
|
887
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
888
|
+
sage: 3 * (x+5)
|
|
889
|
+
3*x + 15
|
|
890
|
+
"""
|
|
891
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
892
|
+
cdef bint do_sig = zz_pX_deg(self.x) > 100000
|
|
893
|
+
if do_sig: sig_on()
|
|
894
|
+
self.c.restore_c()
|
|
895
|
+
zz_pX_lmul(r.x, c, self.x)
|
|
896
|
+
if do_sig: sig_off()
|
|
897
|
+
return r
|
|
898
|
+
|
|
899
|
+
def __pow__(Polynomial_dense_modn_ntl_zz self, ee, modulus):
|
|
900
|
+
r"""
|
|
901
|
+
TESTS::
|
|
902
|
+
|
|
903
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
904
|
+
sage: (x-1)^5
|
|
905
|
+
x^5 + 95*x^4 + 10*x^3 + 90*x^2 + 5*x + 99
|
|
906
|
+
|
|
907
|
+
We define ``0^0`` to be unity, :issue:`13895`::
|
|
908
|
+
|
|
909
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
910
|
+
sage: R(0)^0
|
|
911
|
+
1
|
|
912
|
+
|
|
913
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
914
|
+
|
|
915
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
916
|
+
sage: type(R(0)^0) == type(R(0))
|
|
917
|
+
True
|
|
918
|
+
|
|
919
|
+
Negative powers work (over prime fields) but use the generic
|
|
920
|
+
implementation of fraction fields::
|
|
921
|
+
|
|
922
|
+
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
|
|
923
|
+
sage: f = (x-1)^(-5)
|
|
924
|
+
sage: type(f)
|
|
925
|
+
<class 'sage.rings.fraction_field_element.FractionFieldElement_1poly_field'>
|
|
926
|
+
sage: (f + 2).numerator()
|
|
927
|
+
2*x^5 + 91*x^4 + 20*x^3 + 81*x^2 + 10*x + 100
|
|
928
|
+
|
|
929
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
930
|
+
sage: (x-1)^(-5)
|
|
931
|
+
Traceback (most recent call last):
|
|
932
|
+
...
|
|
933
|
+
TypeError: ...
|
|
934
|
+
"""
|
|
935
|
+
cdef bint recip = 0, do_sig
|
|
936
|
+
cdef long e = ee
|
|
937
|
+
if e != ee:
|
|
938
|
+
raise TypeError("Only integral powers defined.")
|
|
939
|
+
elif e < 0:
|
|
940
|
+
recip = 1
|
|
941
|
+
e = -e
|
|
942
|
+
if self == 0 and e == 0:
|
|
943
|
+
return self.parent(1)
|
|
944
|
+
|
|
945
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
946
|
+
cdef zz_pX_Modulus_c mod
|
|
947
|
+
|
|
948
|
+
self.c.restore_c()
|
|
949
|
+
|
|
950
|
+
if modulus is None:
|
|
951
|
+
if zz_pX_IsX(self.x):
|
|
952
|
+
zz_pX_LeftShift(r.x, self.x, e-1)
|
|
953
|
+
else:
|
|
954
|
+
do_sig = zz_pX_deg(self.x) *e > 1000
|
|
955
|
+
if do_sig: sig_on()
|
|
956
|
+
zz_pX_power(r.x, self.x, e)
|
|
957
|
+
if do_sig: sig_off()
|
|
958
|
+
else:
|
|
959
|
+
if not isinstance(modulus, Polynomial_dense_modn_ntl_zz):
|
|
960
|
+
modulus = self.parent().coerce(modulus)
|
|
961
|
+
zz_pX_Modulus_build(mod, (<Polynomial_dense_modn_ntl_zz>modulus).x)
|
|
962
|
+
|
|
963
|
+
do_sig = zz_pX_deg(self.x) * e * self.c.p_bits > 1e5
|
|
964
|
+
if do_sig: sig_on()
|
|
965
|
+
zz_pX_PowerMod_long_pre(r.x, self.x, e, mod)
|
|
966
|
+
if do_sig: sig_off()
|
|
967
|
+
|
|
968
|
+
if recip:
|
|
969
|
+
return ~r
|
|
970
|
+
else:
|
|
971
|
+
return r
|
|
972
|
+
|
|
973
|
+
@coerce_binop
|
|
974
|
+
def quo_rem(self, right):
|
|
975
|
+
r"""
|
|
976
|
+
Return `q` and `r`, with the degree of `r` less than the degree of ``right``,
|
|
977
|
+
such that `q \cdot` ``right`` `{}+ r =` ``self``.
|
|
978
|
+
|
|
979
|
+
EXAMPLES::
|
|
980
|
+
|
|
981
|
+
sage: R.<x> = PolynomialRing(Integers(125), implementation='NTL')
|
|
982
|
+
sage: f = x^5+1; g = (x+1)^2
|
|
983
|
+
sage: q, r = f.quo_rem(g)
|
|
984
|
+
sage: q
|
|
985
|
+
x^3 + 123*x^2 + 3*x + 121
|
|
986
|
+
sage: r
|
|
987
|
+
5*x + 5
|
|
988
|
+
sage: q*g + r
|
|
989
|
+
x^5 + 1
|
|
990
|
+
"""
|
|
991
|
+
cdef Polynomial_dense_modn_ntl_zz q = self._new()
|
|
992
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
993
|
+
cdef Polynomial_dense_modn_ntl_zz denom = <Polynomial_dense_modn_ntl_zz>right
|
|
994
|
+
sig_on()
|
|
995
|
+
self.c.restore_c()
|
|
996
|
+
zz_pX_divrem(q.x, r.x, self.x, denom.x)
|
|
997
|
+
sig_off()
|
|
998
|
+
return q, r
|
|
999
|
+
|
|
1000
|
+
cpdef _floordiv_(self, right):
|
|
1001
|
+
"""
|
|
1002
|
+
Return the whole part of ``self``/``right``, without remainder.
|
|
1003
|
+
|
|
1004
|
+
For q = n // d, we have deg(n - q*d) < deg(d)
|
|
1005
|
+
|
|
1006
|
+
EXAMPLES::
|
|
1007
|
+
|
|
1008
|
+
sage: R.<x> = PolynomialRing(Integers(25), implementation='NTL')
|
|
1009
|
+
sage: f = x^7 + 1; g = x^2 - 1
|
|
1010
|
+
sage: q = f // g; q
|
|
1011
|
+
x^5 + x^3 + x
|
|
1012
|
+
sage: f - q*g
|
|
1013
|
+
x + 1
|
|
1014
|
+
"""
|
|
1015
|
+
cdef Polynomial_dense_modn_ntl_zz numer = <Polynomial_dense_modn_ntl_zz>self
|
|
1016
|
+
cdef Polynomial_dense_modn_ntl_zz denom = <Polynomial_dense_modn_ntl_zz>right
|
|
1017
|
+
cdef Polynomial_dense_modn_ntl_zz q = numer._new()
|
|
1018
|
+
sig_on()
|
|
1019
|
+
numer.c.restore_c()
|
|
1020
|
+
zz_pX_div(q.x, numer.x, denom.x)
|
|
1021
|
+
sig_off()
|
|
1022
|
+
return q
|
|
1023
|
+
|
|
1024
|
+
cpdef _mod_(self, right):
|
|
1025
|
+
"""
|
|
1026
|
+
EXAMPLES::
|
|
1027
|
+
|
|
1028
|
+
sage: R.<x> = PolynomialRing(Integers(81), implementation='NTL')
|
|
1029
|
+
sage: f = x^7 + x + 1; g = x^3
|
|
1030
|
+
sage: r = f % g; r
|
|
1031
|
+
x + 1
|
|
1032
|
+
sage: g * x^4 + r
|
|
1033
|
+
x^7 + x + 1
|
|
1034
|
+
"""
|
|
1035
|
+
cdef Polynomial_dense_modn_ntl_zz numer = <Polynomial_dense_modn_ntl_zz>self
|
|
1036
|
+
cdef Polynomial_dense_modn_ntl_zz denom = <Polynomial_dense_modn_ntl_zz>right
|
|
1037
|
+
cdef Polynomial_dense_modn_ntl_zz r = numer._new()
|
|
1038
|
+
sig_on()
|
|
1039
|
+
numer.c.restore_c()
|
|
1040
|
+
zz_pX_mod(r.x, numer.x, denom.x)
|
|
1041
|
+
sig_off()
|
|
1042
|
+
return r
|
|
1043
|
+
|
|
1044
|
+
def shift(self, n):
|
|
1045
|
+
"""
|
|
1046
|
+
Shift ``self`` to left by `n`, which is multiplication by `x^n`,
|
|
1047
|
+
truncating if `n` is negative.
|
|
1048
|
+
|
|
1049
|
+
EXAMPLES::
|
|
1050
|
+
|
|
1051
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1052
|
+
sage: f = x^7 + x + 1
|
|
1053
|
+
sage: f.shift(1)
|
|
1054
|
+
x^8 + x^2 + x
|
|
1055
|
+
sage: f.shift(-1)
|
|
1056
|
+
x^6 + 1
|
|
1057
|
+
sage: f.shift(10).shift(-10) == f
|
|
1058
|
+
True
|
|
1059
|
+
|
|
1060
|
+
TESTS::
|
|
1061
|
+
|
|
1062
|
+
sage: p = R(0)
|
|
1063
|
+
sage: p.shift(3).is_zero()
|
|
1064
|
+
True
|
|
1065
|
+
sage: p.shift(-3).is_zero()
|
|
1066
|
+
True
|
|
1067
|
+
"""
|
|
1068
|
+
return self << n
|
|
1069
|
+
|
|
1070
|
+
def __lshift__(Polynomial_dense_modn_ntl_zz self, long n):
|
|
1071
|
+
"""
|
|
1072
|
+
TESTS::
|
|
1073
|
+
|
|
1074
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1075
|
+
sage: f = x^5 + 2*x + 1
|
|
1076
|
+
sage: f << 3
|
|
1077
|
+
x^8 + 2*x^4 + x^3
|
|
1078
|
+
"""
|
|
1079
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
1080
|
+
zz_pX_LeftShift(r.x, self.x, n)
|
|
1081
|
+
return r
|
|
1082
|
+
|
|
1083
|
+
def __rshift__(Polynomial_dense_modn_ntl_zz self, long n):
|
|
1084
|
+
"""
|
|
1085
|
+
TESTS::
|
|
1086
|
+
|
|
1087
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1088
|
+
sage: f = x^5 + 2*x + 1
|
|
1089
|
+
sage: f >> 3
|
|
1090
|
+
x^2
|
|
1091
|
+
"""
|
|
1092
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
1093
|
+
zz_pX_RightShift(r.x, self.x, n)
|
|
1094
|
+
return r
|
|
1095
|
+
|
|
1096
|
+
def _derivative(self, var=None):
|
|
1097
|
+
r"""
|
|
1098
|
+
Return the formal derivative of ``self`` with respect to ``var``.
|
|
1099
|
+
|
|
1100
|
+
``var`` must be either the generator of the polynomial ring to which
|
|
1101
|
+
this polynomial belongs, or ``None`` (either way the behaviour is the
|
|
1102
|
+
same).
|
|
1103
|
+
|
|
1104
|
+
.. SEEALSO:: :meth:`.derivative`
|
|
1105
|
+
|
|
1106
|
+
EXAMPLES::
|
|
1107
|
+
|
|
1108
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1109
|
+
sage: f = x^4 - x - 1
|
|
1110
|
+
sage: f._derivative()
|
|
1111
|
+
4*x^3 + 76
|
|
1112
|
+
sage: f._derivative(None)
|
|
1113
|
+
4*x^3 + 76
|
|
1114
|
+
|
|
1115
|
+
sage: f._derivative(2*x)
|
|
1116
|
+
Traceback (most recent call last):
|
|
1117
|
+
...
|
|
1118
|
+
ValueError: cannot differentiate with respect to 2*x
|
|
1119
|
+
|
|
1120
|
+
TESTS::
|
|
1121
|
+
|
|
1122
|
+
sage: y = var("y") # needs sage.symbolic
|
|
1123
|
+
sage: f._derivative(y) # needs sage.symbolic
|
|
1124
|
+
Traceback (most recent call last):
|
|
1125
|
+
...
|
|
1126
|
+
ValueError: cannot differentiate with respect to y
|
|
1127
|
+
"""
|
|
1128
|
+
if var is not None and var != self._parent.gen():
|
|
1129
|
+
raise ValueError('cannot differentiate with respect to {}'.format(var))
|
|
1130
|
+
|
|
1131
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
1132
|
+
zz_pX_diff(r.x, self.x)
|
|
1133
|
+
return r
|
|
1134
|
+
|
|
1135
|
+
def reverse(self, degree=None):
|
|
1136
|
+
"""
|
|
1137
|
+
Return the reverse of the input polynomial thought as a polynomial of
|
|
1138
|
+
degree ``degree``.
|
|
1139
|
+
|
|
1140
|
+
If `f` is a degree-`d` polynomial, its reverse is `x^d f(1/x)`.
|
|
1141
|
+
|
|
1142
|
+
INPUT:
|
|
1143
|
+
|
|
1144
|
+
- ``degree`` -- ``None`` or integer; if specified, truncate or zero
|
|
1145
|
+
pad the list of coefficients to this degree before reversing it
|
|
1146
|
+
|
|
1147
|
+
EXAMPLES::
|
|
1148
|
+
|
|
1149
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1150
|
+
sage: f = x^4 - x - 1
|
|
1151
|
+
sage: f.reverse()
|
|
1152
|
+
76*x^4 + 76*x^3 + 1
|
|
1153
|
+
sage: f.reverse(2)
|
|
1154
|
+
76*x^2 + 76*x
|
|
1155
|
+
sage: f.reverse(5)
|
|
1156
|
+
76*x^5 + 76*x^4 + x
|
|
1157
|
+
sage: g = x^3 - x
|
|
1158
|
+
sage: g.reverse()
|
|
1159
|
+
76*x^2 + 1
|
|
1160
|
+
|
|
1161
|
+
TESTS:
|
|
1162
|
+
|
|
1163
|
+
We check that this implementation is compatible with the generic one::
|
|
1164
|
+
|
|
1165
|
+
sage: all(f.reverse(d) == Polynomial.reverse(f, d)
|
|
1166
|
+
....: for d in [None, 0, 1, 2, 3, 4, 5])
|
|
1167
|
+
True
|
|
1168
|
+
"""
|
|
1169
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
1170
|
+
|
|
1171
|
+
if degree is None:
|
|
1172
|
+
zz_pX_reverse(r.x, self.x)
|
|
1173
|
+
else:
|
|
1174
|
+
zz_pX_reverse_hi(r.x, self.x, degree)
|
|
1175
|
+
return r
|
|
1176
|
+
|
|
1177
|
+
def is_gen(self):
|
|
1178
|
+
return zz_pX_IsX(self.x)
|
|
1179
|
+
|
|
1180
|
+
def __bool__(self):
|
|
1181
|
+
"""
|
|
1182
|
+
TESTS::
|
|
1183
|
+
|
|
1184
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1185
|
+
sage: f = x^4 - x - 1
|
|
1186
|
+
sage: not f
|
|
1187
|
+
False
|
|
1188
|
+
sage: not (x-x)
|
|
1189
|
+
True
|
|
1190
|
+
"""
|
|
1191
|
+
return not zz_pX_IsZero(self.x)
|
|
1192
|
+
|
|
1193
|
+
def valuation(self):
|
|
1194
|
+
"""
|
|
1195
|
+
Return the valuation of ``self``, that is, the power of the
|
|
1196
|
+
lowest nonzero monomial of ``self``.
|
|
1197
|
+
|
|
1198
|
+
EXAMPLES::
|
|
1199
|
+
|
|
1200
|
+
sage: R.<x> = PolynomialRing(Integers(10), implementation='NTL')
|
|
1201
|
+
sage: x.valuation()
|
|
1202
|
+
1
|
|
1203
|
+
sage: f = x-3; f.valuation()
|
|
1204
|
+
0
|
|
1205
|
+
sage: f = x^99; f.valuation()
|
|
1206
|
+
99
|
|
1207
|
+
sage: f = x-x; f.valuation()
|
|
1208
|
+
+Infinity
|
|
1209
|
+
"""
|
|
1210
|
+
cdef long n
|
|
1211
|
+
for n from 0 <= n <= zz_pX_deg(self.x):
|
|
1212
|
+
if zz_p_rep(zz_pX_GetCoeff(self.x, n)):
|
|
1213
|
+
return n
|
|
1214
|
+
return infinity
|
|
1215
|
+
|
|
1216
|
+
def degree(self):
|
|
1217
|
+
"""
|
|
1218
|
+
EXAMPLES::
|
|
1219
|
+
|
|
1220
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1221
|
+
sage: f = x^4 - x - 1
|
|
1222
|
+
sage: f.degree()
|
|
1223
|
+
4
|
|
1224
|
+
sage: f = 77*x + 1
|
|
1225
|
+
sage: f.degree()
|
|
1226
|
+
0
|
|
1227
|
+
"""
|
|
1228
|
+
return zz_pX_deg(self.x)
|
|
1229
|
+
|
|
1230
|
+
cpdef Polynomial truncate(self, long n):
|
|
1231
|
+
"""
|
|
1232
|
+
Return this polynomial mod `x^n`.
|
|
1233
|
+
|
|
1234
|
+
EXAMPLES::
|
|
1235
|
+
|
|
1236
|
+
sage: R.<x> = PolynomialRing(Integers(77), implementation='NTL')
|
|
1237
|
+
sage: f = sum(x^n for n in range(10)); f
|
|
1238
|
+
x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
|
|
1239
|
+
sage: f.truncate(6)
|
|
1240
|
+
x^5 + x^4 + x^3 + x^2 + x + 1
|
|
1241
|
+
"""
|
|
1242
|
+
cdef Polynomial_dense_modn_ntl_zz r = self._new()
|
|
1243
|
+
zz_pX_trunc(r.x, self.x, n)
|
|
1244
|
+
return r
|
|
1245
|
+
|
|
1246
|
+
def __call__(self, *args, **kwds):
|
|
1247
|
+
"""
|
|
1248
|
+
Evaluate ``self`` at ``x``. If ``x`` is a single argument coercible into
|
|
1249
|
+
the base ring of ``self``, this is done directly in NTL, otherwise
|
|
1250
|
+
the generic Polynomial call code is used.
|
|
1251
|
+
|
|
1252
|
+
EXAMPLES::
|
|
1253
|
+
|
|
1254
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
1255
|
+
sage: f = x^3 + 7
|
|
1256
|
+
sage: f(5)
|
|
1257
|
+
32
|
|
1258
|
+
sage: f(5r)
|
|
1259
|
+
32
|
|
1260
|
+
sage: f(mod(5, 1000))
|
|
1261
|
+
32
|
|
1262
|
+
sage: f(x)
|
|
1263
|
+
x^3 + 7
|
|
1264
|
+
sage: S.<y> = PolynomialRing(Integers(5), implementation='NTL')
|
|
1265
|
+
sage: f(y)
|
|
1266
|
+
y^3 + 2
|
|
1267
|
+
|
|
1268
|
+
TESTS::
|
|
1269
|
+
|
|
1270
|
+
sage: R.<x> = PolynomialRing(Integers(100), implementation='NTL')
|
|
1271
|
+
sage: f = x^3 + 7
|
|
1272
|
+
sage: f(1).parent() == R.base_ring()
|
|
1273
|
+
True
|
|
1274
|
+
sage: f(int(1)).parent() == R.base_ring()
|
|
1275
|
+
True
|
|
1276
|
+
sage: f(x + 1).parent() == f.parent()
|
|
1277
|
+
True
|
|
1278
|
+
|
|
1279
|
+
sage: R.<x> = PolynomialRing(Zmod(12), 'x', implementation='NTL')
|
|
1280
|
+
sage: u = Zmod(4)(3)
|
|
1281
|
+
sage: x(u).parent() == u.parent()
|
|
1282
|
+
True
|
|
1283
|
+
"""
|
|
1284
|
+
if len(args) != 1 or len(kwds) != 0:
|
|
1285
|
+
return Polynomial.__call__(self, *args, **kwds)
|
|
1286
|
+
arg = args[0]
|
|
1287
|
+
cdef ntl_zz_p fx = ntl_zz_p(0, self.c), x = None
|
|
1288
|
+
if isinstance(arg, int):
|
|
1289
|
+
x = ntl_zz_p(arg, self.c)
|
|
1290
|
+
elif isinstance(arg, Integer):
|
|
1291
|
+
x = ntl_zz_p(arg, self.c)
|
|
1292
|
+
elif isinstance(arg, Element):
|
|
1293
|
+
if <void *>self._parent._base == <void *>(<Element>arg)._parent: # c++ pointer hack
|
|
1294
|
+
x = ntl_zz_p(arg, self.c)
|
|
1295
|
+
else:
|
|
1296
|
+
map = self._parent._base.coerce_map_from((<Element>arg)._parent)
|
|
1297
|
+
if map is not None:
|
|
1298
|
+
x = ntl_zz_p(map(arg), self.c)
|
|
1299
|
+
if x is None:
|
|
1300
|
+
return Polynomial.__call__(self, *args, **kwds)
|
|
1301
|
+
else:
|
|
1302
|
+
zz_pX_eval(fx.x, self.x, x.x)
|
|
1303
|
+
return self._parent._base(int(fx))
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n):
|
|
1307
|
+
|
|
1308
|
+
def __init__(self, parent, v=None, check=True, is_gen=False, construct=False):
|
|
1309
|
+
if isinstance(v, Polynomial):
|
|
1310
|
+
if (<Element>v)._parent == parent:
|
|
1311
|
+
Polynomial.__init__(self, parent, is_gen=is_gen)
|
|
1312
|
+
self.x = (<Polynomial_dense_modn_ntl_ZZ>v).x
|
|
1313
|
+
self.c = (<Polynomial_dense_modn_ntl_ZZ>v).c
|
|
1314
|
+
return
|
|
1315
|
+
|
|
1316
|
+
Polynomial_dense_mod_n.__init__(self, parent, v, check=check, is_gen=is_gen, construct=construct)
|
|
1317
|
+
cdef ntl_ZZ_pX ntl = self._poly
|
|
1318
|
+
self._poly = None # this will eventually go away
|
|
1319
|
+
self.x = ntl.x
|
|
1320
|
+
self.c = ntl.c
|
|
1321
|
+
|
|
1322
|
+
def __dealloc__(self):
|
|
1323
|
+
if <object>self.c is not None:
|
|
1324
|
+
self.c.restore_c()
|
|
1325
|
+
|
|
1326
|
+
cdef Polynomial_dense_modn_ntl_ZZ _new(self):
|
|
1327
|
+
cdef Polynomial_dense_modn_ntl_ZZ y = <Polynomial_dense_modn_ntl_ZZ>Polynomial_dense_modn_ntl_ZZ.__new__(Polynomial_dense_modn_ntl_ZZ)
|
|
1328
|
+
y.c = self.c
|
|
1329
|
+
y._parent = self._parent
|
|
1330
|
+
return y
|
|
1331
|
+
|
|
1332
|
+
cpdef list list(self, bint copy=True):
|
|
1333
|
+
return [self.get_unsafe(n) for n from 0 <= n <= self.degree()]
|
|
1334
|
+
|
|
1335
|
+
cdef get_unsafe(self, Py_ssize_t n):
|
|
1336
|
+
"""
|
|
1337
|
+
Return the `n`-th coefficient of ``self``.
|
|
1338
|
+
|
|
1339
|
+
EXAMPLES::
|
|
1340
|
+
|
|
1341
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1342
|
+
sage: from sage.rings.polynomial.polynomial_modn_dense_ntl import Polynomial_dense_modn_ntl_ZZ
|
|
1343
|
+
sage: f = Polynomial_dense_modn_ntl_ZZ(R,[2,1])^7
|
|
1344
|
+
sage: f[3]
|
|
1345
|
+
560
|
|
1346
|
+
sage: f[:6]
|
|
1347
|
+
84*x^5 + 280*x^4 + 560*x^3 + 672*x^2 + 448*x + 128
|
|
1348
|
+
sage: f[:50] == f
|
|
1349
|
+
True
|
|
1350
|
+
"""
|
|
1351
|
+
self.c.restore_c()
|
|
1352
|
+
# TODO, make this faster
|
|
1353
|
+
cdef ntl_ZZ_p ntl = ntl_ZZ_p(0, self.c)
|
|
1354
|
+
ntl.x = ZZ_pX_coeff(self.x, n)
|
|
1355
|
+
return self._parent._base(ntl._integer_())
|
|
1356
|
+
|
|
1357
|
+
def _unsafe_mutate(self, n, value):
|
|
1358
|
+
self.c.restore_c()
|
|
1359
|
+
cdef Integer a
|
|
1360
|
+
if isinstance(value, Integer):
|
|
1361
|
+
a = <Integer>value
|
|
1362
|
+
else:
|
|
1363
|
+
a = ZZ(value)
|
|
1364
|
+
cdef ntl_ZZ_p val = ntl_ZZ_p(a, self.c)
|
|
1365
|
+
ZZ_pX_SetCoeff(self.x, n, val.x)
|
|
1366
|
+
|
|
1367
|
+
cpdef _add_(self, _right):
|
|
1368
|
+
"""
|
|
1369
|
+
TESTS::
|
|
1370
|
+
|
|
1371
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1372
|
+
sage: (x + 5) + (x^2 - 6)
|
|
1373
|
+
x^2 + x + 999999999999999999999999999999
|
|
1374
|
+
"""
|
|
1375
|
+
cdef Polynomial_dense_modn_ntl_ZZ right = <Polynomial_dense_modn_ntl_ZZ>_right
|
|
1376
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1377
|
+
cdef bint do_sig = (ZZ_pX_deg(self.x) + ZZ_pX_deg(right.x)) * self.c.p_bits > 1e7
|
|
1378
|
+
if do_sig: sig_on()
|
|
1379
|
+
self.c.restore_c()
|
|
1380
|
+
ZZ_pX_add(r.x, self.x, right.x)
|
|
1381
|
+
if do_sig: sig_off()
|
|
1382
|
+
return r
|
|
1383
|
+
|
|
1384
|
+
cpdef _sub_(self, _right):
|
|
1385
|
+
"""
|
|
1386
|
+
TESTS::
|
|
1387
|
+
|
|
1388
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1389
|
+
sage: (x + 5) - (x^2 - 6)
|
|
1390
|
+
999999999999999999999999999999*x^2 + x + 11
|
|
1391
|
+
"""
|
|
1392
|
+
cdef Polynomial_dense_modn_ntl_ZZ right = <Polynomial_dense_modn_ntl_ZZ>_right
|
|
1393
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1394
|
+
cdef bint do_sig = (ZZ_pX_deg(self.x) + ZZ_pX_deg(right.x)) * self.c.p_bits > 1e7
|
|
1395
|
+
if do_sig: sig_on()
|
|
1396
|
+
self.c.restore_c()
|
|
1397
|
+
ZZ_pX_sub(r.x, self.x, right.x)
|
|
1398
|
+
if do_sig: sig_off()
|
|
1399
|
+
return r
|
|
1400
|
+
|
|
1401
|
+
cpdef _mul_(self, _right):
|
|
1402
|
+
"""
|
|
1403
|
+
TESTS::
|
|
1404
|
+
|
|
1405
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1406
|
+
sage: (x+5) * (x^2 - 1)
|
|
1407
|
+
x^3 + 5*x^2 + 999999999999999999999999999999*x + 999999999999999999999999999995
|
|
1408
|
+
"""
|
|
1409
|
+
cdef Polynomial_dense_modn_ntl_ZZ right = <Polynomial_dense_modn_ntl_ZZ>_right
|
|
1410
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1411
|
+
cdef bint do_sig = (ZZ_pX_deg(self.x) + ZZ_pX_deg(right.x)) * self.c.p_bits > 1e5
|
|
1412
|
+
if do_sig: sig_on()
|
|
1413
|
+
self.c.restore_c()
|
|
1414
|
+
if self is right:
|
|
1415
|
+
ZZ_pX_sqr(r.x, self.x)
|
|
1416
|
+
else:
|
|
1417
|
+
ZZ_pX_mul(r.x, self.x, right.x)
|
|
1418
|
+
if do_sig: sig_off()
|
|
1419
|
+
return r
|
|
1420
|
+
|
|
1421
|
+
cpdef Polynomial _mul_trunc_(self, Polynomial right, long n):
|
|
1422
|
+
"""
|
|
1423
|
+
Return the product of ``self`` and ``right`` truncated to the
|
|
1424
|
+
given length `n`, only return terms of degree less than `n`.
|
|
1425
|
+
|
|
1426
|
+
EXAMPLES::
|
|
1427
|
+
|
|
1428
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation="NTL")
|
|
1429
|
+
sage: f = x - 2
|
|
1430
|
+
sage: g = x^2 - 8*x + 16
|
|
1431
|
+
sage: f*g
|
|
1432
|
+
x^3 + 999999999999999999999999999990*x^2 + 32*x + 999999999999999999999999999968
|
|
1433
|
+
sage: f._mul_trunc_(g, 42)
|
|
1434
|
+
x^3 + 999999999999999999999999999990*x^2 + 32*x + 999999999999999999999999999968
|
|
1435
|
+
sage: f._mul_trunc_(g, 3)
|
|
1436
|
+
999999999999999999999999999990*x^2 + 32*x + 999999999999999999999999999968
|
|
1437
|
+
sage: f._mul_trunc_(g, 2)
|
|
1438
|
+
32*x + 999999999999999999999999999968
|
|
1439
|
+
sage: f._mul_trunc_(g, 1)
|
|
1440
|
+
999999999999999999999999999968
|
|
1441
|
+
sage: f._mul_trunc_(g, 0)
|
|
1442
|
+
0
|
|
1443
|
+
sage: f = x^2 - 8*x + 16
|
|
1444
|
+
sage: f._mul_trunc_(f, 2)
|
|
1445
|
+
999999999999999999999999999744*x + 256
|
|
1446
|
+
"""
|
|
1447
|
+
cdef Polynomial_dense_modn_ntl_ZZ op2 = <Polynomial_dense_modn_ntl_ZZ> right
|
|
1448
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1449
|
+
cdef bint do_sig = (ZZ_pX_deg(self.x) + ZZ_pX_deg(op2.x)) * self.c.p_bits > 1e5
|
|
1450
|
+
if do_sig: sig_on()
|
|
1451
|
+
self.c.restore_c()
|
|
1452
|
+
if self is op2:
|
|
1453
|
+
ZZ_pX_SqrTrunc(r.x, self.x, n)
|
|
1454
|
+
else:
|
|
1455
|
+
ZZ_pX_MulTrunc(r.x, self.x, op2.x, n)
|
|
1456
|
+
if do_sig: sig_off()
|
|
1457
|
+
return r
|
|
1458
|
+
|
|
1459
|
+
cpdef _rmul_(self, Element c):
|
|
1460
|
+
"""
|
|
1461
|
+
TESTS::
|
|
1462
|
+
|
|
1463
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1464
|
+
sage: (x+5) * 3
|
|
1465
|
+
3*x + 15
|
|
1466
|
+
"""
|
|
1467
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1468
|
+
cdef bint do_sig = ZZ_pX_deg(self.x) * self.c.p_bits > 1e7
|
|
1469
|
+
if do_sig: sig_on()
|
|
1470
|
+
self.c.restore_c()
|
|
1471
|
+
cdef ntl_ZZ_p value = ntl_ZZ_p(c, self.c)
|
|
1472
|
+
ZZ_pX_rmul(r.x, self.x, value.x)
|
|
1473
|
+
if do_sig: sig_off()
|
|
1474
|
+
return r
|
|
1475
|
+
|
|
1476
|
+
cpdef _lmul_(self, Element c):
|
|
1477
|
+
"""
|
|
1478
|
+
TESTS::
|
|
1479
|
+
|
|
1480
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1481
|
+
sage: 3 * (x+5)
|
|
1482
|
+
3*x + 15
|
|
1483
|
+
"""
|
|
1484
|
+
return self._rmul_(c)
|
|
1485
|
+
|
|
1486
|
+
def __pow__(Polynomial_dense_modn_ntl_ZZ self, ee, modulus):
|
|
1487
|
+
"""
|
|
1488
|
+
TESTS::
|
|
1489
|
+
|
|
1490
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1491
|
+
sage: (x+1)^5
|
|
1492
|
+
x^5 + 5*x^4 + 10*x^3 + 10*x^2 + 5*x + 1
|
|
1493
|
+
|
|
1494
|
+
We define ``0^0`` to be unity, :issue:`13895`::
|
|
1495
|
+
|
|
1496
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1497
|
+
sage: R(0)^0
|
|
1498
|
+
1
|
|
1499
|
+
|
|
1500
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
1501
|
+
|
|
1502
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1503
|
+
sage: type(R(0)^0) == type(R(0))
|
|
1504
|
+
True
|
|
1505
|
+
"""
|
|
1506
|
+
cdef bint recip = 0, do_sig
|
|
1507
|
+
cdef long e = ee
|
|
1508
|
+
if e != ee:
|
|
1509
|
+
raise TypeError("Only integral powers defined.")
|
|
1510
|
+
elif e < 0:
|
|
1511
|
+
recip = 1 # delay because powering frac field elements is slow
|
|
1512
|
+
e = -e
|
|
1513
|
+
if self == 0 and e == 0:
|
|
1514
|
+
return self.parent(1)
|
|
1515
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1516
|
+
cdef ZZ_pX_Modulus_c mod
|
|
1517
|
+
|
|
1518
|
+
self.c.restore_c()
|
|
1519
|
+
|
|
1520
|
+
if modulus is None:
|
|
1521
|
+
if ZZ_pX_IsX(self.x):
|
|
1522
|
+
ZZ_pX_LeftShift(r.x, self.x, e - 1)
|
|
1523
|
+
else:
|
|
1524
|
+
do_sig = ZZ_pX_deg(self.x) * e * self.c.p_bits > 1e5
|
|
1525
|
+
if do_sig: sig_on()
|
|
1526
|
+
ZZ_pX_power(r.x, self.x, e)
|
|
1527
|
+
if do_sig: sig_off()
|
|
1528
|
+
else:
|
|
1529
|
+
if not isinstance(modulus, Polynomial_dense_modn_ntl_ZZ):
|
|
1530
|
+
modulus = self.parent().coerce(modulus)
|
|
1531
|
+
ZZ_pX_Modulus_build(mod, (<Polynomial_dense_modn_ntl_ZZ>modulus).x)
|
|
1532
|
+
|
|
1533
|
+
do_sig = ZZ_pX_deg(self.x) * e * self.c.p_bits > 1e5
|
|
1534
|
+
if do_sig: sig_on()
|
|
1535
|
+
ZZ_pX_PowerMod_long_pre(r.x, self.x, e, mod)
|
|
1536
|
+
if do_sig: sig_off()
|
|
1537
|
+
if recip:
|
|
1538
|
+
return ~r
|
|
1539
|
+
else:
|
|
1540
|
+
return r
|
|
1541
|
+
|
|
1542
|
+
@coerce_binop
|
|
1543
|
+
def quo_rem(self, right):
|
|
1544
|
+
r"""
|
|
1545
|
+
Return `q` and `r`, with the degree of `r` less than the degree of ``right``,
|
|
1546
|
+
such that `q \cdot` ``right`` `+ r =` ``self``.
|
|
1547
|
+
|
|
1548
|
+
EXAMPLES::
|
|
1549
|
+
|
|
1550
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1551
|
+
sage: f = x^5+1; g = (x+1)^2
|
|
1552
|
+
sage: q, r = f.quo_rem(g)
|
|
1553
|
+
sage: q
|
|
1554
|
+
x^3 + 999999999999999999999999999998*x^2 + 3*x + 999999999999999999999999999996
|
|
1555
|
+
sage: r
|
|
1556
|
+
5*x + 5
|
|
1557
|
+
sage: q*g + r
|
|
1558
|
+
x^5 + 1
|
|
1559
|
+
"""
|
|
1560
|
+
cdef Polynomial_dense_modn_ntl_ZZ q = self._new()
|
|
1561
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1562
|
+
cdef Polynomial_dense_modn_ntl_ZZ denom = <Polynomial_dense_modn_ntl_ZZ>right
|
|
1563
|
+
sig_on()
|
|
1564
|
+
self.c.restore_c()
|
|
1565
|
+
ZZ_pX_DivRem(q.x, r.x, self.x, denom.x)
|
|
1566
|
+
sig_off()
|
|
1567
|
+
return q, r
|
|
1568
|
+
|
|
1569
|
+
cpdef _floordiv_(self, right):
|
|
1570
|
+
"""
|
|
1571
|
+
Return the whole part of ``self`` / ``right``, without remainder.
|
|
1572
|
+
|
|
1573
|
+
For q = n // d, we have deg(n - q*d) < deg(d)
|
|
1574
|
+
|
|
1575
|
+
EXAMPLES::
|
|
1576
|
+
|
|
1577
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1578
|
+
sage: f = x^7 + 1; g = x^2 - 1
|
|
1579
|
+
sage: q = f // g; q
|
|
1580
|
+
x^5 + x^3 + x
|
|
1581
|
+
sage: f - q*g
|
|
1582
|
+
x + 1
|
|
1583
|
+
"""
|
|
1584
|
+
cdef Polynomial_dense_modn_ntl_ZZ numer = <Polynomial_dense_modn_ntl_ZZ>self
|
|
1585
|
+
cdef Polynomial_dense_modn_ntl_ZZ denom = <Polynomial_dense_modn_ntl_ZZ>right
|
|
1586
|
+
cdef Polynomial_dense_modn_ntl_ZZ q = numer._new()
|
|
1587
|
+
sig_on()
|
|
1588
|
+
numer.c.restore_c()
|
|
1589
|
+
ZZ_pX_div(q.x, numer.x, denom.x)
|
|
1590
|
+
sig_off()
|
|
1591
|
+
return q
|
|
1592
|
+
|
|
1593
|
+
cpdef _mod_(self, right):
|
|
1594
|
+
"""
|
|
1595
|
+
EXAMPLES::
|
|
1596
|
+
|
|
1597
|
+
sage: R.<x> = PolynomialRing(Integers(9^30), implementation='NTL')
|
|
1598
|
+
sage: f = x^7 + x + 1; g = x^3 - 1
|
|
1599
|
+
sage: r = f % g; r
|
|
1600
|
+
2*x + 1
|
|
1601
|
+
sage: g * (x^4 + x) + r
|
|
1602
|
+
x^7 + x + 1
|
|
1603
|
+
"""
|
|
1604
|
+
cdef Polynomial_dense_modn_ntl_ZZ numer = <Polynomial_dense_modn_ntl_ZZ>self
|
|
1605
|
+
cdef Polynomial_dense_modn_ntl_ZZ denom = <Polynomial_dense_modn_ntl_ZZ>right
|
|
1606
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = numer._new()
|
|
1607
|
+
sig_on()
|
|
1608
|
+
numer.c.restore_c()
|
|
1609
|
+
ZZ_pX_rem(r.x, numer.x, denom.x)
|
|
1610
|
+
sig_off()
|
|
1611
|
+
return r
|
|
1612
|
+
|
|
1613
|
+
def shift(self, n):
|
|
1614
|
+
"""
|
|
1615
|
+
Shift ``self`` to left by `n`, which is multiplication by `x^n`,
|
|
1616
|
+
truncating if `n` is negative.
|
|
1617
|
+
|
|
1618
|
+
EXAMPLES::
|
|
1619
|
+
|
|
1620
|
+
sage: R.<x> = PolynomialRing(Integers(12^30), implementation='NTL')
|
|
1621
|
+
sage: f = x^7 + x + 1
|
|
1622
|
+
sage: f.shift(1)
|
|
1623
|
+
x^8 + x^2 + x
|
|
1624
|
+
sage: f.shift(-1)
|
|
1625
|
+
x^6 + 1
|
|
1626
|
+
sage: f.shift(10).shift(-10) == f
|
|
1627
|
+
True
|
|
1628
|
+
|
|
1629
|
+
TESTS::
|
|
1630
|
+
|
|
1631
|
+
sage: p = R(0)
|
|
1632
|
+
sage: p.shift(3).is_zero()
|
|
1633
|
+
True
|
|
1634
|
+
sage: p.shift(-3).is_zero()
|
|
1635
|
+
True
|
|
1636
|
+
"""
|
|
1637
|
+
return self << n
|
|
1638
|
+
|
|
1639
|
+
def __lshift__(Polynomial_dense_modn_ntl_ZZ self, long n):
|
|
1640
|
+
"""
|
|
1641
|
+
TESTS::
|
|
1642
|
+
|
|
1643
|
+
sage: R.<x> = PolynomialRing(Integers(14^30), implementation='NTL')
|
|
1644
|
+
sage: f = x^5 + 2*x + 1
|
|
1645
|
+
sage: f << 3
|
|
1646
|
+
x^8 + 2*x^4 + x^3
|
|
1647
|
+
"""
|
|
1648
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1649
|
+
ZZ_pX_LeftShift(r.x, self.x, n)
|
|
1650
|
+
return r
|
|
1651
|
+
|
|
1652
|
+
def __rshift__(Polynomial_dense_modn_ntl_ZZ self, long n):
|
|
1653
|
+
"""
|
|
1654
|
+
TESTS::
|
|
1655
|
+
|
|
1656
|
+
sage: R.<x> = PolynomialRing(Integers(15^30), implementation='NTL')
|
|
1657
|
+
sage: f = x^5 + 2*x + 1
|
|
1658
|
+
sage: f >> 3
|
|
1659
|
+
x^2
|
|
1660
|
+
"""
|
|
1661
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1662
|
+
ZZ_pX_RightShift(r.x, self.x, n)
|
|
1663
|
+
return r
|
|
1664
|
+
|
|
1665
|
+
def _derivative(self, var=None):
|
|
1666
|
+
r"""
|
|
1667
|
+
Return the formal derivative of ``self`` with respect to ``var``.
|
|
1668
|
+
|
|
1669
|
+
``var`` must be either the generator of the polynomial ring to which
|
|
1670
|
+
this polynomial belongs, or None (either way the behaviour is the
|
|
1671
|
+
same).
|
|
1672
|
+
|
|
1673
|
+
.. SEEALSO:: :meth:`.derivative`
|
|
1674
|
+
|
|
1675
|
+
EXAMPLES::
|
|
1676
|
+
|
|
1677
|
+
sage: R.<x> = PolynomialRing(Integers(12^29), implementation='NTL')
|
|
1678
|
+
sage: f = x^4 + x + 5
|
|
1679
|
+
sage: f._derivative()
|
|
1680
|
+
4*x^3 + 1
|
|
1681
|
+
sage: f._derivative(None)
|
|
1682
|
+
4*x^3 + 1
|
|
1683
|
+
|
|
1684
|
+
sage: f._derivative(2*x)
|
|
1685
|
+
Traceback (most recent call last):
|
|
1686
|
+
...
|
|
1687
|
+
ValueError: cannot differentiate with respect to 2*x
|
|
1688
|
+
|
|
1689
|
+
TESTS::
|
|
1690
|
+
|
|
1691
|
+
sage: y = var("y") # needs sage.symbolic
|
|
1692
|
+
sage: f._derivative(y) # needs sage.symbolic
|
|
1693
|
+
Traceback (most recent call last):
|
|
1694
|
+
...
|
|
1695
|
+
ValueError: cannot differentiate with respect to y
|
|
1696
|
+
"""
|
|
1697
|
+
if var is not None and var != self._parent.gen():
|
|
1698
|
+
raise ValueError("cannot differentiate with respect to {}".format(var))
|
|
1699
|
+
|
|
1700
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1701
|
+
ZZ_pX_diff(r.x, self.x)
|
|
1702
|
+
return r
|
|
1703
|
+
|
|
1704
|
+
def reverse(self, degree=None):
|
|
1705
|
+
"""
|
|
1706
|
+
Return the reverse of the input polynomial thought as a polynomial of
|
|
1707
|
+
degree ``degree``.
|
|
1708
|
+
|
|
1709
|
+
If `f` is a degree-`d` polynomial, its reverse is `x^d f(1/x)`.
|
|
1710
|
+
|
|
1711
|
+
INPUT:
|
|
1712
|
+
|
|
1713
|
+
- ``degree`` -- ``None`` or integer; if specified, truncate or zero
|
|
1714
|
+
pad the list of coefficients to this degree before reversing it
|
|
1715
|
+
|
|
1716
|
+
EXAMPLES::
|
|
1717
|
+
|
|
1718
|
+
sage: R.<x> = PolynomialRing(Integers(12^29), implementation='NTL')
|
|
1719
|
+
sage: f = x^4 + 2*x + 5
|
|
1720
|
+
sage: f.reverse()
|
|
1721
|
+
5*x^4 + 2*x^3 + 1
|
|
1722
|
+
sage: f = x^3 + x
|
|
1723
|
+
sage: f.reverse()
|
|
1724
|
+
x^2 + 1
|
|
1725
|
+
sage: f.reverse(1)
|
|
1726
|
+
1
|
|
1727
|
+
sage: f.reverse(5)
|
|
1728
|
+
x^4 + x^2
|
|
1729
|
+
|
|
1730
|
+
TESTS:
|
|
1731
|
+
|
|
1732
|
+
We check that this implementation is compatible with the generic one::
|
|
1733
|
+
|
|
1734
|
+
sage: all(f.reverse(d) == Polynomial.reverse(f, d)
|
|
1735
|
+
....: for d in [None, 0, 1, 2, 3, 4, 5])
|
|
1736
|
+
True
|
|
1737
|
+
"""
|
|
1738
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1739
|
+
|
|
1740
|
+
if degree is None:
|
|
1741
|
+
ZZ_pX_reverse(r.x, self.x)
|
|
1742
|
+
else:
|
|
1743
|
+
ZZ_pX_reverse_hi(r.x, self.x, degree)
|
|
1744
|
+
return r
|
|
1745
|
+
|
|
1746
|
+
def is_gen(self):
|
|
1747
|
+
return ZZ_pX_IsX(self.x)
|
|
1748
|
+
|
|
1749
|
+
def valuation(self):
|
|
1750
|
+
"""
|
|
1751
|
+
Return the valuation of ``self``, that is, the power of the
|
|
1752
|
+
lowest nonzero monomial of ``self``.
|
|
1753
|
+
|
|
1754
|
+
EXAMPLES::
|
|
1755
|
+
|
|
1756
|
+
sage: R.<x> = PolynomialRing(Integers(10^50), implementation='NTL')
|
|
1757
|
+
sage: x.valuation()
|
|
1758
|
+
1
|
|
1759
|
+
sage: f = x - 3; f.valuation()
|
|
1760
|
+
0
|
|
1761
|
+
sage: f = x^99; f.valuation()
|
|
1762
|
+
99
|
|
1763
|
+
sage: f = x - x; f.valuation()
|
|
1764
|
+
+Infinity
|
|
1765
|
+
"""
|
|
1766
|
+
cdef long n
|
|
1767
|
+
cdef ZZ_p_c coeff
|
|
1768
|
+
for n from 0 <= n <= ZZ_pX_deg(self.x):
|
|
1769
|
+
coeff = ZZ_pX_coeff(self.x, n)
|
|
1770
|
+
if not ZZ_p_IsZero(coeff):
|
|
1771
|
+
return n
|
|
1772
|
+
return infinity
|
|
1773
|
+
|
|
1774
|
+
def __bool__(self):
|
|
1775
|
+
"""
|
|
1776
|
+
TESTS::
|
|
1777
|
+
|
|
1778
|
+
sage: R.<x> = PolynomialRing(Integers(12^29), implementation='NTL')
|
|
1779
|
+
sage: f = x^4 + 1
|
|
1780
|
+
sage: not f
|
|
1781
|
+
False
|
|
1782
|
+
sage: not (x-x)
|
|
1783
|
+
True
|
|
1784
|
+
"""
|
|
1785
|
+
return not ZZ_pX_IsZero(self.x)
|
|
1786
|
+
|
|
1787
|
+
def degree(self):
|
|
1788
|
+
"""
|
|
1789
|
+
EXAMPLES::
|
|
1790
|
+
|
|
1791
|
+
sage: R.<x> = PolynomialRing(Integers(14^34), implementation='NTL')
|
|
1792
|
+
sage: f = x^4 - x - 1
|
|
1793
|
+
sage: f.degree()
|
|
1794
|
+
4
|
|
1795
|
+
sage: f = 14^43*x + 1
|
|
1796
|
+
sage: f.degree()
|
|
1797
|
+
0
|
|
1798
|
+
"""
|
|
1799
|
+
return ZZ_pX_deg(self.x)
|
|
1800
|
+
|
|
1801
|
+
cpdef Polynomial truncate(self, long n):
|
|
1802
|
+
"""
|
|
1803
|
+
Return this polynomial mod `x^n`.
|
|
1804
|
+
|
|
1805
|
+
EXAMPLES::
|
|
1806
|
+
|
|
1807
|
+
sage: R.<x> = PolynomialRing(Integers(15^30), implementation='NTL')
|
|
1808
|
+
sage: f = sum(x^n for n in range(10)); f
|
|
1809
|
+
x^9 + x^8 + x^7 + x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
|
|
1810
|
+
sage: f.truncate(6)
|
|
1811
|
+
x^5 + x^4 + x^3 + x^2 + x + 1
|
|
1812
|
+
"""
|
|
1813
|
+
cdef Polynomial_dense_modn_ntl_ZZ r = self._new()
|
|
1814
|
+
ZZ_pX_trunc(r.x, self.x, n)
|
|
1815
|
+
return r
|
|
1816
|
+
|
|
1817
|
+
def __call__(self, *args, **kwds):
|
|
1818
|
+
"""
|
|
1819
|
+
Evaluate ``self`` at ``x``. If ``x`` is a single argument coercible into
|
|
1820
|
+
the base ring of ``self``, this is done directly in NTL, otherwise
|
|
1821
|
+
the generic Polynomial call code is used.
|
|
1822
|
+
|
|
1823
|
+
EXAMPLES::
|
|
1824
|
+
|
|
1825
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1826
|
+
sage: f = x^3 + 7
|
|
1827
|
+
sage: f(5)
|
|
1828
|
+
132
|
|
1829
|
+
sage: f(5r)
|
|
1830
|
+
132
|
|
1831
|
+
sage: f(mod(5, 10^50))
|
|
1832
|
+
132
|
|
1833
|
+
sage: f(x)
|
|
1834
|
+
x^3 + 7
|
|
1835
|
+
sage: S.<y> = PolynomialRing(Integers(5), implementation='NTL')
|
|
1836
|
+
sage: f(y)
|
|
1837
|
+
y^3 + 2
|
|
1838
|
+
|
|
1839
|
+
TESTS::
|
|
1840
|
+
|
|
1841
|
+
sage: R.<x> = PolynomialRing(Integers(10^30), implementation='NTL')
|
|
1842
|
+
sage: f = x^3 + 7
|
|
1843
|
+
sage: f(1).parent() == R.base_ring()
|
|
1844
|
+
True
|
|
1845
|
+
sage: f(int(1)).parent() == R.base_ring()
|
|
1846
|
+
True
|
|
1847
|
+
sage: f(x + 1).parent() == f.parent()
|
|
1848
|
+
True
|
|
1849
|
+
|
|
1850
|
+
sage: R.<x> = PolynomialRing(Zmod(10^30), 'x', implementation='NTL')
|
|
1851
|
+
sage: u = Zmod(10^29)(3)
|
|
1852
|
+
sage: x(u).parent() == u.parent()
|
|
1853
|
+
True
|
|
1854
|
+
sage: v = Zmod(10)(3)
|
|
1855
|
+
sage: x(v).parent() == v.parent()
|
|
1856
|
+
True
|
|
1857
|
+
"""
|
|
1858
|
+
if len(args) != 1 or len(kwds) != 0:
|
|
1859
|
+
return Polynomial.__call__(self, *args, **kwds)
|
|
1860
|
+
arg = args[0]
|
|
1861
|
+
cdef ntl_ZZ_p fx = ntl_ZZ_p(0, self.c), x = None
|
|
1862
|
+
if isinstance(arg, (int, Integer)):
|
|
1863
|
+
x = ntl_ZZ_p(arg, self.c)
|
|
1864
|
+
elif isinstance(arg, Element):
|
|
1865
|
+
if <void *>self._parent._base == <void *>(<Element>arg)._parent: # c++ pointer hack
|
|
1866
|
+
x = ntl_ZZ_p(arg, self.c)
|
|
1867
|
+
else:
|
|
1868
|
+
map = self._parent._base.coerce_map_from((<Element>arg)._parent)
|
|
1869
|
+
if map is not None:
|
|
1870
|
+
x = ntl_ZZ_p(map(arg), self.c)
|
|
1871
|
+
if x is None:
|
|
1872
|
+
return Polynomial.__call__(self, *args, **kwds)
|
|
1873
|
+
else:
|
|
1874
|
+
ZZ_pX_eval(fx.x, self.x, x.x)
|
|
1875
|
+
return self._parent._base(fx._integer_())
|
|
1876
|
+
|
|
1877
|
+
|
|
1878
|
+
cdef class Polynomial_dense_mod_p(Polynomial_dense_mod_n):
|
|
1879
|
+
"""
|
|
1880
|
+
A dense polynomial over the integers modulo `p`, where `p` is prime.
|
|
1881
|
+
"""
|
|
1882
|
+
|
|
1883
|
+
def __pow__(self, n, modulus):
|
|
1884
|
+
"""
|
|
1885
|
+
Exponentiation of ``self``.
|
|
1886
|
+
|
|
1887
|
+
If ``modulus`` is not ``None``, the exponentiation is performed
|
|
1888
|
+
modulo the polynomial ``modulus``.
|
|
1889
|
+
|
|
1890
|
+
EXAMPLES::
|
|
1891
|
+
|
|
1892
|
+
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
|
|
1893
|
+
sage: (x-1)^5
|
|
1894
|
+
x^5 + 96*x^4 + 10*x^3 + 91*x^2 + 5*x + 100
|
|
1895
|
+
sage: pow(x-1, 15, x^3+x+1)
|
|
1896
|
+
55*x^2 + 6*x + 46
|
|
1897
|
+
|
|
1898
|
+
TESTS:
|
|
1899
|
+
|
|
1900
|
+
Negative powers work but use the generic
|
|
1901
|
+
implementation of fraction fields::
|
|
1902
|
+
|
|
1903
|
+
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
|
|
1904
|
+
sage: f = (x-1)^(-5)
|
|
1905
|
+
sage: type(f)
|
|
1906
|
+
<class 'sage.rings.fraction_field_element.FractionFieldElement_1poly_field'>
|
|
1907
|
+
sage: (f + 2).numerator()
|
|
1908
|
+
2*x^5 + 91*x^4 + 20*x^3 + 81*x^2 + 10*x + 100
|
|
1909
|
+
|
|
1910
|
+
We define ``0^0`` to be unity, :issue:`13895`::
|
|
1911
|
+
|
|
1912
|
+
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
|
|
1913
|
+
sage: R(0)^0
|
|
1914
|
+
1
|
|
1915
|
+
|
|
1916
|
+
The value returned from ``0^0`` should belong to our ring::
|
|
1917
|
+
|
|
1918
|
+
sage: R.<x> = PolynomialRing(Integers(101), implementation='NTL')
|
|
1919
|
+
sage: type(R(0)^0) == type(R(0))
|
|
1920
|
+
True
|
|
1921
|
+
|
|
1922
|
+
The modulus can have smaller degree than ``self``::
|
|
1923
|
+
|
|
1924
|
+
sage: R.<x> = PolynomialRing(GF(101), implementation="NTL")
|
|
1925
|
+
sage: pow(x^4 + 1, 100, x^2 + x + 1)
|
|
1926
|
+
100*x + 100
|
|
1927
|
+
|
|
1928
|
+
Canonical coercion should apply::
|
|
1929
|
+
|
|
1930
|
+
sage: # needs sage.libs.flint
|
|
1931
|
+
sage: R.<x> = PolynomialRing(GF(101), implementation="FLINT")
|
|
1932
|
+
sage: x_ZZ = ZZ["x"].gen()
|
|
1933
|
+
sage: pow(x+1, 100, 2)
|
|
1934
|
+
0
|
|
1935
|
+
sage: pow(x+1, 100, x_ZZ^2 + x_ZZ + 1)
|
|
1936
|
+
100*x + 100
|
|
1937
|
+
sage: pow(x+1, int(100), x_ZZ^2 + x_ZZ + 1)
|
|
1938
|
+
100*x + 100
|
|
1939
|
+
sage: xx = polygen(GF(97))
|
|
1940
|
+
sage: _ = pow(x + 1, 3, xx^3 + xx + 1)
|
|
1941
|
+
Traceback (most recent call last):
|
|
1942
|
+
...
|
|
1943
|
+
TypeError: no common canonical parent for objects with parents: ...
|
|
1944
|
+
"""
|
|
1945
|
+
n = Integer(n)
|
|
1946
|
+
parent = (<Element>self)._parent
|
|
1947
|
+
|
|
1948
|
+
if modulus is not None:
|
|
1949
|
+
# Similar to coerce_binop
|
|
1950
|
+
if not have_same_parent(self, modulus):
|
|
1951
|
+
a, m = canonical_coercion(self, modulus)
|
|
1952
|
+
if a is not self:
|
|
1953
|
+
return pow(a, n, m)
|
|
1954
|
+
modulus = m
|
|
1955
|
+
self = self % modulus
|
|
1956
|
+
return parent(pow(self.ntl_ZZ_pX(), n, modulus.ntl_ZZ_pX()), construct=True)
|
|
1957
|
+
else:
|
|
1958
|
+
if n < 0:
|
|
1959
|
+
return ~(self**(-n))
|
|
1960
|
+
elif self.degree() <= 0:
|
|
1961
|
+
return parent(self[0]**n)
|
|
1962
|
+
else:
|
|
1963
|
+
return parent(self.ntl_ZZ_pX()**n, construct=True)
|
|
1964
|
+
|
|
1965
|
+
@coerce_binop
|
|
1966
|
+
def gcd(self, right):
|
|
1967
|
+
"""
|
|
1968
|
+
Return the greatest common divisor of this polynomial and ``other``, as
|
|
1969
|
+
a monic polynomial.
|
|
1970
|
+
|
|
1971
|
+
INPUT:
|
|
1972
|
+
|
|
1973
|
+
- ``other`` -- a polynomial defined over the same ring as ``self``
|
|
1974
|
+
|
|
1975
|
+
EXAMPLES::
|
|
1976
|
+
|
|
1977
|
+
sage: R.<x> = PolynomialRing(GF(3), implementation="NTL")
|
|
1978
|
+
sage: f, g = x + 2, x^2 - 1
|
|
1979
|
+
sage: f.gcd(g)
|
|
1980
|
+
x + 2
|
|
1981
|
+
"""
|
|
1982
|
+
g = self.ntl_ZZ_pX().gcd(right.ntl_ZZ_pX())
|
|
1983
|
+
return self.parent()(g, construct=True)
|
|
1984
|
+
|
|
1985
|
+
@coerce_binop
|
|
1986
|
+
def xgcd(self, other):
|
|
1987
|
+
r"""
|
|
1988
|
+
Compute the extended gcd of this element and ``other``.
|
|
1989
|
+
|
|
1990
|
+
INPUT:
|
|
1991
|
+
|
|
1992
|
+
- ``other`` -- an element in the same polynomial ring
|
|
1993
|
+
|
|
1994
|
+
OUTPUT:
|
|
1995
|
+
|
|
1996
|
+
A tuple ``(r,s,t)`` of elements in the polynomial ring such
|
|
1997
|
+
that ``r = s*self + t*other``.
|
|
1998
|
+
|
|
1999
|
+
EXAMPLES::
|
|
2000
|
+
|
|
2001
|
+
sage: R.<x> = PolynomialRing(GF(3), implementation='NTL')
|
|
2002
|
+
sage: x.xgcd(x)
|
|
2003
|
+
(x, 0, 1)
|
|
2004
|
+
sage: (x^2 - 1).xgcd(x - 1)
|
|
2005
|
+
(x + 2, 0, 1)
|
|
2006
|
+
sage: R.zero().xgcd(R.one())
|
|
2007
|
+
(1, 0, 1)
|
|
2008
|
+
sage: (x^3 - 1).xgcd((x - 1)^2)
|
|
2009
|
+
(x^2 + x + 1, 0, 1)
|
|
2010
|
+
sage: ((x - 1)*(x + 1)).xgcd(x*(x - 1))
|
|
2011
|
+
(x + 2, 1, 2)
|
|
2012
|
+
"""
|
|
2013
|
+
r, s, t = self.ntl_ZZ_pX().xgcd(other.ntl_ZZ_pX())
|
|
2014
|
+
return self.parent()(r, construct=True), self.parent()(s, construct=True), self.parent()(t, construct=True)
|
|
2015
|
+
|
|
2016
|
+
@coerce_binop
|
|
2017
|
+
def resultant(self, other):
|
|
2018
|
+
"""
|
|
2019
|
+
Return the resultant of ``self`` and ``other``, which must lie in the same
|
|
2020
|
+
polynomial ring.
|
|
2021
|
+
|
|
2022
|
+
INPUT:
|
|
2023
|
+
|
|
2024
|
+
- ``other`` -- a polynomial
|
|
2025
|
+
|
|
2026
|
+
OUTPUT: an element of the base ring of the polynomial ring
|
|
2027
|
+
|
|
2028
|
+
EXAMPLES::
|
|
2029
|
+
|
|
2030
|
+
sage: R.<x> = PolynomialRing(GF(19), implementation='NTL')
|
|
2031
|
+
sage: f = x^3 + x + 1; g = x^3 - x - 1
|
|
2032
|
+
sage: r = f.resultant(g); r
|
|
2033
|
+
11
|
|
2034
|
+
sage: r.parent() is GF(19)
|
|
2035
|
+
True
|
|
2036
|
+
"""
|
|
2037
|
+
other = self.parent().coerce(other)
|
|
2038
|
+
return self.base_ring()(str(self.ntl_ZZ_pX().resultant(other.ntl_ZZ_pX())))
|
|
2039
|
+
|
|
2040
|
+
def discriminant(self):
|
|
2041
|
+
"""
|
|
2042
|
+
EXAMPLES::
|
|
2043
|
+
|
|
2044
|
+
sage: _.<x> = PolynomialRing(GF(19), implementation='NTL')
|
|
2045
|
+
sage: f = x^3 + 3*x - 17
|
|
2046
|
+
sage: f.discriminant()
|
|
2047
|
+
12
|
|
2048
|
+
"""
|
|
2049
|
+
return self.base_ring()(str(self.ntl_ZZ_pX().discriminant()))
|