Skip to content

Commit 885a5fd

Browse files
author
Release Manager
committed
sagemathgh-40855: Fix singular Z2m ring creation and polynomial comparison See the new test, previously it fails. The `n_Z2m` ring creation is caused by sagemath#39075. Singular source code contains ``` // is exponent <=2^(8*sizeof(unsigned long)) mp_bitcnt_t l=mpz_scan1 (modBase,0); if ((l>0) && (l<=8*sizeof(unsigned long))) { ``` so the limit is taken from there. The polynomial comparison fix is workaround for Singular/Singular#1293. sagemath#39018 touches this part of the code, although I think it doesn't introduce the bug. Fix sagemath#40838 ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40855 Reported by: user202729 Reviewer(s): Travis Scrimshaw
2 parents 57090ea + 4d557f2 commit 885a5fd

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

src/sage/libs/singular/polynomial.pyx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,12 +284,19 @@ cdef int singular_polynomial_cmp(poly *p, poly *q, ring *r) noexcept:
284284
sage: P(0) > P(-1)
285285
True
286286
"""
287+
# similar to p_Compare in p_polys.h
287288
cdef int tmp
288289

289290
if r != currRing:
290291
rChangeCurrRing(r)
291292

292293
while True:
294+
# workaround for https://github.com/Singular/Singular/issues/1293
295+
while p != NULL and r.cf.cfIsZero(p_GetCoeff(p, r), r.cf):
296+
p = pNext(p)
297+
while q != NULL and r.cf.cfIsZero(p_GetCoeff(q, r), r.cf):
298+
q = pNext(q)
299+
293300
if p == NULL:
294301
if q == NULL:
295302
return 0

src/sage/libs/singular/ring.pyx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,16 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL:
252252
// block 1 : ordering dp
253253
// : names a b
254254
// block 2 : ordering C
255+
sage: R(2)^32 == R(0)
256+
True
257+
258+
The following may use ``n_Z2m`` or ``n_Znm`` depends on ``sizeof(unsigned long)``::
259+
260+
sage: R = PolynomialRing(Zmod(2^64), ("a", "b"), implementation="singular")
261+
sage: ZZ(R(3^1000)) == 3^1000 % 2^64
262+
True
263+
sage: ZZ(R(5^1000)) == 5^1000 % 2^64
264+
True
255265
256266
Integer modulo large power of 2::
257267
@@ -262,6 +272,10 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL:
262272
// block 1 : ordering dp
263273
// : names a b
264274
// block 2 : ordering C
275+
sage: ZZ(R(5^1000)) == 5^1000 % 2^1000
276+
True
277+
sage: R(2)^1000 == R(0)
278+
True
265279
266280
Integer modulo large power of odd prime::
267281
@@ -516,7 +530,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL:
516530
else:
517531
modbase, cexponent = ch.perfect_power()
518532

519-
if modbase == 2 and cexponent > 1:
533+
if modbase == 2 and 1 < cexponent <= 8*sizeof(unsigned long): # see :issue:`40855`
520534
_cf = nInitChar(n_Z2m, <void *>cexponent)
521535

522536
elif modbase.is_prime() and cexponent > 1:

src/sage/libs/singular/singular.pyx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,7 +1542,6 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring) noexcept:
15421542

15431543
cdef number *nn
15441544

1545-
cdef int64_t _d
15461545
cdef char *_name
15471546
cdef char **_ext_names
15481547

@@ -1552,8 +1551,14 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring) noexcept:
15521551
return n_Init(int(d), _ring.cf)
15531552

15541553
if _ring.cf.type == n_Z2m:
1555-
_d = d
1556-
return nr2mMapZp(<number *>_d, currRing.cf, _ring.cf)
1554+
if sizeof(number *) >= sizeof(unsigned long):
1555+
# one may also always choose the second branch,
1556+
# but the first branch may allow inlining (?)
1557+
# casting to unsigned long is safe because n_Z2m
1558+
# is only chosen if the exponent is small, see singular_ring_new
1559+
return nr2mMapZp(<number *> <unsigned long> d, currRing.cf, _ring.cf)
1560+
else:
1561+
return _ring.cf.cfInit(<long> <unsigned long> d, _ring.cf)
15571562
elif _ring.cf.type == n_Zn or _ring.cf.type == n_Znm:
15581563
lift = d.lift()
15591564

0 commit comments

Comments
 (0)