From 27980e36040d0693fe997de6b6b73c09c3ce1cb5 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sun, 8 Jul 2018 09:22:17 -0600 Subject: [PATCH] Make ash and lsh handle bignums * src/data.c (ash_lsh_impl): Handle bignums. * test/src/data-tests.el (data-tests-ash-lsh): New test. --- src/data.c | 37 ++++++++++++++++++++++++++++--------- test/src/data-tests.el | 6 ++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/data.c b/src/data.c index ac74ff5547f..8a2d600b30d 100644 --- a/src/data.c +++ b/src/data.c @@ -3298,18 +3298,37 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh) Lisp_Object val; - CHECK_FIXNUM (value); + CHECK_INTEGER (value); CHECK_FIXNUM (count); - if (XINT (count) >= EMACS_INT_WIDTH) - XSETINT (val, 0); - else if (XINT (count) > 0) - XSETINT (val, XUINT (value) << XINT (count)); - else if (XINT (count) <= -EMACS_INT_WIDTH) - XSETINT (val, lsh ? 0 : XINT (value) < 0 ? -1 : 0); + if (BIGNUMP (value)) + { + mpz_t result; + mpz_init (result); + if (XINT (count) >= 0) + mpz_mul_2exp (result, XBIGNUM (value)->value, XINT (count)); + else + mpz_tdiv_q_2exp (result, XBIGNUM (value)->value, - XINT (count)); + val = make_number (result); + mpz_clear (result); + } else - XSETINT (val, (lsh ? XUINT (value) >> -XINT (count) - : XINT (value) >> -XINT (count))); + { + /* Just do the work as bignums to make the code simpler. */ + mpz_t result; + eassume (FIXNUMP (value)); + if (lsh) + mpz_init_set_ui (result, XUINT (value)); + else + mpz_init_set_si (result, XINT (value)); + if (XINT (count) >= 0) + mpz_mul_2exp (result, result, XINT (count)); + else + mpz_tdiv_q_2exp (result, result, - XINT (count)); + val = make_number (result); + mpz_clear (result); + } + return val; } diff --git a/test/src/data-tests.el b/test/src/data-tests.el index 2423d7a7098..07159df48cf 100644 --- a/test/src/data-tests.el +++ b/test/src/data-tests.el @@ -614,4 +614,10 @@ comparing the subr with a much slower lisp implementation." (data-tests-check-sign (% -1 -3) (% nb1 nb3)) (data-tests-check-sign (mod -1 -3) (mod nb1 nb3)))) +(ert-deftest data-tests-ash-lsh () + (should (= (ash most-negative-fixnum 1) + (* most-negative-fixnum 2))) + (should (= (lsh most-negative-fixnum 1) + (* (abs most-negative-fixnum) 2)))) + ;;; data-tests.el ends here -- 2.39.2