diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/data.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/src/data.c b/src/data.c index 0980cf99886..c64adb6635e 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2414,14 +2414,14 @@ emacs_mpz_mul (mpz_t rop, mpz_t const op1, mpz_t const op2) | |||
| 2414 | } | 2414 | } |
| 2415 | 2415 | ||
| 2416 | static void | 2416 | static void |
| 2417 | emacs_mpz_mul_2exp (mpz_t rop, mpz_t const op1, mp_bitcnt_t op2) | 2417 | emacs_mpz_mul_2exp (mpz_t rop, mpz_t const op1, EMACS_INT op2) |
| 2418 | { | 2418 | { |
| 2419 | /* Fudge factor derived from GMP 6.1.2, to avoid an abort in | 2419 | /* Fudge factor derived from GMP 6.1.2, to avoid an abort in |
| 2420 | mpz_mul_2exp (look for the '+ 1' in its source code). */ | 2420 | mpz_mul_2exp (look for the '+ 1' in its source code). */ |
| 2421 | enum { mul_2exp_extra_limbs = 1 }; | 2421 | enum { mul_2exp_extra_limbs = 1 }; |
| 2422 | enum { lim = min (NLIMBS_LIMIT, GMP_NLIMBS_MAX - mul_2exp_extra_limbs) }; | 2422 | enum { lim = min (NLIMBS_LIMIT, GMP_NLIMBS_MAX - mul_2exp_extra_limbs) }; |
| 2423 | 2423 | ||
| 2424 | mp_bitcnt_t op2limbs = op2 / GMP_NUMB_BITS; | 2424 | EMACS_INT op2limbs = op2 / GMP_NUMB_BITS; |
| 2425 | if (lim - emacs_mpz_size (op1) < op2limbs) | 2425 | if (lim - emacs_mpz_size (op1) < op2limbs) |
| 2426 | overflow_error (); | 2426 | overflow_error (); |
| 2427 | mpz_mul_2exp (rop, op1, op2); | 2427 | mpz_mul_2exp (rop, op1, op2); |
| @@ -3251,12 +3251,21 @@ If COUNT is negative, shifting is actually to the right. | |||
| 3251 | In this case, the sign bit is duplicated. */) | 3251 | In this case, the sign bit is duplicated. */) |
| 3252 | (Lisp_Object value, Lisp_Object count) | 3252 | (Lisp_Object value, Lisp_Object count) |
| 3253 | { | 3253 | { |
| 3254 | /* The negative of the minimum value of COUNT that fits into a fixnum, | ||
| 3255 | such that mpz_fdiv_q_exp supports -COUNT. */ | ||
| 3256 | EMACS_INT minus_count_min = min (-MOST_NEGATIVE_FIXNUM, | ||
| 3257 | TYPE_MAXIMUM (mp_bitcnt_t)); | ||
| 3258 | CHECK_INTEGER (value); | 3254 | CHECK_INTEGER (value); |
| 3259 | CHECK_RANGED_INTEGER (count, - minus_count_min, TYPE_MAXIMUM (mp_bitcnt_t)); | 3255 | CHECK_INTEGER (count); |
| 3256 | |||
| 3257 | if (! FIXNUMP (count)) | ||
| 3258 | { | ||
| 3259 | if (EQ (value, make_fixnum (0))) | ||
| 3260 | return value; | ||
| 3261 | if (mpz_sgn (XBIGNUM (count)->value) < 0) | ||
| 3262 | { | ||
| 3263 | EMACS_INT v = (FIXNUMP (value) ? XFIXNUM (value) | ||
| 3264 | : mpz_sgn (XBIGNUM (value)->value)); | ||
| 3265 | return make_fixnum (v < 0 ? -1 : 0); | ||
| 3266 | } | ||
| 3267 | overflow_error (); | ||
| 3268 | } | ||
| 3260 | 3269 | ||
| 3261 | if (XFIXNUM (count) <= 0) | 3270 | if (XFIXNUM (count) <= 0) |
| 3262 | { | 3271 | { |
| @@ -3275,7 +3284,11 @@ In this case, the sign bit is duplicated. */) | |||
| 3275 | 3284 | ||
| 3276 | mpz_t *zval = bignum_integer (&mpz[0], value); | 3285 | mpz_t *zval = bignum_integer (&mpz[0], value); |
| 3277 | if (XFIXNUM (count) < 0) | 3286 | if (XFIXNUM (count) < 0) |
| 3278 | mpz_fdiv_q_2exp (mpz[0], *zval, - XFIXNUM (count)); | 3287 | { |
| 3288 | if (TYPE_MAXIMUM (mp_bitcnt_t) < - XFIXNUM (count)) | ||
| 3289 | return make_fixnum (mpz_sgn (*zval) < 0 ? -1 : 0); | ||
| 3290 | mpz_fdiv_q_2exp (mpz[0], *zval, - XFIXNUM (count)); | ||
| 3291 | } | ||
| 3279 | else | 3292 | else |
| 3280 | emacs_mpz_mul_2exp (mpz[0], *zval, XFIXNUM (count)); | 3293 | emacs_mpz_mul_2exp (mpz[0], *zval, XFIXNUM (count)); |
| 3281 | return make_integer_mpz (); | 3294 | return make_integer_mpz (); |