Add forEachInRange

This commit is contained in:
2024-02-25 21:04:39 -08:00
parent 0d3475e229
commit 9fcfc44dc3

View File

@@ -98,6 +98,61 @@ struct BitSet {
void reset(int i);
int firstSetGeq(int i) const;
// Calls `f` with the index of each bit set in [begin, end)
template <class F> void forEachInRange(F f, int begin, int end) {
// See section 3.1 in https://arxiv.org/pdf/1709.07821.pdf for details about
// this approach
if ((begin >> 6) == (end >> 6)) {
{
uint64_t word = words[begin >> 6] & (uint64_t(-1) << (begin & 63)) &
~(uint64_t(-1) << (end & 63));
while (word) {
uint64_t temp = word & -word;
int index = (begin & ~63) + std::countr_zero(word);
f(index);
word ^= temp;
}
}
return;
}
// Check begin partial word
{
uint64_t word = words[begin >> 6] & (uint64_t(-1) << (begin & 63));
while (word) {
uint64_t temp = word & -word;
int index = (begin & ~63) + std::countr_zero(word);
f(index);
word ^= temp;
}
}
// Check inner, full words
begin += 64;
while ((begin >> 6) != (end >> 6)) {
uint64_t word = words[begin >> 6];
while (word) {
uint64_t temp = word & -word;
int index = (begin & ~63) + std::countr_zero(word);
f(index);
word ^= temp;
}
begin += 64;
}
if (end < 256) {
// Check end partial word
uint64_t word = words[end >> 6] & ~(uint64_t(-1) << (end & 63));
while (word) {
uint64_t temp = word & -word;
int index = (begin & ~63) + std::countr_zero(word);
f(index);
word ^= temp;
}
}
}
private:
uint64_t words[4] = {};
};