BitMagic-C++
sample12.cpp
Go to the documentation of this file.
1/*
2Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16For more information please visit: http://bitmagic.io
17*/
18
19/** \example sample12.cpp
20 Example of how to use various bit setting techniques.
21 Several techniques benchmarked to better illustrate relative performance.
22
23 \sa bm::bvector<>::set()
24 \sa bm::bvector<>::set_bit()
25 \sa bm::bvector<>::set_bit_conditional()
26 \sa bm::bvector<>::set_range()
27 \sa bm::bvector<>::clear_bit()
28 \sa bm::bvector<>::reset()
29 \sa bm::bvector<>::flip()
30 \sa bm::bvector<>::swap()
31 \sa bm::bvector<>::extract_next()
32 \sa bm::bvector<>::set_bit_no_check()
33 \sa bm::combine_or()
34 */
35
36/*! \file sample12.cpp
37 \brief Example: bvector<> analysis of bit setting methods
38*/
39
40#include <iostream>
41#include <vector>
42
43#define BM64ADDR
44
45#include "bm.h"
46#include "bmalgo.h"
47#include "bmtimer.h"
48#include "bmundef.h" /* clear the pre-proc defines from BM */
49
50using namespace std;
51
52// timing storage for benchmarking
54
55// depending of the build it may be "unsigned int" or 64-bit "unsigned long long"
57
58const unsigned benchmark_count = 1000;
60
61
62// Utility template function used to print container
63template<class T> void PrintContainer(T first, T last)
64{
65 if (first == last)
66 std::cout << "<EMPTY SET>";
67 else
68 for (; first != last; ++first)
69 std::cout << *first << ";";
70 std::cout << std::endl;
71}
72
73
74static
75void generate_test_vectors(std::vector<bm_size_type> &v1,
76 std::vector<bm_size_type> &v2,
77 std::vector<bm_size_type> &v3)
78{
80 for (j = 0; j < vector_max; j += 2)
81 {
82 v1.push_back(j);
83 }
84 for (j = 0; j < vector_max; j += 5)
85 {
86 v2.push_back(j);
87 }
88 for (j = 0; j < vector_max; j += 120)
89 {
90 v3.push_back(j);
91 }
92}
93
94
95// stress test for bm::bvector<>::set_bit()
96//
97static
99{
100 bm::chrono_taker tt1(cout, "1. bvector<>::set_bit()", benchmark_count, &timing_map);
101 bm::bvector<> bv1, bv2, bv3;
102
103 for (unsigned i = 0; i < benchmark_count; ++i)
104 {
105 bm_size_type j;
106 for (j = 0; j < vector_max; j += 2)
107 {
108 bv1.set_bit(j, true);
109 }
110 for (j = 0; j < vector_max; j += 10)
111 {
112 bv2.set_bit(j, true);
113 }
114 for (j = 0; j < vector_max; j += 120)
115 {
116 bv3.set_bit(j, true);
117 }
118 bv1.reset();
119 bv2.reset();
120 bv3.reset();
121 } // for
122}
123
124
125// stress test for bm::bvector<>::set_bit()
126//
127static
129{
130 bm::chrono_taker tt1(cout, "2. bvector<>::set_bit_no_check()", benchmark_count, &timing_map);
131 bm::bvector<> bv1, bv2, bv3;
132
133 bv1.init();
134 bv2.init();
135 bv3.init();
136
137 for (unsigned i = 0; i < benchmark_count; ++i)
138 {
139 bm::id_t j;
140 for (j = 0; j < vector_max; j += 2)
141 {
142 bv1.set_bit_no_check(j);
143 }
144 for (j = 0; j < vector_max; j += 10)
145 {
146 bv2.set_bit_no_check(j);
147 }
148 for (j = 0; j < vector_max; j += 120)
149 {
150 bv3.set_bit_no_check(j);
151 }
152 }
153}
154
155static
156void combine_or_test(std::vector<bm_size_type> &v1,
157 std::vector<bm_size_type> &v2,
158 std::vector<bm_size_type> &v3)
159{
160 bm::chrono_taker tt1(cout, "3. combine_or()", benchmark_count, &timing_map);
161 bm::bvector<> bv1, bv2, bv3;
162
163 for (unsigned i = 0; i < benchmark_count; ++i)
164 {
165 bm::combine_or(bv1, v1.begin(), v1.end());
166 bm::combine_or(bv2, v2.begin(), v2.end());
167 bm::combine_or(bv3, v3.begin(), v3.end());
168 }
169}
170
171static
172void bvector_bulk_set_test(std::vector<bm_size_type> &v1,
173 std::vector<bm_size_type> &v2,
174 std::vector<bm_size_type> &v3)
175{
176 bm::chrono_taker tt1(cout, "3. bvector<>::set() array", benchmark_count, &timing_map);
177 bm::bvector<> bv1, bv2, bv3;
178
179 for (unsigned i = 0; i < benchmark_count; ++i)
180 {
181 bv1.set(&v1[0], bm_size_type(v1.size()));
182 bv2.set(&v2[0], bm_size_type(v2.size()));
183 bv3.set(&v3[0], bm_size_type(v3.size()));
184 }
185}
186
187
188
189int main(void)
190{
191 try
192 {
193 // 0. create bvector, use brace initialization to add some initial data
194 //
195 bm::bvector<> bv1 { 2, 3, 4 };
196
197 PrintContainer(bv1.first(), bv1.end()); // 2, 3, 4
198 bv1.clear();
199
200 // 1. Set some bits using regular bvector<>::set() method
201 //
202 bv1.set(10);
203 bv1.set(256);
204 bv1.set(1000000);
205
206 PrintContainer(bv1.first(), bv1.end()); // 10, 256, 1000000
207
208 // 2. now use bvector<>::set_bit()
209 // it returns a report if target actually changed
210 //
211
212 bm::id_t bits[] = { 256, 512, 10 };
213 unsigned cnt = 0;
214
215 for (unsigned i = 0; i < sizeof(bits) / sizeof(bits[0]); ++i)
216 {
217 bool b = bv1.set_bit(bits[i], true);
218 cnt += b;
219 }
220 std::cout << "Number of bits changed:" << cnt << std::endl;
221 PrintContainer(bv1.first(), bv1.end());
222
223 // 3. set and clear some bits using bvector<>::set_bit_conditional()
224 // method sets bit n only if current value equals the condition
225 //
226 bool b;
227 b = bv1.set_bit_conditional(5, true, false); // set bit 5 to true if it is false (yes)
228 std::cout << "Bit 5 set:" << (b ? " yes " : " no ") << std::endl; // (yes)
229
230 b = bv1.set_bit_conditional(256, true, false); // set bit 256 to true if it is false
231 std::cout << "Bit 256 set:" << (b ? " yes " : " no ") << std::endl; // (no)
232
233 b = bv1.set_bit_conditional(256, true, true); // set bit 256 to true if it is true
234 std::cout << "Bit 256 set:" << (b ? " yes " : " no ") << std::endl; // (no)
235
236 PrintContainer(bv1.first(), bv1.end());
237
238 // 4. set or clear multiple bits using bvector::set_range()
239 // This method is faster than calling bvector::set() many times in a row
240 //
241 bv1.set_range(10, 15, true); // set all bits in [10..15] closed interval
242 PrintContainer(bv1.first(), bv1.end());
243
244 bv1.set_range(10, 12, false); // clear all bits in [10..15] closed interval
245 PrintContainer(bv1.first(), bv1.end());
246
247 // 5. bvector::clear_bit() - same as set_bit() just a syntax sugar
248 //
249 b = bv1.clear_bit(13);
250 std::cout << "Bit 13 set:" << (b ? " yes " : " no ") << std::endl; // (yes)
251
252 // 6. bvector<>::reset() - clears all the bits, frees the blocks memory
253 // same as bvector<>::clear(true);
254 //
255 bv1.reset();
256 PrintContainer(bv1.first(), bv1.end()); // <EMPTY>
257
258 // 7. use bm::combine_or() to set bits
259 //
260 bm::combine_or(bv1, &bits[0], &bits[0] + (sizeof(bits) / sizeof(bits[0])));
261 PrintContainer(bv1.first(), bv1.end()); // 10, 256, 512
262
263 // 8. use bvector<>::flip( ) to flip a bit
264 //
265 bv1.flip(256);
266 bv1.flip(257);
267 PrintContainer(bv1.first(), bv1.end()); // 10, 257, 512
268
269 // 9. bvector<>::swap() to flip content of two bit-vectors
270 //
271 bm::bvector<> bv2;
272 bv1.swap(bv2);
273 PrintContainer(bv1.first(), bv1.end()); // <EMPTY>
274 PrintContainer(bv2.first(), bv2.end()); // 10, 257, 512
275
276 // 10. use bvector<>::extract_next() to find ON bit and turn it to 0
277 // this function is useful for building FIFO queues on bvector
278 //
279 bm_size_type p = 1;
280 for (p = bv2.extract_next(p); p != 0; p = bv2.extract_next(p))
281 {
282 std::cout << "Extracted p = " << p << std::endl;
283 }
284 PrintContainer(bv2.first(), bv2.end()); // <EMPTY>
285
286 // 11. use bvector<>::set_bit_no_check() to set bits faster
287 //
288 bm::bvector<> bv3;
289 bv3.init(); // the key here you MUST call init() before setting bits this way
290
291 bv3.set_bit_no_check(10);
292 bv3.set_bit_no_check(100);
293 bv3.set_bit_no_check(1000);
294
295 PrintContainer(bv3.first(), bv3.end()); // 10, 100, 1000
296
297
298 std::vector<bm_size_type> v1, v2, v3;
299 generate_test_vectors(v1, v2, v3);
300
301 for (unsigned k = 0; k < 1000; ++k)
302 {
303 // run a few CPU "pre-heat" loops to get consistent results
304 bm_size_type s = 0;
305 bm_size_type i;
306 for (i = 0; i < v1.size(); ++i)
307 s = s + s* v1[i] + i;
308 for (i = 0; i < v2.size(); ++i)
309 s = s + s* v2[i] + i;
310 std::cout << s << "\r";
311 }
312
313 std::cout << std::endl << "Running benchmarks..." << std::endl;
314
317 combine_or_test(v1, v2, v3);
318 bvector_bulk_set_test(v1, v2, v3);
319
320 // print all test timing results
321 //
322 std::cout << std::endl;
324 }
325 catch(std::exception& ex)
326 {
327 std::cerr << ex.what() << std::endl;
328 return 1;
329 }
330
331 return 0;
332}
333
Compressed bit-vector bvector<> container, set algebraic methods, traversal iterators.
Algorithms for bvector<> (main include)
Timing utilities for benchmarking (internal)
pre-processor un-defines to avoid global space pollution (internal)
Bitvector Bit-vector container with runtime compression of bits.
Definition: bm.h:115
bvector< Alloc > & set(size_type n, bool val=true)
Sets bit n if val is true, clears bit n if val is false.
Definition: bm.h:4153
bool set_bit(size_type n, bool val=true)
Sets bit n.
Definition: bm.h:4192
bvector_size_type size_type
Definition: bm.h:121
enumerator first() const
Returns enumerator pointing on the first non-zero bit.
Definition: bm.h:1849
enumerator end() const
Returns enumerator pointing on the next bit after the last.
Definition: bm.h:1855
void swap(bvector< Alloc > &bvect) BMNOEXCEPT
Exchanges content of bv and this bvector.
Definition: bm.h:3931
void init()
Explicit post-construction initialization. Must be caled to make sure safe use of *_no_check() method...
Definition: bm.h:2258
size_type extract_next(size_type prev)
Finds the number of the next bit ON and sets it to 0.
Definition: bm.h:1597
bvector< Alloc > & reset() BMNOEXCEPT
Clears every bit in the bitvector.
Definition: bm.h:1245
void set_bit_no_check(size_type n)
Set bit without checking preconditions (size, etc)
Definition: bm.h:4405
Utility class to collect performance measurements and statistics.
Definition: bmtimer.h:41
std::map< std::string, statistics > duration_map_type
test name to duration map
Definition: bmtimer.h:66
static void print_duration_map(TOut &tout, const duration_map_type &dmap, format fmt=ct_time)
Definition: bmtimer.h:150
void combine_or(BV &bv, It first, It last)
OR Combine bitvector and the iterable sequence.
Definition: bmalgo_impl.h:1080
unsigned int id_t
Definition: bmconst.h:38
const unsigned benchmark_count
Definition: sample12.cpp:58
void PrintContainer(T first, T last)
Definition: sample12.cpp:63
int main(void)
Definition: sample12.cpp:189
static void combine_or_test(std::vector< bm_size_type > &v1, std::vector< bm_size_type > &v2, std::vector< bm_size_type > &v3)
Definition: sample12.cpp:156
bm::chrono_taker ::duration_map_type timing_map
Definition: sample12.cpp:53
static void generate_test_vectors(std::vector< bm_size_type > &v1, std::vector< bm_size_type > &v2, std::vector< bm_size_type > &v3)
Definition: sample12.cpp:75
static void bv_set_bit_no_check_test()
Definition: sample12.cpp:128
static void bvector_bulk_set_test(std::vector< bm_size_type > &v1, std::vector< bm_size_type > &v2, std::vector< bm_size_type > &v3)
Definition: sample12.cpp:172
static void bv_set_bit_test()
Definition: sample12.cpp:98
bm_size_type vector_max
Definition: sample12.cpp:59
bm::bvector ::size_type bm_size_type
Definition: sample12.cpp:56