21 #ifndef BM_BM_SIM_DYNAMIC_BITSET_H_
22 #define BM_BM_SIM_DYNAMIC_BITSET_H_
32 inline int find_lowest_bit(T v);
35 inline int find_lowest_bit<uint32_t>(uint32_t v) {
36 static const int kMultiplyDeBruijnBitPosition[32] = {
37 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
38 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
40 return kMultiplyDeBruijnBitPosition[((v & -v) * 0x077CB531U) >> 27];
44 inline int find_lowest_bit<uint64_t>(uint64_t v) {
45 auto sw =
static_cast<uint32_t
>(v & 0xFFFFFFFF);
47 32 + find_lowest_bit<uint32_t>(
static_cast<uint32_t
>(v >> 32)) :
48 find_lowest_bit<uint32_t>(sw);
53 using Block =
unsigned long;
54 using Backend = std::vector<Block>;
55 using size_type = Backend::size_type;
57 static constexpr size_type npos =
static_cast<size_type
>(-1);
59 size_type size()
const {
63 size_type count()
const {
67 bool test(size_type idx)
const {
68 assert(idx < num_bits);
69 auto word_idx =
static_cast<size_type
>(idx / block_width);
70 auto bit_idx =
static_cast<int>(idx % block_width);
71 return words[word_idx] &
static_cast<Block
>(1) << bit_idx;
74 bool set(size_type idx) {
75 assert(idx < num_bits);
76 auto word_idx =
static_cast<size_type
>(idx / block_width);
77 auto bit_idx =
static_cast<int>(idx % block_width);
78 auto mask =
static_cast<Block
>(1) << bit_idx;
79 auto bit = words[word_idx] & mask;
80 words[word_idx] |= mask;
81 num_bits_set += (bit >> bit_idx) ^ 1;
85 bool reset(size_type idx) {
86 assert(idx < num_bits);
87 auto word_idx =
static_cast<size_type
>(idx / block_width);
88 auto bit_idx =
static_cast<int>(idx % block_width);
89 auto mask =
static_cast<Block
>(1) << bit_idx;
90 auto bit = words[word_idx] & mask;
91 words[word_idx] &= ~mask;
92 num_bits_set -= (bit >> bit_idx);
96 void push_back(
bool v) {
97 auto bit_idx =
static_cast<int>(num_bits % block_width);
98 if (bit_idx == 0) words.push_back(0);
100 if (v) set(num_bits - 1);
109 size_type find_first()
const {
110 return find_from_block(0);
113 size_type find_next(size_type idx)
const {
115 if (idx >= num_bits)
return npos;
116 auto word_idx =
static_cast<size_type
>(idx / block_width);
117 auto bit_idx =
static_cast<int>(idx % block_width);
118 auto sw = words[word_idx] & (ones << bit_idx);
119 if (sw == 0)
return find_from_block(word_idx + 1);
120 return word_idx * block_width + find_lowest_bit(sw);
123 size_type find_unset_first()
const {
124 return find_unset_from_block(0);
127 size_type find_unset_next(size_type idx)
const {
129 if (idx >= num_bits)
return npos;
130 auto word_idx =
static_cast<size_type
>(idx / block_width);
131 auto bit_idx =
static_cast<int>(idx % block_width);
132 auto sw = words[word_idx] | ~(ones << bit_idx);
133 if (sw == ones)
return find_unset_from_block(word_idx + 1);
134 return word_idx * block_width + find_lowest_bit(~sw);
137 bool operator==(
const DynamicBitset &other)
const {
138 return (num_bits == other.num_bits) && (words == other.words);
141 bool operator!=(
const DynamicBitset &other)
const {
142 return !(*
this == other);
145 void resize(size_type new_num_bits) {
146 num_bits = new_num_bits;
147 words.resize((num_bits + block_width - 1) / block_width);
151 size_type find_from_block(size_type word_idx)
const {
152 for (size_type i = word_idx; i < words.size(); i++) {
153 if (words[i] == 0)
continue;
154 return i * block_width + find_lowest_bit(words[i]);
159 size_type find_unset_from_block(size_type word_idx)
const {
160 for (size_type i = word_idx; i < words.size(); i++) {
161 if (words[i] == ones)
continue;
162 return i * block_width + find_lowest_bit(~words[i]);
167 static constexpr size_type block_width = std::numeric_limits<Block>::digits;
168 static constexpr Block ones = ~static_cast<Block>(0);
170 size_type num_bits{0};
171 size_type num_bits_set{0};
176 #endif // BM_BM_SIM_DYNAMIC_BITSET_H_