BitMagic-C++
bmalgo_impl.h
Go to the documentation of this file.
1#ifndef BMALGO_IMPL__H__INCLUDED__
2#define BMALGO_IMPL__H__INCLUDED__
3/*
4Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18For more information please visit: http://bitmagic.io
19*/
20
21/*! \file bmalgo_impl.h
22 \brief Algorithms for bvector<>
23*/
24
25#ifdef _MSC_VER
26#pragma warning( push )
27#pragma warning( disable : 4311 4312 4127)
28#endif
29
30#include "bmdef.h"
31#include "bmutil.h"
32
33namespace bm
34{
35
36/*!
37 @defgroup setalgo bvector<> algorithms
38
39 Set algebra algorithms using bit-vectors, arrays.
40 Binary metrics and distances. Random sub-sets.
41
42 @ingroup bvector
43 */
44
45/*!
46 @defgroup distance Binary-distance metrics
47
48 Distance metrics and algorithms to compute binary distances
49 @ingroup setalgo
50 */
51
52
53/*!
54 \brief Distance metrics codes defined for vectors A and B
55 \ingroup distance
56*/
58{
59 COUNT_AND = set_COUNT_AND, //!< (A & B).count()
60 COUNT_XOR = set_COUNT_XOR, //!< (A ^ B).count()
61 COUNT_OR = set_COUNT_OR, //!< (A | B).count()
62 COUNT_SUB_AB = set_COUNT_SUB_AB, //!< (A - B).count()
63 COUNT_SUB_BA = set_COUNT_SUB_BA, //!< (B - A).count()
64 COUNT_A = set_COUNT_A, //!< A.count()
65 COUNT_B = set_COUNT_B //!< B.count()
66};
67
68/**
69 Convert set operation into compatible distance metric
70 \ingroup distance
71*/
72inline
74{
76 if (op == set_COUNT) op = set_COUNT_B;
77 // distance metric is created as a set operation sub-class
78 // simple cast will work to convert
79 return (distance_metric) op;
80}
81
82/*!
83 \brief Distance metric descriptor, holds metric code and result.
84 \sa distance_operation
85*/
87{
88#ifdef BM64ADDR
89 typedef bm::id64_t size_type;
90#else
92#endif
93
96
98 : metric(m),
99 result(0)
100 {}
102 : metric(bm::COUNT_XOR),
103 result(0)
104 {}
105
106 /*!
107 \brief Sets metric result to 0
108 */
110 {
111 result = 0;
112 }
113};
114
115/// functor-adaptor for C-style callbacks
116///
117/// @internal
118///
119template <class VCBT, class size_type>
121{
123
125 : handle_(h), func_(cb_func)
126 {}
127
128 int add_bits(size_type offset, const unsigned char* bits, unsigned size)
129 {
130 for (unsigned i = 0; i < size; ++i)
131 {
132 int ret = func_(handle_, offset + bits[i]);
133 if (ret < 0)
134 return ret;
135 }
136 return 0;
137 }
138 int add_range(size_type offset, size_type size)
139 {
140 for (size_type i = 0; i < size; ++i)
141 {
142 int ret = func_(handle_, offset + i);
143 if (ret < 0)
144 return ret;
145 }
146 return 0;
147 }
148
149 void* handle_;
151};
152
153/// functor-adaptor for back-inserter
154///
155/// @internal
156///
157template <class BII, class size_type>
159{
160
162 : bi_(bi)
163 {}
164
165 int add_bits(size_type offset, const unsigned char* bits, unsigned size)
166 {
167 for (unsigned i = 0; i < size; ++i)
168 *bi_ = offset + bits[i];
169 return 0;
170 }
171 int add_range(size_type offset, size_type size)
172 {
173 for (size_type i = 0; i < size; ++i)
174 *bi_ = offset + i;
175 return 0;
176 }
177
178 BII bi_;
179};
180
181
182/*!
183 \brief Internal function computes different distance metrics.
184 \internal
185 \ingroup distance
186
187*/
188inline
190 const bm::word_t* arg_blk,
193
194{
195 gap_word_t* g1 = BMGAP_PTR(blk);
196 gap_word_t* g2 = BMGAP_PTR(arg_blk);
197
198 unsigned gap = BM_IS_GAP(blk);
199 unsigned arg_gap = BM_IS_GAP(arg_blk);
200
201 if (gap) // first block GAP-type
202 {
203 if (arg_gap) // both blocks GAP-type
204 {
205 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
206 {
208
209 switch (dmd.metric)
210 {
211 case bm::COUNT_AND:
212 dmd.result += gap_count_and(g1, g2);
213 break;
214 case bm::COUNT_OR:
215 dmd.result += gap_count_or(g1, g2);
216 break;
217 case bm::COUNT_SUB_AB:
218 dmd.result += gap_count_sub(g1, g2);
219 break;
220 case bm::COUNT_SUB_BA:
221 dmd.result += gap_count_sub(g2, g1);
222 break;
223 case bm::COUNT_XOR:
224 dmd.result += gap_count_xor(g1, g2);
225 break;
226 case bm::COUNT_A:
227 dmd.result += gap_bit_count_unr(g1);
228 break;
229 case bm::COUNT_B:
230 dmd.result += gap_bit_count_unr(g2);
231 break;
232 default:
233 BM_ASSERT(0);
234 } // switch
235
236 } // for it
237
238 return;
239
240 }
241 else // first block - GAP, argument - BITSET
242 {
243 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
244 {
246
247 switch (dmd.metric)
248 {
249 case bm::COUNT_AND:
250 if (arg_blk)
251 dmd.result += gap_bitset_and_count(arg_blk, g1);
252 break;
253 case bm::COUNT_OR:
254 if (!arg_blk)
255 dmd.result += gap_bit_count_unr(g1);
256 else
257 dmd.result += gap_bitset_or_count(arg_blk, g1);
258 break;
259 case bm::COUNT_SUB_AB:
260 {
262
263 gap_convert_to_bitset((bm::word_t*) temp_bit_blk, g1);
264 dmd.result +=
265 bit_operation_sub_count((bm::word_t*)temp_bit_blk, arg_blk);
266 }
267 break;
268 case bm::COUNT_SUB_BA:
269 dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB
271 blk,
272 it, it+1);
273 dmd.metric = bm::COUNT_SUB_BA; // restore status quo
274 break;
275 case bm::COUNT_XOR:
276 if (!arg_blk)
277 dmd.result += gap_bit_count_unr(g1);
278 else
279 dmd.result += gap_bitset_xor_count(arg_blk, g1);
280 break;
281 case bm::COUNT_A:
282 if (g1)
283 dmd.result += gap_bit_count_unr(g1);
284 break;
285 case bm::COUNT_B:
286 if (arg_blk)
287 {
288 dmd.result +=
289 bit_block_count(arg_blk);
290 }
291 break;
292 default:
293 BM_ASSERT(0);
294 } // switch
295
296 } // for it
297
298 return;
299
300 }
301 }
302 else // first block is BITSET-type
303 {
304 if (arg_gap) // second argument block is GAP-type
305 {
306 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
307 {
309
310 switch (dmd.metric)
311 {
312 case bm::COUNT_AND:
313 if (blk)
314 dmd.result += gap_bitset_and_count(blk, g2);
315 break;
316 case bm::COUNT_OR:
317 if (!blk)
318 dmd.result += gap_bit_count_unr(g2);
319 else
320 dmd.result += gap_bitset_or_count(blk, g2);
321 break;
322 case bm::COUNT_SUB_AB:
323 if (blk)
324 dmd.result += gap_bitset_sub_count(blk, g2);
325 break;
326 case bm::COUNT_SUB_BA:
327 dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB
329 //arg_gap,
330 blk,
331 //gap,
332 it, it+1);
333 dmd.metric = bm::COUNT_SUB_BA; // restore status quo
334 break;
335 case bm::COUNT_XOR:
336 if (!blk)
337 dmd.result += gap_bit_count_unr(g2);
338 else
339 dmd.result += gap_bitset_xor_count(blk, g2);
340 break;
341 case bm::COUNT_A:
342 if (blk)
343 {
344 dmd.result +=
345 bit_block_count(blk);
346 }
347 break;
348 case bm::COUNT_B:
349 if (g2)
350 dmd.result += gap_bit_count_unr(g2);
351 break;
352 default:
353 BM_ASSERT(0);
354 } // switch
355
356 } // for it
357
358 return;
359 }
360 }
361
362 // --------------------------------------------
363 //
364 // Here we combine two plain bitblocks
365
366 for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
367 {
371 if (gfunc)
372 {
373 dmd.result += (*gfunc)(blk, arg_blk);
374 }
375 else
376 {
377 switch (dmd.metric)
378 {
379 case bm::COUNT_A:
380 if (blk)
381 dmd.result += bm::bit_block_count(blk);
382 break;
383 case bm::COUNT_B:
384 if (arg_blk)
385 dmd.result += bm::bit_block_count(arg_blk);
386 break;
387 case bm::COUNT_AND:
388 case bm::COUNT_XOR:
389 case bm::COUNT_OR:
390 case bm::COUNT_SUB_AB:
391 case bm::COUNT_SUB_BA:
392 default:
393 BM_ASSERT(0);
394 } // switch
395 }
396
397 } // for it
398}
399
400/*!
401\brief Internal function computes AND distance.
402\internal
403\ingroup distance
404*/
405inline
407 const bm::word_t* arg_blk) BMNOEXCEPT
408{
409 unsigned gap = BM_IS_GAP(blk);
410 unsigned arg_gap = BM_IS_GAP(arg_blk);
411 if (gap) // first block GAP-type
412 {
413 if (arg_gap) // both blocks GAP-type
414 {
415 return gap_count_and(BMGAP_PTR(blk), BMGAP_PTR(arg_blk));
416 }
417 else // first block - GAP, argument - BITSET
418 {
419 return gap_bitset_and_count(arg_blk, BMGAP_PTR(blk));
420 }
421 }
422 else // first block is BITSET-type
423 {
424 if (arg_gap) // second argument block is GAP-type
425 {
426 return gap_bitset_and_count(blk, BMGAP_PTR(arg_blk));
427 }
428 }
429
430 // --------------------------------------------
431 // Here we combine two plain bitblocks
432
433 return bit_operation_and_count(blk, arg_blk);
434}
435
436
437/*!
438 \brief Internal function computes different existense of distance metric.
439 \internal
440 \ingroup distance
441*/
442inline
444 unsigned gap,
445 const bm::word_t* arg_blk,
446 unsigned arg_gap,
449
450{
451 gap_word_t* res=0;
452
453 gap_word_t* g1 = BMGAP_PTR(blk);
454 gap_word_t* g2 = BMGAP_PTR(arg_blk);
455
456 if (gap) // first block GAP-type
457 {
458 if (arg_gap) // both blocks GAP-type
459 {
460 gap_word_t tmp_buf[bm::gap_max_buff_len * 3]; // temporary result
461
462 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
463 {
465 if (dmd.result)
466 {
467 continue;
468 }
469 res = 0;
470 unsigned dsize = 0;
471 switch (dmd.metric)
472 {
473 case bm::COUNT_AND:
474 dmd.result += gap_operation_any_and(g1, g2);
475 break;
476 case bm::COUNT_OR:
477 res = gap_operation_or(g1, g2, tmp_buf, dsize);
478 break;
479 case bm::COUNT_SUB_AB:
480 dmd.result += gap_operation_any_sub(g1, g2);
481 break;
482 case bm::COUNT_SUB_BA:
483 dmd.result += gap_operation_any_sub(g2, g1);
484 break;
485 case bm::COUNT_XOR:
486 dmd.result += gap_operation_any_xor(g1, g2);
487 break;
488 case bm::COUNT_A:
489 res = g1;
490 break;
491 case bm::COUNT_B:
492 res = g2;
493 break;
494 default:
495 BM_ASSERT(0);
496 } // switch
497 if (res)
498 dmd.result += !gap_is_all_zero(res);
499
500 } // for it
501
502 return;
503
504 }
505 else // first block - GAP, argument - BITSET
506 {
507 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
508 {
510 if (dmd.result)
511 {
512 continue;
513 }
514
515 switch (dmd.metric)
516 {
517 case bm::COUNT_AND:
518 if (arg_blk)
519 dmd.result += gap_bitset_and_any(arg_blk, g1);
520 break;
521 case bm::COUNT_OR:
522 if (!arg_blk)
523 dmd.result += !gap_is_all_zero(g1);
524 else
525 dmd.result += gap_bitset_or_any(arg_blk, g1);
526 break;
527 case bm::COUNT_SUB_AB:
528 {
530 gap_convert_to_bitset((bm::word_t*) temp_blk, g1);
531 dmd.result +=
532 bit_operation_sub_any((bm::word_t*)temp_blk, arg_blk);
533 }
534 break;
535 case bm::COUNT_SUB_BA:
536 dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB
538 arg_gap,
539 blk,
540 gap,
541 it, it+1);
542 dmd.metric = bm::COUNT_SUB_BA; // restore status quo
543 break;
544 case bm::COUNT_XOR:
545 if (!arg_blk)
546 dmd.result += !gap_is_all_zero(g1);
547 else
548 dmd.result += gap_bitset_xor_any(arg_blk, g1);
549 break;
550 case bm::COUNT_A:
551 if (g1)
552 dmd.result += !gap_is_all_zero(g1);
553 break;
554 case bm::COUNT_B:
555 if (arg_blk)
556 {
557 dmd.result +=
558 !bit_is_all_zero(arg_blk);
559 }
560 break;
561 default:
562 BM_ASSERT(0);
563 } // switch
564
565 } // for it
566
567 return;
568
569 }
570 }
571 else // first block is BITSET-type
572 {
573 if (arg_gap) // second argument block is GAP-type
574 {
575 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
576 {
578 if (dmd.result)
579 {
580 continue;
581 }
582
583 switch (dmd.metric)
584 {
585 case bm::COUNT_AND:
586 if (blk)
587 dmd.result += gap_bitset_and_any(blk, g2);
588 break;
589 case bm::COUNT_OR:
590 if (!blk)
591 dmd.result += !gap_is_all_zero(g2);
592 else
593 dmd.result += gap_bitset_or_any(blk, g2);
594 break;
595 case bm::COUNT_SUB_AB:
596 if (blk)
597 dmd.result += gap_bitset_sub_any(blk, g2);
598 break;
599 case bm::COUNT_SUB_BA:
600 dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB
602 arg_gap,
603 blk,
604 gap,
605 it, it+1);
606 dmd.metric = bm::COUNT_SUB_BA; // restore status quo
607 break;
608 case bm::COUNT_XOR:
609 if (!blk)
610 dmd.result += !gap_is_all_zero(g2);
611 else
612 dmd.result += gap_bitset_xor_any(blk, g2);
613 break;
614 case bm::COUNT_A:
615 if (blk)
616 {
617 dmd.result+=
619 }
620 break;
621 case bm::COUNT_B:
622 if (g2)
623 dmd.result += !gap_is_all_zero(g2);
624 break;
625 default:
626 BM_ASSERT(0);
627 } // switch
628
629 } // for it
630
631 return;
632 }
633 }
634
635 // --------------------------------------------
636 //
637 // Here we combine two plain bitblocks
638
639 for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
640 {
642 if (dmd.result)
643 {
644 continue;
645 }
646
647 switch (dmd.metric)
648 {
649 case bm::COUNT_AND:
650 dmd.result +=
651 bit_operation_and_any(blk, arg_blk);
652 break;
653 case bm::COUNT_OR:
654 dmd.result +=
655 bit_operation_or_any(blk, arg_blk);
656 break;
657 case bm::COUNT_SUB_AB:
658 dmd.result +=
659 bit_operation_sub_any(blk, arg_blk);
660 break;
661 case bm::COUNT_SUB_BA:
662 dmd.result +=
663 bit_operation_sub_any(arg_blk, blk);
664 break;
665 case bm::COUNT_XOR:
666 dmd.result +=
667 bit_operation_xor_any(blk, arg_blk);
668 break;
669 case bm::COUNT_A:
670 if (blk)
671 dmd.result += !bit_is_all_zero(blk);
672 break;
673 case bm::COUNT_B:
674 if (arg_blk)
675 dmd.result += !bit_is_all_zero(arg_blk);
676 break;
677 default:
678 BM_ASSERT(0);
679 } // switch
680
681 } // for it
682}
683
684
685
686/*!
687 Convenience internal function to compute combine count for one metric
688 \internal
689 \ingroup distance
690*/
691inline
692unsigned
694 const bm::word_t* arg_blk,
696{
697 distance_metric_descriptor dmd(metric);
699 arg_blk, //arg_gap,
700 &dmd, &dmd+1);
701 return unsigned(dmd.result);
702}
703
704
705/*!
706 Convenience internal function to compute combine any for one metric
707 \internal
708 \ingroup distance
709*/
710inline
713 unsigned gap,
714 const bm::word_t* arg_blk,
715 unsigned arg_gap,
717{
718 distance_metric_descriptor dmd(metric);
720 arg_blk, arg_gap,
721 &dmd, &dmd+1);
722 return dmd.result;
723}
724
725/*!
726 \brief Staging function for distance operation
727
728 \return temp block allocated (or NULL)
729
730 \internal
731*/
732inline
734 const distance_metric_descriptor* dmit_end,
735 bool* is_all_and) BMNOEXCEPT
736{
737 for (const distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
738 {
739 if (it->metric != bm::COUNT_AND)
740 {
741 *is_all_and = false;
742 }
743 } // for
744}
745
746/*!
747 \brief Distance computing template function.
748
749 Function receives two bitvectors and an array of distance metrics
750 (metrics pipeline). Function computes all metrics saves result into
751 corresponding pipeline results (distance_metric_descriptor::result)
752 An important detail is that function reuses metric descriptors,
753 incrementing received values. It allows you to accumulate results
754 from different calls in the pipeline.
755
756 \param bv1 - argument bitvector 1 (A)
757 \param bv2 - argument bitvector 2 (B)
758 \param dmit - pointer to first element of metric descriptors array
759 Input-Output parameter, receives metric code as input,
760 computation is added to "result" field
761 \param dmit_end - pointer to (last+1) element of metric descriptors array
762 \ingroup distance
763
764*/
765template<class BV>
766void distance_operation(const BV& bv1,
767 const BV& bv2,
770{
771 const typename BV::blocks_manager_type& bman1 = bv1.get_blocks_manager();
772 const typename BV::blocks_manager_type& bman2 = bv2.get_blocks_manager();
773
774 bool is_all_and = true; // flag is distance operation is just COUNT_AND
775 distance_stage(dmit, dmit_end, &is_all_and);
776
777 bm::word_t*** blk_root = bman1.top_blocks_root();
778 typename BV::size_type block_idx = 0;
779 unsigned i, j;
780
781 const bm::word_t* blk;
782 const bm::word_t* arg_blk;
783
784 unsigned top_block_size = bman1.top_block_size();
785 unsigned ebs2 = bman2.top_block_size();
786 unsigned top_size;
787 if (ebs2 > top_block_size)
788 top_size = ebs2;
789 else
790 top_size = top_block_size;
791
792 for (i = 0; i < top_size; ++i)
793 {
794 bm::word_t** blk_blk = (blk_root && (i < top_block_size)) ? blk_root[i] : 0;
795 if (!blk_blk)
796 {
797 // AND operation requested - we can skip this portion here
798 if (is_all_and)
799 {
800 block_idx += bm::set_sub_array_size;
801 continue;
802 }
803 const bm::word_t* const* bvbb = bman2.get_topblock(i);
804 if (bvbb == 0)
805 {
806 block_idx += bm::set_sub_array_size;
807 continue;
808 }
809
810 blk = 0;
811 for (j = 0; j < bm::set_sub_array_size; ++j,++block_idx)
812 {
813 arg_blk = bman2.get_block(i, j);
814 if (!arg_blk)
815 continue;
817 arg_blk,
818 dmit, dmit_end);
819 } // for j
820 continue;
821 }
822
823 for (j = 0; j < bm::set_sub_array_size; ++j, ++block_idx)
824 {
825 blk = bman1.get_block(i, j);
826 if (blk == 0 && is_all_and)
827 continue;
828
829 arg_blk = bman2.get_block(i, j);
830
831 if (!blk & !arg_blk)
832 continue;
833
835 arg_blk,
836 dmit, dmit_end);
837 } // for j
838
839 } // for i
840}
841
842
843/*!
844\brief Distance AND computing template function.
845
846
847\param bv1 - argument bitvector 1 (A)
848\param bv2 - argument bitvector 2 (B)
849\ingroup distance
850
851*/
852template<class BV>
853typename BV::size_type distance_and_operation(const BV& bv1,
854 const BV& bv2) BMNOEXCEPT
855{
856 const typename BV::blocks_manager_type& bman1 = bv1.get_blocks_manager();
857 const typename BV::blocks_manager_type& bman2 = bv2.get_blocks_manager();
858
859 if (!bman1.is_init() || !bman2.is_init())
860 return 0;
861
862 bm::word_t*** blk_root = bman1.top_blocks_root();
863 bm::word_t*** blk_root_arg = bman2.top_blocks_root();
864 typename BV::size_type count = 0;
865
866 unsigned top_block_size =
867 bm::min_value(bman1.top_block_size(),bman2.top_block_size());
868
869 for (unsigned i = 0; i < top_block_size; ++i)
870 {
871 bm::word_t** blk_blk;
872 bm::word_t** blk_blk_arg;
873 if ((blk_blk = blk_root[i]) == 0 || (blk_blk_arg= blk_root_arg[i]) == 0)
874 continue;
875
876 if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
877 blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
878 if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
879 blk_blk_arg = FULL_SUB_BLOCK_REAL_ADDR;
880
881 for (unsigned j = 0; j < bm::set_sub_array_size; j+=4)
882 {
883 (blk_blk[j] && blk_blk_arg[j]) ?
884 count += combine_count_and_operation_with_block(BLOCK_ADDR_SAN(blk_blk[j]), BLOCK_ADDR_SAN(blk_blk_arg[j]))
885 :0;
886 (blk_blk[j+1] && blk_blk_arg[j+1]) ?
887 count += combine_count_and_operation_with_block(BLOCK_ADDR_SAN(blk_blk[j+1]), BLOCK_ADDR_SAN(blk_blk_arg[j+1]))
888 :0;
889 (blk_blk[j+2] && blk_blk_arg[j+2]) ?
890 count += combine_count_and_operation_with_block(BLOCK_ADDR_SAN(blk_blk[j+2]), BLOCK_ADDR_SAN(blk_blk_arg[j+2]))
891 :0;
892 (blk_blk[j+3] && blk_blk_arg[j+3]) ?
893 count += combine_count_and_operation_with_block(BLOCK_ADDR_SAN(blk_blk[j+3]), BLOCK_ADDR_SAN(blk_blk_arg[j+3]))
894 :0;
895 } // for j
896
897 } // for i
898 return count;
899}
900
901
902/*!
903 \brief Distance screening template function.
904
905 Function receives two bitvectors and an array of distance metrics
906 (metrics pipeline). Function computes possybility of a metric(any bit)
907 saves result into corresponding pipeline results
908 (distance_metric_descriptor::result)
909 An important detail is that function reuses metric descriptors,
910 incrementing received values. It allows you to accumulate results
911 from different calls in the pipeline.
912
913 \param bv1 - argument bitvector 1 (A)
914 \param bv2 - argument bitvector 2 (B)
915 \param dmit - pointer to first element of metric descriptors array
916 Input-Output parameter, receives metric code as input,
917 computation is added to "result" field
918 \param dmit_end - pointer to (last+1) element of metric descriptors array
919 \ingroup distance
920*/
921template<class BV>
922void distance_operation_any(const BV& bv1,
923 const BV& bv2,
926{
927 const typename BV::blocks_manager_type& bman1 = bv1.get_blocks_manager();
928 const typename BV::blocks_manager_type& bman2 = bv2.get_blocks_manager();
929
930 bool is_all_and = true; // flag is distance operation is just COUNT_AND
931 distance_stage(dmit, dmit_end, &is_all_and);
932
933 bm::word_t*** blk_root = bman1.top_blocks_root();
934 unsigned block_idx = 0;
935 unsigned i, j;
936
937 const bm::word_t* blk;
938 const bm::word_t* arg_blk;
939 bool blk_gap;
940 bool arg_gap;
941
942 unsigned top_block_size = bman1.top_block_size();
943 unsigned ebs2 = bman2.top_block_size();
944 unsigned top_size;
945 if (ebs2 > top_block_size)
946 top_size = ebs2;
947 else
948 top_size = top_block_size;
949
950 for (i = 0; i < top_size; ++i)
951 {
952 bm::word_t** blk_blk = (blk_root && (i < top_block_size)) ? blk_root[i] : 0;
953 if (blk_blk == 0) // not allocated
954 {
955 // AND operation requested - we can skip this portion here
956 if (is_all_and)
957 {
958 block_idx += bm::set_sub_array_size;
959 continue;
960 }
961
962 const bm::word_t* const* bvbb = bman2.get_topblock(i);
963 if (bvbb == 0)
964 {
965 block_idx += bm::set_sub_array_size;
966 continue;
967 }
968
969 blk = 0;
970 blk_gap = false;
971
972 for (j = 0; j < bm::set_sub_array_size; ++j,++block_idx)
973 {
974 arg_blk = bman2.get_block(i, j);
975 if (!arg_blk)
976 continue;
977 arg_gap = BM_IS_GAP(arg_blk);
978
980 arg_blk, arg_gap,
981 dmit, dmit_end);
982
983 // check if all distance requests alredy resolved
984 bool all_resolved = false;
986 do
987 {
988 if (!it->result)
989 {
990 all_resolved = false;
991 break;
992 }
993 ++it;
994 } while (it < dmit_end);
995 if (all_resolved)
996 return;
997 } // for j
998
999 continue;
1000 }
1001
1002 for (j = 0; j < bm::set_sub_array_size; ++j, ++block_idx)
1003 {
1004 blk = bman1.get_block(i, j);
1005 if (blk == 0 && is_all_and)
1006 continue;
1007
1008 arg_blk = bman2.get_block(i, j);
1009
1010 if (blk == 0 && arg_blk == 0)
1011 continue;
1012
1013 arg_gap = BM_IS_GAP(arg_blk);
1014 blk_gap = BM_IS_GAP(blk);
1015
1017 arg_blk, arg_gap,
1018 dmit, dmit_end);
1019
1020 // check if all distance requests alredy resolved
1021 bool all_resolved = true;
1023 do
1024 {
1025 if (!it->result)
1026 {
1027 all_resolved = false;
1028 break;
1029 }
1030 ++it;
1031 } while (it < dmit_end);
1032 if (all_resolved)
1033 return;
1034
1035 } // for j
1036
1037 } // for i
1038}
1039
1040
1041
1042/**
1043 \brief Internal algorithms scans the input for the block range limit
1044 \internal
1045*/
1046template<typename It, typename SIZE_TYPE>
1047It block_range_scan(It first, It last,
1048 SIZE_TYPE nblock, SIZE_TYPE* max_id) BMNOEXCEPT
1049{
1050 SIZE_TYPE m = *max_id;
1051 It right;
1052 for (right = first; right != last; ++right)
1053 {
1054 SIZE_TYPE v = SIZE_TYPE(*right);
1055 BM_ASSERT(v < bm::id_max);
1056 if (v >= m)
1057 m = v;
1058 SIZE_TYPE nb = v >> bm::set_block_shift;
1059 if (nb != nblock)
1060 break;
1061 }
1062 *max_id = m;
1063 return right;
1064}
1065
1066/**
1067 \brief OR Combine bitvector and the iterable sequence
1068
1069 Algorithm combines bvector with sequence of integers
1070 (represents another set). When the agrument set is sorted
1071 this method can give serious increase in performance.
1072
1073 \param bv - destination bitvector
1074 \param first - first element of the iterated sequence
1075 \param last - last element of the iterated sequence
1076
1077 \ingroup setalgo
1078*/
1079template<class BV, class It>
1080void combine_or(BV& bv, It first, It last)
1081{
1082 typedef typename BV::size_type size_type;
1083 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
1084 if (!bman.is_init())
1085 bman.init_tree();
1086
1087 size_type max_id = 0;
1088
1089 while (first < last)
1090 {
1091 typename BV::block_idx_type nblock = (*first) >> bm::set_block_shift;
1092 It right = bm::block_range_scan(first, last, nblock, &max_id);
1093 if (max_id >= bv.size())
1094 {
1095 BM_ASSERT(max_id < bm::id_max);
1096 bv.resize(max_id + 1);
1097 }
1098
1099 // now we have one in-block array of bits to set
1100
1101 label1:
1102
1103 int block_type;
1104 bm::word_t* blk =
1105 bman.check_allocate_block(nblock,
1106 true,
1107 bv.get_new_blocks_strat(),
1108 &block_type);
1109 if (!blk)
1110 continue;
1111
1112 if (block_type == 1) // gap
1113 {
1114 bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
1115 unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
1116
1117 for (; first < right; ++first)
1118 {
1119 unsigned is_set;
1120 unsigned nbit = (*first) & bm::set_block_mask;
1121
1122 unsigned new_block_len =
1123 bm::gap_set_value(true, gap_blk, nbit, &is_set);
1124 if (new_block_len > threshold)
1125 {
1126 bman.extend_gap_block(nblock, gap_blk);
1127 ++first;
1128 goto label1; // block pointer changed - goto reset
1129 }
1130 }
1131 }
1132 else // bit block
1133 {
1134 for (; first < right; ++first)
1135 {
1136 size_type pos = *first;
1137 unsigned nbit = unsigned(pos & bm::set_block_mask);
1138 unsigned nword = unsigned(nbit >> bm::set_word_shift);
1139 nbit &= bm::set_word_mask;
1140 blk[nword] |= (1u << nbit);
1141 } // for
1142 }
1143 } // while
1144}
1145
1146
1147/**
1148 \brief XOR Combine bitvector and the iterable sequence
1149
1150 Algorithm combines bvector with sequence of integers
1151 (represents another set). When the agrument set is sorted
1152 this method can give serious increase in performance.
1153
1154 \param bv - destination bitvector
1155 \param first - first element of the iterated sequence
1156 \param last - last element of the iterated sequence
1157
1158 \ingroup setalgo
1159*/
1160template<class BV, class It>
1161void combine_xor(BV& bv, It first, It last)
1162{
1163 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
1164 if (!bman.is_init())
1165 bman.init_tree();
1166
1167 typename BV::size_type max_id = 0;
1168
1169 while (first < last)
1170 {
1171 typename BV::block_idx_type nblock = ((*first) >> bm::set_block_shift);
1172 It right = block_range_scan(first, last, nblock, &max_id);
1173
1174 if (max_id >= bv.size())
1175 {
1176 BM_ASSERT(max_id < bm::id_max);
1177 bv.resize(max_id + 1);
1178 }
1179
1180 // now we have one in-block array of bits to set
1181
1182 label1:
1183
1184 int block_type;
1185 bm::word_t* blk =
1186 bman.check_allocate_block(nblock,
1187 true,
1188 bv.get_new_blocks_strat(),
1189 &block_type,
1190 false /* no null return */);
1191 BM_ASSERT(blk);
1192
1193 if (block_type == 1) // gap
1194 {
1195 bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
1196 unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
1197
1198 for (; first < right; ++first)
1199 {
1200 unsigned is_set;
1201 unsigned nbit = (*first) & bm::set_block_mask;
1202
1203 is_set = bm::gap_test_unr(gap_blk, nbit);
1204 BM_ASSERT(is_set <= 1);
1205 is_set ^= 1;
1206
1207 unsigned new_block_len =
1208 gap_set_value(is_set, gap_blk, nbit, &is_set);
1209 if (new_block_len > threshold)
1210 {
1211 bman.extend_gap_block(nblock, gap_blk);
1212 ++first;
1213 goto label1; // block pointer changed - goto reset
1214 }
1215 }
1216 }
1217 else // bit block
1218 {
1219 for (; first < right; ++first)
1220 {
1221 unsigned nbit = unsigned(*first & bm::set_block_mask);
1222 unsigned nword = unsigned(nbit >> bm::set_word_shift);
1223 nbit &= bm::set_word_mask;
1224 blk[nword] ^= (1u << nbit);
1225 } // for
1226 }
1227 } // while
1228
1229 bv.forget_count();
1230}
1231
1232
1233
1234/**
1235 \brief SUB Combine bitvector and the iterable sequence
1236
1237 Algorithm combines bvector with sequence of integers
1238 (represents another set). When the agrument set is sorted
1239 this method can give serious increase in performance.
1240
1241 \param bv - destination bitvector
1242 \param first - first element of the iterated sequence
1243 \param last - last element of the iterated sequence
1244
1245 \ingroup setalgo
1246*/
1247template<class BV, class It>
1248void combine_sub(BV& bv, It first, It last)
1249{
1250 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
1251 if (!bman.is_init())
1252 bman.init_tree();
1253
1254 typename BV::size_type max_id = 0;
1255
1256 while (first < last)
1257 {
1258 typename BV::block_idx_type nblock = (*first) >> bm::set_block_shift;
1259 It right = bm::block_range_scan(first, last, nblock, &max_id);
1260
1261 if (max_id >= bv.size())
1262 {
1263 BM_ASSERT(max_id < bm::id_max);
1264 bv.resize(max_id + 1);
1265 }
1266
1267 // now we have one in-block array of bits to set
1268
1269 label1:
1270
1271 int block_type;
1272 bm::word_t* blk =
1273 bman.check_allocate_block(nblock,
1274 false,
1275 bv.get_new_blocks_strat(),
1276 &block_type);
1277
1278 if (!blk)
1279 continue;
1280
1281 if (block_type == 1) // gap
1282 {
1283 bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
1284 unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
1285
1286 for (; first < right; ++first)
1287 {
1288 unsigned is_set;
1289 unsigned nbit = (*first) & bm::set_block_mask;
1290
1291 is_set = bm::gap_test_unr(gap_blk, nbit);
1292 if (!is_set)
1293 continue;
1294
1295 unsigned new_block_len =
1296 gap_set_value(false, gap_blk, nbit, &is_set);
1297 if (new_block_len > threshold)
1298 {
1299 bman.extend_gap_block(nblock, gap_blk);
1300 ++first;
1301 goto label1; // block pointer changed - goto reset
1302 }
1303 }
1304 }
1305 else // bit block
1306 {
1307 for (; first < right; ++first)
1308 {
1309 unsigned nbit = unsigned(*first & bm::set_block_mask);
1310 unsigned nword = unsigned(nbit >> bm::set_word_shift);
1311 nbit &= bm::set_word_mask;
1312 blk[nword] &= ~((bm::word_t)1 << nbit);
1313 } // for
1314 }
1315 } // while
1316
1317 bv.forget_count();
1318}
1319
1320/**
1321 \brief AND Combine bitvector and the iterable sequence
1322
1323 Algorithm combines bvector with sorted sequence of integers
1324 (represents another set).
1325
1326 \param bv - destination bitvector
1327 \param first - first element of the iterated sequence
1328 \param last - last element of the iterated sequence
1329
1330 \ingroup setalgo
1331*/
1332template<class BV, class It>
1333void combine_and_sorted(BV& bv, It first, It last)
1334{
1335 typename BV::size_type prev = 0;
1336 for ( ;first < last; ++first)
1337 {
1338 typename BV::size_type id = *first;
1339 BM_ASSERT(id >= prev); // make sure it's sorted
1340 bv.set_bit_and(id, true);
1341 if (++prev < id)
1342 {
1343 bv.set_range(prev, id-1, false);
1344 }
1345 prev = id;
1346 }
1347}
1348
1349
1350/**
1351 \brief AND Combine bitvector and the iterable sequence
1352
1353 Algorithm combines bvector with sequence of integers
1354 (represents another set). When the agrument set is sorted
1355 this method can give serious increase in performance.
1356
1357 \param bv - destination bitvector
1358 \param first - first element of the iterated sequence
1359 \param last - last element of the iterated sequence
1360
1361 \ingroup setalgo
1362 \sa combine_and_sorted
1363*/
1364template<class BV, class It>
1365void combine_and(BV& bv, It first, It last)
1366{
1367 BV bv_tmp;
1368 combine_or(bv_tmp, first, last);
1369 bv &= bv_tmp;
1370}
1371
1372/*!
1373 \brief Compute number of bit intervals (GAPs) in the bitvector
1374
1375 Algorithm traverses bit vector and count number of uninterrupted
1376 intervals of 1s and 0s.
1377 <pre>
1378 For example:
1379 empty vector - 1 interval
1380 00001111100000 - gives us 3 intervals
1381 10001111100000 - 4 intervals
1382 00000000000000 - 1 interval
1383 11111111111111 - 1 interval
1384 </pre>
1385 \return Number of intervals
1386 \ingroup setalgo
1387*/
1388template<class BV>
1389typename BV::size_type count_intervals(const BV& bv)
1390{
1391 const typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
1392
1393 if (!bman.is_init())
1394 return 1;
1395
1396 bm::word_t*** blk_root = bman.top_blocks_root();
1397 typename BV::blocks_manager_type::block_count_change_func func(bman);
1398 typename BV::blocks_manager_type::block_idx_type st = 0;
1399 bm::for_each_block(blk_root, bman.top_block_size(), func, st);
1400
1401 typename BV::size_type intervals = func.count();
1402 bool last_bit_set = bv.test(bm::id_max-1);
1403
1404 intervals -= last_bit_set; // correct last (out of range) interval
1405 return intervals;
1406}
1407
1408/*!
1409 \brief Export bitset from an array of binary data representing
1410 the bit vector.
1411
1412 Input array can be array of ints, chars or other native C types.
1413 Method works with iterators, which makes it compatible with
1414 STL containers and C arrays
1415
1416 \param bv - destination bitvector
1417 \param first - first element of the iterated sequence
1418 \param last - last element of the iterated sequence
1419
1420 \ingroup setalgo
1421*/
1422template<typename BV, class It>
1423void export_array(BV& bv, It first, It last)
1424{
1425 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
1426 if (!bman.is_init())
1427 bman.init_tree();
1428
1429 unsigned inp_word_size = sizeof(*first);
1430 size_t array_size = size_t(last - first);
1431 size_t bit_cnt = array_size * inp_word_size * 8;
1432 int block_type;
1433 bm::word_t tmp;
1434 bm::word_t b1, b2, b3, b4;
1435
1436 if (bit_cnt >= bv.size())
1437 bv.resize((bm::id_t)bit_cnt + 1);
1438 else
1439 bv.set_range((typename BV::size_type)bit_cnt, bv.size() - 1, false);
1440 switch (inp_word_size)
1441 {
1442 case 1:
1443 {
1444 size_t word_cnt = array_size / 4;
1445 for (typename BV::block_idx_type i = 0; i < bm::set_total_blocks; ++i)
1446 {
1447 bm::word_t* blk =
1448 bman.check_allocate_block(i,
1449 false,
1450 BM_BIT,
1451 &block_type,
1452 false /*no NULL ret*/);
1453 if (block_type == 1) // gap
1454 {
1455 blk = bman.deoptimize_block(i);
1456 }
1457
1458 bm::word_t* wrd_ptr = blk;
1459 if (word_cnt >= bm::set_block_size) {
1460 bm::word_t* wrd_end = blk + bm::set_block_size;
1461 do {
1462 b1 = bm::word_t(*first++); b2 = bm::word_t(*first++);
1463 b3 = bm::word_t(*first++); b4 = bm::word_t(*first++);
1464 tmp = b1 | (b2 << 8u) | (b3 << 16u) | (b4 << 24u);
1465 *wrd_ptr++ = tmp;
1466 } while (wrd_ptr < wrd_end);
1467 word_cnt -= bm::set_block_size;
1468 }
1469 else
1470 {
1471 size_t to_convert = size_t(last - first);
1472 for (size_t j = 0; j < to_convert / 4; ++j)
1473 {
1474 b1 = bm::word_t(*first++); b2 = bm::word_t(*first++);
1475 b3 = bm::word_t(*first++); b4 = bm::word_t(*first++);
1476 tmp = b1 | (b2 << 8u) | (b3 << 16u) | (b4 << 24u);
1477 *wrd_ptr++ = tmp;
1478 }
1479 while (1)
1480 {
1481 if (first == last) break;
1482 *wrd_ptr = bm::word_t(*first++);
1483 if (first == last) break;
1484 *wrd_ptr |= bm::word_t(*first++) << 8u;
1485 if (first == last) break;
1486 *wrd_ptr |= bm::word_t(*first++) << 16u;
1487 if (first == last) break;
1488 *wrd_ptr |= bm::word_t(*first++) << 24u;
1489 ++wrd_ptr;
1490 }
1491 }
1492 if (first == last) break;
1493 } // for
1494 }
1495 break;
1496 case 2:
1497 {
1498 size_t word_cnt = array_size / 2;
1499 for (typename BV::block_idx_type i = 0; i < bm::set_total_blocks; ++i)
1500 {
1501 bm::word_t* blk =
1502 bman.check_allocate_block(i,
1503 false,
1504 BM_BIT,
1505 &block_type,
1506 false /*no NULL ret*/);
1507 if (block_type) // gap
1508 blk = bman.deoptimize_block(i);
1509
1510 bm::word_t* wrd_ptr = blk;
1511 if (word_cnt >= bm::set_block_size) {
1512 bm::word_t* wrd_end = blk + bm::set_block_size;
1513 do {
1514 b1 = bm::word_t(*first++); b2 = bm::word_t(*first++);
1515 tmp = b1 | (b2 << 16);
1516 *wrd_ptr++ = tmp;
1517 } while (wrd_ptr < wrd_end);
1518 word_cnt -= bm::set_block_size;
1519 }
1520 else
1521 {
1522 size_t to_convert = size_t(last - first);
1523 for (unsigned j = 0; j < to_convert / 2; ++j)
1524 {
1525 b1 = bm::word_t(*first++); b2 = bm::word_t(*first++);
1526 tmp = b1 | (b2 << 16u);
1527 *wrd_ptr++ = tmp;
1528 }
1529 while (1)
1530 {
1531 if (first == last) break;
1532 *wrd_ptr = bm::word_t(*first++);
1533 if (first == last) break;
1534 *wrd_ptr |= bm::word_t((*first++) << 16u);
1535 ++wrd_ptr;
1536 }
1537 }
1538 if (first == last) break;
1539 } // for
1540 }
1541 break;
1542 case 4:
1543 {
1544 size_t word_cnt = array_size;
1545 for (typename BV::block_idx_type i = 0; i < bm::set_total_blocks; ++i)
1546 {
1547 bm::word_t* blk =
1548 bman.check_allocate_block(i,
1549 false,
1550 BM_BIT,
1551 &block_type,
1552 false /*no NULL ret*/);
1553 if (block_type == 1) // gap
1554 blk = bman.deoptimize_block(i);
1555
1556 bm::word_t* wrd_ptr = blk;
1557 if (word_cnt >= bm::set_block_size) {
1558 bm::word_t* wrd_end = blk + bm::set_block_size;
1559 do
1560 {
1561 *wrd_ptr++ = bm::word_t(*first++);
1562 } while (wrd_ptr < wrd_end);
1563 word_cnt -= bm::set_block_size;
1564 }
1565 else
1566 {
1567 while (1)
1568 {
1569 if (first == last) break;
1570 *wrd_ptr = bm::word_t(*first++);
1571 ++wrd_ptr;
1572 }
1573 }
1574 if (first == last) break;
1575 } // for
1576 }
1577 break;
1578 default:
1579 BM_ASSERT(0);
1580 } // switch
1581
1582}
1583
1584
1585/*!
1586 \brief for-each visitor, calls a visitor functor for each 1 bit group
1587
1588 \param block - bit block buffer pointer
1589 \param offset - global block offset (number of bits)
1590 \param bit_functor - functor must support .add_bits(offset, bits_ptr, size)
1591 \return - functor return code (< 0 - interrupt the processing)
1592
1593 @ingroup bitfunc
1594 @internal
1595*/
1596template<typename Func, typename SIZE_TYPE>
1597int for_each_bit_blk(const bm::word_t* block, SIZE_TYPE offset,
1598 Func& bit_functor)
1599{
1600 BM_ASSERT(block);
1601 int ret;
1602 if (IS_FULL_BLOCK(block))
1603 {
1604 ret = bit_functor.add_range(offset, bm::gap_max_bits);
1605 return ret;
1606 }
1607 unsigned char bits[bm::set_bitscan_wave_size*32];
1608 SIZE_TYPE offs = offset;
1609 const word_t* block_end = block + bm::set_block_size;
1610 do
1611 {
1612 if (unsigned cnt = bm::bitscan_wave(block, bits))
1613 {
1614 ret = bit_functor.add_bits(offs, bits, cnt);
1615 if (ret < 0)
1616 return ret;
1617 }
1618 offs += bm::set_bitscan_wave_size * 32;
1620 } while (block < block_end);
1621 return 0;
1622}
1623
1624/*!
1625 \brief for-each range visitor, calls a visitor functor for each 1 bit group
1626
1627 \param block - bit block buffer pointer
1628 \param offset - global block offset (number of bits)
1629 \param left - bit addredd in block from [from..to]
1630 \param right - bit addredd in block to [from..to]
1631 \param bit_functor - functor must support .add_bits(offset, bits_ptr, size)
1632 \return - functor return code (< 0 - interrupt the processing)
1633 @ingroup bitfunc
1634 @internal
1635*/
1636template<typename Func, typename SIZE_TYPE>
1637int for_each_bit_blk(const bm::word_t* block, SIZE_TYPE offset,
1638 unsigned left, unsigned right,
1639 Func& bit_functor)
1640{
1641 BM_ASSERT(block);
1642 BM_ASSERT(left <= right);
1644
1645 int ret = 0;
1646 if (IS_FULL_BLOCK(block))
1647 {
1648 unsigned sz = right - left + 1;
1649 ret = bit_functor.add_range(offset + left, sz);
1650 return ret;
1651 }
1652 unsigned char bits[bm::set_bitscan_wave_size*32];
1653
1654 unsigned cnt, nword, nbit, bitcount, temp;
1655 nbit = left & bm::set_word_mask;
1656 const bm::word_t* word =
1657 block + (nword = unsigned(left >> bm::set_word_shift));
1658 if (left == right) // special case (only 1 bit to check)
1659 {
1660 if ((*word >> nbit) & 1u)
1661 {
1662 bits[0] = (unsigned char)nbit;
1663 ret = bit_functor.add_bits(offset + (nword * 32), bits, 1);
1664 }
1665 return ret;
1666 }
1667
1668 bitcount = right - left + 1u;
1669 if (nbit) // starting position is not aligned
1670 {
1671 unsigned right_margin = nbit + right - left;
1672 if (right_margin < 32)
1673 {
1674 unsigned mask_r = bm::mask_r_u32(nbit);
1675 unsigned mask_l = bm::mask_l_u32(right_margin);
1676 unsigned mask = mask_r & mask_l;
1677
1678 temp = (*word & mask);
1679 cnt = bm::bitscan(temp, bits);
1680 if (cnt)
1681 ret = bit_functor.add_bits(offset + (nword * 32), bits, cnt);
1682 return ret;
1683 }
1684 unsigned mask_r = bm::mask_r_u32(nbit);
1685 temp = *word & mask_r;
1686 cnt = bm::bitscan(temp, bits);
1687 if (cnt)
1688 {
1689 ret = bit_functor.add_bits(offset + (nword * 32), bits, cnt);
1690 if (ret < 0)
1691 return ret;
1692 }
1693 bitcount -= 32 - nbit;
1694 ++word; ++nword;
1695 }
1696 else
1697 {
1698 bitcount = right - left + 1u;
1699 }
1700
1701 // word aligned now - scan the bit-stream loop unrolled 4x words(wave)
1703 for ( ;bitcount >= 128;
1704 bitcount-=128, word+=bm::set_bitscan_wave_size,
1706 {
1707 cnt = bm::bitscan_wave(word, bits);
1708 if (cnt)
1709 {
1710 ret = bit_functor.add_bits(offset + (nword * 32), bits, cnt);
1711 if (ret < 0)
1712 return ret;
1713 }
1714 } // for
1715
1716 for ( ;bitcount >= 32; bitcount-=32, ++word)
1717 {
1718 temp = *word;
1719 cnt = bm::bitscan(temp, bits);
1720 if (cnt)
1721 {
1722 ret = bit_functor.add_bits(offset + (nword * 32), bits, cnt);
1723 if (ret < 0)
1724 return ret;
1725 }
1726 ++nword;
1727 } // for
1728
1729 BM_ASSERT(bitcount < 32);
1730
1731 if (bitcount) // we have a tail to count
1732 {
1733 unsigned mask_l = bm::mask_l_u32(bitcount-1);
1734 temp = *word & mask_l;
1735 cnt = bm::bitscan(temp, bits);
1736 if (cnt)
1737 {
1738 ret = bit_functor.add_bits(offset + (nword * 32), bits, cnt);
1739 if (ret < 0)
1740 return ret;
1741 }
1742 }
1743 return 0;
1744}
1745
1746
1747
1748/*!
1749 \brief for-each visitor, calls a special visitor functor for each 1 bit range
1750
1751 \param buf - bit block buffer pointer
1752 \param offset - global block offset (number of bits)
1753 \param bit_functor - functor must support .add_range(offset, bits_ptr, size)
1754 \return - functor return code (< 0 - interrupt the processing)
1755
1756 @ingroup gapfunc
1757 @internal
1758*/
1759template<typename T, typename Func, typename SIZE_TYPE>
1760int for_each_gap_blk(const T* buf, SIZE_TYPE offset,
1761 Func& bit_functor)
1762{
1763 const T* pcurr = buf + 1;
1764 const T* pend = buf + (*buf >> 3);
1765 int ret = 0;
1766 if (*buf & 1)
1767 {
1768 ret = bit_functor.add_range(offset, *pcurr + 1);
1769 if (ret < 0)
1770 return ret;
1771 ++pcurr;
1772 }
1773 for (++pcurr; (pcurr <= pend) && (ret >= 0); pcurr += 2)
1774 {
1775 T prev = *(pcurr-1);
1776 ret = bit_functor.add_range(offset + prev + 1, *pcurr - prev);
1777 }
1778 return ret;
1779}
1780
1781/*!
1782 \brief for-each visitor, calls a special visitor functor for each 1 bit range
1783
1784 \param buf - bit block buffer pointer
1785 \param offset - global block offset (number of bits)
1786 \param left - interval start [left..right]
1787 \param right - intreval end [left..right]
1788 \param bit_functor - functor must support .add_range(offset, bits_ptr, size)
1789 \return - functor return code (< 0 - interrupt the processing)
1790
1791 @ingroup gapfunc
1792 @internal
1793*/
1794template<typename T, typename Func, typename SIZE_TYPE>
1796 SIZE_TYPE offset,
1797 unsigned left, unsigned right,
1798 Func& bit_functor)
1799{
1800 BM_ASSERT(left <= right);
1802
1803 unsigned is_set;
1804 unsigned start_pos = bm::gap_bfind(buf, left, &is_set);
1805 const T* BMRESTRICT pcurr = buf + start_pos;
1806 int ret = 0;
1807 if (is_set)
1808 {
1809 if (right <= *pcurr)
1810 {
1811 ret = bit_functor.add_range(offset + left, (right + 1)-left);
1812 return ret;
1813 }
1814 ret = bit_functor.add_range(offset + left, (*pcurr + 1)-left);
1815 if (ret < 0)
1816 return ret;
1817 ++pcurr;
1818 }
1819
1820 const T* BMRESTRICT pend = buf + (*buf >> 3);
1821 for (++pcurr; pcurr <= pend; pcurr += 2)
1822 {
1823 T prev = *(pcurr-1);
1824 if (right <= *pcurr)
1825 {
1826 int sz = int(right) - int(prev);
1827 if (sz > 0)
1828 ret = bit_functor.add_range(offset + prev + 1, unsigned(sz));
1829 return ret;
1830 }
1831 ret = bit_functor.add_range(offset + prev + 1, *pcurr - prev);
1832 if (ret < 0)
1833 return ret;
1834 } // for
1835 return 0;
1836}
1837
1838
1839
1840/*! For each non-zero block in [from, to] executes supplied functor
1841 \internal
1842*/
1843template<typename T, typename N, typename F>
1845 N top_size, N nb_from, N nb_to, F& f)
1846{
1847 BM_ASSERT(top_size);
1848 if (nb_from > nb_to)
1849 return 0;
1850 unsigned i_from = unsigned(nb_from >> bm::set_array_shift);
1851 unsigned j_from = unsigned(nb_from & bm::set_array_mask);
1852 unsigned i_to = unsigned(nb_to >> bm::set_array_shift);
1853 unsigned j_to = unsigned(nb_to & bm::set_array_mask);
1854
1855 if (i_from >= top_size)
1856 return 0;
1857 if (i_to >= top_size)
1858 {
1859 i_to = unsigned(top_size-1);
1860 j_to = bm::set_sub_array_size-1;
1861 }
1862 int ret;
1863 for (unsigned i = i_from; i <= i_to; ++i)
1864 {
1865 T** blk_blk = root[i];
1866 if (!blk_blk)
1867 continue;
1868 if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
1869 {
1870 unsigned j = (i == i_from) ? j_from : 0;
1871 if (!j && (i != i_to)) // full sub-block
1872 {
1873 N base_idx = bm::get_super_block_start<N>(i);
1874 ret = f.add_range(base_idx, bm::set_sub_total_bits);
1875 if (ret < 0)
1876 return ret;
1877 }
1878 else
1879 {
1880 do
1881 {
1882 N base_idx = bm::get_block_start<N>(i, j);
1883 ret = f.add_range(base_idx, bm::gap_max_bits);
1884 if (ret < 0)
1885 return ret;
1886 if ((i == i_to) && (j == j_to))
1887 return 0;
1888 } while (++j < bm::set_sub_array_size);
1889 }
1890 }
1891 else
1892 {
1893 unsigned j = (i == i_from) ? j_from : 0;
1894 do
1895 {
1896 const T* block;
1897 if (blk_blk[j])
1898 {
1899 N base_idx = bm::get_block_start<N>(i, j);
1900 if (0 != (block = blk_blk[j]))
1901 {
1902 if (BM_IS_GAP(block))
1903 ret = bm::for_each_gap_blk(BMGAP_PTR(block), base_idx, f);
1904 else
1905 ret = bm::for_each_bit_blk(block, base_idx, f);
1906 if (ret < 0)
1907 return ret;
1908 }
1909 }
1910
1911 if ((i == i_to) && (j == j_to))
1912 return 0;
1913 } while (++j < bm::set_sub_array_size);
1914 }
1915 } // for i
1916 return 0;
1917}
1918
1919
1920/**
1921 Implementation of for_each_bit_range without boilerplave checks
1922 @internal
1923*/
1924template<class BV, class Func>
1926 typename BV::size_type left,
1927 typename BV::size_type right,
1928 Func& bit_functor)
1929{
1930 typedef typename BV::size_type size_type;
1931 typedef typename BV::block_idx_type block_idx_type;
1932
1933 const typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
1934 bm::word_t*** blk_root = bman.top_blocks_root();
1935 if (!blk_root)
1936 return 0;
1937
1938 block_idx_type nblock_left = (left >> bm::set_block_shift);
1939 block_idx_type nblock_right = (right >> bm::set_block_shift);
1940
1941 unsigned i0, j0;
1942 bm::get_block_coord(nblock_left, i0, j0);
1943 const bm::word_t* block = bman.get_block_ptr(i0, j0);
1944 unsigned nbit_left = unsigned(left & bm::set_block_mask);
1945 size_type offset = nblock_left * bm::bits_in_block;
1946 int ret = 0;
1947 if (nblock_left == nblock_right) // hit in the same block
1948 {
1949 if (!block)
1950 return ret;
1951 unsigned nbit_right = unsigned(right & bm::set_block_mask);
1952 if (BM_IS_GAP(block))
1953 {
1954 ret = bm::for_each_gap_blk_range(BMGAP_PTR(block), offset,
1955 nbit_left, nbit_right, bit_functor);
1956 }
1957 else
1958 {
1959 ret = bm::for_each_bit_blk(block, offset, nbit_left, nbit_right,
1960 bit_functor);
1961 }
1962 return ret;
1963 }
1964 // process left block
1965 if (nbit_left && block)
1966 {
1967 if (BM_IS_GAP(block))
1968 {
1969 ret = bm::for_each_gap_blk_range(BMGAP_PTR(block), offset,
1970 nbit_left, bm::bits_in_block-1, bit_functor);
1971 }
1972 else
1973 {
1974 ret = bm::for_each_bit_blk(block, offset, nbit_left, bm::bits_in_block-1,
1975 bit_functor);
1976 }
1977 if (ret < 0)
1978 return ret;
1979 ++nblock_left;
1980 }
1981
1982 // process all complete blocks in the middle
1983 {
1984 block_idx_type top_blocks_size = bman.top_block_size();
1985 ret = bm::for_each_bit_block_range(blk_root, top_blocks_size,
1986 nblock_left, nblock_right-1, bit_functor);
1987 if (ret < 0)
1988 return ret;
1989 }
1990
1991 unsigned nbit_right = unsigned(right & bm::set_block_mask);
1992 bm::get_block_coord(nblock_right, i0, j0);
1993 block = bman.get_block_ptr(i0, j0);
1994
1995 if (block)
1996 {
1997 offset = nblock_right * bm::bits_in_block;
1998 if (BM_IS_GAP(block))
1999 {
2000 ret = bm::for_each_gap_blk_range(BMGAP_PTR(block), offset,
2001 0, nbit_right, bit_functor);
2002 }
2003 else
2004 {
2005 ret = bm::for_each_bit_blk(block, offset, 0, nbit_right, bit_functor);
2006 }
2007 }
2008 return ret;
2009}
2010
2011/**
2012 convert sub-blocks to an array of set 1s (32-bit)
2013 @internal
2014 */
2015template<typename BV, typename VECT>
2016void convert_sub_to_arr(const BV& bv, unsigned sb, VECT& vect)
2017{
2018 vect.resize(0);
2019
2020 typename BV::size_type from, to, idx;
2021 typename BV::size_type sb_max_bc = bm::set_sub_array_size * bm::gap_max_bits;
2022 from = sb * sb_max_bc;
2023 to = (sb+1) * sb_max_bc;
2024 if (!to || to > bm::id_max) // overflow check
2025 to = bm::id_max;
2026
2027 typename BV::enumerator en = bv.get_enumerator(from);
2028 for (; en.valid(); ++en)
2029 {
2030 idx = *en;
2031 if (idx >= to)
2032 break;
2033 idx -= from;
2034 vect.push_back((typename VECT::value_type)idx);
2035 } // for en
2036}
2037
2038
2039} // namespace bm
2040
2041#ifdef _MSC_VER
2042#pragma warning( pop )
2043#endif
2044
2045#endif
Definitions(internal)
#define IS_FULL_BLOCK(addr)
Definition: bmdef.h:162
#define BMRESTRICT
Definition: bmdef.h:203
#define BMNOEXCEPT
Definition: bmdef.h:82
#define BMGAP_PTR(ptr)
Definition: bmdef.h:189
#define BM_IS_GAP(ptr)
Definition: bmdef.h:191
#define BLOCK_ADDR_SAN(addr)
Definition: bmdef.h:160
#define BM_ASSERT
Definition: bmdef.h:139
#define FULL_BLOCK_FAKE_ADDR
Definition: bmdef.h:158
#define BM_VECT_ALIGN_ATTR
Definition: bmdef.h:321
#define FULL_SUB_BLOCK_REAL_ADDR
Definition: bmdef.h:159
#define BM_VECT_ALIGN
Definition: bmdef.h:320
Bit manipulation primitives (internal)
bm::id_t bit_operation_and_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock AND operation test.
Definition: bmfunc.h:7490
unsigned short bitscan(V w, B *bits) BMNOEXCEPT
Templated Bitscan with dynamic dispatch for best type.
Definition: bmfunc.h:761
bm::id_t bit_operation_or_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock OR operation test.
Definition: bmfunc.h:7642
bm::id_t bit_block_count(const bm::word_t *block) BMNOEXCEPT
Bitcount for bit block.
Definition: bmfunc.h:5017
int for_each_bit_blk(const bm::word_t *block, SIZE_TYPE offset, Func &bit_functor)
for-each visitor, calls a visitor functor for each 1 bit group
Definition: bmalgo_impl.h:1597
bm::id_t bit_operation_xor_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock XOR operation test.
Definition: bmfunc.h:8307
bm::id_t bit_operation_sub_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock test of SUB operation.
Definition: bmfunc.h:7570
unsigned short bitscan_wave(const bm::word_t *BMRESTRICT w_ptr, unsigned char *BMRESTRICT bits) BMNOEXCEPT
Unpacks word wave (Nx 32-bit words)
Definition: bmfunc.h:9320
bool bit_is_all_zero(const bm::word_t *BMRESTRICT start) BMNOEXCEPT
Returns "true" if all bits in the block are 0.
Definition: bmfunc.h:1522
bm::id_t bit_operation_and_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock AND operation and calculates bitcount of the result.
Definition: bmfunc.h:7466
bm::id_t bit_operation_sub_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock SUB operation and calculates bitcount of the result.
Definition: bmfunc.h:7515
set_operation
Codes of set operations.
Definition: bmconst.h:167
@ set_COUNT_SUB_AB
Definition: bmconst.h:177
@ set_COUNT_XOR
Definition: bmconst.h:175
@ set_COUNT_OR
Definition: bmconst.h:176
@ set_COUNT_B
Definition: bmconst.h:180
@ set_COUNT_SUB_BA
Definition: bmconst.h:178
@ set_COUNT_AND
Definition: bmconst.h:174
@ set_COUNT
Definition: bmconst.h:173
@ set_COUNT_A
Definition: bmconst.h:179
@ BM_BIT
No GAP compression strategy. All new blocks are bit blocks.
Definition: bmconst.h:146
void distance_operation(const BV &bv1, const BV &bv2, distance_metric_descriptor *dmit, distance_metric_descriptor *dmit_end) BMNOEXCEPT
Distance computing template function.
Definition: bmalgo_impl.h:766
void distance_operation_any(const BV &bv1, const BV &bv2, distance_metric_descriptor *dmit, distance_metric_descriptor *dmit_end) BMNOEXCEPT
Distance screening template function.
Definition: bmalgo_impl.h:922
distance_metric
Distance metrics codes defined for vectors A and B.
Definition: bmalgo_impl.h:58
BV::size_type distance_and_operation(const BV &bv1, const BV &bv2) BMNOEXCEPT
Distance AND computing template function.
Definition: bmalgo_impl.h:853
distance_metric operation2metric(set_operation op) BMNOEXCEPT
Convert set operation into compatible distance metric.
Definition: bmalgo_impl.h:73
@ COUNT_XOR
(A ^ B).count()
Definition: bmalgo_impl.h:60
@ COUNT_SUB_AB
(A - B).count()
Definition: bmalgo_impl.h:62
@ COUNT_A
A.count()
Definition: bmalgo_impl.h:64
@ COUNT_B
B.count()
Definition: bmalgo_impl.h:65
@ COUNT_AND
(A & B).count()
Definition: bmalgo_impl.h:59
@ COUNT_OR
(A | B).count()
Definition: bmalgo_impl.h:61
@ COUNT_SUB_BA
(B - A).count()
Definition: bmalgo_impl.h:63
unsigned gap_test_unr(const T *BMRESTRICT buf, const unsigned pos) BMNOEXCEPT
Tests if bit = pos is true. Analog of bm::gap_test with SIMD unrolling.
Definition: bmfunc.h:1784
gap_word_t * gap_operation_or(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP OR operation.
Definition: bmfunc.h:6632
BMFORCEINLINE unsigned gap_operation_any_xor(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP XOR operation test.
Definition: bmfunc.h:6591
unsigned gap_bit_count_unr(const T *buf) BMNOEXCEPT
Calculates number of bits ON in GAP buffer. Loop unrolled version.
Definition: bmfunc.h:2287
unsigned gap_set_value(unsigned val, T *BMRESTRICT buf, unsigned pos, unsigned *BMRESTRICT is_set) BMNOEXCEPT
Sets or clears bit in the GAP buffer.
Definition: bmfunc.h:3173
int for_each_gap_blk(const T *buf, SIZE_TYPE offset, Func &bit_functor)
for-each visitor, calls a special visitor functor for each 1 bit range
Definition: bmalgo_impl.h:1760
bm::id_t gap_bitset_or_any(const unsigned *BMRESTRICT block, const T *BMRESTRICT buf) BMNOEXCEPT
Compute bitcount test of bit block OR masked by GAP block.
Definition: bmfunc.h:4403
bm::id_t gap_bitset_xor_count(const unsigned *BMRESTRICT block, const T *BMRESTRICT buf) BMNOEXCEPT
Compute bitcount of bit block XOR masked by GAP block.
Definition: bmfunc.h:4295
bm::id_t gap_bitset_and_count(const unsigned *BMRESTRICT block, const T *BMRESTRICT pcurr) BMNOEXCEPT
Compute bitcount of bit block AND masked by GAP block.
Definition: bmfunc.h:4164
int for_each_gap_blk_range(const T *BMRESTRICT buf, SIZE_TYPE offset, unsigned left, unsigned right, Func &bit_functor)
for-each visitor, calls a special visitor functor for each 1 bit range
Definition: bmalgo_impl.h:1795
unsigned gap_operation_any_and(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP AND operation test.
Definition: bmfunc.h:6509
void gap_convert_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT buf, unsigned len=0) BMNOEXCEPT
GAP block to bitblock conversion.
Definition: bmfunc.h:4441
bm::id_t gap_bitset_sub_count(const unsigned *BMRESTRICT block, const T *BMRESTRICT buf) BMNOEXCEPT
Compute bitcount of bit block SUB masked by GAP block.
Definition: bmfunc.h:4222
BMFORCEINLINE unsigned gap_count_xor(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP bitcount XOR operation test.
Definition: bmfunc.h:6607
unsigned gap_operation_any_sub(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP SUB operation test.
Definition: bmfunc.h:6704
bm::id_t gap_bitset_sub_any(const unsigned *BMRESTRICT block, const T *BMRESTRICT buf) BMNOEXCEPT
Compute bitcount test of bit block SUB masked by GAP block.
Definition: bmfunc.h:4257
bm::id_t gap_bitset_xor_any(const unsigned *BMRESTRICT block, const T *BMRESTRICT buf) BMNOEXCEPT
Compute bitcount test of bit block XOR masked by GAP block.
Definition: bmfunc.h:4333
bm::id_t gap_bitset_or_count(const unsigned *BMRESTRICT block, const T *BMRESTRICT buf) BMNOEXCEPT
Compute bitcount of bit block OR masked by GAP block.
Definition: bmfunc.h:4371
unsigned gap_count_and(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP bitcount AND operation test.
Definition: bmfunc.h:6526
BMFORCEINLINE bool gap_is_all_zero(const bm::gap_word_t *BMRESTRICT buf) BMNOEXCEPT
Checks if GAP block is all-zero.
Definition: bmfunc.h:1549
BMFORCEINLINE unsigned gap_count_sub(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP bitcount SUB (AND NOT) operation test.
Definition: bmfunc.h:6723
bm::id_t gap_bitset_and_any(const unsigned *BMRESTRICT block, const T *BMRESTRICT pcurr) BMNOEXCEPT
Bitcount test of bit block AND masked by GAP block.
Definition: bmfunc.h:4192
unsigned gap_limit(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returs GAP block capacity limit.
Definition: bmfunc.h:1607
BMFORCEINLINE unsigned gap_count_or(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2) BMNOEXCEPT
GAP bitcount OR operation test.
Definition: bmfunc.h:6652
void combine_and_sorted(BV &bv, It first, It last)
AND Combine bitvector and the iterable sequence.
Definition: bmalgo_impl.h:1333
void export_array(BV &bv, It first, It last)
Export bitset from an array of binary data representing the bit vector.
Definition: bmalgo_impl.h:1423
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
BV::size_type count_intervals(const BV &bv)
Compute number of bit intervals (GAPs) in the bitvector.
Definition: bmalgo_impl.h:1389
Definition: bm.h:78
const unsigned set_array_mask
Definition: bmconst.h:97
It block_range_scan(It first, It last, SIZE_TYPE nblock, SIZE_TYPE *max_id) BMNOEXCEPT
Internal algorithms scans the input for the block range limit.
Definition: bmalgo_impl.h:1047
bm::id_t(* bit_operation_count_func_type)(const bm::word_t *BMRESTRICT, const bm::word_t *BMRESTRICT)
Definition: bmfunc.h:9232
const unsigned id_max
Definition: bmconst.h:109
unsigned int word_t
Definition: bmconst.h:39
int for_each_bit_range_no_check(const BV &bv, typename BV::size_type left, typename BV::size_type right, Func &bit_functor)
Implementation of for_each_bit_range without boilerplave checks.
Definition: bmalgo_impl.h:1925
const unsigned set_block_mask
Definition: bmconst.h:57
unsigned gap_bfind(const T *BMRESTRICT buf, unsigned pos, unsigned *BMRESTRICT is_set) BMNOEXCEPT
Definition: bmfunc.h:1697
const unsigned set_sub_array_size
Definition: bmconst.h:95
BMFORCEINLINE void get_block_coord(BI_TYPE nb, unsigned &i, unsigned &j) BMNOEXCEPT
Recalc linear bvector block index into 2D matrix coordinates.
Definition: bmfunc.h:172
BMFORCEINLINE unsigned mask_l_u32(unsigned nbit) BMNOEXCEPT
Definition: bmutil.h:522
void combine_count_operation_with_block(const bm::word_t *blk, const bm::word_t *arg_blk, distance_metric_descriptor *dmit, distance_metric_descriptor *dmit_end) BMNOEXCEPT
Internal function computes different distance metrics.
Definition: bmalgo_impl.h:189
const unsigned set_total_blocks
Definition: bmconst.h:111
int for_each_bit_block_range(T ***root, N top_size, N nb_from, N nb_to, F &f)
Definition: bmalgo_impl.h:1844
void combine_any_operation_with_block(const bm::word_t *blk, unsigned gap, const bm::word_t *arg_blk, unsigned arg_gap, distance_metric_descriptor *dmit, distance_metric_descriptor *dmit_end) BMNOEXCEPT
Internal function computes different existense of distance metric.
Definition: bmalgo_impl.h:443
void convert_sub_to_arr(const BV &bv, unsigned sb, VECT &vect)
convert sub-blocks to an array of set 1s (32-bit)
Definition: bmalgo_impl.h:2016
const unsigned set_word_shift
Definition: bmconst.h:72
const unsigned set_sub_total_bits
Definition: bmconst.h:100
BMFORCEINLINE T min_value(T v1, T v2) BMNOEXCEPT
Get minimum of 2 values.
Definition: bmutil.h:103
const unsigned set_block_size
Definition: bmconst.h:55
unsigned long long int id64_t
Definition: bmconst.h:35
void distance_stage(const distance_metric_descriptor *dmit, const distance_metric_descriptor *dmit_end, bool *is_all_and) BMNOEXCEPT
Staging function for distance operation.
Definition: bmalgo_impl.h:733
unsigned int id_t
Definition: bmconst.h:38
BMFORCEINLINE unsigned mask_r_u32(unsigned nbit) BMNOEXCEPT
Definition: bmutil.h:513
const unsigned gap_max_buff_len
Definition: bmconst.h:80
const unsigned short set_bitscan_wave_size
Size of bit decode wave in words.
Definition: bmfunc.h:9308
const unsigned set_array_shift
Definition: bmconst.h:96
unsigned short gap_word_t
Definition: bmconst.h:78
const unsigned gap_max_bits
Definition: bmconst.h:81
void for_each_block(T ***root, unsigned size1, F &f, BLOCK_IDX start)
Definition: bmfunc.h:2133
const unsigned set_block_shift
Definition: bmconst.h:56
unsigned combine_count_and_operation_with_block(const bm::word_t *blk, const bm::word_t *arg_blk) BMNOEXCEPT
Internal function computes AND distance.
Definition: bmalgo_impl.h:406
const unsigned set_word_mask
Definition: bmconst.h:73
const unsigned bits_in_block
Definition: bmconst.h:114
bool is_const_set_operation(set_operation op) BMNOEXCEPT
Returns true if set operation is constant (bitcount)
Definition: bmfunc.h:1302
functor-adaptor for back-inserter
Definition: bmalgo_impl.h:159
int add_range(size_type offset, size_type size)
Definition: bmalgo_impl.h:171
int add_bits(size_type offset, const unsigned char *bits, unsigned size)
Definition: bmalgo_impl.h:165
functor-adaptor for C-style callbacks
Definition: bmalgo_impl.h:121
bit_visitor_callback_adaptor(void *h, bit_visitor_callback_type cb_func)
Definition: bmalgo_impl.h:124
int add_bits(size_type offset, const unsigned char *bits, unsigned size)
Definition: bmalgo_impl.h:128
bit_visitor_callback_type func_
Definition: bmalgo_impl.h:150
int add_range(size_type offset, size_type size)
Definition: bmalgo_impl.h:138
Distance metric descriptor, holds metric code and result.
Definition: bmalgo_impl.h:87
distance_metric_descriptor(distance_metric m) BMNOEXCEPT
Definition: bmalgo_impl.h:97
distance_metric_descriptor() BMNOEXCEPT
Definition: bmalgo_impl.h:101
void reset() BMNOEXCEPT
Sets metric result to 0.
Definition: bmalgo_impl.h:109
static bit_operation_count_func_type bit_operation_count(unsigned i)
Definition: bmfunc.h:9259