aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2018-08-18 20:40:10 -0700
committerPaul Eggert2018-08-18 20:41:09 -0700
commitb1840206ff22359fc099236602928e0fb3828d66 (patch)
treedc7a23519474955ed4efcbd975c79c0629a96a2b /src
parent6eade1efde873d0b048d8f2841646924cb2ceb16 (diff)
downloademacs-b1840206ff22359fc099236602928e0fb3828d66.tar.gz
emacs-b1840206ff22359fc099236602928e0fb3828d66.zip
Minor fixups for intmax_t→mpz_t conversion
* 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.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c17
-rw-r--r--src/data.c9
-rw-r--r--src/lisp.h11
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)
3785void 3785void
3786mpz_set_intmax_slow (mpz_t result, intmax_t v) 3786mpz_set_intmax_slow (mpz_t result, intmax_t v)
3787{ 3787{
3788 /* If long is larger then a faster path is taken. */ 3788 /* If V fits in long, a faster path is taken. */
3789 eassert (sizeof (intmax_t) > sizeof (long)); 3789 eassert (! (LONG_MIN <= v && v <= LONG_MAX));
3790 3790
3791 bool complement = v < 0; 3791 bool complement = v < 0;
3792 if (complement) 3792 if (complement)
3793 v = -1 - v; 3793 v = -1 - v;
3794 3794
3795 /* COUNT = 1 means just a single word of the given size. ORDER = -1 3795 enum { nails = sizeof v * CHAR_BIT - INTMAX_WIDTH };
3796 is arbitrary since there's only a single word. ENDIAN = 0 means 3796# ifndef HAVE_GMP
3797 use the native endian-ness. NAILS = 0 means use the whole 3797 /* mini-gmp requires NAILS to be zero, which is true for all
3798 word. */ 3798 likely Emacs platforms. Sanity-check this. */
3799 mpz_import (result, 1, -1, sizeof v, 0, 0, &v); 3799 verify (nails == 0);
3800# endif
3801
3802 mpz_import (result, 1, -1, sizeof v, 0, nails, &v);
3800 if (complement) 3803 if (complement)
3801 mpz_com (result, result); 3804 mpz_com (result, result);
3802} 3805}
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
2775 Alogxor 2775 Alogxor
2776 }; 2776 };
2777 2777
2778enum { FIXNUMS_FIT_IN_LONG = (LONG_MIN <= MOST_NEGATIVE_FIXNUM
2779 && MOST_POSITIVE_FIXNUM <= LONG_MAX) };
2780
2778static void 2781static void
2779free_mpz_value (void *value_ptr) 2782free_mpz_value (void *value_ptr)
2780{ 2783{
@@ -2829,7 +2832,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2829 case Aadd: 2832 case Aadd:
2830 if (BIGNUMP (val)) 2833 if (BIGNUMP (val))
2831 mpz_add (accum, accum, XBIGNUM (val)->value); 2834 mpz_add (accum, accum, XBIGNUM (val)->value);
2832 else if (sizeof (EMACS_INT) > sizeof (long)) 2835 else if (! FIXNUMS_FIT_IN_LONG)
2833 { 2836 {
2834 mpz_t tem; 2837 mpz_t tem;
2835 mpz_init (tem); 2838 mpz_init (tem);
@@ -2854,7 +2857,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2854 } 2857 }
2855 else if (BIGNUMP (val)) 2858 else if (BIGNUMP (val))
2856 mpz_sub (accum, accum, XBIGNUM (val)->value); 2859 mpz_sub (accum, accum, XBIGNUM (val)->value);
2857 else if (sizeof (EMACS_INT) > sizeof (long)) 2860 else if (! FIXNUMS_FIT_IN_LONG)
2858 { 2861 {
2859 mpz_t tem; 2862 mpz_t tem;
2860 mpz_init (tem); 2863 mpz_init (tem);
@@ -2870,7 +2873,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2870 case Amult: 2873 case Amult:
2871 if (BIGNUMP (val)) 2874 if (BIGNUMP (val))
2872 mpz_mul (accum, accum, XBIGNUM (val)->value); 2875 mpz_mul (accum, accum, XBIGNUM (val)->value);
2873 else if (sizeof (EMACS_INT) > sizeof (long)) 2876 else if (! FIXNUMS_FIT_IN_LONG)
2874 { 2877 {
2875 mpz_t tem; 2878 mpz_t tem;
2876 mpz_init (tem); 2879 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 <https://www.gnu.org/licenses/>. */
30#include <float.h> 30#include <float.h>
31#include <inttypes.h> 31#include <inttypes.h>
32#include <limits.h> 32#include <limits.h>
33
33#ifdef HAVE_GMP 34#ifdef HAVE_GMP
34#include <gmp.h> 35# include <gmp.h>
35#else 36#else
36#include "mini-gmp.h" 37# include "mini-gmp.h"
37#endif 38#endif
38 39
39#include <intprops.h> 40#include <intprops.h>
@@ -3566,10 +3567,10 @@ mpz_set_intmax (mpz_t result, intmax_t v)
3566 /* mpz_set_si works in terms of long, but Emacs may use a wider 3567 /* mpz_set_si works in terms of long, but Emacs may use a wider
3567 integer type, and so sometimes will have to construct the mpz_t 3568 integer type, and so sometimes will have to construct the mpz_t
3568 by hand. */ 3569 by hand. */
3569 if (sizeof (intmax_t) > sizeof (long) && (long) v != v) 3570 if (LONG_MIN <= v && v <= LONG_MAX)
3570 mpz_set_intmax_slow (result, v);
3571 else
3572 mpz_set_si (result, v); 3571 mpz_set_si (result, v);
3572 else
3573 mpz_set_intmax_slow (result, v);
3573} 3574}
3574 3575
3575/* Build a frequently used 2/3/4-integer lists. */ 3576/* Build a frequently used 2/3/4-integer lists. */