guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 34/69: Implement scm_integer_length with new integer lib


From: Andy Wingo
Subject: [Guile-commits] 34/69: Implement scm_integer_length with new integer library
Date: Fri, 7 Jan 2022 08:27:11 -0500 (EST)

wingo pushed a commit to branch wip-inline-digits
in repository guile.

commit 46cba3725aa18f4ea20f79908d2033d49d6ee088
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Tue Jan 4 10:51:20 2022 +0100

    Implement scm_integer_length with new integer library
    
    * libguile/integers.c (scm_integer_length_i)
    (scm_integer_length_z): New internal functions.
    * libguile/integers.h: Declare the new internal functions.
    * libguile/numbers.c (scm_integer_length): Use new internal functions.
---
 libguile/integers.c | 36 ++++++++++++++++++++++++++++++++++++
 libguile/integers.h |  5 ++++-
 libguile/numbers.c  | 34 ++--------------------------------
 3 files changed, 42 insertions(+), 33 deletions(-)

diff --git a/libguile/integers.c b/libguile/integers.c
index db806b35f..fafef184f 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -2291,3 +2291,39 @@ scm_integer_logcount_z (struct scm_bignum *n)
   scm_remember_upto_here_1 (n);
   return scm_from_ulong (count);
 }
+
+static const char scm_ilentab[] = {
+  0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+SCM
+scm_integer_length_i (scm_t_inum n)
+{
+  unsigned long c = 0;
+  unsigned int l = 4;
+  if (n < 0)
+    n = -1 - n;
+  while (n)
+    {
+      c += 4;
+      l = scm_ilentab [15 & n];
+      n >>= 4;
+    }
+  return SCM_I_MAKINUM (c - 4 + l);
+}
+
+SCM
+scm_integer_length_z (struct scm_bignum *n)
+{
+  /* mpz_sizeinbase looks at the absolute value of negatives, whereas we
+     want a ones-complement.  If n is ...111100..00 then mpz_sizeinbase is
+     1 too big, so check for that and adjust.  */
+  mpz_t zn;
+  alias_bignum_to_mpz (n, zn);
+  size_t size = mpz_sizeinbase (zn, 2);
+  /* If negative and no 0 bits above the lowest 1, adjust result.  */
+  if (mpz_sgn (zn) < 0 && mpz_scan0 (zn, mpz_scan1 (zn, 0)) == ULONG_MAX)
+    size--;
+  scm_remember_upto_here_1 (n);
+  return scm_from_size_t (size);
+}
diff --git a/libguile/integers.h b/libguile/integers.h
index 0ffe713a1..5bc2c7650 100644
--- a/libguile/integers.h
+++ b/libguile/integers.h
@@ -1,7 +1,7 @@
 #ifndef SCM_INTEGERS_H
 #define SCM_INTEGERS_H
 
-/* Copyright 2021 Free Software Foundation, Inc.
+/* Copyright 2021, 2022 Free Software Foundation, Inc.
 
    This file is part of Guile.
 
@@ -141,6 +141,9 @@ SCM_INTERNAL SCM scm_integer_bit_extract_z (struct 
scm_bignum *n,
 SCM_INTERNAL SCM scm_integer_logcount_i (scm_t_inum n);
 SCM_INTERNAL SCM scm_integer_logcount_z (struct scm_bignum *n);
 
+SCM_INTERNAL SCM scm_integer_length_i (scm_t_inum n);
+SCM_INTERNAL SCM scm_integer_length_z (struct scm_bignum *n);
+
 
 
 #endif  /* SCM_INTEGERS_H */
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 1a840e424..efc9ed06c 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -3409,12 +3409,6 @@ SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
 }
 #undef FUNC_NAME
 
-
-static const char scm_ilentab[] = {
-  0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
-};
-
-
 SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 0,
             (SCM n),
            "Return the number of bits necessary to represent @var{n}.\n"
@@ -3430,33 +3424,9 @@ SCM_DEFINE (scm_integer_length, "integer-length", 1, 0, 
0,
 #define FUNC_NAME s_scm_integer_length
 {
   if (SCM_I_INUMP (n))
-    {
-      unsigned long c = 0;
-      unsigned int l = 4;
-      scm_t_inum nn = SCM_I_INUM (n);
-      if (nn < 0)
-       nn = -1 - nn;
-      while (nn)
-       {
-         c += 4;
-         l = scm_ilentab [15 & nn];
-         nn >>= 4;
-       }
-      return SCM_I_MAKINUM (c - 4 + l);
-    }
+    return scm_integer_length_i (SCM_I_INUM (n));
   else if (SCM_BIGP (n))
-    {
-      /* mpz_sizeinbase looks at the absolute value of negatives, whereas we
-        want a ones-complement.  If n is ...111100..00 then mpz_sizeinbase is
-        1 too big, so check for that and adjust.  */
-      size_t size = mpz_sizeinbase (SCM_I_BIG_MPZ (n), 2);
-      if (mpz_sgn (SCM_I_BIG_MPZ (n)) < 0
-         && mpz_scan0 (SCM_I_BIG_MPZ (n),  /* no 0 bits above the lowest 1 */
-                       mpz_scan1 (SCM_I_BIG_MPZ (n), 0)) == ULONG_MAX)
-       size--;
-      scm_remember_upto_here_1 (n);
-      return SCM_I_MAKINUM (size);
-    }
+    return scm_integer_length_z (scm_bignum (n));
   else
     SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]