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);
58 typedef unsigned long block_t;
63 storage_(&local_storage_),
71 storage_(&local_storage_)
78 void operator delete(
void *ptr)
81 ::operator
delete(ptr);
91 reserve_blocks(other.block_count_);
93 for (
size_t i = 0; i < block_count_; ++i)
94 storage_[i] = other.storage_[i];
100 if (storage_ != &local_storage_)
109 if (new_block_count < block_count_)
111 if (storage_ == &local_storage_)
113 block_t* new_storage =
static_cast<block_t*
>
114 (malloc(new_block_count *
sizeof(block_t)));
115 if (SPOT_UNLIKELY(!new_storage))
116 throw std::bad_alloc();
117 for (
size_t i = 0; i < block_count_; ++i)
118 new_storage[i] = storage_[i];
119 storage_ = new_storage;
123 block_t* new_storage =
static_cast<block_t*
>
124 (realloc(storage_, new_block_count *
sizeof(block_t)));
125 if (SPOT_UNLIKELY(!new_storage))
127 throw std::bad_alloc();
128 storage_ = new_storage;
130 block_count_ = new_block_count;
136 size_t new_block_count = (block_count_ + 1) * 7 / 5;
137 reserve_blocks(new_block_count);
142 size_t used_blocks()
const
144 const size_t bpb = 8 *
sizeof(block_t);
145 return (size_ + bpb - 1) / bpb;
153 size_t capacity()
const
155 return 8 * block_count_ *
sizeof(block_t);
158 size_t hash() const noexcept;
160 bool get(
size_t pos)
const
162 SPOT_ASSERT(pos < size_);
163 const size_t bpb = 8 *
sizeof(block_t);
164 return storage_[pos / bpb] & (1UL << (pos % bpb));
169 for (
size_t i = 0; i < block_count_; ++i)
173 bool is_fully_clear()
const
176 const size_t bpb = 8 *
sizeof(bitvect::block_t);
177 size_t rest = size() % bpb;
178 for (i = 0; i < block_count_ - !!rest; ++i)
179 if (storage_[i] != 0)
185 block_t mask = (1UL << rest) - 1;
186 return (storage_[i] & mask) == 0;
189 bool is_fully_set()
const
192 const size_t bpb = 8 *
sizeof(bitvect::block_t);
193 size_t rest = size() % bpb;
194 for (i = 0; i < block_count_ - !!rest; ++i)
195 if (storage_[i] != -1UL)
201 block_t mask = (1UL << rest) - 1;
202 return ((~storage_[i]) & mask) == 0;
207 for (
size_t i = 0; i < block_count_; ++i)
213 for (
size_t i = 0; i < block_count_; ++i)
214 storage_[i] = ~storage_[i];
219 SPOT_ASSERT(pos < size_);
220 const size_t bpb = 8 *
sizeof(block_t);
221 storage_[pos / bpb] |= 1UL << (pos % bpb);
224 void clear(
size_t pos)
226 SPOT_ASSERT(pos < size_);
227 const size_t bpb = 8 *
sizeof(block_t);
228 storage_[pos / bpb] &= ~(1UL << (pos % bpb));
231 void flip(
size_t pos)
233 SPOT_ASSERT(pos < size_);
234 const size_t bpb = 8 *
sizeof(block_t);
235 storage_[pos / bpb] ^= (1UL << (pos % bpb));
239 bitvect& operator|=(
const bitvect& other)
241 SPOT_ASSERT(other.size_ <= size_);
242 unsigned m = std::min(other.block_count_, block_count_);
243 for (
size_t i = 0; i < m; ++i)
244 storage_[i] |= other.storage_[i];
248 bitvect& operator&=(
const bitvect& other)
250 SPOT_ASSERT(other.size_ <= size_);
251 unsigned m = std::min(other.block_count_, block_count_);
252 for (
size_t i = 0; i < m; ++i)
253 storage_[i] &= other.storage_[i];
257 bitvect& add_common(
const bitvect& other1,
const bitvect& other2)
259 SPOT_ASSERT(other1.size_ <= size_ && other2.size_ <= size_);
260 unsigned m = std::min(other2.block_count_,
261 std::min(other1.block_count_, block_count_));
262 for (
size_t i = 0; i < m; ++i)
263 storage_[i] |= other1.storage_[i] & other2.storage_[i];
267 bool intersects(
const bitvect& other)
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 if (storage_[i] & other.storage_[i])
277 bitvect& operator^=(
const bitvect& other)
279 SPOT_ASSERT(other.size_ <= size_);
280 unsigned m = std::min(other.block_count_, block_count_);
281 for (
size_t i = 0; i < m; ++i)
282 storage_[i] ^= other.storage_[i];
286 bitvect& operator-=(
const bitvect& other)
288 SPOT_ASSERT(other.block_count_ <= block_count_);
289 for (
size_t i = 0; i < other.block_count_; ++i)
290 storage_[i] &= ~other.storage_[i];
294 bool is_subset_of(
const bitvect& other)
const
296 SPOT_ASSERT(other.block_count_ >= block_count_);
299 const size_t bpb = 8 *
sizeof(bitvect::block_t);
300 size_t rest = size() % bpb;
301 for (i = 0; i < block_count_ - !!rest; ++i)
302 if ((storage_[i] & other.storage_[i]) != storage_[i])
309 block_t mask = (1UL << rest) - 1;
310 return ((storage_[i] & mask & other.storage_[i])
311 == (storage_[i] & mask));
314 unsigned count()
const
317 const size_t bpb = 8 *
sizeof(bitvect::block_t);
318 size_t rest = size() % bpb;
320 for (i = 0; i < block_count_; ++i)
322 block_t v = storage_[i];
323 if ((i == block_count_ - 1) && rest)
326 v &= (1UL << rest) - 1;
328 c += __builtin_popcountl(v);
340 bool operator==(
const bitvect& other)
const
342 if (other.size_ != size_)
347 size_t m = other.used_blocks();
348 const size_t bpb = 8 *
sizeof(bitvect::block_t);
349 size_t rest = size() % bpb;
350 for (i = 0; i < m - !!rest; ++i)
351 if (storage_[i] != other.storage_[i])
357 block_t mask = (1UL << rest) - 1;
358 return (storage_[i] & mask) == (other.storage_[i] & mask);
361 bool operator!=(
const bitvect& other)
const
363 return !(*
this == other);
366 bool operator<(
const bitvect& other)
const
368 if (size_ != other.size_)
369 return size_ < other.size_;
373 size_t m = other.used_blocks();
374 const size_t bpb = 8 *
sizeof(bitvect::block_t);
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);
387 bool operator>=(
const bitvect& other)
const
389 return !(*
this < other);
392 bool operator>(
const bitvect& other)
const
394 return other < *
this;
397 bool operator<=(
const bitvect& other)
const
399 return !(other < *
this);
403 void foreach_set_index(F callback)
const
405 const size_t bpb = 8 *
sizeof(bitvect::block_t);
406 size_t rest = size() % bpb;
407 for (
size_t i = 0; i <= block_count_ - 1; ++i)
409 block_t b = storage_[i];
410 if ((i == block_count_ - 1) && rest)
413 b &= (1UL << rest) - 1;
416 unsigned base = i * bpb;
421 unsigned bit = __builtin_ctzl(b);
423 callback(base + bit);
431 callback(base + bit);
457 block_t local_storage_;
476 return reinterpret_cast<char*
>(
this) +
sizeof(*
this);
479 const char* storage()
const
481 return reinterpret_cast<const char*
>(
this) +
sizeof(*
this);
487 for (
size_t i = 0; i < size_; ++i)
491 void operator delete(
void *ptr)
494 ::operator
delete(ptr);
507 for (
unsigned s = 0; s < size_; s++)
514 SPOT_ASSERT(index < size_);
518 auto v =
static_cast<void*
>(storage() + index * bvsize_);
519 return *
static_cast<bitvect*
>(v);
525 SPOT_ASSERT(index < size_);
526 auto v =
static_cast<const void*
>(storage() + index * bvsize_);
527 return *
static_cast<const bitvect*
>(v);
Definition: bitvect.hh:461
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:523
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:512
size_t size() const
The number of bitvect in the array.
Definition: bitvect.hh:498
A bit vector.
Definition: bitvect.hh:51
friend bitvect_array * make_bitvect_array(size_t bitcount, size_t vectcount)
Allocate vectcount bit-vectors of bitcount bits.
void reserve_blocks(size_t new_block_count)
Definition: bitvect.hh:107
friend bitvect * make_bitvect(size_t bitcount)
Allocate a bit-vector of bitcount bits.
friend std::ostream & operator<<(std::ostream &, const bitvect &)
Print a bitvect.
Definition: automata.hh:26
bitvect * make_bitvect(size_t bitcount)
Allocate a bit-vector of bitcount bits.
bitvect_array * make_bitvect_array(size_t bitcount, size_t vectcount)
Allocate vectcount bit-vectors of bitcount bits.