From 7c87d0f381801cd590e67301dc97a09b876bb1e8 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 10 Feb 2023 15:13:11 +0900 Subject: [PATCH 1/3] Add codecov.yml to control codecov report --- .github/workflows/codecov.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/workflows/codecov.yml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 00000000000..69cb76019a4 --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1 @@ +comment: false From 82318995cf84164bdca86fb3b69fae117a2453b9 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Fri, 10 Feb 2023 15:45:19 +0900 Subject: [PATCH 2/3] Relocate and rename codecov.yml --- .github/workflows/codecov.yml => .codecov.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/codecov.yml => .codecov.yml (100%) diff --git a/.github/workflows/codecov.yml b/.codecov.yml similarity index 100% rename from .github/workflows/codecov.yml rename to .codecov.yml From edc50aea32424bf2d63d2353d5086e8fe03ad09a Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 11 Feb 2023 21:00:12 +0900 Subject: [PATCH 3/3] Refactor .subs() for simplicity and efficiency --- .../multi_polynomial_libsingular.pyx | 236 +++++++----------- 1 file changed, 97 insertions(+), 139 deletions(-) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index f3c0bc09542..ee52bcdffbc 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -2076,30 +2076,30 @@ cdef class MPolynomial_libsingular(MPolynomial): raise TypeError("number of arguments does not match number of variables in parent") try: - # Attempt evaluation via singular. coerced_x = [parent.coerce(e) for e in x] except TypeError: - # give up, evaluate functional + # give up, evaluate symbolically y = parent.base_ring().zero() - for (m,c) in self.dict().iteritems(): - y += c*mul([ x[i]**m[i] for i in m.nonzero_positions()]) + for m, c in self.dict().iteritems(): + y += c * mul([x[i]**m[i] for i in m.nonzero_positions()]) return y - cdef poly *res # ownership will be transferred to us in the next line - singular_polynomial_call(&res, self._poly, _ring, coerced_x, MPolynomial_libsingular_get_element) + cdef poly *_res # contains the substituted polynomial + singular_polynomial_call(&_res, self._poly, _ring, coerced_x, MPolynomial_libsingular_get_element) + res_parent = coercion_model.common_parent(parent._base, *x) - if res == NULL: + if _res == NULL: return res_parent(0) - if p_LmIsConstant(res, _ring): - sage_res = si2sa( p_GetCoeff(res, _ring), _ring, parent._base ) - p_Delete(&res, _ring) # sage_res contains copy + if p_LmIsConstant(_res, _ring): + res = si2sa(p_GetCoeff(_res, _ring), _ring, parent._base) + p_Delete(&_res, _ring) # sage to delete; res contains copy else: - sage_res = new_MP(parent, res) # pass on ownership of res to sage_res + res = new_MP(parent, _res) - if parent(sage_res) is not res_parent: - sage_res = res_parent(sage_res) - return sage_res + if parent(res) is not res_parent: + res = res_parent(res) + return res def __hash__(self): """ @@ -3388,8 +3388,7 @@ cdef class MPolynomial_libsingular(MPolynomial): - ``fixed`` - (optional) dict with variable:value pairs - ``**kw`` - names parameters - OUTPUT: - a new multivariate polynomial + OUTPUT: a new multivariate polynomial EXAMPLES:: @@ -3449,7 +3448,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: P = QQ['x,y'] sage: x = var('x') - sage: parent(P.zero() / x) + sage: parent(P.zero().subs(x=x)) Symbolic Ring We are catching overflows:: @@ -3500,163 +3499,122 @@ cdef class MPolynomial_libsingular(MPolynomial): c*x^2*y + d*x^2 + (2*c)*x*y + (2*d)*x + c*y + d """ - cdef int mi, i, need_map, try_symbolic + cdef int mi, i + cdef bint change_ring = False # indicates the need to change the parent ring + cdef bint need_map = False cdef unsigned long degree = 0 cdef MPolynomialRing_libsingular parent = self._parent cdef ring *_ring = parent._ring - if(_ring != currRing): rChangeCurrRing(_ring) + if (_ring != currRing): + rChangeCurrRing(_ring) cdef poly *_p = p_Copy(self._poly, _ring) cdef poly *_f - cdef ideal *to_id = idInit(_ring.N,1) + cdef ideal *to_id = idInit(_ring.N, 1) cdef ideal *from_id cdef ideal *res_id - need_map = 0 - try_symbolic = 0 + cdef dict gd - if _p == NULL: - # the polynomial is 0. There is nothing to do except to change the - # ring - try_symbolic = 1 - - if not try_symbolic and fixed is not None: - for m,v in fixed.items(): - if isinstance(m, (int, Integer)): - mi = m+1 - elif isinstance(m,MPolynomial_libsingular) and m.parent() is parent: - for i from 0 < i <= _ring.N: - if p_GetExp((m)._poly, i, _ring) != 0: - mi = i - break - if i > _ring.N: - id_Delete(&to_id, _ring) - p_Delete(&_p, _ring) - raise TypeError("key does not match") - else: - id_Delete(&to_id, _ring) - p_Delete(&_p, _ring) - raise TypeError("keys do not match self's parent") - try: - v = parent.coerce(v) - except TypeError: - try_symbolic = 1 - break - _f = (v)._poly - if p_IsConstant(_f, _ring): - singular_polynomial_subst(&_p, mi-1, _f, _ring) - else: - need_map = 1 - degree = p_GetExp(_p, mi, _ring) * p_GetMaxExp(_f, _ring) - if degree > _ring.bitmask: + cdef list g = list(parent.gens()) + cdef list items = [] + + if not change_ring: + if fixed is not None: + for m, v in fixed.items(): + if isinstance(m, (int, Integer)): + mi = m + 1 + elif isinstance(m, MPolynomial_libsingular) and m.parent() is parent: + for i from 0 < i <= _ring.N: + if p_GetExp(( m)._poly, i, _ring) != 0: + mi = i + break + if i > _ring.N: + id_Delete(&to_id, _ring) + p_Delete(&_p, _ring) + raise TypeError("key does not match") + else: id_Delete(&to_id, _ring) p_Delete(&_p, _ring) - raise OverflowError("exponent overflow (%d)"%(degree)) - to_id.m[mi-1] = p_Copy(_f, _ring) - + raise TypeError("keys do not match self's parent") + + items.append((g[mi - 1], v)) + if kw: + gd = parent.gens_dict(copy=False) + for m, v in kw.items(): + items.append((gd[m], v)) + for m, v in items: if _p == NULL: - # polynomial becomes 0 after some substitution - try_symbolic = 1 + change_ring = True break - - cdef dict gd - - if not try_symbolic: - gd = parent.gens_dict(copy=False) - for m,v in kw.iteritems(): - m = gd[m] - for i from 0 < i <= _ring.N: - if p_GetExp((m)._poly, i, _ring) != 0: - mi = i - break - if i > _ring.N: - id_Delete(&to_id, _ring) - p_Delete(&_p, _ring) - raise TypeError("key does not match") + i = g.index(m) try: v = parent.coerce(v) - except TypeError: - try_symbolic = 1 - break - _f = (v)._poly + except TypeError: # give up, evaluate symbolically + id_Delete(&to_id, _ring) + p_Delete(&_p, _ring) + + gg = list(parent.gens()) + for m, v in items: + gg[g.index(m)] = v + y = parent.base_ring().zero() + for (m,c) in self.dict().items(): + y += c*mul([ gg[i]**m[i] for i in m.nonzero_positions()]) + return y + _f = ( v)._poly if p_IsConstant(_f, _ring): - singular_polynomial_subst(&_p, mi-1, _f, _ring) + singular_polynomial_subst(&_p, i, _f, _ring) else: - if to_id.m[mi-1] != NULL: - p_Delete(&to_id.m[mi-1],_ring) - to_id.m[mi-1] = p_Copy(_f, _ring) - degree = p_GetExp(_p, mi, _ring) * p_GetMaxExp(_f, _ring) - if degree > _ring.bitmask: + need_map = True + degree = ( p_GetExp(_p, i + 1, _ring)) * ( p_GetMaxExp(_f, _ring)) + if degree > _ring.bitmask: id_Delete(&to_id, _ring) p_Delete(&_p, _ring) - raise OverflowError("exponent overflow (%d)"%(degree)) - need_map = 1 - - if _p == NULL: - # the polynomial is 0 - try_symbolic = 1 - break + raise OverflowError("exponent overflow (%d)" % (degree,)) + to_id.m[i] = p_Copy(_f, _ring) - if need_map: - for mi from 0 <= mi < _ring.N: - if to_id.m[mi] == NULL: - to_id.m[mi] = p_ISet(1,_ring) - p_SetExp(to_id.m[mi], mi+1, 1, _ring) - p_Setm(to_id.m[mi], _ring) + if not change_ring and need_map: + for mi from 0 <= mi < _ring.N: + if to_id.m[mi] == NULL: + to_id.m[mi] = p_ISet(1,_ring) + p_SetExp(to_id.m[mi], mi + 1, 1, _ring) + p_Setm(to_id.m[mi], _ring) - from_id=idInit(1,1) - from_id.m[0] = _p + from_id = idInit(1, 1) + from_id.m[0] = _p - rChangeCurrRing(_ring) - res_id = fast_map_common_subexp(from_id, _ring, to_id, _ring) - _p = res_id.m[0] + rChangeCurrRing(_ring) + res_id = fast_map_common_subexp(from_id, _ring, to_id, _ring) + _p = res_id.m[0] - from_id.m[0] = NULL - res_id.m[0] = NULL + from_id.m[0] = NULL + res_id.m[0] = NULL - id_Delete(&from_id, _ring) - id_Delete(&res_id, _ring) + id_Delete(&from_id, _ring) + id_Delete(&res_id, _ring) id_Delete(&to_id, _ring) - if not try_symbolic: + if not change_ring: return new_MP(parent,_p) - # now as everything else failed, try to do it symbolically with call - - cdef list g = list(parent.gens()) - - if fixed is not None: - for m,v in fixed.items(): - if isinstance(m, (int, Integer)): - mi = m+1 - elif isinstance(m, MPolynomial_libsingular) and m.parent() is parent: - for i from 0 < i <= _ring.N: - if p_GetExp((m)._poly, i, _ring) != 0: - mi = i - break - if i > _ring.N: - raise TypeError("key does not match") - else: - raise TypeError("keys do not match self's parent") + # finally change the parent of the result - g[mi-1] = v + res_parent = coercion_model.common_parent(parent._base, *[v for _, v in items]) - gd = parent.gens_dict(copy=False) - for m,v in kw.iteritems(): - m = gd[m] - for i from 0 < i <= _ring.N: - if p_GetExp((m)._poly, i, _ring) != 0: - mi = i - break - if i > _ring.N: - raise TypeError("key does not match") - - g[mi-1] = v + if _p == NULL: + return res_parent(0) - return self(*g) + if p_LmIsConstant(_p, _ring): + res = si2sa(p_GetCoeff(_p, _ring), _ring, parent._base) + p_Delete(&_p, _ring) # safe to delete; res contains copy + else: + res = new_MP(parent, _p) + if parent(res) is not res_parent: + res = res_parent(res) + return res def monomials(self): """