21 using size_type = std::uint64_t;
22 using block_type = std::uint64_t;
23 static constexpr size_type bits_per_block =
24 std::numeric_limits<block_type>::digits;
35 m_blocks.resize(1, 0);
38 m_num_bits = std::numeric_limits<size_type>::digits - clzll(value);
39 m_blocks.resize((m_num_bits + bits_per_block - 1) / bits_per_block);
45 size_type size()
const {
50 std::fill(m_blocks.begin(), m_blocks.end(), 0);
53 void resize(size_type nbits) {
55 m_blocks.resize((nbits + bits_per_block - 1) / bits_per_block);
60 if (exclude_mask.size() > size()) {
61 resize(exclude_mask.size());
62 }
else if (size() > exclude_mask.size()) {
63 exclude_mask.resize(size());
66 for (size_type i = 0; i < m_blocks.size(); ++i) {
67 m_blocks[i] &= ~exclude_mask.m_blocks[i];
75 size_type min_blocks = std::min(m_blocks.size(), rhs.m_blocks.size());
76 for (size_type i = 0; i < min_blocks; ++i) {
77 m_blocks[i] &= rhs.m_blocks[i];
80 if (m_blocks.size() > rhs.m_blocks.size()) {
81 std::fill(m_blocks.begin() + min_blocks, m_blocks.end(), 0);
89 if (rhs.m_num_bits > m_num_bits) {
90 resize(rhs.m_num_bits);
92 for (size_type i = 0; i < rhs.m_blocks.size(); ++i) {
93 m_blocks[i] |= rhs.m_blocks[i];
101 if (rhs.m_num_bits > m_num_bits) {
102 resize(rhs.m_num_bits);
104 for (size_type i = 0; i < rhs.m_blocks.size(); ++i) {
105 m_blocks[i] ^= rhs.m_blocks[i];
114 for (
auto& block : result.m_blocks) {
117 result.zero_unused_bits();
123 if (shift >= m_num_bits) {
125 std::fill(m_blocks.begin(), m_blocks.end(), 0);
129 size_type block_shift = shift / bits_per_block;
130 size_type bit_shift = shift % bits_per_block;
131 size_type inv_bit_shift = bits_per_block - bit_shift;
133 if (block_shift != 0) {
134 for (size_type i = m_blocks.size(); i-- > block_shift;) {
135 m_blocks[i] = m_blocks[i - block_shift];
137 std::fill(m_blocks.begin(), m_blocks.begin() + block_shift, 0);
140 if (bit_shift != 0) {
141 block_type carry = 0;
142 for (size_type i = block_shift; i < m_blocks.size(); ++i) {
143 block_type temp = m_blocks[i];
144 m_blocks[i] = (temp << bit_shift) | carry;
145 carry = temp >> inv_bit_shift;
154 if (shift >= m_num_bits) {
156 std::fill(m_blocks.begin(), m_blocks.end(), 0);
160 size_type block_shift = shift / bits_per_block;
161 size_type bit_shift = shift % bits_per_block;
162 size_type inv_bit_shift = bits_per_block - bit_shift;
164 if (block_shift != 0) {
165 for (size_type i = 0; i < m_blocks.size() - block_shift; ++i) {
166 m_blocks[i] = m_blocks[i + block_shift];
168 std::fill(m_blocks.end() - block_shift, m_blocks.end(), 0);
171 if (bit_shift != 0) {
172 block_type carry = 0;
173 for (size_type i = m_blocks.size(); i-- > 0;) {
174 block_type temp = m_blocks[i];
175 m_blocks[i] = (temp >> bit_shift) | carry;
176 carry = temp << inv_bit_shift;
213 bool operator[](size_type pos)
const {
214 if (pos >= m_num_bits) {
217 size_type block_index = pos / bits_per_block;
218 size_type bit_index = pos % bits_per_block;
219 return (m_blocks[block_index] & (block_type(1) << bit_index)) != 0;
223 void set(size_type pos,
bool value =
true) {
224 if (pos >= m_num_bits) {
227 size_type block_index = pos / bits_per_block;
228 size_type bit_index = pos % bits_per_block;
230 m_blocks[block_index] |= (block_type(1) << bit_index);
232 m_blocks[block_index] &= ~(block_type(1) << bit_index);
237 void reset(size_type pos) {
242 void flip(size_type pos) {
243 if (pos >= m_num_bits) {
246 size_type block_index = pos / bits_per_block;
247 size_type bit_index = pos % bits_per_block;
248 m_blocks[block_index] ^= (block_type(1) << bit_index);
253 if (m_num_bits != rhs.m_num_bits) {
256 return m_blocks == rhs.m_blocks;
260 return !(*
this == rhs);
264 size_type count()
const {
266 for (
const auto& block : m_blocks) {
267 cnt += popcount(block);
274 for (
const auto& m_block : m_blocks) {
289 for (
size_t i = 0; i < other.size(); ++i) {
290 if (other.test(i) && !this->test(i)) {
298 bool test(size_type pos)
const {
299 return operator[](pos);
302 std::string to_string()
const {
303 std::string result(m_num_bits,
'0');
305 for (size_type i = 0; i < m_num_bits; ++i) {
307 result[m_num_bits - 1 - i] =
'1';
314 std::vector<block_type> m_blocks;
315 size_t m_num_bits {0};
317 void zero_unused_bits() {
320 size_type unused_bits = bits_per_block - (m_num_bits % bits_per_block);
321 if (unused_bits != bits_per_block) {
322 m_blocks.back() &= (block_type(~0) >> unused_bits);
327 inline static int clzll(
unsigned long long value) {
329 return _BitScanReverse64(&index, value) ? (63 - index) : 64;
332 inline static int clzll(
unsigned long long value) {
333 return value == 0 ? 64 : __builtin_clzll(value);
337 static size_type popcount(block_type x) {
338#if defined(__GNUC__) || defined(__clang__)
339 if constexpr (
sizeof(block_type) <=
sizeof(
unsigned int))
340 return __builtin_popcount(x);
341 else if constexpr (
sizeof(block_type) <=
sizeof(
unsigned long))
342 return __builtin_popcountl(x);
343 else if constexpr (
sizeof(block_type) <=
sizeof(
unsigned long long))
344 return __builtin_popcountll(x);
354#elif defined(_MSC_VER)
355 if constexpr (
sizeof(block_type) ==
sizeof(
unsigned int))
356 return __popcnt(
static_cast<unsigned int>(x));
357 else if constexpr (
sizeof(block_type) ==
sizeof(
unsigned long long))
358 return __popcnt64(
static_cast<unsigned long long>(x));