summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
authorAndy Moreton <andrewjmoreton@gmail.com>2018-08-04 10:28:13 -0600
committerTom Tromey <tom@tromey.com>2018-08-04 10:28:13 -0600
commitbc8ff54efee05f4a2769be32046866ed1e152b41 (patch)
treec6dac43f3b9abfc6bde54a9d245c04e5dbb360d5 /src/alloc.c
parent76715f8921dca740880cd22c644a6328cd810846 (diff)
downloademacs-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.c28
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