]> git.saurik.com Git - bison.git/blobdiff - lib/lbitset.c
maint: run "make update-copyright"
[bison.git] / lib / lbitset.c
index 2e5b208140126711f0a21331a14336587f385b2d..d48a4a83510914c0df1da65dda5c0ba072f13962 100644 (file)
@@ -1,10 +1,11 @@
 /* Functions to support link list bitsets.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002-2004, 2006, 2009-2010 Free Software Foundation,
+   Inc.
    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
 
-   This program is free software; you can redistribute it and/or modify
+   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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <config.h>
 
 #include "lbitset.h"
+
 #include "obstack.h"
 #include <stddef.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 /* This file implements linked-list bitsets.  These bitsets can be of
    arbitrary length and are more efficient than arrays of bits for
 /* Number of words to use for each element.  The larger the value the
    greater the size of the cache and the shorter the time to find a given bit
    but the more memory wasted for sparse bitsets and the longer the time
-   to search for set bits.  */
+   to search for set bits.
+
+   The routines that dominate timing profiles are lbitset_elt_find
+   and lbitset_elt_link, especially when accessing the bits randomly.  */
 
 #define LBITSET_ELT_WORDS 2
 
@@ -50,7 +52,7 @@ typedef bitset_word lbitset_word;
 
 /* Number of bits stored in each element.  */
 #define LBITSET_ELT_BITS \
-  ((unsigned) (LBITSET_ELT_WORDS * LBITSET_WORD_BITS))
+  ((unsigned int) (LBITSET_ELT_WORDS * LBITSET_WORD_BITS))
 
 /* Lbitset element.   We use an array of bits for each element.
    These are linked together in a doubly-linked list.  */
@@ -74,7 +76,7 @@ static struct obstack lbitset_obstack;
 static bool lbitset_obstack_init = false;
 static lbitset_elt *lbitset_free_list; /* Free list of bitset elements.  */
 
-extern void debug_lbitset PARAMS ((bitset));
+extern void debug_lbitset (bitset);
 
 #define LBITSET_CURRENT1(X) \
   ((lbitset_elt *) (void *) ((char *) (X) - offsetof (lbitset_elt, words)))
@@ -117,15 +119,13 @@ lbitset_elt_alloc (void)
 #define OBSTACK_CHUNK_FREE free
 #endif
 
-#if !defined(__GNUC__) || (__GNUC__ < 2)
+#if ! defined __GNUC__ || __GNUC__ < 2
 #define __alignof__(type) 0
 #endif
 
          obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE,
                                      __alignof__ (lbitset_elt),
-                                     (void *(*)PARAMS ((long)))
                                      OBSTACK_CHUNK_ALLOC,
-                                     (void (*)PARAMS ((void *)))
                                      OBSTACK_CHUNK_FREE);
        }
 
@@ -361,6 +361,9 @@ lbitset_elt_find (bitset bset, bitset_windex windex,
 
   switch (mode)
     {
+    default:
+      abort ();
+
     case LBITSET_FIND:
       return 0;
 
@@ -374,9 +377,6 @@ lbitset_elt_find (bitset bset, bitset_windex windex,
 
     case LBITSET_SUBST:
       return &lbitset_zero_elts[0];
-
-    default:
-      abort ();
     }
 }
 
@@ -502,21 +502,15 @@ lbitset_copy_cmp (bitset dst, bitset src)
 }
 
 
-/* Return size in bits of bitset SRC.  */
 static bitset_bindex
-lbitset_size (bitset src)
+lbitset_resize (bitset src, bitset_bindex size)
 {
-  lbitset_elt *elt;
-
-  elt = LBITSET_TAIL (src);
-  if (!elt)
-    return 0;
+    BITSET_NBITS_ (src) = size;
 
-  /* Return current size of bitset in bits.  */
-  return (elt->index + LBITSET_ELT_WORDS) * BITSET_WORD_BITS;
+    /* Need to prune any excess bits.  FIXME.  */
+    return size;
 }
 
-
 /* Set bit BITNO in bitset DST.  */
 static void
 lbitset_set (bitset dst, bitset_bindex bitno)
