[Gmp-commit] /var/hg/gmp: Fix LONG_MIN / mpz_class(-1)

mercurial at gmplib.org mercurial at gmplib.org
Sun Nov 1 11:24:28 CET 2026


details:   /var/hg/gmp/rev/722f5c638d3a
changeset: 18594:722f5c638d3a
user:      Marc Glisse <marc.glisse at inria.fr>
date:      Sun Nov 01 11:24:25 2026 +0100
description:
Fix LONG_MIN / mpz_class(-1)

diffstat:

 ChangeLog            |   6 ++++++
 gmpxx.h              |  18 ++++++++++++++++--
 tests/cxx/t-ops2z.cc |   2 ++
 3 files changed, 24 insertions(+), 2 deletions(-)

diffs (60 lines):

diff -r 19e57d407ade -r 722f5c638d3a ChangeLog
--- a/ChangeLog	Mon Oct 26 13:09:17 2026 +0100
+++ b/ChangeLog	Sun Nov 01 11:24:25 2026 +0100
@@ -1,3 +1,9 @@
+2026-11-01  Marc Glisse <marc.glisse at inria.fr>
+
+	* gmpxx.h (__gmp_binary_divides, __gmp_binary_modulus): Fix LONG_MIN /
+	mpz_class(-1).
+	* tests/cxx/t-ops2z.cc: Test it.
+
 2026-10-26  Jeff Bailey  <jbailey at raspberryginger.com>
 
 	* gmp-h.in (_GMP_H_HAVE_FILE): Test also _LLVM_LIBC_STDIO_H (for
diff -r 19e57d407ade -r 722f5c638d3a gmpxx.h
--- a/gmpxx.h	Mon Oct 26 13:09:17 2026 +0100
+++ b/gmpxx.h	Sun Nov 01 11:24:25 2026 +0100
@@ -671,7 +671,17 @@
   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
   {
     if (mpz_fits_slong_p(w))
-      mpz_set_si(z, l / mpz_get_si(w));
+      {
+	signed long divisor = mpz_get_si(w);
+	// LONG_MIN / -1 is not representable as a signed long.
+	if (divisor == -1)
+	  {
+	    mpz_set_si(z, l);
+	    mpz_neg(z, z);
+	  }
+	else
+	  mpz_set_si(z, l / divisor);
+      }
     else
       {
         /* if w is bigger than a long then the quotient must be zero, unless
@@ -825,7 +835,11 @@
   static void eval(mpz_ptr z, signed long int l, mpz_srcptr w)
   {
     if (mpz_fits_slong_p(w))
-      mpz_set_si(z, l % mpz_get_si(w));
+      {
+	signed long divisor = mpz_get_si(w);
+	// LONG_MIN % -1 is undefined in C++ even though the result is zero.
+	mpz_set_si(z, divisor == -1 ? 0 : l % divisor);
+      }
     else
       {
         /* if w is bigger than a long then the remainder is l unchanged,
diff -r 19e57d407ade -r 722f5c638d3a tests/cxx/t-ops2z.cc
--- a/tests/cxx/t-ops2z.cc	Mon Oct 26 13:09:17 2026 +0100
+++ b/tests/cxx/t-ops2z.cc	Sun Nov 01 11:24:25 2026 +0100
@@ -36,6 +36,8 @@
   CHECK_ALL_SIGNS(mpz_class,17,2,%);
   CHECK(unsigned long,mpz_class,5,-2,/);
   CHECK(unsigned long,mpz_class,5,-2,%);
+  ASSERT_ALWAYS(LONG_MIN/mpz_class(-1)+LONG_MIN==0);
+  ASSERT_ALWAYS(LONG_MIN%mpz_class(-1)==0);
   ASSERT_ALWAYS(7ul/mpz_class(1e35)==0);
   ASSERT_ALWAYS(7ul%mpz_class(1e35)==7);
   ASSERT_ALWAYS(7ul/mpz_class(-1e35)==0);


More information about the gmp-commit mailing list