2020
2121#include < bitset>
2222#include < cstddef>
23+ #include < iostream>
2324#include < ostream>
2425#include < stdexcept>
2526#include < vector>
2930namespace scl {
3031
3132/* *
32- * @brief A simple bitmap.
33+ * @brief A bitmap.
3334 *
34- * The Bitmap class holds bits. It serves some of the same functionality as
35- * <code>std::vector<bool></code>. The implementation of Bitmap stores bits
36- * packed in objects of type Bitmap::BlockType, current <code>unsigned
37- * char</code>. As a consequence, Bitmap always stores a multiple of
38- * <code>sizeof(Bitmap::BlockType) * 8</code> bits. Any unset bits are
39- * guaranteed to be 0.
35+ * Bitmap serves a similar purpose as <code>std::vector<bool></code>, but
36+ * behaves a bit more like a "fixed-length vector of bits". The main
37+ * differentiator is that Bitmap implements various element-wise operations.
38+ *
39+ * A Bitmap is always a multiple of Bitmap::BlockType. One consequence of this
40+ * is that its "true size" must be tracked externally.
41+ *
42+ * @code
43+ * Bitmap bm(10); // this creates a Bitmap with space for 10 bits, with
44+ * // all 10 bits initialized to be 0.
45+ *
46+ * assert(bm.size() == 10);
47+ * assert(bm.numberOfBlocks() == ...); // a multiple of Bitmap::BITS_PER_BLOCK
48+ *
49+ * assert(bm.count() == 0)
50+ * bm.set(0, true); // set the first bit to be 1
51+ * assert(bm.count() == 1);
52+ * assert(bm.at(0));
53+ * assert(!bm.at(1));
54+ *
55+ * std::cout << bm;
56+ * // 0000000000000001
57+ *
58+ * Bitmap bm1(10);
59+ * Bitmap bm2(10);
60+ *
61+ * bm1.set(0, 1);
62+ * bm1.set(1, 1);
63+ * bm2.set(1, 1);
64+ * bm2.set(2, 1);
65+ *
66+ * assert((bm1 & bm2).count() == 1);
67+ * assert((bm1 ^ bm2).count() == 2);
68+ * assert((bm1 | bm2).count() == 3);
69+ *
70+ * assert((~bm1).count() == 8);
71+ * @endcode
4072 */
4173class Bitmap {
4274 public:
@@ -55,24 +87,22 @@ class Bitmap {
5587
5688 public:
5789 /* *
58- * @brief Create a Bitmap from an <code>std::vector<bool></code>.
59- * @param bool_vec the <code>std::vector<bool></code>.
60- * @return a Bitmap.
90+ * @brief Create a Bitmap from an STL vector of booleans.
6191 */
6292 static Bitmap fromStdVecBool (const std::vector<bool >& bool_vec) {
6393 Bitmap bm (bool_vec.size ());
6494 for (std::size_t i = 0 ; i < bool_vec.size (); ++i) {
6595 bm.set (i, bool_vec[i]);
6696 }
6797 return bm;
68- } // LCOV_EXCL_LINE
98+ }
6999
70100 /* *
71101 * @brief Construct a Bitmap with some initial size.
72- * @param initial_size the initial size.
73102 */
74103 Bitmap (std::size_t initial_size)
75- : m_bits(ContainerType(bytesRequired(initial_size), 0 )) {}
104+ : m_bits(ContainerType(bytesRequired(initial_size), 0 )),
105+ m_true_size (initial_size) {}
76106
77107 /* *
78108 * @brief Construct an empty Bitmap.
@@ -81,8 +111,6 @@ class Bitmap {
81111
82112 /* *
83113 * @brief Check the bit at some position.
84- * @param index the bit position.
85- * @return true if the bit at position \p index is set and 0 otherwise.
86114 */
87115 bool at (std::size_t index) const {
88116 const std::size_t block = index / BITS_PER_BLOCK;
@@ -92,8 +120,6 @@ class Bitmap {
92120
93121 /* *
94122 * @brief Set the bit at some position.
95- * @param index the position of the bit to set.
96- * @param b the value to set.
97123 */
98124 void set (std::size_t index, bool b) {
99125 const std::size_t block = index / BITS_PER_BLOCK;
@@ -103,7 +129,6 @@ class Bitmap {
103129
104130 /* *
105131 * @brief Count the number of bits set in this Bitmap.
106- * @return the population count of this Bitmap.
107132 */
108133 std::size_t count () const {
109134 // https://stackoverflow.com/a/698108
@@ -118,36 +143,31 @@ class Bitmap {
118143
119144 /* *
120145 * @brief Get the number of blocks this Bitmap uses.
121- * @return the number of BlockType elements used by this Bitmap.
122146 */
123147 std::size_t numberOfBlocks () const {
124148 return m_bits.size ();
125149 }
126150
151+ std::size_t size () const {
152+ return m_true_size;
153+ }
154+
127155 /* *
128156 * @brief Check if two bitmaps contain the same content.
129- * @param bm0 the first Bitmap.
130- * @param bm1 the second Bitmap.
131- * @return true if \p bm0 and \p bm1 are equal, false otherwise.
132157 */
133158 friend bool operator ==(const Bitmap& bm0, const Bitmap& bm1) {
134159 return bm0.m_bits == bm1.m_bits ;
135160 }
136161
137162 /* *
138163 * @brief Check if two bitmaps are different.
139- * @param bm0 the first Bitmap.
140- * @param bm1 the second Bitmap.
141- * @return false if \p bm0 and \p bm1 are equal, true otherwise.
142164 */
143165 friend bool operator !=(const Bitmap& bm0, const Bitmap& bm1) {
144166 return !(bm0 == bm1);
145167 }
146168
147169 /* *
148170 * @brief Write this bitmap to a stream.
149- * @param os the stream.
150- * @param m the bitmap.
151171 */
152172 friend std::ostream& operator <<(std::ostream& os, const Bitmap& m) {
153173 for (const BlockType& block : m.m_bits ) {
@@ -158,13 +178,10 @@ class Bitmap {
158178
159179 /* *
160180 * @brief Compute the XOR of two bitmaps.
161- * @param bm0 the first bitmap.
162- * @param bm1 the other bitmap.
163181 */
164182 friend Bitmap operator ^(const Bitmap& bm0, const Bitmap& bm1) {
165183 validateSizes (bm0, bm1);
166- Bitmap bm;
167- bm.m_bits .resize (bm0.numberOfBlocks ());
184+ Bitmap bm (bm0.m_true_size );
168185 for (std::size_t i = 0 ; i < bm.m_bits .size (); i++) {
169186 bm.m_bits [i] = bm0.m_bits [i] ^ bm1.m_bits [i];
170187 }
@@ -173,13 +190,10 @@ class Bitmap {
173190
174191 /* *
175192 * @brief Compute the AND of two bitmaps.
176- * @param bm0 the first bitmap.
177- * @param bm1 the other bitmap.
178193 */
179194 friend Bitmap operator &(const Bitmap& bm0, const Bitmap& bm1) {
180195 validateSizes (bm0, bm1);
181- Bitmap bm;
182- bm.m_bits .resize (bm0.numberOfBlocks ());
196+ Bitmap bm (bm0.m_true_size );
183197 for (std::size_t i = 0 ; i < bm.m_bits .size (); i++) {
184198 bm.m_bits [i] = bm0.m_bits [i] & bm1.m_bits [i];
185199 }
@@ -188,13 +202,10 @@ class Bitmap {
188202
189203 /* *
190204 * @brief Compute the OR of two bitmaps.
191- * @param bm0 the first bitmap.
192- * @param bm1 the other bitmap.
193205 */
194206 friend Bitmap operator |(const Bitmap& bm0, const Bitmap& bm1) {
195207 validateSizes (bm0, bm1);
196- Bitmap bm;
197- bm.m_bits .resize (bm0.numberOfBlocks ());
208+ Bitmap bm (bm0.m_true_size );
198209 for (std::size_t i = 0 ; i < bm.m_bits .size (); i++) {
199210 bm.m_bits [i] = bm0.m_bits [i] | bm1.m_bits [i];
200211 }
@@ -203,63 +214,47 @@ class Bitmap {
203214
204215 /* *
205216 * @brief Compute the negation of a bitmap.
206- * @param bm0 the bitmap.
207217 */
208218 friend Bitmap operator ~(const Bitmap& bm0) {
209- Bitmap bm;
210- bm. m_bits . resize (bm0. numberOfBlocks ()) ;
211- for (std:: size_t i = 0 ; i < bm.m_bits .size (); i++) {
219+ Bitmap bm (bm0. m_true_size ) ;
220+ std:: size_t i = 0 ;
221+ for (; i < bm.m_bits .size () - 1 ; i++) {
212222 bm.m_bits [i] = ~bm0.m_bits [i];
213223 }
224+ // for the last block we only negate some of the bits, potentially.
225+ const auto mask = (1 << (bm.m_true_size % BITS_PER_BLOCK)) - 1 ;
226+ bm.m_bits [i] = ~bm0.m_bits [i] & mask;
214227 return bm;
215228 }
216229
217230 private:
231+ friend Serializer<Bitmap>;
232+
218233 ContainerType m_bits;
234+ std::size_t m_true_size;
219235
220236 static constexpr std::size_t bytesRequired (std::size_t bits) {
221237 return bits == 0 ? 1 : (bits - 1 ) / (BITS_PER_BLOCK) + 1 ;
222238 }
223239
224240 static void validateSizes (const Bitmap& bm0, const Bitmap& bm1) {
225- if (bm0.numberOfBlocks () != bm1.numberOfBlocks ()) {
241+ if (bm0.size () != bm1.size ()) {
226242 throw std::logic_error (" bitmaps are different sizes" );
227243 }
228244 }
229-
230- friend Serializer<Bitmap>;
231245};
232246
233247/* *
234248 * @brief Serializer for util::Bitmap types.
235249 */
236250template <>
237251struct Serializer <Bitmap> {
238- /* *
239- * @brief Get serialized size of a util::Bitmap.
240- * @param bm the util::Bitmap.
241- * @return the size in bytes of the \p bm.
242- */
243252 static std::size_t sizeOf (const Bitmap& bm) {
244253 return Serializer<Bitmap::ContainerType>::sizeOf (bm.m_bits );
245254 }
246-
247- /* *
248- * @brief Write a util::Bitmap to a buffer.
249- * @param bm the util::Bitmap.
250- * @param buf the buffer.
251- * @return the number of bytes written.
252- */
253255 static std::size_t write (const Bitmap& bm, unsigned char * buf) {
254256 return Serializer<Bitmap::ContainerType>::write (bm.m_bits , buf);
255257 }
256-
257- /* *
258- * @brief Read a util::Bitmap from a buffer.
259- * @param bm the util::Bitmap that will store the result.
260- * @param buf the buffer to read the util::Bitmap from.
261- * @return the number of bytes read from \p buf.
262- */
263258 static std::size_t read (Bitmap& bm, const unsigned char * buf) {
264259 return Serializer<Bitmap::ContainerType>::read (bm.m_bits , buf);
265260 }
0 commit comments