Path: blob/master/src/sage/libs/singular/polynomial.pyx
8817 views
"""1Wrapper for Singular's Polynomial Arithmetic23AUTHOR:45- Martin Albrecht (2009-07): refactoring6"""7#*****************************************************************************8# Copyright (C) 2009 Martin Albrecht <[email protected]>9#10# Distributed under the terms of the GNU General Public License (GPL)11# http://www.gnu.org/licenses/12#*****************************************************************************13include "sage/ext/interrupt.pxi"1415cdef extern from *: # hack to get at cython macro16int unlikely(int)1718import re19plusminus_pattern = re.compile("([^\(^])([\+\-])")2021from sage.libs.singular.decl cimport number, ideal22from sage.libs.singular.decl cimport currRing, rChangeCurrRing23from sage.libs.singular.decl cimport p_Copy, p_Add_q, p_Neg, pp_Mult_nn, p_GetCoeff, p_IsConstant, p_Cmp, pNext24from sage.libs.singular.decl cimport p_GetMaxExp, pp_Mult_qq, pPower, p_String, p_GetExp, pLDeg25from sage.libs.singular.decl cimport n_Delete, idInit, fast_map, id_Delete26from sage.libs.singular.decl cimport omAlloc0, omStrDup, omFree27from sage.libs.singular.decl cimport p_GetComp, p_SetComp282930from sage.libs.singular.singular cimport sa2si, si2sa, overflow_check3132from sage.misc.latex import latex3334cdef int singular_polynomial_check(poly *p, ring *r) except -1:35"""36Run consistency checks on ``p``.37"""38while p:39if p_GetCoeff(p, r) == NULL:40raise ZeroDivisionError("NULL pointer as coefficient.")41p = p.next42return 04344cdef int singular_polynomial_add(poly **ret, poly *p, poly *q, ring *r):45"""46``ret[0] = p+q`` where ``p`` and ``p`` in ``r``.4748INPUT:4950- ``ret`` - a pointer to a Singular polynomial to store the result in51- ``p`` - a Singular polynomial52- ``q`` - a Singular polynomial53- ``r`` - a Singular ring5455EXAMPLE::5657sage: P.<x,y,z> = QQ[]58sage: x + y # indirect doctest59x + y6061sage: x + P(0)62x63"""64if(r != currRing): rChangeCurrRing(r)65p = p_Copy(p, r)66q = p_Copy(q, r)67ret[0] = p_Add_q(p, q, r)68return 0;6970cdef int singular_polynomial_sub(poly **ret, poly *p, poly *q, ring *r):71"""72``ret[0] = p-q`` where ``p`` and ``p`` in ``r``.7374INPUT:7576- ``ret`` - a pointer to a Singular polynomial to store the result in77- ``p`` - a Singular polynomial78- ``q`` - a Singular polynomial79- ``r`` - a Singular ring8081EXAMPLE::8283sage: P.<x,y,z> = QQ[]84sage: x - y # indirect doctest85x - y8687sage: x + P(0)88x89"""90if(r != currRing): rChangeCurrRing(r)91p = p_Copy(p, r)92q = p_Copy(q, r)93ret[0] = p_Add_q(p, p_Neg(q, r), r)94return 0;9596cdef int singular_polynomial_rmul(poly **ret, poly *p, RingElement n, ring *r):97"""98``ret[0] = n*p`` where ``n`` is a coefficient and ``p`` in ``r``.99100INPUT:101102- ``ret`` - a pointer to a Singular polynomial to store the result in103- ``p`` - a Singular polynomial104- ``n`` - a Sage coefficient105- ``r`` - a Singular ring106107EXAMPLE::108109sage: P.<x,y,z> = QQ[]110sage: 2*x # indirect doctest1112*x112113sage: P(0)*x1140115"""116if(r != currRing): rChangeCurrRing(r)117cdef number *_n = sa2si(n,r)118ret[0] = pp_Mult_nn(p, _n, r)119n_Delete(&_n, r)120return 0121122cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly *(*get_element)(object)):123"""124``ret[0] = p(*args)`` where each entry in arg is a polynomial and ``p`` in ``r``.125126INPUT:127128- ``ret`` - a pointer to a Singular polynomial to store the result in129- ``p`` - a Singular polynomial130- ``r`` - a Singular ring131- ``args`` - a list/tuple of elements which can be converted to132Singular polynomials using the ``(get_element)`` function133provided.134- ``(*get_element)`` - a function to turn a Sage element into a135Singular element.136137EXAMPLE::138139sage: P.<x,y,z> = QQ[]140sage: x(0,0,0) # indirect doctest1410142143sage: (3*x*z)(x,x,x)1443*x^2145"""146cdef long l = len(args)147cdef ideal *to_id = idInit(l,1)148for i from 0 <= i < l:149to_id.m[i]= p_Copy( get_element(args[i]), r)150151cdef ideal *from_id=idInit(1,1)152from_id.m[0] = p153154rChangeCurrRing(r)155cdef ideal *res_id = fast_map(from_id, r, to_id, r)156ret[0] = res_id.m[0]157158from_id.m[0] = NULL159res_id.m[0] = NULL160161id_Delete(&to_id, r)162id_Delete(&from_id, r)163id_Delete(&res_id, r)164165return 0166167cdef int singular_polynomial_cmp(poly *p, poly *q, ring *r):168"""169Compare two Singular elements ``p`` and ``q`` in ``r``.170171INPUT:172173- ``p`` - a Singular polynomial174- ``q`` - a Singular polynomial175- ``r`` - a Singular ring176177EXAMPLES::178179sage: P.<x,y,z> = PolynomialRing(QQ,order='degrevlex')180sage: x == x181True182183sage: x > y184True185sage: y^2 > x186True187188sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10)189True190"""191cdef number *h192cdef int ret = 0193194if(r != currRing): rChangeCurrRing(r)195196# handle special cases first (slight slowdown, as special cases197# are - well - special198if p == NULL:199if q == NULL:200# compare 0, 0201return 0202elif p_IsConstant(q,r):203# compare 0, const204return 1-2*r.cf.nGreaterZero(p_GetCoeff(q,r)) # -1: <, 1: > #205elif q == NULL:206if p_IsConstant(p,r):207# compare const, 0208return -1+2*r.cf.nGreaterZero(p_GetCoeff(p,r)) # -1: <, 1: >209#else210211while ret==0 and p!=NULL and q!=NULL:212ret = p_Cmp( p, q, r)213214if ret==0:215h = r.cf.nSub(p_GetCoeff(p, r),p_GetCoeff(q, r))216# compare coeffs217ret = -1+r.cf.nIsZero(h)+2*r.cf.nGreaterZero(h) # -1: <, 0:==, 1: >218n_Delete(&h, r)219p = pNext(p)220q = pNext(q)221222if ret==0:223if p==NULL and q != NULL:224ret = -1225elif p!=NULL and q==NULL:226ret = 1227228return ret229230cdef int singular_polynomial_mul(poly** ret, poly *p, poly *q, ring *r) except -1:231"""232``ret[0] = p*q`` where ``p`` and ``p`` in ``r``.233234INPUT:235236- ``ret`` - a pointer to a Singular polynomial to store the result in237- ``p`` - a Singular polynomial238- ``q`` - a Singular polynomial239- ``r`` - a Singular ring240241EXAMPLE::242243sage: P.<x,y,z> = QQ[]244sage: x*y # indirect doctest245x*y246247sage: x * P(0)2480249"""250if(r != currRing): rChangeCurrRing(r)251cdef unsigned long le = p_GetMaxExp(p, r)252cdef unsigned long lr = p_GetMaxExp(q, r)253cdef unsigned long esum = le + lr254overflow_check(esum, r)255ret[0] = pp_Mult_qq(p, q, r)256return 0;257258cdef int singular_polynomial_div_coeff(poly** ret, poly *p, poly *q, ring *r) except -1:259"""260``ret[0] = p/n`` where ``p`` and ``q`` in ``r`` and ``q`` constant.261262The last condition is not checked.263264INPUT:265266- ``ret`` - a pointer to a Singular polynomial to store the result in267- ``p`` - a Singular polynomial268- ``q`` - a constant Singular polynomial269- ``r`` - a Singular ring270271EXAMPLE::272273sage: P.<x,y,z> = QQ[]274sage: x/2 # indirect doctest2751/2*x276277sage: x/0278Traceback (most recent call last):279...280ZeroDivisionError: rational division by zero281"""282if q == NULL:283raise ZeroDivisionError284sig_on()285cdef number *n = p_GetCoeff(q, r)286n = r.cf.nInvers(n)287ret[0] = pp_Mult_nn(p, n, r)288n_Delete(&n, r)289sig_off()290return 0291292cdef int singular_polynomial_pow(poly **ret, poly *p, long exp, ring *r) except -1:293"""294``ret[0] = p**exp`` where ``p`` in ``r`` and ``exp`` > 0.295296The last condition is not checked.297298INPUT:299300- ``ret`` - a pointer to a Singular polynomial to store the result in301- ``p`` - a Singular polynomial302- ``exp`` - integer303- ``r`` - a Singular ring304305EXAMPLE::306307sage: P.<x,y,z> = QQ[]308sage: f = 3*x*y + 5/2*z309sage: f*f == f^2 # indirect doctest310True311sage: f^23129*x^2*y^2 + 15*x*y*z + 25/4*z^2313sage: f^03141315sage: f^(2^60)316Traceback (most recent call last):317...318OverflowError: ...319"""320cdef unsigned long v = p_GetMaxExp(p, r)321v = v * exp322323overflow_check(v, r)324325if(r != currRing): rChangeCurrRing(r)326cdef int count = singular_polynomial_length_bounded(p,15)327if count >= 15 or exp > 15:328sig_on()329ret[0] = pPower( p_Copy(p,r), exp)330if count >= 15 or exp > 15:331sig_off()332return 0333334cdef int singular_polynomial_neg(poly **ret, poly *p, ring *r):335"""336``ret[0] = -p where ``p`` in ``r``.337338The last condition is not checked.339340INPUT:341342- ``ret`` - a pointer to a Singular polynomial to store the result in343- ``p`` - a Singular polynomial344- ``r`` - a Singular ring345346EXAMPLE::347348sage: P.<x,y,z> = QQ[]349sage: f = 3*x*y + 5/2*z350sage: -f # indirect doctest351-3*x*y - 5/2*z352sage: -P(0)3530354"""355if(r != currRing): rChangeCurrRing(r)356ret[0] = p_Neg(p_Copy(p,r),r)357return 0358359cdef object singular_polynomial_str(poly *p, ring *r):360"""361Return the string representation of ``p``.362363INPUT:364365- ``p`` - a Singular polynomial366- ``r`` - a Singular ring367368EXAMPLE::369370sage: P.<x,y,z> = ZZ[]371sage: str(x) # indirect doctest372'x'373sage: str(10*x)374'10*x'375"""376if(r!=currRing): rChangeCurrRing(r)377378s = p_String(p, r, r)379s = re.sub(plusminus_pattern, "\\1 \\2 ", s)380return s381382383cdef object singular_polynomial_latex(poly *p, ring *r, object base, object latex_gens):384r"""385Return the LaTeX string representation of ``p``.386387INPUT:388389- ``p`` - a Singular polynomial390- ``r`` - a Singular ring391392EXAMPLE::393394sage: P.<x,y,z> = QQ[]395sage: latex(x) # indirect doctest396x397sage: latex(10*x^2 + 1/2*y)39810 x^{2} + \frac{1}{2} y399400Demonstrate that coefficients over non-atomic representated rings are401properly parenthesized (Trac 11186)402sage: x = var('x')403sage: K.<z> = QQ.extension(x^2 + x + 1)404sage: P.<v,w> = K[]405sage: latex((z+1)*v*w - z*w^2 + z*v + z^2*w + z + 1)406\left(z + 1\right) v w - z w^{2} + z v + \left(-z - 1\right) w + z + 1407"""408poly = ""409cdef long e,j410cdef int n = r.N411cdef int atomic_repr = base._repr_option('element_is_atomic')412while p:413414# First determine the multinomial:415multi = ""416for j in range(1,n+1):417e = p_GetExp(p, j, r)418if e > 0:419multi += " "+latex_gens[j-1]420if e > 1:421multi += "^{%d}"%e422multi = multi.lstrip().rstrip()423424# Next determine coefficient of multinomial425c = si2sa( p_GetCoeff(p, r), r, base)426if len(multi) == 0:427multi = latex(c)428elif c != 1:429if c == -1:430multi = "- %s"%(multi)431else:432sc = latex(c)433# Add parenthesis if the coefficient consists of terms divided by +, -434# (starting with - is not enough) and is not the constant term435if not atomic_repr and multi and (sc.find("+") != -1 or sc[1:].find("-") != -1):436sc = "\\left(%s\\right)"%sc437multi = "%s %s"%(sc,multi)438439# Now add on coefficiented multinomials440if len(poly) > 0:441poly = poly + " + "442poly = poly + multi443444p = pNext(p)445446poly = poly.lstrip().rstrip()447poly = poly.replace("+ -","- ")448449if len(poly) == 0:450return "0"451return poly452453cdef object singular_polynomial_str_with_changed_varnames(poly *p, ring *r, object varnames):454cdef char **_names455cdef char **_orig_names456cdef char *_name457cdef int i458459if len(varnames) != r.N:460raise TypeError("len(varnames) doesn't equal self.parent().ngens()")461462_names = <char**>omAlloc0(sizeof(char*)*r.N)463for i from 0 <= i < r.N:464_name = varnames[i]465_names[i] = omStrDup(_name)466467_orig_names = r.names468r.names = _names469s = singular_polynomial_str(p, r)470r.names = _orig_names471472for i from 0 <= i < r.N:473omFree(_names[i])474omFree(_names)475return s476477cdef long singular_polynomial_deg(poly *p, poly *x, ring *r):478cdef int deg, _deg, i479480deg = 0481if p == NULL:482return -1483if(r != currRing): rChangeCurrRing(r)484if x == NULL:485return pLDeg(p,°,r)486487for i in range(1,r.N+1):488if p_GetExp(x, i, r):489break490while p:491_deg = p_GetExp(p,i,r)492if _deg > deg:493deg = _deg494p = pNext(p)495return deg496497cdef int singular_polynomial_length_bounded(poly *p, int bound):498"""499Return the number of monomials in ``p`` but stop counting at500``bound``.501502This is useful to estimate whether a certain calculation will take503long or not.504505INPUT:506507- ``p`` - a Singular polynomial508- ``bound`` - an integer > 0509"""510cdef int count = 0511while p != NULL and count < bound:512p = pNext(p)513count += 1514return count515516cdef int singular_vector_maximal_component(poly *v, ring *r) except -1:517"""518returns the maximal module component of the vector ``v``.519INPUT:520521- ``v`` - a polynomial/vector522- ``r`` - a ring523"""524cdef int res=0525while v!=NULL:526res=max(p_GetComp(v, r), res)527v = pNext(v)528return res529530531