@@ -867,8 +861,48 @@ lbitset_list (bitset bset, bitset_bindex *list,
 static bool
 lbitset_empty_p (bitset dst)
 {
-  lbitset_weed (dst);
-  return !LBITSET_HEAD (dst);
+  lbitset_elt *elt;
+  lbitset_elt *next;
+
+  for (elt = LBITSET_HEAD (dst); elt; elt = next)
+    {
+      next = elt->next;
+      if (!lbitset_elt_zero_p (elt))
+       return 0;
+      /* Weed as we go.  */
+      lbitset_elt_unlink (dst, elt);
+    }
+
+  return 1;
+}
+
+
+/* Ensure that any unused bits within the last element are clear.  */
+static inline void
+lbitset_unused_clear (bitset dst)
+{
+  unsigned int last_bit;
+  bitset_bindex n_bits;
+
+  n_bits = BITSET_SIZE_ (dst);
+  last_bit = n_bits % LBITSET_ELT_BITS;
+
+  if (last_bit)
+    {
+      lbitset_elt *elt;
+      bitset_windex windex;
+      bitset_word *srcp;
+
+      elt = LBITSET_TAIL (dst);
+      srcp = elt->words;
+      windex = n_bits / BITSET_WORD_BITS;
+
+      srcp[windex - elt->index] &= ((bitset_word) 1 << last_bit) - 1;
+      windex++;
+
+      for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
+       srcp[windex - elt->index] = 0;
+    }
 }
 
 
@@ -883,18 +917,17 @@ lbitset_ones (bitset dst)
       bitset!  It makes a sparse bitset become dense.  An alternative
       is to have a flag that indicates that the bitset stores the
       complement of what it indicates.  */
-  elt = LBITSET_TAIL (dst);
-  /* Ignore empty set.  */
-  if (!elt)
-    return;
 
-  windex = elt->index;
+  windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS;
+
   for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
     {
       /* Create new elements if they cannot be found.  */
       elt = lbitset_elt_find (dst, i, LBITSET_CREATE);
       memset (elt->words, -1, sizeof (elt->words));
     }
+
+  lbitset_unused_clear (dst);
 }
 
 
@@ -911,11 +944,9 @@ lbitset_not (bitset dst, bitset src)
   /* This is another unfriendly operation for a linked list
      bitset!  */
   elt = LBITSET_TAIL (dst);
-  /* Ignore empty set.  */
-  if (!elt)
-    return;
 
-  windex = elt->index;
+  windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS;
+
   for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
     {
       /* Create new elements for dst if they cannot be found
@@ -926,6 +957,7 @@ lbitset_not (bitset dst, bitset src)
       for (j = 0; j < LBITSET_ELT_WORDS; j++)
        delt->words[j] = ~selt->words[j];
     }
+  lbitset_unused_clear (dst);
   lbitset_weed (dst);
   return;
 }
@@ -1083,6 +1115,9 @@ lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
       dstp = dtmp->words;
       switch (op)
        {
+       default:
+         abort ();
+
        case BITSET_OP_OR:
          for (i = 0; i < LBITSET_ELT_WORDS; i++, dstp++)
            {
@@ -1134,9 +1169,6 @@ lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
                }
            }
          break;
-
-       default:
-         abort ();
        }
 
       if (!lbitset_elt_zero_p (dtmp))
@@ -1280,7 +1312,8 @@ struct bitset_vtable lbitset_vtable = {
   lbitset_reset,
   bitset_toggle_,
   lbitset_test,
-  lbitset_size,
+  lbitset_resize,
+  bitset_size_,
   bitset_count_,
   lbitset_empty_p,
   lbitset_ones,
@@ -1323,6 +1356,7 @@ lbitset_bytes (bitset_bindex n_bits ATTRIBUTE_UNUSED)
 bitset
 lbitset_init (bitset bset, bitset_bindex n_bits ATTRIBUTE_UNUSED)
 {
+  BITSET_NBITS_ (bset) = n_bits;
   bset->b.vtable = &lbitset_vtable;
   return bset;
 }
@@ -1352,7 +1386,7 @@ debug_lbitset (bitset bset)
 
   for (elt = LBITSET_HEAD (bset); elt; elt = elt->next)
     {
-      fprintf (stderr, "Elt %lu\n", (unsigned long) elt->index);
+      fprintf (stderr, "Elt %lu\n", (unsigned long int) elt->index);
       for (i = 0; i < LBITSET_ELT_WORDS; i++)
        {
          unsigned int j;