From 2d1f5de16ef6c0be14355f294326d98c6fb6348b Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 11 Jul 2024 12:42:57 +0200 Subject: [PATCH] Optimize smallish mpz to native int conversion * src/bignum.c (make_integer_mpz, mpz_to_intmax): If FASTER_BIGNUM, optimize the common case where the value fits in long int. In this case we can use mpz_fits_slong_p and mpz_get_si instead of looping with mpz_getlimbn. (mpz_to_uintmax): Likewise for unsigned long int and mpz_get_ui. (cherry picked from commit 0c850df888ebb68096a82ab32089e809de591620) --- src/bignum.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/bignum.c b/src/bignum.c index 1fe195d78ea..7589691dd0c 100644 --- a/src/bignum.c +++ b/src/bignum.c @@ -145,9 +145,19 @@ make_neg_biguint (uintmax_t n) Lisp_Object make_integer_mpz (void) { + if (FASTER_BIGNUM && mpz_fits_slong_p (mpz[0])) + { + long int v = mpz_get_si (mpz[0]); + if (!FIXNUM_OVERFLOW_P (v)) + return make_fixnum (v); + } + size_t bits = mpz_sizeinbase (mpz[0], 2); - if (bits <= FIXNUM_BITS) + if (! (FASTER_BIGNUM + && FIXNUM_OVERFLOW_P (LONG_MIN) + && FIXNUM_OVERFLOW_P (LONG_MAX)) + && bits <= FIXNUM_BITS) { EMACS_INT v = 0; int i = 0, shift = 0; @@ -216,6 +226,17 @@ mpz_set_uintmax_slow (mpz_t result, uintmax_t v) bool mpz_to_intmax (mpz_t const z, intmax_t *pi) { + if (FASTER_BIGNUM) + { + if (mpz_fits_slong_p (z)) + { + *pi = mpz_get_si (z); + return true; + } + if (LONG_MIN <= INTMAX_MIN && INTMAX_MAX <= LONG_MAX) + return false; + } + ptrdiff_t bits = mpz_sizeinbase (z, 2); bool negative = mpz_sgn (z) < 0; @@ -246,6 +267,17 @@ mpz_to_intmax (mpz_t const z, intmax_t *pi) bool mpz_to_uintmax (mpz_t const z, uintmax_t *pi) { + if (FASTER_BIGNUM) + { + if (mpz_fits_ulong_p (z)) + { + *pi = mpz_get_ui (z); + return true; + } + if (UINTMAX_MAX <= ULONG_MAX) + return false; + } + if (mpz_sgn (z) < 0) return false; ptrdiff_t bits = mpz_sizeinbase (z, 2); -- 2.39.2