aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Tromey2018-07-19 15:58:10 -0600
committerTom Tromey2018-07-19 16:08:41 -0600
commit76715f8921dca740880cd22c644a6328cd810846 (patch)
treed85940e4c452575c453ab3ea6a7d0ec25b20f2ab /src
parent678881e428073b39a906c1ffd01e1b76e271cb5d (diff)
downloademacs-76715f8921dca740880cd22c644a6328cd810846.tar.gz
emacs-76715f8921dca740880cd22c644a6328cd810846.zip
Fix bignum creation when EMACS_INT is wider than long
* src/alloc.c (mpz_set_intmax_slow, mpz_set_uintmax_slow): New functions. * src/data.c (arith_driver, Frem, Fmod, ash_lsh_impl, Fadd1) (Fsub1): Use mpz_set_intmax, mpz_set_uintmax. * src/emacs-module.c (module_make_integer): Use mpz_set_intmax. * src/floatfns.c (Fabs): Use mpz_set_intmax. * src/lisp.h (mpz_set_intmax, mpz_set_uintmax): New inline functions. (mpz_set_uintmax_slow, mpz_set_intmax_slow): Declare.
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c30
-rw-r--r--src/data.c36
-rw-r--r--src/emacs-module.c3
-rw-r--r--src/floatfns.c3
-rw-r--r--src/lisp.h26
5 files changed, 83 insertions, 15 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b775948fd96..1dc1bbb031a 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3824,6 +3824,36 @@ make_number (mpz_t value)
3824 return obj; 3824 return obj;
3825} 3825}
3826 3826
3827void
3828mpz_set_intmax_slow (mpz_t result, intmax_t v)
3829{
3830 /* If long is larger then a faster path is taken. */
3831 eassert (sizeof (intmax_t) > sizeof (long));
3832
3833 bool negate = false;
3834 if (v < 0)
3835 {
3836 v = -v;
3837 negate = true;
3838 }
3839 mpz_set_uintmax_slow (result, (uintmax_t) v);
3840 if (negate)
3841 mpz_neg (result, result);
3842}
3843
3844void
3845mpz_set_uintmax_slow (mpz_t result, uintmax_t v)
3846{
3847 /* If long is larger then a faster path is taken. */
3848 eassert (sizeof (uintmax_t) > sizeof (unsigned long));
3849 /* This restriction could be lifted if needed. */
3850 eassert (sizeof (uintmax_t) <= 2 * sizeof (unsigned long));
3851
3852 mpz_set_ui (result, v >> (CHAR_BIT * sizeof (unsigned long)));
3853 mpz_mul_2exp (result, result, CHAR_BIT * sizeof (unsigned long));
3854 mpz_add_ui (result, result, v & -1ul);
3855}
3856
3827 3857
3828/* Return a newly created vector or string with specified arguments as 3858/* Return a newly created vector or string with specified arguments as
3829 elements. If all the arguments are characters that can fit 3859 elements. If all the arguments are characters that can fit
diff --git a/src/data.c b/src/data.c
index 862381229d7..0deebdca1ae 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2882,7 +2882,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2882 if (BIGNUMP (val)) 2882 if (BIGNUMP (val))
2883 mpz_set (accum, XBIGNUM (val)->value); 2883 mpz_set (accum, XBIGNUM (val)->value);
2884 else 2884 else
2885 mpz_set_si (accum, XINT (val)); 2885 mpz_set_intmax (accum, XINT (val));
2886 if (nargs == 1) 2886 if (nargs == 1)
2887 mpz_neg (accum, accum); 2887 mpz_neg (accum, accum);
2888 } 2888 }
@@ -2905,7 +2905,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2905 if (BIGNUMP (val)) 2905 if (BIGNUMP (val))
2906 mpz_set (accum, XBIGNUM (val)->value); 2906 mpz_set (accum, XBIGNUM (val)->value);
2907 else 2907 else
2908 mpz_set_si (accum, XINT (val)); 2908 mpz_set_intmax (accum, XINT (val));
2909 } 2909 }
2910 else 2910 else
2911 { 2911 {
@@ -2933,7 +2933,8 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2933 else 2933 else
2934 { 2934 {
2935 mpz_t tem; 2935 mpz_t tem;
2936 mpz_init_set_ui (tem, XUINT (val)); 2936 mpz_init (tem);
2937 mpz_set_uintmax (tem, XUINT (val));
2937 mpz_and (accum, accum, tem); 2938 mpz_and (accum, accum, tem);
2938 mpz_clear (tem); 2939 mpz_clear (tem);
2939 } 2940 }
@@ -2944,7 +2945,8 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2944 else 2945 else
2945 { 2946 {
2946 mpz_t tem; 2947 mpz_t tem;
2947 mpz_init_set_ui (tem, XUINT (val)); 2948 mpz_init (tem);
2949 mpz_set_uintmax (tem, XUINT (val));
2948 mpz_ior (accum, accum, tem); 2950 mpz_ior (accum, accum, tem);
2949 mpz_clear (tem); 2951 mpz_clear (tem);
2950 } 2952 }
@@ -2955,7 +2957,8 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args)
2955 else 2957 else
2956 { 2958 {
2957 mpz_t tem; 2959 mpz_t tem;
2958 mpz_init_set_ui (tem, XUINT (val)); 2960 mpz_init (tem);
2961 mpz_set_uintmax (tem, XUINT (val));
2959 mpz_xor (accum, accum, tem); 2962 mpz_xor (accum, accum, tem);
2960 mpz_clear (tem); 2963 mpz_clear (tem);
2961 } 2964 }
@@ -3092,7 +3095,8 @@ Both must be integers or markers. */)
3092 xmp = &XBIGNUM (x)->value; 3095 xmp = &XBIGNUM (x)->value;
3093 else 3096 else
3094 { 3097 {
3095 mpz_init_set_si (xm, XINT (x)); 3098 mpz_init (xm);
3099 mpz_set_intmax (xm, XINT (x));
3096 xmp = &xm; 3100 xmp = &xm;
3097 } 3101 }
3098 3102
@@ -3100,7 +3104,8 @@ Both must be integers or markers. */)
3100 ymp = &XBIGNUM (y)->value; 3104 ymp = &XBIGNUM (y)->value;
3101 else 3105 else
3102 { 3106 {
3103 mpz_init_set_si (ym, XINT (y)); 3107 mpz_init (ym);
3108 mpz_set_intmax (ym, XINT (y));
3104 ymp = &ym; 3109 ymp = &ym;
3105 } 3110 }
3106 3111
@@ -3163,7 +3168,8 @@ Both X and Y must be numbers or markers. */)
3163 xmp = &XBIGNUM (x)->value; 3168 xmp = &XBIGNUM (x)->value;
3164 else 3169 else
3165 { 3170 {
3166 mpz_init_set_si (xm, XINT (x)); 3171 mpz_init (xm);
3172 mpz_set_intmax (xm, XINT (x));
3167 xmp = &xm; 3173 xmp = &xm;
3168 } 3174 }
3169 3175
@@ -3171,7 +3177,8 @@ Both X and Y must be numbers or markers. */)
3171 ymp = &XBIGNUM (y)->value; 3177 ymp = &XBIGNUM (y)->value;
3172 else 3178 else
3173 { 3179 {
3174 mpz_init_set_si (ym, XINT (y)); 3180 mpz_init (ym);
3181 mpz_set_intmax (ym, XINT (y));
3175 ymp = &ym; 3182 ymp = &ym;
3176 } 3183 }
3177 3184
@@ -3317,10 +3324,11 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh)
3317 /* Just do the work as bignums to make the code simpler. */ 3324 /* Just do the work as bignums to make the code simpler. */
3318 mpz_t result; 3325 mpz_t result;
3319 eassume (FIXNUMP (value)); 3326 eassume (FIXNUMP (value));
3327 mpz_init (result);
3320 if (lsh) 3328 if (lsh)
3321 mpz_init_set_ui (result, XUINT (value)); 3329 mpz_set_uintmax (result, XUINT (value));
3322 else 3330 else
3323 mpz_init_set_si (result, XINT (value)); 3331 mpz_set_intmax (result, XINT (value));
3324 if (XINT (count) >= 0) 3332 if (XINT (count) >= 0)
3325 mpz_mul_2exp (result, result, XINT (count)); 3333 mpz_mul_2exp (result, result, XINT (count));
3326 else 3334 else
@@ -3376,7 +3384,8 @@ Markers are converted to integers. */)
3376 else 3384 else
3377 { 3385 {
3378 mpz_t num; 3386 mpz_t num;
3379 mpz_init_set_si (num, XINT (number) + 1); 3387 mpz_init (num);
3388 mpz_set_intmax (num, XINT (number) + 1);
3380 number = make_number (num); 3389 number = make_number (num);
3381 mpz_clear (num); 3390 mpz_clear (num);
3382 } 3391 }
@@ -3410,7 +3419,8 @@ Markers are converted to integers. */)
3410 else 3419 else
3411 { 3420 {
3412 mpz_t num; 3421 mpz_t num;
3413 mpz_init_set_si (num, XINT (number) - 1); 3422 mpz_init (num);
3423 mpz_set_intmax (num, XINT (number) - 1);
3414 number = make_number (num); 3424 number = make_number (num);
3415 mpz_clear (num); 3425 mpz_clear (num);
3416 } 3426 }
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 7709eeca94a..39150f6f67b 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -536,7 +536,8 @@ module_make_integer (emacs_env *env, intmax_t n)
536 if (FIXNUM_OVERFLOW_P (n)) 536 if (FIXNUM_OVERFLOW_P (n))
537 { 537 {
538 mpz_t val; 538 mpz_t val;
539 mpz_init_set_si (val, n); 539 mpz_init (val);
540 mpz_set_intmax (val, n);
540 obj = make_number (val); 541 obj = make_number (val);
541 mpz_clear (val); 542 mpz_clear (val);
542 } 543 }
diff --git a/src/floatfns.c b/src/floatfns.c
index 9a5f0a3ad2f..563c65f827a 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -288,7 +288,8 @@ DEFUN ("abs", Fabs, Sabs, 1, 1, 0,
288 else if (FIXNUMP (arg) && XINT (arg) == MOST_NEGATIVE_FIXNUM) 288 else if (FIXNUMP (arg) && XINT (arg) == MOST_NEGATIVE_FIXNUM)
289 { 289 {
290 mpz_t val; 290 mpz_t val;
291 mpz_init_set_si (val, - MOST_NEGATIVE_FIXNUM); 291 mpz_init (val);
292 mpz_set_intmax (val, - MOST_NEGATIVE_FIXNUM);
292 arg = make_number (val); 293 arg = make_number (val);
293 mpz_clear (val); 294 mpz_clear (val);
294 } 295 }
diff --git a/src/lisp.h b/src/lisp.h
index e046429c1b1..4208634fa95 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3655,6 +3655,32 @@ extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...);
3655 3655
3656extern Lisp_Object make_bignum_str (const char *num, int base); 3656extern Lisp_Object make_bignum_str (const char *num, int base);
3657extern Lisp_Object make_number (mpz_t value); 3657extern Lisp_Object make_number (mpz_t value);
3658extern void mpz_set_intmax_slow (mpz_t result, intmax_t v);
3659extern void mpz_set_uintmax_slow (mpz_t result, uintmax_t v);
3660
3661INLINE void
3662mpz_set_intmax (mpz_t result, intmax_t v)
3663{
3664 /* mpz_set_si works in terms of long, but Emacs may use a wider
3665 integer type, and so sometimes will have to construct the mpz_t
3666 by hand. */
3667 if (sizeof (intmax_t) > sizeof (long) && (long) v != v)
3668 mpz_set_intmax_slow (result, v);
3669 else
3670 mpz_set_si (result, v);
3671}
3672
3673INLINE void
3674mpz_set_uintmax (mpz_t result, uintmax_t v)
3675{
3676 /* mpz_set_ui works in terms of unsigned long, but Emacs may use a
3677 wider integer type, and so sometimes will have to construct the
3678 mpz_t by hand. */
3679 if (sizeof (uintmax_t) > sizeof (unsigned long) && (unsigned long) v != v)
3680 mpz_set_uintmax_slow (result, v);
3681 else
3682 mpz_set_ui (result, v);
3683}
3658 3684
3659/* Build a frequently used 2/3/4-integer lists. */ 3685/* Build a frequently used 2/3/4-integer lists. */
3660 3686