summaryrefslogtreecommitdiff
path: root/src/floatfns.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2018-08-21 02:16:50 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2018-08-21 02:38:53 -0700
commitd6a497dd887cdbb35c5b4e2929e83962ba708159 (patch)
tree9f0441f9fe88419b71e568b05ef7f7bea0a0ff06 /src/floatfns.c
parent77fc2725985b4e5ef977ae6930835c7f0771c61c (diff)
downloademacs-d6a497dd887cdbb35c5b4e2929e83962ba708159.tar.gz
Avoid libgmp aborts by imposing limits
libgmp calls ‘abort’ when given numbers too big for its internal data structures. The numeric limit is large and platform-dependent; with 64-bit GMP 6.1.2 it is around 2**2**37. Work around the problem by refusing to call libgmp functions with arguments that would cause an abort. With luck libgmp will have a better way to do this in the future. Also, introduce a variable integer-width that lets the user control how large bignums can be. This currently defaults to 2**16, i.e., it allows bignums up to 2**2**16. This should be enough for ordinary computation, and should help Emacs to avoid thrashing or hanging. Problem noted by Pip Cet (Bug#32463#71). * doc/lispref/numbers.texi, etc/NEWS: Document recent bignum changes, including this one. Improve documentation for bitwise operations, in the light of bignums. * src/alloc.c (make_number): Enforce integer-width. (integer_overflow): New function. (xrealloc_for_gmp, xfree_for_gmp): Move here from emacs.c, as it's memory allocation. (init_alloc): Initialize GMP here, rather than in emacs.c. (integer_width): New var. * src/data.c (GMP_NLIMBS_MAX, NLIMBS_LIMIT): New constants. (emacs_mpz_size, emacs_mpz_mul) (emacs_mpz_mul_2exp, emacs_mpz_pow_ui): New functions. (arith_driver, Fash, expt_integer): Use them. (expt_integer): New function, containing integer code that was out of place in floatfns.c. (check_bignum_size, xmalloc_for_gmp): Remove. * src/emacs.c (main): Do not initialize GMP here. * src/floatfns.c (Fexpt): Use expt_integer, which now contains integer code moved from here. * src/lisp.h (GMP_NUMB_BITS): Define if gmp.h doesn’t.
Diffstat (limited to 'src/floatfns.c')
-rw-r--r--src/floatfns.c24
1 files changed, 1 insertions, 23 deletions
diff --git a/src/floatfns.c b/src/floatfns.c
index 7c52a0a9a20..ea9000b90a0 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -210,29 +210,7 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0,
/* Common Lisp spec: don't promote if both are integers, and if the
result is not fractional. */
if (INTEGERP (arg1) && NATNUMP (arg2))
- {
- unsigned long exp;
- if (TYPE_RANGED_FIXNUMP (unsigned long, arg2))
- exp = XFIXNUM (arg2);
- else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (arg2)
- && mpz_fits_ulong_p (XBIGNUM (arg2)->value))
- exp = mpz_get_ui (XBIGNUM (arg2)->value);
- else
- xsignal3 (Qrange_error, build_string ("expt"), arg1, arg2);
-
- mpz_t val;
- mpz_init (val);
- if (FIXNUMP (arg1))
- {
- mpz_set_intmax (val, XFIXNUM (arg1));
- mpz_pow_ui (val, val, exp);
- }
- else
- mpz_pow_ui (val, XBIGNUM (arg1)->value, exp);
- Lisp_Object res = make_number (val);
- mpz_clear (val);
- return res;
- }
+ return expt_integer (arg1, arg2);
return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2)));
}