Skip to content

Commit

Permalink
gh-37492: make sagelib work with singular>=4.3.2.p15 (future 4.4)
Browse files Browse the repository at this point in the history
    
Two major breaking changes:

- The `rp` ordering is renamed to `ip`
- `hilb` now returns a `bigintvec` object (which isn't even exposed in
the C++ API, seems to be an instance of `bigintmat`)

This branch builds and works fine with 4.3.2.p15, but I have no idea how
to make it work with both old and new singular, suggestions welcome.
    
URL: #37492
Reported by: Antonio Rojas
Reviewer(s): Antonio Rojas, Gonzalo Tornaría, Matthias Köppe
  • Loading branch information
Release Manager committed May 1, 2024
2 parents 2d77ac5 + d999b20 commit 721fc79
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 18 deletions.
19 changes: 17 additions & 2 deletions src/sage/interfaces/singular.py
Original file line number Diff line number Diff line change
Expand Up @@ -1211,14 +1211,14 @@ def current_ring(self):
polynomial ring, over a field, global ordering
// coefficients: ZZ/127
// number of vars : 3
// block 1 : ordering rp
// block 1 : ordering ip
// : names x y z
// block 2 : ordering C
sage: singular.current_ring()
polynomial ring, over a field, global ordering
// coefficients: ZZ/127
// number of vars : 3
// block 1 : ordering rp
// block 1 : ordering ip
// : names x y z
// block 2 : ordering C
"""
Expand Down Expand Up @@ -1402,6 +1402,14 @@ def _repr_(self):
if self._name in s:
if self.get_custom_name() is None and self.type() == 'matrix':
s = self.parent().eval('pmat(%s,20)' % (self.name()))
# compatibility for singular 4.3.2p10 and before
if s.startswith("polynomial ring,"):
from sage.rings.polynomial.term_order import singular_name_mapping
from sage.repl.rich_output import get_display_manager
# this is our cue that singular uses `rp` instead of `ip`
if singular_name_mapping['invlex'] == 'rp' and 'doctest' in str(get_display_manager()):
s = re.sub('^(// .*block.* : ordering )rp$', '\\1ip',
s, 0, re.MULTILINE);
return s

def __copy__(self):
Expand Down Expand Up @@ -2025,6 +2033,10 @@ def _sage_(self, R=None):
sage: type(singular(int(5)).sage())
<class 'sage.rings.integer.Integer'>
Test that bigintvec can be coerced::
sage: singular('hilb((ideal(x)), 1)').sage()
(1, -1, 0, 0, -1, 1, 0)
"""
typ = self.type()
if typ == 'poly':
Expand All @@ -2040,6 +2052,9 @@ def _sage_(self, R=None):
elif typ == 'intvec':
from sage.modules.free_module_element import vector
return vector([sage.rings.integer.Integer(str(e)) for e in self])
elif typ == 'bigintvec':
from sage.modules.free_module_element import vector
return vector([sage.rings.rational.Rational(str(e)) for e in self])
elif typ == 'intmat':
from sage.matrix.constructor import matrix
from sage.rings.integer_ring import ZZ
Expand Down
14 changes: 13 additions & 1 deletion src/sage/libs/singular/decl.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ cdef extern from "factory/factory.h":
cdef int SW_USE_NTL_SORT

cdef extern from "singular/Singular/libsingular.h":
"""
// compatibility for singular 4.3.2p10 and before
#if SINGULAR_VERSION <= 4330
#define ringorder_ip ringorder_rp
#define BIGINTVEC_CMD INTVEC_CMD
#endif
"""

#
# OPTIONS
Expand Down Expand Up @@ -243,7 +250,7 @@ cdef extern from "singular/Singular/libsingular.h":
ringorder_s
ringorder_lp
ringorder_dp
ringorder_rp
ringorder_ip
ringorder_Dp
ringorder_wp
ringorder_Wp
Expand Down Expand Up @@ -291,6 +298,10 @@ cdef extern from "singular/Singular/libsingular.h":
int row
int col

cdef cppclass bigintmat:
int (*length)()
number* (*get)(int i)

# omalloc bins

