Skip to content

Commit 1c436bd

Browse files
committed
Refactor subs method
1 parent 52a81cb commit 1c436bd

File tree

1 file changed

+97
-139
lines changed

1 file changed

+97
-139
lines changed

src/sage/rings/polynomial/multi_polynomial_libsingular.pyx

+97-139
Original file line numberDiff line numberDiff line change
@@ -2077,30 +2077,30 @@ cdef class MPolynomial_libsingular(MPolynomial):
20772077
raise TypeError("number of arguments does not match number of variables in parent")
20782078

20792079
try:
2080-
# Attempt evaluation via singular.
20812080
coerced_x = [parent.coerce(e) for e in x]
20822081
except TypeError:
2083-
# give up, evaluate functional
2082+
# give up, evaluate symbolically
20842083
y = parent.base_ring().zero()
2085-
for (m,c) in self.dict().iteritems():
2086-
y += c*mul([ x[i]**m[i] for i in m.nonzero_positions()])
2084+
for m, c in self.dict().iteritems():
2085+
y += c * mul([x[i]**m[i] for i in m.nonzero_positions()])
20872086
return y
20882087

2089-
cdef poly *res # ownership will be transferred to us in the next line
2090-
singular_polynomial_call(&res, self._poly, _ring, coerced_x, MPolynomial_libsingular_get_element)
2088+
cdef poly *_res # contains the substituted polynomial
2089+
singular_polynomial_call(&_res, self._poly, _ring, coerced_x, MPolynomial_libsingular_get_element)
2090+
20912091
res_parent = coercion_model.common_parent(parent._base, *x)
20922092

2093-
if res == NULL:
2093+
if _res == NULL:
20942094
return res_parent(0)
2095-
if p_LmIsConstant(res, _ring):
2096-
sage_res = si2sa( p_GetCoeff(res, _ring), _ring, parent._base )
2097-
p_Delete(&res, _ring) # sage_res contains copy
2095+
if p_LmIsConstant(_res, _ring):
2096+
res = si2sa(p_GetCoeff(_res, _ring), _ring, parent._base)
2097+
p_Delete(&_res, _ring) # sage to delete; res contains copy
20982098
else:
2099-
sage_res = new_MP(parent, res) # pass on ownership of res to sage_res
2099+
res = new_MP(parent, _res)
21002100

2101-
if parent(sage_res) is not res_parent:
2102-
sage_res = res_parent(sage_res)
2103-
return sage_res
2101+
if parent(res) is not res_parent:
2102+
res = res_parent(res)
2103+
return res
21042104

21052105
def __hash__(self):
21062106
"""
@@ -3391,8 +3391,7 @@ cdef class MPolynomial_libsingular(MPolynomial):
33913391
- ``fixed`` - (optional) dict with variable:value pairs
33923392
- ``**kw`` - names parameters
33933393
3394-
OUTPUT:
3395-
a new multivariate polynomial
3394+
OUTPUT: a new multivariate polynomial
33963395
33973396
EXAMPLES::
33983397
@@ -3452,7 +3451,7 @@ cdef class MPolynomial_libsingular(MPolynomial):
34523451
34533452
sage: P = QQ['x,y']
34543453
sage: x = var('x')
3455-
sage: parent(P.zero() / x)
3454+
sage: parent(P.zero().subs(x=x))
34563455
Symbolic Ring
34573456
34583457
We are catching overflows::
@@ -3503,163 +3502,122 @@ cdef class MPolynomial_libsingular(MPolynomial):
35033502
c*x^2*y + d*x^2 + (2*c)*x*y + (2*d)*x + c*y + d
35043503
35053504
"""
3506-
cdef int mi, i, need_map, try_symbolic
3505+
cdef int mi, i
3506+
cdef bint change_ring = False # indicates the need to change the parent ring
3507+
cdef bint need_map = False
35073508

35083509
cdef unsigned long degree = 0
35093510
cdef MPolynomialRing_libsingular parent = self._parent
35103511
cdef ring *_ring = parent._ring
35113512

3512-
if(_ring != currRing): rChangeCurrRing(_ring)
3513+
if (_ring != currRing):
3514+
rChangeCurrRing(_ring)
35133515

35143516
cdef poly *_p = p_Copy(self._poly, _ring)
35153517
cdef poly *_f
35163518

3517-
cdef ideal *to_id = idInit(_ring.N,1)
3519+
cdef ideal *to_id = idInit(_ring.N, 1)
35183520
cdef ideal *from_id
35193521
cdef ideal *res_id
3520-
need_map = 0
3521-
try_symbolic = 0
3522+
cdef dict gd
35223523

