21 #include <spot/misc/common.hh>
54 bitvect(
size_t size,
size_t block_count);
55 bitvect(
size_t size,
size_t block_count,
bool);
63 storage_(&local_storage_),
72 storage_(&local_storage_)
80 void operator delete(
void *ptr)
83 ::operator
delete(ptr);
95 reserve_blocks(other.block_count_);
97 for (
size_t i = 0; i < block_count_; ++i)
98 storage_[i] = other.storage_[i];
104 if (storage_ != &local_storage_)
113 if (new_block_count < block_count_)
115 if (storage_ == &local_storage_)
118 (malloc(new_block_count *
sizeof(
block_t)));
119 if (SPOT_UNLIKELY(!new_storage))
120 throw std::bad_alloc();
121 for (
size_t i = 0; i < block_count_; ++i)
122 new_storage[i] = storage_[i];
123 storage_ = new_storage;
128 (realloc(storage_, new_block_count *
sizeof(
block_t)));
129 if (SPOT_UNLIKELY(!new_storage))
131 throw std::bad_alloc();
132 storage_ = new_storage;
134 block_count_ = new_block_count;
140 size_t new_block_count = (block_count_ + 1) * 7 / 5;
141 reserve_blocks(new_block_count);
149 const size_t bpb = 8 *
sizeof(
block_t);
150 return (size_ + bpb - 1) / bpb;
162 return 8 * block_count_ *
sizeof(
block_t);
169 bool get(
size_t pos)
const
171 SPOT_ASSERT(pos < size_);
172 const size_t bpb = 8 *
sizeof(
block_t);
173 return storage_[pos / bpb] & (1UL << (pos % bpb));
179 for (
size_t i = 0; i < block_count_; ++i)
188 size_t rest = size() % bpb;
189 for (i = 0; i < block_count_ - !!rest; ++i)
190 if (storage_[i] != 0)
196 block_t mask = (1UL << rest) - 1;
197 return (storage_[i] & mask) == 0;
205 size_t rest = size() % bpb;
206 for (i = 0; i < block_count_ - !!rest; ++i)
207 if (storage_[i] != -1UL)
213 block_t mask = (1UL << rest) - 1;
214 return ((~storage_[i]) & mask) == 0;
220 for (
size_t i = 0; i < block_count_; ++i)
227 for (
size_t i = 0; i < block_count_; ++i)
228 storage_[i] = ~storage_[i];
234 SPOT_ASSERT(pos < size_);
235 const size_t bpb = 8 *
sizeof(
block_t);
236 storage_[pos / bpb] |= 1UL << (pos % bpb);
242 SPOT_ASSERT(pos < size_);
243 const size_t bpb = 8 *
sizeof(
block_t);
244 storage_[pos / bpb] &= ~(1UL << (pos % bpb));
250 SPOT_ASSERT(pos < size_);
251 const size_t bpb = 8 *
sizeof(
block_t);
252 storage_[pos / bpb] ^= (1UL << (pos % bpb));
259 SPOT_ASSERT(other.size_ <= size_);
260 unsigned m = std::min(other.block_count_, block_count_);
261 for (
size_t i = 0; i < m; ++i)
262 storage_[i] |= other.storage_[i];
269 SPOT_ASSERT(other.size_ <= size_);
270 unsigned m = std::min(other.block_count_, block_count_);
271 for (
size_t i = 0; i < m; ++i)
272 storage_[i] &= other.storage_[i];
279 SPOT_ASSERT(other1.size_ <= size_ && other2.size_ <= size_);
280 unsigned m = std::min(other2.block_count_,
281 std::min(other1.block_count_, block_count_));
282 for (
size_t i = 0; i < m; ++i)
283 storage_[i] |= other1.storage_[i] & other2.storage_[i];
290 SPOT_ASSERT(other.size_ <= size_);
291 unsigned m = std::min(other.block_count_, block_count_);
292 for (
size_t i = 0; i < m; ++i)
293 if (storage_[i] & other.storage_[i])
301 SPOT_ASSERT(other.size_ <= size_);
302 unsigned m = std::min(other.block_count_, block_count_);
303 for (
size_t i = 0; i < m; ++i)
304 storage_[i] ^= other.storage_[i];
311 SPOT_ASSERT(other.block_count_ <= block_count_);
312 for (
size_t i = 0; i < other.block_count_; ++i)
313 storage_[i] &= ~other.storage_[i];
320 SPOT_ASSERT(other.block_count_ >= block_count_);
324 size_t rest = size() % bpb;
325 for (i = 0; i < block_count_ - !!rest; ++i)
326 if ((storage_[i] & other.storage_[i]) != storage_[i])
333 block_t mask = (1UL << rest) - 1;
334 return ((storage_[i] & mask & other.storage_[i])
335 == (storage_[i] & mask));
343 size_t rest = size() % bpb;
345 for (i = 0; i < block_count_; ++i)
348 if ((i == block_count_ - 1) && rest)
351 v &= (1UL << rest) - 1;
353 c += __builtin_popcountl(v);
368 if (other.size_ != size_)
375 size_t rest = size() % bpb;
376 for (i = 0; i < m - !!rest; ++i)
377 if (storage_[i] != other.storage_[i])
383 block_t mask = (1UL << rest) - 1;
384 return (storage_[i] & mask) == (other.storage_[i] & mask);
390 return !(*
this == other);
396 if (size_ != other.size_)
397 return size_ < other.size_;
403 size_t rest = size() % bpb;
404 for (i = 0; i < m - !!rest; ++i)
405 if (storage_[i] > other.storage_[i])
411 block_t mask = (1UL << rest) - 1;
412 return (storage_[i] & mask) < (other.storage_[i] & mask);
418 return !(*
this < other);
424 return other < *
this;
430 return !(other < *
this);
438 size_t rest = size() % bpb;
439 for (
size_t i = 0; i <= block_count_ - 1; ++i)
442 if ((i == block_count_ - 1) && rest)
445 b &= (1UL << rest) - 1;
448 unsigned base = i * bpb;
453 unsigned bit = __builtin_ctzl(b);
455 callback(base + bit);
463 callback(base + bit);
509 return reinterpret_cast<char*
>(
this) +
sizeof(*
this);
512 const char* storage()
const
514 return reinterpret_cast<const char*
>(
this) +
sizeof(*
this);
520 for (
size_t i = 0; i < size_; ++i)
525 void operator delete(
void *ptr)
528 ::operator
delete(ptr);
542 for (
unsigned s = 0; s < size_; s++)
549 SPOT_ASSERT(index < size_);
553 auto v =
static_cast<void*
>(storage() + index * bvsize_);
554 return *
static_cast<bitvect*
>(v);
560 SPOT_ASSERT(index < size_);
561 auto v =
static_cast<const void*
>(storage() + index * bvsize_);
562 return *
static_cast<const bitvect*
>(v);
An array of fixed-size bit vectors allocated contiguously.
Definition: bitvect.hh:494
friend std::ostream & operator<<(std::ostream &, const bitvect_array &)
Print a bitvect_array.
bitvect & at(const size_t index)
Return the bit-vector at index.
Definition: bitvect.hh:547
void clear_all()
Clear all bits in all vectors of the array.
Definition: bitvect.hh:538
friend bitvect_array * make_bitvect_array(size_t bitcount, size_t vectcount)
Allocate vectcount bit-vectors of bitcount bits.
const bitvect & at(const size_t index) const
Return the bit-vector at index.
Definition: bitvect.hh:558
size_t size() const
The number of bitvect in the array.
Definition: bitvect.hh:532
A bit vector.
Definition: bitvect.hh:51
bitvect & operator-=(const bitvect &other)
Clear in *this the bits that are set in other.
Definition: bitvect.hh:309
friend bitvect * make_bitvect(size_t bitcount)
Allocate a bit-vector of bitcount bits.
bool operator<=(const bitvect &other) const
Lexicographic less-than-or-equal comparison.
Definition: bitvect.hh:428
void reserve_blocks(size_t new_block_count)
Definition: bitvect.hh:111
bool is_fully_set() const
Return true iff all bits are set to one.
Definition: bitvect.hh:201
friend std::ostream & operator<<(std::ostream &, const bitvect &)
Print a bitvect.
void set(size_t pos)
Set bit at position pos to one.
Definition: bitvect.hh:232
bool is_fully_clear() const
Return true iff all bits are zero.
Definition: bitvect.hh:184
friend bitvect_array * make_bitvect_array(size_t bitcount, size_t vectcount)
Allocate vectcount bit-vectors of bitcount bits.
bool intersects(const bitvect &other)
Return true if *this and other share any set bit.
Definition: bitvect.hh:288
void make_empty()
Reset the size to zero without freeing storage.
Definition: bitvect.hh:87
bool operator==(const bitvect &other) const
Equality comparison.
Definition: bitvect.hh:366
unsigned long block_t
Storage block type.
Definition: bitvect.hh:58
bool is_subset_of(const bitvect &other) const
Return true if every set bit of *this is also set in other.
Definition: bitvect.hh:318
bitvect & add_common(const bitvect &other1, const bitvect &other2)
OR into *this the bits common to other1 and other2.
Definition: bitvect.hh:277
bitvect * clone() const
Return a heap-allocated copy.
void set_all()
Set all bits to one.
Definition: bitvect.hh:218
bool operator>(const bitvect &other) const
Lexicographic greater-than comparison.
Definition: bitvect.hh:422
void foreach_set_index(F callback) const
Call callback with the index of each set bit.
Definition: bitvect.hh:435
size_t hash() const noexcept
Return a hash of the bit vector.
bitvect & operator=(const bitvect &other)
Copy-assignment operator.
Definition: bitvect.hh:93
size_t capacity() const
Return the maximum number of bits the storage can hold.
Definition: bitvect.hh:160
bitvect & operator&=(const bitvect &other)
In-place bitwise AND with other.
Definition: bitvect.hh:267
bitvect & operator|=(const bitvect &other)
In-place bitwise OR with other.
Definition: bitvect.hh:257
void clear(size_t pos)
Clear bit at position pos (set it to zero).
Definition: bitvect.hh:240
size_t size() const
Return the number of bits in the vector.
Definition: bitvect.hh:154
size_t used_blocks() const
Return the number of blocks currently in use.
Definition: bitvect.hh:147
void clear_all()
Clear all bits (set them to zero).
Definition: bitvect.hh:177
void flip(size_t pos)
Flip the bit at position pos.
Definition: bitvect.hh:248
bool operator>=(const bitvect &other) const
Lexicographic greater-than-or-equal comparison.
Definition: bitvect.hh:416
bool operator!=(const bitvect &other) const
Inequality comparison.
Definition: bitvect.hh:388
bitvect & operator^=(const bitvect &other)
In-place bitwise XOR with other.
Definition: bitvect.hh:299
bitvect(const bitvect &other)
Copy constructor.
Definition: bitvect.hh:69
unsigned count() const
Return the number of set bits (popcount).
Definition: bitvect.hh:339
void flip_all()
Flip all bits.
Definition: bitvect.hh:225
bool operator<(const bitvect &other) const
Lexicographic less-than comparison.
Definition: bitvect.hh:394
Definition: automata.hh:26
bitvect_array * make_bitvect_array(size_t bitcount, size_t vectcount)
Allocate vectcount bit-vectors of bitcount bits.
bitvect * make_bitvect(size_t bitcount)
Allocate a bit-vector of bitcount bits.