bit-vector: Add new functions for working with bit vectors.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 2 Dec 2019 03:29:31 +0000 (03:29 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 29 Dec 2019 05:28:10 +0000 (05:28 +0000)
These will receive their first users in an upcoming commit.

src/language/dictionary/modify-variables.c
src/libpspp/automake.mk
src/libpspp/bit-vector.c [new file with mode: 0644]
src/libpspp/bit-vector.h
src/libpspp/model-checker.c

index 3dbbc18a02bd2e1b15142f333aa68d8bcf7959ba..a1fe6d75df294244fe11bc168c0120e2c77f57bd 100644 (file)
@@ -26,7 +26,6 @@
 #include "language/lexer/variable-parser.h"
 #include "libpspp/array.h"
 #include "libpspp/assertion.h"
-#include "libpspp/bit-vector.h"
 #include "libpspp/compiler.h"
 #include "libpspp/i18n.h"
 #include "libpspp/message.h"
index ddff61f8fc727a2970f84a1d091b95e43c50ab6a..0cde825f5b52d5aa1c220a35bc65b4af80eeecbb 100644 (file)
@@ -27,6 +27,7 @@ src_libpspp_liblibpspp_la_SOURCES = \
        src/libpspp/array.c \
        src/libpspp/array.h \
        src/libpspp/assertion.h \
+       src/libpspp/bit-vector.c \
        src/libpspp/bit-vector.h \
        src/libpspp/bt.c \
        src/libpspp/bt.h \
diff --git a/src/libpspp/bit-vector.c b/src/libpspp/bit-vector.c
new file mode 100644 (file)
index 0000000..2b98291
--- /dev/null
@@ -0,0 +1,40 @@
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "libpspp/bit-vector.h"
+
+#include "libpspp/misc.h"
+
+#include "gl/xalloc.h"
+
+unsigned long int *
+bitvector_allocate(size_t n)
+{
+  return xcalloc (sizeof (unsigned long int), DIV_RND_UP (n, BITS_PER_ULONG));
+}
+
+size_t
+bitvector_count (const unsigned long int *vec, size_t n)
+{
+  /* XXX This can be optimized. */
+  size_t count = 0;
+  for (size_t i = 0; i < n; i++)
+    count += bitvector_is_set (vec, i);
+  return count;
+}
+
index f994d4af472f58bd3e1fab8e5b4a684e6a43c936..53db166998249fddca017e7ead3ce62015a6f4db 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2019 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#if !bitvector_h
-#define bitvector_h 1
+#ifndef BITVECTOR_H
+#define BITVECTOR_H 1
 
 #include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
 
-/* Sets bit Y starting at address X. */
-#define SET_BIT(X, Y)                                  \
-       (((unsigned char *) X)[(Y) / CHAR_BIT] |= 1 << ((Y) % CHAR_BIT))
+enum { BITS_PER_ULONG = CHAR_BIT * sizeof (unsigned long int) };
 
-/* Clears bit Y starting at address X. */
-#define CLEAR_BIT(X, Y)                                \
-       (((unsigned char *) X)[(Y) / CHAR_BIT] &= ~(1 << ((Y) % CHAR_BIT)))
+unsigned long int *bitvector_allocate(size_t n);
+size_t bitvector_count (const unsigned long int *, size_t);
 
-/* Sets bit Y starting at address X to Z, which is zero/nonzero */
-#define SET_BIT_TO(X, Y, Z)                    \
-       ((Z) ? SET_BIT(X, Y) : CLEAR_BIT(X, Y))
+static unsigned long int
+bitvector_mask (size_t idx)
+{
+  return 1UL << (idx % BITS_PER_ULONG);
+}
 
-/* Nonzero if bit Y starting at address X is set. */
-#define TEST_BIT(X, Y)                                         \
-       (((unsigned char *) X)[(Y) / CHAR_BIT] & (1 << ((Y) % CHAR_BIT)))
+static const unsigned long int *
+bitvector_unit (const unsigned long int *vec, size_t idx)
+{
+  return &vec[idx / BITS_PER_ULONG];
+}
+
+static unsigned long int *
+bitvector_unit_rw (unsigned long int *vec, size_t idx)
+{
+  return &vec[idx / BITS_PER_ULONG];
+}
+
+static inline void
+bitvector_set1 (unsigned long int *vec, size_t idx)
+{
+  *bitvector_unit_rw (vec, idx) |= bitvector_mask (idx);
+}
+
+static inline void
+bitvector_set0 (unsigned long int *vec, size_t idx)
+{
+  *bitvector_unit_rw (vec, idx) &= ~bitvector_mask (idx);
+}
+
+static inline bool
+bitvector_is_set (const unsigned long int *vec, size_t idx)
+{
+  return (*bitvector_unit (vec, idx) & bitvector_mask (idx)) != 0;
+}
 
 /* Returns 2**X, 0 <= X < 32. */
 #define BIT_INDEX(X) (1ul << (X))
index 02ae9e733b268cc4234787bb5f760df36aadf071..c15dac9bbaf65e4363b98c252eaa18d1f5c1f345 100644 (file)
@@ -1150,7 +1150,7 @@ struct mc
 
     /* Array of 2**(options->hash_bits) bits representing states
        already visited. */
-    unsigned char *hash;
+    unsigned long int *hash;
 
     /* State queue. */
     struct mc_state **queue;            /* Array of pointers to states. */
@@ -1269,7 +1269,7 @@ mc_discard_dup_state (struct mc *mc, unsigned int hash)
   if (!mc->state_error && mc->options->hash_bits > 0)
     {
       hash &= (1u << mc->options->hash_bits) - 1;
-      if (TEST_BIT (mc->hash, hash))
+      if (bitvector_is_set (mc->hash, hash))
         {
           if (mc->options->verbosity > 2)
             fprintf (mc->options->output_file,
@@ -1278,7 +1278,7 @@ mc_discard_dup_state (struct mc *mc, unsigned int hash)
           next_operation (mc);
           return true;
         }
-      SET_BIT (mc->hash, hash);
+      bitvector_set1 (mc->hash, hash);
     }
   return false;
 }
@@ -1688,7 +1688,7 @@ init_mc (struct mc *mc, const struct mc_class *class,
   mc->results = mc_results_create ();
 
   mc->hash = (mc->options->hash_bits > 0
-              ? xcalloc (1, DIV_RND_UP (1 << mc->options->hash_bits, CHAR_BIT))
+              ? bitvector_allocate (1 << mc->options->hash_bits)
               : NULL);
 
   mc->queue = NULL;