BitMagic-C++
bvsetalgebra.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 bvsetalgebra.cpp
20 Example demonstrates variety of algebra of sets operations.
21 http://bitmagic.io/set-algebra.html
22
23 <a href="http://bitmagic.io/set-algebra.html">Algebra Of Sets</a>
24
25 \sa bvector
26
27 \sa bvector<>::bit_or
28 \sa bvector<>::bit_and
29 \sa bvector<>::bit_xor
30 \sa bvector<>::bit_sub
31
32 \sa bm::aggregator
33 \sa bm::operation_deserializer
34
35 \sa bm::combine_and
36 \sa bm::combine_and_sorted
37 \sa bm::combine_sub
38 \sa bm::combine_or
39 \sa bm::combine_xor
40
41 \sa sample7.cpp
42
43*/
44
45/*! \file bvsetalgebra.cpp
46 \brief Example: algebra of sets operations
47*/
48
49
50#include <iostream>
51#include <vector>
52
53
54#include "bm.h"
55#include "bmalgo.h"
56#include "bmserial.h"
57#include "bmaggregator.h"
58
59
60using namespace std;
61
62// utility function to print a set
63static
65{
67 bm::bvector<>::enumerator en = bv.first();
68 for (; en.valid() && cnt < 10; ++en, ++cnt)
69 cout << *en << ", ";
70 if (cnt == 10)
71 cout << " ...";
72 cout << "(size = "<< bv.size() << ")" << endl;
73}
74
75// utility function to create serialized bit-vector BLOB
76static
77void make_BLOB(vector<unsigned char>& target_buf, bm::bvector<>& bv)
78{
82
83 bv.optimize(tb, bm::bvector<>::opt_compress); // memory compression
84
85 bm::serializer<bm::bvector<> >::buffer sbuf;
86 bvs.serialize(bv, sbuf, 0);
87 target_buf.resize(sbuf.size());
88 ::memcpy(target_buf.data(), sbuf.buf(), sbuf.size());
89}
90
91
92// -------------------------------------------------------------
93// Demo for Set Union (OR) operations
94//
95static
96void DemoOR()
97{
98 typedef bm::bvector<>::size_type size_type;
100
101 // bit-vector set union operation: bv_A |= bv_B
102 {
103 bm::bvector<> bv_A { 1, 2, 3 };
104 bm::bvector<> bv_B { 1, 2, 4 };
105 bv_A.bit_or(bv_B);
106
107 print_bvector(bv_A); // 1, 2, 3, 4
108 }
109 // same, but sizes are set, observe size gets extended up
110 {
111 bm::bvector<> bv_A { 1, 2, 3 };
112 bm::bvector<> bv_B { 1, 2, 4 };
113 bv_A.resize(5);
114 bv_B.resize(10);
115
116 bv_A.bit_or(bv_B);
117
118 print_bvector(bv_A); // 1, 2, 3, 4 (size = 10)
119 }
120 // 3-operand OR: bv_T = bv_A | bv_B
121 {
122 bm::bvector<> bv_T;
123 bm::bvector<> bv_A { 1, 2, 3 };
124 bm::bvector<> bv_B { 1, 2, 4 };
125
126 bv_T.bit_or(bv_A, bv_B, bm::bvector<>::opt_compress);
127
128 print_bvector(bv_T); // 1, 2, 3, 4 (size = 10)
129 }
130
131
132 // merge operation is a logical equivalent of OR
133 // except it can destroy the source vector to borrow memory blocks from it
134 // (this is faster, especially in multi-threaded cases)
135 {
136 bm::bvector<> bv_A { 1, 2, 3 };
137 bm::bvector<> bv_B { 1, 2, 4 };
138 bv_A.merge(bv_B);
139
140 print_bvector(bv_A); // 1, 2, 3, 4 (size = 10)
141 }
142
143 // bit-vector set union operation (opcode interpeter mode)
144 // maybe useful for building query interpetors
145 {
146 bm::bvector<> bv_A { 1, 2, 3 };
147 bm::bvector<> bv_B { 1, 2, 4 };
148 bv_A.combine_operation(bv_B, bm::BM_OR);
149
150 print_bvector(bv_A); // 1, 2, 3, 4
151 }
152
153 // Set union between bit-vector and STL container
154 {
155 bm::bvector<> bv_A { 1, 2, 3 };
156 vector<size_type> vect_B { 1, 2, 4 };
157
158 bm::combine_or(bv_A, vect_B.begin(), vect_B.end());
159 print_bvector(bv_A); // 1, 2, 3, 4
160 }
161
162 // Set union between bit-vector and C-array.
163 // This tends to be faster then "combine_or()" especially on sorted vectors
164 // and in SIMD enabled configurations
165 {
166 bm::bvector<> bv_A { 1, 2, 3 };
167 vector<size_type> vect_B { 1, 2, 4 };
168
169 const size_type* arr = &vect_B[0];
170 bv_A.set(arr, unsigned(vect_B.size()), bm::BM_SORTED); // sorted - fastest
171 print_bvector(bv_A); // 1, 2, 3, 4
172 }
173
174 // Set union between bit-vector and a serialized bit-vector BLOB
175 // (created on the fly)
176 {
177 bm::bvector<> bv_A { 1, 2, 3 };
178 vector<unsigned char> blob;
179 {
180 bm::bvector<> bv_B { 1, 2, 4 };
181 make_BLOB(blob, bv_B);
182 }
183 od.deserialize(bv_A, blob.data(), bm::set_OR);
184 print_bvector(bv_A); // 1, 2, 3, 4
185 }
186
187 // Union of many sets with bm::aggegator<>
188 // target := A OR B OR C
189 //
190 // This method is best when we have multiple vectors at hands, aggregator
191 // is capable of doing it faster, than pair by pair OR
192 {
193 bm::bvector<> bv_T; // target vector
194
195 bm::bvector<> bv_A { 1, 2 };
196 bm::bvector<> bv_B { 2, 3 };
197 bm::bvector<> bv_C { 3, 4 };
198
200 agg.set_optimization(); // perform on-the-fly optimization of result
201
202 // attach vectors to group 0 for OR operation
203 agg.add(&bv_A);
204 agg.add(&bv_B);
205 agg.add(&bv_C);
206
207 agg.combine_or(bv_T);
208
209 agg.reset(); // reset the aggregator parameters
210
211 print_bvector(bv_T); // 1, 2, 3, 4
212 }
213
214}
215
216
217// -------------------------------------------------------------
218// Demo for Set Intersect (AND) operations
219//
220static
222{
223 typedef bm::bvector<>::size_type size_type;
225
226 // bit-vector set intersect operation: bv_A &= bv_B
227 {
228 bm::bvector<> bv_A { 1, 2, 3 };
229 bm::bvector<> bv_B { 1, 2, 4 };
230 bv_A.bit_and(bv_B);
231
232 print_bvector(bv_A); // 1, 2
233 }
234 // same, but sizes are set, observe size gets extended up
235 {
236 bm::bvector<> bv_A { 1, 2, 3 };
237 bm::bvector<> bv_B { 1, 2, 4 };
238 bv_A.resize(5);
239 bv_B.resize(10);
240
241 bv_A.bit_and(bv_B);
242
243 print_bvector(bv_A); // 1, 2 (size = 10)
244 }
245 // 3-operand AND: bv_T = bv_A & bv_B
246 {
247 bm::bvector<> bv_T;
248 bm::bvector<> bv_A { 1, 2, 3 };
249 bm::bvector<> bv_B { 1, 2, 4 };
250 bv_T.bit_and(bv_A, bv_B, bm::bvector<>::opt_compress);
251
252 print_bvector(bv_T); // 1, 2
253 }
254
255 // bit-vector set union operation (opcode interpeter mode)
256 // maybe useful for building query interpetors
257 {
258 bm::bvector<> bv_A { 1, 2, 3 };
259 bm::bvector<> bv_B { 1, 2, 4 };
260 bv_A.combine_operation(bv_B, bm::BM_AND);
261
262 print_bvector(bv_A); // 1, 2
263 }
264
265 // Set Intersect between bit-vector and STL container
266 {
267 bm::bvector<> bv_A { 1, 2, 3 };
268 vector<unsigned> vect_B { 1, 2, 4 };
269
270 bm::combine_and(bv_A, vect_B.begin(), vect_B.end());
271 print_bvector(bv_A); // 1, 2
272 }
273
274 // Set Intersect between bit-vector and C-array.
275 // This may be faster then "combine_and()" especially on sorted vectors
276 {
277 bm::bvector<> bv_A { 1, 2, 3 };
278 vector<size_type> vect_B { 1, 2, 4 };
279
280 const size_type* arr = &vect_B[0];
281 bv_A.keep(arr, size_type(vect_B.size()), bm::BM_SORTED); // sorted - fastest
282 print_bvector(bv_A); // 1, 2
283 }
284
285 // Set Intersect between bit-vector and a serialized bit-vector BLOB
286 //
287 {
288 bm::bvector<> bv_A { 1, 2, 3 };
289 vector<unsigned char> blob;
290 {
291 bm::bvector<> bv_B { 1, 2, 4 };
292 make_BLOB(blob, bv_B);
293 }
294 od.deserialize(bv_A, blob.data(), bm::set_AND);
295 print_bvector(bv_A); // 1, 2
296 }
297
298 // Intersection of many sets with bm::aggegator<> (find common subset)
299 // target := A AND B AND C
300 //
301 // This method is best when we have multiple vectors at hands, aggregator
302 // is capable of doing it faster, than pair by pair AND
303 {
304 bm::bvector<> bv_T; // target vector
305
306 bm::bvector<> bv_A { 1, 2 };
307 bm::bvector<> bv_B { 1, 2, 3 };
308 bm::bvector<> bv_C { 1, 2, 3, 4 };
309
311 agg.set_optimization(); // perform on-the-fly optimization of result
312
313 // attach vectors to group 0 for OR operation
314 agg.add(&bv_A);
315 agg.add(&bv_B);
316 agg.add(&bv_C);
317
318 agg.combine_and(bv_T);
319
320 agg.reset(); // reset the aggregator parameters
321
322 print_bvector(bv_T); // 1, 2
323 }
324}
325
326// -------------------------------------------------------------
327// Demo for XOR operations
328//
329static
331{
333
334 // bit-vector xor operation: bv_A ^= bv_B
335 {
336 bm::bvector<> bv_A { 1, 2, 3 };
337 bm::bvector<> bv_B { 1, 2, 4 };
338 bv_A.bit_xor(bv_B);
339
340 print_bvector(bv_A); // 3, 4
341 }
342 // same, but sizes are set, observe size gets extended up
343 {
344 bm::bvector<> bv_A { 1, 2, 3 };
345 bm::bvector<> bv_B { 1, 2, 4 };
346 bv_A.resize(5);
347 bv_B.resize(10);
348
349 bv_A.bit_xor(bv_B);
350
351 print_bvector(bv_A); // 3, 4 (size = 10)
352 }
353 // 3-operand XOR: bv_T = bv_A ^ bv_B
354 {
355 bm::bvector<> bv_T;
356 bm::bvector<> bv_A { 1, 2, 3 };
357 bm::bvector<> bv_B { 1, 2, 4 };
358 bv_T.bit_xor(bv_A, bv_B, bm::bvector<>::opt_compress);
359
360 print_bvector(bv_T); // 3, 4
361 }
362
363 // bit-vector xor operation (opcode interpeter mode)
364 // maybe useful for building query interpetors
365 {
366 bm::bvector<> bv_A { 1, 2, 3 };
367 bm::bvector<> bv_B { 1, 2, 4 };
368 bv_A.combine_operation(bv_B, bm::BM_XOR);
369
370 print_bvector(bv_A); // 3, 4
371 }
372
373 // xor between bit-vector and STL container
374 {
375 bm::bvector<> bv_A { 1, 2, 3 };
376 vector<unsigned> vect_B { 1, 2, 4 };
377
378 bm::combine_xor(bv_A, vect_B.begin(), vect_B.end());
379 print_bvector(bv_A); // 3, 4
380 }
381
382 // xor between bit-vector and a serialized bit-vector BLOB
383 //
384 {
385 bm::bvector<> bv_A { 1, 2, 3 };
386 vector<unsigned char> blob;
387 {
388 bm::bvector<> bv_B { 1, 2, 4 };
389 make_BLOB(blob, bv_B);
390 }
391 od.deserialize(bv_A, blob.data(), bm::set_XOR);
392 print_bvector(bv_A); // 3, 4
393 }
394}
395
396
397// -------------------------------------------------------------
398// Demo for Set Substract (AND NOT) operations
399//
400static
402{
403 typedef bm::bvector<>::size_type size_type;
405
406 // bit-vector set union operation: bv_A -= bv_B
407 {
408 bm::bvector<> bv_A { 1, 2, 3 };
409 bm::bvector<> bv_B { 1, 2, 4 };
410 bv_A.bit_sub(bv_B);
411
412 print_bvector(bv_A); // 3
413 }
414 // same, but sizes are set, observe size gets extended up
415 {
416 bm::bvector<> bv_A { 1, 2, 3 };
417 bm::bvector<> bv_B { 1, 2, 4 };
418 bv_A.resize(5);
419 bv_B.resize(10);
420
421 bv_A.bit_sub(bv_B);
422
423 print_bvector(bv_A); // 3 (size = 10)
424 }
425
426 // 3-operand SUB: bv_T = bv_A - bv_B
427 {
428 bm::bvector<> bv_T;
429 bm::bvector<> bv_A { 1, 2, 3 };
430 bm::bvector<> bv_B { 1, 2, 4 };
431 bv_T.bit_sub(bv_A, bv_B, bm::bvector<>::opt_compress);
432
433 print_bvector(bv_T); // 3
434 }
435
436 // bit-vector minus operation (opcode interpeter mode)
437 // maybe useful for building query interpetors
438 {
439 bm::bvector<> bv_A { 1, 2, 3 };
440 bm::bvector<> bv_B { 1, 2, 4 };
441 bv_A.combine_operation(bv_B, bm::BM_SUB);
442
443 print_bvector(bv_A); // 3
444 }
445
446 // and not between bit-vector and STL container
447 {
448 bm::bvector<> bv_A { 1, 2, 3 };
449 vector<size_type> vect_B { 1, 2, 4 };
450
451 bm::combine_sub(bv_A, vect_B.begin(), vect_B.end());
452 print_bvector(bv_A); // 3
453 }
454
455 // Set Intersect between bit-vector and C-array.
456 // This may be faster then "combine_and()" especially on sorted vectors
457 {
458 bm::bvector<> bv_A { 1, 2, 3 };
459 vector<size_type> vect_B { 1, 2, 4 };
460
461 const size_type* arr = &vect_B[0];
462 bv_A.clear(arr, unsigned(vect_B.size()), bm::BM_SORTED); // sorted - fastest
463 print_bvector(bv_A); // 3
464 }
465
466 // Set union between bit-vector and a serialized bit-vector BLOB
467 //
468 {
469 bm::bvector<> bv_A { 1, 2, 3 };
470 vector<unsigned char> blob;
471 {
472 bm::bvector<> bv_B { 1, 2, 4 };
473 make_BLOB(blob, bv_B);
474 }
475 od.deserialize(bv_A, blob.data(), bm::set_SUB);
476 print_bvector(bv_A); // 3
477 }
478
479 // Subtraction of many sets with bm::aggegator<>
480 // target := (target SUB A) OR (target SUB B) OR (target SUB C)
481 //
482 {
483 bm::bvector<> bv_T; // target vector
484
485 bm::bvector<> bv_A { 1, 2, 3, 4 };
486 bm::bvector<> bv_B { 1, 2 };
487 bm::bvector<> bv_C { 1, 2, 4 };
488
490 agg.set_optimization(); // perform on-the-fly optimization of result
491
492 // here we are really using AND SUB operation
493 // where group 0 is all ANDed and group 1 SUBtracted from the result
494 // group 1 is only 1 vector, so AND part will be no-op
495 //
496 agg.add(&bv_A, 0); // add to group 0 (subtraction source)
497
498 agg.add(&bv_B, 1); // add to group 1 (subtraction arguments)
499 agg.add(&bv_C, 1);
500
501 agg.combine_and_sub(bv_T);
502
503 agg.reset(); // reset the aggregator parameters
504
505 print_bvector(bv_T); // 3
506 }
507}
508
509// -------------------------------------------------------------
510// Demo for Set Invert (NOT)
511//
512static
514{
515 // bit-vector invert operation
516 // by default it inverts the whole 32-bit space
517 {
518 bm::bvector<> bv_A { 4, 5, 6 };
519 bv_A.invert();
520
521 print_bvector(bv_A); // 0, 1, 2, 3, 7 ...
522 }
523
524 // bit-vector invert operation
525 // it is size bound, inverts within set limits
526 {
527 bm::bvector<> bv_A { 4, 5, 6 };
528 bv_A.resize(7);
529 bv_A.invert();
530
531 print_bvector(bv_A); // 0, 1, 2, 3, size = 7
532 }
533}
534
535
536// -------------------------------------------------------------
537// Demo for AND-SUB
538// AND-SUB implements a search pattern "all this but not that"
539//
540static
542{
543 // Operation on two groups of vectors using aggregator
544 // 1. Group 0 - find common subset (Set Intersect / AND)
545 // 2. Group 1 - find union (OR) of the group and SUBtract it from #1
546 //
547 // target := (A AND D AND ...) AND NOT (B OR C OR ...)
548 //
549 {
550 bm::bvector<> bv_T; // target vector
551
552 bm::bvector<> bv_A { 1, 2, 3, 4 };
553 bm::bvector<> bv_B { 1, 2 };
554 bm::bvector<> bv_C { 1, 2, 4 };
555 bm::bvector<> bv_D { 0, 2, 3, 4, 5 };
556
558 agg.set_optimization(); // perform on-the-fly optimization of result
559
560 // here we are really using AND SUB operation
561 // where group 0 is all ANDed and group 1 SUBtracted from the result
562 //
563 agg.add(&bv_A, 0); // add to group 0 for AND
564 agg.add(&bv_D, 0); //
565
566 agg.add(&bv_B, 1); // add to group 1 SUB tract from group 0 result
567 agg.add(&bv_C, 1);
568
569 agg.combine_and_sub(bv_T);
570
571 agg.reset(); // reset the aggregator parameters
572
573 print_bvector(bv_T); // 3
574 }
575}
576
577
578
579int main(void)
580{
581 try
582 {
583 cout << endl << "Set Union (OR) demo" << endl << endl;
584 DemoOR();
585
586 cout << endl << "Set Intersect (AND) demo" << endl << endl;
587 DemoAND();
588
589 cout << endl << "XOR demo" << endl << endl;
590 DemoXOR();
591
592 cout << endl << "Set Minus (SUB/AND-NOT) demo" << endl << endl;
593 DemoSUB();
594
595 cout << endl << "Set Invert (NOT) demo" << endl << endl;
596 DemoINV();
597
598 cout << endl << "Set AND-SUB demo" << endl << endl;
599 DemoAND_SUB();
600 }
601 catch(std::exception& ex)
602 {
603 std::cerr << ex.what() << std::endl;
604 }
605
606 return 0;
607}
Compressed bit-vector bvector<> container, set algebraic methods, traversal iterators.
#define BM_DECLARE_TEMP_BLOCK(x)
Definition bm.h:47
Algorithms for fast aggregation of N bvectors.
Algorithms for bvector<> (main include)
Serialization / compression of bvector<>. Set theoretical operations on compressed BLOBs.
static void DemoINV()
static void DemoXOR()
static void DemoOR()
int main(void)
static void DemoSUB()
static void DemoAND_SUB()
static void make_BLOB(vector< unsigned char > &target_buf, bm::bvector<> &bv)
static void print_bvector(const bm::bvector<> &bv)
static void DemoAND()
Algorithms for fast aggregation of a group of bit-vectors.
void set_optimization(typename bvector_type::optmode opt=bvector_type::opt_compress)
set on-the-fly bit-block compression By default aggregator does not try to optimize result,...
void reset() BMNOEXCEPT
Reset aggregate groups, forget all attached vectors.
unsigned add(const bvector_type *bv, unsigned agr_group=0) BMNOEXCEPT
Attach source bit-vector to a argument group (0 or 1).
bool combine_and_sub(bvector_type &bv_target)
Aggregate added group of vectors using fused logical AND-SUB Operation does NOT perform an explicit r...
void combine_or(bvector_type &bv_target)
Aggregate added group of vectors using logical OR Operation does NOT perform an explicit reset of arg...
void combine_and(bvector_type &bv_target)
Aggregate added group of vectors using logical AND Operation does NOT perform an explicit reset of ar...
void merge(bm::bvector< Alloc > &bvect)
Merge/move content from another vector.
Definition bm.h:4724
bvector< Alloc > & invert()
Invert/NEG all bits It should be noted, invert is affected by size() if size is set - it only inverts...
Definition bm.h:2987
size_type size() const BMNOEXCEPT
Returns bvector's capacity (number of bits it can store)
Definition bm.h:1258
bm::bvector< Alloc > & bit_and(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand AND : this := bv1 AND bv2
Definition bm.h:5017
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:3581
void resize(size_type new_size)
Change size of the bvector.
Definition bm.h:2256
void optimize(bm::word_t *temp_block=0, optmode opt_mode=opt_compress, statistics *stat=0)
Optimize memory bitvector's memory allocation.
Definition bm.h:3071
bm::bvector< Alloc > & bit_or(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand OR : this := bv1 OR bv2
Definition bm.h:4809
enumerator first() const
Returns enumerator pointing on the first non-zero bit.
Definition bm.h:1770
bm::bvector< Alloc > & bit_sub(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand SUB : this := bv1 MINUS bv2 SUBtraction is also known as AND NOT
Definition bm.h:5111
void clear(const size_type *ids, size_type ids_size, bm::sort_order so=bm::BM_UNKNOWN)
clear list of bits in this bitset
Definition bm.h:3546
bm::bvector< Alloc > & bit_xor(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand XOR : this := bv1 XOR bv2
Definition bm.h:4906
void combine_operation(const bm::bvector< Alloc > &bvect, bm::operation opcode)
perform a set-algebra operation by operation code
Definition bm.h:5529
void keep(const size_type *ids, size_type ids_size, bm::sort_order so=bm::BM_UNKNOWN)
Keep list of bits in this bitset, others are cleared.
Definition bm.h:3518
Deserializer, performs logical operations between bit-vector and serialized bit-vector.
Definition bmserial.h:825
size_type deserialize(bvector_type &bv, const unsigned char *buf, set_operation op, bool exit_on_one=false)
Deserialize bvector using buffer as set operation argument.
Definition bmserial.h:5772
Bit-vector serialization class.
Definition bmserial.h:76
void set_compression_level(unsigned clevel) BMNOEXCEPT
Set compression level.
Definition bmserial.h:1119
size_type serialize(const BV &bv, unsigned char *buf, size_t buf_size)
Bitvector serialization into memory block.
Definition bmserial.h:2264
@ BM_SORTED
input set is sorted (ascending order)
Definition bmconst.h:191
@ BM_OR
Definition bmconst.h:178
@ BM_SUB
Definition bmconst.h:179
@ BM_XOR
Definition bmconst.h:180
@ BM_AND
Definition bmconst.h:177
@ set_OR
Definition bmconst.h:155
@ set_SUB
Definition bmconst.h:156
@ set_AND
Definition bmconst.h:154
@ set_XOR
Definition bmconst.h:157
void combine_and(BV &bv, It first, It last)
AND Combine bitvector and the iterable sequence.
void combine_sub(BV &bv, It first, It last)
SUB Combine bitvector and the iterable sequence.
void combine_xor(BV &bv, It first, It last)
XOR Combine bitvector and the iterable sequence.
void combine_or(BV &bv, It first, It last)
OR Combine bitvector and the iterable sequence.