3523-
if _p == NULL:
3524-
# the polynomial is 0. There is nothing to do except to change the
3525-
# ring
3526-
try_symbolic = 1
3527-
3528-
if not try_symbolic and fixed is not None:
3529-
for m,v in fixed.items():
3530-
if isinstance(m, (int, Integer)):
3531-
mi = m+1
3532-
elif isinstance(m,MPolynomial_libsingular) and m.parent() is parent:
3533-
for i from 0 < i <= _ring.N:
3534-
if p_GetExp((<MPolynomial_libsingular>m)._poly, i, _ring) != 0:
3535-
mi = i
3536-
break
3537-
if i > _ring.N:
3538-
id_Delete(&to_id, _ring)
3539-
p_Delete(&_p, _ring)
3540-
raise TypeError("key does not match")
3541-
else:
3542-
id_Delete(&to_id, _ring)
3543-
p_Delete(&_p, _ring)
3544-
raise TypeError("keys do not match self's parent")
3545-
try:
3546-
v = parent.coerce(v)
3547-
except TypeError:
3548-
try_symbolic = 1
3549-
break
3550-
_f = (<MPolynomial_libsingular>v)._poly
3551-
if p_IsConstant(_f, _ring):
3552-
singular_polynomial_subst(&_p, mi-1, _f, _ring)
3553-
else:
3554-
need_map = 1
3555-
degree = <unsigned long>p_GetExp(_p, mi, _ring) * <unsigned long>p_GetMaxExp(_f, _ring)
3556-
if degree > _ring.bitmask:
3524+
cdef list g = list(parent.gens())
3525+
cdef list items = []
3526+
3527+
if not change_ring:
3528+
if fixed is not None:
3529+
for m, v in fixed.items():
3530+
if isinstance(m, (int, Integer)):
3531+
mi = m + 1
3532+
elif isinstance(m, MPolynomial_libsingular) and m.parent() is parent:
3533+
for i from 0 < i <= _ring.N:
3534+
if p_GetExp((<MPolynomial_libsingular> m)._poly, i, _ring) != 0:
3535+
mi = i
3536+
break
3537+
if i > _ring.N:
3538+
id_Delete(&to_id, _ring)
3539+
p_Delete(&_p, _ring)
3540+
raise TypeError("key does not match")
3541+
else:
35573542
id_Delete(&to_id, _ring)
35583543
p_Delete(&_p, _ring)
3559-
raise OverflowError("exponent overflow (%d)"%(degree))
3560-
to_id.m[mi-1] = p_Copy(_f, _ring)
3561-
3544+
raise TypeError("keys do not match self's parent")
3545+
3546+
items.append((g[mi - 1], v))
3547+
if kw:
3548+
gd = parent.gens_dict(copy=False)
3549+
for m, v in kw.items():
3550+
items.append((gd[m], v))
3551+
for m, v in items:
35623552
if _p == NULL:
3563-
# polynomial becomes 0 after some substitution
3564-
try_symbolic = 1
3553+
change_ring = True
35653554
break
3566-
3567-
cdef dict gd
3568-
3569-
if not try_symbolic:
3570-
gd = parent.gens_dict(copy=False)
3571-
for m,v in kw.iteritems():
3572-
m = gd[m]
3573-
for i from 0 < i <= _ring.N:
3574-
if p_GetExp((<MPolynomial_libsingular>m)._poly, i, _ring) != 0:
3575-
mi = i
3576-
break
3577-
if i > _ring.N:
3578-
id_Delete(&to_id, _ring)
3579-
p_Delete(&_p, _ring)
3580-
raise TypeError("key does not match")
3555+
i = g.index(m)
35813556
try:
35823557
v = parent.coerce(v)
3583-
except TypeError:
3584-
try_symbolic = 1
3585-
break
3586-
_f = (<MPolynomial_libsingular>v)._poly
3558+
except TypeError: # give up, evaluate symbolically
3559+
id_Delete(&to_id, _ring)
3560+
p_Delete(&_p, _ring)
3561+
3562+
gg = list(parent.gens())
3563+
for m, v in items:
3564+
gg[g.index(m)] = v
3565+
y = parent.base_ring().zero()
3566+
for (m,c) in self.dict().items():
3567+
y += c*mul([ gg[i]**m[i] for i in m.nonzero_positions()])
3568+
return y
3569+
_f = (<MPolynomial_libsingular> v)._poly
35873570
if p_IsConstant(_f, _ring):
3588-
singular_polynomial_subst(&_p, mi-1, _f, _ring)
3571+
singular_polynomial_subst(&_p, i, _f, _ring)
35893572
else:
3590-
if to_id.m[mi-1] != NULL:
3591-
p_Delete(&to_id.m[mi-1],_ring)
3592-
to_id.m[mi-1] = p_Copy(_f, _ring)
3593-
degree = <unsigned long>p_GetExp(_p, mi, _ring) * <unsigned long>p_GetMaxExp(_f, _ring)
3594-
if degree > _ring.bitmask:
3573+
need_map = True
3574+
degree = (<unsigned long> p_GetExp(_p, i + 1, _ring)) * (<unsigned long> p_GetMaxExp(_f, _ring))
3575+
if degree > _ring.bitmask:
35953576
id_Delete(&to_id, _ring)
35963577
p_Delete(&_p, _ring)
3597-
raise OverflowError("exponent overflow (%d)"%(degree))
3598-
need_map = 1
3599-
3600-
if _p == NULL:
3601-
# the polynomial is 0
3602-
try_symbolic = 1
3603-
break
3578+
raise OverflowError("exponent overflow (%d)" % (degree,))
3579+
to_id.m[i] = p_Copy(_f, _ring)
36043580

