From: Tom Tromey Date: Sun, 8 Jul 2018 15:22:17 +0000 (-0600) Subject: Make ash and lsh handle bignums X-Git-Tag: emacs-27.0.90~4598^2~20 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=27980e36040d0693fe997de6b6b73c09c3ce1cb5;p=emacs.git 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. --- 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