BitMagic-C++
bmalgo.h
Go to the documentation of this file.
1#ifndef BMALGO__H__INCLUDED__
2#define BMALGO__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.h
22 \brief Algorithms for bvector<> (main include)
23*/
24
25#ifndef BM__H__INCLUDED__
26// BitMagic utility headers do not include main "bm.h" declaration
27// #include "bm.h" or "bm64.h" explicitly
28# error missing include (bm.h or bm64.h)
29#endif
30
31#include "bmfunc.h"
32#include "bmdef.h"
33
34#include "bmalgo_impl.h"
35
36
37
38namespace bm
39{
40
41/*!
42 \brief Computes bitcount of AND operation of two bitsets
43 \param bv1 - Argument bit-vector.
44 \param bv2 - Argument bit-vector.
45 \return bitcount of the result
46 \ingroup setalgo
47*/
48template<class BV>
49typename BV::size_type count_and(const BV& bv1, const BV& bv2) BMNOEXCEPT
50{
51 return bm::distance_and_operation(bv1, bv2);
52}
53
54/*!
55 \brief Computes if there is any bit in AND operation of two bitsets
56 \param bv1 - Argument bit-vector.
57 \param bv2 - Argument bit-vector.
58 \return non zero value if there is any bit
59 \ingroup setalgo
60*/
61template<class BV>
62typename BV::size_type any_and(const BV& bv1, const BV& bv2) BMNOEXCEPT
63{
65
66 distance_operation_any(bv1, bv2, &dmd, &dmd + 1);
67 return dmd.result;
68}
69
70
71
72/*!
73 \brief Computes bitcount of XOR operation of two bitsets
74 \param bv1 - Argument bit-vector.
75 \param bv2 - Argument bit-vector.
76 \return bitcount of the result
77 \ingroup setalgo
78*/
79template<class BV>
81count_xor(const BV& bv1, const BV& bv2) BMNOEXCEPT
82{
84
85 distance_operation(bv1, bv2, &dmd, &dmd + 1);
86 return dmd.result;
87}
88
89/*!
90 \brief Computes if there is any bit in XOR operation of two bitsets
91 \param bv1 - Argument bit-vector.
92 \param bv2 - Argument bit-vector.
93 \return non zero value if there is any bit
94 \ingroup setalgo
95*/
96template<class BV>
97typename BV::size_type any_xor(const BV& bv1, const BV& bv2) BMNOEXCEPT
98{
100
101 distance_operation_any(bv1, bv2, &dmd, &dmd + 1);
102 return dmd.result;
103}
104
105
106
107/*!
108 \brief Computes bitcount of SUB operation of two bitsets
109 \param bv1 - Argument bit-vector.
110 \param bv2 - Argument bit-vector.
111 \return bitcount of the result
112 \ingroup setalgo
113*/
114template<class BV>
115typename BV::size_type count_sub(const BV& bv1, const BV& bv2) BMNOEXCEPT
116{
118
119 distance_operation(bv1, bv2, &dmd, &dmd + 1);
120 return dmd.result;
121}
122
123
124/*!
125 \brief Computes if there is any bit in SUB operation of two bitsets
126 \param bv1 - Argument bit-vector.
127 \param bv2 - Argument bit-vector.
128 \return non zero value if there is any bit
129 \ingroup setalgo
130*/
131template<class BV>
132typename BV::size_type any_sub(const BV& bv1, const BV& bv2) BMNOEXCEPT
133{
135
136 distance_operation_any(bv1, bv2, &dmd, &dmd + 1);
137 return dmd.result;
138}
139
140
141/*!
142 \brief Computes bitcount of OR operation of two bitsets
143 \param bv1 - Argument bit-vector.
144 \param bv2 - Argument bit-vector.
145 \return bitcount of the result
146 \ingroup setalgo
147*/
148template<class BV>
149typename BV::size_type count_or(const BV& bv1, const BV& bv2) BMNOEXCEPT
150{
152
153 distance_operation(bv1, bv2, &dmd, &dmd + 1);
154 return dmd.result;
155}
156
157/*!
158 \brief Computes if there is any bit in OR operation of two bitsets
159 \param bv1 - Argument bit-vector.
160 \param bv2 - Argument bit-vector.
161 \return non zero value if there is any bit
162 \ingroup setalgo
163*/
164template<class BV>
165typename BV::size_type any_or(const BV& bv1, const BV& bv2) BMNOEXCEPT
166{
168
169 distance_operation_any(bv1, bv2, &dmd, &dmd + 1);
170 return dmd.result;
171}
172
173
174
175#define BM_SCANNER_OP(x) \
176if (0 != (block = blk_blk[j+x])) \
177{ int ret;\
178 if (BM_IS_GAP(block)) \
179 { \
180 ret = bm::for_each_gap_blk(BMGAP_PTR(block), (r+j+x)*bm::bits_in_block,\
181 bit_functor); \
182 } \
183 else \
184 { \
185 ret = bm::for_each_bit_blk(block, (r+j+x)*bm::bits_in_block,bit_functor); \
186 } \
187 if (ret < 0) return ret; \
188}
189
190
191/**
192 @brief bit-vector visitor scanner to traverse each 1 bit using C++ visitor
193
194 @param bv - bit vector to scan
195 @param bit_functor - visitor: should support add_bits(), add_range()
196 @return return code from functor (< 0 indicates to interrupt iteration and exit)
197
198 \ingroup setalgo
199 @sa for_each_bit_range visit_each_bit
200*/
201template<class BV, class Func>
202int for_each_bit(const BV& bv,
203 Func& bit_functor)
204{
205 typedef typename BV::size_type size_type;
206
207 const typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
208 bm::word_t*** blk_root = bman.top_blocks_root();
209
210 if (!blk_root)
211 return 0;
212
213 unsigned tsize = bman.top_block_size();
214 for (unsigned i = 0; i < tsize; ++i)
215 {
216 bm::word_t** blk_blk = blk_root[i];
217 if (!blk_blk)
218 continue;
219
220 if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
221 blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
222
223 const bm::word_t* block;
224 size_type r = size_type(i) * bm::set_sub_array_size;
225 unsigned j = 0;
226 do
227 {
228 #ifdef BM64_AVX2
229 if (!avx2_test_all_zero_wave(blk_blk + j))
230 {
235 }
236 j += 4;
237 #elif defined(BM64_SSE4)
238 if (!sse42_test_all_zero_wave(blk_blk + j))
239 {
242 }
243 j += 2;
244 #else
246 ++j;
247 #endif
248
249 } while (j < bm::set_sub_array_size);
250 } // for i
251 return 0;
252}
253
254/**
255 @brief bit-vector range visitor to traverse each 1 bit
256
257 @param bv - bit vector to scan
258 @param right - start of closed interval [from..to]
259 @param left - end of close interval [from..to]
260 @param bit_functor - visitor: should support add_bits(), add_range()
261
262 \ingroup setalgo
263 @sa for_each_bit
264*/
265template<class BV, class Func>
266int for_each_bit_range(const BV& bv,
267 typename BV::size_type left,
268 typename BV::size_type right,
269 Func& bit_functor)
270{
271 if (left > right)
272 bm::xor_swap(left, right);
273 if (right == bm::id_max)
274 --right;
275 BM_ASSERT(left < bm::id_max && right < bm::id_max);
276 int res = bm::for_each_bit_range_no_check(bv, left, right, bit_functor);
277 return res;
278}
279
280
281#undef BM_SCANNER_OP
282
283
284
285
286
287/// Functor for bit-copy (for testing)
288///
289/// @internal
290///
291template <class BV>
293{
294 typedef typename BV::size_type size_type;
295
297 : bv_(bv)
298 {
299 bv_.init();
300 }
301
302 int add_bits(size_type offset, const unsigned char* bits, unsigned size)
303 {
304 BM_ASSERT(size);
305 for (unsigned i = 0; i < size; ++i)
306 bv_.set_bit_no_check(offset + bits[i]);
307 return 0;
308 }
309 int add_range(size_type offset, size_type size)
310 {
311 BM_ASSERT(size);
312 bv_.set_range(offset, offset + size - 1);
313 return 0;
314 }
315
316 BV& bv_;
318};
319
320
321
322/**
323 @brief bvector visitor scanner to traverse each 1 bit using C callback
324
325 @param bv - bit vector to scan
326 @param handle_ptr - handle to private memory used by callback
327 @param callback_ptr - callback function
328
329 @return exit code form call back function
330
331 \ingroup setalgo
332
333 @sa bit_visitor_callback_type
334*/
335template<class BV>
336int visit_each_bit(const BV& bv,
337 void* handle_ptr,
338 bit_visitor_callback_type callback_ptr)
339{
340 typedef typename BV::size_type size_type;
342 func(handle_ptr, callback_ptr);
343 int res = bm::for_each_bit(bv, func);
344 return res;
345}
346
347/**
348 @brief bvector visitor scanner to traverse each bits in range (C callback)
349
350 @param bv - bit vector to scan
351 @param left - from [left..right]
352 @param right - to [left..right]
353 @param handle_ptr - handle to private memory used by callback
354 @param callback_ptr - callback function
355 @return exit code form call back function
356
357 \ingroup setalgo
358
359 @sa bit_visitor_callback_type for_each_bit
360*/
361template<class BV>
362int visit_each_bit_range(const BV& bv,
363 typename BV::size_type left,
364 typename BV::size_type right,
365 void* handle_ptr,
366 bit_visitor_callback_type callback_ptr)
367{
368 typedef typename BV::size_type size_type;
370 func(handle_ptr, callback_ptr);
371 int res = bm::for_each_bit_range(bv, left, right, func);
372 return res;
373}
374
375/**
376 @brief Algorithm to identify bit-vector ranges (splits) for the rank
377
378 Rank range split algorithm walks the bit-vector to create list of
379 non-overlapping ranges [s1..e1],[s2..e2]...[sN...eN] with requested
380 (rank) number of 1 bits. All ranges should be the same popcount weight,
381 except the last one, which may have less.
382 Scan is progressing from left to right so result ranges will be
383 naturally sorted.
384
385 @param bv - bit vector to perform the range split scan
386 @param rank - requested number of bits in each range
387 if 0 it will create single range [first..last]
388 to cover the whole bv
389 @param target_v - [out] STL(or STL-like) vector of pairs to keep pairs results
390
391 \ingroup setalgo
392 */
393template<typename BV, typename PairVect>
394void rank_range_split(const BV& bv,
395 typename BV::size_type rank,
396 PairVect& target_v)
397{
398 target_v.resize(0);
399 typename BV::size_type first, last, pos;
400 bool found = bv.find_range(first, last);
401 if (!found) // empty bit-vector
402 return;
403
404 if (!rank) // if rank is not defined, include the whole vector [first..last]
405 {
406 typename PairVect::value_type pv;
407 pv.first = first; pv.second = last;
408 target_v.push_back(pv);
409 return;
410 }
411
412 while (1)
413 {
414 typename PairVect::value_type pv;
415 found = bv.find_rank(rank, first, pos);
416 if (found)
417 {
418 pv.first = first; pv.second = pos;
419 target_v.push_back(pv);
420 if (pos >= last)
421 break;
422 first = pos + 1;
423 continue;
424 }
425 // insufficient rank (last range)
426 found = bv.any_range(first, last);
427 if (found)
428 {
429 pv.first = first; pv.second = last;
430 target_v.push_back(pv);
431 }
432 break;
433 } // while
434
435}
436
437
438
439/**
440 Algorithms for rank compression of bit-vector
441
442 1. Source vector (bv_src) is a subset of index vector (bv_idx)
443 2. As a subset it can be collapsed using bit-rank method, where each position
444 in the source vector is defined by population count (range)
445 [0..index_position] (count_range())
446 As a result all integer set of source vector gets re-mapped in
447 accord with the index vector.
448
449 \ingroup setalgo
450*/
451template<typename BV>
453{
454public:
455 typedef BV bvector_type;
456 typedef typename BV::size_type size_type;
457 typedef typename BV::rs_index_type rs_index_type;
459 {
460 n_buffer_cap = 1024
461 };
462public:
463
464 /**
465 Rank decompression
466 */
467 void decompress(BV& bv_target, const BV& bv_idx, const BV& bv_src);
468
469 /**
470 Rank compression algorithm based on two palallel iterators/enumerators
471 set of source vector gets re-mapped in accord with the index/rank vector.
472
473 \param bv_target - target bit-vector
474 \param bv_idx - index (rank) vector used for address recalculation
475 \param bv_src - source vector for re-mapping
476 */
477 void compress(BV& bv_target, const BV& bv_idx, const BV& bv_src);
478
479 /**
480 \brief Source vector priority + index based rank
481
482 @sa compress
483 */
484 void compress_by_source(BV& bv_target,
485 const BV& bv_idx,
486 const rs_index_type& bc_idx,
487 const BV& bv_src);
488};
489
490
491// ------------------------------------------------------------------------
492//
493// ------------------------------------------------------------------------
494
495
496template<class BV>
498 const BV& bv_idx,
499 const BV& bv_src)
500{
501 bv_target.clear();
502 bv_target.init();
503
504 if (&bv_idx == &bv_src)
505 {
506 bv_target = bv_src;
507 return;
508 }
509 size_type ibuffer[n_buffer_cap];
510 size_type b_size;
511
512 typedef typename BV::enumerator enumerator_t;
513 enumerator_t en_s = bv_src.first();
514 enumerator_t en_i = bv_idx.first();
515
516 size_type r_idx = b_size = 0;
517 size_type i, s;
518
519 for (; en_i.valid(); )
520 {
521 if (!en_s.valid())
522 break;
523 i = *en_i; s = *en_s;
524
525 BM_ASSERT(s >= i);
526 BM_ASSERT(bv_idx.test(i));
527
528 if (i == s)
529 {
530 ibuffer[b_size++] = r_idx++;
531 if (b_size == n_buffer_cap)
532 {
533 bv_target.set(ibuffer, b_size, bm::BM_SORTED);
534 b_size = 0;
535 }
536 ++en_i; ++en_s;
537 continue;
538 }
539 BM_ASSERT(s > i);
540
541 size_type dist = s - i;
542 if (dist >= 64) // sufficiently far away, jump
543 {
544 size_type r_dist = bv_idx.count_range(i + 1, s);
545 r_idx += r_dist;
546 en_i.go_to(s);
547 BM_ASSERT(en_i.valid());
548 }
549 else // small distance, iterate to close the gap
550 {
551 for (; s > i; ++r_idx)
552 {
553 ++en_i;
554 i = *en_i;
555 } // for
556 BM_ASSERT(en_i.valid());
557 }
558 } // for
559
560 if (b_size)
561 {
562 bv_target.set(ibuffer, b_size, bm::BM_SORTED);
563 }
564
565}
566
567// ------------------------------------------------------------------------
568
569template<class BV>
571 const BV& bv_idx,
572 const BV& bv_src)
573{
574 bv_target.clear();
575 bv_target.init();
576
577 if (&bv_idx == &bv_src)
578 {
579 bv_target = bv_src;
580 return;
581 }
582
583 size_type r_idx, i, s, b_size;
584 size_type ibuffer[n_buffer_cap];
585
586 b_size = r_idx = 0;
587
588 typedef typename BV::enumerator enumerator_t;
589 enumerator_t en_s = bv_src.first();
590 enumerator_t en_i = bv_idx.first();
591 for (; en_i.valid(); )
592 {
593 if (!en_s.valid())
594 break;
595 s = *en_s;
596 i = *en_i;
597 if (s == r_idx)
598 {
599 ibuffer[b_size++] = i;
600 if (b_size == n_buffer_cap)
601 {
602 bv_target.set(ibuffer, b_size, bm::BM_SORTED);
603 b_size = 0;
604 }
605 ++en_i; ++en_s; ++r_idx;
606 continue;
607 }
608 // source is "faster" than index, need to re-align
609 BM_ASSERT(s > r_idx);
610 size_type rank = s - r_idx + 1u;
611 size_type new_pos = 0;
612
613 if (rank < 256)
614 {
615 en_i.skip(s - r_idx);
616 BM_ASSERT(en_i.valid());
617 new_pos = *en_i;
618 }
619 else
620 {
621 bv_idx.find_rank(rank, i, new_pos);
622 BM_ASSERT(new_pos);
623 en_i.go_to(new_pos);
624 BM_ASSERT(en_i.valid());
625 }
626
627 r_idx = s;
628 ibuffer[b_size++] = new_pos;
629 if (b_size == n_buffer_cap)
630 {
631 bv_target.set(ibuffer, b_size, bm::BM_SORTED);
632 b_size = 0;
633 }
634 ++en_i; ++en_s; ++r_idx;
635
636 } // for en
637
638 if (b_size)
639 {
640 bv_target.set(ibuffer, b_size, bm::BM_SORTED);
641 }
642}
643
644// ------------------------------------------------------------------------
645
646template<class BV>
648 const BV& bv_idx,
649 const rs_index_type& bc_idx,
650 const BV& bv_src)
651{
652 /// Rank compressor visitor (functor)
653 /// @internal
654 struct visitor_func
655 {
656 visitor_func(bvector_type& bv_out,
657 const bvector_type& bv_index,
658 const rs_index_type& bc_index)
659 : bv_target_(bv_out),
660 bv_index_(bv_index),
661 bc_index_(bc_index)
662 {}
663
664 int add_bits(size_type arr_offset, const unsigned char* bits, unsigned bits_size)
665 {
666 for (unsigned i = 0; i < bits_size; ++i)
667 {
668 size_type idx = arr_offset + bits[i];
669 BM_ASSERT(bv_index_.test(idx));
670
671 size_type r_idx = bv_index_.count_to(idx, bc_index_) - 1;
672 bv_target_.set_bit_no_check(r_idx);
673 }
674 return 0;
675 }
676 int add_range(size_type arr_offset, size_type sz)
677 {
678 for (size_type i = 0; i < sz; ++i)
679 {
680 size_type idx = i + arr_offset;
681 BM_ASSERT(bv_index_.test(idx));
682
683 size_type r_idx = bv_index_.count_to(idx, bc_index_) - 1;
684 bv_target_.set_bit_no_check(r_idx);
685 }
686 return 0;
687 }
688
689 bvector_type& bv_target_;
690 const bvector_type& bv_index_;
691 const rs_index_type& bc_index_;
692 };
693 // ------------------------------------
694
695 bv_target.clear();
696 bv_target.init();
697
698 if (&bv_idx == &bv_src)
699 {
700 bv_target = bv_src;
701 return;
702 }
703 visitor_func func(bv_target, bv_idx, bc_idx);
704 bm::for_each_bit(bv_src, func);
705}
706
707
708
709
710} // bm
711
712
713#endif
#define BM_SCANNER_OP(x)
Definition: bmalgo.h:175
Algorithms for bvector<>
Definitions(internal)
#define BMNOEXCEPT
Definition: bmdef.h:82
#define BM_ASSERT
Definition: bmdef.h:139
#define FULL_BLOCK_FAKE_ADDR
Definition: bmdef.h:158
#define FULL_SUB_BLOCK_REAL_ADDR
Definition: bmdef.h:159
Bit manipulation primitives (internal)
Algorithms for rank compression of bit-vector.
Definition: bmalgo.h:453
void decompress(BV &bv_target, const BV &bv_idx, const BV &bv_src)
Rank decompression.
Definition: bmalgo.h:570
void compress_by_source(BV &bv_target, const BV &bv_idx, const rs_index_type &bc_idx, const BV &bv_src)
Source vector priority + index based rank.
Definition: bmalgo.h:647
BV::size_type size_type
Definition: bmalgo.h:456
void compress(BV &bv_target, const BV &bv_idx, const BV &bv_src)
Rank compression algorithm based on two palallel iterators/enumerators set of source vector gets re-m...
Definition: bmalgo.h:497
BV::rs_index_type rs_index_type
Definition: bmalgo.h:457
BMFORCEINLINE bool avx2_test_all_zero_wave(const void *ptr)
check if wave of pointers is all NULL
Definition: bmavx2.h:1592
BMFORCEINLINE bool sse42_test_all_zero_wave(const void *ptr) BMNOEXCEPT
check if wave of pointers is all NULL
Definition: bmsse4.h:671
int(* bit_visitor_callback_type)(void *handle_ptr, bm::id_t bit_idx)
Callback type to visit (callback style) bits in bit-vector(s)
Definition: bm.h:72
@ BM_SORTED
input set is sorted (ascending order)
Definition: bmconst.h:205
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
BV::size_type distance_and_operation(const BV &bv1, const BV &bv2) BMNOEXCEPT
Distance AND computing template function.
Definition: bmalgo_impl.h:853
@ COUNT_XOR
(A ^ B).count()
Definition: bmalgo_impl.h:60
@ COUNT_SUB_AB
(A - B).count()
Definition: bmalgo_impl.h:62
@ COUNT_AND
(A & B).count()
Definition: bmalgo_impl.h:59
@ COUNT_OR
(A | B).count()
Definition: bmalgo_impl.h:61
void rank_range_split(const BV &bv, typename BV::size_type rank, PairVect &target_v)
Algorithm to identify bit-vector ranges (splits) for the rank.
Definition: bmalgo.h:394
BV::size_type any_or(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes if there is any bit in OR operation of two bitsets.
Definition: bmalgo.h:165
BV::size_type any_xor(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes if there is any bit in XOR operation of two bitsets.
Definition: bmalgo.h:97
int visit_each_bit(const BV &bv, void *handle_ptr, bit_visitor_callback_type callback_ptr)
bvector visitor scanner to traverse each 1 bit using C callback
Definition: bmalgo.h:336
int visit_each_bit_range(const BV &bv, typename BV::size_type left, typename BV::size_type right, void *handle_ptr, bit_visitor_callback_type callback_ptr)
bvector visitor scanner to traverse each bits in range (C callback)
Definition: bmalgo.h:362
BV::size_type count_and(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes bitcount of AND operation of two bitsets.
Definition: bmalgo.h:49
BV::size_type count_or(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes bitcount of OR operation of two bitsets.
Definition: bmalgo.h:149
BV::size_type any_and(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes if there is any bit in AND operation of two bitsets.
Definition: bmalgo.h:62
BV::size_type count_sub(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes bitcount of SUB operation of two bitsets.
Definition: bmalgo.h:115
BV::size_type any_sub(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes if there is any bit in SUB operation of two bitsets.
Definition: bmalgo.h:132
int for_each_bit_range(const BV &bv, typename BV::size_type left, typename BV::size_type right, Func &bit_functor)
bit-vector range visitor to traverse each 1 bit
Definition: bmalgo.h:266
int for_each_bit(const BV &bv, Func &bit_functor)
bit-vector visitor scanner to traverse each 1 bit using C++ visitor
Definition: bmalgo.h:202
bm::distance_metric_descriptor::size_type count_xor(const BV &bv1, const BV &bv2) BMNOEXCEPT
Computes bitcount of XOR operation of two bitsets.
Definition: bmalgo.h:81
Definition: bm.h:78
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_sub_array_size
Definition: bmconst.h:95
BMFORCEINLINE void xor_swap(W &x, W &y) BMNOEXCEPT
XOR swap two variables.
Definition: bmutil.h:534
functor-adaptor for C-style callbacks
Definition: bmalgo_impl.h:121
Functor for bit-copy (for testing)
Definition: bmalgo.h:293
bit_vistor_copy_functor(BV &bv)
Definition: bmalgo.h:296
BV::size_type size_type
Definition: bmalgo.h:294
bit_visitor_callback_type func_
Definition: bmalgo.h:317
int add_bits(size_type offset, const unsigned char *bits, unsigned size)
Definition: bmalgo.h:302
int add_range(size_type offset, size_type size)
Definition: bmalgo.h:309
Distance metric descriptor, holds metric code and result.
Definition: bmalgo_impl.h:87