diff options
author | Andy Moreton <andrewjmoreton@gmail.com> | 2018-08-04 10:28:13 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-08-04 10:28:13 -0600 |
commit | bc8ff54efee05f4a2769be32046866ed1e152b41 (patch) | |
tree | c6dac43f3b9abfc6bde54a9d245c04e5dbb360d5 /src/alloc.c | |
parent | 76715f8921dca740880cd22c644a6328cd810846 (diff) | |
download | emacs-bc8ff54efee05f4a2769be32046866ed1e152b41.tar.gz |
Make bignums work better when EMACS_INT is larger than long
* lisp/international/ccl.el (ccl-fixnum): New function.
(ccl-embed-data, ccl-embed-current-address, ccl-dump): Use it.
* src/alloc.c (make_number): Handle case where EMACS_INT is
larger than long.
* src/data.c (bignumcompare): Handle case where EMACS_INT is
larger than long.
(arith_driver): Likewise. Coerce markers.
(float_arith_driver): Coerce markers.
(Flogcount): Use mpz_sgn.
(ash_lsh_impl): Fix bugs.
(Fsub1): Fix underflow check.
* src/lisp.h (NUMBERP): Don't check BIGNUMP.
(CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER): Fix indentation.
* test/lisp/international/ccl-tests.el: New file.
Diffstat (limited to 'src/alloc.c')
-rw-r--r-- | src/alloc.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/alloc.c b/src/alloc.c index 1dc1bbb031a..367bb73fc15 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3815,6 +3815,34 @@ make_number (mpz_t value) } } + /* Check if fixnum can be larger than long. */ + if (sizeof (EMACS_INT) > sizeof (long)) + { + size_t bits = mpz_sizeinbase (value, 2); + int sign = mpz_sgn (value); + + if (bits < FIXNUM_BITS + (sign < 0)) + { + EMACS_INT v = 0; + size_t limbs = mpz_size (value); + mp_size_t i; + + for (i = 0; i < limbs; i++) + { + mp_limb_t limb = mpz_getlimbn (value, i); + v |= (EMACS_INT) ((EMACS_UINT) limb << (i * GMP_NUMB_BITS)); + } + if (sign < 0) + v = -v; + + if (!FIXNUM_OVERFLOW_P (v)) + { + XSETINT (obj, v); + return obj; + } + } + } + obj = allocate_misc (Lisp_Misc_Bignum); b = XBIGNUM (obj); /* We could mpz_init + mpz_swap here, to avoid a copy, but the |