1#ifndef ALGORITHMS_DYNAMIC_BITSET_H
2#define ALGORITHMS_DYNAMIC_BITSET_H
15namespace dynamic_bitset {
16template <
typename Block =
unsigned int>
19 !std::numeric_limits<Block>::is_signed,
20 "Block type must be unsigned");
22 std::vector<Block> blocks;
23 const std::size_t num_bits;
25 static const Block zeros;
26 static const Block ones;
28 static const int bits_per_block = std::numeric_limits<Block>::digits;
30 static int compute_num_blocks(std::size_t num_bits)
32 return num_bits / bits_per_block +
33 static_cast<int>(num_bits % bits_per_block != 0);
36 static std::size_t block_index(std::size_t pos)
38 return pos / bits_per_block;
41 static std::size_t bit_index(std::size_t pos)
43 return pos % bits_per_block;
46 static Block bit_mask(std::size_t pos)
48 return Block(1) << bit_index(pos);
51 int count_bits_in_last_block()
const {
return bit_index(num_bits); }
53 void zero_unused_bits()
55 const int bits_in_last_block = count_bits_in_last_block();
57 if (bits_in_last_block != 0) {
58 assert(!blocks.empty());
59 blocks.back() &= ~(ones << bits_in_last_block);
64 explicit DynamicBitset(std::size_t num_bits)
65 : blocks(compute_num_blocks(num_bits), zeros)
70 std::size_t size()
const {
return num_bits; }
81 for (std::size_t pos = 0; pos < num_bits; ++pos) {
82 result +=
static_cast<int>(test(pos));
89 std::fill(blocks.begin(), blocks.end(), ones);
93 void reset() { std::fill(blocks.begin(), blocks.end(), zeros); }
95 void set(std::size_t pos)
97 assert(pos < num_bits);
98 blocks[block_index(pos)] |= bit_mask(pos);
101 void reset(std::size_t pos)
103 assert(pos < num_bits);
104 blocks[block_index(pos)] &= ~bit_mask(pos);
107 bool test(std::size_t pos)
const
109 assert(pos < num_bits);
110 return (blocks[block_index(pos)] & bit_mask(pos)) != 0;
113 bool operator[](std::size_t pos)
const {
return test(pos); }
115 bool intersects(
const DynamicBitset& other)
const
117 assert(size() == other.size());
118 for (std::size_t i = 0; i < blocks.size(); ++i) {
119 if (blocks[i] & other.blocks[i])
return true;
124 bool is_subset_of(
const DynamicBitset& other)
const
126 assert(size() == other.size());
127 for (std::size_t i = 0; i < blocks.size(); ++i) {
128 if (blocks[i] & ~other.blocks[i])
return false;
133 friend bool operator<(
134 const DynamicBitset<Block>& left,
135 const DynamicBitset<Block>& right)
137 return std::tie(left.blocks, left.num_bits) <
138 std::tie(right.blocks, right.num_bits);
141 friend bool operator==(
142 const DynamicBitset<Block>& left,
143 const DynamicBitset<Block>& right)
145 return std::tie(left.blocks, left.num_bits) ==
146 std::tie(right.blocks, right.num_bits);
150template <
typename Block>
151const Block DynamicBitset<Block>::zeros = Block(0);
153template <
typename Block>
155const Block DynamicBitset<Block>::ones = Block(~Block(0));