guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 32/69: Implement scm_logcount with new integer library


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

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

commit 18a37a60edf4041093642f3db6987137803477aa
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Tue Jan 4 09:53:09 2022 +0100

    Implement scm_logcount with new integer library
    
    * libguile/integers.c (scm_integer_logcount_i)
    (scm_integer_logcount_z): New internal functions.
    * libguile/integers.h: Declare the new internal functions.
    * libguile/numbers.c (scm_logcount): Use new internal functions.
---
 libguile/integers.c | 37 +++++++++++++++++++++++++++++++++++++
 libguile/integers.h |  3 +++
 libguile/numbers.c  | 34 ++--------------------------------
 3 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/libguile/integers.c b/libguile/integers.c
index 8ddcd087e..baa95b129 100644
--- a/libguile/integers.c
+++ b/libguile/integers.c
@@ -2254,3 +2254,40 @@ scm_integer_bit_extract_z (SCM n, unsigned long start, 
unsigned long bits)
   scm_remember_upto_here_1 (n);
   return take_mpz (result);
 }
+
+static const char scm_logtab[] = {
+  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
+};
+
+SCM
+scm_integer_logcount_i (scm_t_inum n)
+{
+  unsigned long c = 0;
+  if (n < 0)
+    n = -1 - n;
+  while (n)
+    {
+      c += scm_logtab[15 & n];
+      n >>= 4;
+    }
+  return SCM_I_MAKINUM (c);
+}
+
+SCM
+scm_integer_logcount_z (SCM n)
+{
+  unsigned long count;
+  mpz_t zn;
+  alias_bignum_to_mpz (scm_bignum (n), zn);
+  if (mpz_sgn (zn) >= 0)
+    count = mpz_popcount (zn);
+  else
+    {
+      mpz_t z_negative_one;
+      mpz_init_set_si (z_negative_one, -1);
+      count = mpz_hamdist (zn, z_negative_one);
+      mpz_clear (z_negative_one);
+    }
+  scm_remember_upto_here_1 (n);
+  return scm_from_ulong (count);
+}
diff --git a/libguile/integers.h b/libguile/integers.h
index e77084ea3..3955e5ea8 100644
--- a/libguile/integers.h
+++ b/libguile/integers.h
@@ -168,6 +168,9 @@ SCM_INTERNAL SCM scm_integer_bit_extract_i (scm_t_inum n, 
unsigned long start,
 SCM_INTERNAL SCM scm_integer_bit_extract_z (SCM n, unsigned long start,
                                             unsigned long bits);
 
+SCM_INTERNAL SCM scm_integer_logcount_i (scm_t_inum n);
+SCM_INTERNAL SCM scm_integer_logcount_z (SCM n);
+
 
 
 #endif  /* SCM_INTEGERS_H */
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 84b920eac..191e6e968 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -234,10 +234,6 @@ scm_from_complex_double (complex double z)
 
 
 
-static mpz_t z_negative_one;
-
-
-
 /* Clear the `mpz_t' embedded in bignum PTR.  */
 static void
 finalize_bignum (void *ptr, void *data)
@@ -3369,11 +3365,6 @@ SCM_DEFINE (scm_bit_extract, "bit-extract", 3, 0, 0,
 }
 #undef FUNC_NAME
 
-
-static const char scm_logtab[] = {
-  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
-};
-
 SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
             (SCM n),
            "Return the number of bits in integer @var{n}.  If integer is\n"
@@ -3392,28 +3383,9 @@ SCM_DEFINE (scm_logcount, "logcount", 1, 0, 0,
 #define FUNC_NAME s_scm_logcount
 {
   if (SCM_I_INUMP (n))
-    {
-      unsigned long c = 0;
-      scm_t_inum nn = SCM_I_INUM (n);
-      if (nn < 0)
-        nn = -1 - nn;
-      while (nn)
-        {
-          c += scm_logtab[15 & nn];
-          nn >>= 4;
-        }
-      return SCM_I_MAKINUM (c);
-    }
+    return scm_integer_logcount_i (SCM_I_INUM (n));
   else if (SCM_BIGP (n))
-    {
-      unsigned long count;
-      if (mpz_sgn (SCM_I_BIG_MPZ (n)) >= 0)
-        count = mpz_popcount (SCM_I_BIG_MPZ (n));
-      else
-        count = mpz_hamdist (SCM_I_BIG_MPZ (n), z_negative_one);
-      scm_remember_upto_here_1 (n);
-      return SCM_I_MAKINUM (count);
-    }
+    return scm_integer_logcount_z (n);
   else
     SCM_WRONG_TYPE_ARG (SCM_ARG1, n);
 }
@@ -8527,8 +8499,6 @@ scm_init_numbers ()
                              custom_gmp_realloc,
                              custom_gmp_free);
 
-  mpz_init_set_si (z_negative_one, -1);
-
   /* It may be possible to tune the performance of some algorithms by using
    * the following constants to avoid the creation of bignums.  Please, before
    * using these values, remember the two rules of program optimization:



reply via email to

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