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