Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/libs/flint/fmpz_poly.pyx
8817 views
1
"""
2
FLINT fmpz_poly class wrapper
3
4
AUTHORS:
5
6
- Robert Bradshaw (2007-09-15) Initial version.
7
- William Stein (2007-10-02) update for new flint; add arithmetic and creation
8
of coefficients of arbitrary size.
9
"""
10
11
12
#*****************************************************************************
13
# Copyright (C) 2007 Robert Bradshaw <[email protected]>
14
#
15
# Distributed under the terms of the GNU General Public License (GPL)
16
#
17
# This code is distributed in the hope that it will be useful,
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
# General Public License for more details.
21
#
22
# The full text of the GPL is available at:
23
#
24
# http://www.gnu.org/licenses/
25
#*****************************************************************************
26
27
28
from cpython.sequence cimport *
29
30
from sage.structure.sage_object cimport SageObject
31
from sage.rings.integer cimport Integer
32
33
cdef class Fmpz_poly(SageObject):
34
35
def __cinit__(self):
36
fmpz_poly_init(self.poly)
37
38
def __init__(self, v):
39
"""
40
Construct a new fmpz_poly from a sequence, constant coefficient,
41
or string (in the same format as it prints).
42
43
EXAMPLES::
44
45
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
46
sage: Fmpz_poly([1,2,3])
47
3 1 2 3
48
sage: Fmpz_poly(5)
49
1 5
50
sage: Fmpz_poly(str(Fmpz_poly([3,5,7])))
51
3 3 5 7
52
"""
53
cdef Py_ssize_t i
54
cdef long c
55
cdef Integer w
56
if PY_TYPE_CHECK(v, str):
57
if not fmpz_poly_set_str(self.poly, v):
58
return
59
else:
60
raise ValueError, "Unable to create Fmpz_poly from that string."
61
if not PySequence_Check(v):
62
v = [v]
63
try:
64
fmpz_poly_set_coeff_si(self.poly, 0, 1)
65
fmpz_poly_set_coeff_si(self.poly, 0, 0)
66
for i from 0 <= i < len(v):
67
#fmpz_poly_set_coeff_si(self.poly, i, v[i])
68
w = Integer(v[i])
69
fmpz_poly_set_coeff_mpz(self.poly, i, w.value)
70
except OverflowError:
71
raise ValueError, "No fmpz_poly_set_coeff_mpz() method."
72
73
def __dealloc__(self):
74
fmpz_poly_clear(self.poly)
75
76
def __setitem__(self, i, value):
77
"""
78
Set the $i$-th item of self, which is the coefficient of the $x^i$ term.
79
80
EXAMPLES::
81
82
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
83
sage: f = Fmpz_poly(range(10))
84
sage: f[7] = 100; f
85
10 0 1 2 3 4 5 6 100 8 9
86
sage: f[2] = 10**100000
87
sage: f[2] == 10**100000
88
True
89
"""
90
if PY_TYPE_CHECK(value, Integer) :
91
fmpz_poly_set_coeff_mpz(self.poly, i, (<Integer>value).value)
92
else :
93
fmpz_poly_set_coeff_si(self.poly, i, value)
94
95
def __getitem__(self, i):
96
"""
97
Return the $i$-th item of self, which is the coefficient of the $x^i$ term.
98
99
EXAMPLES::
100
101
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
102
sage: f = Fmpz_poly(range(100))
103
sage: f[13]
104
13
105
sage: f[200]
106
0
107
"""
108
cdef Integer res = <Integer>PY_NEW(Integer)
109
fmpz_poly_get_coeff_mpz(res.value, self.poly, i)
110
return res
111
112
def __repr__(self):
113
"""
114
Print self according to the native FLINT format.
115
116
EXAMPLES::
117
118
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
119
sage: f = Fmpz_poly([0,1]); f^7
120
8 0 0 0 0 0 0 0 1
121
"""
122
cdef char* ss = fmpz_poly_get_str(self.poly)
123
cdef object s = ss
124
sage_free(ss)
125
return s
126
127
def degree(self):
128
"""
129
The degree of self.
130
131
EXAMPLES::
132
133
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
134
sage: f = Fmpz_poly([1,2,3]); f
135
3 1 2 3
136
sage: f.degree()
137
2
138
sage: Fmpz_poly(range(1000)).degree()
139
999
140
sage: Fmpz_poly([2,0]).degree()
141
0
142
"""
143
return fmpz_poly_degree(self.poly)
144
145
def list(self):
146
"""
147
Return self as a list of coefficients, lowest terms first.
148
149
EXAMPLES::
150
151
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
152
sage: f = Fmpz_poly([2,1,0,-1])
153
sage: f.list()
154
[2, 1, 0, -1]
155
"""
156
return [self[i] for i in xrange(self.degree()+1)]
157
158
def __add__(left, right):
159
"""
160
Add together two Flint polynomials.
161
162
EXAMPLES::
163
164
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
165
sage: Fmpz_poly([1,2,3]) + Fmpz_poly(range(6))
166
6 1 3 5 3 4 5
167
"""
168
if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly):
169
raise TypeError
170
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
171
fmpz_poly_add(res.poly, (<Fmpz_poly>left).poly, (<Fmpz_poly>right).poly)
172
return res
173
174
def __sub__(left, right):
175
"""
176
Subtract two Flint polynomials.
177
178
EXAMPLES::
179
180
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
181
sage: Fmpz_poly([10,2,3]) - Fmpz_poly([4,-2,1])
182
3 6 4 2
183
"""
184
if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly):
185
raise TypeError
186
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
187
fmpz_poly_sub(res.poly, (<Fmpz_poly>left).poly, (<Fmpz_poly>right).poly)
188
return res
189
190
def __neg__(self):
191
"""
192
Return the negative of self.
193
194
EXAMPLES::
195
196
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
197
sage: -Fmpz_poly([2,10,2,3,18,-5])
198
6 -2 -10 -2 -3 -18 5
199
"""
200
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
201
fmpz_poly_neg(res.poly, self.poly)
202
return res
203
204
def __mul__(left, right):
205
"""
206
Return the product of left and right.
207
208
EXAMPLES::
209
210
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
211
sage: f = Fmpz_poly([0,1]); g = Fmpz_poly([2,3,4])
212
sage: f*g
213
4 0 2 3 4
214
sage: f = Fmpz_poly([1,0,-1]); g = Fmpz_poly([2,3,4])
215
sage: f*g
216
5 2 3 2 -3 -4
217
218
Scalar multiplication
219
sage: f * 3
220
3 3 0 -3
221
sage: f * 5r
222
3 5 0 -5
223
"""
224
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
225
if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly):
226
if PY_TYPE_CHECK(left, int) :
227
fmpz_poly_scalar_mul_si(res.poly, (<Fmpz_poly>right).poly, left)
228
elif PY_TYPE_CHECK(left, Integer) :
229
fmpz_poly_scalar_mul_mpz(res.poly, (<Fmpz_poly>right).poly, (<Integer>left).value)
230
elif PY_TYPE_CHECK(right, int) :
231
fmpz_poly_scalar_mul_si(res.poly, (<Fmpz_poly>left).poly, right)
232
elif PY_TYPE_CHECK(right, Integer) :
233
fmpz_poly_scalar_mul_mpz(res.poly, (<Fmpz_poly>left).poly, (<Integer>right).value)
234
else:
235
raise TypeError
236
else:
237
fmpz_poly_mul(res.poly, (<Fmpz_poly>left).poly, (<Fmpz_poly>right).poly)
238
return res
239
240
def __pow__(self, n, dummy):
241
"""
242
Return self raised to the power of n.
243
244
EXAMPLES::
245
246
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
247
sage: f = Fmpz_poly([1,1])
248
sage: f**6
249
7 1 6 15 20 15 6 1
250
sage: f = Fmpz_poly([2])
251
sage: f^150
252
1 1427247692705959881058285969449495136382746624
253
sage: 2^150
254
1427247692705959881058285969449495136382746624
255
"""
256
cdef long nn = n
257
if not PY_TYPE_CHECK(self, Fmpz_poly):
258
raise TypeError
259
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
260
fmpz_poly_pow(res.poly, (<Fmpz_poly>self).poly, nn)
261
return res
262
263
def pow_truncate(self, exp, n):
264
"""
265
Return self raised to the power of exp mod x^n.
266
267
EXAMPLES::
268
269
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
270
sage: f = Fmpz_poly([1,2])
271
sage: f.pow_truncate(10,3)
272
3 1 20 180
273
sage: f.pow_truncate(1000,3)
274
3 1 2000 1998000
275
"""
276
if exp < 0:
277
raise ValueError, "Exponent must be at least 0"
278
if n < 0:
279
raise ValueError, "Exponent must be at least 0"
280
cdef long exp_c = exp, nn = n
281
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
282
fmpz_poly_pow_trunc(res.poly, (<Fmpz_poly>self).poly, exp_c, nn)
283
return res
284
285
def __floordiv__(left, right):
286
"""
287
Return left // right, truncated.
288
289
EXAMPLES::
290
291
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
292
sage: f = Fmpz_poly([3,4,5])
293
sage: g = f^5; g
294
11 243 1620 6345 16560 32190 47224 53650 46000 29375 12500 3125
295
sage: g // f
296
9 81 432 1404 2928 4486 4880 3900 2000 625
297
sage: f^4
298
9 81 432 1404 2928 4486 4880 3900 2000 625
299
"""
300
if not PY_TYPE_CHECK(left, Fmpz_poly) or not PY_TYPE_CHECK(right, Fmpz_poly):
301
raise TypeError
302
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
303
fmpz_poly_div(res.poly, (<Fmpz_poly>left).poly, (<Fmpz_poly>right).poly)
304
return res
305
306
def div_rem(self, Fmpz_poly other):
307
"""
308
Return self / other, self, % other.
309
310
EXAMPLES::
311
312
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
313
sage: f = Fmpz_poly([1,3,4,5])
314
sage: g = f^23
315
sage: g.div_rem(f)[1]
316
0
317
sage: g.div_rem(f)[0] - f^22
318
0
319
sage: f = Fmpz_poly([1..10])
320
sage: g = Fmpz_poly([1,3,5])
321
sage: q, r = f.div_rem(g)
322
sage: q*f+r
323
17 1 2 3 4 4 4 10 11 17 18 22 26 30 23 26 18 20
324
sage: g
325
3 1 3 5
326
sage: q*g+r
327
10 1 2 3 4 5 6 7 8 9 10
328
"""
329
cdef Fmpz_poly Q = <Fmpz_poly>PY_NEW(Fmpz_poly)
330
cdef Fmpz_poly R = <Fmpz_poly>PY_NEW(Fmpz_poly)
331
fmpz_poly_divrem(Q.poly, R.poly, self.poly, other.poly)
332
return Q, R
333
334
def left_shift(self, unsigned long n) :
335
"""
336
Left shift self by n.
337
338
EXAMPLES::
339
340
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
341
sage: f = Fmpz_poly([1,2])
342
sage: f.left_shift(1).list() == [0,1,2]
343
True
344
"""
345
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
346
347
fmpz_poly_shift_left(res.poly, self.poly, n)
348
349
return res
350
351
def right_shift(self, unsigned long n) :
352
"""
353
Right shift self by n.
354
355
EXAMPLES::
356
357
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
358
sage: f = Fmpz_poly([1,2])
359
sage: f.right_shift(1).list() == [2]
360
True
361
"""
362
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
363
364
fmpz_poly_shift_right(res.poly, self.poly, n)
365
366
return res
367
368
def pseudo_div(self, Fmpz_poly other):
369
cdef unsigned long d
370
cdef Fmpz_poly Q = <Fmpz_poly>PY_NEW(Fmpz_poly)
371
fmpz_poly_pseudo_div(Q.poly, &d, self.poly, other.poly)
372
return Q, d
373
374
def pseudo_div_rem(self, Fmpz_poly other):
375
cdef unsigned long d
376
cdef Fmpz_poly Q = <Fmpz_poly>PY_NEW(Fmpz_poly)
377
cdef Fmpz_poly R = <Fmpz_poly>PY_NEW(Fmpz_poly)
378
fmpz_poly_pseudo_divrem(Q.poly, R.poly, &d, self.poly, other.poly)
379
return Q, R, d
380
381
def derivative(self) :
382
"""
383
Return the derivative of self.
384
385
EXAMPLES::
386
387
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
388
sage: f = Fmpz_poly([1,2,6])
389
sage: f.derivative().list() == [2, 12]
390
True
391
"""
392
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
393
394
fmpz_poly_derivative(res.poly, self.poly)
395
396
return res
397
398
def __copy__(self):
399
cdef Fmpz_poly res = <Fmpz_poly>PY_NEW(Fmpz_poly)
400
fmpz_poly_set(res.poly, self.poly)
401
return res
402
403
def truncate(self, n):
404
"""
405
Return the truncation of self at degree n.
406
407
EXAMPLES::
408
409
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
410
sage: f = Fmpz_poly([1,1])
411
sage: g = f**10; g
412
11 1 10 45 120 210 252 210 120 45 10 1
413
sage: g.truncate(5)
414
5 1 10 45 120 210
415
"""
416
cdef Fmpz_poly g = self.__copy__()
417
fmpz_poly_truncate(g.poly, n)
418
return g
419
420
def _unsafe_mutate_truncate(self, n):
421
"""
422
Return the truncation of self at degree n.
423
424
Don't do this unless you know there are no other references to
425
this polynomial!!!!!
426
427
EXAMPLES::
428
429
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
430
sage: f = Fmpz_poly([1,1])
431
sage: g = f**10; g
432
11 1 10 45 120 210 252 210 120 45 10 1
433
sage: g._unsafe_mutate_truncate(5); g
434
5 1 10 45 120 210
435
"""
436
cdef long nn = n
437
fmpz_poly_truncate(self.poly, nn) # mutating!
438
439
440
def _sage_(self, var='x'):
441
"""
442
Return self as an element of the sage ZZ[var].
443
444
EXAMPLES::
445
446
sage: from sage.libs.flint.fmpz_poly import Fmpz_poly
447
sage: f = Fmpz_poly([1,1])
448
sage: f._sage_('t')
449
t + 1
450
sage: Fmpz_poly([-1,0,0,1])._sage_()
451
x^3 - 1
452
"""
453
from sage.rings.all import ZZ
454
return ZZ[var](self.list())
455
456
457