Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/ntl/ntl_lzz_pX.pyx
4100 views
1
"""
2
ntl_lzz_pX.pyx
3
4
Wraps NTL's zz_pX type for SAGE
5
6
AUTHORS:
7
- Craig Citro
8
"""
9
10
#*****************************************************************************
11
# Copyright (C) 2005 William Stein <[email protected]>
12
#
13
# Distributed under the terms of the GNU General Public License (GPL)
14
#
15
# This code is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
# General Public License for more details.
19
#
20
# The full text of the GPL is available at:
21
#
22
# http://www.gnu.org/licenses/
23
#*****************************************************************************
24
25
include "../../ext/interrupt.pxi"
26
include "../../ext/stdsage.pxi"
27
include "../../ext/cdefs.pxi"
28
include 'misc.pxi'
29
include 'decl.pxi'
30
31
from sage.rings.integer import Integer
32
from sage.rings.integer_ring import IntegerRing
33
from sage.rings.integer cimport Integer
34
from sage.rings.integer_ring cimport IntegerRing_class
35
36
from sage.rings.finite_rings.integer_mod cimport IntegerMod_gmp, IntegerMod_int, IntegerMod_int64
37
38
from sage.libs.ntl.ntl_lzz_pContext import ntl_zz_pContext
39
from sage.libs.ntl.ntl_lzz_pContext cimport ntl_zz_pContext_class
40
41
from sage.libs.ntl.ntl_lzz_p import ntl_zz_p
42
from sage.libs.ntl.ntl_lzz_p cimport ntl_zz_p
43
44
ZZ_sage = IntegerRing()
45
46
##############################################################################
47
#
48
# zz_pX -- polynomials over the integers modulo p, p small
49
#
50
##############################################################################
51
52
cdef class ntl_zz_pX:
53
r"""
54
The class \class{zz_pX} implements polynomial arithmetic modulo $p$,
55
for p smaller than a machine word.
56
57
Polynomial arithmetic is implemented using the FFT, combined with
58
the Chinese Remainder Theorem. A more detailed description of the
59
techniques used here can be found in [Shoup, J. Symbolic
60
Comp. 20:363-397, 1995].
61
62
Small degree polynomials are multiplied either with classical
63
or Karatsuba algorithms.
64
"""
65
# See ntl_zz_pX.pxd for definition of data members
66
def __init__(self, ls=[], modulus=None):
67
"""
68
EXAMPLES:
69
sage: f = ntl.zz_pX([1,2,5,-9],20)
70
sage: f
71
[1, 2, 5, 11]
72
sage: g = ntl.zz_pX([0,0,0],20); g
73
[]
74
sage: g[10]=5
75
sage: g
76
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5]
77
sage: g[10]
78
5
79
sage: f = ntl.zz_pX([10^30+1, 10^50+1], 100); f
80
[1, 1]
81
"""
82
if modulus is None:
83
raise ValueError, "You must specify a modulus."
84
85
cdef long n
86
cdef Py_ssize_t i
87
cdef long temp
88
89
if PY_TYPE_CHECK(modulus, Integer):
90
p_sage = modulus
91
else:
92
p_sage = Integer(self.c.p)
93
94
#self.c.restore_c() ## We did this in __new__
95
96
n = len(ls)
97
if (n == 0):
98
## the 0 polynomial is just the empty list;
99
## so in this case, we're done.
100
return
101
102
self.x.SetMaxLength(n+1)
103
104
for i from 0 <= i < n:
105
a = ls[i]
106
107
if PY_TYPE_CHECK(a, IntegerMod_int):
108
if (self.c.p == (<IntegerMod_int>a).__modulus.int32): ## this is slow
109
zz_pX_SetCoeff_long(self.x, i, (<IntegerMod_int>a).ivalue)
110
else:
111
raise ValueError, \
112
"Mismatched modulus for converting to zz_pX."
113
elif PY_TYPE_CHECK(a, IntegerMod_int64):
114
if (self.c.p == (<IntegerMod_int64>a).__modulus.int64): ## this is slow
115
zz_pX_SetCoeff_long(self.x, i, (<IntegerMod_int64>a).ivalue)
116
else:
117
raise ValueError, \
118
"Mismatched modulus for converting to zz_pX."
119
elif PY_TYPE_CHECK(a, IntegerMod_gmp):
120
if (p_sage == (<IntegerMod_gmp>a).__modulus.sageInteger): ## this is slow
121
zz_pX_SetCoeff_long(self.x, i, mpz_get_si((<IntegerMod_gmp>a).value))
122
else:
123
raise ValueError, \
124
"Mismatched modulus for converting to zz_pX."
125
elif PY_TYPE_CHECK(a, Integer):
126
zz_pX_SetCoeff_long(self.x, i, mpz_fdiv_ui((<Integer>a).value, self.c.p))
127
elif PY_TYPE_CHECK(a, int):
128
## we're lucky that python int is no larger than long
129
temp = a
130
zz_pX_SetCoeff_long(self.x, i, temp%self.c.p)
131
else:
132
a = Integer(a)
133
zz_pX_SetCoeff_long(self.x, i, mpz_fdiv_ui((<Integer>a).value, self.c.p))
134
135
return
136
137
def __cinit__(self, v=None, modulus=None):
138
#################### WARNING ###################
139
## Before creating a zz_pX, you must create a ##
140
## zz_pContext, and restore it. In Python, ##
141
## the error checking in __init__ will prevent##
142
## you from constructing a zz_pX ##
143
## inappropriately. However, from Cython, you##
144
## could do r = PY_NEW(ntl_zz_pX) without ##
145
## first restoring a zz_pContext, which could ##
146
## have unfortunate consequences. See _new ##
147
## defined below for an example of the right ##
148
## way to short-circuit __init__ (or just call##
149
## _new in your own code). ##
150
################################################
151
if modulus is None:
152
zz_pX_construct(&self.x)
153
return
154
if PY_TYPE_CHECK( modulus, ntl_zz_pContext_class ):
155
self.c = <ntl_zz_pContext_class>modulus
156
elif PY_TYPE_CHECK( modulus, Integer ):
157
self.c = <ntl_zz_pContext_class>ntl_zz_pContext(modulus)
158
elif PY_TYPE_CHECK( modulus, long ):
159
self.c = <ntl_zz_pContext_class>ntl_zz_pContext(modulus)
160
else:
161
try:
162
modulus = int(modulus)
163
except:
164
raise ValueError, "%s is not a valid modulus."%modulus
165
self.c = <ntl_zz_pContext_class>ntl_zz_pContext(modulus)
166
167
## now that we've determined the modulus, set that modulus.
168
self.c.restore_c()
169
zz_pX_construct(&self.x)
170
171
def __dealloc__(self):
172
zz_pX_destruct(&self.x)
173
174
def __reduce__(self):
175
"""
176
TESTS:
177
sage: f = ntl.zz_pX([10,10^30+1], 20)
178
sage: f == loads(dumps(f))
179
True
180
"""
181
return make_zz_pX, (self.list(), self.c)
182
183
def __repr__(self):
184
"""
185
Return the string representation of self.
186
187
EXAMPLES:
188
sage: f = ntl.zz_pX([3,5], 17)
189
sage: f.__repr__()
190
'[3, 5]'
191
"""
192
return str(self.list())
193
194
def __getitem__(self, i):
195
"""
196
Return the ith coefficient of f.
197
198
EXAMPLES:
199
sage: f = ntl.zz_pX(range(7), 71)
200
sage: f[3] ## indirect doctest
201
3
202
203
sage: f[-5]
204
0
205
206
sage: f[27]
207
0
208
"""
209
cdef ntl_zz_p y
210
y = PY_NEW(ntl_zz_p)
211
y.c = self.c
212
self.c.restore_c()
213
if not PY_TYPE_CHECK( i, long ):
214
i = long(i)
215
y.x = zz_pX_GetCoeff(self.x, i)
216
return y
217
218
def __setitem__(self, i, val):
219
"""
220
Set the ith coefficient of self to val. If
221
i is out of range, raise an exception.
222
223
EXAMPLES:
224
sage: f = ntl.zz_pX([], 7)
225
sage: f[3] = 2 ; f
226
[0, 0, 0, 2]
227
sage: f[-1] = 5
228
Traceback (most recent call last):
229
...
230
ValueError: index (=-1) is out of range
231
"""
232
cdef long zero = 0L
233
if not PY_TYPE_CHECK( i, long ):
234
i = long(i)
235
if (i < zero):
236
raise ValueError, "index (=%s) is out of range"%i
237
if not PY_TYPE_CHECK( val, long ):
238
val = long(val)
239
self.c.restore_c()
240
zz_pX_SetCoeff_long(self.x, i, val)
241
return
242
243
cdef ntl_zz_pX _new(self):
244
"""
245
Quick and dirty method for creating a new object with the
246
same zz_pContext as self.
247
248
EXAMPLES:
249
sage: f = ntl.zz_pX([1], 20)
250
sage: f.square() ## indirect doctest
251
[1]
252
"""
253
cdef ntl_zz_pX y
254
y = PY_NEW(ntl_zz_pX)
255
y.c = self.c
256
return y
257
258
def __add__(ntl_zz_pX self, other):
259
"""
260
Return self + other.
261
262
EXAMPLES:
263
sage: ntl.zz_pX(range(5),20) + ntl.zz_pX(range(6),20) ## indirect doctest
264
[0, 2, 4, 6, 8, 5]
265
sage: ntl.zz_pX(range(5),20) + ntl.zz_pX(range(6),50)
266
Traceback (most recent call last):
267
...
268
ValueError: arithmetic operands must have the same modulus.
269
"""
270
cdef ntl_zz_pX y
271
if not PY_TYPE_CHECK(other, ntl_zz_pX):
272
other = ntl_zz_pX(other, modulus=self.c)
273
elif self.c is not (<ntl_zz_pX>other).c:
274
raise ValueError, "arithmetic operands must have the same modulus."
275
y = self._new()
276
self.c.restore_c()
277
zz_pX_add(y.x, self.x, (<ntl_zz_pX>other).x)
278
return y
279
280
def __sub__(ntl_zz_pX self, other):
281
"""
282
Return self - other.
283
284
EXAMPLES:
285
sage: ntl.zz_pX(range(5),32) - ntl.zz_pX(range(6),32)
286
[0, 0, 0, 0, 0, 27]
287
sage: ntl.zz_pX(range(5),20) - ntl.zz_pX(range(6),50) ## indirect doctest
288
Traceback (most recent call last):
289
...
290
ValueError: arithmetic operands must have the same modulus.
291
"""
292
cdef ntl_zz_pX y
293
if not PY_TYPE_CHECK(other, ntl_zz_pX):
294
other = ntl_zz_pX(other, modulus=self.c)
295
elif self.c is not (<ntl_zz_pX>other).c:
296
raise ValueError, "arithmetic operands must have the same modulus."
297
self.c.restore_c()
298
y = self._new()
299
zz_pX_sub(y.x, self.x, (<ntl_zz_pX>other).x)
300
return y
301
302
def __mul__(ntl_zz_pX self, other):
303
"""
304
EXAMPLES:
305
sage: ntl.zz_pX(range(5),20) * ntl.zz_pX(range(6),20) ## indirect doctest
306
[0, 0, 1, 4, 10, 0, 10, 14, 11]
307
sage: ntl.zz_pX(range(5),20) * ntl.zz_pX(range(6),50)
308
Traceback (most recent call last):
309
...
310
ValueError: arithmetic operands must have the same modulus.
311
"""
312
cdef ntl_zz_pX y
313
if not PY_TYPE_CHECK(other, ntl_zz_pX):
314
other = ntl_zz_pX(other, modulus=self.c)
315
elif self.c is not (<ntl_zz_pX>other).c:
316
raise ValueError, "arithmetic operands must have the same modulus."
317
self.c.restore_c()
318
y = self._new()
319
sig_on()
320
zz_pX_mul(y.x, self.x, (<ntl_zz_pX>other).x)
321
sig_off()
322
return y
323
324
def __div__(ntl_zz_pX self, other):
325
"""
326
Compute quotient self / other, if the quotient is a polynomial.
327
Otherwise an Exception is raised.
328
329
EXAMPLES:
330
sage: f = ntl.zz_pX([1,2,3],17) * ntl.zz_pX([4,5],17)**2
331
sage: g = ntl.zz_pX([4,5],17)
332
sage: f/g ## indirect doctest
333
[4, 13, 5, 15]
334
sage: ntl.zz_pX([1,2,3],17) * ntl.zz_pX([4,5],17)
335
[4, 13, 5, 15]
336
337
sage: f = ntl.zz_pX(range(10),17); g = ntl.zz_pX([-1,0,1],17)
338
sage: f/g
339
Traceback (most recent call last):
340
...
341
ArithmeticError: self (=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) is not divisible by other (=[16, 0, 1])
342
sage: ntl.zz_pX(range(5),20) / ntl.zz_pX(range(6),50)
343
Traceback (most recent call last):
344
...
345
ValueError: arithmetic operands must have the same modulus.
346
"""
347
cdef long divisible
348
cdef ntl_zz_pX q
349
if not PY_TYPE_CHECK(other, ntl_zz_pX):
350
other = ntl_zz_pX(other, modulus=self.c)
351
elif self.c is not (<ntl_zz_pX>other).c:
352
raise ValueError, "arithmetic operands must have the same modulus."
353
self.c.restore_c()
354
q = self._new()
355
sig_on()
356
divisible = zz_pX_divide(q.x, self.x, (<ntl_zz_pX>other).x)
357
sig_off()
358
if not divisible:
359
raise ArithmeticError, "self (=%s) is not divisible by other (=%s)"%(self, other)
360
return q
361
362
def __mod__(ntl_zz_pX self, other):
363
"""
364
Given polynomials a, b in ZZ[X], there exist polynomials q, r
365
in QQ[X] such that a = b*q + r, deg(r) < deg(b). This
366
function returns q if q lies in ZZ[X], and otherwise raises an
367
Exception.
368
369
EXAMPLES:
370
sage: f = ntl.zz_pX([2,4,6],17); g = ntl.zz_pX([2],17)
371
sage: f % g ## indirect doctest
372
[]
373
374
sage: f = ntl.zz_pX(range(10),17); g = ntl.zz_pX([-1,0,1],17)
375
sage: f % g
376
[3, 8]
377
"""
378
cdef ntl_zz_pX y
379
if not PY_TYPE_CHECK(other, ntl_zz_pX):
380
other = ntl_zz_pX(other, modulus=self.c)
381
elif self.c is not (<ntl_zz_pX>other).c:
382
raise ValueError, "arithmetic operands must have the same modulus."
383
self.c.restore_c()
384
y = self._new()
385
sig_on()
386
zz_pX_mod(y.x, self.x, (<ntl_zz_pX>other).x)
387
sig_off()
388
return y
389
390
def __pow__(ntl_zz_pX self, long n, ignored):
391
"""
392
Return the n-th nonnegative power of self.
393
394
EXAMPLES:
395
sage: g = ntl.zz_pX([-1,0,1],20)
396
sage: g**10 ## indirect doctest
397
[1, 0, 10, 0, 5, 0, 0, 0, 10, 0, 8, 0, 10, 0, 0, 0, 5, 0, 10, 0, 1]
398
"""
399
if n < 0:
400
raise ValueError, "Only positive exponents allowed."
401
cdef ntl_zz_pX y = self._new()
402
self.c.restore_c()
403
sig_on()
404
zz_pX_power(y.x, self.x, n)
405
sig_off()
406
return y
407
408
def quo_rem(ntl_zz_pX self, ntl_zz_pX right):
409
"""
410
Returns the quotient and remainder when self is divided by right.
411
412
Specifically, this return r, q such that $self = q * right + r$
413
414
EXAMPLES:
415
sage: f = ntl.zz_pX(range(7), 19)
416
sage: g = ntl.zz_pX([2,4,6], 19)
417
sage: f // g
418
[1, 1, 15, 16, 1]
419
sage: f % g
420
[17, 14]
421
sage: f.quo_rem(g)
422
([1, 1, 15, 16, 1], [17, 14])
423
sage: (f // g) * g + f % g
424
[0, 1, 2, 3, 4, 5, 6]
425
"""
426
cdef ntl_zz_pX q = self._new()
427
cdef ntl_zz_pX r = self._new()
428
self.c.restore_c()
429
sig_on()
430
zz_pX_divrem(q.x, r.x, self.x, right.x)
431
sig_off()
432
return q, r
433
434
def __floordiv__(ntl_zz_pX self, ntl_zz_pX right):
435
"""
436
Returns the whole part of $self / right$.
437
438
EXAMPLE:
439
sage: f = ntl.zz_pX(range(10), 19); g = ntl.zz_pX([1]*5, 19)
440
sage: f // g ## indirect doctest
441
[8, 18, 18, 18, 18, 9]
442
443
"""
444
cdef ntl_zz_pX q = self._new()
445
self.c.restore_c()
446
sig_on()
447
zz_pX_div(q.x, self.x, right.x)
448
sig_off()
449
return q
450
451
def __lshift__(ntl_zz_pX self, long n):
452
"""
453
Shifts this polynomial to the left, which is multiplication by $x^n$.
454
455
EXAMPLE:
456
sage: f = ntl.zz_pX([2,4,6], 17)
457
sage: f << 2 ## indirect doctest
458
[0, 0, 2, 4, 6]
459
"""
460
cdef ntl_zz_pX r = self._new()
461
self.c.restore_c()
462
zz_pX_LeftShift(r.x, self.x, n)
463
return r
464
465
def __rshift__(ntl_zz_pX self, long n):
466
"""
467
Shifts this polynomial to the right, which is division by $x^n$ (and truncation).
468
469
EXAMPLE:
470
sage: f = ntl.zz_pX([1,2,3], 17)
471
sage: f >> 2 ## indirect doctest
472
[3]
473
"""
474
cdef ntl_zz_pX r = self._new()
475
self.c.restore_c()
476
zz_pX_RightShift(r.x, self.x, n)
477
return r
478
479
def diff(self):
480
"""
481
The formal derivative of self.
482
483
EXAMPLE:
484
sage: f = ntl.zz_pX(range(10), 17)
485
sage: f.diff()
486
[1, 4, 9, 16, 8, 2, 15, 13, 13]
487
"""
488
cdef ntl_zz_pX r = self._new()
489
self.c.restore_c()
490
zz_pX_diff(r.x, self.x)
491
return r
492
493
def reverse(self):
494
"""
495
Returns self with coefficients reversed, i.e. $x^n self(x^{-n})$.
496
497
EXAMPLE:
498
sage: f = ntl.zz_pX([2,4,6], 17)
499
sage: f.reverse()
500
[6, 4, 2]
501
"""
502
cdef ntl_zz_pX r = self._new()
503
self.c.restore_c()
504
zz_pX_reverse(r.x, self.x)
505
return r
506
507
def __neg__(self):
508
"""
509
Return the negative of self.
510
EXAMPLES:
511
sage: f = ntl.zz_pX([2,0,0,1],20)
512
sage: -f
513
[18, 0, 0, 19]
514
"""
515
cdef ntl_zz_pX y
516
y = self._new()
517
self.c.restore_c()
518
sig_on()
519
zz_pX_negate(y.x, self.x)
520
sig_off()
521
return y
522
523
def __cmp__(ntl_zz_pX self, other):
524
"""
525
Decide whether or not self and other are equal.
526
527
EXAMPLES:
528
sage: f = ntl.zz_pX([1,2,3],20)
529
sage: g = ntl.zz_pX([1,2,3,0],20)
530
sage: f == g
531
True
532
sage: g = ntl.zz_pX([0,1,2,3],20)
533
sage: f == g
534
False
535
"""
536
if not PY_TYPE_CHECK(other, ntl_zz_pX):
537
return cmp(ntl_zz_pX, other.parent())
538
if not (self.c is (<ntl_zz_pX>other).c):
539
return cmp(self.c.p, (<ntl_zz_pX>other).c.p)
540
541
self.c.restore_c()
542
if (NTL_zz_pX_DOUBLE_EQUALS(self.x, (<ntl_zz_pX>other).x)):
543
return 0
544
else:
545
return -1
546
547
def list(self):
548
"""
549
Return list of entries as a list of python ints.
550
551
EXAMPLES:
552
sage: f = ntl.zz_pX([23, 5,0,1], 10)
553
sage: f.list()
554
[3, 5, 0, 1]
555
sage: type(f.list()[0])
556
<type 'int'>
557
"""
558
cdef long i
559
self.c.restore_c()
560
return [ zz_p_rep(zz_pX_GetCoeff(self.x, i)) for i from 0 <= i <= zz_pX_deg(self.x) ]
561
562
def degree(self):
563
"""
564
Return the degree of this polynomial. The degree of the 0
565
polynomial is -1.
566
567
EXAMPLES:
568
sage: f = ntl.zz_pX([5,0,1],50)
569
sage: f.degree()
570
2
571
sage: f = ntl.zz_pX(range(100),50)
572
sage: f.degree()
573
99
574
sage: f = ntl.zz_pX([],10)
575
sage: f.degree()
576
-1
577
sage: f = ntl.zz_pX([1],77)
578
sage: f.degree()
579
0
580
"""
581
self.c.restore_c()
582
return zz_pX_deg(self.x)
583
584
def leading_coefficient(self):
585
"""
586
Return the leading coefficient of this polynomial.
587
588
EXAMPLES:
589
sage: f = ntl.zz_pX([3,6,9],19)
590
sage: f.leading_coefficient()
591
9
592
sage: f = ntl.zz_pX([],21)
593
sage: f.leading_coefficient()
594
0
595
"""
596
self.c.restore_c()
597
return zz_p_rep(zz_pX_LeadCoeff(self.x))
598
599
def constant_term(self):
600
"""
601
Return the constant coefficient of this polynomial.
602
603
EXAMPLES:
604
sage: f = ntl.zz_pX([3,6,9],127)
605
sage: f.constant_term()
606
3
607
sage: f = ntl.zz_pX([], 12223)
608
sage: f.constant_term()
609
0
610
"""
611
self.c.restore_c()
612
return zz_p_rep(zz_pX_ConstTerm(self.x))
613
614
def square(self):
615
"""
616
Return f*f.
617
618
EXAMPLES:
619
sage: f = ntl.zz_pX([-1,0,1],17)
620
sage: f*f
621
[1, 0, 15, 0, 1]
622
"""
623
cdef ntl_zz_pX y = self._new()
624
self.c.restore_c()
625
sig_on()
626
zz_pX_sqr(y.x, self.x)
627
sig_off()
628
return y
629
630
def truncate(self, long m):
631
"""
632
Return the truncation of this polynomial obtained by
633
removing all terms of degree >= m.
634
635
EXAMPLES:
636
sage: f = ntl.zz_pX([1,2,3,4,5],70)
637
sage: f.truncate(3)
638
[1, 2, 3]
639
sage: f.truncate(8)
640
[1, 2, 3, 4, 5]
641
sage: f.truncate(1)
642
[1]
643
sage: f.truncate(0)
644
[]
645
sage: f.truncate(-1)
646
[]
647
sage: f.truncate(-5)
648
[]
649
"""
650
cdef ntl_zz_pX y = self._new()
651
self.c.restore_c()
652
if m <= 0:
653
y.x = zz_pX_zero()
654
else:
655
sig_on()
656
zz_pX_trunc(y.x, self.x, m)
657
sig_off()
658
return y
659
660
def multiply_and_truncate(self, ntl_zz_pX other, long m):
661
"""
662
Return self*other but with terms of degree >= m removed.
663
664
EXAMPLES:
665
sage: f = ntl.zz_pX([1,2,3,4,5],20)
666
sage: g = ntl.zz_pX([10],20)
667
sage: f.multiply_and_truncate(g, 2)
668
[10]
669
sage: g.multiply_and_truncate(f, 2)
670
[10]
671
"""
672
cdef ntl_zz_pX y = self._new()
673
self.c.restore_c()
674
if m <= 0:
675
y.x = zz_pX_zero()
676
else:
677
sig_on()
678
zz_pX_MulTrunc(y.x, self.x, other.x, m)
679
sig_off()
680
return y
681
682
def square_and_truncate(self, long m):
683
"""
684
Return self*self but with terms of degree >= m removed.
685
686
EXAMPLES:
687
sage: f = ntl.zz_pX([1,2,3,4,5],20)
688
sage: f.square_and_truncate(4)
689
[1, 4, 10]
690
sage: (f*f).truncate(4)
691
[1, 4, 10]
692
"""
693
cdef ntl_zz_pX y = self._new()
694
self.c.restore_c()
695
if m <= 0:
696
y.x = zz_pX_zero()
697
else:
698
sig_on()
699
zz_pX_SqrTrunc(y.x, self.x, m)
700
sig_off()
701
return y
702
703
def invert_and_truncate(self, long m):
704
"""
705
Compute and return the inverse of self modulo $x^m$.
706
The constant term of self must be 1 or -1.
707
708
EXAMPLES:
709
sage: f = ntl.zz_pX([1,2,3,4,5,6,7],20)
710
sage: f.invert_and_truncate(20)
711
[1, 18, 1, 0, 0, 0, 0, 8, 17, 2, 13, 0, 0, 0, 4, 0, 17, 10, 9]
712
sage: g = f.invert_and_truncate(20)
713
sage: g * f
714
[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]
715
"""
716
if m < 0:
717
raise ArithmeticError, "m (=%s) must be positive"%m
718
n = self.constant_term()
719
if n != 1 and n != -1:
720
raise ArithmeticError, \
721
"The constant term of self must be 1 or -1."
722
723
cdef ntl_zz_pX y = self._new()
724
725
self.c.restore_c()
726
if m <= 0:
727
y.x = zz_pX_zero()
728
else:
729
sig_on()
730
zz_pX_InvTrunc(y.x, self.x, m)
731
sig_off()
732
return y
733
734
735
def is_zero(self):
736
"""
737
Return True exactly if this polynomial is 0.
738
739
EXAMPLES:
740
sage: f = ntl.zz_pX([0,0,0,20],5)
741
sage: f.is_zero()
742
True
743
sage: f = ntl.zz_pX([0,0,1],30)
744
sage: f
745
[0, 0, 1]
746
sage: f.is_zero()
747
False
748
"""
749
self.c.restore_c()
750
return zz_pX_IsZero(self.x)
751
752
def is_one(self):
753
"""
754
Return True exactly if this polynomial is 1.
755
756
EXAMPLES:
757
sage: f = ntl.zz_pX([1,1],101)
758
sage: f.is_one()
759
False
760
sage: f = ntl.zz_pX([1],2)
761
sage: f.is_one()
762
True
763
"""
764
self.c.restore_c()
765
return zz_pX_IsOne(self.x)
766
767
def is_monic(self):
768
"""
769
Return True exactly if this polynomial is monic.
770
771
EXAMPLES:
772
sage: f = ntl.zz_pX([2,0,0,1],17)
773
sage: f.is_monic()
774
True
775
sage: g = f.reverse()
776
sage: g.is_monic()
777
False
778
sage: g
779
[1, 0, 0, 2]
780
sage: f = ntl.zz_pX([1,2,0,3,0,2],717)
781
sage: f.is_monic()
782
False
783
"""
784
self.c.restore_c()
785
if zz_pX_IsZero(self.x):
786
return False
787
return ( zz_p_rep(zz_pX_LeadCoeff(self.x)) == 1 )
788
789
def set_x(self):
790
"""
791
Set this polynomial to the monomial "x".
792
793
EXAMPLES:
794
sage: f = ntl.zz_pX([],177)
795
sage: f.set_x()
796
sage: f
797
[0, 1]
798
sage: g = ntl.zz_pX([0,1],177)
799
sage: f == g
800
True
801
802
Though f and g are equal, they are not the same objects in memory:
803
sage: f is g
804
False
805
806
"""
807
self.c.restore_c()
808
zz_pX_SetX(self.x)
809
810
def is_x(self):
811
"""
812
True if this is the polynomial "x".
813
814
EXAMPLES:
815
sage: f = ntl.zz_pX([],100)
816
sage: f.set_x()
817
sage: f.is_x()
818
True
819
sage: f = ntl.zz_pX([0,1],383)
820
sage: f.is_x()
821
True
822
sage: f = ntl.zz_pX([1],38)
823
sage: f.is_x()
824
False
825
"""
826
self.c.restore_c()
827
return zz_pX_IsX(self.x)
828
829
def clear(self):
830
"""
831
Reset this polynomial to 0. Changes this polynomial in place.
832
833
EXAMPLES:
834
sage: f = ntl.zz_pX([1,2,3],17)
835
sage: f
836
[1, 2, 3]
837
sage: f.clear()
838
sage: f
839
[]
840
"""
841
self.c.restore_c()
842
zz_pX_clear(self.x)
843
844
def preallocate_space(self, long n):
845
"""
846
Pre-allocate spaces for n coefficients. The polynomial that f
847
represents is unchanged. This is useful if you know you'll be
848
setting coefficients up to n, so memory isn't re-allocated as
849
the polynomial grows. (You might save a millisecond with this
850
function.)
851
852
EXAMPLES:
853
sage: f = ntl.zz_pX([1,2,3],17)
854
sage: f.preallocate_space(20)
855
sage: f
856
[1, 2, 3]
857
sage: f[10]=5 # no new memory is allocated
858
sage: f
859
[1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 5]
860
"""
861
self.c.restore_c()
862
sig_on()
863
self.x.SetMaxLength(n)
864
sig_off()
865
return
866
867
868
def make_zz_pX(L, context):
869
"""
870
For unpickling.
871
872
TESTS:
873
sage: f = ntl.zz_pX(range(16), 12)
874
sage: loads(dumps(f)) == f
875
True
876
"""
877
return ntl_zz_pX(L, context)
878
879