aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2018-12-18 12:21:27 -0800
committerPaul Eggert2018-12-18 12:23:02 -0800
commitcdaaaf2e1bd1f8ad2784ffc8265aa642da2d1190 (patch)
tree3dbe9cc04690882db9d4fae33a1d69bc32b996a2
parent5a04e8261458d887c7b7d7c259053f236379cf78 (diff)
downloademacs-cdaaaf2e1bd1f8ad2784ffc8265aa642da2d1190.tar.gz
emacs-cdaaaf2e1bd1f8ad2784ffc8265aa642da2d1190.zip
Support (ash INTEGER BIGNUM)
* src/data.c (emacs_mpz_mul_2exp): 2nd arg is now a nonnegative EMACS_INT not mp_bitcnt_t, to simplify checking. (Fash): Support COUNT values that are bignums or that exceed mp_bitcnt_t range. * test/src/data-tests.el (data-tests-ash-lsh): Test this.
-rw-r--r--src/data.c29
-rw-r--r--test/src/data-tests.el4
2 files changed, 25 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
2416static void 2416static void
2417emacs_mpz_mul_2exp (mpz_t rop, mpz_t const op1, mp_bitcnt_t op2) 2417emacs_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.
3251In this case, the sign bit is duplicated. */) 3251In 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 ();
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index d41c7623289..bbf7e2a2394 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -656,6 +656,10 @@ comparing the subr with a much slower lisp implementation."
656(ert-deftest data-tests-ash-lsh () 656(ert-deftest data-tests-ash-lsh ()
657 (should (= (ash most-negative-fixnum 1) 657 (should (= (ash most-negative-fixnum 1)
658 (* most-negative-fixnum 2))) 658 (* most-negative-fixnum 2)))
659 (should (= (ash 0 (* 2 most-positive-fixnum)) 0))
660 (should (= (ash 1000 (* 2 most-negative-fixnum)) 0))
661 (should (= (ash -1000 (* 2 most-negative-fixnum)) -1))
662 (should (= (ash (* 2 most-negative-fixnum) (* 2 most-negative-fixnum)) -1))
659 (should (= (lsh most-negative-fixnum 1) 663 (should (= (lsh most-negative-fixnum 1)
660 (* most-negative-fixnum 2))) 664 (* most-negative-fixnum 2)))
661 (should (= (ash (* 2 most-negative-fixnum) -1) 665 (should (= (ash (* 2 most-negative-fixnum) -1)