passagemath-ntl 10.6.38__cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-ntl might be problematic. Click here for more details.

Files changed (162) hide show
  1. passagemath_ntl/__init__.py +3 -0
  2. passagemath_ntl-10.6.38.dist-info/METADATA +122 -0
  3. passagemath_ntl-10.6.38.dist-info/RECORD +162 -0
  4. passagemath_ntl-10.6.38.dist-info/WHEEL +6 -0
  5. passagemath_ntl-10.6.38.dist-info/top_level.txt +3 -0
  6. passagemath_ntl.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
  7. passagemath_ntl.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  8. passagemath_ntl.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
  9. passagemath_ntl.libs/libmpfr-9d41ebf1.so.6.2.1 +0 -0
  10. passagemath_ntl.libs/libntl-1bc30f7e.so.45.0.0 +0 -0
  11. sage/all__sagemath_ntl.py +7 -0
  12. sage/libs/all__sagemath_ntl.py +3 -0
  13. sage/libs/mpfi/__init__.pxd +287 -0
  14. sage/libs/mpfi/types.pxd +10 -0
  15. sage/libs/ntl/GF2.pxd +18 -0
  16. sage/libs/ntl/GF2E.pxd +28 -0
  17. sage/libs/ntl/GF2EX.pxd +12 -0
  18. sage/libs/ntl/GF2X.pxd +81 -0
  19. sage/libs/ntl/ZZ.pxd +93 -0
  20. sage/libs/ntl/ZZX.pxd +85 -0
  21. sage/libs/ntl/ZZ_p.pxd +28 -0
  22. sage/libs/ntl/ZZ_pE.pxd +37 -0
  23. sage/libs/ntl/ZZ_pEX.pxd +106 -0
  24. sage/libs/ntl/ZZ_pX.pxd +122 -0
  25. sage/libs/ntl/__init__.py +4 -0
  26. sage/libs/ntl/all.py +72 -0
  27. sage/libs/ntl/conversion.pxd +106 -0
  28. sage/libs/ntl/convert.cpython-314-aarch64-linux-gnu.so +0 -0
  29. sage/libs/ntl/convert.pxd +7 -0
  30. sage/libs/ntl/convert.pyx +38 -0
  31. sage/libs/ntl/decl.pxi +18 -0
  32. sage/libs/ntl/error.cpython-314-aarch64-linux-gnu.so +0 -0
  33. sage/libs/ntl/error.pyx +63 -0
  34. sage/libs/ntl/lzz_p.pxd +20 -0
  35. sage/libs/ntl/lzz_pX.pxd +59 -0
  36. sage/libs/ntl/mat_GF2.pxd +30 -0
  37. sage/libs/ntl/mat_GF2E.pxd +30 -0
  38. sage/libs/ntl/mat_ZZ.pxd +59 -0
  39. sage/libs/ntl/misc.pxi +33 -0
  40. sage/libs/ntl/ntl_GF2.cpython-314-aarch64-linux-gnu.so +0 -0
  41. sage/libs/ntl/ntl_GF2.pxd +5 -0
  42. sage/libs/ntl/ntl_GF2.pyx +281 -0
  43. sage/libs/ntl/ntl_GF2E.cpython-314-aarch64-linux-gnu.so +0 -0
  44. sage/libs/ntl/ntl_GF2E.pxd +8 -0
  45. sage/libs/ntl/ntl_GF2E.pyx +488 -0
  46. sage/libs/ntl/ntl_GF2EContext.cpython-314-aarch64-linux-gnu.so +0 -0
  47. sage/libs/ntl/ntl_GF2EContext.pxd +9 -0
  48. sage/libs/ntl/ntl_GF2EContext.pyx +134 -0
  49. sage/libs/ntl/ntl_GF2EX.cpython-314-aarch64-linux-gnu.so +0 -0
  50. sage/libs/ntl/ntl_GF2EX.pxd +10 -0
  51. sage/libs/ntl/ntl_GF2EX.pyx +251 -0
  52. sage/libs/ntl/ntl_GF2X.cpython-314-aarch64-linux-gnu.so +0 -0
  53. sage/libs/ntl/ntl_GF2X.pxd +5 -0
  54. sage/libs/ntl/ntl_GF2X.pyx +771 -0
  55. sage/libs/ntl/ntl_GF2X_linkage.pxi +404 -0
  56. sage/libs/ntl/ntl_ZZ.cpython-314-aarch64-linux-gnu.so +0 -0
  57. sage/libs/ntl/ntl_ZZ.pxd +7 -0
  58. sage/libs/ntl/ntl_ZZ.pyx +541 -0
  59. sage/libs/ntl/ntl_ZZX.cpython-314-aarch64-linux-gnu.so +0 -0
  60. sage/libs/ntl/ntl_ZZX.pxd +7 -0
  61. sage/libs/ntl/ntl_ZZX.pyx +1206 -0
  62. sage/libs/ntl/ntl_ZZ_p.cpython-314-aarch64-linux-gnu.so +0 -0
  63. sage/libs/ntl/ntl_ZZ_p.pxd +10 -0
  64. sage/libs/ntl/ntl_ZZ_p.pyx +509 -0
  65. sage/libs/ntl/ntl_ZZ_pContext.cpython-314-aarch64-linux-gnu.so +0 -0
  66. sage/libs/ntl/ntl_ZZ_pContext.pxd +22 -0
  67. sage/libs/ntl/ntl_ZZ_pContext.pyx +201 -0
  68. sage/libs/ntl/ntl_ZZ_pE.cpython-314-aarch64-linux-gnu.so +0 -0
  69. sage/libs/ntl/ntl_ZZ_pE.pxd +11 -0
  70. sage/libs/ntl/ntl_ZZ_pE.pyx +349 -0
  71. sage/libs/ntl/ntl_ZZ_pEContext.cpython-314-aarch64-linux-gnu.so +0 -0
  72. sage/libs/ntl/ntl_ZZ_pEContext.pxd +23 -0
  73. sage/libs/ntl/ntl_ZZ_pEContext.pyx +226 -0
  74. sage/libs/ntl/ntl_ZZ_pEX.cpython-314-aarch64-linux-gnu.so +0 -0
  75. sage/libs/ntl/ntl_ZZ_pEX.pxd +10 -0
  76. sage/libs/ntl/ntl_ZZ_pEX.pyx +1255 -0
  77. sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi +420 -0
  78. sage/libs/ntl/ntl_ZZ_pX.cpython-314-aarch64-linux-gnu.so +0 -0
  79. sage/libs/ntl/ntl_ZZ_pX.pxd +17 -0
  80. sage/libs/ntl/ntl_ZZ_pX.pyx +1532 -0
  81. sage/libs/ntl/ntl_lzz_p.cpython-314-aarch64-linux-gnu.so +0 -0
  82. sage/libs/ntl/ntl_lzz_p.pxd +8 -0
  83. sage/libs/ntl/ntl_lzz_p.pyx +440 -0
  84. sage/libs/ntl/ntl_lzz_pContext.cpython-314-aarch64-linux-gnu.so +0 -0
  85. sage/libs/ntl/ntl_lzz_pContext.pxd +7 -0
  86. sage/libs/ntl/ntl_lzz_pContext.pyx +137 -0
  87. sage/libs/ntl/ntl_lzz_pX.cpython-314-aarch64-linux-gnu.so +0 -0
  88. sage/libs/ntl/ntl_lzz_pX.pxd +10 -0
  89. sage/libs/ntl/ntl_lzz_pX.pyx +902 -0
  90. sage/libs/ntl/ntl_mat_GF2.cpython-314-aarch64-linux-gnu.so +0 -0
  91. sage/libs/ntl/ntl_mat_GF2.pxd +8 -0
  92. sage/libs/ntl/ntl_mat_GF2.pyx +612 -0
  93. sage/libs/ntl/ntl_mat_GF2E.cpython-314-aarch64-linux-gnu.so +0 -0
  94. sage/libs/ntl/ntl_mat_GF2E.pxd +10 -0
  95. sage/libs/ntl/ntl_mat_GF2E.pyx +752 -0
  96. sage/libs/ntl/ntl_mat_ZZ.cpython-314-aarch64-linux-gnu.so +0 -0
  97. sage/libs/ntl/ntl_mat_ZZ.pxd +6 -0
  98. sage/libs/ntl/ntl_mat_ZZ.pyx +1523 -0
  99. sage/libs/ntl/ntl_tools.pxd +3 -0
  100. sage/libs/ntl/ntlwrap.h +53 -0
  101. sage/libs/ntl/ntlwrap_impl.h +743 -0
  102. sage/libs/ntl/types.pxd +157 -0
  103. sage/libs/ntl/vec_GF2.pxd +26 -0
  104. sage/libs/ntl/vec_GF2E.pxd +2 -0
  105. sage/matrix/all__sagemath_ntl.py +1 -0
  106. sage/matrix/matrix_modn_dense_double.pxd +10 -0
  107. sage/matrix/matrix_modn_dense_float.pxd +9 -0
  108. sage/matrix/matrix_modn_dense_template.pxi +3257 -0
  109. sage/matrix/matrix_modn_dense_template_header.pxi +15 -0
  110. sage/matrix/matrix_modn_sparse.pxd +8 -0
  111. sage/misc/all__sagemath_ntl.py +1 -0
  112. sage/rings/all__sagemath_ntl.py +7 -0
  113. sage/rings/bernmm.cpython-314-aarch64-linux-gnu.so +0 -0
  114. sage/rings/bernmm.pyx +161 -0
  115. sage/rings/bernoulli_mod_p.cpython-314-aarch64-linux-gnu.so +0 -0
  116. sage/rings/bernoulli_mod_p.pyx +313 -0
  117. sage/rings/finite_rings/all__sagemath_ntl.py +1 -0
  118. sage/rings/finite_rings/finite_field_ntl_gf2e.py +305 -0
  119. sage/rings/finite_rings/residue_field_ntl_gf2e.cpython-314-aarch64-linux-gnu.so +0 -0
  120. sage/rings/finite_rings/residue_field_ntl_gf2e.pyx +140 -0
  121. sage/rings/padics/all__sagemath_ntl.py +5 -0
  122. sage/rings/padics/padic_ZZ_pX_CA_element.cpython-314-aarch64-linux-gnu.so +0 -0
  123. sage/rings/padics/padic_ZZ_pX_CA_element.pxd +25 -0
  124. sage/rings/padics/padic_ZZ_pX_CA_element.pyx +2368 -0
  125. sage/rings/padics/padic_ZZ_pX_CR_element.cpython-314-aarch64-linux-gnu.so +0 -0
  126. sage/rings/padics/padic_ZZ_pX_CR_element.pxd +33 -0
  127. sage/rings/padics/padic_ZZ_pX_CR_element.pyx +3277 -0
  128. sage/rings/padics/padic_ZZ_pX_FM_element.cpython-314-aarch64-linux-gnu.so +0 -0
  129. sage/rings/padics/padic_ZZ_pX_FM_element.pxd +12 -0
  130. sage/rings/padics/padic_ZZ_pX_FM_element.pyx +1739 -0
  131. sage/rings/padics/padic_ZZ_pX_element.cpython-314-aarch64-linux-gnu.so +0 -0
  132. sage/rings/padics/padic_ZZ_pX_element.pxd +6 -0
  133. sage/rings/padics/padic_ZZ_pX_element.pyx +919 -0
  134. sage/rings/padics/padic_ext_element.cpython-314-aarch64-linux-gnu.so +0 -0
  135. sage/rings/padics/padic_ext_element.pxd +38 -0
  136. sage/rings/padics/padic_ext_element.pyx +512 -0
  137. sage/rings/padics/pow_computer_ext.cpython-314-aarch64-linux-gnu.so +0 -0
  138. sage/rings/padics/pow_computer_ext.pxd +107 -0
  139. sage/rings/padics/pow_computer_ext.pyx +2401 -0
  140. sage/rings/polynomial/all__sagemath_ntl.py +1 -0
  141. sage/rings/polynomial/evaluation_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
  142. sage/rings/polynomial/evaluation_ntl.pxd +7 -0
  143. sage/rings/polynomial/evaluation_ntl.pyx +70 -0
  144. sage/rings/polynomial/polynomial_gf2x.cpython-314-aarch64-linux-gnu.so +0 -0
  145. sage/rings/polynomial/polynomial_gf2x.pxd +10 -0
  146. sage/rings/polynomial/polynomial_gf2x.pyx +364 -0
  147. sage/rings/polynomial/polynomial_integer_dense_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
  148. sage/rings/polynomial/polynomial_integer_dense_ntl.pxd +8 -0
  149. sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +1128 -0
  150. sage/rings/polynomial/polynomial_modn_dense_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
  151. sage/rings/polynomial/polynomial_modn_dense_ntl.pxd +36 -0
  152. sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +2049 -0
  153. sage/rings/polynomial/polynomial_template.pxi +842 -0
  154. sage/rings/polynomial/polynomial_template_header.pxi +11 -0
  155. sage/rings/polynomial/polynomial_zz_pex.cpython-314-aarch64-linux-gnu.so +0 -0
  156. sage/rings/polynomial/polynomial_zz_pex.pxd +12 -0
  157. sage/rings/polynomial/polynomial_zz_pex.pyx +778 -0
  158. sage/rings/real_mpfi.pxd +50 -0
  159. sage/schemes/all__sagemath_ntl.py +1 -0
  160. sage/schemes/hyperelliptic_curves/all__sagemath_ntl.py +1 -0
  161. sage/schemes/hyperelliptic_curves/hypellfrob.cpython-314-aarch64-linux-gnu.so +0 -0
  162. sage/schemes/hyperelliptic_curves/hypellfrob.pyx +252 -0