ctypedef struct omBin "omBin_s"
Expand Down Expand Up @@ -921,6 +932,7 @@ cdef extern from "singular/Singular/libsingular.h":
cdef int MATRIX_CMD
cdef int LIST_CMD
cdef int INTVEC_CMD
cdef int BIGINTVEC_CMD
cdef int NONE
cdef int RESOLUTION_CMD
cdef int PACKAGE_CMD
Expand Down
28 changes: 21 additions & 7 deletions src/sage/libs/singular/function.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence_g
from sage.libs.singular.decl cimport *
from sage.libs.singular.option import opt_ctx
from sage.libs.singular.polynomial cimport singular_vector_maximal_component
from sage.libs.singular.singular cimport sa2si, si2sa, si2sa_intvec
from sage.libs.singular.singular cimport sa2si, si2sa, si2sa_intvec, si2sa_bigintvec
from sage.libs.singular.singular import error_messages

from sage.interfaces.singular import get_docstring
Expand Down Expand Up @@ -954,6 +954,8 @@ cdef class Converter(SageObject):
return si2sa(<number *>to_convert.data, self._singular_ring, self._sage_ring.base_ring())
elif rtyp == INTVEC_CMD:
return si2sa_intvec(<intvec *> to_convert.data)
elif rtyp == BIGINTVEC_CMD:
return si2sa_bigintvec(<bigintmat *> to_convert.data)
elif rtyp == STRING_CMD:
# TODO: Need to determine what kind of data can be returned by a
# STRING_CMD--is it just ASCII strings or can it be an arbitrary
Expand Down Expand Up @@ -1048,6 +1050,17 @@ cdef class LibraryCallHandler(BaseCallHandler):
"""
return False

# mapping int --> string for function arity
arity_dict = {
CMD_1: "CMD_1",
CMD_2: "CMD_2",
CMD_3: "CMD_3",
CMD_12: "CMD_12",
CMD_13: "CMD_13",
CMD_23: "CMD_23",
CMD_123: "CMD_123",
CMD_M: "CMD_M"
}

cdef class KernelCallHandler(BaseCallHandler):
"""
Expand Down Expand Up @@ -1125,8 +1138,9 @@ cdef class KernelCallHandler(BaseCallHandler):

errorreported += 1
error_messages.append(
"Wrong number of arguments (got {} arguments, arity code is {})"
.format(number_of_arguments, self.arity))
"Wrong number of arguments (got {} arguments, arity is {})"
.format(number_of_arguments,
arity_dict.get(self.arity) or self.arity))
return NULL

cdef bint free_res(self) noexcept:
Expand Down Expand Up @@ -1231,7 +1245,7 @@ cdef class SingularFunction(SageObject):
Traceback (most recent call last):
...
RuntimeError: error in Singular function call 'size':
Wrong number of arguments (got 2 arguments, arity code is 302)
Wrong number of arguments (got 2 arguments, arity is CMD_1)
sage: size('foobar', ring=P)
6
Expand Down Expand Up @@ -1634,17 +1648,17 @@ def singular_function(name):
Traceback (most recent call last):
...
RuntimeError: error in Singular function call 'factorize':
Wrong number of arguments (got 0 arguments, arity code is 305)
Wrong number of arguments (got 0 arguments, arity is CMD_12)
sage: factorize(f, 1, 2)
Traceback (most recent call last):
...
RuntimeError: error in Singular function call 'factorize':
Wrong number of arguments (got 3 arguments, arity code is 305)
Wrong number of arguments (got 3 arguments, arity is CMD_12)
sage: factorize(f, 1, 2, 3)
Traceback (most recent call last):
...
RuntimeError: error in Singular function call 'factorize':
Wrong number of arguments (got 4 arguments, arity code is 305)
Wrong number of arguments (got 4 arguments, arity is CMD_12)
The Singular function ``list`` can be called with any number of
arguments::
Expand Down
16 changes: 13 additions & 3 deletions src/sage/libs/singular/ring.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ AUTHORS:
# https://www.gnu.org/licenses/
# ****************************************************************************

from sage.cpython.string cimport str_to_bytes
from sage.cpython.string cimport str_to_bytes, bytes_to_str

from sage.libs.gmp.types cimport __mpz_struct
from sage.libs.gmp.mpz cimport mpz_init_set_ui

