spot 2.16
Loading...
Searching...
No Matches
bitset.hh
1// -*- coding: utf-8 -*-
2// Copyright (C) by the Spot authors, see the AUTHORS file for details.
3//
4// This file is part of Spot, a model checking library.
5//
6// Spot is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 3 of the License, or
9// (at your option) any later version.
10//
11// Spot is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14// License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#pragma once
20
21#include <array>
22#include <spot/misc/hashfunc.hh>
23#include <spot/misc/common.hh>
24#include <spot/misc/clz.hh>
25
26namespace spot
27{
28#ifndef SWIG
29 namespace internal
30 {
31 [[noreturn]] SPOT_API void report_bit_shift_too_big();
32 [[noreturn]] SPOT_API void report_bit_out_of_bounds();
33 }
34#endif
35
38 template<size_t N>
39 class SPOT_API bitset
40 {
41 using word_t = unsigned;
42 // the number of bits must hold on an unsigned
43 static_assert(8*N*sizeof(word_t) < -1U, "too many bits in bitset");
44
45 std::array<word_t, N> data;
46
48 struct minus_one_tag {};
49 explicit bitset(minus_one_tag)
50 {
51 for (auto& v : data)
52 v = -1U;
53 }
54
55 constexpr explicit bitset(word_t s)
56 : data{{s}}
57 {
58 SPOT_ASSERT(s == 0U || s == 1U);
59 }
60
61 public:
62 // constructor
63 bitset() = default;
64 ~bitset() = default;
65
67 static constexpr bitset zero() { return bitset{0U}; }
69 static constexpr bitset one() { return bitset{1U}; }
71 static bitset mone() { return bitset(minus_one_tag{}); }
72
74 explicit operator bool() const
75 {
76 for (const auto& v : data)
77 if (v)
78 return true;
79 return false;
80 }
81
83 size_t hash() const
84 {
85 return fnv_hash(data.begin(), data.end());
86 }
87
89 bool operator==(const bitset& other) const
90 {
91 // TODO use std::algorithms instead?
92 for (unsigned i = 0; i != N; ++i)
93 if (data[i] != other.data[i])
94 return false;
95 return true;
96 }
97
99 bool operator!=(const bitset& other) const
100 {
101 return !this->operator==(other);
102 }
103
105 bool operator<(const bitset& other) const
106 {
107 for (unsigned i = 0; i != N; ++i)
108 if (data[i] < other.data[i])
109 return true;
110 else if (data[i] > other.data[i])
111 return false;
112 return false;
113 }
114
116 bool operator<=(const bitset& other) const
117 {
118 for (unsigned i = 0; i != N; ++i)
119 if (data[i] < other.data[i])
120 return true;
121 else if (data[i] > other.data[i])
122 return false;
123 return true;
124 }
125
127 bool operator>(const bitset& other) const
128 {
129 return other.operator<(*this);
130 }
131
133 bool operator>=(const bitset& other) const
134 {
135 return other.operator<=(*this);
136 }
137
139 void set(unsigned s)
140 {
141#if SPOT_DEBUG || defined(SWIGPYTHON)
142 if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
143 internal::report_bit_out_of_bounds();
144#else
145 SPOT_ASSUME(s < 8 * N * sizeof(word_t));
146#endif
147 data[s / (8*sizeof(word_t))] |= 1U << (s % (8*sizeof(word_t)));
148 }
149
151 void clear(unsigned s)
152 {
153#if SPOT_DEBUG || defined(SWIGPYTHON)
154 if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
155 internal::report_bit_out_of_bounds();
156#else
157 SPOT_ASSUME(s < 8 * N * sizeof(word_t));
158#endif
159 data[s / (8*sizeof(word_t))] &= ~(1U << (s % (8*sizeof(word_t))));
160 }
161
163 bitset operator<<(unsigned s) const
164 {
165 bitset r = *this;
166 r <<= s;
167 return r;
168 }
170 bitset operator>>(unsigned s) const
171 {
172 bitset r = *this;
173 r >>= s;
174 return r;
175 }
176
178 bitset& operator<<=(unsigned s)
179 {
180#if SPOT_DEBUG || defined(SWIGPYTHON)
181 if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
182 internal::report_bit_shift_too_big();
183#else
184 SPOT_ASSUME(s < 8 * N * sizeof(word_t));
185#endif
186
187 // Skip the rest of this function in the most common case of
188 // N==1. g++ 6 can optimize away all the loops if N==1, but
189 // clang++4 cannot and needs help.
190 if (N == 1)
191 {
192 data[0] <<= s;
193 return *this;
194 }
195
196 if (s == 0)
197 return *this;
198 const unsigned wshift = s / (8 * sizeof(word_t));
199 const unsigned offset = s % (8 * sizeof(word_t));
200
201 if (offset == 0)
202 {
203 for (unsigned i = N - 1; i >= wshift; --i)
204 data[i] = data[i - wshift];
205 }
206 else
207 {
208 const unsigned sub_offset = 8 * sizeof(word_t) - offset;
209 for (unsigned i = N - 1; i > wshift; --i)
210 data[i] = ((data[i - wshift] << offset) |
211 (data[i - wshift - 1] >> sub_offset));
212 data[wshift] = data[0] << offset;
213 }
214 std::fill(data.begin(), data.begin() + wshift, word_t(0));
215 return *this;
216 }
217
219 bitset& operator>>=(unsigned s)
220 {
221#if SPOT_DEBUG || defined(SWIGPYTHON)
222 if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
223 internal::report_bit_shift_too_big();
224#else
225 SPOT_ASSUME(s < 8 * N * sizeof(word_t));
226#endif
227 // Skip the rest of this function in the most common case of
228 // N==1. g++ 6 can optimize away all the loops if N==1, but
229 // clang++4 cannot and needs help.
230 if (N == 1)
231 {
232 data[0] >>= s;
233 return *this;
234 }
235
236 if (s == 0)
237 return *this;
238 const unsigned wshift = s / (8 * sizeof(word_t));
239 const unsigned offset = s % (8 * sizeof(word_t));
240 const unsigned limit = N - wshift - 1;
241
242 if (offset == 0)
243 {
244 for (unsigned i = 0; i <= limit; ++i)
245 data[i] = data[i + wshift];
246 }
247 else
248 {
249 const unsigned sub_offset = 8 * sizeof(word_t) - offset;
250 for (unsigned i = 0; i < limit; ++i)
251 data[i] = ((data[i + wshift] >> offset) |
252 (data[i + wshift + 1] << sub_offset));
253 data[limit] = data[N - 1] >> offset;
254 }
255 std::fill(data.begin() + limit + 1, data.end(), word_t(0));
256 return *this;
257 }
258
261 {
262 bitset r = *this;
263 for (auto& v : r.data)
264 v = ~v;
265 return r;
266 }
267
269 bitset operator&(const bitset& other) const
270 {
271 bitset r = *this;
272 r &= other;
273 return r;
274 }
275
277 bitset operator|(const bitset& other) const
278 {
279 bitset r = *this;
280 r |= other;
281 return r;
282 }
283
285 bitset operator^(const bitset& other) const
286 {
287 bitset r = *this;
288 r ^= other;
289 return r;
290 }
291
293 bitset& operator&=(const bitset& other)
294 {
295 for (unsigned i = 0; i != N; ++i)
296 data[i] &= other.data[i];
297 return *this;
298 }
300 bitset& operator|=(const bitset& other)
301 {
302 for (unsigned i = 0; i != N; ++i)
303 data[i] |= other.data[i];
304 return *this;
305 }
307 bitset& operator^=(const bitset& other)
308 {
309 for (unsigned i = 0; i != N; ++i)
310 data[i] ^= other.data[i];
311 return *this;
312 }
313
315 bitset operator-(word_t s) const
316 {
317 bitset r = *this;
318 r -= s;
319 return r;
320 }
323 {
324 for (auto& v : data)
325 if (v >= s)
326 {
327 v -= s;
328 s = 0;
329 break;
330 }
331 else
332 {
333 v -= s;
334 s = 1;
335 }
336 return *this;
337 }
338
341 {
342 bitset res = *this;
343 unsigned carry = 1;
344 for (auto& v : res.data)
345 {
346 word_t old = v;
347 v = ~v + carry;
348 carry = old == 0;
349 }
350 return res;
351 }
352
354 unsigned count() const
355 {
356 unsigned c = 0U;
357 for (auto v : data)
358 {
359#ifdef __GNUC__
360 c += __builtin_popcount(v);
361#else
362 while (v)
363 {
364 ++c;
365 v &= v - 1;
366 }
367#endif
368 }
369 return c;
370 }
371
373 unsigned highest() const
374 {
375 unsigned res = (N-1)*8*sizeof(word_t);
376 unsigned i = N;
377 while (i--)
378 {
379 auto v = data[i];
380 if (v == 0)
381 {
382 res -= CHAR_BIT*sizeof(word_t);
383 continue;
384 }
385 return res + CHAR_BIT*sizeof(word_t) - clz(v) - 1;
386 }
387 return 0;
388 }
389
391 unsigned lowest() const
392 {
393 unsigned res = 0U;
394 for (auto v: data)
395 {
396 if (v == 0)
397 {
398 res += 8*sizeof(v);
399 continue;
400 }
401#ifdef __GNUC__
402 res += __builtin_ctz(v);
403#else
404 while ((v & 1) == 0)
405 {
406 ++res;
407 v >>= 1;
408 }
409#endif
410 return res;
411 }
412 return 0;
413 }
414 };
415
416}
417
418namespace std
419{
421 template<size_t N>
422 struct hash<spot::bitset<N>>
423 {
425 size_t operator()(const spot::bitset<N>& b) const
426 {
427 return b.hash();
428 }
429 };
430}
A fixed-size bitset backed by N unsigned words.
Definition bitset.hh:40
static bitset mone()
the -1 (all bits are set to 1)
Definition bitset.hh:71
size_t hash() const
Return a hash of the bitset.
Definition bitset.hh:83
bitset operator|(const bitset &other) const
Return the bitwise OR of *this and other.
Definition bitset.hh:277
bitset & operator-=(word_t s)
Subtract s from the bitset in place.
Definition bitset.hh:322
bool operator<(const bitset &other) const
Lexicographic less-than comparison.
Definition bitset.hh:105
bitset operator>>(unsigned s) const
Return the bitset shifted right by s positions.
Definition bitset.hh:170
bool operator!=(const bitset &other) const
Inequality comparison.
Definition bitset.hh:99
void set(unsigned s)
Set bit s to one.
Definition bitset.hh:139
static constexpr bitset zero()
the 0
Definition bitset.hh:67
bitset operator-(word_t s) const
Return the result of subtracting s from the bitset.
Definition bitset.hh:315
bitset & operator|=(const bitset &other)
In-place bitwise OR with other.
Definition bitset.hh:300
unsigned highest() const
Return the position of the highest set bit.
Definition bitset.hh:373
bitset & operator>>=(unsigned s)
Shift right in place by s positions.
Definition bitset.hh:219
bool operator>(const bitset &other) const
Lexicographic greater-than comparison.
Definition bitset.hh:127
bool operator==(const bitset &other) const
Equality comparison.
Definition bitset.hh:89
unsigned count() const
Return the number of set bits (popcount).
Definition bitset.hh:354
bitset & operator<<=(unsigned s)
Shift left in place by s positions.
Definition bitset.hh:178
bool operator<=(const bitset &other) const
Lexicographic less-than-or-equal comparison.
Definition bitset.hh:116
bitset operator-() const
Return the arithmetic negation (two's complement).
Definition bitset.hh:340
bool operator>=(const bitset &other) const
Lexicographic greater-than-or-equal comparison.
Definition bitset.hh:133
bitset operator&(const bitset &other) const
Return the bitwise AND of *this and other.
Definition bitset.hh:269
bitset operator^(const bitset &other) const
Return the bitwise XOR of *this and other.
Definition bitset.hh:285
bitset operator<<(unsigned s) const
Return the bitset shifted left by s positions.
Definition bitset.hh:163
static constexpr bitset one()
the 1
Definition bitset.hh:69
unsigned lowest() const
Return the position of the lowest set bit.
Definition bitset.hh:391
bitset & operator^=(const bitset &other)
In-place bitwise XOR with other.
Definition bitset.hh:307
bitset & operator&=(const bitset &other)
In-place bitwise AND with other.
Definition bitset.hh:293
void clear(unsigned s)
Clear bit s (set it to zero).
Definition bitset.hh:151
bitset operator~() const
Return the bitwise complement.
Definition bitset.hh:260
size_t fnv_hash(It begin, It end)
Fowler-Noll-Vo hash function.
Definition hashfunc.hh:95
constexpr unsigned clz(Type n) noexcept
Count leading zeros of an unsigned integer.
Definition clz.hh:31
@ U
until
Definition automata.hh:26
constexpr bool operator==(trival a, trival b)
Equality comparison of two trival values.
Definition trival.hh:134
size_t operator()(const spot::bitset< N > &b) const
Compute the hash of b.
Definition bitset.hh:425

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Feb 27 2015 10:00:07 for spot by doxygen 1.9.8