Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/libs/singular/polynomial.pyx
8817 views
1
"""
2
Wrapper for Singular's Polynomial Arithmetic
3
4
AUTHOR:
5
6
- Martin Albrecht (2009-07): refactoring
7
"""
8
#*****************************************************************************
9
# Copyright (C) 2009 Martin Albrecht <[email protected]>
10
#
11
# Distributed under the terms of the GNU General Public License (GPL)
12
# http://www.gnu.org/licenses/
13
#*****************************************************************************
14
include "sage/ext/interrupt.pxi"
15
16
cdef extern from *: # hack to get at cython macro
17
int unlikely(int)
18
19
import re
20
plusminus_pattern = re.compile("([^\(^])([\+\-])")
21
22
from sage.libs.singular.decl cimport number, ideal
23
from sage.libs.singular.decl cimport currRing, rChangeCurrRing
24
from sage.libs.singular.decl cimport p_Copy, p_Add_q, p_Neg, pp_Mult_nn, p_GetCoeff, p_IsConstant, p_Cmp, pNext
25
from sage.libs.singular.decl cimport p_GetMaxExp, pp_Mult_qq, pPower, p_String, p_GetExp, pLDeg
26
from sage.libs.singular.decl cimport n_Delete, idInit, fast_map, id_Delete
27
from sage.libs.singular.decl cimport omAlloc0, omStrDup, omFree
28
from sage.libs.singular.decl cimport p_GetComp, p_SetComp
29
30
31
from sage.libs.singular.singular cimport sa2si, si2sa, overflow_check
32
33
from sage.misc.latex import latex
34
35
cdef int singular_polynomial_check(poly *p, ring *r) except -1:
36
"""
37
Run consistency checks on ``p``.
38
"""
39
while p:
40
if p_GetCoeff(p, r) == NULL:
41
raise ZeroDivisionError("NULL pointer as coefficient.")
42
p = p.next
43
return 0
44
45
cdef int singular_polynomial_add(poly **ret, poly *p, poly *q, ring *r):
46
"""
47
``ret[0] = p+q`` where ``p`` and ``p`` in ``r``.
48
49
INPUT:
50
51
- ``ret`` - a pointer to a Singular polynomial to store the result in
52
- ``p`` - a Singular polynomial
53
- ``q`` - a Singular polynomial
54
- ``r`` - a Singular ring
55
56
EXAMPLE::
57
58
sage: P.<x,y,z> = QQ[]
59
sage: x + y # indirect doctest
60
x + y
61
62
sage: x + P(0)
63
x
64
"""
65
if(r != currRing): rChangeCurrRing(r)
66
p = p_Copy(p, r)
67
q = p_Copy(q, r)
68
ret[0] = p_Add_q(p, q, r)
69
return 0;
70
71
cdef int singular_polynomial_sub(poly **ret, poly *p, poly *q, ring *r):
72
"""
73
``ret[0] = p-q`` where ``p`` and ``p`` in ``r``.
74
75
INPUT:
76
77
- ``ret`` - a pointer to a Singular polynomial to store the result in
78
- ``p`` - a Singular polynomial
79
- ``q`` - a Singular polynomial
80
- ``r`` - a Singular ring
81
82
EXAMPLE::
83
84
sage: P.<x,y,z> = QQ[]
85
sage: x - y # indirect doctest
86
x - y
87
88
sage: x + P(0)
89
x
90
"""
91
if(r != currRing): rChangeCurrRing(r)
92
p = p_Copy(p, r)
93
q = p_Copy(q, r)
94
ret[0] = p_Add_q(p, p_Neg(q, r), r)
95
return 0;
96
97
cdef int singular_polynomial_rmul(poly **ret, poly *p, RingElement n, ring *r):
98
"""
99
``ret[0] = n*p`` where ``n`` is a coefficient and ``p`` in ``r``.
100
101
INPUT:
102
103
- ``ret`` - a pointer to a Singular polynomial to store the result in
104
- ``p`` - a Singular polynomial
105
- ``n`` - a Sage coefficient
106
- ``r`` - a Singular ring
107
108
EXAMPLE::
109
110
sage: P.<x,y,z> = QQ[]
111
sage: 2*x # indirect doctest
112
2*x
113
114
sage: P(0)*x
115
0
116
"""
117
if(r != currRing): rChangeCurrRing(r)
118
cdef number *_n = sa2si(n,r)
119
ret[0] = pp_Mult_nn(p, _n, r)
120
n_Delete(&_n, r)
121
return 0
122
123
cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly *(*get_element)(object)):
124
"""
125
``ret[0] = p(*args)`` where each entry in arg is a polynomial and ``p`` in ``r``.
126
127
INPUT:
128
129
- ``ret`` - a pointer to a Singular polynomial to store the result in
130
- ``p`` - a Singular polynomial
131
- ``r`` - a Singular ring
132
- ``args`` - a list/tuple of elements which can be converted to
133
Singular polynomials using the ``(get_element)`` function
134
provided.
135
- ``(*get_element)`` - a function to turn a Sage element into a
136
Singular element.
137
138
EXAMPLE::
139
140
sage: P.<x,y,z> = QQ[]
141
sage: x(0,0,0) # indirect doctest
142
0
143
144
sage: (3*x*z)(x,x,x)
145
3*x^2
146
"""
147
cdef long l = len(args)
148
cdef ideal *to_id = idInit(l,1)
149
for i from 0 <= i < l:
150
to_id.m[i]= p_Copy( get_element(args[i]), r)
151
152
cdef ideal *from_id=idInit(1,1)
153
from_id.m[0] = p
154
155
rChangeCurrRing(r)
156
cdef ideal *res_id = fast_map(from_id, r, to_id, r)
157
ret[0] = res_id.m[0]
158
159
from_id.m[0] = NULL
160
res_id.m[0] = NULL
161
162
id_Delete(&to_id, r)
163
id_Delete(&from_id, r)
164
id_Delete(&res_id, r)
165
166
return 0
167
168
cdef int singular_polynomial_cmp(poly *p, poly *q, ring *r):
169
"""
170
Compare two Singular elements ``p`` and ``q`` in ``r``.
171
172
INPUT:
173
174
- ``p`` - a Singular polynomial
175
- ``q`` - a Singular polynomial
176
- ``r`` - a Singular ring
177
178
EXAMPLES::
179
180
sage: P.<x,y,z> = PolynomialRing(QQ,order='degrevlex')
181
sage: x == x
182
True
183
184
sage: x > y
185
True
186
sage: y^2 > x
187
True
188
189
sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10)
190
True
191
"""
192
cdef number *h
193
cdef int ret = 0
194
195
if(r != currRing): rChangeCurrRing(r)
196
197
# handle special cases first (slight slowdown, as special cases
198
# are - well - special
199
if p == NULL:
200
if q == NULL:
201
# compare 0, 0
202
return 0
203
elif p_IsConstant(q,r):
204
# compare 0, const
205
return 1-2*r.cf.nGreaterZero(p_GetCoeff(q,r)) # -1: <, 1: > #
206
elif q == NULL:
207
if p_IsConstant(p,r):
208
# compare const, 0
209
return -1+2*r.cf.nGreaterZero(p_GetCoeff(p,r)) # -1: <, 1: >
210
#else
211
212
while ret==0 and p!=NULL and q!=NULL:
213
ret = p_Cmp( p, q, r)
214
215
if ret==0:
216
h = r.cf.nSub(p_GetCoeff(p, r),p_GetCoeff(q, r))
217
# compare coeffs
218
ret = -1+r.cf.nIsZero(h)+2*r.cf.nGreaterZero(h) # -1: <, 0:==, 1: >
219
n_Delete(&h, r)
220
p = pNext(p)
221
q = pNext(q)
222
223
if ret==0:
224
if p==NULL and q != NULL:
225
ret = -1
226
elif p!=NULL and q==NULL:
227
ret = 1
228
229
return ret
230
231
cdef int singular_polynomial_mul(poly** ret, poly *p, poly *q, ring *r) except -1:
232
"""
233
``ret[0] = p*q`` where ``p`` and ``p`` in ``r``.
234
235
INPUT:
236
237
- ``ret`` - a pointer to a Singular polynomial to store the result in
238
- ``p`` - a Singular polynomial
239
- ``q`` - a Singular polynomial
240
- ``r`` - a Singular ring
241
242
EXAMPLE::
243
244
sage: P.<x,y,z> = QQ[]
245
sage: x*y # indirect doctest
246
x*y
247
248
sage: x * P(0)
249
0
250
"""
251
if(r != currRing): rChangeCurrRing(r)
252
cdef unsigned long le = p_GetMaxExp(p, r)
253
cdef unsigned long lr = p_GetMaxExp(q, r)
254
cdef unsigned long esum = le + lr
255
overflow_check(esum, r)
256
ret[0] = pp_Mult_qq(p, q, r)
257
return 0;
258
259
cdef int singular_polynomial_div_coeff(poly** ret, poly *p, poly *q, ring *r) except -1:
260
"""
261
``ret[0] = p/n`` where ``p`` and ``q`` in ``r`` and ``q`` constant.
262
263
The last condition is not checked.
264
265
INPUT:
266
267
- ``ret`` - a pointer to a Singular polynomial to store the result in
268
- ``p`` - a Singular polynomial
269
- ``q`` - a constant Singular polynomial
270
- ``r`` - a Singular ring
271
272
EXAMPLE::
273
274
sage: P.<x,y,z> = QQ[]
275
sage: x/2 # indirect doctest
276
1/2*x
277
278
sage: x/0
279
Traceback (most recent call last):
280
...
281
ZeroDivisionError: rational division by zero
282
"""
283
if q == NULL:
284
raise ZeroDivisionError
285
sig_on()
286
cdef number *n = p_GetCoeff(q, r)
287
n = r.cf.nInvers(n)
288
ret[0] = pp_Mult_nn(p, n, r)
289
n_Delete(&n, r)
290
sig_off()
291
return 0
292
293
cdef int singular_polynomial_pow(poly **ret, poly *p, long exp, ring *r) except -1:
294
"""
295
``ret[0] = p**exp`` where ``p`` in ``r`` and ``exp`` > 0.
296
297
The last condition is not checked.
298
299
INPUT:
300
301
- ``ret`` - a pointer to a Singular polynomial to store the result in
302
- ``p`` - a Singular polynomial
303
- ``exp`` - integer
304
- ``r`` - a Singular ring
305
306
EXAMPLE::
307
308
sage: P.<x,y,z> = QQ[]
309
sage: f = 3*x*y + 5/2*z
310
sage: f*f == f^2 # indirect doctest
311
True
312
sage: f^2
313
9*x^2*y^2 + 15*x*y*z + 25/4*z^2
314
sage: f^0
315
1
316
sage: f^(2^60)
317
Traceback (most recent call last):
318
...
319
OverflowError: ...
320
"""
321
cdef unsigned long v = p_GetMaxExp(p, r)
322
v = v * exp
323
324
overflow_check(v, r)
325
326
if(r != currRing): rChangeCurrRing(r)
327
cdef int count = singular_polynomial_length_bounded(p,15)
328
if count >= 15 or exp > 15:
329
sig_on()
330
ret[0] = pPower( p_Copy(p,r), exp)
331
if count >= 15 or exp > 15:
332
sig_off()
333
return 0
334
335
cdef int singular_polynomial_neg(poly **ret, poly *p, ring *r):
336
"""
337
``ret[0] = -p where ``p`` in ``r``.
338
339
The last condition is not checked.
340
341
INPUT:
342
343
- ``ret`` - a pointer to a Singular polynomial to store the result in
344
- ``p`` - a Singular polynomial
345
- ``r`` - a Singular ring
346
347
EXAMPLE::
348
349
sage: P.<x,y,z> = QQ[]
350
sage: f = 3*x*y + 5/2*z
351
sage: -f # indirect doctest
352
-3*x*y - 5/2*z
353
sage: -P(0)
354
0
355
"""
356
if(r != currRing): rChangeCurrRing(r)
357
ret[0] = p_Neg(p_Copy(p,r),r)
358
return 0
359
360
cdef object singular_polynomial_str(poly *p, ring *r):
361
"""
362
Return the string representation of ``p``.
363
364
INPUT:
365
366
- ``p`` - a Singular polynomial
367
- ``r`` - a Singular ring
368
369
EXAMPLE::
370
371
sage: P.<x,y,z> = ZZ[]
372
sage: str(x) # indirect doctest
373
'x'
374
sage: str(10*x)
375
'10*x'
376
"""
377
if(r!=currRing): rChangeCurrRing(r)
378
379
s = p_String(p, r, r)
380
s = re.sub(plusminus_pattern, "\\1 \\2 ", s)
381
return s
382
383
384
cdef object singular_polynomial_latex(poly *p, ring *r, object base, object latex_gens):
385
r"""
386
Return the LaTeX string representation of ``p``.
387
388
INPUT:
389
390
- ``p`` - a Singular polynomial
391
- ``r`` - a Singular ring
392
393
EXAMPLE::
394
395
sage: P.<x,y,z> = QQ[]
396
sage: latex(x) # indirect doctest
397
x
398
sage: latex(10*x^2 + 1/2*y)
399
10 x^{2} + \frac{1}{2} y
400
401
Demonstrate that coefficients over non-atomic representated rings are
402
properly parenthesized (Trac 11186)
403
sage: x = var('x')
404
sage: K.<z> = QQ.extension(x^2 + x + 1)
405
sage: P.<v,w> = K[]
406
sage: latex((z+1)*v*w - z*w^2 + z*v + z^2*w + z + 1)
407
\left(z + 1\right) v w - z w^{2} + z v + \left(-z - 1\right) w + z + 1
408
"""
409
poly = ""
410
cdef long e,j
411
cdef int n = r.N
412
cdef int atomic_repr = base._repr_option('element_is_atomic')
413
while p:
414
415
# First determine the multinomial:
416
multi = ""
417
for j in range(1,n+1):
418
e = p_GetExp(p, j, r)
419
if e > 0:
420
multi += " "+latex_gens[j-1]
421
if e > 1:
422
multi += "^{%d}"%e
423
multi = multi.lstrip().rstrip()
424
425
# Next determine coefficient of multinomial
426
c = si2sa( p_GetCoeff(p, r), r, base)
427
if len(multi) == 0:
428
multi = latex(c)
429
elif c != 1:
430
if c == -1:
431
multi = "- %s"%(multi)
432
else:
433
sc = latex(c)
434
# Add parenthesis if the coefficient consists of terms divided by +, -
435
# (starting with - is not enough) and is not the constant term
436
if not atomic_repr and multi and (sc.find("+") != -1 or sc[1:].find("-") != -1):
437
sc = "\\left(%s\\right)"%sc
438
multi = "%s %s"%(sc,multi)
439
440
# Now add on coefficiented multinomials
441
if len(poly) > 0:
442
poly = poly + " + "
443
poly = poly + multi
444
445
p = pNext(p)
446
447
poly = poly.lstrip().rstrip()
448
poly = poly.replace("+ -","- ")
449
450
if len(poly) == 0:
451
return "0"
452
return poly
453
454
cdef object singular_polynomial_str_with_changed_varnames(poly *p, ring *r, object varnames):
455
cdef char **_names
456
cdef char **_orig_names
457
cdef char *_name
458
cdef int i
459
460
if len(varnames) != r.N:
461
raise TypeError("len(varnames) doesn't equal self.parent().ngens()")
462
463
_names = <char**>omAlloc0(sizeof(char*)*r.N)
464
for i from 0 <= i < r.N:
465
_name = varnames[i]
466
_names[i] = omStrDup(_name)
467
468
_orig_names = r.names
469
r.names = _names
470
s = singular_polynomial_str(p, r)
471
r.names = _orig_names
472
473
for i from 0 <= i < r.N:
474
omFree(_names[i])
475
omFree(_names)
476
return s
477
478
cdef long singular_polynomial_deg(poly *p, poly *x, ring *r):
479
cdef int deg, _deg, i
480
481
deg = 0
482
if p == NULL:
483
return -1
484
if(r != currRing): rChangeCurrRing(r)
485
if x == NULL:
486
return pLDeg(p,&deg,r)
487
488
for i in range(1,r.N+1):
489
if p_GetExp(x, i, r):
490
break
491
while p:
492
_deg = p_GetExp(p,i,r)
493
if _deg > deg:
494
deg = _deg
495
p = pNext(p)
496
return deg
497
498
cdef int singular_polynomial_length_bounded(poly *p, int bound):
499
"""
500
Return the number of monomials in ``p`` but stop counting at
501
``bound``.
502
503
This is useful to estimate whether a certain calculation will take
504
long or not.
505
506
INPUT:
507
508
- ``p`` - a Singular polynomial
509
- ``bound`` - an integer > 0
510
"""
511
cdef int count = 0
512
while p != NULL and count < bound:
513
p = pNext(p)
514
count += 1
515
return count
516
517
cdef int singular_vector_maximal_component(poly *v, ring *r) except -1:
518
"""
519
returns the maximal module component of the vector ``v``.
520
INPUT:
521
522
- ``v`` - a polynomial/vector
523
- ``r`` - a ring
524
"""
525
cdef int res=0
526
while v!=NULL:
527
res=max(p_GetComp(v, r), res)
528
v = pNext(v)
529
return res
530
531