from sage.libs.singular.decl cimport ring, currRing
from sage.libs.singular.decl cimport rChangeCurrRing, rComplete, rDelete, idInit
from sage.libs.singular.decl cimport omAlloc0, omStrDup, omAlloc
from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_rp, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_c, ringorder_C, ringorder_wp, ringorder_Wp, ringorder_ws, ringorder_Ws, ringorder_a, rRingOrder_t
from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, ringorder_ip, ringorder_ds, ringorder_Ds, ringorder_ls, ringorder_M, ringorder_c, ringorder_C, ringorder_wp, ringorder_Wp, ringorder_ws, ringorder_Ws, ringorder_a, rRingOrder_t
from sage.libs.singular.decl cimport prCopyR
from sage.libs.singular.decl cimport n_unknown, n_algExt, n_transExt, n_Z, n_Zn, n_Znm, n_Z2m
from sage.libs.singular.decl cimport n_coeffType
Expand Down Expand Up @@ -60,7 +60,7 @@ order_dict = {
"dp": ringorder_dp,
"Dp": ringorder_Dp,
"lp": ringorder_lp,
"rp": ringorder_rp,
"ip": ringorder_ip,
"ds": ringorder_ds,
"Ds": ringorder_Ds,
"ls": ringorder_ls,
Expand All @@ -71,6 +71,16 @@ order_dict = {
"a": ringorder_a,
}

cdef extern from "singular/Singular/libsingular.h":
cdef char * rSimpleOrdStr(rRingOrder_t)

if bytes_to_str(rSimpleOrdStr(ringorder_ip)) == "rp":
# compatibility for singular 4.3.2p10 and before
order_dict["rp"] = ringorder_ip
# also patch term_order mappings
from sage.rings.polynomial import term_order
term_order.singular_name_mapping['invlex'] = 'rp'
term_order.inv_singular_name_mapping['rp'] = 'invlex'

#############################################################################
cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL:
Expand Down
3 changes: 2 additions & 1 deletion src/sage/libs/singular/singular.pxd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from sage.libs.singular.decl cimport ring, poly, number, intvec
from sage.libs.singular.decl cimport ring, poly, number, intvec, bigintmat
from sage.libs.singular.function cimport Resolution

from sage.rings.rational cimport Rational
Expand Down Expand Up @@ -29,6 +29,7 @@ cdef object si2sa_ZZmod(number *n, ring *_ring, object base)
cdef object si2sa_NF(number *n, ring *_ring, object base)

cdef object si2sa_intvec(intvec *v)
cdef object si2sa_bigintvec(bigintmat *v)

# dispatches to all the above.
cdef object si2sa(number *n, ring *_ring, object base)
Expand Down
19 changes: 19 additions & 0 deletions src/sage/libs/singular/singular.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,25 @@ cdef object si2sa_intvec(intvec *v):
l.append(v.get(r))
return tuple(l)

cdef object si2sa_bigintvec(bigintmat *v):
r"""
create a sage tuple from a singular vector of big integers
INPUT:
- ``v`` -- a (pointer to) singular bigintmat
OUTPUT:
a sage tuple
"""
cdef int r
cdef list l = list()
for r in range(v.length()):
n = v.get(r)
l.append(si2sa_QQ(n, &n, currRing))
return tuple(l)

# ==============
# Initialisation
# ==============
Expand Down
6 changes: 3 additions & 3 deletions src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base):
polynomial ring, over a field, global ordering
// coefficients: ZZ/2[a]/(a^8+a^4+a^3+a^2+1)
// number of vars : 10
// block 1 : ordering rp
// block 1 : ordering ip
// : names x0 x1 x2 x3 x4 x5 x6 x7 x8 x9
// block 2 : ordering C
Expand All @@ -1294,7 +1294,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base):
polynomial ring, over a field, global ordering
// coefficients: ZZ/127
// number of vars : 2
// block 1 : ordering rp
// block 1 : ordering ip
// : names x0 x1
// block 2 : ordering C
Expand All @@ -1303,7 +1303,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base):
polynomial ring, over a field, global ordering
// coefficients: QQ
// number of vars : 2
// block 1 : ordering rp
// block 1 : ordering ip
// : names x0 x1
// block 2 : ordering C
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/polynomial/term_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@

singular_name_mapping = {
'lex' : 'lp',
'invlex' : 'rp',
'invlex' : 'ip',
'degrevlex' : 'dp',
'deglex' : 'Dp',
'neglex' : 'ls',
Expand Down

0 comments on commit 721fc79

Please sign in to comment.