From b1840206ff22359fc099236602928e0fb3828d66 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 18 Aug 2018 20:40:10 -0700 Subject: [PATCH] =?utf8?q?Minor=20fixups=20for=20intmax=5Ft=E2=86=92mpz=5F?= =?utf8?q?t=20conversion?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * 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 | 17 ++++++++++------- src/data.c | 9 ++++++--- src/lisp.h | 11 ++++++----- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 60850f73d51..ddc0696ba91 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -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); } diff --git a/src/data.c b/src/data.c index 0754d4c176d..7a8179ed38d 100644 --- a/src/data.c +++ b/src/data.c @@ -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); diff --git a/src/lisp.h b/src/lisp.h index f2cfe81ca75..fe384d1844b 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -30,10 +30,11 @@ along with GNU Emacs. If not, see . */ #include #include #include + #ifdef HAVE_GMP -#include +# include #else -#include "mini-gmp.h" +# include "mini-gmp.h" #endif #include @@ -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. */ -- 2.39.2