13 #include "core/adt/id.h"
23 template<
typename T,
unsigned N = 8>
27 static constexpr uint64_t kBitsInBucket =
sizeof(uint64_t) * CHAR_BIT;
29 static constexpr uint64_t kBitsInChunk = kBitsInBucket * N;
36 for (
unsigned i = 0; i < N; ++i) {
43 const uint64_t bucket = bit / kBitsInBucket;
44 const uint64_t mask = 1ull << (bit - bucket * kBitsInBucket);
45 const uint64_t val = arr[bucket];
46 const bool inserted = !(val & mask);
47 arr[bucket] = val | mask;
53 uint64_t bucket = bit / kBitsInBucket;
54 const uint64_t mask = 1ull << (bit - bucket * kBitsInBucket);
55 return arr[bucket] & mask;
58 bool Erase(
unsigned bit)
60 const uint64_t bucket = bit / kBitsInBucket;
62 arr[bucket] &= ~(1ull << (bit - bucket * kBitsInBucket));
64 for (
unsigned i = 0; i < N; ++i) {
75 for (
unsigned i = 0; i < N; ++i) {
76 size += __builtin_popcountll(arr[i]);
83 for (
unsigned i = 0; i < N; ++i) {
84 if (arr[i] != that.arr[i]) {
91 unsigned Union(
const Node &that)
94 for (
unsigned i = 0; i < N; ++i) {
95 uint64_t old = arr[i];
96 arr[i] |= that.arr[i];
97 changed += __builtin_popcountll(old ^ arr[i]);
105 for (
unsigned i = 0; i < N; ++i) {
106 arr[i] = arr[i] & ~that.arr[i];
107 zero = zero && (arr[i] == 0);
112 bool And(
const Node &that)
115 for (
unsigned i = 0; i < N; ++i) {
116 arr[i] = arr[i] & that.arr[i];
117 zero = zero && (arr[i] == 0);
122 unsigned Next(
unsigned bit)
const
124 const unsigned bucket = bit / kBitsInBucket;
125 const unsigned offset = bit - bucket * kBitsInBucket;
128 if (offset + 1 == kBitsInBucket) {
131 mask = arr[bucket] & ~((1ull << (offset + 1)) - 1);
135 return bucket * kBitsInBucket + __builtin_ctzll(mask);
137 for (
unsigned i = bucket + 1; i < N; ++i) {
139 return i * kBitsInBucket + __builtin_ctzll(arr[i]);
146 unsigned First()
const
148 for (
unsigned i = 0; i < N; ++i) {
150 return i * kBitsInBucket + __builtin_ctzll(arr[i]);
156 unsigned Prev(
unsigned bit)
const
158 const unsigned bucket = bit / kBitsInBucket;
159 const unsigned offset = bit - bucket * kBitsInBucket;
165 mask = arr[bucket] & ((1ull << offset) - 1);
169 return (bucket + 1) * kBitsInBucket - __builtin_clzll(mask) - 1;
171 for (
int i = bucket - 1; i >= 0; --i) {
173 return (i + 1) * kBitsInBucket - __builtin_clzll(arr[i]) - 1;
180 unsigned Last()
const
182 for (
int i = N - 1; i >= 0; --i) {
184 return (i + 1) * kBitsInBucket - __builtin_clzll(arr[i]) - 1;
195 using NodeIt =
typename std::map<uint32_t, Node>::const_iterator;
204 , current_(that.current_)
210 , it_(set.nodes_.find(current / kBitsInChunk))
219 current_ = that.current_;
223 ID<T> operator*()
const
237 if (current_ == set_->last_) {
238 current_ = set_->last_ + 1;
240 unsigned currPos = current_ & (kBitsInChunk - 1);
241 unsigned nextPos = it_->second.Next(currPos);
244 current_ = it_->first * kBitsInChunk + it_->second.First();
246 current_ = it_->first * kBitsInChunk + nextPos;
252 bool operator == (
const iterator &that)
const
254 return current_ == that.current_;
257 bool operator != (
const iterator &that)
const
259 return !(*
this == that);
277 , current_(that.current_)
283 , it_(set.nodes_.find(current / kBitsInChunk))
288 ID<T> operator * ()
const
302 if (current_ == set_.first_) {
303 current_ = set_.first_ - 1;
305 unsigned currPos = current_ & (kBitsInChunk - 1);
306 unsigned nextPos = it_->second.Prev(currPos);
307 if (nextPos == kBitsInChunk) {
309 current_ = it_->first * kBitsInChunk + it_->second.Last();
311 current_ = it_->first * kBitsInChunk + nextPos;
319 return current_ == that.current_;
324 return !(*
this == that);
338 : first_(std::numeric_limits<uint32_t>::max())
339 , last_(std::numeric_limits<uint32_t>::min())
358 return Empty() ?
end() : iterator(*
this, first_);
364 return iterator(*
this,
static_cast<int64_t
>(last_) + 1ull);
370 return Empty() ?
rend() : reverse_iterator(*
this, last_);
376 return reverse_iterator(*
this,
static_cast<int64_t
>(first_) - 1ull);
380 bool Empty()
const {
return nodes_.empty(); }
385 first_ = std::numeric_limits<uint32_t>::max();
386 last_ = std::numeric_limits<uint32_t>::min();
393 first_ = std::min(first_,
static_cast<uint32_t
>(item));
394 last_ = std::max(last_,
static_cast<uint32_t
>(item));
396 auto &node = nodes_[item / kBitsInChunk];
397 return node.Insert(item - (item / kBitsInChunk) * kBitsInChunk);
403 if (item == first_ && item == last_) {
404 first_ = std::numeric_limits<uint32_t>::max();
405 last_ = std::numeric_limits<uint32_t>::min();
406 }
else if (item == first_) {
408 }
else if (item == last_) {
412 auto &node = nodes_[item / kBitsInChunk];
413 if (node.Erase(item - (item / kBitsInChunk) * kBitsInChunk)) {
414 nodes_.erase(item / kBitsInChunk);
421 if (item < first_ || last_ < item) {
424 auto it = nodes_.find(item / kBitsInChunk);
425 if (it == nodes_.end()) {
428 return it->second.Contains(item - (item / kBitsInChunk) * kBitsInChunk);
436 unsigned changed = 0;
438 for (
auto &thatNode : that.nodes_) {
439 changed += nodes_[thatNode.first].Union(thatNode.second);
442 first_ = std::min(first_, that.first_);
443 last_ = std::max(last_, that.last_);
451 auto it = nodes_.begin();
452 auto tt = that.nodes_.begin();
453 while (it != nodes_.end() && tt != that.nodes_.end()) {
455 while (it != nodes_.end() && it->first < tt->first) {
458 if (it == nodes_.end()) {
461 while (tt != that.nodes_.end() && tt->first < it->first) {
464 if (tt == that.nodes_.end()) {
469 if (it->first == tt->first) {
470 if (it->second.Subtract(tt->second)) {
484 auto it = nodes_.begin();
485 auto tt = that.nodes_.begin();
486 while (it != nodes_.end() && tt != that.nodes_.end()) {
488 while (it != nodes_.end() && it->first < tt->first) {
491 if (it == nodes_.end()) {
494 while (tt != that.nodes_.end() && tt->first < it->first) {
497 if (tt == that.nodes_.end()) {
502 if (it->first == tt->first) {
503 if (it->second.And(tt->second)) {
519 for (
auto &[
id, node] : nodes_) {
528 if (first_ != that.first_) {
531 if (last_ != that.last_) {
535 if (nodes_.size() != that.nodes_.size()) {
540 nodes_.begin(), nodes_.end(),
541 that.nodes_.begin(), that.nodes_.end()
584 void ResetFirstLast()
586 if (nodes_.empty()) {
587 first_ = std::numeric_limits<uint32_t>::max();
588 last_ = std::numeric_limits<uint32_t>::min();
590 auto &[fi, fo] = *nodes_.begin();
591 auto &[li, lo] = *nodes_.rbegin();
592 first_ = fi * kBitsInChunk + fo.First();
593 last_ = li * kBitsInChunk + lo.Last();
603 std::map<uint32_t, Node> nodes_;
607 template <
typename T>
608 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
const BitSet<T> &s)