3605-
if need_map:
3606-
for mi from 0 <= mi < _ring.N:
3607-
if to_id.m[mi] == NULL:
3608-
to_id.m[mi] = p_ISet(1,_ring)
3609-
p_SetExp(to_id.m[mi], mi+1, 1, _ring)
3610-
p_Setm(to_id.m[mi], _ring)
3581+
if not change_ring and need_map:
3582+
for mi from 0 <= mi < _ring.N:
3583+
if to_id.m[mi] == NULL:
3584+
to_id.m[mi] = p_ISet(1,_ring)
3585+
p_SetExp(to_id.m[mi], mi + 1, 1, _ring)
3586+
p_Setm(to_id.m[mi], _ring)
36113587

3612-
from_id=idInit(1,1)
3613-
from_id.m[0] = _p
3588+
from_id = idInit(1, 1)
3589+
from_id.m[0] = _p
36143590

3615-
rChangeCurrRing(_ring)
3616-
res_id = fast_map_common_subexp(from_id, _ring, to_id, _ring)
3617-
_p = res_id.m[0]
3591+
rChangeCurrRing(_ring)
3592+
res_id = fast_map_common_subexp(from_id, _ring, to_id, _ring)
3593+
_p = res_id.m[0]
36183594

3619-
from_id.m[0] = NULL
3620-
res_id.m[0] = NULL
3595+
from_id.m[0] = NULL
3596+
res_id.m[0] = NULL
36213597

3622-
id_Delete(&from_id, _ring)
3623-
id_Delete(&res_id, _ring)
3598+
id_Delete(&from_id, _ring)
3599+
id_Delete(&res_id, _ring)
36243600

36253601
id_Delete(&to_id, _ring)
36263602

3627-
if not try_symbolic:
3603+
if not change_ring:
36283604
return new_MP(parent,_p)
36293605

3630-
# now as everything else failed, try to do it symbolically with call
3631-
3632-
cdef list g = list(parent.gens())
3633-
3634-
if fixed is not None:
3635-
for m,v in fixed.items():
3636-
if isinstance(m, (int, Integer)):
3637-
mi = m+1
3638-
elif isinstance(m, MPolynomial_libsingular) and m.parent() is parent:
3639-
for i from 0 < i <= _ring.N:
3640-
if p_GetExp((<MPolynomial_libsingular>m)._poly, i, _ring) != 0:
3641-
mi = i
3642-
break
3643-
if i > _ring.N:
3644-
raise TypeError("key does not match")
3645-
else:
3646-
raise TypeError("keys do not match self's parent")
3606+
# finally change the parent of the result
36473607

3648-
g[mi-1] = v
3608+
res_parent = coercion_model.common_parent(parent._base, *[v for _, v in items])
36493609

3650-
gd = parent.gens_dict(copy=False)
3651-
for m,v in kw.iteritems():
3652-
m = gd[m]
3653-
for i from 0 < i <= _ring.N:
3654-
if p_GetExp((<MPolynomial_libsingular>m)._poly, i, _ring) != 0:
3655-
mi = i
3656-
break
3657-
if i > _ring.N:
3658-
raise TypeError("key does not match")
3659-
3660-
g[mi-1] = v
3610+
if _p == NULL:
3611+
return res_parent(0)
36613612

3662-
return self(*g)
3613+
if p_LmIsConstant(_p, _ring):
3614+
res = si2sa(p_GetCoeff(_p, _ring), _ring, parent._base)
3615+
p_Delete(&_p, _ring) # safe to delete; res contains copy
3616+
else:
3617+
res = new_MP(parent, _p)
3618+
if parent(res) is not res_parent:
3619+
res = res_parent(res)
3620+
return res
36633621

36643622
def monomials(self):
36653623
"""

0 commit comments

Comments
 (0)