]> git.eshelyaron.com Git - emacs.git/commitdiff
Minor fixups for intmax_t→mpz_t conversion
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 19 Aug 2018 03:40:10 +0000 (20:40 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 19 Aug 2018 03:41:09 +0000 (20:41 -0700)
* src/alloc.c (mpz_set_intmax_slow): Tighten assertion.
Work even in the unlikely case where libgmp uses nails.
* src/data.c (FIXNUMS_FIT_IN_LONG): New constant.
(arith_driver): Use it to tighten compile-time checks.
* src/lisp.h (mpz_set_intmax): Do not assume that converting
an out-of-range value to ‘long’ is harmless, as it might raise
a signal.  Use simpler expression; compiler can optimize.

src/alloc.c
src/data.c
src/lisp.h

index 60850f73d511b8f7cc65f483de8ad8b824ce9c85..ddc0696ba910c7eee56e881f759fa55bc66b6fbf 100644 (file)
@@ -3785,18 +3785,21 @@ make_number (mpz_t value)
 void
 mpz_set_intmax_slow (mpz_t result, intmax_t v)
 {
-  /* If long is larger then a faster path is taken.  */
-  eassert (sizeof (intmax_t) > sizeof (long));
+  /* If V fits in long, a faster path is taken.  */
+  eassert (! (LONG_MIN <= v && v <= LONG_MAX));
 
   bool complement = v < 0;
   if (complement)
     v = -1 - v;
 
-  /* COUNT = 1 means just a single word of the given size.  ORDER = -1
-     is arbitrary since there's only a single word.  ENDIAN = 0 means
-     use the native endian-ness.  NAILS = 0 means use the whole
-     word.  */
-  mpz_import (result, 1, -1, sizeof v, 0, 0, &v);
+  enum { nails = sizeof v * CHAR_BIT - INTMAX_WIDTH };
+# ifndef HAVE_GMP
+  /* mini-gmp requires NAILS to be zero, which is true for all
+     likely Emacs platforms.  Sanity-check this.  */
+  verify (nails == 0);
+# endif
+
+  mpz_import (result, 1, -1, sizeof v, 0, nails, &v);
   if (complement)
     mpz_com (result, result);
 }
index 0754d4c176d78a754d1a5036bfd20e2660d00849..7a8179ed38d5ddd67206fb0f075ba207ebbec738 100644 (file)
@@ -2775,6 +2775,9 @@ enum arithop
     Alogxor
   };
 
+enum { FIXNUMS_FIT_IN_LONG = (LONG_MIN <= MOST_NEGATIVE_FIXNUM
+                             && MOST_POSITIVE_FIXNUM <= LONG_MAX) };
+
 static void
 free_mpz_value (void *value_ptr)
 {
@@ -2829,7 +2832,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
        case Aadd:
          if (BIGNUMP (val))
            mpz_add (accum, accum, XBIGNUM (val)->value);
-         else if (sizeof (EMACS_INT) > sizeof (long))
+         else if (! FIXNUMS_FIT_IN_LONG)
             {
              mpz_t tem;
              mpz_init (tem);
@@ -2854,7 +2857,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
            }
          else if (BIGNUMP (val))
            mpz_sub (accum, accum, XBIGNUM (val)->value);
-         else if (sizeof (EMACS_INT) > sizeof (long))
+         else if (! FIXNUMS_FIT_IN_LONG)
             {
              mpz_t tem;
              mpz_init (tem);
@@ -2870,7 +2873,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
        case Amult:
          if (BIGNUMP (val))
            mpz_mul (accum, accum, XBIGNUM (val)->value);
-         else if (sizeof (EMACS_INT) > sizeof (long))
+         else if (! FIXNUMS_FIT_IN_LONG)
             {
              mpz_t tem;
              mpz_init (tem);
index f2cfe81ca752cf1ed3d3bcf4103500ce92f2762d..fe384d1844bddc46b497a925e7ce59b5a12168fb 100644 (file)
@@ -30,10 +30,11 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <float.h>
 #include <inttypes.h>
 #include <limits.h>
+
 #ifdef HAVE_GMP
-#include <gmp.h>
+# include <gmp.h>
 #else
-#include "mini-gmp.h"
+# include "mini-gmp.h"
 #endif
 
 #include <intprops.h>
@@ -3566,10 +3567,10 @@ mpz_set_intmax (mpz_t result, intmax_t v)
   /* mpz_set_si works in terms of long, but Emacs may use a wider
      integer type, and so sometimes will have to construct the mpz_t
      by hand.  */
-  if (sizeof (intmax_t) > sizeof (long) && (long) v != v)
-    mpz_set_intmax_slow (result, v);
-  else
+  if (LONG_MIN <= v && v <= LONG_MAX)
     mpz_set_si (result, v);
+  else
+    mpz_set_intmax_slow (result, v);
 }
 
 /* Build a frequently used 2/3/4-integer lists.  */