diff options
| author | Tom Tromey | 2018-07-08 09:22:17 -0600 |
|---|---|---|
| committer | Tom Tromey | 2018-07-12 22:12:28 -0600 |
| commit | 27980e36040d0693fe997de6b6b73c09c3ce1cb5 (patch) | |
| tree | 15e8f67ea21970bad9d4956f105dd41047a20894 /src | |
| parent | cca0e79ea81712786f92a6668c61001e60d24f32 (diff) | |
| download | emacs-27980e36040d0693fe997de6b6b73c09c3ce1cb5.tar.gz emacs-27980e36040d0693fe997de6b6b73c09c3ce1cb5.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/data.c | 37 |
1 files changed, 28 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) | |||
| 3298 | 3298 | ||
| 3299 | Lisp_Object val; | 3299 | Lisp_Object val; |
| 3300 | 3300 | ||
| 3301 | CHECK_FIXNUM (value); | 3301 | CHECK_INTEGER (value); |
| 3302 | CHECK_FIXNUM (count); | 3302 | CHECK_FIXNUM (count); |
| 3303 | 3303 | ||
| 3304 | if (XINT (count) >= EMACS_INT_WIDTH) | 3304 | if (BIGNUMP (value)) |
| 3305 | XSETINT (val, 0); | 3305 | { |
| 3306 | else if (XINT (count) > 0) | 3306 | mpz_t result; |
| 3307 | XSETINT (val, XUINT (value) << XINT (count)); | 3307 | mpz_init (result); |
| 3308 | else if (XINT (count) <= -EMACS_INT_WIDTH) | 3308 | if (XINT (count) >= 0) |
| 3309 | XSETINT (val, lsh ? 0 : XINT (value) < 0 ? -1 : 0); | 3309 | mpz_mul_2exp (result, XBIGNUM (value)->value, XINT (count)); |
| 3310 | else | ||
| 3311 | mpz_tdiv_q_2exp (result, XBIGNUM (value)->value, - XINT (count)); | ||
| 3312 | val = make_number (result); | ||
| 3313 | mpz_clear (result); | ||
| 3314 | } | ||
| 3310 | else | 3315 | else |
| 3311 | XSETINT (val, (lsh ? XUINT (value) >> -XINT (count) | 3316 | { |
| 3312 | : XINT (value) >> -XINT (count))); | 3317 | /* Just do the work as bignums to make the code simpler. */ |
| 3318 | mpz_t result; | ||
| 3319 | eassume (FIXNUMP (value)); | ||
| 3320 | if (lsh) | ||
| 3321 | mpz_init_set_ui (result, XUINT (value)); | ||
| 3322 | else | ||
| 3323 | mpz_init_set_si (result, XINT (value)); | ||
| 3324 | if (XINT (count) >= 0) | ||
| 3325 | mpz_mul_2exp (result, result, XINT (count)); | ||
| 3326 | else | ||
| 3327 | mpz_tdiv_q_2exp (result, result, - XINT (count)); | ||
| 3328 | val = make_number (result); | ||
| 3329 | mpz_clear (result); | ||
| 3330 | } | ||
| 3331 | |||
| 3313 | return val; | 3332 | return val; |
| 3314 | } | 3333 | } |
| 3315 | 3334 | ||