AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
dynamic_bitset.h
1#ifndef ALGORITHMS_DYNAMIC_BITSET_H
2#define ALGORITHMS_DYNAMIC_BITSET_H
3
4#include <algorithm>
5#include <cassert>
6#include <compare>
7#include <limits>
8#include <tuple>
9#include <vector>
10
11/*
12 Poor man's version of boost::dynamic_bitset, mostly copied from there.
13*/
14
15namespace dynamic_bitset {
16template <typename Block = unsigned int>
17class DynamicBitset {
18 static_assert(
19 !std::numeric_limits<Block>::is_signed,
20 "Block type must be unsigned");
21
22 std::vector<Block> blocks;
23 const std::size_t num_bits;
24
25 static const Block zeros;
26 static const Block ones;
27
28 static const int bits_per_block = std::numeric_limits<Block>::digits;
29
30 static int compute_num_blocks(std::size_t num_bits)
31 {
32 return num_bits / bits_per_block +
33 static_cast<int>(num_bits % bits_per_block != 0);
34 }
35
36 static std::size_t block_index(std::size_t pos)
37 {
38 return pos / bits_per_block;
39 }
40
41 static std::size_t bit_index(std::size_t pos)
42 {
43 return pos % bits_per_block;
44 }
45
46 static Block bit_mask(std::size_t pos)
47 {
48 return Block(1) << bit_index(pos);
49 }
50
51 int count_bits_in_last_block() const { return bit_index(num_bits); }
52
53 void zero_unused_bits()
54 {
55 const int bits_in_last_block = count_bits_in_last_block();
56
57 if (bits_in_last_block != 0) {
58 assert(!blocks.empty());
59 blocks.back() &= ~(ones << bits_in_last_block);
60 }
61 }
62
63public:
64 explicit DynamicBitset(std::size_t num_bits)
65 : blocks(compute_num_blocks(num_bits), zeros)
66 , num_bits(num_bits)
67 {
68 }
69
70 std::size_t size() const { return num_bits; }
71
72 /*
73 Count the number of set bits.
74
75 The computation could be made faster by using a more sophisticated
76 algorithm (see https://en.wikipedia.org/wiki/Hamming_weight).
77 */
78 int count() const
79 {
80 int result = 0;
81 for (std::size_t pos = 0; pos < num_bits; ++pos) {
82 result += static_cast<int>(test(pos));
83 }
84 return result;
85 }
86
87 void set()
88 {
89 std::fill(blocks.begin(), blocks.end(), ones);
90 zero_unused_bits();
91 }
92
93 void reset() { std::fill(blocks.begin(), blocks.end(), zeros); }
94
95 void set(std::size_t pos)
96 {
97 assert(pos < num_bits);
98 blocks[block_index(pos)] |= bit_mask(pos);
99 }
100
101 void reset(std::size_t pos)
102 {
103 assert(pos < num_bits);
104 blocks[block_index(pos)] &= ~bit_mask(pos);
105 }
106
107 bool test(std::size_t pos) const
108 {
109 assert(pos < num_bits);
110 return (blocks[block_index(pos)] & bit_mask(pos)) != 0;
111 }
112
113 bool operator[](std::size_t pos) const { return test(pos); }
114
115 bool intersects(const DynamicBitset& other) const
116 {
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;
120 }
121 return false;
122 }
123
124 bool is_subset_of(const DynamicBitset& other) const
125 {
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;
129 }
130 return true;
131 }
132
133 friend bool operator<(
134 const DynamicBitset<Block>& left,
135 const DynamicBitset<Block>& right)
136 {
137 return std::tie(left.blocks, left.num_bits) <
138 std::tie(right.blocks, right.num_bits);
139 }
140
141 friend bool operator==(
142 const DynamicBitset<Block>& left,
143 const DynamicBitset<Block>& right)
144 {
145 return std::tie(left.blocks, left.num_bits) ==
146 std::tie(right.blocks, right.num_bits);
147 }
148};
149
150template <typename Block>
151const Block DynamicBitset<Block>::zeros = Block(0);
152
153template <typename Block>
154// MSVC's bitwise negation always returns a signed type.
155const Block DynamicBitset<Block>::ones = Block(~Block(0));
156} // namespace dynamic_bitset
157
158/*
159This source file was derived from the boost::dynamic_bitset library
160version 1.54. Original copyright statement and license for this
161original source follow.
162
163Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
164Copyright (c) 2003-2006, 2008 Gennaro Prota
165
166Distributed under the Boost Software License, Version 1.0.
167
168Boost Software License - Version 1.0 - August 17th, 2003
169
170Permission is hereby granted, free of charge, to any person or organization
171obtaining a copy of the software and accompanying documentation covered by
172this license (the "Software") to use, reproduce, display, distribute,
173execute, and transmit the Software, and to prepare derivative works of the
174Software, and to permit third-parties to whom the Software is furnished to
175do so, all subject to the following:
176
177The copyright notices in the Software and this entire statement, including
178the above license grant, this restriction and the following disclaimer,
179must be included in all copies of the Software, in whole or in part, and
180all derivative works of the Software, unless such copies or derivative
181works are solely in the form of machine-executable object code generated by
182a source language processor.
183
184THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
185IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
187SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
188FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
189ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
190DEALINGS IN THE SOFTWARE.
191*/
192
193#endif