diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/src/alloc.c b/src/alloc.c index ddc0696ba91..24a24aab96b 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3746,33 +3746,33 @@ make_bignum_str (const char *num, int base) | |||
| 3746 | Lisp_Object | 3746 | Lisp_Object |
| 3747 | make_number (mpz_t value) | 3747 | make_number (mpz_t value) |
| 3748 | { | 3748 | { |
| 3749 | if (mpz_fits_slong_p (value)) | 3749 | size_t bits = mpz_sizeinbase (value, 2); |
| 3750 | { | 3750 | |
| 3751 | long l = mpz_get_si (value); | 3751 | if (bits <= FIXNUM_BITS) |
| 3752 | if (!FIXNUM_OVERFLOW_P (l)) | ||
| 3753 | return make_fixnum (l); | ||
| 3754 | } | ||
| 3755 | else if (LONG_WIDTH < FIXNUM_BITS) | ||
| 3756 | { | 3752 | { |
| 3757 | size_t bits = mpz_sizeinbase (value, 2); | 3753 | EMACS_INT v = 0; |
| 3754 | int i = 0, shift = 0; | ||
| 3758 | 3755 | ||
| 3759 | if (bits <= FIXNUM_BITS) | 3756 | do |
| 3760 | { | 3757 | { |
| 3761 | EMACS_INT v = 0; | 3758 | EMACS_INT limb = mpz_getlimbn (value, i++); |
| 3762 | int i = 0; | 3759 | v += limb << shift; |
| 3763 | for (int shift = 0; shift < bits; shift += mp_bits_per_limb) | 3760 | shift += GMP_NUMB_BITS; |
| 3764 | { | 3761 | } |
| 3765 | EMACS_INT limb = mpz_getlimbn (value, i++); | 3762 | while (shift < bits); |
| 3766 | v += limb << shift; | ||
| 3767 | } | ||
| 3768 | if (mpz_sgn (value) < 0) | ||
| 3769 | v = -v; | ||
| 3770 | 3763 | ||
| 3771 | if (!FIXNUM_OVERFLOW_P (v)) | 3764 | if (mpz_sgn (value) < 0) |
| 3772 | return make_fixnum (v); | 3765 | v = -v; |
| 3773 | } | 3766 | |
| 3767 | if (!FIXNUM_OVERFLOW_P (v)) | ||
| 3768 | return make_fixnum (v); | ||
| 3774 | } | 3769 | } |
| 3775 | 3770 | ||
| 3771 | /* The documentation says integer-width should be nonnegative, so | ||
| 3772 | a single comparison suffices even though 'bits' is unsigned. */ | ||
| 3773 | if (integer_width < bits) | ||
| 3774 | integer_overflow (); | ||
| 3775 | |||
| 3776 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, | 3776 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, |
| 3777 | PVEC_BIGNUM); | 3777 | PVEC_BIGNUM); |
| 3778 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the | 3778 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the |
| @@ -7200,6 +7200,26 @@ verify_alloca (void) | |||
| 7200 | 7200 | ||
| 7201 | #endif /* ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */ | 7201 | #endif /* ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */ |
| 7202 | 7202 | ||
| 7203 | /* Memory allocation for GMP. */ | ||
| 7204 | |||
| 7205 | void | ||
| 7206 | integer_overflow (void) | ||
| 7207 | { | ||
| 7208 | error ("Integer too large to be represented"); | ||
| 7209 | } | ||
| 7210 | |||
| 7211 | static void * | ||
| 7212 | xrealloc_for_gmp (void *ptr, size_t ignore, size_t size) | ||
| 7213 | { | ||
| 7214 | return xrealloc (ptr, size); | ||
| 7215 | } | ||
| 7216 | |||
| 7217 | static void | ||
| 7218 | xfree_for_gmp (void *ptr, size_t ignore) | ||
| 7219 | { | ||
| 7220 | xfree (ptr); | ||
| 7221 | } | ||
| 7222 | |||
| 7203 | /* Initialization. */ | 7223 | /* Initialization. */ |
| 7204 | 7224 | ||
| 7205 | void | 7225 | void |
| @@ -7233,6 +7253,10 @@ init_alloc_once (void) | |||
| 7233 | void | 7253 | void |
| 7234 | init_alloc (void) | 7254 | init_alloc (void) |
| 7235 | { | 7255 | { |
| 7256 | eassert (mp_bits_per_limb == GMP_NUMB_BITS); | ||
| 7257 | integer_width = 1 << 16; | ||
| 7258 | mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp); | ||
| 7259 | |||
| 7236 | Vgc_elapsed = make_float (0.0); | 7260 | Vgc_elapsed = make_float (0.0); |
| 7237 | gcs_done = 0; | 7261 | gcs_done = 0; |
| 7238 | 7262 | ||
| @@ -7335,6 +7359,11 @@ The time is in seconds as a floating point value. */); | |||
| 7335 | DEFVAR_INT ("gcs-done", gcs_done, | 7359 | DEFVAR_INT ("gcs-done", gcs_done, |
| 7336 | doc: /* Accumulated number of garbage collections done. */); | 7360 | doc: /* Accumulated number of garbage collections done. */); |
| 7337 | 7361 | ||
| 7362 | DEFVAR_INT ("integer-width", integer_width, | ||
| 7363 | doc: /* Maximum number of bits in bignums. | ||
| 7364 | Integers outside the fixnum range are limited to absolute values less | ||
| 7365 | than 2**N, where N is this variable's value. N should be nonnegative. */); | ||
| 7366 | |||
| 7338 | defsubr (&Scons); | 7367 | defsubr (&Scons); |
| 7339 | defsubr (&Slist); | 7368 | defsubr (&Slist); |
| 7340 | defsubr (&Svector); | 7369 | defsubr (&Svector); |