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.
This commit is contained in:
parent
cca0e79ea8
commit
27980e3604
2 changed files with 34 additions and 9 deletions
37
src/data.c
37
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue