bitset.h revision 01e04c3f
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2006  Brian Paul   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file bitset.h
27 * \brief Bitset of arbitrary size definitions.
28 * \author Michal Krol
29 */
30
31#ifndef BITSET_H
32#define BITSET_H
33
34#include "util/bitscan.h"
35#include "util/macros.h"
36
37/****************************************************************************
38 * generic bitset implementation
39 */
40
41#define BITSET_WORD unsigned int
42#define BITSET_WORDBITS (sizeof (BITSET_WORD) * 8)
43
44/* bitset declarations
45 */
46#define BITSET_WORDS(bits) (((bits) + BITSET_WORDBITS - 1) / BITSET_WORDBITS)
47#define BITSET_DECLARE(name, bits) BITSET_WORD name[BITSET_WORDS(bits)]
48
49/* bitset operations
50 */
51#define BITSET_COPY(x, y) memcpy( (x), (y), sizeof (x) )
52#define BITSET_EQUAL(x, y) (memcmp( (x), (y), sizeof (x) ) == 0)
53#define BITSET_ZERO(x) memset( (x), 0, sizeof (x) )
54#define BITSET_ONES(x) memset( (x), 0xff, sizeof (x) )
55
56#define BITSET_BITWORD(b) ((b) / BITSET_WORDBITS)
57#define BITSET_BIT(b) (1u << ((b) % BITSET_WORDBITS))
58
59/* single bit operations
60 */
61#define BITSET_TEST(x, b) ((x)[BITSET_BITWORD(b)] & BITSET_BIT(b))
62#define BITSET_SET(x, b) ((x)[BITSET_BITWORD(b)] |= BITSET_BIT(b))
63#define BITSET_CLEAR(x, b) ((x)[BITSET_BITWORD(b)] &= ~BITSET_BIT(b))
64
65#define BITSET_MASK(b) ((b) == BITSET_WORDBITS ? ~0 : BITSET_BIT(b) - 1)
66#define BITSET_RANGE(b, e) (BITSET_MASK((e) + 1) & ~BITSET_MASK(b))
67
68/* bit range operations
69 */
70#define BITSET_TEST_RANGE(x, b, e) \
71   (BITSET_BITWORD(b) == BITSET_BITWORD(e) ? \
72   ((x)[BITSET_BITWORD(b)] & BITSET_RANGE(b, e)) : \
73   (assert (!"BITSET_TEST_RANGE: bit range crosses word boundary"), 0))
74#define BITSET_SET_RANGE(x, b, e) \
75   (BITSET_BITWORD(b) == BITSET_BITWORD(e) ? \
76   ((x)[BITSET_BITWORD(b)] |= BITSET_RANGE(b, e)) : \
77   (assert (!"BITSET_SET_RANGE: bit range crosses word boundary"), 0))
78#define BITSET_CLEAR_RANGE(x, b, e) \
79   (BITSET_BITWORD(b) == BITSET_BITWORD(e) ? \
80   ((x)[BITSET_BITWORD(b)] &= ~BITSET_RANGE(b, e)) : \
81   (assert (!"BITSET_CLEAR_RANGE: bit range crosses word boundary"), 0))
82
83/* Get first bit set in a bitset.
84 */
85static inline int
86__bitset_ffs(const BITSET_WORD *x, int n)
87{
88   int i;
89
90   for (i = 0; i < n; i++) {
91      if (x[i])
92	 return ffs(x[i]) + BITSET_WORDBITS * i;
93   }
94
95   return 0;
96}
97
98#define BITSET_FFS(x) __bitset_ffs(x, ARRAY_SIZE(x))
99
100static inline unsigned
101__bitset_next_set(unsigned i, BITSET_WORD *tmp,
102                  const BITSET_WORD *set, unsigned size)
103{
104   unsigned bit, word;
105
106   /* NOTE: The initial conditions for this function are very specific.  At
107    * the start of the loop, the tmp variable must be set to *set and the
108    * initial i value set to 0.  This way, if there is a bit set in the first
109    * word, we ignore the i-value and just grab that bit (so 0 is ok, even
110    * though 0 may be returned).  If the first word is 0, then the value of
111    * `word` will be 0 and we will go on to look at the second word.
112    */
113   word = BITSET_BITWORD(i);
114   while (*tmp == 0) {
115      word++;
116
117      if (word >= BITSET_WORDS(size))
118         return size;
119
120      *tmp = set[word];
121   }
122
123   /* Find the next set bit in the non-zero word */
124   bit = ffs(*tmp) - 1;
125
126   /* Unset the bit */
127   *tmp &= ~(1ull << bit);
128
129   return word * BITSET_WORDBITS + bit;
130}
131
132#define BITSET_FOREACH_SET(__i, __tmp, __set, __size) \
133   for (__tmp = *(__set), __i = 0; \
134        (__i = __bitset_next_set(__i, &__tmp, __set, __size)) < __size;)
135
136#ifdef __cplusplus
137
138/**
139 * Simple C++ wrapper of a bitset type of static size, with value semantics
140 * and basic bitwise arithmetic operators.  The operators defined below are
141 * expected to have the same semantics as the same operator applied to other
142 * fundamental integer types.  T is the name of the struct to instantiate
143 * it as, and N is the number of bits in the bitset.
144 */
145#define DECLARE_BITSET_T(T, N) struct T {                       \
146      EXPLICIT_CONVERSION                                       \
147      operator bool() const                                     \
148      {                                                         \
149         for (unsigned i = 0; i < BITSET_WORDS(N); i++)         \
150            if (words[i])                                       \
151               return true;                                     \
152         return false;                                          \
153      }                                                         \
154                                                                \
155      T &                                                       \
156      operator=(int x)                                          \
157      {                                                         \
158         const T c = {{ (BITSET_WORD)x }};                      \
159         return *this = c;                                      \
160      }                                                         \
161                                                                \
162      friend bool                                               \
163      operator==(const T &b, const T &c)                        \
164      {                                                         \
165         return BITSET_EQUAL(b.words, c.words);                 \
166      }                                                         \
167                                                                \
168      friend bool                                               \
169      operator!=(const T &b, const T &c)                        \
170      {                                                         \
171         return !(b == c);                                      \
172      }                                                         \
173                                                                \
174      friend bool                                               \
175      operator==(const T &b, int x)                             \
176      {                                                         \
177         const T c = {{ (BITSET_WORD)x }};                      \
178         return b == c;                                         \
179      }                                                         \
180                                                                \
181      friend bool                                               \
182      operator!=(const T &b, int x)                             \
183      {                                                         \
184         return !(b == x);                                      \
185      }                                                         \
186                                                                \
187      friend T                                                  \
188      operator~(const T &b)                                     \
189      {                                                         \
190         T c;                                                   \
191         for (unsigned i = 0; i < BITSET_WORDS(N); i++)         \
192            c.words[i] = ~b.words[i];                           \
193         return c;                                              \
194      }                                                         \
195                                                                \
196      T &                                                       \
197      operator|=(const T &b)                                    \
198      {                                                         \
199         for (unsigned i = 0; i < BITSET_WORDS(N); i++)         \
200            words[i] |= b.words[i];                             \
201         return *this;                                          \
202      }                                                         \
203                                                                \
204      friend T                                                  \
205      operator|(const T &b, const T &c)                         \
206      {                                                         \
207         T d = b;                                               \
208         d |= c;                                                \
209         return d;                                              \
210      }                                                         \
211                                                                \
212      T &                                                       \
213      operator&=(const T &b)                                    \
214      {                                                         \
215         for (unsigned i = 0; i < BITSET_WORDS(N); i++)         \
216            words[i] &= b.words[i];                             \
217         return *this;                                          \
218      }                                                         \
219                                                                \
220      friend T                                                  \
221      operator&(const T &b, const T &c)                         \
222      {                                                         \
223         T d = b;                                               \
224         d &= c;                                                \
225         return d;                                              \
226      }                                                         \
227                                                                \
228      bool                                                      \
229      test(unsigned i) const                                    \
230      {                                                         \
231         return BITSET_TEST(words, i);                          \
232      }                                                         \
233                                                                \
234      T &                                                       \
235      set(unsigned i)                                           \
236      {                                                         \
237         BITSET_SET(words, i);                                  \
238         return *this;                                          \
239      }                                                         \
240                                                                \
241      T &                                                       \
242      clear(unsigned i)                                         \
243      {                                                         \
244         BITSET_CLEAR(words, i);                                \
245         return *this;                                          \
246      }                                                         \
247                                                                \
248      BITSET_WORD words[BITSET_WORDS(N)];                       \
249   }
250
251#endif
252
253#endif
254