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 bm::bvector::bit_or
28 \sa bm::bvector::bit_and
29 \sa bm::bvector::bit_xor
30 \sa bm::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 <assert.h>
51#include <iostream>
52#include <vector>
53
54#include "bm.h"
55#include "bmalgo.h"
56#include "bmserial.h"
57#include "bmaggregator.h"
58#include "bmundef.h" /* clear the pre-proc defines from BM */
59
60using namespace std;
61
62// utility function to print a set
63static
65{
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 intesect 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 Intersect (AND) operations fused with OR
511//
512static
514{
515 // bit-vector set intersect with fused OR: bv_R |= bv_A & bv_B
516 {
517 bm::bvector<> bv_R { 0, 5 };
518
519 bm::bvector<> bv_A { 1, 2, 3 };
520 bm::bvector<> bv_B { 1, 2, 4 };
521 bv_R.bit_or_and(bv_A, bv_B);
522
523 print_bvector(bv_R); // 0, 1, 2, 5
524 }
525
526 // same, but sizes are set, observe size gets extended up
527 {
528 bm::bvector<> bv_R { 0, 5 };
529 bv_R.resize(12);
530
531 bm::bvector<> bv_A { 1, 2, 3 };
532 bm::bvector<> bv_B { 1, 2, 4 };
533 bv_A.resize(5);
534 bv_B.resize(10);
535
536 bv_R.bit_or_and(bv_A, bv_B);
537
538 print_bvector(bv_R); // 0, 1, 2, 5 (size = 12)
539 }
540
541 // AND OR with aggregator pipeline
542
544
545 // Aggregator pipeline can efficiently run a group of AND (or AND-SUB)
546 // operations on bit-vectors, assuming that groups of ANDs are comprised
547 // of essentially the same super-set of vectors which are going to be
548 // reused (cached) by the CPU, thus run more efficintly
549 //
550 // In this case pipeline is configured to ignore the sub-results of AND
551 // operations and just UNION all set-results into a target bit-vector
552 // (logical OR)
553 //
554 // The formula here is:
555 // bv_TARGET = bv_TARGET OR (BV1 AND BV2) OR (BV1 & BV3) & (BV2 & BV3)
556 //
557 // This pipeline configuration avoids allocations of temporary vectors
558 // and CPU cache-friendly (thus fast)
559 //
560 bm::aggregator<bm::bvector<> >::pipeline<bm::agg_opt_disable_bvects_and_counts> agg_pipe;
561
562 bm::bvector<> bv_T { 0, 65536 };
563
564 bm::bvector<> bv_A { 1, 2, 3 };
565 bm::bvector<> bv_B { 1, 2 };
566 bm::bvector<> bv_C { 2, 3, 256 };
567
568 // feed input queries into pipeline
569 {
570 bm::aggregator<bm::bvector<> >::arg_groups* args;
571
572 // Define AND group 1 as: (A & B)
573 args = agg_pipe.add();
574 args->add(&bv_A, 0); // 0 - means AND arg group
575 args->add(&bv_B, 0);
576
577 // Define AND group 2 as: (B & C)
578 args = agg_pipe.add();
579 args->add(&bv_B, 0);
580 args->add(&bv_C, 0);
581 }
582
583 // T |= (A & B) | (B & C)
584 //
585 agg_pipe.set_or_target(&bv_T);
586
587 agg_pipe.complete(); // finish the pipeline configuration
588
589 // We use AND-MINUS operation but since we did not add any subtraction
590 // vectors the result will be just AND
591 //
592 agg.combine_and_sub(agg_pipe); // T |= (A & B) | (B & C)
593
594 print_bvector(bv_T); // 0, 1, 2, 65536
595}
596
597
598
599// -------------------------------------------------------------
600// Demo for Set Invert (NOT)
601//
602static
604{
605 // bit-vector invert operation
606 // by default it inverts the whole 32-bit space
607 {
608 bm::bvector<> bv_A { 4, 5, 6 };
609 bv_A.invert();
610
611 print_bvector(bv_A); // 0, 1, 2, 3, 7 ...
612 }
613
614 // bit-vector invert operation
615 // it is size bound, inverts within set limits
616 {
617 bm::bvector<> bv_A { 4, 5, 6 };
618 bv_A.resize(7);
619 bv_A.invert();
620
621 print_bvector(bv_A); // 0, 1, 2, 3, size = 7
622 }
623}
624
625
626// -------------------------------------------------------------
627// Demo for AND-SUB
628// AND-SUB implements a search pattern "all this but not that"
629//
630static
632{
634
635 // Operation on two groups of vectors using aggregator
636 // 1. Group 0 - find common subset (Set Intersect / AND)
637 // 2. Group 1 - find union (OR) of the group and SUBtract it from #1
638 //
639 // target := (A AND D AND ...) AND NOT (B OR C OR ...)
640 //
641 bm::bvector<> bv_A { 1, 2, 3, 4 };
642 bm::bvector<> bv_B { 1, 2 };
643 bm::bvector<> bv_C { 1, 2, 4 };
644 bm::bvector<> bv_D { 0, 2, 3, 4, 5 };
645
646 {
647 bm::bvector<> bv_T; // target vector
648
649 agg.set_optimization(); // perform on-the-fly optimization of result
650
651 // here we are really using AND SUB operation
652 // where group 0 is all ANDed and group 1 SUBtracted from the result
653 //
654 agg.add(&bv_A, 0); // add to group 0 for AND
655 agg.add(&bv_D, 0); //
656
657 agg.add(&bv_B, 1); // add to group 1 SUB tract from group 0 result
658 agg.add(&bv_C, 1);
659
660 agg.combine_and_sub(bv_T);
661
662 agg.reset(); // reset the aggregator parameters
663
664 print_bvector(bv_T); // 3
665 }
666
667 cout << endl;
668
669 // Next example shows how to run a group of AND-SUB queries
670 // using aggregator::pipeline
671 //
672 // Pipeline runs multiple search formulas, consiting of essentially the
673 // same super-set bit-vectors (vectors are re-used).
674 // This reuse opens an oppotinity to run groups of queries faster
675 // because of CPU cache reuse
676 //
677 {
678 // default pipeline configuration will produce intermediate results
679 // for all pipeline searches
680 //
681 bm::aggregator<bm::bvector<> >::pipeline<> agg_pipe;
682 bm::bvector<> bv_T;
683
684 // Configure 3 different AND-SUB queries based on the same set of vectors
685 //
686 // Note that if we don't add SUBtraction vectors it will work just as
687 // AND formula (AND_SET MINUS empty_set == AND_SET)
688 {
689 bm::aggregator<bm::bvector<> >::arg_groups* args;
690
691 args = agg_pipe.add();
692 // T1 := (A AND B) MINUS D
693 args->add(&bv_A, 0); // 0 - means AND arg group
694 args->add(&bv_B, 0);
695 args->add(&bv_D, 1); // 1 - means SUB arg group
696
697 // T2 := (A AND D) MINUS B
698 args = agg_pipe.add();
699 args->add(&bv_A, 0);
700 args->add(&bv_D, 0);
701 args->add(&bv_B, 1); // 1 - means SUB arg group
702
703 // T3 := D MINUS (C OR B)
704 // or
705 // T3 := (D AND NOT C) OR (D AND NOT B)
706 args = agg_pipe.add();
707 args->add(&bv_D, 0);
708 args->add(&bv_C, 1); // 1 - means SUB arg group
709 args->add(&bv_B, 1);
710 }
711 // this is optional, pipeline can run OR aggregate (UNION ALL)
712 // on all searches in the pipeline
713 //
714 // T = T OR T1 OR T2 OR T3
715 //
716 agg_pipe.set_or_target(&bv_T);
717
718 agg_pipe.complete(); // finish the configuration
719
720 agg.combine_and_sub(agg_pipe); // run the pipeline search
721
722 // now we iterate the results and print it all
723 // we expect 3 output vectors, one for each pipeline AND-SUB group
724 //
725 auto& res_vect = agg_pipe.get_bv_res_vector();
726 assert(res_vect.size()==3); // we expect 3 results
727 for (size_t i = 0; i < res_vect.size(); ++i)
728 {
729 const bm::bvector<>* bv = res_vect[i];
730 if (bv)
731 print_bvector(*bv); // 1
732 // 3, 4
733 // 0, 3, 5
734 else
735 cout << "Empty result" << endl; // possible outcome as a "not found"
736 } // for i
737
738 // OR target contains the UNION of all pipeline AND-SUB searches
739 //
740 print_bvector(bv_T); // 0, 1, 3, 4, 5,
741 }
742
743}
744
745
746
747int main(void)
748{
749 try
750 {
751 cout << endl << "Set Union (OR) demo" << endl << endl;
752 DemoOR();
753
754 cout << endl << "Set Intersect (AND) demo" << endl << endl;
755 DemoAND();
756
757 cout << endl << "XOR demo" << endl << endl;
758 DemoXOR();
759
760 cout << endl << "Set Minus (SUB/AND-NOT) demo" << endl << endl;
761 DemoSUB();
762
763 cout << endl << "Set Invert (NOT) demo" << endl << endl;
764 DemoINV();
765
766 cout << endl << "Set AND-SUB demo" << endl << endl;
767 DemoAND_SUB();
768
769 cout << endl << "Set AND-OR demo" << endl << endl;
770 DemoAND_OR();
771 }
772 catch(std::exception& ex)
773 {
774 std::cerr << ex.what() << std::endl;
775 }
776
777 return 0;
778}
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.
pre-processor un-defines to avoid global space pollution (internal)
static void DemoINV()
static void DemoXOR()
static void DemoOR()
static void DemoAND_OR()
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.
Definition: bmaggregator.h:122
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 reset()
Reset aggregate groups, forget all attached vectors.
Definition: bmaggregator.h:932
void combine_or(bvector_type &bv_target)
Aggregate added group of vectors using logical OR Operation does NOT perform an explicit reset of arg...
Definition: bmaggregator.h:994
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 set_optimization(typename bvector_type::optmode opt=bvector_type::opt_compress) BMNOEXCEPT
set on-the-fly bit-block compression By default aggregator does not try to optimize result,...
Definition: bmaggregator.h:359
size_t add(const bvector_type *bv, unsigned agr_group=0)
Attach source bit-vector to a argument group (0 or 1).
Definition: bmaggregator.h:986
Constant iterator designed to enumerate "ON" bits.
Definition: bm.h:603
bool valid() const BMNOEXCEPT
Checks if iterator is still valid.
Definition: bm.h:283
Bitvector Bit-vector container with runtime compression of bits.
Definition: bm.h:115
bm::bvector< Alloc > & bit_or(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand OR : this := bv1 OR bv2
Definition: bm.h:5668
void merge(bm::bvector< Alloc > &bvect)
Merge/move content from another vector.
Definition: bm.h:5578
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:3515
size_type size() const BMNOEXCEPT
Returns bvector's capacity (number of bits it can store)
Definition: bm.h:1278
bm::bvector< Alloc > & bit_and(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand AND : this := bv1 AND bv2
Definition: bm.h:5880
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
void resize(size_type new_size)
Change size of the bvector.
Definition: bm.h:2428
bm::bvector< Alloc > & bit_sub(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand SUB : this := bv1 MINUS bv2 SUBtraction is also known as AND NOT
Definition: bm.h:6092
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:3600
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
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:4114
void combine_operation(const bm::bvector< Alloc > &bvect, bm::operation opcode)
perform a set-algebra operation by operation code
Definition: bm.h:6512
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:4070
bm::bvector< Alloc > & bit_or_and(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand AND where result is ORed into the terget vector : this |= bv1 AND bv2 TARGET := TARGET OR (...
Definition: bm.h:5975
bm::bvector< Alloc > & bit_xor(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand XOR : this := bv1 XOR bv2
Definition: bm.h:5767
Deserializer, performs logical operations between bit-vector and serialized bit-vector.
Definition: bmserial.h:930
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:6579
Bit-vector serialization class.
Definition: bmserial.h:76
void set_compression_level(unsigned clevel) BMNOEXCEPT
Set compression level.
Definition: bmserial.h:1254
size_type serialize(const BV &bv, unsigned char *buf, size_t buf_size)
Bitvector serialization into memory block.
Definition: bmserial.h:2706
@ BM_SORTED
input set is sorted (ascending order)
Definition: bmconst.h:205
@ BM_OR
Definition: bmconst.h:192
@ BM_SUB
Definition: bmconst.h:193
@ BM_XOR
Definition: bmconst.h:194
@ BM_AND
Definition: bmconst.h:191
@ set_OR
Definition: bmconst.h:169
@ set_SUB
Definition: bmconst.h:170
@ set_AND
Definition: bmconst.h:168
@ set_XOR
Definition: bmconst.h:171
void combine_and(BV &bv, It first, It last)
AND Combine bitvector and the iterable sequence.
Definition: bmalgo_impl.h:1365
void combine_sub(BV &bv, It first, It last)
SUB Combine bitvector and the iterable sequence.
Definition: bmalgo_impl.h:1248
void combine_xor(BV &bv, It first, It last)
XOR Combine bitvector and the iterable sequence.
Definition: bmalgo_impl.h:1161
void combine_or(BV &bv, It first, It last)
OR Combine bitvector and the iterable sequence.
Definition: bmalgo_impl.h:1080