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.

Files changed (161) hide show
  1. passagemath_ntl-10.6.33.dist-info/METADATA +122 -0
  2. passagemath_ntl-10.6.33.dist-info/RECORD +161 -0
  3. passagemath_ntl-10.6.33.dist-info/WHEEL +6 -0
  4. passagemath_ntl-10.6.33.dist-info/top_level.txt +2 -0
  5. passagemath_ntl.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
  6. passagemath_ntl.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  7. passagemath_ntl.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
  8. passagemath_ntl.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
  9. passagemath_ntl.libs/libntl-0043a3a2.so.44.0.1 +0 -0
  10. sage/all__sagemath_ntl.py +7 -0
  11. sage/libs/all__sagemath_ntl.py +3 -0
  12. sage/libs/mpfi/__init__.pxd +287 -0
  13. sage/libs/mpfi/types.pxd +10 -0
  14. sage/libs/ntl/GF2.pxd +18 -0
  15. sage/libs/ntl/GF2E.pxd +28 -0
  16. sage/libs/ntl/GF2EX.pxd +12 -0
  17. sage/libs/ntl/GF2X.pxd +81 -0
  18. sage/libs/ntl/ZZ.pxd +93 -0
  19. sage/libs/ntl/ZZX.pxd +85 -0
  20. sage/libs/ntl/ZZ_p.pxd +28 -0
  21. sage/libs/ntl/ZZ_pE.pxd +37 -0
  22. sage/libs/ntl/ZZ_pEX.pxd +106 -0
  23. sage/libs/ntl/ZZ_pX.pxd +122 -0
  24. sage/libs/ntl/__init__.py +4 -0
  25. sage/libs/ntl/all.py +72 -0
  26. sage/libs/ntl/conversion.pxd +106 -0
  27. sage/libs/ntl/convert.cpython-314t-aarch64-linux-gnu.so +0 -0
  28. sage/libs/ntl/convert.pxd +7 -0
  29. sage/libs/ntl/convert.pyx +38 -0
  30. sage/libs/ntl/decl.pxi +18 -0
  31. sage/libs/ntl/error.cpython-314t-aarch64-linux-gnu.so +0 -0
  32. sage/libs/ntl/error.pyx +63 -0
  33. sage/libs/ntl/lzz_p.pxd +20 -0
  34. sage/libs/ntl/lzz_pX.pxd +59 -0
  35. sage/libs/ntl/mat_GF2.pxd +30 -0
  36. sage/libs/ntl/mat_GF2E.pxd +30 -0
  37. sage/libs/ntl/mat_ZZ.pxd +59 -0
  38. sage/libs/ntl/misc.pxi +33 -0
  39. sage/libs/ntl/ntl_GF2.cpython-314t-aarch64-linux-gnu.so +0 -0
  40. sage/libs/ntl/ntl_GF2.pxd +5 -0
  41. sage/libs/ntl/ntl_GF2.pyx +281 -0
  42. sage/libs/ntl/ntl_GF2E.cpython-314t-aarch64-linux-gnu.so +0 -0
  43. sage/libs/ntl/ntl_GF2E.pxd +8 -0
  44. sage/libs/ntl/ntl_GF2E.pyx +488 -0
  45. sage/libs/ntl/ntl_GF2EContext.cpython-314t-aarch64-linux-gnu.so +0 -0
  46. sage/libs/ntl/ntl_GF2EContext.pxd +9 -0
  47. sage/libs/ntl/ntl_GF2EContext.pyx +134 -0
  48. sage/libs/ntl/ntl_GF2EX.cpython-314t-aarch64-linux-gnu.so +0 -0
  49. sage/libs/ntl/ntl_GF2EX.pxd +10 -0
  50. sage/libs/ntl/ntl_GF2EX.pyx +251 -0
  51. sage/libs/ntl/ntl_GF2X.cpython-314t-aarch64-linux-gnu.so +0 -0
  52. sage/libs/ntl/ntl_GF2X.pxd +5 -0
  53. sage/libs/ntl/ntl_GF2X.pyx +771 -0
  54. sage/libs/ntl/ntl_GF2X_linkage.pxi +404 -0
  55. sage/libs/ntl/ntl_ZZ.cpython-314t-aarch64-linux-gnu.so +0 -0
  56. sage/libs/ntl/ntl_ZZ.pxd +7 -0
  57. sage/libs/ntl/ntl_ZZ.pyx +541 -0
  58. sage/libs/ntl/ntl_ZZX.cpython-314t-aarch64-linux-gnu.so +0 -0
  59. sage/libs/ntl/ntl_ZZX.pxd +7 -0
  60. sage/libs/ntl/ntl_ZZX.pyx +1206 -0
  61. sage/libs/ntl/ntl_ZZ_p.cpython-314t-aarch64-linux-gnu.so +0 -0
  62. sage/libs/ntl/ntl_ZZ_p.pxd +10 -0
  63. sage/libs/ntl/ntl_ZZ_p.pyx +509 -0
  64. sage/libs/ntl/ntl_ZZ_pContext.cpython-314t-aarch64-linux-gnu.so +0 -0
  65. sage/libs/ntl/ntl_ZZ_pContext.pxd +22 -0
  66. sage/libs/ntl/ntl_ZZ_pContext.pyx +201 -0
  67. sage/libs/ntl/ntl_ZZ_pE.cpython-314t-aarch64-linux-gnu.so +0 -0
  68. sage/libs/ntl/ntl_ZZ_pE.pxd +11 -0
  69. sage/libs/ntl/ntl_ZZ_pE.pyx +349 -0
  70. sage/libs/ntl/ntl_ZZ_pEContext.cpython-314t-aarch64-linux-gnu.so +0 -0
  71. sage/libs/ntl/ntl_ZZ_pEContext.pxd +23 -0
  72. sage/libs/ntl/ntl_ZZ_pEContext.pyx +226 -0
  73. sage/libs/ntl/ntl_ZZ_pEX.cpython-314t-aarch64-linux-gnu.so +0 -0
  74. sage/libs/ntl/ntl_ZZ_pEX.pxd +10 -0
  75. sage/libs/ntl/ntl_ZZ_pEX.pyx +1255 -0
  76. sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi +420 -0
  77. sage/libs/ntl/ntl_ZZ_pX.cpython-314t-aarch64-linux-gnu.so +0 -0
  78. sage/libs/ntl/ntl_ZZ_pX.pxd +17 -0
  79. sage/libs/ntl/ntl_ZZ_pX.pyx +1532 -0
  80. sage/libs/ntl/ntl_lzz_p.cpython-314t-aarch64-linux-gnu.so +0 -0
  81. sage/libs/ntl/ntl_lzz_p.pxd +8 -0
  82. sage/libs/ntl/ntl_lzz_p.pyx +440 -0
  83. sage/libs/ntl/ntl_lzz_pContext.cpython-314t-aarch64-linux-gnu.so +0 -0
  84. sage/libs/ntl/ntl_lzz_pContext.pxd +7 -0
  85. sage/libs/ntl/ntl_lzz_pContext.pyx +137 -0
  86. sage/libs/ntl/ntl_lzz_pX.cpython-314t-aarch64-linux-gnu.so +0 -0
  87. sage/libs/ntl/ntl_lzz_pX.pxd +10 -0
  88. sage/libs/ntl/ntl_lzz_pX.pyx +902 -0
  89. sage/libs/ntl/ntl_mat_GF2.cpython-314t-aarch64-linux-gnu.so +0 -0
  90. sage/libs/ntl/ntl_mat_GF2.pxd +8 -0
  91. sage/libs/ntl/ntl_mat_GF2.pyx +612 -0
  92. sage/libs/ntl/ntl_mat_GF2E.cpython-314t-aarch64-linux-gnu.so +0 -0
  93. sage/libs/ntl/ntl_mat_GF2E.pxd +10 -0
  94. sage/libs/ntl/ntl_mat_GF2E.pyx +752 -0
  95. sage/libs/ntl/ntl_mat_ZZ.cpython-314t-aarch64-linux-gnu.so +0 -0
  96. sage/libs/ntl/ntl_mat_ZZ.pxd +6 -0
  97. sage/libs/ntl/ntl_mat_ZZ.pyx +1523 -0
  98. sage/libs/ntl/ntl_tools.pxd +3 -0
  99. sage/libs/ntl/ntlwrap.h +53 -0
  100. sage/libs/ntl/ntlwrap_impl.h +743 -0
  101. sage/libs/ntl/types.pxd +157 -0
  102. sage/libs/ntl/vec_GF2.pxd +26 -0
  103. sage/libs/ntl/vec_GF2E.pxd +2 -0
  104. sage/matrix/all__sagemath_ntl.py +1 -0
  105. sage/matrix/matrix_modn_dense_double.pxd +10 -0
  106. sage/matrix/matrix_modn_dense_float.pxd +9 -0
  107. sage/matrix/matrix_modn_dense_template.pxi +3257 -0
  108. sage/matrix/matrix_modn_dense_template_header.pxi +15 -0
  109. sage/matrix/matrix_modn_sparse.pxd +8 -0
  110. sage/misc/all__sagemath_ntl.py +1 -0
  111. sage/rings/all__sagemath_ntl.py +7 -0
  112. sage/rings/bernmm.cpython-314t-aarch64-linux-gnu.so +0 -0
  113. sage/rings/bernmm.pyx +161 -0
  114. sage/rings/bernoulli_mod_p.cpython-314t-aarch64-linux-gnu.so +0 -0
  115. sage/rings/bernoulli_mod_p.pyx +313 -0
  116. sage/rings/finite_rings/all__sagemath_ntl.py +1 -0
  117. sage/rings/finite_rings/finite_field_ntl_gf2e.py +305 -0
  118. sage/rings/finite_rings/residue_field_ntl_gf2e.cpython-314t-aarch64-linux-gnu.so +0 -0
  119. sage/rings/finite_rings/residue_field_ntl_gf2e.pyx +140 -0
  120. sage/rings/padics/all__sagemath_ntl.py +5 -0
  121. sage/rings/padics/padic_ZZ_pX_CA_element.cpython-314t-aarch64-linux-gnu.so +0 -0
  122. sage/rings/padics/padic_ZZ_pX_CA_element.pxd +25 -0
  123. sage/rings/padics/padic_ZZ_pX_CA_element.pyx +2368 -0
  124. sage/rings/padics/padic_ZZ_pX_CR_element.cpython-314t-aarch64-linux-gnu.so +0 -0
  125. sage/rings/padics/padic_ZZ_pX_CR_element.pxd +33 -0
  126. sage/rings/padics/padic_ZZ_pX_CR_element.pyx +3277 -0
  127. sage/rings/padics/padic_ZZ_pX_FM_element.cpython-314t-aarch64-linux-gnu.so +0 -0
  128. sage/rings/padics/padic_ZZ_pX_FM_element.pxd +12 -0
  129. sage/rings/padics/padic_ZZ_pX_FM_element.pyx +1739 -0
  130. sage/rings/padics/padic_ZZ_pX_element.cpython-314t-aarch64-linux-gnu.so +0 -0
  131. sage/rings/padics/padic_ZZ_pX_element.pxd +6 -0
  132. sage/rings/padics/padic_ZZ_pX_element.pyx +919 -0
  133. sage/rings/padics/padic_ext_element.cpython-314t-aarch64-linux-gnu.so +0 -0
  134. sage/rings/padics/padic_ext_element.pxd +38 -0
  135. sage/rings/padics/padic_ext_element.pyx +512 -0
  136. sage/rings/padics/pow_computer_ext.cpython-314t-aarch64-linux-gnu.so +0 -0
  137. sage/rings/padics/pow_computer_ext.pxd +107 -0
  138. sage/rings/padics/pow_computer_ext.pyx +2401 -0
  139. sage/rings/polynomial/all__sagemath_ntl.py +1 -0
  140. sage/rings/polynomial/evaluation_ntl.cpython-314t-aarch64-linux-gnu.so +0 -0
  141. sage/rings/polynomial/evaluation_ntl.pxd +7 -0
  142. sage/rings/polynomial/evaluation_ntl.pyx +70 -0
  143. sage/rings/polynomial/polynomial_gf2x.cpython-314t-aarch64-linux-gnu.so +0 -0
  144. sage/rings/polynomial/polynomial_gf2x.pxd +10 -0
  145. sage/rings/polynomial/polynomial_gf2x.pyx +364 -0
  146. sage/rings/polynomial/polynomial_integer_dense_ntl.cpython-314t-aarch64-linux-gnu.so +0 -0
  147. sage/rings/polynomial/polynomial_integer_dense_ntl.pxd +8 -0
  148. sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +1128 -0
  149. sage/rings/polynomial/polynomial_modn_dense_ntl.cpython-314t-aarch64-linux-gnu.so +0 -0
  150. sage/rings/polynomial/polynomial_modn_dense_ntl.pxd +36 -0
  151. sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +2049 -0
  152. sage/rings/polynomial/polynomial_template.pxi +842 -0
  153. sage/rings/polynomial/polynomial_template_header.pxi +11 -0
  154. sage/rings/polynomial/polynomial_zz_pex.cpython-314t-aarch64-linux-gnu.so +0 -0
  155. sage/rings/polynomial/polynomial_zz_pex.pxd +12 -0
  156. sage/rings/polynomial/polynomial_zz_pex.pyx +778 -0
  157. sage/rings/real_mpfi.pxd +50 -0
  158. sage/schemes/all__sagemath_ntl.py +1 -0
  159. sage/schemes/hyperelliptic_curves/all__sagemath_ntl.py +1 -0
  160. sage/schemes/hyperelliptic_curves/hypellfrob.cpython-314t-aarch64-linux-gnu.so +0 -0
  161. 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()))