]> git.eshelyaron.com Git - emacs.git/commitdiff
Optimize smallish mpz to native int conversion
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 11 Jul 2024 10:42:57 +0000 (12:42 +0200)
committerEshel Yaron <me@eshelyaron.com>
Thu, 11 Jul 2024 14:39:50 +0000 (16:39 +0200)
* 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

index 1fe195d78ea5fefc485d0d17b497177cc2b11e7b..7589691dd0c15db47bacf9c6688486c8e296aaff 100644 (file)
@@ -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);