125 uintptr_t word(
size_t i)
const {
return i < size ? size > 1 ? ptr[i] : data : 0; }
128 static constexpr size_t bits_per_unit = CHAR_BIT *
sizeof(uintptr_t);
136 bitref(T s,
int i) : self(s), idx(i) {}
139 bitref(
const bitref &a) =
default;
140 bitref(bitref &&a) =
default;
141 operator bool()
const {
return self.getbit(idx); }
142 bool operator==(
const bitref &a)
const {
return &self == &a.self && idx == a.idx; }
143 bool operator!=(
const bitref &a)
const {
return &self != &a.self || idx != a.idx; }
144 int index()
const {
return idx; }
145 int operator*()
const {
return idx; }
146 bitref &operator++() {
147 while ((
size_t)++idx < self.size * bitvec::bits_per_unit) {
149 self.word(idx / bitvec::bits_per_unit) >> (idx % bitvec::bits_per_unit)) {
150 idx += bv::count_trailing_zeroes(w);
153 idx = (idx / bitvec::bits_per_unit) * bitvec::bits_per_unit +
154 bitvec::bits_per_unit - 1;
159 bitref &operator--() {
160 if (idx < 0) idx = self.size * bitvec::bits_per_unit;
162 if (
auto w = self.word(idx / bitvec::bits_per_unit)
163 << (bitvec::bits_per_unit - 1 - idx % bitvec::bits_per_unit)) {
164 idx -= bv::count_leading_zeroes(w);
167 idx = (idx / bitvec::bits_per_unit) * bitvec::bits_per_unit;
182 bool operator=(
bool b)
const {
184 return b ? self.setbit(idx) : self.clrbit(idx);
186 bool set(
bool b =
true) {
188 bool rv = self.getbit(idx);
189 b ? self.setbit(idx) : self.clrbit(idx);
192 using difference_type = std::ptrdiff_t;
195 using reference =
const bool &;
196 using iterator_category = std::bidirectional_iterator_tag;
205 const_bitref(
const bitref<const bitvec &> &a) : bitref(a) {}
208 using difference_type = std::ptrdiff_t;
211 using reference =
const bool &;
212 using iterator_category = std::bidirectional_iterator_tag;
221 bitvec() : size(1), data(0) {}
222 explicit bitvec(uintptr_t v) : size(1), data(v) {}
223 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value &&
224 (
sizeof(T) >
sizeof(uintptr_t))>::type>
225 explicit bitvec(T v) : size(1), data(v) {
227 size =
sizeof(v) /
sizeof(data);
228 ptr =
new IF_HAVE_LIBGC((PointerFreeGC)) uintptr_t[size];
229 for (
unsigned i = 0; i < size; ++i) {
235 bitvec(
size_t lo,
size_t cnt) : size(1), data(0) { setrange(lo, cnt); }
238 ptr =
new IF_HAVE_LIBGC((PointerFreeGC)) uintptr_t[size];
239 memcpy(ptr, a.ptr, size *
sizeof(*ptr));
244 bitvec(
bitvec &&a) : size(a.size), data(a.data) { a.size = 1; }
246 if (
this == &a)
return *
this;
247 if (size > 1)
delete[] ptr;
248 if ((size = a.size) > 1) {
249 ptr =
new IF_HAVE_LIBGC((PointerFreeGC)) uintptr_t[size];
250 memcpy(ptr, a.ptr, size *
sizeof(*ptr));
257 std::swap(size, a.size);
258 std::swap(data, a.data);
262 if (size > 1)
delete[] ptr;
267 memset(ptr, 0, size *
sizeof(*ptr));
271 bool setbit(
size_t idx) {
272 if (idx >= size * bits_per_unit) expand(1 + idx / bits_per_unit);
274 ptr[idx / bits_per_unit] |= (uintptr_t)1 << (idx % bits_per_unit);
276 data |= (uintptr_t)1 << idx;
279 void setrange(
size_t idx,
size_t sz) {
281 if (idx + sz > size * bits_per_unit) expand(1 + (idx + sz - 1) / bits_per_unit);
283 data |= ~(~(uintptr_t)1 << (sz - 1)) << idx;
284 }
else if (idx / bits_per_unit == (idx + sz - 1) / bits_per_unit) {
285 ptr[idx / bits_per_unit] |= ~(~(uintptr_t)1 << (sz - 1)) << (idx % bits_per_unit);
287 size_t i = idx / bits_per_unit;
288 ptr[i] |= ~(uintptr_t)0 << (idx % bits_per_unit);
290 while (++i < idx / bits_per_unit) {
291 ptr[i] = ~(uintptr_t)0;
293 if (i < size) ptr[i] |= (((uintptr_t)1 << (idx % bits_per_unit)) - 1);
296 void setraw(uintptr_t raw) {
301 for (
size_t i = 1; i < size; i++) ptr[i] = 0;
304 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value &&
305 (
sizeof(T) >
sizeof(uintptr_t))>::type>
307 if (
sizeof(T) /
sizeof(uintptr_t) > size) expand(
sizeof(T) /
sizeof(uintptr_t));
308 for (
size_t i = 0; i < size; i++) {
310 raw >>= bits_per_unit;
313 void setraw(uintptr_t *raw,
size_t sz) {
314 if (sz > size) expand(sz);
318 for (
size_t i = 0; i < sz; i++) ptr[i] = raw[i];
319 for (
size_t i = sz; i < size; i++) ptr[i] = 0;
322 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value &&
323 (
sizeof(T) >
sizeof(uintptr_t))>::type>
324 void setraw(T *raw,
size_t sz) {
325 constexpr size_t m =
sizeof(T) /
sizeof(uintptr_t);
326 if (m * sz > size) expand(m * sz);
328 for (; i < sz * m; ++i) ptr[i] = raw[i / m] >> ((i % m) * bits_per_unit);
329 for (; i < size; ++i) ptr[i] = 0;
331 bool clrbit(
size_t idx) {
332 if (idx >= size * bits_per_unit)
return false;
334 ptr[idx / bits_per_unit] &= ~((uintptr_t)1 << (idx % bits_per_unit));
336 data &= ~((uintptr_t)1 << idx);
339 void clrrange(
size_t idx,
size_t sz) {
341 if (size < sz / bits_per_unit)
342 sz = size * bits_per_unit;
343 if (idx >= size * bits_per_unit)
return;
345 if (idx + sz < bits_per_unit)
346 data &= ~(~(~(uintptr_t)1 << (sz - 1)) << idx);
348 data &= ~(~(uintptr_t)0 << idx);
349 }
else if (idx / bits_per_unit == (idx + sz - 1) / bits_per_unit) {
350 ptr[idx / bits_per_unit] &= ~(~(~(uintptr_t)1 << (sz - 1)) << (idx % bits_per_unit));
352 size_t i = idx / bits_per_unit;
353 ptr[i] &= ~(~(uintptr_t)0 << (idx % bits_per_unit));
355 while (++i < idx / bits_per_unit && i < size) {
358 if (i < size) ptr[i] &= ~(((uintptr_t)1 << (idx % bits_per_unit)) - 1);
361 bool getbit(
size_t idx)
const {
362 return (word(idx / bits_per_unit) >> (idx % bits_per_unit)) & 1;
364 uintmax_t getrange(
size_t idx,
size_t sz)
const {
365 assert(sz > 0 && sz <= CHAR_BIT *
sizeof(uintmax_t));
366 if (idx >= size * bits_per_unit)
return 0;
368 unsigned shift = idx % bits_per_unit;
369 idx /= bits_per_unit;
370 uintmax_t rv = ptr[idx] >> shift;
371 shift = bits_per_unit - shift;
373 if (++idx >= size)
break;
374 rv |= (uintmax_t)ptr[idx] << shift;
375 shift += bits_per_unit;
377 return rv & ~(~(uintmax_t)1 << (sz - 1));
379 return (data >> idx) & ~(~(uintmax_t)1 << (sz - 1));
382 void putrange(
size_t idx,
size_t sz, uintmax_t v) {
383 assert(sz > 0 && sz <= CHAR_BIT *
sizeof(uintmax_t));
384 uintptr_t mask = ~(uintmax_t)0 >> (CHAR_BIT *
sizeof(uintmax_t) - sz);
386 if (idx + sz > size * bits_per_unit) expand(1 + (idx + sz - 1) / bits_per_unit);
388 data &= ~(mask << idx);
391 unsigned shift = idx % bits_per_unit;
392 idx /= bits_per_unit;
393 ptr[idx] &= ~(mask << shift);
394 ptr[idx] |= v << shift;
395 shift = bits_per_unit - shift;
397 assert(idx + 1 < size);
398 ptr[++idx] &= ~(mask >> shift);
399 ptr[idx] |= v >> shift;
400 shift += bits_per_unit;
404 bitvec getslice(
size_t idx,
size_t sz)
const;
405 nonconst_bitref operator[](
int idx) {
return nonconst_bitref(*
this, idx); }
406 bool operator[](
int idx)
const {
return getbit(idx); }
407 int ffs(
unsigned start = 0)
const;
408 unsigned ffz(
unsigned start = 0)
const;
409 const_bitref min() const & {
return const_bitref(*
this, ffs()); }
410 const_bitref max() const & {
return --const_bitref(*
this, size * bits_per_unit); }
411 const_bitref begin() const & {
return min(); }
412 const_bitref end() const & {
return const_bitref(*
this, -1); }
414 copy_bitref min() &&;
415 copy_bitref max() &&;
416 copy_bitref begin() &&;
417 copy_bitref end() &&;
418 nonconst_bitref min() & {
return nonconst_bitref(*
this, ffs()); }
419 nonconst_bitref max() & {
return --nonconst_bitref(*
this, size * bits_per_unit); }
420 nonconst_bitref begin() & {
return min(); }
421 nonconst_bitref end() & {
return nonconst_bitref(*
this, -1); }
423 for (
size_t i = 0; i < size; i++)
424 if (word(i) != 0)
return false;
427 explicit operator bool()
const {
return !empty(); }
428 bool operator&=(
const bitvec &a) {
432 for (
size_t i = 0; i < size && i < a.size; i++) {
433 rv |= ((ptr[i] & a.ptr[i]) != ptr[i]);
437 rv |= ((*ptr & a.data) != *ptr);
442 for (
size_t i = a.size; i < size; i++)
448 memset(ptr + a.size, 0, (size - a.size) *
sizeof(*ptr));
450 }
else if (a.size > 1) {
451 rv |= ((data & a.ptr[0]) != data);
454 rv |= ((data & a.data) != data);
460 if (size <= a.size) {
470 bool operator|=(
const bitvec &a) {
472 if (size < a.size) expand(a.size);
475 for (
size_t i = 0; i < a.size; i++) {
476 rv |= ((ptr[i] | a.ptr[i]) != ptr[i]);
480 rv |= ((*ptr | a.data) != *ptr);
484 rv |= ((data | a.data) != data);
489 bool operator|=(uintptr_t a) {
491 auto t = size > 1 ? ptr : &data;
492 rv |= ((*t | a) != *t);
496 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value &&
497 (
sizeof(T) >
sizeof(uintptr_t))>::type>
498 bool operator|=(T a) {
499 return (*
this) |=
bitvec(a);
506 bitvec operator|(uintptr_t a)
const {
511 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value &&
512 (
sizeof(T) >
sizeof(uintptr_t))>::type>
519 if (size < a.size) expand(a.size);
522 for (
size_t i = 0; i < a.size; i++) ptr[i] ^= a.ptr[i];
536 bool operator-=(
const bitvec &a) {
540 for (
size_t i = 0; i < size && i < a.size; i++) {
541 rv |= ((ptr[i] & ~a.ptr[i]) != ptr[i]);
545 rv |= ((*ptr & ~a.data) != *ptr);
548 }
else if (a.size > 1) {
549 rv |= ((data & ~a.ptr[0]) != data);
552 rv |= ((data & ~a.data) != data);
562 bool operator==(
const bitvec &a)
const {
563 for (
size_t i = 0; i < size || i < a.size; i++)
564 if (word(i) != a.word(i))
return false;
567 bool operator!=(
const bitvec &a)
const {
return !(*
this == a); }
568 bool operator<(
const bitvec &a)
const {
569 size_t i = std::max(size, a.size);
571 if (word(i) < a.word(i))
return true;
572 if (word(i) > a.word(i))
return false;
576 bool operator>(
const bitvec &a)
const {
return a < *
this; }
577 bool operator>=(
const bitvec &a)
const {
return !(*
this < a); }
578 bool operator<=(
const bitvec &a)
const {
return !(a < *
this); }
579 bool intersects(
const bitvec &a)
const {
580 for (
size_t i = 0; i < size && i < a.size; i++)
581 if (word(i) & a.word(i))
return true;
584 bool contains(
const bitvec &a)
const {
585 for (
size_t i = 0; i < size && i < a.size; i++)
586 if ((word(i) & a.word(i)) != a.word(i))
return false;
587 for (
size_t i = size; i < a.size; i++)
588 if (a.word(i))
return false;
591 bitvec &operator>>=(
size_t count);
592 bitvec &operator<<=(
size_t count);
593 bitvec operator>>(
size_t count)
const {
598 bitvec operator<<(
size_t count)
const {
603 void rotate_right(
size_t start_bit,
size_t rotation_idx,
size_t end_bit);
604 bitvec rotate_right_copy(
size_t start_bit,
size_t rotation_idx,
size_t end_bit)
const;
605 int popcount()
const {
607 for (
size_t i = 0; i < size; i++) rv += bv::popcount(word(i));
610 bool is_contiguous()
const;
613 void expand(
size_t newsize) {
614 assert(newsize > size);
615 if (
size_t m = newsize >> 3) {
622 newsize = (newsize + m) & ~m;
625 uintptr_t *old = ptr;
626 ptr =
new IF_HAVE_LIBGC((PointerFreeGC)) uintptr_t[newsize];
627 memcpy(ptr, old, size *
sizeof(*ptr));
628 memset(ptr + size, 0, (newsize - size) *
sizeof(*ptr));
632 ptr =
new IF_HAVE_LIBGC((PointerFreeGC)) uintptr_t[newsize];
634 memset(ptr + size, 0, (newsize - size) *
sizeof(*ptr));
639 bitvec rotate_right_helper(
size_t start_bit,
size_t rotation_idx,
size_t end_bit)
const;
642 friend std::ostream &operator<<(std::ostream &,
const bitvec &);
643 friend std::istream &operator>>(std::istream &,
bitvec &);
644 friend bool operator>>(
const char *,
bitvec &);