From 4d557f23e4d10a32d1b5aa1d5caf206f625ef892 Mon Sep 17 00:00:00 2001 From: user202729 <25191436+user202729@users.noreply.github.com> Date: Sat, 20 Sep 2025 18:26:44 +0700 Subject: [PATCH] Fix singular Z2m ring creation and polynomial comparison --- src/sage/libs/singular/polynomial.pyx | 7 +++++++ src/sage/libs/singular/ring.pyx | 16 +++++++++++++++- src/sage/libs/singular/singular.pyx | 11 ++++++++--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/sage/libs/singular/polynomial.pyx b/src/sage/libs/singular/polynomial.pyx index bf203f2786b..ca6fe8063b7 100644 --- a/src/sage/libs/singular/polynomial.pyx +++ b/src/sage/libs/singular/polynomial.pyx @@ -284,12 +284,19 @@ cdef int singular_polynomial_cmp(poly *p, poly *q, ring *r) noexcept: sage: P(0) > P(-1) True """ + # similar to p_Compare in p_polys.h cdef int tmp if r != currRing: rChangeCurrRing(r) while True: + # workaround for https://github.com/Singular/Singular/issues/1293 + while p != NULL and r.cf.cfIsZero(p_GetCoeff(p, r), r.cf): + p = pNext(p) + while q != NULL and r.cf.cfIsZero(p_GetCoeff(q, r), r.cf): + q = pNext(q) + if p == NULL: if q == NULL: return 0 diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 841a7349d91..eae7c1a7549 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -252,6 +252,16 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: // block 1 : ordering dp // : names a b // block 2 : ordering C + sage: R(2)^32 == R(0) + True + + The following may use ``n_Z2m`` or ``n_Znm`` depends on ``sizeof(unsigned long)``:: + + sage: R = PolynomialRing(Zmod(2^64), ("a", "b"), implementation="singular") + sage: ZZ(R(3^1000)) == 3^1000 % 2^64 + True + sage: ZZ(R(5^1000)) == 5^1000 % 2^64 + True Integer modulo large power of 2:: @@ -262,6 +272,10 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: // block 1 : ordering dp // : names a b // block 2 : ordering C + sage: ZZ(R(5^1000)) == 5^1000 % 2^1000 + True + sage: R(2)^1000 == R(0) + True Integer modulo large power of odd prime:: @@ -516,7 +530,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: else: modbase, cexponent = ch.perfect_power() - if modbase == 2 and cexponent > 1: + if modbase == 2 and 1 < cexponent <= 8*sizeof(unsigned long): # see :issue:`40855` _cf = nInitChar(n_Z2m, cexponent) elif modbase.is_prime() and cexponent > 1: diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 9fe33068c62..cbe09d1d0a9 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -1542,7 +1542,6 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring) noexcept: cdef number *nn - cdef int64_t _d cdef char *_name cdef char **_ext_names @@ -1552,8 +1551,14 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring) noexcept: return n_Init(int(d), _ring.cf) if _ring.cf.type == n_Z2m: - _d = d - return nr2mMapZp(_d, currRing.cf, _ring.cf) + if sizeof(number *) >= sizeof(unsigned long): + # one may also always choose the second branch, + # but the first branch may allow inlining (?) + # casting to unsigned long is safe because n_Z2m + # is only chosen if the exponent is small, see singular_ring_new + return nr2mMapZp( d, currRing.cf, _ring.cf) + else: + return _ring.cf.cfInit( d, _ring.cf) elif _ring.cf.type == n_Zn or _ring.cf.type == n_Znm: lift = d.lift()