Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/ntl/ntl_ZZ_pEX.pyx
4101 views
1
"""
2
Wrapper for NTL's polynomials over finite ring extensions of $\Z / p\Z.$
3
4
AUTHORS:
5
-- David Roe (2007-10-10)
6
"""
7
8
#*****************************************************************************
9
# Copyright (C) 2007 William Stein <[email protected]>
10
# David Roe <[email protected]>
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
# http://www.gnu.org/licenses/
22
#*****************************************************************************
23
24
include "../../ext/interrupt.pxi"
25
include "../../ext/stdsage.pxi"
26
include 'misc.pxi'
27
include 'decl.pxi'
28
29
from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
30
from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p
31
from sage.libs.ntl.ntl_ZZ_pE cimport ntl_ZZ_pE
32
from sage.libs.ntl.ntl_ZZ_pX cimport ntl_ZZ_pX
33
from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class
34
from sage.libs.ntl.ntl_ZZ_pEContext import ntl_ZZ_pEContext
35
from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class
36
37
from sage.libs.ntl.ntl_ZZ import unpickle_class_args
38
39
##############################################################################
40
#
41
# ZZ_pEX -- polynomials over an extension of the integers modulo p
42
#
43
##############################################################################
44
45
cdef class ntl_ZZ_pEX:
46
r"""
47
The class \class{ZZ_pEX} implements polynomials over finite ring extensions of $\Z / p\Z$.
48
49
It can be used, for example, for arithmetic in $GF(p^n)[X]$.
50
However, except where mathematically necessary (e.g., GCD computations),
51
ZZ_pE need not be a field.
52
"""
53
# See ntl_ZZ_pEX.pxd for definition of data members
54
def __init__(self, v=None, modulus=None):
55
"""
56
EXAMPLES:
57
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
58
sage: a = ntl.ZZ_pE([3,2], c)
59
sage: b = ntl.ZZ_pE([1,2], c)
60
sage: f = ntl.ZZ_pEX([a, b, b])
61
sage: f
62
[[3 2] [1 2] [1 2]]
63
sage: g = ntl.ZZ_pEX([0,0,0], c); g
64
[]
65
sage: g[10]=5
66
sage: g
67
[[] [] [] [] [] [] [] [] [] [] [5]]
68
sage: g[10]
69
[5]
70
"""
71
if modulus is None and v is None:
72
raise ValueError, "You must specify a modulus when creating a ZZ_pEX."
73
74
# self.c.restore_c() ## Restoring the context is taken care of in __new__
75
76
cdef ntl_ZZ_pE cc
77
cdef Py_ssize_t i
78
79
if v is None:
80
return
81
elif PY_TYPE_CHECK(v, list) or PY_TYPE_CHECK(v, tuple):
82
for i from 0 <= i < len(v):
83
x = v[i]
84
if not PY_TYPE_CHECK(x, ntl_ZZ_pE):
85
cc = ntl_ZZ_pE(x,self.c)
86
else:
87
if self.c is not (<ntl_ZZ_pE>x).c:
88
raise ValueError, "inconsistent moduli"
89
cc = x
90
ZZ_pEX_SetCoeff(self.x, i, cc.x)
91
else:
92
raise NotImplementedError
93
s = str(v).replace(',',' ').replace('L','')
94
#sig_on()
95
#ZZ_pEX_from_str(&self.x, s)
96
#sig_off()
97
98
def __cinit__(self, v=None, modulus=None):
99
#################### WARNING ###################
100
## Before creating a ZZ_pEX, you must create a##
101
## ZZ_pEContext, and restore it. In Python, ##
102
## the error checking in __init__ will prevent##
103
## you from constructing an ntl_ZZ_pEX ##
104
## inappropriately. However, from Cython, you##
105
## could do r = PY_NEW(ntl_ZZ_pEX) without ##
106
## first restoring a ZZ_pEContext, which could##
107
## have unfortunate consequences. See _new ##
108
## defined below for an example of the right ##
109
## way to short-circuit __init__ (or just call##
110
## _new in your own code). ##
111
################################################
112
if modulus is None and v is None: # we also check for v is None so that a user can specify the modulus by v.
113
ZZ_pEX_construct(&self.x)
114
return
115
if PY_TYPE_CHECK( modulus, ntl_ZZ_pEContext_class ):
116
self.c = <ntl_ZZ_pEContext_class>modulus
117
elif PY_TYPE_CHECK(v, ntl_ZZ_pEX):
118
self.c = (<ntl_ZZ_pEX>v).c
119
elif PY_TYPE_CHECK(v, ntl_ZZ_pE):
120
self.c = (<ntl_ZZ_pE>v).c
121
elif (PY_TYPE_CHECK(v, list) or PY_TYPE_CHECK(v, tuple)) and len(v) > 0:
122
if PY_TYPE_CHECK(v[0], ntl_ZZ_pEX):
123
self.c = (<ntl_ZZ_pEX>v[0]).c
124
elif PY_TYPE_CHECK(v[0], ntl_ZZ_pE):
125
self.c = (<ntl_ZZ_pEX>v[0]).c
126
else:
127
self.c = <ntl_ZZ_pEContext_class>ntl_ZZ_pEContext(modulus)
128
elif modulus is not None:
129
self.c = <ntl_ZZ_pEContext_class>ntl_ZZ_pEContext(modulus)
130
else:
131
raise ValueError, "modulus must not be None"
132
self.c.restore_c()
133
ZZ_pEX_construct(&self.x)
134
135
def __dealloc__(self):
136
ZZ_pEX_destruct(&self.x)
137
138
cdef ntl_ZZ_pEX _new(self):
139
cdef ntl_ZZ_pEX r
140
self.c.restore_c()
141
r = PY_NEW(ntl_ZZ_pEX)
142
r.c = self.c
143
return r
144
145
def __reduce__(self):
146
"""
147
TEST:
148
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
149
sage: a = ntl.ZZ_pE([3,2], c)
150
sage: b = ntl.ZZ_pE([1,2], c)
151
sage: f = ntl.ZZ_pEX([a, b, b])
152
sage: loads(dumps(f)) == f
153
True
154
"""
155
return make_ZZ_pEX, (self.list(), self.get_modulus_context())
156
157
def __repr__(self):
158
"""
159
Returns a string representation of self.
160
161
TEST:
162
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
163
sage: a = ntl.ZZ_pE([3,2], c)
164
sage: b = ntl.ZZ_pE([1,2], c)
165
sage: f = ntl.ZZ_pEX([a, b, b])
166
sage: f
167
[[3 2] [1 2] [1 2]]
168
"""
169
self.c.restore_c()
170
return ZZ_pEX_to_PyString(&self.x)
171
#return string_delete(ZZ_pEX_to_str(&self.x))
172
173
def __copy__(self):
174
"""
175
Return a copy of self.
176
177
TEST:
178
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
179
sage: a = ntl.ZZ_pE([3,2], c)
180
sage: b = ntl.ZZ_pE([1,2], c)
181
sage: f = ntl.ZZ_pEX([a, b, b])
182
sage: f
183
[[3 2] [1 2] [1 2]]
184
sage: y = copy(f)
185
sage: y == f
186
True
187
sage: y is f
188
False
189
sage: f[0] = 0; y
190
[[3 2] [1 2] [1 2]]
191
"""
192
cdef ntl_ZZ_pEX r = self._new()
193
#self.c.restore_c() ## _new() restores
194
r.x = self.x
195
return r
196
197
def get_modulus_context(self):
198
"""
199
Returns the structure that holds the underlying NTL modulus.
200
201
EXAMPLES:
202
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
203
sage: a = ntl.ZZ_pE([3,2], c)
204
sage: b = ntl.ZZ_pE([1,2], c)
205
sage: f = ntl.ZZ_pEX([a, b, b])
206
sage: f.get_modulus_context()
207
NTL modulus [1 1 1] (mod 7)
208
"""
209
return self.c
210
211
def __setitem__(self, long i, a):
212
r"""
213
Sets the ith coefficient of self to be a.
214
215
EXAMPLES:
216
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
217
sage: a = ntl.ZZ_pE([3,2], c)
218
sage: b = ntl.ZZ_pE([1,2], c)
219
sage: f = ntl.ZZ_pEX([a, b, b])
220
sage: f[1] = 4; f
221
[[3 2] [4] [1 2]]
222
"""
223
if i < 0:
224
raise IndexError, "index (i=%s) must be >= 0"%i
225
cdef ntl_ZZ_pE _a
226
if PY_TYPE_CHECK(a, ntl_ZZ_pE):
227
_a = <ntl_ZZ_pE> a
228
else:
229
_a = ntl_ZZ_pE(a,self.c)
230
self.c.restore_c()
231
ZZ_pEX_SetCoeff(self.x, i, _a.x)
232
233
def __getitem__(self, long i):
234
r"""
235
Returns the ith coefficient of self.
236
237
EXAMPLES:
238
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
239
sage: a = ntl.ZZ_pE([3,2], c)
240
sage: b = ntl.ZZ_pE([1,2], c)
241
sage: f = ntl.ZZ_pEX([a, b, b])
242
sage: f[0]
243
[3 2]
244
sage: f[5]
245
[]
246
"""
247
if i < 0:
248
raise IndexError, "index (=%s) must be >= 0"%i
249
cdef ntl_ZZ_pE r
250
sig_on()
251
self.c.restore_c()
252
r = PY_NEW(ntl_ZZ_pE)
253
r.c = self.c
254
r.x = ZZ_pEX_coeff( self.x, i)
255
sig_off()
256
return r
257
258
def list(self):
259
"""
260
Return list of entries as a list of ntl_ZZ_pEs.
261
262
EXAMPLES:
263
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
264
sage: a = ntl.ZZ_pE([3,2], c)
265
sage: b = ntl.ZZ_pE([1,2], c)
266
sage: f = ntl.ZZ_pEX([a, b, b])
267
sage: f.list()
268
[[3 2], [1 2], [1 2]]
269
"""
270
# This function could be sped up by using the list API and not restoring the context each time.
271
# Or by using self.x.rep directly.
272
self.c.restore_c()
273
cdef Py_ssize_t i
274
return [self[i] for i from 0 <= i <= self.degree()]
275
276
def __add__(ntl_ZZ_pEX self, ntl_ZZ_pEX other):
277
"""
278
Adds self and other.
279
280
EXAMPLES:
281
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
282
sage: a = ntl.ZZ_pE([3,2], c)
283
sage: b = ntl.ZZ_pE([1,2], c)
284
sage: f = ntl.ZZ_pEX([a, b, b])
285
sage: g = ntl.ZZ_pEX([-b, a])
286
sage: f + g
287
[[2] [4 4] [1 2]]
288
"""
289
if self.c is not other.c:
290
raise ValueError, "You can not perform arithmetic with elements of different moduli."
291
cdef ntl_ZZ_pEX r = self._new()
292
sig_on()
293
# self.c.restore_c() # _new restores the context
294
ZZ_pEX_add(r.x, self.x, other.x)
295
sig_off()
296
return r
297
298
def __sub__(ntl_ZZ_pEX self, ntl_ZZ_pEX other):
299
"""
300
Subtracts other from self.
301
302
EXAMPLES:
303
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
304
sage: a = ntl.ZZ_pE([3,2], c)
305
sage: b = ntl.ZZ_pE([1,2], c)
306
sage: f = ntl.ZZ_pEX([a, b, b])
307
sage: g = ntl.ZZ_pEX([-b, a])
308
sage: f - g
309
[[4 4] [5] [1 2]]
310
"""
311
if self.c is not other.c:
312
raise ValueError, "You can not perform arithmetic with elements of different moduli."
313
cdef ntl_ZZ_pEX r = self._new()
314
sig_on()
315
# self.c.restore_c() # _new restores the context
316
ZZ_pEX_sub(r.x, self.x, other.x)
317
sig_off()
318
return r
319
320
def __mul__(ntl_ZZ_pEX self, ntl_ZZ_pEX other):
321
"""
322
Returns the product self * other.
323
324
EXAMPLES:
325
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
326
sage: a = ntl.ZZ_pE([3,2], c)
327
sage: b = ntl.ZZ_pE([1,2], c)
328
sage: f = ntl.ZZ_pEX([a, b, b])
329
sage: g = ntl.ZZ_pEX([-b, a])
330
sage: f * g
331
[[1 3] [1 1] [2 4] [6 4]]
332
sage: c2 = ntl.ZZ_pEContext(ntl.ZZ_pX([4,1,1], 5)) # we can mix up the moduli
333
sage: x = c2.ZZ_pEX([2,4])
334
sage: x^2
335
[[4] [1] [1]]
336
sage: f * g # back to the first one and the ntl modulus gets reset correctly
337
[[1 3] [1 1] [2 4] [6 4]]
338
"""
339
if self.c is not other.c:
340
raise ValueError, "You can not perform arithmetic with elements of different moduli."
341
cdef ntl_ZZ_pEX r = self._new()
342
sig_on()
343
# self.c.restore_c() # _new() restores the context
344
ZZ_pEX_mul(r.x, self.x, other.x)
345
sig_off()
346
return r
347
348
def __div__(ntl_ZZ_pEX self, ntl_ZZ_pEX other):
349
"""
350
Compute quotient self / other, if the quotient is a polynomial.
351
Otherwise an Exception is raised.
352
353
EXAMPLES:
354
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
355
sage: a = ntl.ZZ_pE([3,2], c)
356
sage: b = ntl.ZZ_pE([1,2], c)
357
sage: f = ntl.ZZ_pEX([a^2, -a*b-a*b, b^2])
358
sage: g = ntl.ZZ_pEX([-a, b])
359
sage: f / g
360
[[4 5] [1 2]]
361
sage: g / f
362
Traceback (most recent call last):
363
...
364
ArithmeticError: self (=[[4 5] [1 2]]) is not divisible by other (=[[5 1] [2 6] [4]])
365
"""
366
if self.c is not other.c:
367
raise ValueError, "You can not perform arithmetic with elements of different moduli."
368
cdef int divisible
369
cdef ntl_ZZ_pEX r = self._new()
370
sig_on()
371
#self.c.restore_c() # _new restores context
372
divisible = ZZ_pEX_divide(r.x, self.x, other.x)
373
sig_off()
374
if not divisible:
375
raise ArithmeticError, "self (=%s) is not divisible by other (=%s)"%(self, other)
376
return r
377
378
def __mod__(ntl_ZZ_pEX self, ntl_ZZ_pEX other):
379
"""
380
Given polynomials a, b in ZZ_pE[X], if p is prime and the defining modulus irreducible,
381
there exist polynomials q, r in ZZ_pE[X] such that a = b*q + r, deg(r) < deg(b). This
382
function returns r.
383
384
If p is not prime or the modulus is not irreducible, this function may raise a
385
RuntimeError due to division by a noninvertible element of ZZ_p.
386
387
EXAMPLES:
388
sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5, 0, 1], 5^10))
389
sage: a = c.ZZ_pE([5, 1])
390
sage: b = c.ZZ_pE([4, 99])
391
sage: f = c.ZZ_pEX([a, b])
392
sage: g = c.ZZ_pEX([a^2, -b, a + b])
393
sage: g % f
394
[[1864280 2123186]]
395
sage: f % g
396
[[5 1] [4 99]]
397
"""
398
if self.c is not other.c:
399
raise ValueError, "You can not perform arithmetic with elements of different moduli."
400
cdef ntl_ZZ_pEX r = self._new()
401
sig_on()
402
# self.c.restore_c() # _new() restores the context
403
ZZ_pEX_rem(r.x, self.x, other.x)
404
sig_off()
405
return r
406
407
def quo_rem(self, ntl_ZZ_pEX other):
408
"""
409
Given polynomials a, b in ZZ_pE[X], if p is prime and the defining modulus irreducible,
410
there exist polynomials q, r in ZZ_pE[X] such that a = b*q + r, deg(r) < deg(b). This
411
function returns (q, r).
412
413
If p is not prime or the modulus is not irreducible, this function may raise a
414
RuntimeError due to division by a noninvertible element of ZZ_p.
415
416
EXAMPLES:
417
sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5, 0, 1], 5^10))
418
sage: a = c.ZZ_pE([5, 1])
419
sage: b = c.ZZ_pE([4, 99])
420
sage: f = c.ZZ_pEX([a, b])
421
sage: g = c.ZZ_pEX([a^2, -b, a + b])
422
sage: g.quo_rem(f)
423
([[4947544 2492106] [4469276 6572944]], [[1864280 2123186]])
424
sage: f.quo_rem(g)
425
([], [[5 1] [4 99]])
426
"""
427
if self.c is not other.c:
428
raise ValueError, "You can not perform arithmetic with elements of different moduli."
429
cdef ntl_ZZ_pEX r = self._new()
430
cdef ntl_ZZ_pEX q = self._new()
431
sig_on()
432
# self.c.restore_c() # _new() restores the context
433
ZZ_pEX_DivRem(q.x, r.x, self.x, other.x)
434
sig_off()
435
return q,r
436
437
def square(self):
438
"""
439
Return $f^2$.
440
441
EXAMPLES:
442
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
443
sage: a = ntl.ZZ_pE([3,2], c)
444
sage: b = ntl.ZZ_pE([1,2], c)
445
sage: f = ntl.ZZ_pEX([a, b, b])
446
sage: f.square()
447
[[5 1] [5 1] [2 1] [1] [4]]
448
"""
449
# self.c.restore_c() # _new() restores the context
450
cdef ntl_ZZ_pEX r = self._new()
451
sig_on()
452
ZZ_pEX_sqr(r.x, self.x)
453
sig_off()
454
return r
455
456
def __pow__(ntl_ZZ_pEX self, long n, ignored):
457
"""
458
Return the n-th nonnegative power of self.
459
460
EXAMPLES:
461
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
462
sage: a = ntl.ZZ_pE([3,2], c)
463
sage: b = ntl.ZZ_pE([1,2], c)
464
sage: f = ntl.ZZ_pEX([a, b, b])
465
sage: f^5
466
[[5 1] [2 6] [4 5] [5 1] [] [6 2] [2 3] [0 1] [1 4] [3 6] [2 4]]
467
"""
468
self.c.restore_c()
469
if n < 0:
470
raise NotImplementedError
471
import sage.groups.generic as generic
472
return generic.power(self, n, ntl_ZZ_pEX([[1]],self.c))
473
474
def __cmp__(ntl_ZZ_pEX self, ntl_ZZ_pEX other):
475
"""
476
Decide whether or not self and other are equal.
477
478
EXAMPLES:
479
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
480
sage: a = ntl.ZZ_pE([3,2], c)
481
sage: b = ntl.ZZ_pE([1,2], c)
482
sage: f = ntl.ZZ_pEX([a, b, b])
483
sage: g = ntl.ZZ_pEX([a, b, b, 0])
484
sage: f == g
485
True
486
sage: g = ntl.ZZ_pEX([a, b, a])
487
sage: f == g
488
False
489
"""
490
self.c.restore_c()
491
if ZZ_pEX_equal(self.x, other.x):
492
return 0
493
return -1
494
495
def is_zero(self):
496
"""
497
Return True exactly if this polynomial is 0.
498
499
EXAMPLES:
500
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
501
sage: a = ntl.ZZ_pE([3,2], c)
502
sage: b = ntl.ZZ_pE([1,2], c)
503
sage: f = ntl.ZZ_pEX([a, b, b])
504
sage: f.is_zero()
505
False
506
sage: f = ntl.ZZ_pEX([0,0,7], c)
507
sage: f.is_zero()
508
True
509
"""
510
self.c.restore_c()
511
return bool(ZZ_pEX_IsZero(self.x))
512
513
def is_one(self):
514
"""
515
Return True exactly if this polynomial is 1.
516
517
EXAMPLES:
518
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
519
sage: a = ntl.ZZ_pE([3,2], c)
520
sage: b = ntl.ZZ_pE([1,2], c)
521
sage: f = ntl.ZZ_pEX([a, b, b])
522
sage: f.is_one()
523
False
524
sage: f = ntl.ZZ_pEX([1, 0, 0], c)
525
sage: f.is_one()
526
True
527
"""
528
self.c.restore_c()
529
return bool(ZZ_pEX_IsOne(self.x))
530
531
def is_monic(self):
532
"""
533
Return True exactly if this polynomial is monic.
534
535
EXAMPLES:
536
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
537
sage: a = ntl.ZZ_pE([3,2], c)
538
sage: b = ntl.ZZ_pE([1,2], c)
539
sage: f = ntl.ZZ_pEX([a, b, b])
540
sage: f.is_monic()
541
False
542
sage: f = ntl.ZZ_pEX([a, b, 1], c)
543
sage: f.is_monic()
544
True
545
"""
546
self.c.restore_c()
547
# The following line is what we should have. However, strangely this is *broken*
548
# on PowerPC Intel in NTL, so we program around
549
# the problem. (William Stein)
550
#return bool(ZZ_pEX_is_monic(self.x))
551
552
if ZZ_pEX_IsZero(self.x):
553
return False
554
cdef ZZ_pE_c x = ZZ_pEX_LeadCoeff(self.x)
555
return bool(ZZ_pE_IsOne(x))
556
557
def __neg__(self):
558
"""
559
Return the negative of self.
560
561
EXAMPLES:
562
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
563
sage: a = ntl.ZZ_pE([3,2], c)
564
sage: b = ntl.ZZ_pE([1,2], c)
565
sage: f = ntl.ZZ_pEX([a, b, b])
566
sage: -f
567
[[4 5] [6 5] [6 5]]
568
"""
569
cdef ntl_ZZ_pEX r = self._new()
570
# self.c.restore_c() # _new() calls restore
571
ZZ_pEX_negate(r.x, self.x)
572
return r
573
574
def convert_to_modulus(self, ntl_ZZ_pContext_class c):
575
"""
576
Returns a new ntl_ZZ_pX which is the same as self, but considered modulo a different p (but the SAME polynomial).
577
578
In order for this to make mathematical sense, c.p should divide self.c.p
579
(in which case self is reduced modulo c.p) or self.c.p should divide c.p
580
(in which case self is lifted to something modulo c.p congruent to self modulo self.c.p)
581
582
EXAMPLES:
583
sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5, 0, 1], 5^20))
584
sage: a = ntl.ZZ_pE([192870, 1928189], c)
585
sage: b = ntl.ZZ_pE([18275,293872987], c)
586
sage: f = ntl.ZZ_pEX([a, b])
587
sage: g = f.convert_to_modulus(ntl.ZZ_pContext(ntl.ZZ(5^5)))
588
sage: g
589
[[2245 64] [2650 1112]]
590
sage: g.get_modulus_context()
591
NTL modulus [3120 0 1] (mod 3125)
592
sage: g^2
593
[[1130 2985] [805 830] [2095 2975]]
594
sage: (f^2).convert_to_modulus(ntl.ZZ_pContext(ntl.ZZ(5^5)))
595
[[1130 2985] [805 830] [2095 2975]]
596
"""
597
cdef ntl_ZZ_pEContext_class cE = ntl_ZZ_pEContext(self.c.f.convert_to_modulus(c))
598
cE.restore_c()
599
cdef ntl_ZZ_pEX ans = PY_NEW(ntl_ZZ_pEX)
600
sig_on()
601
ZZ_pEX_conv_modulus(ans.x, self.x, c.x)
602
sig_off()
603
ans.c = cE
604
return ans
605
606
def left_shift(self, long n):
607
"""
608
Return the polynomial obtained by shifting all coefficients of
609
this polynomial to the left n positions.
610
611
EXAMPLES:
612
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
613
sage: a = ntl.ZZ_pE([3,2], c)
614
sage: b = ntl.ZZ_pE([1,2], c)
615
sage: f = ntl.ZZ_pEX([a, b, b]); f
616
[[3 2] [1 2] [1 2]]
617
sage: f.left_shift(2)
618
[[] [] [3 2] [1 2] [1 2]]
619
sage: f.left_shift(5)
620
[[] [] [] [] [] [3 2] [1 2] [1 2]]
621
622
A negative left shift is a right shift.
623
sage: f.left_shift(-2)
624
[[1 2]]
625
"""
626
# self.c.restore_c() # _new() calls restore
627
cdef ntl_ZZ_pEX r = self._new()
628
sig_on()
629
ZZ_pEX_LeftShift(r.x, self.x, n)
630
sig_off()
631
return r
632
633
def right_shift(self, long n):
634
"""
635
Return the polynomial obtained by shifting all coefficients of
636
this polynomial to the right n positions.
637
638
EXAMPLES:
639
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 7))
640
sage: a = ntl.ZZ_pE([3,2], c)
641
sage: b = ntl.ZZ_pE([1,2], c)
642
sage: f = ntl.ZZ_pEX([a, b, b]); f
643
[[3 2] [1 2] [1 2]]
644
sage: f.right_shift(2)
645
[[1 2]]
646
sage: f.right_shift(5)
647
[]
648
649
A negative right shift is a left shift.
650
sage: f.right_shift(-5)
651
[[] [] [] [] [] [3 2] [1 2] [1 2]]
652
"""
653
# self.c.restore_c() # _new() calls restore
654
cdef ntl_ZZ_pEX r = self._new()
655
sig_on()
656
ZZ_pEX_RightShift(r.x, self.x, n)
657
sig_off()
658
return r
659
660
def gcd(self, ntl_ZZ_pEX other, check=True):
661
"""
662
Returns gcd(self, other) if we are working over a field.
663
664
NOTE: Does not work if p is not prime or if the modulus is not irreducible.
665
666
EXAMPLES:
667
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
668
sage: a = ntl.ZZ_pE([3,2], c)
669
sage: b = ntl.ZZ_pE([1,2], c)
670
sage: f = ntl.ZZ_pEX([a, b, b])
671
sage: g = f^2
672
sage: h = f^3
673
sage: g.gcd(h)
674
[[2 1] [8 1] [9 1] [2] [1]]
675
sage: f^2
676
[[5 8] [9 8] [6 8] [5] [8]]
677
sage: eight = ntl.ZZ_pEX([[8]], c)
678
sage: f^2 / eight
679
[[2 1] [8 1] [9 1] [2] [1]]
680
"""
681
#If check = True, need to check that ZZ_pE is a field.
682
self.c.restore_c()
683
cdef ntl_ZZ_pEX r = self._new()
684
sig_on()
685
ZZ_pEX_GCD(r.x, self.x, other.x)
686
sig_off()
687
return r
688
689
def xgcd(self, ntl_ZZ_pEX other):
690
"""
691
Returns r,s,t such that r = s*self + t*other.
692
693
Here r is the gcd of self and other.
694
695
EXAMPLES:
696
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
697
sage: a = ntl.ZZ_pE([3,2], c)
698
sage: b = ntl.ZZ_pE([1,2], c)
699
sage: f = ntl.ZZ_pEX([a, b, b])
700
sage: g = ntl.ZZ_pEX([a-b, b^2, a])
701
sage: h = ntl.ZZ_pEX([a^2-b, b^4, b,a])
702
sage: r,s,t = (g*f).xgcd(h*f)
703
sage: r
704
[[4 6] [1] [1]]
705
sage: f / ntl.ZZ_pEX([b])
706
[[4 6] [1] [1]]
707
sage: s*f*g+t*f*h
708
[[4 6] [1] [1]]
709
"""
710
self.c.restore_c()
711
cdef ntl_ZZ_pEX s = self._new()
712
cdef ntl_ZZ_pEX t = self._new()
713
cdef ntl_ZZ_pEX r = self._new()
714
sig_on()
715
ZZ_pEX_XGCD(r.x, s.x, t.x, self.x, other.x)
716
sig_off()
717
return (r,s,t)
718
719
def degree(self):
720
"""
721
Return the degree of this polynomial. The degree of the 0
722
polynomial is -1.
723
724
EXAMPLES:
725
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
726
sage: a = ntl.ZZ_pE([3,2], c)
727
sage: b = ntl.ZZ_pE([1,2], c)
728
sage: f = ntl.ZZ_pEX([a, b, b])
729
sage: f.degree()
730
2
731
sage: ntl.ZZ_pEX([], c).degree()
732
-1
733
"""
734
self.c.restore_c()
735
return ZZ_pEX_deg(self.x)
736
737
def leading_coefficient(self):
738
"""
739
Return the leading coefficient of this polynomial.
740
741
EXAMPLES:
742
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
743
sage: a = ntl.ZZ_pE([3,2], c)
744
sage: b = ntl.ZZ_pE([1,2], c)
745
sage: f = ntl.ZZ_pEX([a, b, b])
746
sage: f.leading_coefficient()
747
[1 2]
748
"""
749
self.c.restore_c()
750
cdef long i
751
i = ZZ_pEX_deg(self.x)
752
return self[i]
753
754
def constant_term(self):
755
"""
756
Return the constant coefficient of this polynomial.
757
758
EXAMPLES:
759
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
760
sage: a = ntl.ZZ_pE([3,2], c)
761
sage: b = ntl.ZZ_pE([1,2], c)
762
sage: f = ntl.ZZ_pEX([a, b, b])
763
sage: f.constant_term()
764
[3 2]
765
"""
766
self.c.restore_c()
767
return self[0]
768
769
def set_x(self):
770
"""
771
Set this polynomial to the monomial "x".
772
773
EXAMPLES:
774
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
775
sage: a = ntl.ZZ_pE([3,2], c)
776
sage: b = ntl.ZZ_pE([1,2], c)
777
sage: f = ntl.ZZ_pEX([a, b, b])
778
sage: f
779
[[3 2] [1 2] [1 2]]
780
sage: f.set_x(); f
781
[[] [1]]
782
"""
783
self.c.restore_c()
784
ZZ_pEX_SetX(self.x)
785
786
def is_x(self):
787
"""
788
True if this is the polynomial "x".
789
790
EXAMPLES:
791
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
792
sage: a = ntl.ZZ_pE([3,2], c)
793
sage: b = ntl.ZZ_pE([1,2], c)
794
sage: f = ntl.ZZ_pEX([a, b, b])
795
sage: f.is_x()
796
False
797
sage: f.set_x(); f.is_x()
798
True
799
"""
800
return bool(ZZ_pEX_IsX(self.x))
801
802
def derivative(self):
803
"""
804
Return the derivative of this polynomial.
805
806
EXAMPLES:
807
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
808
sage: a = ntl.ZZ_pE([3,2], c)
809
sage: b = ntl.ZZ_pE([1,2], c)
810
sage: f = ntl.ZZ_pEX([a, b, b])
811
sage: f.derivative()
812
[[1 2] [2 4]]
813
"""
814
cdef ntl_ZZ_pEX r = self._new()
815
sig_on()
816
ZZ_pEX_diff(r.x, self.x)
817
sig_off()
818
return r
819
820
#def factor(self, verbose=False):
821
# cdef ZZ_pX_c** v
822
# cdef long* e
823
# cdef long i, n
824
# sig_on()
825
# ZZ_pX_factor(&v, &e, &n, &self.x, verbose)
826
# sig_off()
827
# F = []
828
# for i from 0 <= i < n:
829
# F.append((make_ZZ_pX(v[i], self.c), e[i]))
830
# free(v)
831
# free(e)
832
# return F
833
834
#def linear_roots(self):
835
# """
836
# Assumes that input is monic, and has deg(f) distinct roots.
837
# Returns the list of roots.
838
# """
839
# cdef ZZ_p_c** v
840
# cdef long i, n
841
# sig_on()
842
# ZZ_pX_linear_roots(&v, &n, &self.x)
843
# sig_off()
844
# F = []
845
# for i from 0 <= i < n:
846
# F.append(make_ZZ_p(v[i], self.c))
847
# free(v)
848
# return F
849
850
def reverse(self, hi=None):
851
"""
852
Return the polynomial obtained by reversing the coefficients
853
of this polynomial. If hi is set then this function behaves
854
as if this polynomial has degree hi.
855
856
EXAMPLES:
857
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
858
sage: a = ntl.ZZ_pE([3,2], c)
859
sage: b = ntl.ZZ_pE([1,2], c)
860
sage: f = ntl.ZZ_pEX([a, b, b])
861
sage: f.reverse()
862
[[1 2] [1 2] [3 2]]
863
sage: f.reverse(hi=5)
864
[[] [] [] [1 2] [1 2] [3 2]]
865
sage: f.reverse(hi=1)
866
[[1 2] [3 2]]
867
sage: f.reverse(hi=-2)
868
[]
869
"""
870
cdef ntl_ZZ_pEX r = self._new()
871
if not (hi is None):
872
ZZ_pEX_reverse_hi(r.x, self.x, int(hi))
873
else:
874
ZZ_pEX_reverse(r.x, self.x)
875
return r
876
877
def truncate(self, long m):
878
"""
879
Return the truncation of this polynomial obtained by
880
removing all terms of degree >= m.
881
882
EXAMPLES:
883
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
884
sage: a = ntl.ZZ_pE([3,2], c)
885
sage: b = ntl.ZZ_pE([1,2], c)
886
sage: f = ntl.ZZ_pEX([a, b, b])
887
sage: f.truncate(3)
888
[[3 2] [1 2] [1 2]]
889
sage: f.truncate(1)
890
[[3 2]]
891
"""
892
cdef ntl_ZZ_pEX r = self._new()
893
if m > 0:
894
sig_on()
895
ZZ_pEX_trunc(r.x, self.x, m)
896
sig_off()
897
return r
898
899
def multiply_and_truncate(self, ntl_ZZ_pEX other, long m):
900
"""
901
Return self*other but with terms of degree >= m removed.
902
903
EXAMPLES:
904
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
905
sage: a = ntl.ZZ_pE([3,2], c)
906
sage: b = ntl.ZZ_pE([1,2], c)
907
sage: f = ntl.ZZ_pEX([a, b, b])
908
sage: g = ntl.ZZ_pEX([a - b, b^2, a, a*b])
909
sage: f*g
910
[[6 4] [4 9] [4 6] [7] [1 9] [2 5]]
911
sage: f.multiply_and_truncate(g, 3)
912
[[6 4] [4 9] [4 6]]
913
"""
914
cdef ntl_ZZ_pEX r = self._new()
915
if m > 0:
916
sig_on()
917
ZZ_pEX_MulTrunc(r.x, self.x, other.x, m)
918
sig_off()
919
return r
920
921
def square_and_truncate(self, long m):
922
"""
923
Return self*self but with terms of degree >= m removed.
924
925
EXAMPLES:
926
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
927
sage: a = ntl.ZZ_pE([3,2], c)
928
sage: b = ntl.ZZ_pE([1,2], c)
929
sage: f = ntl.ZZ_pEX([a, b, b])
930
sage: f^2
931
[[5 8] [9 8] [6 8] [5] [8]]
932
sage: f.square_and_truncate(3)
933
[[5 8] [9 8] [6 8]]
934
"""
935
cdef ntl_ZZ_pEX r = self._new()
936
if m > 0:
937
sig_on()
938
ZZ_pEX_SqrTrunc(r.x, self.x, m)
939
sig_off()
940
return r
941
942
def invert_and_truncate(self, long m):
943
"""
944
Compute and return the inverse of self modulo $x^m$.
945
The constant term of self must be invertible.
946
947
EXAMPLES:
948
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
949
sage: a = ntl.ZZ_pE([3,2], c)
950
sage: b = ntl.ZZ_pE([1,2], c)
951
sage: f = ntl.ZZ_pEX([a, b, b])
952
sage: g = f.invert_and_truncate(5)
953
sage: g
954
[[8 6] [4 4] [5 9] [1 4] [0 1]]
955
sage: f * g
956
[[1] [] [] [] [] [2 8] [9 10]]
957
"""
958
if m < 0:
959
raise ArithmeticError, "m (=%s) must be positive"%m
960
#Need to check here if constant term is invertible
961
cdef ntl_ZZ_pEX r = self._new()
962
if m > 0:
963
sig_on()
964
ZZ_pEX_InvTrunc(r.x, self.x, m)
965
sig_off()
966
return r
967
968
def multiply_mod(self, ntl_ZZ_pEX other, ntl_ZZ_pEX modulus):
969
"""
970
Return self*other % modulus. The modulus must be monic with
971
deg(modulus) > 0, and self and other must have smaller degree.
972
973
EXAMPLES:
974
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
975
sage: a = ntl.ZZ_pE([3,2], c)
976
sage: b = ntl.ZZ_pE([1,2], c)
977
sage: f = ntl.ZZ_pEX([a, b, b])
978
sage: g = ntl.ZZ_pEX([b^4, a*b^2, a - b])
979
sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b])
980
sage: f.multiply_mod(g, m)
981
[[10 10] [4 4] [10 3]]
982
"""
983
self.c.restore_c()
984
cdef ntl_ZZ_pEX r = self._new()
985
sig_on()
986
ZZ_pEX_MulMod(r.x, self.x, other.x, modulus.x)
987
sig_off()
988
return r
989
990
def trace_mod(self, ntl_ZZ_pEX modulus):
991
"""
992
Return the trace of this polynomial modulo the modulus.
993
The modulus must be monic, and of positive degree degree bigger
994
than the degree of self.
995
996
EXAMPLES:
997
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
998
sage: a = ntl.ZZ_pE([3,2], c)
999
sage: b = ntl.ZZ_pE([1,2], c)
1000
sage: f = ntl.ZZ_pEX([a, b, b])
1001
sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b])
1002
sage: f.trace_mod(m)
1003
[8 1]
1004
"""
1005
self.c.restore_c()
1006
cdef ntl_ZZ_pE r = ntl_ZZ_pE(modulus = self.c)
1007
sig_on()
1008
ZZ_pEX_TraceMod(r.x, self.x, modulus.x)
1009
sig_off()
1010
return r
1011
1012
#def trace_list(self):
1013
# """
1014
# Return the list of traces of the powers $x^i$ of the
1015
# monomial x modulo this polynomial for i = 0, ..., deg(f)-1.
1016
# This polynomial must be monic.
1017
#
1018
# EXAMPLES:
1019
# sage: c=ntl.ZZ_pContext(ntl.ZZ(20))
1020
# sage: f = c.ZZ_pX([1,2,0,3,0,1])
1021
# sage: f.trace_list()
1022
# [5, 0, 14, 0, 10]
1023
#
1024
# The input polynomial must be monic or a ValueError is raised:
1025
# sage: c=ntl.ZZ_pContext(ntl.ZZ(20))
1026
# sage: f = c.ZZ_pX([1,2,0,3,0,2]
1027
# sage: f.trace_list()
1028
# Traceback (most recent call last):
1029
# ...
1030
# ValueError: polynomial must be monic.
1031
# """
1032
# self.c.restore_c()
1033
# if not self.is_monic():
1034
# raise ValueError, "polynomial must be monic."
1035
# cdef long N = self.degree()
1036
# cdef vec_ZZ_pE_c
1037
# sig_on()
1038
# cdef char* t
1039
# t = ZZ_pX_trace_list(&self.x)
1040
# return eval(string(t).replace(' ', ','))
1041
1042
def resultant(self, ntl_ZZ_pEX other):
1043
"""
1044
Return the resultant of self and other.
1045
1046
EXAMPLES:
1047
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
1048
sage: a = ntl.ZZ_pE([3,2], c)
1049
sage: b = ntl.ZZ_pE([1,2], c)
1050
sage: f = ntl.ZZ_pEX([a, b, b])
1051
sage: g = ntl.ZZ_pEX([a - b, b^2, a, a*b])
1052
sage: f.resultant(g)
1053
[1]
1054
sage: (f*g).resultant(f^2)
1055
[]
1056
"""
1057
self.c.restore_c()
1058
cdef ntl_ZZ_pE r = ntl_ZZ_pE(modulus = self.c)
1059
sig_on()
1060
ZZ_pEX_resultant(r.x, self.x, other.x)
1061
sig_off()
1062
return r
1063
1064
def norm_mod(self, ntl_ZZ_pEX modulus):
1065
"""
1066
Return the norm of this polynomial modulo the modulus. The
1067
modulus must be monic, and of positive degree strictly greater
1068
than the degree of self.
1069
1070
EXAMPLE:
1071
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
1072
sage: a = ntl.ZZ_pE([3,2], c)
1073
sage: b = ntl.ZZ_pE([1,2], c)
1074
sage: f = ntl.ZZ_pEX([a, b, b])
1075
sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b])
1076
sage: f.norm_mod(m)
1077
[9 2]
1078
"""
1079
self.c.restore_c()
1080
cdef ntl_ZZ_pE r = ntl_ZZ_pE(modulus = self.c)
1081
sig_on()
1082
ZZ_pEX_NormMod(r.x, self.x, modulus.x)
1083
sig_off()
1084
return r
1085
1086
def discriminant(self):
1087
r"""
1088
Return the discriminant of a=self, which is by definition
1089
$$
1090
(-1)^{m(m-1)/2} {\mbox{\tt resultant}}(a, a')/lc(a),
1091
$$
1092
where m = deg(a), and lc(a) is the leading coefficient of a.
1093
1094
EXAMPLES:
1095
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
1096
sage: a = ntl.ZZ_pE([3,2], c)
1097
sage: b = ntl.ZZ_pE([1,2], c)
1098
sage: f = ntl.ZZ_pEX([a, b, b])
1099
sage: f.discriminant()
1100
[1 6]
1101
"""
1102
self.c.restore_c()
1103
cdef long m
1104
1105
c = ~self.leading_coefficient()
1106
m = self.degree()
1107
if (m*(m-1)/2) % 2:
1108
c = -c
1109
return c*self.resultant(self.derivative())
1110
1111
def minpoly_mod(self, ntl_ZZ_pEX modulus):
1112
"""
1113
Return the minimal polynomial of this polynomial modulo the
1114
modulus. The modulus must be monic of degree bigger than
1115
self.
1116
1117
EXAMPLES:
1118
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
1119
sage: a = ntl.ZZ_pE([3,2], c)
1120
sage: b = ntl.ZZ_pE([1,2], c)
1121
sage: f = ntl.ZZ_pEX([a, b, b])
1122
sage: m = ntl.ZZ_pEX([a - b, b^2, a, a*b])
1123
sage: f.minpoly_mod(m)
1124
[[2 9] [8 2] [3 10] [1]]
1125
"""
1126
self.c.restore_c()
1127
cdef ntl_ZZ_pEX r = self._new()
1128
sig_on()
1129
ZZ_pEX_MinPolyMod(r.x, self.x, modulus.x)
1130
sig_off()
1131
return r
1132
1133
def clear(self):
1134
"""
1135
Reset this polynomial to 0. Changes this polynomial in place.
1136
1137
EXAMPLES:
1138
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
1139
sage: a = ntl.ZZ_pE([3,2], c)
1140
sage: b = ntl.ZZ_pE([1,2], c)
1141
sage: f = ntl.ZZ_pEX([a, b, b])
1142
sage: f
1143
[[3 2] [1 2] [1 2]]
1144
sage: f.clear(); f
1145
[]
1146
"""
1147
self.c.restore_c()
1148
sig_on()
1149
ZZ_pEX_clear(self.x)
1150
sig_off()
1151
1152
def preallocate_space(self, long n):
1153
"""
1154
Pre-allocate spaces for n coefficients. The polynomial that f
1155
represents is unchanged. This is useful if you know you'll be
1156
setting coefficients up to n, so memory isn't re-allocated as
1157
the polynomial grows. (You might save a millisecond with this
1158
function.)
1159
1160
EXAMPLES:
1161
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1], 11))
1162
sage: a = ntl.ZZ_pE([3,2], c)
1163
sage: b = ntl.ZZ_pE([1,2], c)
1164
sage: f = ntl.ZZ_pEX([a, b, b])
1165
sage: f[10]=ntl.ZZ_pE([1,8],c) # no new memory is allocated
1166
sage: f
1167
[[3 2] [1 2] [1 2] [] [] [] [] [] [] [] [1 8]]
1168
"""
1169
self.c.restore_c()
1170
sig_on()
1171
self.x.SetMaxLength(n)
1172
sig_off()
1173
1174
1175
def make_ZZ_pEX(v, modulus):
1176
"""
1177
Here for unpickling.
1178
1179
EXAMPLES:
1180
sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5,0,1],25))
1181
sage: a = ntl.ZZ_pE([3,2], c)
1182
sage: b = ntl.ZZ_pE([1,2], c)
1183
sage: sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c)
1184
[[3 2] [1 2] [1 2]]
1185
sage: type(sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c))
1186
<type 'sage.libs.ntl.ntl_ZZ_pEX.ntl_ZZ_pEX'>
1187
"""
1188
return ntl_ZZ_pEX(v, modulus)
1189
1190