@@ -0,0 +1,1532 @@
1
+ # sage_setup: distribution = sagemath-ntl
2
+ # distutils: libraries = NTL_LIBRARIES gmp M_LIBRARIES
3
+ # distutils: extra_compile_args = NTL_CFLAGS
4
+ # distutils: include_dirs = NTL_INCDIR
5
+ # distutils: library_dirs = NTL_LIBDIR
6
+ # distutils: extra_link_args = NTL_LIBEXTRA
7
+ # distutils: language = c++
8
+
9
+ # ****************************************************************************
10
+ # Copyright (C) 2005 William Stein <wstein@gmail.com>
11
+ #
12
+ # Distributed under the terms of the GNU General Public License (GPL)
13
+ #
14
+ # This code is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # General Public License for more details.
18
+ #
19
+ # The full text of the GPL is available at:
20
+ #
21
+ # https://www.gnu.org/licenses/
22
+ # ****************************************************************************
23
+
24
+ from cysignals.signals cimport sig_on, sig_off
25
+ from sage.ext.cplusplus cimport ccrepr, ccreadstr
26
+
27
+ include 'misc.pxi'
28
+ include 'decl.pxi'
29
+
30
+ from cpython.object cimport Py_EQ, Py_NE
31
+ from sage.cpython.string cimport char_to_str
32
+ from sage.rings.integer cimport Integer
33
+ from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
34
+ from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p
35
+ from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class
36
+ from sage.libs.ntl.ntl_ZZ_pContext import ntl_ZZ_pContext
37
+ from sage.libs.ntl.ntl_ZZ import unpickle_class_args
38
+ from sage.misc.randstate cimport current_randstate
39
+ from sage.libs.gmp.mpz cimport *
40
+
41
+
42
+ cdef inline make_ZZ_p(ZZ_p_c* x, ntl_ZZ_pContext_class ctx):
43
+ cdef ntl_ZZ_p y
44
+ sig_off()
45
+ y = ntl_ZZ_p(modulus = ctx)
46
+ y.x = x[0]
47
+ del x
48
+ return y
49
+
50
+
51
+ cdef make_ZZ_pX(ZZ_pX_c* x, ntl_ZZ_pContext_class ctx):
52
+ cdef ntl_ZZ_pX y
53
+ y = <ntl_ZZ_pX>ntl_ZZ_pX.__new__(ntl_ZZ_pX)
54
+ y.c = ctx
55
+ y.x = x[0]
56
+ del x
57
+ sig_off()
58
+ return y
59
+
60
+
61
+ ##############################################################################
62
+ #
63
+ # ZZ_pX -- polynomials over the integers modulo p
64
+ #
65
+ ##############################################################################
66
+
67
+ cdef class ntl_ZZ_pX():
68
+ r"""
69
+ The class \class{ZZ_pX} implements polynomial arithmetic modulo `p`.
70
+
71
+ Polynomial arithmetic is implemented using the FFT, combined with
72
+ the Chinese Remainder Theorem. A more detailed description of the
73
+ techniques used here can be found in [Shoup, J. Symbolic
74
+ Comp. 20:363-397, 1995].
75
+
76
+ Small degree polynomials are multiplied either with classical
77
+ or Karatsuba algorithms.
78
+ """
79
+
80
+ # See ntl_ZZ_pX.pxd for definition of data members
81
+ def __init__(self, v=None, modulus=None):
82
+ """
83
+ EXAMPLES::
84
+
85
+ sage: c = ntl.ZZ_pContext(ntl.ZZ(20))
86
+ sage: f = ntl.ZZ_pX([1,2,5,-9], c)
87
+ sage: f
88
+ [1 2 5 11]
89
+ sage: g = ntl.ZZ_pX([0,0,0], c); g
90
+ []
91
+ sage: g[10]=5
92
+ sage: g
93
+ [0 0 0 0 0 0 0 0 0 0 5]
94
+ sage: g[10]
95
+ 5
96
+ """
97
+ if modulus is None:
98
+ raise ValueError("You must specify a modulus when creating a ZZ_pX.")
99
+
100
+ # self.c._assert_is_current_modulus() # the context was restored in __new__
101
+ cdef ntl_ZZ_p cc
102
+ cdef Py_ssize_t i
103
+
104
+ if isinstance(v, ntl_ZZ_pX) and (<ntl_ZZ_pX>v).c is self.c:
105
+ self.x = (<ntl_ZZ_pX>v).x
106
+ elif isinstance(v, (list, tuple, xrange)):
107
+ for i, x in enumerate(v):
108
+ if not isinstance(x, ntl_ZZ_p):
109
+ cc = ntl_ZZ_p(x, self.c)
110
+ self.c.restore_c()
111
+ else:
112
+ cc = x
113
+ ZZ_pX_SetCoeff(self.x, i, cc.x)
114
+ elif v is not None:
115
+ s = str(v).replace(',', ' ').replace('L', '') # can change the modulus; Issue #25790
116
+ self.c.restore_c()
117
+ ccreadstr(self.x, s)
118
+
119
+ def __cinit__(self, v=None, modulus=None):
120
+ #################### WARNING ###################
121
+ ## Before creating a ZZ_pX, you must create a ##
122
+ ## ZZ_pContext, and restore it. In Python, ##
123
+ ## the error checking in __init__ will prevent##
124
+ ## you from constructing an ntl_ZZ_p ##
125
+ ## inappropriately. However, from Cython, you##
126
+ ## could do r = ntl_ZZ_p.__new__(ntl_ZZ_p) without
127
+ ## first restoring a ZZ_pContext, which could ##
128
+ ## have unfortunate consequences. See _new ##
129
+ ## defined below for an example of the right ##
130
+ ## way to short-circuit __init__ (or just call##
131
+ ## _new in your own code). ##
132
+ ################################################
133
+ if modulus is None:
134
+ return
135
+ if isinstance(modulus, ntl_ZZ_pContext_class):
136
+ self.c = <ntl_ZZ_pContext_class>modulus
137
+ self.c.restore_c()
138
+ elif modulus is not None:
139
+ self.c = <ntl_ZZ_pContext_class>ntl_ZZ_pContext(ntl_ZZ(modulus))
140
+ self.c.restore_c()
141
+
142
+ cdef ntl_ZZ_pX _new(self):
143
+ cdef ntl_ZZ_pX r
144
+ self.c.restore_c()
145
+ r = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
146
+ r.c = self.c
147
+ return r
148
+
149
+ def __reduce__(self):
150
+ """
151
+ TESTS::
152
+
153
+ sage: f = ntl.ZZ_pX([1,2,3,7], 5); f
154
+ [1 2 3 2]
155
+ sage: loads(dumps(f)) == f
156
+ True
157
+ """
158
+ return unpickle_class_args, (ntl_ZZ_pX, (self.list(), self.get_modulus_context()))
159
+
160
+ def __repr__(self):
161
+ """
162
+ Return the string representation of ``self``.
163
+
164
+ EXAMPLES::
165
+
166
+ sage: x = ntl.ZZ_pX([1,0,8],5)
167
+ sage: x
168
+ [1 0 3]
169
+ sage: x.__repr__()
170
+ '[1 0 3]'
171
+ """
172
+ self.c.restore_c()
173
+ return ccrepr(self.x)
174
+
175
+ def __copy__(self):
176
+ """
177
+ Return a copy of ``self``.
178
+
179
+ EXAMPLES::
180
+
181
+ sage: x = ntl.ZZ_pX([0,5,-3],11)
182
+ sage: y = copy(x)
183
+ sage: x == y
184
+ True
185
+ sage: x is y
186
+ False
187
+ sage: x[0] = 4; y
188
+ [0 5 8]
189
+ """
190
+ cdef ntl_ZZ_pX r = self._new()
191
+ #self.c.restore_c() # restored in _new()
192
+ r.x = self.x
193
+ return r
194
+
195
+ def get_modulus_context(self):
196
+ """
197
+ Return the modulus for ``self``.
198
+
199
+ EXAMPLES::
200
+
201
+ sage: x = ntl.ZZ_pX([0,5,3],17)
202
+ sage: c = x.get_modulus_context()
203
+ sage: y = ntl.ZZ_pX([5],c)
204
+ sage: x+y
205
+ [5 5 3]
206
+ """
207
+ return self.c
208
+
209
+ def __setitem__(self, long i, a):
210
+ r"""
211
+ EXAMPLES::
212
+
213
+ sage: c = ntl.ZZ_pContext(23)
214
+ sage: x = ntl.ZZ_pX([2, 3, 4], c)
215
+ sage: x[1] = 5
216
+ sage: x
217
+ [2 5 4]
218
+ """
219
+ if i < 0:
220
+ raise IndexError("index (i=%s) must be >= 0" % i)
221
+ cdef ntl_ZZ_p _a
222
+ _a = ntl_ZZ_p(a,self.c)
223
+ self.c.restore_c()
224
+ ZZ_pX_SetCoeff(self.x, i, _a.x)
225
+
226
+ cdef void setitem_from_int(ntl_ZZ_pX self, long i, int value) noexcept:
227
+ r"""
228
+ Set `i`-th coefficient to value.
229
+
230
+ AUTHOR: David Harvey (2006-08-05)
231
+ """
232
+ self.c.restore_c()
233
+ ZZ_pX_SetCoeff_long(self.x, i, value)
234
+
235
+ def _setitem_from_int_doctest(self, i, value):
236
+ r"""
237
+ This method exists solely for automated testing of setitem_from_int().
238
+
239
+ TESTS::
240
+
241
+ sage: c = ntl.ZZ_pContext(20)
242
+ sage: x = ntl.ZZ_pX([2, 3, 4], c)
243
+ sage: x._setitem_from_int_doctest(5, 42)
244
+ sage: x
245
+ [2 3 4 0 0 2]
246
+ """
247
+ self.c.restore_c()
248
+ self.setitem_from_int(i, value)
249
+
250
+ def __getitem__(self, long i):
251
+ r"""
252
+ Return the `i`-th entry of ``self``.
253
+
254
+ EXAMPLES::
255
+
256
+ sage: c = ntl.ZZ_pContext(20)
257
+ sage: x = ntl.ZZ_pX([2, 3, 4], c)
258
+ sage: x[1]
259
+ 3
260
+ """
261
+ cdef ntl_ZZ_p r
262
+ r = ntl_ZZ_p.__new__(ntl_ZZ_p)
263
+ r.c = self.c
264
+ self.c.restore_c()
265
+ if i < 0:
266
+ r.set_from_int(0)
267
+ else:
268
+ r.x = ZZ_pX_coeff( self.x, i)
269
+ return r
270
+
271
+ cdef int getitem_as_int(ntl_ZZ_pX self, long i) noexcept:
272
+ r"""
273
+ Return `i`-th coefficient as C int.
274
+
275
+ Return value is only valid if the result fits into an int.
276
+
277
+ AUTHOR: David Harvey (2006-08-05)
278
+ """
279
+ self.c.restore_c()
280
+ cdef ZZ_p_c r
281
+ cdef long l = 0
282
+ sig_on()
283
+ r = ZZ_pX_coeff( self.x, i)
284
+ ZZ_conv_to_long(l, ZZ_p_rep(r))
285
+ sig_off()
286
+ return l
287
+
288
+ def _getitem_as_int_doctest(self, i):
289
+ r"""
290
+ This method exists solely for automated testing of getitem_as_int().
291
+
292
+ TESTS::
293
+
294
+ sage: c = ntl.ZZ_pContext(20)
295
+ sage: x = ntl.ZZ_pX([2, 3, 5, -7, 11], c)
296
+ sage: i = x._getitem_as_int_doctest(3)
297
+ sage: i
298
+ 13
299
+ sage: type(i)
300
+ <... 'int'>
301
+ sage: x._getitem_as_int_doctest(15)
302
+ 0
303
+ """
304
+ # self.c.restore_c() # restored in getitem_as_int()
305
+ return self.getitem_as_int(i)
306
+
307
+ def list(self):
308
+ """
309
+ Return list of entries as a list of ntl_ZZ_p.
310
+
311
+ EXAMPLES::
312
+
313
+ sage: x = ntl.ZZ_pX([1,3,5],11)
314
+ sage: x.list()
315
+ [1, 3, 5]
316
+ sage: type(x.list()[0])
317
+ <class 'sage.libs.ntl.ntl_ZZ_p.ntl_ZZ_p'>
318
+ """
319
+ # could be sped up.
320
+ self.c.restore_c()
321
+ cdef Py_ssize_t i
322
+ return [self[i] for i from 0 <= i <= self.degree()]
323
+
324
+ def __add__(ntl_ZZ_pX self, ntl_ZZ_pX other):
325
+ """
326
+ EXAMPLES::
327
+
328
+ sage: c = ntl.ZZ_pContext(20)
329
+ sage: ntl.ZZ_pX(range(5),c) + ntl.ZZ_pX(range(6),c)
330
+ [0 2 4 6 8 5]
331
+ """
332
+ if self.c is not other.c:
333
+ raise ValueError("You cannot perform arithmetic with elements of different moduli.")
334
+ cdef ntl_ZZ_pX r = self._new()
335
+ sig_on()
336
+ #self.c.restore_c() # restored in _new()
337
+ ZZ_pX_add(r.x, self.x, other.x)
338
+ sig_off()
339
+ return r
340
+
341
+ def __sub__(ntl_ZZ_pX self, ntl_ZZ_pX other):
342
+ """
343
+ EXAMPLES::
344
+
345
+ sage: c = ntl.ZZ_pContext(20)
346
+ sage: ntl.ZZ_pX(range(5),c) - ntl.ZZ_pX(range(6),c)
347
+ [0 0 0 0 0 15]
348
+ """
349
+ if self.c is not other.c:
350
+ raise ValueError("You cannot perform arithmetic with elements of different moduli.")
351
+ cdef ntl_ZZ_pX r = self._new()
352
+ sig_on()
353
+ #self.c.restore_c() # restored in _new()
354
+ ZZ_pX_sub(r.x, self.x, other.x)
355
+ sig_off()
356
+ return r
357
+
358
+ def __mul__(ntl_ZZ_pX self, ntl_ZZ_pX other):
359
+ """
360
+ EXAMPLES::
361
+
362
+ sage: c1 = ntl.ZZ_pContext(20)
363
+ sage: alpha = ntl.ZZ_pX(range(5), c1)
364
+ sage: beta = ntl.ZZ_pX(range(6), c1)
365
+ sage: alpha * beta
366
+ [0 0 1 4 10 0 10 14 11]
367
+ sage: c2 = ntl.ZZ_pContext(ntl.ZZ(5)) # we can mix up the moduli
368
+ sage: x = ntl.ZZ_pX([2, 3, 4], c2)
369
+ sage: x^2
370
+ [4 2 0 4 1]
371
+ sage: alpha * beta # back to the first one and the ntl modulus gets reset correctly
372
+ [0 0 1 4 10 0 10 14 11]
373
+ """
374
+ if self.c is not other.c:
375
+ raise ValueError("You cannot perform arithmetic with elements of different moduli.")
376
+ cdef ntl_ZZ_pX r = self._new()
377
+ sig_on()
378
+ # self.c.restore_c() # restored in _new()
379
+ ZZ_pX_mul(r.x, self.x, other.x)
380
+ sig_off()
381
+ return r
382
+
383
+ def __truediv__(ntl_ZZ_pX self, ntl_ZZ_pX other):
384
+ """
385
+ Compute quotient ``self / other``, if the quotient is a polynomial.
386
+ Otherwise an Exception is raised.
387
+
388
+ EXAMPLES::
389
+
390
+ sage: c = ntl.ZZ_pContext(17)
391
+ sage: f = ntl.ZZ_pX([1,2,3], c) * ntl.ZZ_pX([4,5], c)**2
392
+ sage: g = ntl.ZZ_pX([4,5], c)
393
+ sage: f/g
394
+ [4 13 5 15]
395
+ sage: ntl.ZZ_pX([1,2,3],c) * ntl.ZZ_pX([4,5],c)
396
+ [4 13 5 15]
397
+
398
+ sage: f = ntl.ZZ_pX(range(10), c); g = ntl.ZZ_pX([-1,0,1], c)
399
+ sage: f/g
400
+ Traceback (most recent call last):
401
+ ...
402
+ ArithmeticError: self (=[0 1 2 3 4 5 6 7 8 9]) is not divisible by other (=[16 0 1])
403
+ """
404
+ if self.c is not other.c:
405
+ raise ValueError("You cannot perform arithmetic with elements of different moduli.")
406
+ cdef int divisible
407
+ cdef ntl_ZZ_pX r = self._new()
408
+ sig_on()
409
+ #self.c.restore_c() # restored in _new()
410
+ divisible = ZZ_pX_divide(r.x, self.x, other.x)
411
+ sig_off()
412
+ if not divisible:
413
+ raise ArithmeticError("self (=%s) is not divisible by other (=%s)" % (self, other))
414
+ return r
415
+
416
+ def __mod__(ntl_ZZ_pX self, ntl_ZZ_pX other):
417
+ """
418
+ Given polynomials a, b in ZZ_p[X], if p is prime, then there exist polynomials q, r
419
+ in ZZ_p[X] such that a = b*q + r, deg(r) < deg(b). This
420
+ function returns r.
421
+
422
+ If p is not prime this function may raise a :exc:`RuntimeError`
423
+ due to division by a noninvertible element of ZZ_p.
424
+
425
+ EXAMPLES::
426
+
427
+ sage: c = ntl.ZZ_pContext(ntl.ZZ(17))
428
+ sage: f = ntl.ZZ_pX([2,4,6], c); g = ntl.ZZ_pX([2], c)
429
+ sage: f % g # 0
430
+ []
431
+ sage: f = ntl.ZZ_pX(range(10), c); g = ntl.ZZ_pX([-1,0,1], c)
432
+ sage: f % g
433
+ [3 8]
434
+
435
+ sage: c = ntl.ZZ_pContext(ntl.ZZ(16))
436
+ sage: f = ntl.ZZ_pX([2,4,6], c); g = ntl.ZZ_pX([2], c)
437
+ sage: f % g
438
+ Traceback (most recent call last):
439
+ ...
440
+ NTLError: ZZ_p: division by non-invertible element
441
+ """
442
+ if self.c is not other.c:
443
+ raise ValueError("You cannot perform arithmetic with elements of different moduli.")
444
+ cdef ntl_ZZ_pX r = self._new()
445
+ sig_on()
446
+ #self.c.restore_c() # restored in _new()
447
+ ZZ_pX_rem(r.x, self.x, other.x)
448
+ sig_off()
449
+ return r
450
+
451
+ def quo_rem(self, ntl_ZZ_pX other):
452
+ """
453
+ Return the unique integral `q` and `r` such that ``self = q*other +
454
+ r``, if they exist. Otherwise raises an Exception.
455
+
456
+ EXAMPLES::
457
+
458
+ sage: c = ntl.ZZ_pContext(17)
459
+ sage: f = ntl.ZZ_pX(range(10), c); g = ntl.ZZ_pX([-1,0,1], c)
460
+ sage: q, r = f.quo_rem(g)
461
+ sage: q, r
462
+ ([3 7 1 4 14 16 8 9], [3 8])
463
+ sage: q*g + r == f
464
+ True
465
+ """
466
+ if self.c is not other.c:
467
+ raise ValueError("You cannot perform arithmetic with elements of different moduli.")
468
+ cdef ntl_ZZ_pX r = self._new()
469
+ cdef ntl_ZZ_pX q = self._new()
470
+ sig_on()
471
+ #self.c.restore_c() # restored in _new()
472
+ ZZ_pX_DivRem(q.x, r.x, self.x, other.x)
473
+ sig_off()
474
+ return q,r
475
+
476
+ def square(self):
477
+ """
478
+ Return f*f.
479
+
480
+ EXAMPLES::
481
+
482
+ sage: c = ntl.ZZ_pContext(17)
483
+ sage: f = ntl.ZZ_pX([-1,0,1], c)
484
+ sage: f*f
485
+ [1 0 15 0 1]
486
+ """
487
+ #self.c.restore_c() # restored in _new()
488
+ cdef ntl_ZZ_pX r = self._new()
489
+ sig_on()
490
+ ZZ_pX_sqr(r.x, self.x)
491
+ sig_off()
492
+ return r
493
+
494
+ def __pow__(self, n, modulus):
495
+ """
496
+ Return the ``n``-th nonnegative power of ``self``.
497
+
498
+ If ``modulus`` is not ``None``, the exponentiation is performed
499
+ modulo the polynomial ``modulus``.
500
+
501
+ EXAMPLES::
502
+
503
+ sage: c = ntl.ZZ_pContext(20)
504
+ sage: g = ntl.ZZ_pX([-1,0,1],c)
505
+ sage: g**10
506
+ [1 0 10 0 5 0 0 0 10 0 8 0 10 0 0 0 5 0 10 0 1]
507
+
508
+ sage: x = ntl.ZZ_pX([0,1],c)
509
+ sage: x**10
510
+ [0 0 0 0 0 0 0 0 0 0 1]
511
+
512
+ Modular exponentiation::
513
+
514
+ sage: c = ntl.ZZ_pContext(20)
515
+ sage: f = ntl.ZZ_pX([1,0,1],c)
516
+ sage: m = ntl.ZZ_pX([1,0,0,0,0,1],c)
517
+ sage: pow(f, 123**45, m)
518
+ [1 19 3 0 3]
519
+
520
+ Modular exponentiation of ``x``::
521
+
522
+ sage: f = ntl.ZZ_pX([0,1],c)
523
+ sage: f.is_x()
524
+ True
525
+ sage: m = ntl.ZZ_pX([1,1,0,0,0,1],c)
526
+ sage: pow(f, 123**45, m)
527
+ [15 5 5 11]
528
+ """
529
+ if modulus is None:
530
+ return (<ntl_ZZ_pX>self)._pow(n)
531
+ else:
532
+ return (<ntl_ZZ_pX>self)._powmod(Integer(n), modulus)
533
+
534
+ cdef ntl_ZZ_pX _pow(ntl_ZZ_pX self, long n):
535
+ """
536
+ Compute the ``n``-th power of ``self``.
537
+ """
538
+ if n < 0:
539
+ raise NotImplementedError
540
+ cdef long ln = n
541
+ #self.c.restore_c() # restored in _new()
542
+ cdef ntl_ZZ_pX r = self._new()
543
+ if self.is_x() and n >= 1:
544
+ ZZ_pX_LeftShift(r.x, self.x, n-1)
545
+ else:
546
+ sig_on()
547
+ ZZ_pX_power(r.x, self.x, ln)
548
+ sig_off()
549
+ return r
550
+
551
+ cdef ntl_ZZ_pX _powmod(ntl_ZZ_pX self, Integer n, ntl_ZZ_pX modulus):
552
+ r"""
553
+ Compute the ``n``-th power of ``self`` modulo a polynomial.
554
+ """
555
+ cdef ntl_ZZ_pX r = self._new()
556
+ cdef ZZ_c n_ZZ
557
+ cdef ZZ_pX_Modulus_c mod
558
+ is_x = self.is_x()
559
+ sig_on()
560
+ mpz_to_ZZ(&n_ZZ, (<Integer>n).value)
561
+ ZZ_pX_Modulus_build(mod, modulus.x)
562
+ if is_x:
563
+ ZZ_pX_PowerXMod_pre(r.x, n_ZZ, mod)
564
+ else:
565
+ ZZ_pX_PowerMod_pre(r.x, self.x, n_ZZ, mod)
566
+ sig_off()
567
+ return r
568
+
569
+ def __richcmp__(ntl_ZZ_pX self, other, int op):
570
+ """
571
+ Compare ``self`` to ``other``.
572
+
573
+ EXAMPLES::
574
+
575
+ sage: c = ntl.ZZ_pContext(20)
576
+ sage: f = ntl.ZZ_pX([1,2,3],c)
577
+ sage: g = ntl.ZZ_pX([1,2,3,0],c)
578
+ sage: f == g
579
+ True
580
+ sage: g = ntl.ZZ_pX([0,1,2,3],c)
581
+ sage: f != g
582
+ True
583
+ sage: f != 0
584
+ True
585
+ """
586
+ self.c.restore_c()
587
+
588
+ if op != Py_EQ and op != Py_NE:
589
+ raise TypeError("polynomials are not ordered")
590
+
591
+ cdef ntl_ZZ_pX b
592
+ try:
593
+ b = <ntl_ZZ_pX?>other
594
+ except TypeError:
595
+ b = ntl_ZZ_pX(other, self.c)
596
+
597
+ return (op == Py_EQ) == (self.x == b.x)
598
+
599
+ def is_zero(self):
600
+ """
601
+ Return ``True`` exactly if this polynomial is 0.
602
+
603
+ EXAMPLES::
604
+
605
+ sage: c = ntl.ZZ_pContext(20)
606
+ sage: f = ntl.ZZ_pX([0,0,0,20],c)
607
+ sage: f.is_zero()
608
+ True
609
+ sage: f = ntl.ZZ_pX([0,0,1],c)
610
+ sage: f
611
+ [0 0 1]
612
+ sage: f.is_zero()
613
+ False
614
+ """
615
+ self.c.restore_c()
616
+ return bool(ZZ_pX_IsZero(self.x))
617
+
618
+ def is_one(self):
619
+ """
620
+ Return ``True`` exactly if this polynomial is 1.
621
+
622
+ EXAMPLES::
623
+
624
+ sage: c = ntl.ZZ_pContext(20)
625
+ sage: f = ntl.ZZ_pX([1,1],c)
626
+ sage: f.is_one()
627
+ False
628
+ sage: f = ntl.ZZ_pX([1],c)
629
+ sage: f.is_one()
630
+ True
631
+ """
632
+ self.c.restore_c()
633
+ return bool(ZZ_pX_IsOne(self.x))
634
+
635
+ def is_monic(self):
636
+ """
637
+ Return ``True`` exactly if this polynomial is monic.
638
+
639
+ EXAMPLES::
640
+
641
+ sage: c = ntl.ZZ_pContext(20)
642
+ sage: f = ntl.ZZ_pX([2,0,0,1],c)
643
+ sage: f.is_monic()
644
+ True
645
+ sage: g = f.reverse()
646
+ sage: g.is_monic()
647
+ False
648
+ sage: g
649
+ [1 0 0 2]
650
+ sage: f = ntl.ZZ_pX([1,2,0,3,0,2],c)
651
+ sage: f.is_monic()
652
+ False
653
+ """
654
+ self.c.restore_c()
655
+ if ZZ_pX_IsZero(self.x):
656
+ return False
657
+ return bool(ZZ_p_IsOne(ZZ_pX_LeadCoeff(self.x)))
658
+
659
+ def __neg__(self):
660
+ """
661
+ Return the negative of ``self``.
662
+
663
+ EXAMPLES::
664
+
665
+ sage: c = ntl.ZZ_pContext(20)
666
+ sage: f = ntl.ZZ_pX([2,0,0,1],c)
667
+ sage: -f
668
+ [18 0 0 19]
669
+ """
670
+ cdef ntl_ZZ_pX r = self._new()
671
+ self.c.restore_c()
672
+ ZZ_pX_negate(r.x, self.x)
673
+ return r
674
+
675
+ def left_shift(self, long n):
676
+ """
677
+ Return the polynomial obtained by shifting all coefficients of
678
+ this polynomial to the left n positions.
679
+
680
+ EXAMPLES::
681
+
682
+ sage: c = ntl.ZZ_pContext(20)
683
+ sage: f = ntl.ZZ_pX([2,0,0,1],c)
684
+ sage: f
685
+ [2 0 0 1]
686
+ sage: f.left_shift(2)
687
+ [0 0 2 0 0 1]
688
+ sage: f.left_shift(5)
689
+ [0 0 0 0 0 2 0 0 1]
690
+
691
+ A negative left shift is a right shift.
692
+ sage: f.left_shift(-2)
693
+ [0 1]
694
+ """
695
+ #self.c.restore_c() # restored in _new()
696
+ cdef ntl_ZZ_pX r = self._new()
697
+ sig_on()
698
+ ZZ_pX_LeftShift(r.x, self.x, n)
699
+ sig_off()
700
+ return r
701
+
702
+ def right_shift(self, long n):
703
+ """
704
+ Return the polynomial obtained by shifting all coefficients of
705
+ this polynomial to the right n positions.
706
+
707
+ EXAMPLES::
708
+
709
+ sage: c = ntl.ZZ_pContext(20)
710
+ sage: f = ntl.ZZ_pX([2,0,0,1],c)
711
+ sage: f
712
+ [2 0 0 1]
713
+ sage: f.right_shift(2)
714
+ [0 1]
715
+ sage: f.right_shift(5)
716
+ []
717
+ sage: f.right_shift(-2)
718
+ [0 0 2 0 0 1]
719
+ """
720
+ #self.c.restore_c() # restored in _new()
721
+ cdef ntl_ZZ_pX r = self._new()
722
+ sig_on()
723
+ ZZ_pX_RightShift(r.x, self.x, n)
724
+ sig_off()
725
+ return r
726
+
727
+ def _left_pshift(self, ntl_ZZ n):
728
+ """
729
+ Multiply all coefficients by `n` and the context by `n`.
730
+ """
731
+ cdef ntl_ZZ new_c_p = ntl_ZZ.__new__(ntl_ZZ)
732
+ ZZ_mul(new_c_p.x, (<ntl_ZZ>self.c.p).x, n.x)
733
+ cdef ntl_ZZ_pContext_class new_c = <ntl_ZZ_pContext_class>ntl_ZZ_pContext(new_c_p)
734
+ new_c.restore_c()
735
+ cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
736
+ ans.c = new_c
737
+ ZZ_pX_left_pshift(ans.x, self.x, n.x, new_c.x)
738
+ return ans
739
+
740
+ def _right_pshift(self, ntl_ZZ n):
741
+ """
742
+ Divide all coefficients by `n` and the context by `n`. Only really
743
+ makes sense when `n` divides ``self.c.p``.
744
+ """
745
+ cdef ntl_ZZ new_c_p = ntl_ZZ.__new__(ntl_ZZ)
746
+ ZZ_div(new_c_p.x, (<ntl_ZZ>self.c.p).x, n.x)
747
+ cdef ntl_ZZ_pContext_class new_c = <ntl_ZZ_pContext_class>ntl_ZZ_pContext(new_c_p)
748
+ new_c.restore_c()
749
+ cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
750
+ ans.c = new_c
751
+ ZZ_pX_right_pshift(ans.x, self.x, n.x, new_c.x)
752
+ return ans
753
+
754
+ def gcd(self, ntl_ZZ_pX other):
755
+ """
756
+ Return the gcd d = gcd(a, b), where by convention the leading coefficient
757
+ of d is >= 0. We uses a multi-modular algorithm.
758
+
759
+ EXAMPLES::
760
+
761
+ sage: c = ntl.ZZ_pContext(17)
762
+ sage: f = ntl.ZZ_pX([1,2,3],c) * ntl.ZZ_pX([4,5],c)**2
763
+ sage: g = ntl.ZZ_pX([1,1,1],c)**3 * ntl.ZZ_pX([1,2,3],c)
764
+ sage: f.gcd(g)
765
+ [6 12 1]
766
+ sage: g.gcd(f)
767
+ [6 12 1]
768
+ """
769
+ #self.c.restore_c() # restored in _new()
770
+ cdef ntl_ZZ_pX r = self._new()
771
+ sig_on()
772
+ ZZ_pX_GCD(r.x, self.x, other.x)
773
+ sig_off()
774
+ return r
775
+
776
+ def xgcd(self, ntl_ZZ_pX other, plain=True):
777
+ """
778
+ Return `r`, `s`, `t` such that ``r = s*self + t*other``.
779
+
780
+ Here r is the resultant of a and b; if r != 0, then this
781
+ function computes s and t such that: a*s + b*t = r; otherwise
782
+ s and t are both 0.
783
+
784
+ EXAMPLES::
785
+
786
+ sage: c = ntl.ZZ_pContext(17)
787
+ sage: f = ntl.ZZ_pX([1,2,3],c) * ntl.ZZ_pX([4,5],c)**2
788
+ sage: g = ntl.ZZ_pX([1,1,1],c)**3 * ntl.ZZ_pX([1,2,3],c)
789
+ sage: f.xgcd(g) # nothing since they are not coprime
790
+ ([6 12 1], [15 13 6 8 7 9], [4 13])
791
+
792
+ In this example the input quadratic polynomials have a common
793
+ root modulo 13::
794
+
795
+ sage: f = ntl.ZZ_pX([5,0,1],c)
796
+ sage: g = ntl.ZZ_pX([18,0,1],c)
797
+ sage: f.xgcd(g)
798
+ ([1], [13], [4])
799
+ """
800
+ self.c.restore_c()
801
+ cdef ntl_ZZ_pX s = self._new()
802
+ cdef ntl_ZZ_pX t = self._new()
803
+ cdef ntl_ZZ_pX r = self._new()
804
+ sig_on()
805
+ if plain:
806
+ ZZ_pX_PlainXGCD(r.x, s.x, t.x, self.x, other.x)
807
+ else:
808
+ ZZ_pX_XGCD(r.x, s.x, t.x, self.x, other.x)
809
+ sig_off()
810
+ return (r,s,t)
811
+
812
+ def degree(self):
813
+ """
814
+ Return the degree of this polynomial. The degree of the 0
815
+ polynomial is -1.
816
+
817
+ EXAMPLES::
818
+
819
+ sage: c = ntl.ZZ_pContext(20)
820
+ sage: f = ntl.ZZ_pX([5,0,1],c)
821
+ sage: f.degree()
822
+ 2
823
+ sage: f = ntl.ZZ_pX(range(100),c)
824
+ sage: f.degree()
825
+ 99
826
+ sage: f = ntl.ZZ_pX([], c)
827
+ sage: f.degree()
828
+ -1
829
+ sage: f = ntl.ZZ_pX([1],c)
830
+ sage: f.degree()
831
+ 0
832
+ """
833
+ self.c.restore_c()
834
+ return ZZ_pX_deg(self.x)
835
+
836
+ def leading_coefficient(self):
837
+ """
838
+ Return the leading coefficient of this polynomial.
839
+
840
+ EXAMPLES::
841
+
842
+ sage: c = ntl.ZZ_pContext(20)
843
+ sage: f = ntl.ZZ_pX([3,6,9],c)
844
+ sage: f.leading_coefficient()
845
+ 9
846
+ sage: f = ntl.ZZ_pX([],c)
847
+ sage: f.leading_coefficient()
848
+ 0
849
+ """
850
+ self.c.restore_c()
851
+ #return ZZ_pX_LeadCoeff(self.x)
852
+ cdef long i
853
+ i = ZZ_pX_deg(self.x)
854
+ return self[i]
855
+
856
+ def constant_term(self):
857
+ """
858
+ Return the constant coefficient of this polynomial.
859
+
860
+ EXAMPLES::
861
+
862
+ sage: c = ntl.ZZ_pContext(20)
863
+ sage: f = ntl.ZZ_pX([3,6,9],c)
864
+ sage: f.constant_term()
865
+ 3
866
+ sage: f = ntl.ZZ_pX([],c)
867
+ sage: f.constant_term()
868
+ 0
869
+ """
870
+ self.c.restore_c()
871
+ #return ZZ_pX_ConstTerm(self.x)
872
+ return self[0]
873
+
874
+ def set_x(self):
875
+ """
876
+ Set this polynomial to the monomial "x".
877
+
878
+ EXAMPLES::
879
+
880
+ sage: c = ntl.ZZ_pContext(20)
881
+ sage: f = ntl.ZZ_pX([],c)
882
+ sage: f.set_x()
883
+ sage: f
884
+ [0 1]
885
+ sage: g = ntl.ZZ_pX([0,1],c)
886
+ sage: f == g
887
+ True
888
+
889
+ Though f and g are equal, they are not the same objects in memory::
890
+
891
+ sage: f is g
892
+ False
893
+ """
894
+ self.c.restore_c()
895
+ ZZ_pX_SetX(self.x)
896
+ #ZZ_pX_clear(self.x)
897
+ #ZZ_pX_SetCoeff_long(self.x, 1, 1)
898
+
899
+ def is_x(self):
900
+ """
901
+ ``True`` if this is the polynomial "x".
902
+
903
+ EXAMPLES::
904
+
905
+ sage: c = ntl.ZZ_pContext(20)
906
+ sage: f = ntl.ZZ_pX([],c)
907
+ sage: f.set_x()
908
+ sage: f.is_x()
909
+ True
910
+ sage: f = ntl.ZZ_pX([0,1],c)
911
+ sage: f.is_x()
912
+ True
913
+ sage: f = ntl.ZZ_pX([1],c)
914
+ sage: f.is_x()
915
+ False
916
+ """
917
+ return bool(ZZ_pX_IsX(self.x))
918
+
919
+ def convert_to_modulus(self, ntl_ZZ_pContext_class c):
920
+ """
921
+ Return a new ntl_ZZ_pX which is the same as self, but considered modulo a different p.
922
+
923
+ In order for this to make mathematical sense, c.p should divide self.c.p
924
+ (in which case ``self`` is reduced modulo c.p) or self.c.p should divide c.p
925
+ (in which case ``self`` is lifted to something modulo c.p congruent to ``self`` modulo self.c.p)
926
+
927
+ EXAMPLES::
928
+
929
+ sage: a = ntl.ZZ_pX([412,181,991],5^4)
930
+ sage: a
931
+ [412 181 366]
932
+ sage: b = ntl.ZZ_pX([198,333,91],5^4)
933
+ sage: ap = a.convert_to_modulus(ntl.ZZ_pContext(5^2))
934
+ sage: bp = b.convert_to_modulus(ntl.ZZ_pContext(5^2))
935
+ sage: ap
936
+ [12 6 16]
937
+ sage: bp
938
+ [23 8 16]
939
+ sage: ap*bp
940
+ [1 9 8 24 6]
941
+ sage: (a*b).convert_to_modulus(ntl.ZZ_pContext(5^2))
942
+ [1 9 8 24 6]
943
+ """
944
+ c.restore_c()
945
+ cdef ntl_ZZ_pX ans = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
946
+ ZZ_pX_conv_modulus(ans.x, self.x, c.x)
947
+ ans.c = c
948
+ return ans
949
+
950
+ def derivative(self):
951
+ """
952
+ Return the derivative of this polynomial.
953
+
954
+ EXAMPLES::
955
+
956
+ sage: c = ntl.ZZ_pContext(20)
957
+ sage: f = ntl.ZZ_pX([1,7,0,13],c)
958
+ sage: f.derivative()
959
+ [7 0 19]
960
+ """
961
+ cdef ntl_ZZ_pX r = self._new() # restores context
962
+ sig_on()
963
+ ZZ_pX_diff(r.x, self.x)
964
+ sig_off()
965
+ return r
966
+
967
+ def factor(self, verbose=False):
968
+ """
969
+ Return the factorization of ``self``. Assumes ``self`` is
970
+ monic.
971
+
972
+ NOTE: The roots are returned in a random order.
973
+
974
+ EXAMPLES:
975
+
976
+ These computations use pseudo-random numbers, so we set the
977
+ seed for reproducible testing. ::
978
+
979
+ sage: set_random_seed(12)
980
+ sage: ntl.ZZ_pX([-1,0,0,0,0,1],5).factor()
981
+ [([4 1], 5)]
982
+ sage: ls = ntl.ZZ_pX([-1,0,0,0,1],5).factor()
983
+ sage: ls
984
+ [([4 1], 1), ([2 1], 1), ([1 1], 1), ([3 1], 1)]
985
+ sage: prod( [ x[0] for x in ls ] )
986
+ [4 0 0 0 1]
987
+ sage: ntl.ZZ_pX([3,7,0,1], 31).factor()
988
+ [([3 7 0 1], 1)]
989
+ sage: ntl.ZZ_pX([3,7,1,8], 28).factor()
990
+ Traceback (most recent call last):
991
+ ...
992
+ ValueError: self must be monic.
993
+ """
994
+ current_randstate().set_seed_ntl(False)
995
+
996
+ self.c.restore_c()
997
+ cdef ZZ_pX_c** v
998
+ cdef ntl_ZZ_pX r
999
+ cdef long* e
1000
+ cdef long i, n
1001
+ if not self.is_monic():
1002
+ raise ValueError("self must be monic.")
1003
+ sig_on()
1004
+ ZZ_pX_factor(&v, &e, &n, &self.x, verbose)
1005
+ sig_off()
1006
+ F = []
1007
+ for i from 0 <= i < n:
1008
+ r = self._new()
1009
+ r.x = v[i][0]
1010
+ F.append((r, e[i]))
1011
+ #F.append((make_ZZ_pX(v[i], self.c), e[i]))
1012
+ for i from 0 <= i < n:
1013
+ del v[i]
1014
+ sig_free(v)
1015
+ sig_free(e)
1016
+ return F
1017
+
1018
+ def linear_roots(self):
1019
+ """
1020
+ Assumes that input is monic, and has deg(f) roots.
1021
+ Returns the list of roots.
1022
+
1023
+ NOTE: This function will go into an infinite loop if you
1024
+ give it a polynomial without deg(f) linear factors. Note
1025
+ also that the result is not deterministic, i.e. the
1026
+ order of the roots returned is random.
1027
+
1028
+ EXAMPLES::
1029
+
1030
+ sage: ntl.ZZ_pX([-1,0,0,0,0,1],5).linear_roots()
1031
+ [1, 1, 1, 1, 1]
1032
+ sage: roots = ntl.ZZ_pX([-1,0,0,0,1],5).linear_roots()
1033
+ sage: [ ntl.ZZ_p(i,5) in roots for i in [1..4] ]
1034
+ [True, True, True, True]
1035
+ sage: ntl.ZZ_pX([3,7,1,8], 28).linear_roots()
1036
+ Traceback (most recent call last):
1037
+ ...
1038
+ ValueError: self must be monic.
1039
+ """
1040
+ current_randstate().set_seed_ntl(False)
1041
+
1042
+ self.c.restore_c()
1043
+ cdef ZZ_p_c** v
1044
+ cdef ntl_ZZ_p r
1045
+ cdef long i, n
1046
+ if not self.is_monic():
1047
+ raise ValueError("self must be monic.")
1048
+ sig_on()
1049
+ ZZ_pX_linear_roots(&v, &n, &self.x)
1050
+ sig_off()
1051
+ F = []
1052
+ for i from 0 <= i < n:
1053
+ r = ntl_ZZ_p.__new__(ntl_ZZ_p)
1054
+ r.c = self.c
1055
+ r.x = v[i][0]
1056
+ F.append(r)
1057
+ #F.append(make_ZZ_p(v[i], self.c))
1058
+ for i from 0 <= i < n:
1059
+ del v[i]
1060
+ sig_free(v)
1061
+ return F
1062
+
1063
+ def reverse(self, hi=None):
1064
+ """
1065
+ Return the polynomial obtained by reversing the coefficients
1066
+ of this polynomial. If hi is set then this function behaves
1067
+ as if this polynomial has degree hi.
1068
+
1069
+ EXAMPLES::
1070
+
1071
+ sage: c = ntl.ZZ_pContext(20)
1072
+ sage: f = ntl.ZZ_pX([1,2,3,4,5],c)
1073
+ sage: f.reverse()
1074
+ [5 4 3 2 1]
1075
+ sage: f.reverse(hi=10)
1076
+ [0 0 0 0 0 0 5 4 3 2 1]
1077
+ sage: f.reverse(hi=2)
1078
+ [3 2 1]
1079
+ sage: f.reverse(hi=-2)
1080
+ []
1081
+ """
1082
+ cdef ntl_ZZ_pX r = self._new()
1083
+ if hi is None:
1084
+ ZZ_pX_reverse(r.x, self.x)
1085
+ else:
1086
+ ZZ_pX_reverse_hi(r.x, self.x, int(hi))
1087
+ return r
1088
+
1089
+ def truncate(self, long m):
1090
+ """
1091
+ Return the truncation of this polynomial obtained by
1092
+ removing all terms of degree >= m.
1093
+
1094
+ EXAMPLES::
1095
+
1096
+ sage: c = ntl.ZZ_pContext(20)
1097
+ sage: f = ntl.ZZ_pX([1,2,3,4,5],c)
1098
+ sage: f.truncate(3)
1099
+ [1 2 3]
1100
+ sage: f.truncate(8)
1101
+ [1 2 3 4 5]
1102
+ sage: f.truncate(1)
1103
+ [1]
1104
+ sage: f.truncate(0)
1105
+ []
1106
+ sage: f.truncate(-1)
1107
+ []
1108
+ sage: f.truncate(-5)
1109
+ []
1110
+ """
1111
+ cdef ntl_ZZ_pX r = self._new()
1112
+ if m <= 0:
1113
+ return r
1114
+ sig_on()
1115
+ ZZ_pX_trunc(r.x, self.x, m)
1116
+ sig_off()
1117
+ return r
1118
+
1119
+ def multiply_and_truncate(self, ntl_ZZ_pX other, long m):
1120
+ """
1121
+ Return self*other but with terms of degree >= m removed.
1122
+
1123
+ EXAMPLES::
1124
+
1125
+ sage: c = ntl.ZZ_pContext(20)
1126
+ sage: f = ntl.ZZ_pX([1,2,3,4,5],c)
1127
+ sage: g = ntl.ZZ_pX([10],c)
1128
+ sage: f.multiply_and_truncate(g, 2)
1129
+ [10]
1130
+ sage: g.multiply_and_truncate(f, 2)
1131
+ [10]
1132
+ """
1133
+ cdef ntl_ZZ_pX r = self._new()
1134
+ if m <= 0:
1135
+ return r
1136
+ sig_on()
1137
+ ZZ_pX_MulTrunc(r.x, self.x, other.x, m)
1138
+ sig_off()
1139
+ return r
1140
+
1141
+ def square_and_truncate(self, long m):
1142
+ """
1143
+ Return self*self but with terms of degree >= m removed.
1144
+
1145
+ EXAMPLES::
1146
+
1147
+ sage: c = ntl.ZZ_pContext(20)
1148
+ sage: f = ntl.ZZ_pX([1,2,3,4,5],c)
1149
+ sage: f.square_and_truncate(4)
1150
+ [1 4 10]
1151
+ sage: (f*f).truncate(4)
1152
+ [1 4 10]
1153
+ """
1154
+ cdef ntl_ZZ_pX r = self._new()
1155
+ if m <= 0:
1156
+ return r
1157
+ sig_on()
1158
+ ZZ_pX_SqrTrunc(r.x, self.x, m)
1159
+ sig_off()
1160
+ return r
1161
+
1162
+ def invert_and_truncate(self, long m):
1163
+ """
1164
+ Compute and return the inverse of ``self`` modulo `x^m`.
1165
+
1166
+ The constant term of ``self`` must be a unit.
1167
+
1168
+ EXAMPLES::
1169
+
1170
+ sage: c = ntl.ZZ_pContext(20)
1171
+ sage: f = ntl.ZZ_pX([1,2,3,4,5,6,7],c)
1172
+ sage: f.invert_and_truncate(20)
1173
+ [1 18 1 0 0 0 0 8 17 2 13 0 0 0 4 0 17 10 9]
1174
+ sage: g = f.invert_and_truncate(20)
1175
+ sage: g * f
1176
+ [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 4 4 3]
1177
+ """
1178
+ if m < 0:
1179
+ raise ArithmeticError("m (=%s) must be positive" % m)
1180
+ cdef ntl_ZZ_pX r = self._new()
1181
+ sig_on()
1182
+ ZZ_pX_InvTrunc(r.x, self.x, m)
1183
+ sig_off()
1184
+ return r
1185
+
1186
+ def invmod(self, ntl_ZZ_pX modulus):
1187
+ """
1188
+ Return the inverse of ``self`` modulo the modulus using NTL's InvMod.
1189
+ """
1190
+ cdef ntl_ZZ_pX r = self._new()
1191
+ sig_on()
1192
+ ZZ_pX_InvMod(r.x, self.x, modulus.x)
1193
+ sig_off()
1194
+ return r
1195
+
1196
+ def invmod_newton(self, ntl_ZZ_pX modulus):
1197
+ """
1198
+ Return the inverse of ``self`` modulo the modulus using Newton lifting.
1199
+ Only works if modulo a power of a prime, and if modulus is either
1200
+ unramified or Eisenstein.
1201
+ """
1202
+ cdef Integer pn = Integer(self.c.p)
1203
+ cdef ntl_ZZ_pX ans = self._new()
1204
+ F = pn.factor()
1205
+ if len(F) > 1:
1206
+ raise ValueError("must be modulo a prime power")
1207
+ p = F[0][0]
1208
+ cdef ntl_ZZ pZZ = <ntl_ZZ>ntl_ZZ(p)
1209
+ cdef ZZ_pX_Modulus_c mod
1210
+ ZZ_pX_Modulus_build(mod, modulus.x)
1211
+ cdef ntl_ZZ_pX mod_prime
1212
+ cdef ntl_ZZ_pContext_class ctx
1213
+ cdef long mini = 0, minval = 0
1214
+ if Integer(modulus[0].lift()).valuation(p) == 1:
1215
+ eisenstein = True
1216
+ for c in modulus.list()[1:-1]:
1217
+ if not p.divides(Integer(c.lift())):
1218
+ eisenstein = False
1219
+ break
1220
+ if eisenstein:
1221
+ if p.divides(Integer(self[0])):
1222
+ raise ZeroDivisionError("cannot invert element")
1223
+ ZZ_pX_InvMod_newton_ram(ans.x, self.x, mod, self.c.x)
1224
+ else:
1225
+ raise ValueError("not eisenstein or unramified")
1226
+ else:
1227
+ ctx = <ntl_ZZ_pContext_class>ntl_ZZ_pContext(p)
1228
+ mod_prime = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
1229
+ ZZ_pX_conv_modulus(mod_prime.x, modulus.x, ctx.x)
1230
+ mod_prime.c = ctx
1231
+ F = mod_prime.factor()
1232
+ if len(F) == 1 and F[0][1] == 1:
1233
+ ZZ_pX_min_val_coeff(minval, mini, self.x, pZZ.x)
1234
+ if minval > 0:
1235
+ raise ZeroDivisionError("cannot invert element")
1236
+ ZZ_pX_InvMod_newton_unram(ans.x, self.x, mod, self.c.x, ctx.x)
1237
+ else:
1238
+ raise ValueError("not eisenstein or unramified")
1239
+ return ans
1240
+
1241
+ def multiply_mod(self, ntl_ZZ_pX other, ntl_ZZ_pX modulus):
1242
+ """
1243
+ Return ``self*other % modulus``. The modulus must be monic with
1244
+ ``deg(modulus) > 0``, and ``self`` and ``other`` must have smaller degree.
1245
+
1246
+ EXAMPLES::
1247
+
1248
+ sage: c = ntl.ZZ_pContext(ntl.ZZ(20))
1249
+ sage: modulus = ntl.ZZ_pX([1,2,0,1],c) # must be monic
1250
+ sage: g = ntl.ZZ_pX([-1,0,1],c)
1251
+ sage: h = ntl.ZZ_pX([3,7,13],c)
1252
+ sage: h.multiply_mod(g, modulus)
1253
+ [10 6 4]
1254
+ """
1255
+ cdef ntl_ZZ_pX r = self._new()
1256
+ sig_on()
1257
+ ZZ_pX_MulMod(r.x, self.x, other.x, modulus.x)
1258
+ sig_off()
1259
+ return r
1260
+
1261
+ def trace_mod(self, ntl_ZZ_pX modulus):
1262
+ """
1263
+ Return the trace of this polynomial modulus the modulus.
1264
+ The modulus must be monic, and of positive degree bigger
1265
+ than the degree of ``self``.
1266
+
1267
+ EXAMPLES::
1268
+
1269
+ sage: c = ntl.ZZ_pContext(20)
1270
+ sage: f = ntl.ZZ_pX([1,2,0,3],c)
1271
+ sage: mod = ntl.ZZ_pX([5,3,-1,1,1],c)
1272
+ sage: f.trace_mod(mod)
1273
+ 3
1274
+ """
1275
+ self.c.restore_c()
1276
+ cdef ntl_ZZ_p r = ntl_ZZ_p.__new__(ntl_ZZ_p)
1277
+ r.c = self.c
1278
+ sig_on()
1279
+ ZZ_pX_TraceMod(r.x, self.x, modulus.x)
1280
+ sig_off()
1281
+ return r
1282
+
1283
+ def trace_list(self):
1284
+ """
1285
+ Return the list of traces of the powers `x^i` of the
1286
+ monomial x modulo this polynomial for i = 0, ..., deg(f)-1.
1287
+
1288
+ This polynomial must be monic.
1289
+
1290
+ EXAMPLES::
1291
+
1292
+ sage: c = ntl.ZZ_pContext(20)
1293
+ sage: f = ntl.ZZ_pX([1,2,0,3,0,1],c)
1294
+ sage: f.trace_list()
1295
+ [5, 0, 14, 0, 10]
1296
+
1297
+ The input polynomial must be monic or a :exc:`ValueError` is raised::
1298
+
1299
+ sage: c = ntl.ZZ_pContext(20)
1300
+ sage: f = ntl.ZZ_pX([1,2,0,3,0,2],c)
1301
+ sage: f.trace_list()
1302
+ Traceback (most recent call last):
1303
+ ...
1304
+ ValueError: polynomial must be monic.
1305
+ """
1306
+ # This function should be redone to use TraceVec, which requires improving the wrapper for vec_ZZ_p
1307
+ self.c.restore_c()
1308
+ if not self.is_monic():
1309
+ raise ValueError("polynomial must be monic.")
1310
+ sig_on()
1311
+ cdef char* t
1312
+ t = ZZ_pX_trace_list(&self.x)
1313
+ r = eval(char_to_str(t).replace(' ', ','))
1314
+ string_delete(t)
1315
+ return r
1316
+
1317
+ def resultant(self, ntl_ZZ_pX other):
1318
+ """
1319
+ Return the resultant of ``self`` and ``other``.
1320
+
1321
+ EXAMPLES::
1322
+
1323
+ sage: c = ntl.ZZ_pContext(17)
1324
+ sage: f = ntl.ZZ_pX([17,0,1,1],c)
1325
+ sage: g = ntl.ZZ_pX([34,-17,18,2],c)
1326
+ sage: f.resultant(g)
1327
+ 0
1328
+ """
1329
+ self.c.restore_c()
1330
+ cdef ntl_ZZ_p r = ntl_ZZ_p.__new__(ntl_ZZ_p)
1331
+ r.c = self.c
1332
+ sig_on()
1333
+ ZZ_pX_resultant(r.x, self.x, other.x)
1334
+ sig_off()
1335
+ return r
1336
+
1337
+ def norm_mod(self, ntl_ZZ_pX modulus):
1338
+ """
1339
+ Return the norm of this polynomial modulo the modulus. The
1340
+ modulus must be monic, and of positive degree strictly greater
1341
+ than the degree of ``self``.
1342
+
1343
+ EXAMPLES::
1344
+
1345
+ sage: c = ntl.ZZ_pContext(17)
1346
+ sage: f = ntl.ZZ_pX([1,2,0,3],c)
1347
+ sage: mod = ntl.ZZ_pX([-5,2,0,0,1],c)
1348
+ sage: f.norm_mod(mod)
1349
+ 11
1350
+
1351
+ The norm is the constant term of the characteristic polynomial::
1352
+
1353
+ sage: f.charpoly_mod(mod)
1354
+ [11 1 8 14 1]
1355
+ """
1356
+ self.c.restore_c()
1357
+ cdef ntl_ZZ_p r = ntl_ZZ_p.__new__(ntl_ZZ_p)
1358
+ r.c = self.c
1359
+ sig_on()
1360
+ ZZ_pX_NormMod(r.x, self.x, modulus.x)
1361
+ sig_off()
1362
+ return r
1363
+
1364
+ def discriminant(self):
1365
+ r"""
1366
+ Return the discriminant of a=self, which is by definition
1367
+ $$
1368
+ (-1)^{m(m-1)/2} {\mbox{\tt resultant}}(a, a')/lc(a),
1369
+ $$
1370
+ where m = deg(a), and lc(a) is the leading coefficient of a.
1371
+
1372
+ EXAMPLES::
1373
+
1374
+ sage: c = ntl.ZZ_pContext(ntl.ZZ(17))
1375
+ sage: f = ntl.ZZ_pX([1,2,0,3],c)
1376
+ sage: f.discriminant()
1377
+ 1
1378
+ """
1379
+ self.c.restore_c()
1380
+ cdef long m
1381
+
1382
+ c = ~self.leading_coefficient()
1383
+ m = self.degree()
1384
+ if (m*(m-1) // 2) % 2:
1385
+ c = -c
1386
+ return c*self.resultant(self.derivative())
1387
+
1388
+ def charpoly_mod(self, ntl_ZZ_pX modulus):
1389
+ """
1390
+ Return the characteristic polynomial of this polynomial modulo
1391
+ the modulus. The modulus must be monic of degree bigger than
1392
+ ``self``.
1393
+
1394
+ EXAMPLES::
1395
+
1396
+ sage: c = ntl.ZZ_pContext(17)
1397
+ sage: f = ntl.ZZ_pX([1,2,0,3],c)
1398
+ sage: mod = ntl.ZZ_pX([-5,2,0,0,1],c)
1399
+ sage: f.charpoly_mod(mod)
1400
+ [11 1 8 14 1]
1401
+ """
1402
+ cdef ntl_ZZ_pX r = self._new()
1403
+ sig_on()
1404
+ ZZ_pX_CharPolyMod(r.x, self.x, modulus.x)
1405
+ sig_off()
1406
+ return r
1407
+
1408
+ def minpoly_mod(self, ntl_ZZ_pX modulus):
1409
+ """
1410
+ Return the minimal polynomial of this polynomial modulo the
1411
+ modulus. The modulus must be monic of degree bigger than
1412
+ ``self``.
1413
+
1414
+ EXAMPLES::
1415
+
1416
+ sage: c = ntl.ZZ_pContext(17)
1417
+ sage: f = ntl.ZZ_pX([0,0,1],c)
1418
+ sage: g = f*f
1419
+ sage: f.charpoly_mod(g)
1420
+ [0 0 0 0 1]
1421
+
1422
+ However, since `f^2 = 0` modulo `g`, its minimal polynomial
1423
+ is of degree `2`::
1424
+
1425
+ sage: f.minpoly_mod(g)
1426
+ [0 0 1]
1427
+ """
1428
+ cdef ntl_ZZ_pX r = self._new()
1429
+ sig_on()
1430
+ ZZ_pX_MinPolyMod(r.x, self.x, modulus.x)
1431
+ sig_off()
1432
+ return r
1433
+
1434
+ def clear(self):
1435
+ """
1436
+ Reset this polynomial to 0. Changes this polynomial in place.
1437
+
1438
+ EXAMPLES::
1439
+
1440
+ sage: c = ntl.ZZ_pContext(17)
1441
+ sage: f = ntl.ZZ_pX([1,2,3],c)
1442
+ sage: f
1443
+ [1 2 3]
1444
+ sage: f.clear()
1445
+ sage: f
1446
+ []
1447
+ """
1448
+ self.c.restore_c()
1449
+ ZZ_pX_clear(self.x)
1450
+
1451
+ def preallocate_space(self, long n):
1452
+ """
1453
+ Pre-allocate spaces for n coefficients. The polynomial that f
1454
+ represents is unchanged. This is useful if you know you'll be
1455
+ setting coefficients up to n, so memory isn't re-allocated as
1456
+ the polynomial grows. (You might save a millisecond with this
1457
+ function.)
1458
+
1459
+ EXAMPLES::
1460
+
1461
+ sage: c = ntl.ZZ_pContext(17)
1462
+ sage: f = ntl.ZZ_pX([1,2,3],c)
1463
+ sage: f.preallocate_space(20)
1464
+ sage: f
1465
+ [1 2 3]
1466
+ sage: f[10]=5 # no new memory is allocated
1467
+ sage: f
1468
+ [1 2 3 0 0 0 0 0 0 0 5]
1469
+ """
1470
+ self.c.restore_c()
1471
+ sig_on()
1472
+ self.x.SetMaxLength(n)
1473
+ #ZZ_pX_preallocate_space(&self.x, n)
1474
+ sig_off()
1475
+
1476
+ def compose_mod(self, ntl_ZZ_pX other, ntl_ZZ_pX modulus):
1477
+ r"""
1478
+ Compute `f(g) \bmod h`.
1479
+
1480
+ To be precise about the order fo compostion, given ``self``, ``other``
1481
+ and ``modulus`` as `f(x)`, `g(x)` and `h(x)` compute `f(g(x)) \bmod h(x)`.
1482
+
1483
+ INPUT:
1484
+
1485
+ - ``other`` -- a polynomial `g(x)`
1486
+ - ``modulus`` -- a polynomial `h(x)`
1487
+
1488
+ EXAMPLES::
1489
+
1490
+ sage: c = ntl.ZZ_pContext(17)
1491
+ sage: f = ntl.ZZ_pX([1,2,3],c)
1492
+ sage: g = ntl.ZZ_pX([3,2,1],c)
1493
+ sage: h = ntl.ZZ_pX([1,0,1],c)
1494
+ sage: f.compose_mod(g, h)
1495
+ [5 11]
1496
+
1497
+ AUTHORS:
1498
+
1499
+ - Giacomo Pope (2024-08) initial implementation
1500
+ """
1501
+ cdef ntl_ZZ_pX r = self._new()
1502
+ cdef ZZ_pX_Modulus_c mod
1503
+
1504
+ sig_on()
1505
+ # NTL requires that g is reduced
1506
+ other = other % modulus
1507
+
1508
+ # Build the modulus type
1509
+ ZZ_pX_Modulus_build(mod, modulus.x)
1510
+
1511
+ # Compute f(g) % h
1512
+ ZZ_pX_CompMod(r.x, self.x, other.x, mod)
1513
+ sig_off()
1514
+ return r
1515
+
1516
+ cdef class ntl_ZZ_pX_Modulus():
1517
+ """
1518
+ Thin holder for ZZ_pX_Moduli.
1519
+ """
1520
+ def __cinit__(self, ntl_ZZ_pX poly):
1521
+ ZZ_pX_Modulus_build(self.x, poly.x)
1522
+ self.poly = poly
1523
+
1524
+ def __repr__(self) -> str:
1525
+ return "NTL ZZ_pXModulus %s (mod %s)" % (self.poly, self.poly.c.p)
1526
+
1527
+ def degree(self):
1528
+ cdef Integer ans = Integer.__new__(Integer)
1529
+ mpz_set_ui(ans.value, ZZ_pX_Modulus_deg(self.x))
1530
+ return ans
1531
+
1532
+ ## TODO: NTL's ZZ_pX has minpolys of linear recurrence sequences!!!