Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Wrapper for Singular's Polynomial Arithmetic
AUTHOR:
- Martin Albrecht (2009-07): refactoring """
#***************************************************************************** # Copyright (C) 2009 Martin Albrecht <malb@informatik.uni-bremen.de> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import absolute_import
from cysignals.signals cimport sig_on, sig_off
cdef extern from *: # hack to get at cython macro int unlikely(int)
import re plusminus_pattern = re.compile("([^\(^])([\+\-])")
from sage.cpython.string cimport bytes_to_str, str_to_bytes
from sage.libs.singular.decl cimport number, ideal from sage.libs.singular.decl cimport currRing, rChangeCurrRing from sage.libs.singular.decl cimport p_Copy, p_Add_q, p_Neg, pp_Mult_nn, p_GetCoeff, p_IsConstant, p_Cmp, pNext from sage.libs.singular.decl cimport p_GetMaxExp, pp_Mult_qq, pPower, p_String, p_GetExp, p_Deg, p_Totaldegree, p_WTotaldegree, p_WDegree from sage.libs.singular.decl cimport n_Delete, idInit, fast_map_common_subexp, id_Delete from sage.libs.singular.decl cimport omAlloc0, omStrDup, omFree from sage.libs.singular.decl cimport p_GetComp, p_SetComp from sage.libs.singular.decl cimport pSubst from sage.libs.singular.decl cimport p_Normalize
from sage.libs.singular.singular cimport sa2si, si2sa, overflow_check
from sage.misc.latex import latex
cdef int singular_polynomial_check(poly *p, ring *r) except -1: """ Run consistency checks on ``p``. """ while p: if p_GetCoeff(p, r) == NULL: raise ZeroDivisionError("NULL pointer as coefficient.") p = p.next return 0
cdef int singular_polynomial_add(poly **ret, poly *p, poly *q, ring *r): """ ``ret[0] = p+q`` where ``p`` and ``p`` in ``r``.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``q`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: x + y # indirect doctest x + y
sage: x + P(0) x """
cdef int singular_polynomial_sub(poly **ret, poly *p, poly *q, ring *r): """ ``ret[0] = p-q`` where ``p`` and ``p`` in ``r``.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``q`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: x - y # indirect doctest x - y
sage: x + P(0) x """
cdef int singular_polynomial_rmul(poly **ret, poly *p, RingElement n, ring *r): """ ``ret[0] = n*p`` where ``n`` is a coefficient and ``p`` in ``r``.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``n`` - a Sage coefficient - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: 2*x # indirect doctest 2*x
sage: P(0)*x 0 """
cdef int singular_polynomial_call(poly **ret, poly *p, ring *r, list args, poly *(*get_element)(object)): """ ``ret[0] = p(*args)`` where each entry in arg is a polynomial and ``p`` in ``r``.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``r`` - a Singular ring - ``args`` - a list/tuple of elements which can be converted to Singular polynomials using the ``(get_element)`` function provided. - ``(*get_element)`` - a function to turn a Sage element into a Singular element.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: x(0,0,0) # indirect doctest 0
sage: (3*x*z)(x,x,x) 3*x^2
TESTS:
Test that there is no memory leak in evaluating polynomials. Note that (lib)Singular has pre-allocated buckets, so we have to run a lot of iterations to fill those up first::
sage: import resource sage: import gc sage: F.<a> = GF(7^2) sage: R.<x,y> = F[] sage: p = x+2*y sage: def leak(N): ....: before = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss ....: gc.collect() ....: for i in range(N): ....: _ = p(a, a) ....: after = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss ....: return (after - before) * 1024 # ru_maxrss is in kilobytes
Loop (at most 30 times) until we have 6 consecutive zeros when calling ``leak(10000)``. Depending on the operating system, it is possible to have several non-zero leak values in the beginning, but after a while we should get only zeros. The fact that we require 6 zeros also means that Singular's pre-allocated buckets should not be sufficient if there really would be a memory leak. ::
sage: zeros = 0 sage: for i in range(30): # long time ....: n = leak(10000) ....: print("Leaked {} bytes".format(n)) ....: if n == 0: ....: zeros += 1 ....: if zeros >= 6: ....: break ....: else: ....: zeros = 0 Leaked... Leaked 0 bytes Leaked 0 bytes Leaked 0 bytes Leaked 0 bytes Leaked 0 bytes """
# Unsure why we have to normalize here. See #16958
cdef int singular_polynomial_cmp(poly *p, poly *q, ring *r): """ Compare two Singular elements ``p`` and ``q`` in ``r``.
INPUT:
- ``p`` - a Singular polynomial - ``q`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(QQ,order='degrevlex') sage: x == x True
sage: x > y True sage: y^2 > x True
sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10) True """ cdef number *h
# handle special cases first (slight slowdown, as special cases # are - well - special # compare 0, 0 # compare 0, const # compare const, 0
# compare coeffs
cdef int singular_polynomial_mul(poly** ret, poly *p, poly *q, ring *r) except -1: """ ``ret[0] = p*q`` where ``p`` and ``p`` in ``r``.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``q`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: x*y # indirect doctest x*y
sage: x * P(0) 0 """
cdef int singular_polynomial_div_coeff(poly** ret, poly *p, poly *q, ring *r) except -1: """ ``ret[0] = p/n`` where ``p`` and ``q`` in ``r`` and ``q`` constant.
The last condition is not checked.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``q`` - a constant Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: x/2 # indirect doctest 1/2*x
sage: x/0 Traceback (most recent call last): ... ZeroDivisionError: rational division by zero """ raise ZeroDivisionError
cdef int singular_polynomial_pow(poly **ret, poly *p, unsigned long exp, ring *r) except -1: """ ``ret[0] = p**exp`` where ``p`` in ``r`` and ``exp`` > 0.
The last condition is not checked.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``exp`` - integer - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = 3*x*y + 5/2*z sage: f*f == f^2 # indirect doctest True sage: f^2 9*x^2*y^2 + 15*x*y*z + 25/4*z^2 sage: f^0 1 sage: f^(2^60) Traceback (most recent call last): ... OverflowError: ... """
cdef int singular_polynomial_neg(poly **ret, poly *p, ring *r): """ ``ret[0] = -p where ``p`` in ``r``.
The last condition is not checked.
INPUT:
- ``ret`` - a pointer to a Singular polynomial to store the result in - ``p`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = 3*x*y + 5/2*z sage: -f # indirect doctest -3*x*y - 5/2*z sage: -P(0) 0 """
cdef object singular_polynomial_str(poly *p, ring *r): """ Return the string representation of ``p``.
INPUT:
- ``p`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = ZZ[] sage: str(x) # indirect doctest 'x' sage: str(10*x) '10*x' """
cdef object singular_polynomial_latex(poly *p, ring *r, object base, object latex_gens): r""" Return the LaTeX string representation of ``p``.
INPUT:
- ``p`` - a Singular polynomial - ``r`` - a Singular ring
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: latex(x) # indirect doctest x sage: latex(10*x^2 + 1/2*y) 10 x^{2} + \frac{1}{2} y
Demonstrate that coefficients over non-atomic representated rings are properly parenthesized (:trac:`11186`)::
sage: x = var('x') sage: K.<z> = QQ.extension(x^2 + x + 1) sage: P.<v,w> = K[] sage: latex((z+1)*v*w - z*w^2 + z*v + z^2*w + z + 1) \left(z + 1\right) v w - z w^{2} + z v + \left(-z - 1\right) w + z + 1 """ cdef unsigned long e
# First determine the multinomial:
# Next determine coefficient of multinomial else: # Add parenthesis if the coefficient consists of terms divided by +, - # (starting with - is not enough) and is not the constant term
# Now add on coefficiented multinomials
return "0"
cdef object singular_polynomial_str_with_changed_varnames(poly *p, ring *r, object varnames): cdef char **_names cdef char **_orig_names cdef int i
raise TypeError("len(varnames) doesn't equal self.parent().ngens()")
cdef long singular_polynomial_deg(poly *p, poly *x, ring *r): cdef long _deg, deg
cdef int singular_polynomial_length_bounded(poly *p, int bound): """ Return the number of monomials in ``p`` but stop counting at ``bound``.
This is useful to estimate whether a certain calculation will take long or not.
INPUT:
- ``p`` - a Singular polynomial - ``bound`` - an integer > 0 """
cdef int singular_vector_maximal_component(poly *v, ring *r) except -1: """ returns the maximal module component of the vector ``v``. INPUT:
- ``v`` - a polynomial/vector - ``r`` - a ring """
cdef int singular_polynomial_subst(poly **p, int var_index, poly *value, ring *r) except -1: """ Substitute variable ``var_index`` with ``value`` in ``p``.
INPUT:
- ``p`` - a polynomial - ``var_index`` - an integer < ngens (zero based indexing) - ``value`` - a polynomial - ``r`` - a ring """
cdef unsigned long exp = p_GetExp(p[0], var_index+1, r) * p_GetMaxExp(value, r)
overflow_check(exp, r) if(r != currRing): rChangeCurrRing(r)
cdef int count = singular_polynomial_length_bounded(p[0], 15) if unlikely(count >= 15 or exp > 15): sig_on() p[0] = pSubst(p[0], var_index+1, value) if unlikely(count >= 15 or exp > 15): sig_off() return 0 |