BitMagic-C++
bmfunc.h
Go to the documentation of this file.
1#ifndef BMFUNC__H__INCLUDED__
2#define BMFUNC__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 bmfunc.h
22 \brief Bit manipulation primitives (internal)
23*/
24
25#include <memory.h>
26#include <type_traits>
27
28#include "bmdef.h"
29#include "bmutil.h"
30
31
32#ifdef _MSC_VER
33# pragma warning( disable: 4146 )
34#endif
35
36namespace bm
37{
38
39
40template<bool LWA=false, bool RWA=false>
42 bm::word_t left,
44
45inline
47 bm::word_t left,
49
50/*!
51 @brief Structure with statistical information about memory
52 allocation footprint, serialization projection, number of vectors
53 @ingroup bvector
54*/
56{
57 size_t bit_blocks; ///< Number of bit blocks
58 size_t gap_blocks; ///< Number of GAP blocks
59 size_t ptr_sub_blocks; ///< Number of sub-blocks
60 size_t bv_count; ///< Number of bit-vectors
61 size_t max_serialize_mem; ///< estimated maximum memory for serialization
62 size_t memory_used; ///< memory usage for all blocks and service tables
63 size_t gap_cap_overhead; ///< gap memory overhead between length and capacity
64 gap_word_t gap_levels[bm::gap_levels]; ///< GAP block lengths in the bvect
65 unsigned long long gaps_by_level[bm::gap_levels]; ///< number of GAP blocks at each level
66
67 /// cound bit block
69 {
70 ++bit_blocks;
71 size_t mem_used = sizeof(bm::word_t) * bm::set_block_size;
72 memory_used += mem_used;
73 max_serialize_mem += mem_used;
74 }
75
76 /// count gap block
77 void add_gap_block(unsigned capacity, unsigned length, unsigned level) BMNOEXCEPT
78 {
80
81 ++gap_blocks;
82 size_t mem_used = (capacity * sizeof(gap_word_t));
83 memory_used += mem_used;
84 max_serialize_mem += (unsigned)(length * sizeof(gap_word_t));
85 BM_ASSERT(length <= capacity);
86 gap_cap_overhead += (capacity - length) * sizeof(gap_word_t);
87 if (level < bm::gap_levels)
88 gaps_by_level[level]++;
89 }
90
91 /// Reset statisctics
93 {
96 for (unsigned i = 0; i < bm::gap_levels; ++i)
97 gaps_by_level[i] = 0;
98 }
99
100 /// Sum data from another sttructure
102 {
103 bit_blocks += st.bit_blocks;
104 gap_blocks += st.gap_blocks;
105 ptr_sub_blocks += st.ptr_sub_blocks;
106 bv_count += st.bv_count;
107 max_serialize_mem += st.max_serialize_mem + 8;
108 memory_used += st.memory_used;
109 gap_cap_overhead += st.gap_cap_overhead;
110 }
111};
112
113/*!
114 @brief Structure with statistical information about memory
115 allocation for arena based vectors
116 @ingroup bvector
117*/
119{
120 size_t bit_blocks_sz; ///< Total size of bit blocks
121 size_t gap_blocks_sz; ///< Total size of gap blocks
122 size_t ptr_sub_blocks_sz; ///< Total size of sub-blocks ptrs
123 unsigned top_block_size; ///< size of top descriptor
124
125 /// Reset statisctics
127 {
129 }
130
131 /// Get allocation size in bytes
133 {
134 size_t sz = bit_blocks_sz * sizeof(bm::word_t);
135 sz += gap_blocks_sz * sizeof(bm::gap_word_t);
136 sz += (ptr_sub_blocks_sz + top_block_size) * sizeof(void*);
137 return sz;
138 }
139};
140
141/**
142 @brief Pair type
143*/
144template<typename First, typename Second>
145struct pair
146{
147 First first;
148 Second second;
149
150 pair(First f, Second s) : first(f), second(s) {}
151};
152
153/**
154 \brief bit-decode cache structure
155*/
157{
158 unsigned short bits[65]; //< decoded bits
159 unsigned bcnt; //< length of bits array
160 bm::id64_t cvalue; //< cache decoded value
161
163};
164
165
166/**
167 \brief Recalc linear bvector block index into 2D matrix coordinates
168 \internal
169*/
170template<typename BI_TYPE>
172void get_block_coord(BI_TYPE nb, unsigned& i, unsigned& j) BMNOEXCEPT
173{
174 i = unsigned(nb >> bm::set_array_shift); // top block address
175 j = unsigned(nb & bm::set_array_mask); // address in sub-block
176}
177
178/**
179 Compute bit address of the first bit in a superblock
180 \internal
181*/
182template<typename RTYPE>
184{
185 return RTYPE(i) * bm::set_sub_total_bits;
186}
187
188/**
189 Compute bit address of the first bit in a block
190 \internal
191*/
192template<typename RTYPE>
193BMFORCEINLINE RTYPE get_block_start(unsigned i, unsigned j) BMNOEXCEPT
194{
195 RTYPE idx = bm::get_super_block_start<RTYPE>(i);
196 idx += (j) * bm::gap_max_bits;
197 return idx;
198}
199
200
201/*!
202 @defgroup gapfunc GAP functions
203 GAP functions implement different opereations on GAP compressed blocks (internals)
204 and serve as a minimal building blocks.
205 \internal
206 @ingroup bvector
207 */
208
209/*!
210 @defgroup bitfunc BIT functions
211 Bit functions implement different opereations on bit blocks (internals)
212 and serve as a minimal building blocks.
213 \internal
214 @ingroup bvector
215 */
216
217
218/**
219 32-bit paralle, bitcount
220 \internal
221 @ingroup bitfunc
222 */
223inline
225{
226 unsigned int tmp;
227
228 tmp = n - ((n >> 1) & 033333333333)
229 - ((n >> 2) & 011111111111);
230 return ((tmp + (tmp >> 3)) & 030707070707) % 63;
231}
232
233
234
235/*!
236 Parallel popcount on 4x 64-bit words
237 @ingroup bitfunc
238*/
239inline
242{
243 const bm::id64_t m1 = 0x5555555555555555U;
244 const bm::id64_t m2 = 0x3333333333333333U;
245 const bm::id64_t m3 = 0x0F0F0F0F0F0F0F0FU;
246 const bm::id64_t m4 = 0x000000FF000000FFU;
247
248 x = x - ((x >> 1) & m1);
249 y = y - ((y >> 1) & m1);
250 u = u - ((u >> 1) & m1);
251 v = v - ((v >> 1) & m1);
252 x = (x & m2) + ((x >> 2) & m2);
253 y = (y & m2) + ((y >> 2) & m2);
254 u = (u & m2) + ((u >> 2) & m2);
255 v = (v & m2) + ((v >> 2) & m2);
256 x = x + y;
257 u = u + v;
258 x = (x & m3) + ((x >> 4) & m3);
259 u = (u & m3) + ((u >> 4) & m3);
260 x = x + u;
261 x = x + (x >> 8);
262 x = x + (x >> 16);
263 x = x & m4;
264 x = x + (x >> 32);
265 return x & 0x000001FFU;
266}
267
268
269// --------------------------------------------------------------
270// Functions for bit-scanning
271// --------------------------------------------------------------
272
273/*!
274 \brief Templated algorithm to unpacks octet based word into list of ON bit indexes
275 \param w - value
276 \param func - bit functor
277
278 @ingroup bitfunc
279*/
280template<typename T, typename F>
281void bit_for_each_4(T w, F& func)
282{
283 for (unsigned sub_octet = 0; w != 0; w >>= 4, sub_octet += 4)
284 {
285 switch (w & 15) // 1111
286 {
287 case 0: // 0000
288 break;
289 case 1: // 0001
290 func(sub_octet);
291 break;
292 case 2: // 0010
293 func(sub_octet + 1);
294 break;
295 case 3: // 0011
296 func(sub_octet, sub_octet + 1);
297 break;
298 case 4: // 0100
299 func(sub_octet + 2);
300 break;
301 case 5: // 0101
302 func(sub_octet, sub_octet + 2);
303 break;
304 case 6: // 0110
305 func(sub_octet + 1, sub_octet + 2);
306 break;
307 case 7: // 0111
308 func(sub_octet, sub_octet + 1, sub_octet + 2);
309 break;
310 case 8: // 1000
311 func(sub_octet + 3);
312 break;
313 case 9: // 1001
314 func(sub_octet, sub_octet + 3);
315 break;
316 case 10: // 1010
317 func(sub_octet + 1, sub_octet + 3);
318 break;
319 case 11: // 1011
320 func(sub_octet, sub_octet + 1, sub_octet + 3);
321 break;
322 case 12: // 1100
323 func(sub_octet + 2, sub_octet + 3);
324 break;
325 case 13: // 1101
326 func(sub_octet, sub_octet + 2, sub_octet + 3);
327 break;
328 case 14: // 1110
329 func(sub_octet + 1, sub_octet + 2, sub_octet + 3);
330 break;
331 case 15: // 1111
332 func(sub_octet, sub_octet + 1, sub_octet + 2, sub_octet + 3);
333 break;
334 default:
335 BM_ASSERT(0);
336 break;
337 }
338
339 } // for
340}
341
342
343/*!
344 \brief Templated algorithm to unpacks word into list of ON bit indexes
345 \param w - value
346 \param func - bit functor
347
348 @ingroup bitfunc
349*/
350template<typename T, typename F>
351void bit_for_each(T w, F& func)
352{
353 // Note: 4-bit table method works slower than plain check approach
354 for (unsigned octet = 0; w != 0; w >>= 8, octet += 8)
355 {
356 if (w & 1) func(octet + 0);
357 if (w & 2) func(octet + 1);
358 if (w & 4) func(octet + 2);
359 if (w & 8) func(octet + 3);
360 if (w & 16) func(octet + 4);
361 if (w & 32) func(octet + 5);
362 if (w & 64) func(octet + 6);
363 if (w & 128) func(octet + 7);
364
365 } // for
366}
367
368/**
369 portable, switch based bitscan
370 @internal
371 @ingroup bitfunc
372 */
373inline
374unsigned bitscan_nibble(unsigned w, unsigned* bits) BMNOEXCEPT
375{
376 unsigned cnt = 0;
377 for (unsigned sub_octet = 0; w; w >>= 4, sub_octet+=4)
378 {
379 switch (w & 15) // 1111
380 {
381 //case 0: // 0000
382 // break;
383 case 1: // 0001
384 bits[cnt++] = 0 + sub_octet;
385 break;
386 case 2: // 0010
387 bits[cnt++] = 1 + sub_octet;
388 break;
389 case 3: // 0011
390 bits[cnt] = 0 + sub_octet;
391 bits[cnt+1] = 1 + sub_octet;
392 cnt += 2;
393 break;
394 case 4: // 0100
395 bits[cnt++] = 2 + sub_octet;
396 break;
397 case 5: // 0101
398 bits[cnt+0] = 0 + sub_octet;
399 bits[cnt+1] = 2 + sub_octet;
400 cnt += 2;
401 break;
402 case 6: // 0110
403 bits[cnt+0] = 1 + sub_octet;
404 bits[cnt+1] = 2 + sub_octet;
405 cnt += 2;
406 break;
407 case 7: // 0111
408 bits[cnt+0] = 0 + sub_octet;
409 bits[cnt+1] = 1 + sub_octet;
410 bits[cnt+2] = 2 + sub_octet;
411 cnt += 3;
412 break;
413 case 8: // 1000
414 bits[cnt++] = 3 + sub_octet;
415 break;
416 case 9: // 1001
417 bits[cnt+0] = 0 + sub_octet;
418 bits[cnt+1] = 3 + sub_octet;
419 cnt += 2;
420 break;
421 case 10: // 1010
422 bits[cnt+0] = 1 + sub_octet;
423 bits[cnt+1] = 3 + sub_octet;
424 cnt += 2;
425 break;
426 case 11: // 1011
427 bits[cnt+0] = 0 + sub_octet;
428 bits[cnt+1] = 1 + sub_octet;
429 bits[cnt+2] = 3 + sub_octet;
430 cnt += 3;
431 break;
432 case 12: // 1100
433 bits[cnt+0] = 2 + sub_octet;
434 bits[cnt+1] = 3 + sub_octet;
435 cnt += 2;
436 break;
437 case 13: // 1101
438 bits[cnt+0] = 0 + sub_octet;
439 bits[cnt+1] = 2 + sub_octet;
440 bits[cnt+2] = 3 + sub_octet;
441 cnt += 3;
442 break;
443 case 14: // 1110
444 bits[cnt+0] = 1 + sub_octet;
445 bits[cnt+1] = 2 + sub_octet;
446 bits[cnt+2] = 3 + sub_octet;
447 cnt += 3;
448 break;
449 case 15: // 1111
450 bits[cnt+0] = 0 + sub_octet;
451 bits[cnt+1] = 1 + sub_octet;
452 bits[cnt+2] = 2 + sub_octet;
453 bits[cnt+3] = 3 + sub_octet;
454 cnt += 4;
455 break;
456 default:
457 break;
458 }
459 } // for
460 return cnt;
461}
462
463#ifdef BM_NONSTANDARD_EXTENTIONS
464#ifdef __GNUC__
465/**
466 bitscan based on computed goto (GCC/clang)
467 @internal
468 @ingroup bitfunc
469 */
470inline
471unsigned bitscan_nibble_gcc(unsigned w, unsigned* bits) BMNOEXCEPT
472{
473 static void* d_table[] = { &&l0,
474 &&l1, &&l3_1, &&l3, &&l7_1, &&l5, &&l7_0, &&l7, &&l15_1,
475 &&l9, &&l11_0, &&l11, &&l15_0, &&l13, &&l14, &&l15 };
476 unsigned cnt = 0;
477
478 for (unsigned sub_octet = 0; w; w >>= 4, sub_octet+=4)
479 {
480 goto *d_table[w & 15];
481 l1: // 0001
482 bits[cnt++] = sub_octet;
483 continue;
484 l3: // 0011
485 bits[cnt++] = sub_octet;
486 l3_1:
487 bits[cnt++] = 1 + sub_octet;
488 continue;
489 l5: // 0101
490 bits[cnt++] = sub_octet;
491 goto l7_1;
492 l7: // 0111
493 bits[cnt++] = sub_octet;
494 l7_0:
495 bits[cnt++] = 1 + sub_octet;
496 l7_1:
497 bits[cnt++] = 2 + sub_octet;
498 continue;
499 l9: // 1001
500 bits[cnt++] = sub_octet;
501 goto l15_1;
502 continue;
503 l11: // 1011
504 bits[cnt++] = sub_octet;
505 l11_0:
506 bits[cnt++] = 1 + sub_octet;
507 bits[cnt++] = 3 + sub_octet;
508 continue;
509 l13: // 1101
510 bits[cnt++] = sub_octet;
511 goto l15_0;
512 l14: // 1110
513 bits[cnt++] = 1 + sub_octet;
514 goto l15_0;
515 l15: // 1111
516 bits[cnt++] = 0 + sub_octet;
517 bits[cnt++] = 1 + sub_octet;
518 l15_0:
519 bits[cnt++] = 2 + sub_octet;
520 l15_1:
521 bits[cnt++] = 3 + sub_octet;
522 l0:
523 continue;
524 } // for
525 return cnt;
526}
527
528#endif
529#endif
530
531/*! @brief Adaptor to copy 1 bits to array
532 @internal
533*/
534template<typename B>
536{
537public:
538 copy_to_array_functor(B* bits): bp_(bits)
539 {}
540
541 B* ptr() { return bp_; }
542
543 void operator()(unsigned bit_idx) BMNOEXCEPT { *bp_++ = (B)bit_idx; }
544
545 void operator()(unsigned bit_idx0,
546 unsigned bit_idx1) BMNOEXCEPT
547 {
548 bp_[0] = (B)bit_idx0; bp_[1] = (B)bit_idx1;
549 bp_+=2;
550 }
551
552 void operator()(unsigned bit_idx0,
553 unsigned bit_idx1,
554 unsigned bit_idx2) BMNOEXCEPT
555 {
556 bp_[0] = (B)bit_idx0; bp_[1] = (B)bit_idx1; bp_[2] = (B)bit_idx2;
557 bp_+=3;
558 }
559
560 void operator()(unsigned bit_idx0,
561 unsigned bit_idx1,
562 unsigned bit_idx2,
563 unsigned bit_idx3) BMNOEXCEPT
564 {
565 bp_[0] = (B)bit_idx0; bp_[1] = (B)bit_idx1;
566 bp_[2] = (B)bit_idx2; bp_[3] = (B)bit_idx3;
567 bp_+=4;
568 }
569
570private:
573private:
574 B* bp_;
575};
576
577
578/*!
579 \brief Unpacks word into list of ON bit indexes
580 \param w - value
581 \param bits - pointer on the result array
582 \return number of bits in the list
583
584 @ingroup bitfunc
585*/
586template<typename T,typename B>
587unsigned bit_list(T w, B* bits) BMNOEXCEPT
588{
589 copy_to_array_functor<B> func(bits);
590 bit_for_each(w, func);
591 return (unsigned)(func.ptr() - bits);
592}
593
594
595
596/*!
597 \brief Unpacks word into list of ON bit indexes (quad-bit based)
598 \param w - value
599 \param bits - pointer on the result array
600 \return number of bits in the list
601
602 @ingroup bitfunc
603*/
604template<typename T,typename B>
605unsigned bit_list_4(T w, B* bits) BMNOEXCEPT
606{
607 copy_to_array_functor<B> func(bits);
608 bit_for_each_4(w, func);
609 return (unsigned)(func.ptr() - bits);
610}
611
612/*!
613 \brief Unpacks word into list of ON bit indexes using popcnt method
614 \param w - value
615 \param bits - pointer on the result array
616 \param offs - value to add to bit position (programmed shift)
617 \return number of bits in the list
618
619 @ingroup bitfunc
620 @internal
621*/
622template<typename B>
623unsigned short
624bitscan_popcnt(bm::id_t w, B* bits, unsigned short offs) BMNOEXCEPT
625{
626 unsigned pos = 0;
627 while (w)
628 {
629 bm::id_t t = w & -w;
630 bits[pos++] = (B)(bm::word_bitcount(t - 1) + offs);
631 w &= w - 1;
632 }
633 return (unsigned short)pos;
634}
635
636/*!
637 \brief Unpacks word into list of ON bit indexes using popcnt method
638 \param w - value
639 \param bits - pointer on the result array
640 \return number of bits in the list
641
642 @ingroup bitfunc
643 @internal
644*/
645template<typename B>
646unsigned short bitscan_popcnt(bm::id_t w, B* bits) BMNOEXCEPT
647{
648 unsigned pos = 0;
649 while (w)
650 {
651 bm::id_t t = w & -w;
652 bits[pos++] = (B)(bm::word_bitcount(t - 1));
653 w &= w - 1;
654 }
655 return (unsigned short)pos;
656}
657
658
659/*!
660 \brief Unpacks 64-bit word into list of ON bit indexes using popcnt method
661 \param w - value
662 \param bits - pointer on the result array
663 \return number of bits in the list
664 @ingroup bitfunc
665*/
666template<typename B>
667unsigned short bitscan_popcnt64(bm::id64_t w, B* bits) BMNOEXCEPT
668{
669 unsigned short pos = 0;
670 while (w)
671 {
672 bm::id64_t t = bmi_blsi_u64(w); // w & -w;
673 bits[pos++] = (B) bm::word_bitcount64(t - 1);
674 w = bmi_bslr_u64(w); // w &= w - 1;
675 }
676 return pos;
677}
678
679/*!
680 \brief Unpacks word into list of ON bits (BSF/__builtin_ctz)
681 \param w - value
682 \param bits - pointer on the result array
683 \return number of bits in the list
684
685 @ingroup bitfunc
686 @internal
687*/
688template<typename B>
689unsigned short bitscan_bsf(unsigned w, B* bits) BMNOEXCEPT
690{
691 unsigned short pos = 0;
692 while (w)
693 {
694 bits[pos++] = count_trailing_zeros_u32(w);
695 w &= w - 1;
696 }
697 return pos;
698}
699
700template<typename B, typename OT>
701unsigned short bitscan_bsf(unsigned w, B* bits, OT offs) BMNOEXCEPT
702{
703 unsigned short pos = 0;
704 while (w)
705 {
706 bits[pos++] = (B) (bm::count_trailing_zeros_u32(w) + offs);
707 w &= w - 1;
708 }
709 return pos;
710}
711
712/*!
713 \brief Unpacks word into list of ON bits (BSF/__builtin_ctz)
714 \param w - value
715 \param bits - pointer on the result array
716 \return number of bits in the list
717
718 @ingroup bitfunc
719 @internal
720*/
721template<typename B>
722unsigned short bitscan_bsf64(bm::id64_t w, B* bits) BMNOEXCEPT
723{
724 unsigned short pos = 0;
725 while (w)
726 {
727 bits[pos++] = bm::count_trailing_zeros_u64(w);
728 w &= w - 1;
729 }
730 return pos;
731}
732
733
734/*!
735 \brief Unpacks 64-bit word into list of ON bit indexes using popcnt method
736 \param w - value
737 \param bits - pointer on the result array
738 \param offs - value to add to bit position (programmed shift)
739 \return number of bits in the list
740 @ingroup bitfunc
741*/
742template<typename B>
743unsigned short
744bitscan_popcnt64(bm::id64_t w, B* bits, unsigned short offs) BMNOEXCEPT
745{
746 unsigned short pos = 0;
747 while (w)
748 {
749 bm::id64_t t = bmi_blsi_u64(w); // w & -w;
750 bits[pos++] = B(bm::word_bitcount64(t - 1) + offs);
751 w = bmi_bslr_u64(w); // w &= w - 1;
752 }
753 return pos;
754}
755
756/**
757 Templated Bitscan with dynamic dispatch for best type
758 @ingroup bitfunc
759 */
760template<typename V, typename B>
761unsigned short bitscan(V w, B* bits) BMNOEXCEPT
762{
763 static_assert(std::is_unsigned<V>::value, "BM: unsigned type is required");
764#if (defined(__arm__) || defined(__aarch64__))
765 if constexpr (sizeof(V) == 8)
766 return bm::bitscan_bsf64(w, bits);
767 else
768 return bm::bitscan_bsf((bm::word_t)w, bits);
769#else
770 if constexpr (sizeof(V) == 8)
771 return bm::bitscan_popcnt64(w, bits);
772 else
773 return bm::bitscan_popcnt((bm::word_t)w, bits);
774#endif
775}
776
777// --------------------------------------------------------------
778// Functions for select
779// --------------------------------------------------------------
780
781/**
782 \brief word find index of the rank-th bit set by bit-testing
783 \param w - 64-bit work to search
784 \param rank - rank to select (should be > 0)
785
786 \return selected value (inxed of bit set)
787 @ingroup bitfunc
788 @internal
789*/
790inline
792{
793 BM_ASSERT(w);
794 BM_ASSERT(rank);
795
796 for (unsigned count = 0; w; w >>=1ull, ++count)
797 {
798 rank -= unsigned(w & 1ull);
799 if (!rank)
800 return count;
801 }
802 BM_ASSERT(0); // shoud not be here if rank is achievable
803 return ~0u;
804}
805
806/**
807 \brief word find index of the rank-th bit set by bit-testing
808 \param w - 64-bit work to search
809 \param rank - rank to select (should be > 0)
810
811 \return selected value (inxed of bit set)
812 @ingroup bitfunc
813 @internal
814
815*/
816inline
818{
819 BM_ASSERT(w);
820 BM_ASSERT(rank);
821 BM_ASSERT(rank <= bm::word_bitcount64(w));
822
823 do
824 {
825 --rank;
826 if (!rank)
827 break;
828 w &= w - 1;
829 } while (1);
830 bm::id64_t t = w & -w;
831 unsigned count = bm::word_bitcount64(t - 1);
832 return count;
833}
834
835/**
836 \brief word find index of the rank-th bit set by bit-testing
837 \param w - 64-bit work to search
838 \param rank - rank to select (should be > 0)
839
840 \return selected value (inxed of bit set)
841 @ingroup bitfunc
842 @internal
843
844*/
845inline
847{
848 BM_ASSERT(w);
849 BM_ASSERT(rank);
850 BM_ASSERT(rank <= bm::word_bitcount64(w));
851
852 do
853 {
854 if (!(--rank))
855 break;
856 w &= w - 1;
857 } while (1);
858 bm::id64_t t = w & -w;
859 unsigned count = bm::count_trailing_zeros_u64(t);
860 return count;
861}
862
863
864
865/**
866 \brief word find index of the rank-th bit set by bit-testing
867 \param w - 32-bit work to search
868 \param rank - rank to select (should be > 0)
869
870 \return selected value (inxed of bit set)
871 @ingroup bitfunc
872 @internal
873*/
874inline
875unsigned word_select32_bitscan_popcnt(unsigned w, unsigned rank) BMNOEXCEPT
876{
877 BM_ASSERT(w);
878 BM_ASSERT(rank);
879 BM_ASSERT(rank <= bm::word_bitcount(w));
880
881 do
882 {
883 --rank;
884 if (!rank)
885 break;
886 w &= w - 1;
887 } while (1);
888 unsigned t = w & -w;
889 unsigned count = bm::word_bitcount(t - 1);
890 return count;
891}
892
893/**
894 \brief word find index of the rank-th bit set by bit-testing
895 \param w - 32-bit work to search
896 \param rank - rank to select (should be > 0)
897
898 \return selected value (inxed of bit set)
899 @ingroup bitfunc
900 @internal
901
902*/
903inline
904unsigned word_select32_bitscan_tz(unsigned w, unsigned rank) BMNOEXCEPT
905{
906 BM_ASSERT(w);
907 BM_ASSERT(rank);
908 BM_ASSERT(rank <= bm::word_bitcount(w));
909
910 do
911 {
912 if (!(--rank))
913 break;
914 w &= w - 1;
915 } while (1);
916 return bm::count_trailing_zeros_u32(w & -w);
917}
918
919
920/**
921 \brief word find index of the rank-th bit set by bit-testing
922 \param w - 64-bit work to search
923 \param rank - rank to select (should be > 0)
924
925 \return selected value (inxed of bit set)
926 @ingroup bitfunc
927 @internal
928*/
929inline
930unsigned word_select64(bm::id64_t w, unsigned rank) BMNOEXCEPT
931{
932#if defined(BMI2_SELECT64)
933 return BMI2_SELECT64(w, rank);
934#else
935 #if defined(BMI1_SELECT64)
936 return BMI2_SELECT64(w, rank);
937 #else
938 #if (defined(__arm__) || defined(__aarch64__))
939 return bm::word_select64_bitscan_tz(w, rank);
940 #else
941 return bm::word_select64_bitscan_popcnt(w, rank);
942 #endif
943 #endif
944#endif
945}
946
947/**
948 \brief word find index of the rank-th bit set by bit-testing
949 \param w - 32-bit work to search
950 \param rank - rank to select (should be > 0)
951
952 \return selected value (inxed of bit set)
953 @ingroup bitfunc
954 @internal
955*/
956inline
957unsigned word_select32(unsigned w, unsigned rank) BMNOEXCEPT
958{
959#if defined(BMI2_SELECT64)
960 return BMI2_SELECT64(w, rank);
961#else
962 #if defined(BMI1_SELECT64)
963 return BMI2_SELECT64(w, rank);
964 #else
965 #if (defined(__arm__) || defined(__aarch64__))
966 return bm::word_select32_bitscan_tz(w, rank);
967 #else
968 return bm::word_select32_bitscan_popcnt(w, rank);
969 #endif
970 #endif
971#endif
972}
973
974
975
976// --------------------------------------------------------------
977// Functions for bit-block digest calculation
978// --------------------------------------------------------------
979
980/*!
981 \brief Compute digest mask for word address in block
982
983 @return digest bit-mask
984
985 @ingroup bitfunc
986 @internal
987*/
990{
991 bm::id64_t mask(1ull);
992 return mask << (w_idx / bm::set_block_digest_wave_size);
993}
994
995/** digest mask control generation (for debug and test only)
996 @internal
997 */
998inline
999bm::id64_t dm_control(unsigned from, unsigned to) BMNOEXCEPT
1000{
1001 bm::id64_t m = 0;
1002 for (unsigned i = from; i <= to; ++i)
1003 m |= (1ull << (i / 1024));
1004 return m;
1005}
1006
1007
1008/**
1009 \brief Compute digest mask for [from..to] positions
1010 \param from - range from (in bit-block coordinates)
1011 \param to - range to (in bit-block coordinates)
1012
1013 @ingroup bitfunc
1014 @internal
1015*/
1017bm::id64_t digest_mask(unsigned from, unsigned to) BMNOEXCEPT
1018{
1019 BM_ASSERT(from <= to);
1021
1022 bm::id64_t digest_from = from >> bm::set_block_digest_pos_shift;
1023 bm::id64_t digest_to = to >> bm::set_block_digest_pos_shift;;
1024 bm::id64_t mask(~0ull);
1025 mask = (mask >> (63 - (digest_to - digest_from))) << digest_from;
1026
1027 //BM_ASSERT(mask == bm::dm_control(from, to));
1028
1029 return mask;
1030}
1031
1032
1033/*!
1034 \brief check if all digest bits for the range [from..to] are 0
1035
1036 \param digest - current digest
1037 \param bitpos_from - range from (in bit-block coordinates)
1038 \param bitpos_to - range to (in bit-block coordinates)
1039
1040 @return true if all range is zero
1041
1042 @ingroup bitfunc
1043 @internal
1044*/
1045inline
1047 unsigned bitpos_from, unsigned bitpos_to) BMNOEXCEPT
1048{
1049 bm::id64_t mask = bm::digest_mask(bitpos_from, bitpos_to);
1050 return !(digest & mask);
1051}
1052
1053/*!
1054 \brief Init block with 000111000 pattren based on digest
1055 \param block - Bit block [out]
1056 \param digest - digest (used for block initialization)
1057
1058 @ingroup bitfunc
1059 @internal
1060*/
1061inline
1063{
1064 unsigned off;
1065 for (unsigned i = 0; i < 64; ++i)
1066 {
1068 bm::word_t mask = (digest & 1) ? ~0u : 0u;
1069#if defined(VECT_BLOCK_SET_DIGEST)
1070 VECT_BLOCK_SET_DIGEST(&block[off], mask);
1071#else
1072 for (unsigned j = 0; j < bm::set_block_digest_wave_size; j+=4)
1073 {
1074 block[off+j+0] = block[off+j+1] =
1075 block[off+j+2] = block[off+j+3] = mask;
1076 } // for j
1077#endif
1078 digest >>= 1ull;
1079 } // for
1080}
1081
1082/*!
1083 \brief Compute digest for 64 non-zero areas
1084 \param block - Bit block
1085
1086 @return digest bit-mask (0 means all block is empty)
1087
1088 @ingroup bitfunc
1089 @internal
1090*/
1091inline
1093{
1094 bm::id64_t digest0 = 0;
1095 unsigned off;
1096
1097 for (unsigned i = 0; i < 64; ++i)
1098 {
1100 #if defined(VECT_IS_DIGEST_ZERO)
1101 bool all_zero = VECT_IS_DIGEST_ZERO(&block[off]);
1102 digest0 |= bm::id64_t(!all_zero) << i;
1103 #else
1104 const bm::id64_t mask(1ull);
1105 for (unsigned j = 0; j < bm::set_block_digest_wave_size; j+=4)
1106 {
1107 bm::word_t w = block[off+j+0] | block[off+j+1] |
1108 block[off+j+2] | block[off+j+3];
1109 if (w)
1110 {
1111 digest0 |= (mask << i);
1112 break;
1113 }
1114 } // for j
1115 #endif
1116
1117 } // for i
1118 return digest0;
1119}
1120
1121/*!
1122 \brief Compute digest for 64 non-zero areas based on existing digest
1123 (function revalidates zero areas)
1124 \param block - bit block
1125 \param digest - start digest
1126
1127 @return digest bit-mask (0 means all block is empty)
1128
1129 @ingroup bitfunc
1130 @internal
1131*/
1132inline
1135{
1136 const bm::id64_t mask(1ull);
1137 bm::id64_t d = digest;
1138
1139 while (d)
1140 {
1141 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
1142
1143 unsigned wave = bm::word_bitcount64(t - 1);
1144 unsigned off = wave * bm::set_block_digest_wave_size;
1145
1146 #if defined(VECT_IS_DIGEST_ZERO)
1147 bool all_zero = VECT_IS_DIGEST_ZERO(&block[off]);
1148 digest &= all_zero ? ~(mask << wave) : digest;
1149 #else
1151 (const bm::bit_block_t::bunion_t*)(&block[off]);
1152 bm::id64_t w64 = 0;
1153 unsigned j = 0;
1154 do
1155 {
1156 w64 |=
1157 src_u->w64[j+0] | src_u->w64[j+1] | src_u->w64[j+2] | src_u->w64[j+3];
1158 j += 4;
1159 } while ((j < bm::set_block_digest_wave_size/2) & !w64);
1160 digest &= w64 ? digest : ~(mask << wave);
1161 #endif
1162
1163 d = bm::bmi_bslr_u64(d); // d &= d - 1;
1164 } // while
1165
1166 BM_ASSERT(bm::calc_block_digest0(block) == digest);
1167 return digest;
1168}
1169
1170// --------------------------------------------------------------
1171
1172/**
1173 Compact sub-blocks by digest (rank compaction)
1174 \param t_block - target block
1175 \param block - src bit block
1176 \param digest - digest to use for copy
1177 \param zero_tail - flag to zero the tail memory
1178
1179 @ingroup bitfunc
1180 @internal
1181 */
1182inline
1184 const bm::word_t* block,
1185 bm::id64_t digest,
1186 bool zero_tail) BMNOEXCEPT
1187{
1188 unsigned t_wave = 0;
1189 bm::id64_t d = digest;
1190
1191 while (d)
1192 {
1193 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
1194 unsigned wave = bm::word_bitcount64(t - 1);
1195 unsigned off = wave * bm::set_block_digest_wave_size;
1196 unsigned t_off = t_wave * bm::set_block_digest_wave_size;
1197
1198 const bm::word_t* sub_block = block + off;
1199 bm::word_t* t_sub_block = t_block + t_off;
1200 const bm::word_t* sub_block_end =
1202 // TODO 64-bit optimization or SIMD
1203 for (; sub_block < sub_block_end; t_sub_block+=4, sub_block+=4)
1204 {
1205 t_sub_block[0] = sub_block[0];
1206 t_sub_block[1] = sub_block[1];
1207 t_sub_block[2] = sub_block[2];
1208 t_sub_block[3] = sub_block[3];
1209 } // for
1210
1211 d = bm::bmi_bslr_u64(d); // d &= d - 1;
1212 ++t_wave;
1213 } // while
1214
1215 // init rest as zeroes (maybe need to be parametric)
1216 //
1217 if (zero_tail)
1218 {
1219 for ( ;t_wave < bm::block_waves; ++t_wave)
1220 {
1221 unsigned t_off = t_wave * bm::set_block_digest_wave_size;
1222 bm::word_t* t_sub_block = t_block + t_off;
1223 const bm::word_t* t_sub_block_end =
1224 t_sub_block + bm::set_block_digest_wave_size;
1225 for (; t_sub_block < t_sub_block_end; t_sub_block+=4)
1226 {
1227 t_sub_block[0] = 0;
1228 t_sub_block[1] = 0;
1229 t_sub_block[2] = 0;
1230 t_sub_block[3] = 0;
1231 } // for
1232 } // for
1233 }
1234}
1235
1236// --------------------------------------------------------------
1237
1238/**
1239 expand sub-blocks by digest (rank expansion)
1240 \param t_block - target block
1241 \param block - src bit block
1242 \param digest - digest to use for copy
1243 \param zero_subs - flag to zero the non-digest sub waves
1244
1245 @ingroup bitfunc
1246 @internal
1247 */
1248
1249inline
1251 const bm::word_t* block,
1252 bm::id64_t digest,
1253 bool zero_subs) BMNOEXCEPT
1254{
1255 unsigned s_wave = 0;
1256 bm::id64_t d = digest;
1257
1258 bm::id64_t mask1 = 1ULL;
1259 for (unsigned wave = 0; wave < bm::block_waves; ++wave)
1260 {
1261 unsigned s_off = s_wave * bm::set_block_digest_wave_size;
1262 const bm::word_t* sub_block = block + s_off;
1263 const bm::word_t* sub_block_end =
1265 bm::word_t* t_sub_block =
1266 t_block + (wave * bm::set_block_digest_wave_size);
1267 if (d & mask1)
1268 {
1269 for (; sub_block < sub_block_end; t_sub_block+=4, sub_block+=4)
1270 {
1271 t_sub_block[0] = sub_block[0];
1272 t_sub_block[1] = sub_block[1];
1273 t_sub_block[2] = sub_block[2];
1274 t_sub_block[3] = sub_block[3];
1275 } // for
1276
1277 ++s_wave;
1278 }
1279 else
1280 {
1281 if (zero_subs)
1282 {
1283 const bm::word_t* t_sub_block_end =
1284 t_sub_block + bm::set_block_digest_wave_size;
1285 for (; t_sub_block < t_sub_block_end; t_sub_block+=4)
1286 {
1287 t_sub_block[0] = 0; t_sub_block[1] = 0;
1288 t_sub_block[2] = 0; t_sub_block[3] = 0;
1289 } // for
1290 }
1291 }
1292 mask1 <<= 1;
1293 } // for i
1294}
1295
1296
1297// --------------------------------------------------------------
1298
1299
1300/// Returns true if set operation is constant (bitcount)
1301inline
1303{
1304 return (int(op) >= int(set_COUNT));
1305}
1306
1307/**
1308 Convert set operation to operation
1309*/
1310inline
1312{
1313 BM_ASSERT(op == set_AND ||
1314 op == set_OR ||
1315 op == set_SUB ||
1316 op == set_XOR);
1317 return (bm::operation) op;
1318}
1319
1320//---------------------------------------------------------------------
1321
1322/**
1323 Structure carries pointer on bit block with all bits 1
1324 @ingroup bitfunc
1325 @internal
1326*/
1327template<bool T> struct all_set
1328{
1330 {
1334
1336 {
1337 ::memset(_p, 0xFF, sizeof(_p)); // set FULL BLOCK content (all 1s)
1338 if constexpr (sizeof(void*) == 8)
1339 {
1340 const unsigned long long magic_mask = 0xFFFFfffeFFFFfffe;
1341 ::memcpy(&_p_fullp, &magic_mask, sizeof(magic_mask));
1342 for (unsigned i = 0; i < bm::set_sub_array_size; ++i)
1343 _s[i] = reinterpret_cast<bm::word_t*>(magic_mask);
1344 }
1345 else
1346 {
1347 const unsigned magic_mask = 0xFFFFfffe;
1348 ::memcpy(&_p_fullp, &magic_mask, sizeof(magic_mask));
1349 for (unsigned i = 0; i < bm::set_sub_array_size; ++i)
1350 _s[i] = reinterpret_cast<bm::word_t*>(magic_mask);
1351 }
1352 }
1353 };
1354
1355 // version with minimal branching, super-scalar friendly
1356 //
1357 inline
1359 {
1360 bm::id64_t type;
1361 if constexpr (sizeof(void*) == 8)
1362 {
1363 bm::id64_t w = reinterpret_cast<unsigned long long>(bp);
1364 type = (w & 3) | // FULL BLOCK or GAP
1365 ((bp == _block._p) << 1);
1366 type = type ? type : w;
1367 }
1368 else
1369 {
1370 unsigned w = reinterpret_cast<unsigned long>(bp);
1371 type = (w & 3) | // FULL BLOCK or GAP
1372 ((bp == _block._p) << 1);
1373 type = type ? type : w;
1374 }
1375 return type;
1376 }
1377
1379 static bool is_full_block(const bm::word_t* bp) BMNOEXCEPT
1380 { return (bp == _block._p || bp == _block._p_fullp); }
1381
1384 { return (bp && !(bp == _block._p || bp == _block._p_fullp)); }
1385
1387};
1388
1389
1390template<bool T> typename all_set<T>::all_set_block all_set<T>::_block;
1391
1392
1393/*!
1394 Fini not NULL position
1395 @return index of not NULL pointer
1396 @internal
1397*/
1398template<typename N>
1399bool find_not_null_ptr(const bm::word_t* const * const* arr,
1400 N start, N size, N* pos) BMNOEXCEPT
1401{
1402 BM_ASSERT(pos);
1403// BM_ASSERT(start < size);
1404//#if defined(BM64_AVX2) || defined(BM64_AVX512)
1405// TODO: optimization for SIMD based next ptr scan
1406#if 0
1407 const unsigned unroll_factor = 4;
1408 const unsigned len = (size - start);
1409 const unsigned len_unr = len - (len % unroll_factor);
1410 unsigned k;
1411
1412 arr += start;
1413 for (k = 0; k < len_unr; k+=unroll_factor)
1414 {
1415 if (!avx2_test_all_zero_wave(arr+k))
1416 {
1417 if (arr[k])
1418 {
1419 *pos = k + start;
1420 return true;
1421 }
1422 if (arr[k+1])
1423 {
1424 *pos = k + start + 1;
1425 return true;
1426 }
1427 if (arr[k+2])
1428 {
1429 *pos = k + start + 2;
1430 return true;
1431 }
1432 if (arr[k+3])
1433 {
1434 *pos = k + start + 3;
1435 return true;
1436 }
1437 }
1438 } // for k
1439
1440 for (; k < len; ++k)
1441 {
1442 if (arr[k])
1443 {
1444 *pos = k + start;
1445 return true;
1446 }
1447 } // for k
1448#else
1449 for (; start < size; ++start)
1450 {
1451 if (arr[start])
1452 {
1453 *pos = start;
1454 return true;
1455 }
1456 } // for i
1457#endif
1458 return false;
1459}
1460
1461
1462
1463
1464//---------------------------------------------------------------------
1465
1466/*!
1467 \brief Lexicographical comparison of two words as bit strings (reference)
1468 Auxiliary implementation for testing and reference purposes.
1469 \param w1 - First word.
1470 \param w2 - Second word.
1471 \return <0 - less, =0 - equal, >0 - greater.
1472
1473 @ingroup bitfunc
1474*/
1475template<typename T> int wordcmp0(T w1, T w2) BMNOEXCEPT
1476{
1477 while (w1 != w2)
1478 {
1479 int res = (w1 & 1) - (w2 & 1);
1480 if (res != 0) return res;
1481 w1 >>= 1;
1482 w2 >>= 1;
1483 }
1484 return 0;
1485}
1486
1487
1488/*
1489template<typename T> int wordcmp(T w1, T w2)
1490{
1491 T diff = w1 ^ w2;
1492 return diff ? ((w1 & diff & (diff ^ (diff - 1)))? 1 : -1) : 0;
1493}
1494*/
1495/*!
1496 \brief Lexicographical comparison of two words as bit strings.
1497 Auxiliary implementation for testing and reference purposes.
1498 \param a - First word.
1499 \param b - Second word.
1500 \return <0 - less, =0 - equal, >0 - greater.
1501
1502 @ingroup bitfunc
1503*/
1504template<typename T> int wordcmp(T a, T b) BMNOEXCEPT
1505{
1506 T diff = a ^ b;
1507 return diff? ( (a & diff & -diff)? 1 : -1 ) : 0;
1508}
1509
1510
1511// Low bit extraction
1512// x & (x ^ (x-1))
1513
1514
1515// ----------------------------------------------------------------------
1516
1517
1518/*! @brief Returns "true" if all bits in the block are 0
1519 @ingroup bitfunc
1520*/
1521inline
1523{
1524#if defined(VECT_IS_ZERO_BLOCK)
1525 return VECT_IS_ZERO_BLOCK(start);
1526#else
1527 const bm::wordop_t* BMRESTRICT blk = (bm::wordop_t*) (start);
1528 const bm::wordop_t* BMRESTRICT blk_end = (bm::wordop_t*)(start + bm::set_block_size);
1529 do
1530 {
1531 if (blk[0] | blk[1] | blk[2] | blk[3])
1532 return false;
1533 blk += 4;
1534 } while (blk < blk_end);
1535 return true;
1536#endif
1537}
1538
1539// ----------------------------------------------------------------------
1540
1541/*!
1542 \brief Checks if GAP block is all-zero.
1543 \param buf - GAP buffer pointer.
1544 \returns true if all-zero.
1545
1546 @ingroup gapfunc
1547*/
1550{
1551 // (almost) branchless variant:
1552 return (!(*buf & 1u)) & (!(bm::gap_max_bits - 1 - buf[1]));
1553}
1554
1555/*!
1556 \brief Checks if GAP block is all-one.
1557 \param buf - GAP buffer pointer.
1558 \returns true if all-one.
1559 @ingroup gapfunc
1560*/
1563{
1564 return ((*buf & 1u) && (buf[1] == bm::gap_max_bits - 1));
1565}
1566
1567/*!
1568 \brief Returs GAP block length.
1569 \param buf - GAP buffer pointer.
1570 \returns GAP block length.
1571
1572 @ingroup gapfunc
1573*/
1576{
1577 return (bm::gap_word_t)((*buf >> 3) + 1);
1578}
1579
1580
1581/*!
1582 \brief Returs GAP block capacity
1583 \param buf - GAP buffer pointer
1584 \param glevel_len - pointer on GAP header word
1585 \returns GAP block capacity.
1586
1587 @ingroup gapfunc
1588*/
1589template<typename T>
1590unsigned
1591gap_capacity(const T* BMRESTRICT buf, const T* BMRESTRICT glevel_len) BMNOEXCEPT
1592{
1593 return glevel_len[(*buf >> 1) & 3];
1594}
1595
1596
1597/*!
1598 \brief Returs GAP block capacity limit.
1599 \param buf - GAP buffer pointer.
1600 \param glevel_len - GAP lengths table (gap_len_table)
1601 \returns GAP block limit.
1602
1603 @ingroup gapfunc
1604*/
1605template<typename T>
1606unsigned
1607gap_limit(const T* BMRESTRICT buf, const T* BMRESTRICT glevel_len) BMNOEXCEPT
1608{
1609 return glevel_len[(*buf >> 1) & 3]-4;
1610}
1611
1612
1613/*!
1614 \brief Returs GAP blocks capacity level.
1615 \param buf - GAP buffer pointer.
1616 \returns GAP block capacity level.
1617
1618 @ingroup gapfunc
1619*/
1620template<typename T>
1622{
1623 return T((*buf >> 1) & 3u);
1624}
1625
1626
1627/*!
1628 \brief GAP block find the last set bit
1629
1630 \param buf - GAP buffer pointer.
1631 \param last - index of the last 1 bit
1632
1633 \return 0 if 1 bit was NOT found
1634
1635 @ingroup gapfunc
1636*/
1637template<typename T>
1638unsigned
1639gap_find_last(const T* BMRESTRICT buf, unsigned* BMRESTRICT last) BMNOEXCEPT
1640{
1641 BM_ASSERT(last);
1642
1643 T is_set = (*buf) & 1u;
1644 T end = T((*buf) >> 3u);
1645
1646 BM_ASSERT(buf[end] == bm::gap_max_bits - 1);
1647
1648 is_set ^= T((end-1) & 1u);
1649 if (is_set)
1650 {
1651 *last = buf[end];
1652 return is_set;
1653 }
1654 *last = buf[--end];
1655 return end;
1656}
1657
1658/*!
1659 \brief GAP block find the first set bit
1660
1661 \param buf - GAP buffer pointer.
1662 \param first - index of the first 1 bit
1663
1664 \return 0 if 1 bit was NOT found
1665
1666 @ingroup gapfunc
1667*/
1668template<typename T>
1669unsigned
1670gap_find_first(const T* BMRESTRICT buf, unsigned* BMRESTRICT first) BMNOEXCEPT
1671{
1672 BM_ASSERT(first);
1673
1674 T is_set = (*buf) & 1u;
1675 if (is_set)
1676 {
1677 *first = 0;
1678 return is_set;
1679 }
1680 if (buf[1] == bm::gap_max_bits - 1)
1681 return 0;
1682 *first = buf[1] + 1;
1683 return 1;
1684}
1685
1686
1687
1688/*
1689 \brief Binary search for the block where bit = pos located.
1690 \param buf - GAP buffer pointer.
1691 \param pos - index of the element.
1692 \param is_set - output. GAP value (0 or 1).
1693 \return GAP index.
1694 @ingroup gapfunc
1695*/
1696template<typename T>
1697unsigned gap_bfind(const T* BMRESTRICT buf,
1698 unsigned pos, unsigned* BMRESTRICT is_set) BMNOEXCEPT
1699{
1701 #undef VECT_GAP_BFIND // TODO: VECTOR bfind causes performance degradation
1702 #ifdef VECT_GAP_BFIND
1703 return VECT_GAP_BFIND(buf, pos, is_set);
1704 #else
1705 *is_set = (*buf) & 1;
1706 unsigned start = 1;
1707 unsigned end = 1 + ((*buf) >> 3);
1708 while (start != end)
1709 {
1710 if ((end - start) < 16) // use direct scan on short span
1711 {
1712 do
1713 {
1714 if (buf[start] >= pos)
1715 goto break2;
1716 } while (++start);
1717 BM_ASSERT(0); // should not get here
1718 break;
1719 }
1720 unsigned curr = (start + end) >> 1;
1721 if ( buf[curr] < pos )
1722 start = curr + 1;
1723 else
1724 end = curr;
1725 } // while
1726 break2:
1727 *is_set ^= ((start-1) & 1);
1728 return start;
1729 #endif
1730}
1731
1732
1733/*!
1734 \brief Tests if bit = pos is true.
1735 \param buf - GAP buffer pointer.
1736 \param pos - index of the element.
1737 \return true if position is in "1" gap
1738 @ingroup gapfunc
1739*/
1740template<typename T>
1741unsigned gap_test(const T* BMRESTRICT buf, unsigned pos) BMNOEXCEPT
1742{
1744
1745 unsigned start = 1;
1746 unsigned end = 1 + ((*buf) >> 3);
1747 if (end - start < 10)
1748 {
1749 unsigned sv = *buf & 1;
1750 unsigned sv1= sv ^ 1;
1751 if (buf[1] >= pos) return sv;
1752 if (buf[2] >= pos) return sv1;
1753 if (buf[3] >= pos) return sv;
1754 if (buf[4] >= pos) return sv1;
1755 if (buf[5] >= pos) return sv;
1756 if (buf[6] >= pos) return sv1;
1757 if (buf[7] >= pos) return sv;
1758 if (buf[8] >= pos) return sv1;
1759 if (buf[9] >= pos) return sv;
1760 BM_ASSERT(0);
1761 }
1762 else
1763 {
1764 while (start != end)
1765 {
1766 unsigned curr = (start + end) >> 1;
1767 if (buf[curr] < pos)
1768 start = curr + 1;
1769 else
1770 end = curr;
1771 }
1772 }
1773 return ((*buf) & 1) ^ ((--start) & 1);
1774}
1775
1776/*!
1777 \brief Tests if bit = pos is true. Analog of bm::gap_test with SIMD unrolling.
1778 \param buf - GAP buffer pointer.
1779 \param pos - index of the element.
1780 \return true if position is in "1" gap
1781 @ingroup gapfunc
1782*/
1783template<typename T>
1784unsigned gap_test_unr(const T* BMRESTRICT buf, const unsigned pos) BMNOEXCEPT
1785{
1787
1788 if (pos == 0) // quick answer possible
1789 {
1790 return (*buf) & 1;
1791 }
1792#if defined(BMSSE2OPT)
1793 unsigned res = bm::sse2_gap_test(buf, pos);
1794 BM_ASSERT(res == bm::gap_test(buf, pos));
1795#elif defined(BMSSE42OPT)
1796 unsigned res = bm::sse42_gap_test(buf, pos);
1797 BM_ASSERT(res == bm::gap_test(buf, pos));
1798#elif defined(BMAVX2OPT)
1799 unsigned res = bm::avx2_gap_test(buf, pos);
1800 BM_ASSERT(res == bm::gap_test(buf, pos));
1801#else
1802 unsigned res = bm::gap_test(buf, pos);
1803#endif
1804 return res;
1805}
1806
1807/*! For each non-zero block in [from, to] executes supplied functor
1808 \internal
1809*/
1810template<typename T, typename N, typename F>
1812 N top_size, N nb_from, N nb_to, F& f) BMNOEXCEPT
1813{
1814 BM_ASSERT(top_size);
1815 if (nb_from > nb_to)
1816 return;
1817 unsigned i_from = unsigned(nb_from >> bm::set_array_shift);
1818 unsigned j_from = unsigned(nb_from & bm::set_array_mask);
1819 unsigned i_to = unsigned(nb_to >> bm::set_array_shift);
1820 unsigned j_to = unsigned(nb_to & bm::set_array_mask);
1821
1822 if (i_from >= top_size)
1823 return;
1824 if (i_to >= top_size)
1825 {
1826 i_to = unsigned(top_size-1);
1827 j_to = bm::set_sub_array_size-1;
1828 }
1829
1830 for (unsigned i = i_from; i <= i_to; ++i)
1831 {
1832 T** blk_blk = root[i];
1833 if (!blk_blk)
1834 continue;
1835 if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
1836 {
1837 unsigned j = (i == i_from) ? j_from : 0;
1838 if (!j && (i != i_to)) // full sub-block
1839 f.add_full(bm::set_sub_total_bits);
1840 else
1841 {
1842 do
1843 {
1844 f.add_full(bm::gap_max_bits);
1845 if ((i == i_to) && (j == j_to))
1846 return;
1847 } while (++j < bm::set_sub_array_size);
1848 }
1849 }
1850 else
1851 {
1852 unsigned j = (i == i_from) ? j_from : 0;
1853 do
1854 {
1855 if (blk_blk[j])
1856 f(blk_blk[j]);
1857 if ((i == i_to) && (j == j_to))
1858 return;
1859 } while (++j < bm::set_sub_array_size);
1860 }
1861 } // for i
1862}
1863
1864/*! For each non-zero block executes supplied function.
1865 \internal
1866*/
1867template<class T, class F>
1868void for_each_nzblock(T*** root, unsigned size1, F& f)
1869{
1870 typedef typename F::size_type size_type;
1871 for (unsigned i = 0; i < size1; ++i)
1872 {
1873 T** blk_blk = root[i];
1874 if (!blk_blk)
1875 {
1876 f.on_empty_top(i);
1877 continue;
1878 }
1879 f.on_non_empty_top(i);
1880 if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
1881 {
1882 size_type r = i * bm::set_sub_array_size;
1883 unsigned j = 0;
1884 do
1885 {
1886 f(FULL_BLOCK_FAKE_ADDR, r + j);
1887 } while (++j < bm::set_sub_array_size);
1888 continue;
1889 }
1890
1891 unsigned non_empty_top = 0;
1892 size_type r = i * bm::set_sub_array_size;
1893 unsigned j = 0;
1894 do
1895 {
1896#if defined(BM64_AVX2) || defined(BM64_AVX512)
1897 if (!avx2_test_all_zero_wave(blk_blk + j))
1898 {
1899 non_empty_top = 1;
1900 T* blk0 = blk_blk[j + 0];
1901 T* blk1 = blk_blk[j + 1];
1902 T* blk2 = blk_blk[j + 2];
1903 T* blk3 = blk_blk[j + 3];
1904
1905 size_type block_idx = r + j + 0;
1906 if (blk0)
1907 f(blk0, block_idx);
1908 else
1909 f.on_empty_block(block_idx);
1910
1911 if (blk1)
1912 f(blk1, block_idx + 1);
1913 else
1914 f.on_empty_block(block_idx + 1);
1915
1916 if (blk2)
1917 f(blk2, block_idx + 2);
1918 else
1919 f.on_empty_block(block_idx + 2);
1920
1921 if (blk3)
1922 f(blk3, block_idx + 3);
1923 else
1924 f.on_empty_block(block_idx + 3);
1925 }
1926 else
1927 {
1928 f.on_empty_block(r + j + 0); f.on_empty_block(r + j + 1);
1929 f.on_empty_block(r + j + 2); f.on_empty_block(r + j + 3);
1930 }
1931 j += 4;
1932#elif defined(BM64_SSE4)
1933 if (!sse42_test_all_zero_wave((blk_blk + j)))
1934 {
1935 non_empty_top = 1;
1936 T* blk0 = blk_blk[j + 0];
1937 T* blk1 = blk_blk[j + 1];
1938
1939 size_type block_idx = r + j + 0;
1940 if (blk0)
1941 f(blk0, block_idx);
1942 else
1943 f.on_empty_block(block_idx);
1944
1945 ++block_idx;
1946 if (blk1)
1947 f(blk1, block_idx);
1948 else
1949 f.on_empty_block(block_idx);
1950 }
1951 else
1952 {
1953 f.on_empty_block(r + j + 0);
1954 f.on_empty_block(r + j + 1);
1955 }
1956 j += 2;
1957#else
1958 if (blk_blk[j])
1959 {
1960 f(blk_blk[j], r + j);
1961 non_empty_top = 1;
1962 }
1963 else
1964 f.on_empty_block(r + j);
1965 ++j;
1966#endif
1967 } while (j < bm::set_sub_array_size);
1968
1969 if (non_empty_top == 0)
1970 f.on_empty_top(i);
1971 } // for i
1972}
1973
1974/*! For each non-zero block executes supplied function.
1975*/
1976template<class T, class F>
1977void for_each_nzblock2(T*** root, unsigned size1, F& f)
1978{
1979#ifdef BM64_SSE4
1980 for (unsigned i = 0; i < size1; ++i)
1981 {
1982 T** blk_blk;
1983 if ((blk_blk = root[i])!=0)
1984 {
1985 if (blk_blk == (T**)FULL_BLOCK_FAKE_ADDR)
1986 {
1987 for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
1988 {
1990 }
1991 continue;
1992 }
1993 {
1994 __m128i w0;
1995 for (unsigned j = 0; j < bm::set_sub_array_size; j+=4)
1996 {
1997 w0 = _mm_loadu_si128((__m128i*)(blk_blk + j));
1998 if (!_mm_testz_si128(w0, w0))
1999 {
2000 T* blk0 = blk_blk[j + 0];
2001 T* blk1 = blk_blk[j + 1];
2002
2003 if (blk0)
2004 f(blk0);
2005 if (blk1)
2006 f(blk1);
2007 }
2008 w0 = _mm_loadu_si128((__m128i*)(blk_blk + j + 2));
2009 if (!_mm_testz_si128(w0, w0))
2010 {
2011 T* blk0 = blk_blk[j + 2];
2012 T* blk1 = blk_blk[j + 3];
2013 if (blk0)
2014 f(blk0);
2015 if (blk1)
2016 f(blk1);
2017 }
2018 } // for j
2019 }
2020 }
2021 } // for i
2022#elif defined(BM64_AVX2) || defined(BM64_AVX512)
2023 for (unsigned i = 0; i < size1; ++i)
2024 {
2025 T** blk_blk;
2026 if ((blk_blk = root[i]) != 0)
2027 {
2028 if (blk_blk == (T**)FULL_BLOCK_FAKE_ADDR)
2029 {
2030 for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
2031 {
2033 }
2034 continue;
2035 }
2036 {
2037 for (unsigned j = 0; j < bm::set_sub_array_size; j += 4)
2038 {
2039 __m256i w0 = _mm256_loadu_si256((__m256i*)(blk_blk + j));
2040 if (!_mm256_testz_si256(w0, w0))
2041 {
2042 // as a variant could use: blk0 = (T*)_mm256_extract_epi64(w0, 0);
2043 // but it measures marginally slower
2044 T* blk0 = blk_blk[j + 0];
2045 T* blk1 = blk_blk[j + 1];
2046 T* blk2 = blk_blk[j + 2];
2047 T* blk3 = blk_blk[j + 3];
2048 if (blk0)
2049 f(blk0);
2050 if (blk1)
2051 f(blk1);
2052 if (blk2)
2053 f(blk2);
2054 if (blk3)
2055 f(blk3);
2056 }
2057 } // for j
2058 }
2059 }
2060 } // for i
2061
2062#else // non-SIMD mode
2063 for (unsigned i = 0; i < size1; ++i)
2064 {
2065 T** blk_blk;
2066 if ((blk_blk = root[i])!=0)
2067 {
2068 if (blk_blk == (T**)FULL_BLOCK_FAKE_ADDR)
2069 {
2070 for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
2071 {
2073 }
2074 continue;
2075 }
2076 unsigned j = 0;
2077 do
2078 {
2079 if (blk_blk[j])
2080 f(blk_blk[j]);
2081 if (blk_blk[j+1])
2082 f(blk_blk[j+1]);
2083 if (blk_blk[j+2])
2084 f(blk_blk[j+2]);
2085 if (blk_blk[j+3])
2086 f(blk_blk[j+3]);
2087 j += 4;
2088 } while (j < bm::set_sub_array_size);
2089 }
2090 } // for i
2091#endif
2092}
2093
2094
2095/*! For each non-zero block executes supplied function-predicate.
2096 Function returns if function-predicate returns true
2097*/
2098template<typename T, typename BI, typename F>
2099bool for_each_nzblock_if(T*** root, BI size1, F& f) BMNOEXCEPT
2100{
2101 BI block_idx = 0;
2102 for (BI i = 0; i < size1; ++i)
2103 {
2104 T** blk_blk = root[i];
2105 if (!blk_blk)
2106 {
2107 block_idx += bm::set_sub_array_size;
2108 continue;
2109 }
2110 if (blk_blk == (T**)FULL_BLOCK_FAKE_ADDR)
2111 {
2112 for (unsigned j = 0; j < bm::set_sub_array_size; ++j, ++block_idx)
2113 {
2114 if (f(FULL_BLOCK_FAKE_ADDR, block_idx))
2115 return true;
2116 } // for j
2117 continue;
2118 }
2119
2120 for (unsigned j = 0;j < bm::set_sub_array_size; ++j, ++block_idx)
2121 {
2122 if (blk_blk[j])
2123 if (f(blk_blk[j], block_idx))
2124 return true;
2125 } // for j
2126 } // for i
2127 return false;
2128}
2129
2130/*! For each block executes supplied function.
2131*/
2132template<class T, class F, typename BLOCK_IDX>
2133void for_each_block(T*** root, unsigned size1, F& f, BLOCK_IDX start)
2134{
2135 BLOCK_IDX block_idx = start;
2136 for (unsigned i = 0; i < size1; ++i)
2137 {
2138 T** blk_blk = root[i];
2139 if (blk_blk)
2140 {
2141 if (blk_blk == (T**)FULL_BLOCK_FAKE_ADDR)
2142 {
2143 for (unsigned j = 0; j < bm::set_sub_array_size; ++j, ++block_idx)
2144 {
2145 f(FULL_BLOCK_FAKE_ADDR, block_idx);
2146 }
2147 continue;
2148 }
2149 for (unsigned j = 0;j < bm::set_sub_array_size; ++j, ++block_idx)
2150 {
2151 f(blk_blk[j], block_idx);
2152 }
2153 }
2154 else
2155 {
2156 for (unsigned j = 0;j < bm::set_sub_array_size; ++j, ++block_idx)
2157 {
2158 f(0, block_idx);
2159 }
2160 }
2161 }
2162}
2163
2164
2165
2166/*! Special BM optimized analog of STL for_each
2167*/
2168template<class T, class F> F bmfor_each(T first, T last, F f)
2169{
2170 do
2171 {
2172 f(*first);
2173 ++first;
2174 } while (first < last);
2175 return f;
2176}
2177
2178/*! Computes SUM of all elements of the sequence
2179*/
2180template<typename T>
2181bm::id64_t sum_arr(const T* first, const T* last) BMNOEXCEPT
2182{
2183 bm::id64_t sum = 0;
2184 for (;first < last; ++first)
2185 sum += *first;
2186 return sum;
2187}
2188
2189/*!
2190 Extract short (len=1) exceptions from the GAP block
2191 \param buf - GAP buffer to split
2192 \param arr0 - [OUT] list of isolates 0 positions (clear list)
2193 \param arr1 - [OUT] list of isolated 1 positions (set list)
2194 \param arr0_cnt - [OUT] arr0 size
2195 \param arr1_cnt -
2196 @ingroup gapfunc
2197*/
2198template<typename T>
2199void gap_split(const T* buf,
2200 T* arr0, T* arr1, T& arr0_cnt, T& arr1_cnt) BMNOEXCEPT
2201{
2202 const T* pcurr = buf;
2203 unsigned len = (*pcurr >> 3);
2204 const T* pend = pcurr + len;
2205
2206 T cnt0, cnt1;
2207 cnt0 = cnt1 = 0;
2208 unsigned is_set = (*buf & 1);
2209
2210 if (*pcurr == 0)
2211 {
2212 if (is_set)
2213 {
2214 arr1[cnt1] = *pcurr;
2215 ++cnt1;
2216 }
2217 else
2218 {
2219 arr0[cnt0] = *pcurr;
2220 ++cnt0;
2221 }
2222 }
2223 T prev = *pcurr;
2224 ++pcurr;
2225
2226 while (pcurr <= pend)
2227 {
2228 is_set ^= 1;
2229 T delta = *pcurr - prev;
2230 if (delta == 1)
2231 {
2232 if (is_set)
2233 {
2234 arr1[cnt1] = prev;
2235 ++cnt1;
2236 }
2237 else
2238 {
2239 arr0[cnt0] = prev;
2240 ++cnt0;
2241 }
2242 }
2243 prev = *pcurr++;
2244 } // while
2245
2246 arr0_cnt = cnt0;
2247 arr1_cnt = cnt1;
2248}
2249
2250
2251/*!
2252 \brief Calculates number of bits ON in GAP buffer.
2253 \param buf - GAP buffer pointer.
2254 \param dsize - buffer size
2255 \return Number of non-zero bits.
2256 @ingroup gapfunc
2257*/
2258template<typename T>
2259unsigned gap_bit_count(const T* buf, unsigned dsize=0) BMNOEXCEPT
2260{
2261 const T* pcurr = buf;
2262 if (dsize == 0)
2263 dsize = (*pcurr >> 3);
2264
2265 const T* pend = pcurr + dsize;
2266
2267 unsigned bits_counter = 0;
2268 ++pcurr;
2269
2270 if (*buf & 1)
2271 {
2272 bits_counter += *pcurr + 1;
2273 ++pcurr;
2274 }
2275 for (++pcurr; pcurr <= pend; pcurr += 2)
2276 bits_counter += *pcurr - *(pcurr-1);
2277 return bits_counter;
2278}
2279
2280/*!
2281 \brief Calculates number of bits ON in GAP buffer. Loop unrolled version.
2282 \param buf - GAP buffer pointer.
2283 \return Number of non-zero bits.
2284 @ingroup gapfunc
2285*/
2286template<typename T>
2287unsigned gap_bit_count_unr(const T* buf) BMNOEXCEPT
2288{
2289 const T* pcurr = buf;
2290 unsigned dsize = (*pcurr >> 3);
2291
2292 unsigned cnt = 0;
2293 pcurr = buf + 1; // set up start position
2294 T first_one = *buf & 1;
2295 if (first_one)
2296 {
2297 cnt += *pcurr + 1;
2298 ++pcurr;
2299 }
2300 ++pcurr; // set GAP to 1
2301
2302 #if defined(BMAVX2OPT) || defined(BMAVX512OPT)
2303 if (dsize > 34)
2304 {
2305 const unsigned unr_factor = 32;
2306 unsigned waves = (dsize-2) / unr_factor;
2307 pcurr = avx2_gap_sum_arr(pcurr, waves, &cnt);
2308 }
2309 #elif defined(BMSSE42OPT) || defined(BMSSE2OPT)
2310 if (dsize > 18)
2311 {
2312 const unsigned unr_factor = 16;
2313 unsigned waves = (dsize - 2) / unr_factor;
2314 pcurr = sse2_gap_sum_arr(pcurr, waves, &cnt);
2315 }
2316 #else
2317 if (dsize > 10)
2318 {
2319 const unsigned unr_factor = 8;
2320 unsigned waves = (dsize - 2) / unr_factor;
2321 for (unsigned i = 0; i < waves; i += unr_factor)
2322 {
2323 cnt += pcurr[0] - pcurr[0 - 1];
2324 cnt += pcurr[2] - pcurr[2 - 1];
2325 cnt += pcurr[4] - pcurr[4 - 1];
2326 cnt += pcurr[6] - pcurr[6 - 1];
2327
2328 pcurr += unr_factor;
2329 } // for
2330 }
2331 #endif
2332
2333 const T* pend = buf + dsize;
2334 for ( ; pcurr <= pend ; pcurr+=2)
2335 cnt += *pcurr - *(pcurr - 1);
2336
2337 BM_ASSERT(cnt == bm::gap_bit_count(buf));
2338 return cnt;
2339}
2340
2341
2342
2343/*!
2344 \brief Counts 1 bits in GAP buffer in the closed [left, right] range.
2345 \param buf - GAP buffer pointer.
2346 \param left - leftmost bit index to start from
2347 \param right - rightmost bit index
2348 \param pos - position in the
2349 \return Number of non-zero bits.
2350 @ingroup gapfunc
2351*/
2352template<typename T, bool RIGHT_END = false>
2353unsigned gap_bit_count_range(const T* const buf,
2354 unsigned left, unsigned right) BMNOEXCEPT
2355{
2356 BM_ASSERT(left <= right);
2357 BM_ASSERT(right < bm::gap_max_bits);
2358
2359 unsigned is_set, bits_counter, prev_gap;
2360 unsigned start_pos = bm::gap_bfind(buf, left, &is_set);
2361 is_set = ~(is_set - 1u); // 0xFFF.. if true (mask for branchless code)
2362
2363 const T* pcurr = buf + start_pos;
2364 if (right <= *pcurr) // we are in the target gap right now
2365 bits_counter = unsigned(right - left + 1u) & is_set;
2366 else
2367 {
2368 bits_counter = unsigned(*pcurr - left + 1u) & is_set;
2369 if constexpr (RIGHT_END) // count to the end
2370 {
2371 BM_ASSERT(right == bm::gap_max_bits-1);
2372 for (prev_gap = *pcurr++ ;true; prev_gap = *pcurr++)
2373 {
2374 bits_counter += (is_set ^= ~0u) & (*pcurr - prev_gap);
2375 if (*pcurr == bm::gap_max_bits-1)
2376 break;
2377 } // for
2378 }
2379 else // true range search here
2380 {
2381 for (prev_gap = *pcurr++; right > *pcurr; prev_gap = *pcurr++)
2382 bits_counter += (is_set ^= ~0u) & (*pcurr - prev_gap);
2383 bits_counter += unsigned(right - prev_gap) & (is_set ^ ~0u);
2384 }
2385 }
2386 return bits_counter;
2387
2388}
2389
2390/*!
2391 \brief Counts 1 bits in GAP buffer in the closed [left, right] range using position hint to avoid bfind
2392 \param buf - GAP buffer pointer.
2393 \param left - leftmost bit index to start from
2394 \param right - rightmost bit index
2395 \param pos - position in the
2396 \param hint - position hint
2397 \return Number of non-zero bits.
2398 @ingroup gapfunc
2399*/
2400template<typename T>
2401unsigned gap_bit_count_range_hint(const T* const buf,
2402 unsigned left, unsigned right, unsigned hint) BMNOEXCEPT
2403{
2404 BM_ASSERT(left <= right);
2405 BM_ASSERT(right < bm::gap_max_bits);
2406
2407 unsigned is_set, bits_counter, prev_gap;
2408
2409 // process the hint instead of binary search
2410 is_set = hint & 1;
2411 is_set = ~(is_set - 1u); // 0xFFF.. if true (mask for branchless code)
2412 unsigned start_pos = hint >> 1;
2413 {
2414 unsigned is_set_c; (void)is_set_c;
2415 unsigned pos; (void)pos;
2416 BM_ASSERT((pos = bm::gap_bfind(buf, left, &is_set_c))==start_pos);
2417 BM_ASSERT(bool(is_set) == bool(is_set_c));
2418 }
2419
2420 const T* pcurr = buf + start_pos;
2421 if (right <= *pcurr) // we are in the target gap right now
2422 bits_counter = unsigned(right - left + 1u) & is_set;
2423 else
2424 {
2425 bits_counter = unsigned(*pcurr - left + 1u) & is_set;
2426 for (prev_gap = *pcurr++; right > *pcurr; prev_gap = *pcurr++)
2427 bits_counter += (is_set ^= ~0u) & (*pcurr - prev_gap);
2428 bits_counter += unsigned(right - prev_gap) & (is_set ^ ~0u);
2429 }
2430 return bits_counter;
2431}
2432
2433
2434/*!
2435 \brief Test if all bits are 1 in GAP buffer in the [left, right] range.
2436 \param buf - GAP buffer pointer.
2437 \param left - leftmost bit index to start from
2438 \param right- rightmost bit index
2439 \return true if all bits are "11111"
2440 @ingroup gapfunc
2441*/
2442template<typename T>
2443bool gap_is_all_one_range(const T* const BMRESTRICT buf,
2444 unsigned left, unsigned right) BMNOEXCEPT
2445{
2446 BM_ASSERT(left <= right);
2447 BM_ASSERT(right < bm::gap_max_bits);
2448
2449 unsigned is_set;
2450 unsigned start_pos = bm::gap_bfind(buf, left, &is_set);
2451 if (!is_set) // GAP is 0
2452 return false;
2453 const T* const pcurr = buf + start_pos;
2454 return (right <= *pcurr);
2455}
2456
2457/*!
2458 \brief Test if any bits are 1 in GAP buffer in the [left, right] range.
2459 \param buf - GAP buffer pointer.
2460 \param left - leftmost bit index to start from
2461 \param right- rightmost bit index
2462 \return true if at least 1 "00010"
2463 @ingroup gapfunc
2464*/
2465template<typename T>
2466bool gap_any_range(const T* const BMRESTRICT buf,
2467 unsigned left, unsigned right) BMNOEXCEPT
2468{
2469 BM_ASSERT(left <= right);
2470 BM_ASSERT(right < bm::gap_max_bits);
2471
2472 unsigned is_set;
2473 unsigned start_pos = bm::gap_bfind(buf, left, &is_set);
2474 const T* const pcurr = buf + start_pos;
2475
2476 if (!is_set) // start GAP is 0 ...
2477 {
2478 if (right <= *pcurr) // ...bit if the interval goes into at least 1 blk
2479 return false; // .. nope
2480 return true;
2481 }
2482 return true;
2483}
2484
2485/*!
2486 \brief Test if any bits are 1 in GAP buffer in the [left, right] range
2487 and flanked with 0s
2488 \param buf - GAP buffer pointer.
2489 \param left - leftmost bit index to start from
2490 \param right- rightmost bit index
2491 \return true if "011110"
2492 @ingroup gapfunc
2493*/
2494template<typename T>
2495bool gap_is_interval(const T* const BMRESTRICT buf,
2496 unsigned left, unsigned right) BMNOEXCEPT
2497{
2498 BM_ASSERT(left <= right);
2499 BM_ASSERT(left > 0); // cannot check left-1 otherwise
2500 BM_ASSERT(right < bm::gap_max_bits-1); // cannot check right+1 otherwise
2501
2502 unsigned is_set;
2503 unsigned start_pos = bm::gap_bfind(buf, left, &is_set);
2504
2505 const T* pcurr = buf + start_pos;
2506 if (!is_set || (right != *pcurr) || (start_pos <= 1))
2507 return false;
2508 --pcurr;
2509 if (*pcurr != left-1)
2510 return false;
2511 return true;
2512}
2513
2514/**
2515 \brief Searches for the last 1 bit in the 111 interval of a GAP block
2516 \param buf - BIT block buffer
2517 \param nbit - bit index to start checking from
2518 \param pos - [out] found value
2519
2520 \return false if not found
2521 @ingroup gapfunc
2522*/
2523template<typename T>
2524bool gap_find_interval_end(const T* const BMRESTRICT buf,
2525 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
2526{
2527 BM_ASSERT(pos);
2529
2530 unsigned is_set;
2531 unsigned start_pos = bm::gap_bfind(buf, nbit, &is_set);
2532 if (!is_set)
2533 return false;
2534 *pos = buf[start_pos];
2535 return true;
2536}
2537
2538
2539/**
2540 \brief Searches for the first 1 bit in the 111 interval of a GAP block
2541 \param buf - GAP block buffer
2542 \param nbit - bit index to start checking from
2543 \param pos - [out] found value
2544
2545 \return false if not found
2546 @ingroup gapfunc
2547*/
2548template<typename T>
2549bool gap_find_interval_start(const T* const BMRESTRICT buf,
2550 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
2551{
2552 BM_ASSERT(pos);
2554
2555 unsigned is_set;
2556 unsigned start_pos = bm::gap_bfind(buf, nbit, &is_set);
2557 if (!is_set)
2558 return false;
2559 --start_pos;
2560 if (!start_pos)
2561 *pos = 0;
2562 else
2563 *pos = buf[start_pos]+1;
2564 return true;
2565}
2566
2567/**
2568 \brief reverse search for the first 1 bit of a GAP block
2569 \param buf - GAP block buffer
2570 \param nbit - bit index to start checking from
2571 \param pos - [out] found value
2572
2573 \return false if not found
2574 @ingroup gapfunc
2575*/
2576template<typename T>
2577bool gap_find_prev(const T* const BMRESTRICT buf,
2578 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
2579{
2580 BM_ASSERT(pos);
2582
2583 unsigned is_set;
2584 unsigned start_pos = bm::gap_bfind(buf, nbit, &is_set);
2585 if (is_set)
2586 {
2587 *pos = nbit;
2588 return true;
2589 }
2590 --start_pos;
2591 if (!start_pos)
2592 return false;
2593 else
2594 *pos = buf[start_pos];
2595 return true;
2596}
2597
2598
2599
2600/*!
2601 \brief GAP block find position for the rank
2602
2603 \param block - bit block buffer pointer
2604 \param rank - rank to find (must be > 0)
2605 \param nbit_from - start bit position in block
2606 \param nbit_pos - found position
2607
2608 \return 0 if position with rank was found, or
2609 the remaining rank (rank - population count)
2610
2611 @ingroup gapfunc
2612*/
2613template<typename T, typename SIZE_TYPE>
2614SIZE_TYPE gap_find_rank(const T* const block,
2615 SIZE_TYPE rank,
2616 unsigned nbit_from,
2617 unsigned& nbit_pos) BMNOEXCEPT
2618{
2619 BM_ASSERT(block);
2620 BM_ASSERT(rank);
2621
2622 const T* pcurr = block;
2623 const T* pend = pcurr + (*pcurr >> 3);
2624
2625 unsigned bits_counter = 0;
2626 unsigned is_set;
2627 unsigned start_pos = bm::gap_bfind(block, nbit_from, &is_set);
2628 is_set = ~(is_set - 1u); // 0xFFF.. if true (mask for branchless code)
2629
2630 pcurr = block + start_pos;
2631 bits_counter += unsigned(*pcurr - nbit_from + 1u) & is_set;
2632 if (bits_counter >= rank) // found!
2633 {
2634 nbit_pos = nbit_from + unsigned(rank) - 1u;
2635 return 0;
2636 }
2637 rank -= bits_counter;
2638 unsigned prev_gap = *pcurr++;
2639 for (is_set ^= ~0u; pcurr <= pend; is_set ^= ~0u)
2640 {
2641 bits_counter = (*pcurr - prev_gap) & is_set;
2642 if (bits_counter >= rank) // found!
2643 {
2644 nbit_pos = prev_gap + unsigned(rank);
2645 return 0;
2646 }
2647 rank -= bits_counter;
2648 prev_gap = *pcurr++;
2649 } // for
2650
2651 return rank;
2652}
2653
2654
2655
2656/*!
2657 \brief Counts 1 bits in GAP buffer in the closed [0, right] range.
2658 \param buf - GAP buffer pointer.
2659 \param right- rightmost bit index
2660 \param is_corrected - if true the result will be rank corrected
2661 if right bit == true count=count-1
2662 \return Number of non-zero bits
2663 @ingroup gapfunc
2664*/
2665/*
2666template<typename T>
2667unsigned gap_bit_count_to(const T* const buf, T right,
2668 bool is_corrected=false) BMNOEXCEPT
2669{
2670 const T* pcurr = buf;
2671 const T* pend = pcurr + (*pcurr >> 3);
2672
2673 unsigned bits_counter = 0;
2674 unsigned is_set = ~((unsigned(*buf) & 1u) - 1u); // 0xFFF.. if true (mask for branchless code)
2675 BM_ASSERT(is_set == 0u || is_set == ~0u);
2676 pcurr = buf + 1;
2677
2678 if (right <= *pcurr) // we are in the target block right now
2679 {
2680 bits_counter = (right + 1u) & is_set; // & is_set == if (is_set)
2681 bits_counter -= (is_set & unsigned(is_corrected));
2682 return bits_counter;
2683 }
2684 bits_counter += (*pcurr + 1u) & is_set;
2685
2686 unsigned prev_gap = *pcurr++;
2687 for (is_set ^= ~0u; right > *pcurr; is_set ^= ~0u)
2688 {
2689 bits_counter += (*pcurr - prev_gap) & is_set;
2690 if (pcurr == pend)
2691 {
2692 bits_counter -= (is_set & unsigned(is_corrected));
2693 return bits_counter;
2694 }
2695 prev_gap = *pcurr++;
2696 }
2697 bits_counter += (right - prev_gap) & is_set;
2698 bits_counter -= (is_set & unsigned(is_corrected));
2699 return bits_counter;
2700}
2701*/
2702template<typename T, bool TCORRECT=false>
2703unsigned gap_bit_count_to(const T* const buf, T right) BMNOEXCEPT
2704{
2705 BM_ASSERT(right < bm::gap_max_bits);
2706
2707 unsigned bits_counter, prev_gap;
2708
2709 unsigned is_set = ~((unsigned(*buf) & 1u) - 1u); // 0xFFF.. if true (mask for branchless code)
2710 const T* pcurr = buf + 1;
2711 if (right <= *pcurr) // we are in the target block right now
2712 {
2713 bits_counter = (right + 1u) & is_set; // & is_set == if (is_set)
2714 }
2715 else
2716 {
2717 bits_counter = (*pcurr + 1u) & is_set;
2718 prev_gap = *pcurr++;
2719 for (is_set ^= ~0u; right > *pcurr; is_set ^= ~0u, prev_gap = *pcurr++)
2720 {
2721 bits_counter += (*pcurr - prev_gap) & is_set;
2722 if (*pcurr == bm::gap_max_bits-1)
2723 goto cret;
2724 }
2725 bits_counter += (right - prev_gap) & is_set;
2726 }
2727
2728 cret:
2729 if constexpr (TCORRECT)
2730 bits_counter -= (is_set & unsigned(TCORRECT));
2731 return bits_counter;
2732}
2733
2734
2735
2736/*!
2737 D-GAP block for_each algorithm
2738
2739 D-Gap Functor is called for each element but last one.
2740
2741 \param gap_buf - GAP buffer
2742 \param func - functor object
2743
2744*/
2745template<class T, class Func>
2746void for_each_dgap(const T* gap_buf, Func& func)
2747{
2748 const T* pcurr = gap_buf;
2749 const T* pend = pcurr + (*pcurr >> 3);
2750 ++pcurr;
2751
2752 T prev = *pcurr;
2753 func((T)(prev + 1)); // first element incremented to avoid 0
2754 ++pcurr;
2755 do
2756 {
2757 func((T)(*pcurr - prev)); // all others are [N] - [N-1]
2758 prev = *pcurr;
2759 } while (++pcurr < pend);
2760}
2761
2762/** d-Gap copy functor
2763 @internal
2764*/
2765template<typename T> struct d_copy_func
2766{
2767 d_copy_func(T* dg_buf) : dgap_buf_(dg_buf) {}
2768 void operator()(T dgap) { *dgap_buf_++ = dgap; }
2769
2771};
2772
2773/*!
2774 \brief Convert GAP buffer into D-GAP buffer
2775
2776 Delta GAP representation is DGAP[N] = GAP[N] - GAP[N-1]
2777
2778 \param gap_buf - GAP buffer
2779 \param dgap_buf - Delta-GAP buffer
2780 \param copy_head - flag to copy GAP header
2781
2782 \internal
2783
2784 @ingroup gapfunc
2785*/
2786template<typename T>
2787T* gap_2_dgap(const T* BMRESTRICT gap_buf,
2788 T* BMRESTRICT dgap_buf, bool copy_head=true) BMNOEXCEPT
2789{
2790 if (copy_head) // copy GAP header
2791 {
2792 *dgap_buf++ = *gap_buf;
2793 }
2794
2795 d_copy_func<T> copy_func(dgap_buf);
2796 for_each_dgap<T, d_copy_func<T> >(gap_buf, copy_func);
2797 return copy_func.dgap_buf_;
2798}
2799
2800/*!
2801 \brief Convert D-GAP buffer into GAP buffer
2802
2803 GAP representation is GAP[N] = DGAP[N] + DGAP[N-1]
2804
2805 \param dgap_buf - Delta-GAP buffer
2806 \param gap_header - GAP header word
2807 \param gap_buf - GAP buffer
2808
2809 \internal
2810 @ingroup gapfunc
2811*/
2812template<typename T>
2813void dgap_2_gap(const T* BMRESTRICT dgap_buf,
2814 T* BMRESTRICT gap_buf, T gap_header=0) BMNOEXCEPT
2815{
2816 const T* pcurr = dgap_buf;
2817 unsigned len;
2818 if (!gap_header) // GAP header is already part of the stream
2819 {
2820 len = *pcurr >> 3;
2821 *gap_buf++ = *pcurr++; // copy GAP header
2822 }
2823 else // GAP header passed as a parameter
2824 {
2825 len = gap_header >> 3;
2826 *gap_buf++ = gap_header; // assign GAP header
2827 }
2828 --len; // last element is actually not encoded
2829 const T* pend = pcurr + len;
2830
2831 *gap_buf = *pcurr++; // copy first element
2832 if (*gap_buf == 0)
2833 *gap_buf = 65535; // fix +1 overflow
2834 else
2835 *gap_buf = T(*gap_buf - 1);
2836
2837 for (++gap_buf; pcurr < pend; ++pcurr)
2838 {
2839 T prev = *(gap_buf-1); // don't remove temp(undef expression!)
2840 *gap_buf++ = T(*pcurr + prev);
2841 }
2842 *gap_buf = 65535; // add missing last element
2843}
2844
2845
2846/*!
2847 \brief Lexicographical comparison of GAP buffers.
2848 \param buf1 - First GAP buffer pointer.
2849 \param buf2 - Second GAP buffer pointer.
2850 \return <0 - less, =0 - equal, >0 - greater.
2851
2852 @ingroup gapfunc
2853*/
2854template<typename T>
2855int gapcmp(const T* buf1, const T* buf2) BMNOEXCEPT
2856{
2857 const T* pcurr1 = buf1;
2858 const T* pend1 = pcurr1 + (*pcurr1 >> 3);
2859 unsigned bitval1 = *buf1 & 1;
2860 ++pcurr1;
2861
2862 const T* pcurr2 = buf2;
2863 unsigned bitval2 = *buf2 & 1;
2864 ++pcurr2;
2865
2866 while (pcurr1 <= pend1)
2867 {
2868 if (*pcurr1 == *pcurr2)
2869 {
2870 if (bitval1 != bitval2)
2871 {
2872 return (bitval1) ? 1 : -1;
2873 }
2874 }
2875 else
2876 {
2877 if (bitval1 == bitval2)
2878 {
2879 if (bitval1)
2880 {
2881 return (*pcurr1 < *pcurr2) ? -1 : 1;
2882 }
2883 else
2884 {
2885 return (*pcurr1 < *pcurr2) ? 1 : -1;
2886 }
2887 }
2888 else
2889 {
2890 return (bitval1) ? 1 : -1;
2891 }
2892 }
2893 ++pcurr1; ++pcurr2;
2894 bitval1 ^= 1;
2895 bitval2 ^= 1;
2896 }
2897
2898 return 0;
2899}
2900
2901/*!
2902 \brief Find first bit which is different between two GAP-blocks
2903 \param buf1 - block 1
2904 \param buf2 - block 2
2905 \param pos - out - position of difference (undefined if blocks are equal)
2906 \return true if difference was found
2907
2908 @ingroup gapfunc
2909*/
2910template<typename T>
2912 const T* BMRESTRICT buf2,
2913 unsigned* BMRESTRICT pos) BMNOEXCEPT
2914{
2915 BM_ASSERT(buf1 && buf2 && pos);
2916
2917 const T* pcurr1 = buf1;
2918 const T* pend1 = pcurr1 + (*pcurr1 >> 3);
2919 const T* pcurr2 = buf2;
2920 for (++pcurr1, ++pcurr2; pcurr1 <= pend1; ++pcurr1, ++pcurr2)
2921 {
2922 if (*pcurr1 != *pcurr2)
2923 {
2924 *pos = 1 + ((*pcurr1 < *pcurr2) ? *pcurr1 : *pcurr2);
2925 return true;
2926 }
2927 } // for
2928 return false;
2929}
2930
2931// -------------------------------------------------------------------------
2932//
2933
2934/*!
2935 \brief Abstract operation for GAP buffers.
2936 Receives functor F as a template argument
2937 \param dest - destination memory buffer.
2938 \param vect1 - operand 1 GAP encoded buffer.
2939 \param vect1_mask - XOR mask for starting bitflag for vector1
2940 can be 0 or 1 (1 inverts the vector)
2941 \param vect2 - operand 2 GAP encoded buffer.
2942 \param vect2_mask - same as vect1_mask
2943 \param dlen - destination length after the operation
2944
2945 \note Internal function.
2946 @internal
2947
2948 @ingroup gapfunc
2949*/
2950template<typename T, class F>
2952 const T* BMRESTRICT vect1,
2953 unsigned vect1_mask,
2954 const T* BMRESTRICT vect2,
2955 unsigned vect2_mask,
2956 unsigned& dlen) BMNOEXCEPT2
2957{
2958 const T* cur1 = vect1;
2959 const T* cur2 = vect2;
2960
2961 T bitval1 = (T)((*cur1++ & 1) ^ vect1_mask);
2962 T bitval2 = (T)((*cur2++ & 1) ^ vect2_mask);
2963
2964 T bitval = (T) F::op(bitval1, bitval2);
2965 T bitval_prev = bitval;
2966
2967 T* res = dest;
2968 *res = bitval;
2969 ++res;
2970
2971 T c1 = *cur1; T c2 = *cur2;
2972 while (1)
2973 {
2974 bitval = (T) F::op(bitval1, bitval2);
2975
2976 // Check if GAP value changes and we need to
2977 // start the next one
2978 //
2979 res += (bitval != bitval_prev);
2980 bitval_prev = bitval;
2981 if (c1 < c2) // (*cur1 < *cur2)
2982 {
2983 *res = c1;
2984 ++cur1; c1 = *cur1;
2985 bitval1 ^= 1;
2986 }
2987 else // >=
2988 {
2989 *res = c2;
2990 if (c2 < c1) // (*cur2 < *cur1)
2991 {
2992 bitval2 ^= 1;
2993 }
2994 else // equal
2995 {
2996 if (c2 == (bm::gap_max_bits - 1))
2997 break;
2998
2999 ++cur1; c1 = *cur1;
3000 bitval1 ^= 1; bitval2 ^= 1;
3001 }
3002 ++cur2; c2 = *cur2;
3003 }
3004 } // while
3005
3006 dlen = (unsigned)(res - dest);
3007 *dest = (T)((*dest & 7) + (dlen << 3));
3008}
3009
3010
3011
3012/*!
3013 \brief Abstract distance test operation for GAP buffers.
3014 Receives functor F as a template argument
3015 \param vect1 - operand 1 GAP encoded buffer.
3016 \param vect1_mask - XOR mask for starting bitflag for vector1
3017 can be 0 or 1 (1 inverts the vector)
3018 \param vect2 - operand 2 GAP encoded buffer.
3019 \param vect2_mask - same as vect1_mask
3020 \note Internal function.
3021 \return non zero value if operation result returns any 1 bit
3022
3023 @ingroup gapfunc
3024*/
3025template<typename T, class F>
3026unsigned gap_buff_any_op(const T* BMRESTRICT vect1,
3027 unsigned vect1_mask,
3028 const T* BMRESTRICT vect2,
3029 unsigned vect2_mask) BMNOEXCEPT2
3030{
3031 const T* cur1 = vect1;
3032 const T* cur2 = vect2;
3033
3034 unsigned bitval1 = (*cur1++ & 1) ^ vect1_mask;
3035 unsigned bitval2 = (*cur2++ & 1) ^ vect2_mask;
3036
3037 unsigned bitval = F::op(bitval1, bitval2);
3038 if (bitval)
3039 return bitval;
3040 unsigned bitval_prev = bitval;
3041
3042 while (1)
3043 {
3044 bitval = F::op(bitval1, bitval2);
3045 if (bitval)
3046 return bitval;
3047
3048 if (bitval != bitval_prev)
3049 bitval_prev = bitval;
3050
3051 if (*cur1 < *cur2)
3052 {
3053 ++cur1;
3054 bitval1 ^= 1;
3055 }
3056 else // >=
3057 {
3058 if (*cur2 < *cur1)
3059 {
3060 bitval2 ^= 1;
3061 }
3062 else // equal
3063 {
3064 if (*cur2 == (bm::gap_max_bits - 1))
3065 {
3066 break;
3067 }
3068 ++cur1;
3069 bitval1 ^= 1; bitval2 ^= 1;
3070 }
3071 ++cur2;
3072 }
3073
3074 } // while
3075
3076 return 0;
3077}
3078
3079
3080
3081/*!
3082 \brief Abstract distance(similarity) operation for GAP buffers.
3083 Receives functor F as a template argument
3084 \param vect1 - operand 1 GAP encoded buffer.
3085 \param vect2 - operand 2 GAP encoded buffer.
3086 \note Internal function.
3087
3088 @ingroup gapfunc
3089*/
3090template<typename T, class F>
3091unsigned gap_buff_count_op(const T* vect1, const T* vect2) BMNOEXCEPT2
3092{
3093 unsigned count;// = 0;
3094 const T* cur1 = vect1;
3095 const T* cur2 = vect2;
3096
3097 unsigned bitval1 = (*cur1++ & 1);
3098 unsigned bitval2 = (*cur2++ & 1);
3099 unsigned bitval = count = F::op(bitval1, bitval2);
3100 unsigned bitval_prev = bitval;
3101
3102 T res, res_prev;
3103 res = res_prev = 0;
3104
3105 while (1)
3106 {
3107 bitval = F::op(bitval1, bitval2);
3108 // Check if GAP value changes and we need to
3109 // start the next one.
3110 if (bitval != bitval_prev)
3111 {
3112 bitval_prev = bitval;
3113 res_prev = res;
3114 }
3115
3116 if (*cur1 < *cur2)
3117 {
3118 res = *cur1;
3119 if (bitval)
3120 {
3121 count += res - res_prev;
3122 res_prev = res;
3123 }
3124 ++cur1; bitval1 ^= 1;
3125 }
3126 else // >=
3127 {
3128 res = *cur2;
3129 if (bitval)
3130 {
3131 count += res - res_prev;
3132 res_prev = res;
3133 }
3134 if (*cur2 < *cur1)
3135 {
3136 bitval2 ^= 1;
3137 }
3138 else // equal
3139 {
3140 if (*cur2 == (bm::gap_max_bits - 1))
3141 break;
3142
3143 ++cur1;
3144 bitval1 ^= 1; bitval2 ^= 1;
3145 }
3146 ++cur2;
3147 }
3148
3149 } // while
3150
3151 return count;
3152}
3153
3154
3155#ifdef __GNUG__
3156#pragma GCC diagnostic push
3157#pragma GCC diagnostic ignored "-Wconversion"
3158#endif
3159
3160/*!
3161 \brief Sets or clears bit in the GAP buffer.
3162
3163 \param val - new bit value
3164 \param buf - GAP buffer.
3165 \param pos - Index of bit to set.
3166 \param is_set - (OUT) flag if bit was actually set.
3167
3168 \return New GAP buffer length.
3169
3170 @ingroup gapfunc
3171*/
3172template<typename T>
3173unsigned gap_set_value(unsigned val,
3174 T* BMRESTRICT buf,
3175 unsigned pos,
3176 unsigned* BMRESTRICT is_set) BMNOEXCEPT
3177{
3179
3180 unsigned curr = bm::gap_bfind(buf, pos, is_set);
3181 T end = (T)(*buf >> 3);
3182 if (*is_set == val)
3183 {
3184 *is_set = 0;
3185 return end;
3186 }
3187 *is_set = 1;
3188
3189 T* pcurr = buf + curr;
3190 T* pprev = pcurr - 1;
3191 T* pend = buf + end;
3192
3193 // Special case, first bit GAP operation. There is no platform beside it.
3194 // initial flag must be inverted.
3195 if (!pos)
3196 {
3197 *buf ^= 1;
3198 if (buf[1]) // We need to insert a 1 bit GAP here
3199 {
3200 ::memmove(&buf[2], &buf[1], (end - 1) * sizeof(gap_word_t));
3201 buf[1] = 0;
3202 ++end;
3203 }
3204 else // Only 1 bit in the GAP. We need to delete the first GAP.
3205 {
3206 pprev = buf + 1; pcurr = pprev + 1;
3207 goto copy_gaps;
3208 }
3209 }
3210 else
3211 if (curr > 1 && ((unsigned)(*pprev))+1 == pos) // Left border bit
3212 {
3213 ++(*pprev);
3214 if (*pprev == *pcurr) // Curr. GAP to be merged with prev.GAP.
3215 {
3216 --end;
3217 if (pcurr != pend) // GAP merge: 2 GAPS to be deleted
3218 {
3219 ++pcurr;
3220 copy_gaps:
3221 --end;
3222 do { *pprev++ = *pcurr++; } while (pcurr < pend);
3223 }
3224 }
3225 }
3226 else
3227 if (*pcurr == pos) // Rightmost bit in the GAP. Border goes left.
3228 {
3229 --(*pcurr);
3230 end += (pcurr == pend);
3231 }
3232 else // Worst case: split current GAP
3233 {
3234 if (*pcurr != bm::gap_max_bits-1) // last gap does not need memmove
3235 ::memmove(pcurr+2, pcurr, (end - curr + 1)*(sizeof(T)));
3236 end += 2;
3237 pcurr[0] = (T)(pos-1);
3238 pcurr[1] = (T)pos;
3239 }
3240
3241 // Set correct length word and last border word
3242 *buf = (T)((*buf & 7) + (end << 3));
3243 buf[end] = bm::gap_max_bits-1;
3244 return end;
3245}
3246
3247
3248
3249
3250
3251/*!
3252 \brief Sets or clears bit in the GAP buffer.
3253
3254 \param val - new bit value
3255 \param buf - GAP buffer.
3256 \param pos - Index of bit to set.
3257
3258 \return New GAP buffer length.
3259
3260 @ingroup gapfunc
3261*/
3262template<typename T>
3263unsigned gap_set_value(unsigned val,
3264 T* BMRESTRICT buf,
3265 unsigned pos) BMNOEXCEPT
3266{
3268 unsigned is_set;
3269 unsigned curr = bm::gap_bfind(buf, pos, &is_set);
3270 T end = (T)(*buf >> 3);
3271 if (is_set == val)
3272 return end;
3273
3274 T* pcurr = buf + curr;
3275 T* pprev = pcurr - 1;
3276 T* pend = buf + end;
3277
3278 // Special case, first bit GAP operation. There is no platform beside it.
3279 // initial flag must be inverted.
3280 if (!pos)
3281 {
3282 *buf ^= 1;
3283 if (buf[1]) // We need to insert a 1 bit GAP here
3284 {
3285 ::memmove(&buf[2], &buf[1], (end - 1) * sizeof(gap_word_t));
3286 buf[1] = 0;
3287 ++end;
3288 }
3289 else // Only 1 bit in the GAP. We need to delete the first GAP.
3290 {
3291 pprev = buf + 1; pcurr = pprev + 1;
3292 goto copy_gaps;
3293 }
3294 }
3295 else
3296 if (curr > 1 && ((unsigned)(*pprev))+1 == pos) // Left border bit
3297 {
3298 ++(*pprev);
3299 if (*pprev == *pcurr) // Curr. GAP to be merged with prev.GAP.
3300 {
3301 --end;
3302 if (pcurr != pend) // GAP merge: 2 GAPS to be deleted
3303 {
3304 ++pcurr;
3305 copy_gaps:
3306 --end;
3307 do { *pprev++ = *pcurr++; } while (pcurr < pend);
3308 }
3309 }
3310 }
3311 else
3312 if (*pcurr == pos) // Rightmost bit in the GAP. Border goes left.
3313 {
3314 --(*pcurr);
3315 end += (pcurr == pend);
3316 }
3317 else // Worst case: split current GAP
3318 {
3319 if (*pcurr != bm::gap_max_bits-1) // last gap does not need memmove
3320 ::memmove(pcurr+2, pcurr, (end - curr + 1)*(sizeof(T)));
3321 end += 2;
3322 pcurr[0] = (T)(pos-1);
3323 pcurr[1] = (T)pos;
3324 }
3325
3326 // Set correct length word and last border word
3327 *buf = (T)((*buf & 7) + (end << 3));
3328 buf[end] = bm::gap_max_bits-1;
3329 return end;
3330}
3331
3332/*!
3333 \brief Add new value to the end of GAP buffer.
3334
3335 \param buf - GAP buffer.
3336 \param pos - Index of bit to set.
3337
3338 \return New GAP buffer length.
3339
3340 @ingroup gapfunc
3341*/
3342template<typename T>
3343unsigned gap_add_value(T* buf, unsigned pos) BMNOEXCEPT
3344{
3346
3347 T end = (T)(*buf >> 3);
3348 T curr = end;
3349 T* pcurr = buf + end;
3350 T* pend = pcurr;
3351 T* pprev = pcurr - 1;
3352
3353 // Special case, first bit GAP operation. There is no platform beside it.
3354 // initial flag must be inverted.
3355 if (!pos)
3356 {
3357 *buf ^= 1;
3358 if ( buf[1] ) // We need to insert a 1 bit platform here.
3359 {
3360 ::memmove(&buf[2], &buf[1], (end - 1) * sizeof(gap_word_t));
3361 buf[1] = 0;
3362 ++end;
3363 }
3364 else // Only 1 bit in the GAP. We need to delete the first GAP.
3365 {
3366 pprev = buf + 1; pcurr = pprev + 1;
3367 --end;
3368 do { *pprev++ = *pcurr++; } while (pcurr < pend);
3369 }
3370 }
3371 else if (((unsigned)(*pprev))+1 == pos && (curr > 1) ) // Left border bit
3372 {
3373 ++(*pprev);
3374 if (*pprev == *pcurr) // Curr. GAP to be merged with prev.GAP.
3375 {
3376 --end;
3377 BM_ASSERT(pcurr == pend);
3378 }
3379 }
3380 else if (*pcurr == pos) // Rightmost bit in the GAP. Border goes left.
3381 {
3382 --(*pcurr);
3383 end += (pcurr == pend);
3384 }
3385 else // Worst case we need to split current block.
3386 {
3387 pcurr[0] = (T)(pos-1);
3388 pcurr[1] = (T)pos;
3389 end = (T)(end+2);
3390 }
3391
3392 // Set correct length word.
3393 *buf = (T)((*buf & 7) + (end << 3));
3394 buf[end] = bm::gap_max_bits - 1;
3395 return end;
3396}
3397
3398#ifdef __GNUG__
3399#pragma GCC diagnostic pop
3400#endif
3401
3402
3403/*!
3404 @brief Right shift GAP block by 1 bit
3405 @param buf - block pointer
3406 @param co_flag - carry over from the previous block
3407 @param new_len - output length of the GAP block after the operation
3408
3409 @return carry over bit (1 or 0)
3410 @ingroup gapfunc
3411*/
3412template<typename T>
3414 unsigned co_flag, unsigned* BMRESTRICT new_len) BMNOEXCEPT
3415{
3416 BM_ASSERT(new_len);
3417 BM_ASSERT(co_flag <= 1);
3418
3419 bool co, gap_set_flag;
3420 unsigned len = (*buf >> 3);
3421 // 1: increment all GAP values by 1
3422 {
3423 unsigned bitval = *buf & 1;
3424 gap_set_flag = (bitval != co_flag);
3425 if (buf[1] == bm::gap_max_bits-1) // full GAP block
3426 co = bitval;
3427 else
3428 {
3429 unsigned i = 1;
3430 for (; i < len; ++i)
3431 {
3432 buf[i]++;
3433 bitval ^= 1;
3434 } // for i
3435 BM_ASSERT(buf[i] == bm::gap_max_bits-1);
3436 if (buf[i-1] == bm::gap_max_bits-1) // last element shifts out
3437 {
3438 // Set correct length word
3439 --len;
3440 *buf = (T)((*buf & 7) + (len << 3));
3441 }
3442 co = bitval;
3443 }
3444 }
3445 // set bit bit 0 with carry-in flag
3446 unsigned is_set;
3447 if (gap_set_flag)
3448 *new_len = bm::gap_set_value(co_flag, buf, 0, &is_set);
3449 else
3450 *new_len = len;
3451
3452 return co;
3453}
3454
3455/*!
3456 @brief isnert bit into GAP compressed block
3457 @param buf - block pointer
3458 @param pos - insert position
3459 @param value - (0 or 1) - value to set
3460 @param new_len - output length of the GAP block after the operation
3461
3462 @return carry over bit (1 or 0)
3463 @ingroup gapfunc
3464*/
3465template<typename T>
3467 unsigned pos, unsigned val, unsigned* BMRESTRICT new_len) BMNOEXCEPT
3468{
3469 BM_ASSERT(new_len);
3470 BM_ASSERT(val <= 1);
3471
3472 bool co, gap_set_flag;
3473 unsigned is_set;
3474 unsigned idx = bm::gap_bfind(buf, pos, &is_set);
3475 BM_ASSERT(is_set <= 1);
3476
3477 gap_set_flag = (val != is_set);
3478 unsigned len = (*buf >> 3);
3479
3480 // 1: increment all GAP values by 1
3481 if (buf[idx] == bm::gap_max_bits-1)
3482 {
3483 co = is_set;
3484 }
3485 else
3486 {
3487 unsigned i = idx;
3488 for (; i < len; ++i)
3489 {
3490 buf[i]++;
3491 is_set ^= 1;
3492 } // for i
3493 BM_ASSERT(buf[i] == bm::gap_max_bits-1);
3494 if (buf[i-1] == bm::gap_max_bits-1) // last element shifts out
3495 {
3496 // Set correct length word
3497 --len;
3498 *buf = (T)((*buf & 7) + (len << 3));
3499 *new_len = len;
3500 }
3501 co = is_set;
3502 }
3503
3504 if (gap_set_flag)
3505 *new_len = bm::gap_set_value(val, buf, pos, &is_set);
3506 else
3507 *new_len = len;
3508
3509 return co;
3510}
3511
3512/*!
3513 @brief Left shift GAP block by 1 bit
3514 @param buf - block pointer
3515 @param co_flag - carry over from the previous block
3516 @param new_len - new length of the block
3517
3518 @return carry over bit (1 or 0)
3519 @ingroup gapfunc
3520*/
3521template<typename T>
3523 unsigned co_flag, unsigned* BMRESTRICT new_len) BMNOEXCEPT
3524{
3525 BM_ASSERT(new_len);
3526 BM_ASSERT(co_flag <= 1);
3527
3528 unsigned is_set;
3529
3530 // 1: decrement all GAP values by 1
3531 //
3532 unsigned bitval = *buf & 1;
3533 bool co0 = bitval;
3534
3535 if (!buf[1]) // cannot decrement (corner case)
3536 {
3537 bitval ^= 1;
3538 *new_len = bm::gap_set_value(bitval, buf, 0, &is_set);
3539
3540 BM_ASSERT(is_set);
3541 BM_ASSERT(buf[1]);
3542 BM_ASSERT(bitval == unsigned(*buf & 1u));
3543
3544 if (*new_len == 1)
3545 {
3546 *new_len = bm::gap_set_value(co_flag, buf,
3547 bm::gap_max_bits-1, &is_set);
3548 return co0;
3549 }
3550 }
3551 if (buf[1] != bm::gap_max_bits-1) // full GAP block
3552 {
3553 BM_ASSERT(buf[1]);
3554 unsigned len = (*buf >> 3);
3555 unsigned i = 1;
3556 for (; i < len; ++i)
3557 {
3558 buf[i]--;
3559 bitval ^= 1;
3560 } // for i
3561 BM_ASSERT(buf[i] == bm::gap_max_bits-1);
3562 }
3563 // 2: set last bit position with carry-in flag
3564 //
3565 *new_len = bm::gap_set_value(co_flag, buf, bm::gap_max_bits-1, &is_set);
3566 return co0;
3567}
3568
3569
3570/*!
3571 \brief Convert array to GAP buffer.
3572
3573 \param buf - GAP buffer.
3574 \param arr - array of values to set
3575 \param len - length of the array
3576
3577 \return New GAP buffer length.
3578
3579 @ingroup gapfunc
3580*/
3581
3582template<typename T>
3583unsigned gap_set_array(T* buf, const T* arr, unsigned len) BMNOEXCEPT
3584{
3585 *buf = (T)((*buf & 6u) + (1u << 3)); // gap header setup
3586
3587 T* pcurr = buf + 1;
3588
3589 unsigned i = 0;
3590 T curr = arr[i];
3591 if (curr != 0) // need to add the first gap: (0 to arr[0]-1)
3592 {
3593 *pcurr = (T)(curr - 1);
3594 ++pcurr;
3595 }
3596 else
3597 {
3598 ++(*buf); // GAP starts with 1
3599 }
3600 T prev = curr;
3601 T acc = prev;
3602
3603 for (i = 1; i < len; ++i)
3604 {
3605 curr = arr[i];
3606 if (curr == prev + 1)
3607 {
3608 ++acc;
3609 prev = curr;
3610 }
3611 else
3612 {
3613 *pcurr++ = acc;
3614 acc = curr;
3615 *pcurr++ = (T)(curr-1);
3616 }
3617 prev = curr;
3618 }
3619 *pcurr = acc;
3620 if (acc != bm::gap_max_bits - 1)
3621 {
3622 ++pcurr;
3623 *pcurr = bm::gap_max_bits - 1;
3624 }
3625
3626 unsigned gap_len = unsigned(pcurr - buf);
3627 BM_ASSERT(gap_len == ((gap_len << 3) >> 3));
3628
3629 *buf = (T)((*buf & 7) + (gap_len << 3));
3630 return gap_len+1;
3631}
3632
3633
3634//------------------------------------------------------------------------
3635
3636/**
3637 \brief Compute number of GAPs in bit-array
3638 \param arr - array of BITs
3639 \param len - array length
3640
3641 @ingroup gapfunc
3642*/
3643template<typename T>
3644unsigned bit_array_compute_gaps(const T* arr, unsigned len) BMNOEXCEPT
3645{
3646 unsigned gap_count = 1;
3647 T prev = arr[0];
3648 if (prev > 0)
3649 ++gap_count;
3650 for (unsigned i = 1; i < len; ++i)
3651 {
3652 T curr = arr[i];
3653 if (curr != prev + 1)
3654 {
3655 gap_count += 2;
3656 }
3657 prev = curr;
3658 }
3659 return gap_count;
3660}
3661
3662
3663//------------------------------------------------------------------------
3664
3665/**
3666 \brief Searches for the next 1 bit in the GAP block
3667 \param buf - GAP buffer
3668 \param nbit - bit index to start checking from.
3669 \param prev - returns previously checked value
3670
3671 \return 0 if not found
3672
3673 @ingroup gapfunc
3674*/
3675template<typename T>
3676unsigned gap_block_find(const T* BMRESTRICT buf,
3677 unsigned nbit,
3679{
3681
3682 unsigned bitval;
3683 unsigned gap_idx = bm::gap_bfind(buf, nbit, &bitval);
3684
3685 if (bitval) // positive block.
3686 {
3687 *prev = nbit;
3688 return 1u;
3689 }
3690 unsigned val = buf[gap_idx] + 1;
3691 *prev = val;
3692 return (val != bm::gap_max_bits); // no bug here.
3693}
3694
3695//------------------------------------------------------------------------
3696
3697
3698/*!
3699 \brief Set 1 bit in a block
3700 @ingroup bitfunc
3701*/
3703void set_bit(unsigned* dest, unsigned bitpos) BMNOEXCEPT
3704{
3705 unsigned nbit = unsigned(bitpos & bm::set_block_mask);
3706 unsigned nword = unsigned(nbit >> bm::set_word_shift);
3707 nbit &= bm::set_word_mask;
3708 dest[nword] |= unsigned(1u << nbit);
3709}
3710
3711/*!
3712 \brief Set 1 bit in a block
3713 @ingroup bitfunc
3714*/
3716void clear_bit(unsigned* dest, unsigned bitpos) BMNOEXCEPT
3717{
3718 unsigned nbit = unsigned(bitpos & bm::set_block_mask);
3719 unsigned nword = unsigned(nbit >> bm::set_word_shift);
3720 nbit &= bm::set_word_mask;
3721 dest[nword] &= ~(unsigned(1u << nbit));
3722}
3723
3724/*!
3725 \brief Test 1 bit in a block
3726
3727 @ingroup bitfunc
3728*/
3730unsigned test_bit(const unsigned* block, unsigned bitpos) BMNOEXCEPT
3731{
3732 unsigned nbit = unsigned(bitpos & bm::set_block_mask);
3733 unsigned nword = unsigned(nbit >> bm::set_word_shift);
3734 nbit &= bm::set_word_mask;
3735 return (block[nword] >> nbit) & 1u;
3736}
3737
3738
3739/*!
3740 \brief Sets bits to 1 in the bitblock.
3741 \param dest - Bitset buffer.
3742 \param bitpos - Offset of the start bit.
3743 \param bitcount - number of bits to set.
3744
3745 @ingroup bitfunc
3746*/
3747inline
3748void or_bit_block(unsigned* dest, unsigned bitpos, unsigned bitcount) BMNOEXCEPT
3749{
3750 const unsigned maskFF = ~0u;
3751
3752 dest += unsigned(bitpos >> bm::set_word_shift); // nword
3753 bitpos &= bm::set_word_mask;
3754
3755 if (bitcount == 1u) // special case (only 1 bit to set)
3756 {
3757 *dest |= (1u << bitpos);
3758 return;
3759 }
3760
3761 if (bitpos) // starting pos is not aligned
3762 {
3763 unsigned mask_r = maskFF << bitpos;
3764 unsigned right_margin = bitpos + bitcount;
3765 if (right_margin < 32)
3766 {
3767 *dest |= (maskFF >> (32 - right_margin)) & mask_r;
3768 return;
3769 }
3770 *dest++ |= mask_r;
3771 bitcount -= 32 - bitpos;
3772 }
3773 for ( ;bitcount >= 64; bitcount-=64, dest+=2)
3774 dest[0] = dest[1] = maskFF;
3775 if (bitcount >= 32)
3776 {
3777 *dest++ = maskFF; bitcount -= 32;
3778 }
3779 if (bitcount)
3780 {
3781 *dest |= maskFF >> (32 - bitcount);
3782 }
3783}
3784
3785
3786/*!
3787 \brief SUB (AND NOT) bit interval to 1 in the bitblock.
3788 \param dest - Bitset buffer.
3789 \param bitpos - Offset of the start bit.
3790 \param bitcount - number of bits to set.
3791
3792 @ingroup bitfunc
3793*/
3794inline
3795void sub_bit_block(unsigned* dest, unsigned bitpos, unsigned bitcount) BMNOEXCEPT
3796{
3797 const unsigned maskFF = ~0u;
3798
3799 dest += unsigned(bitpos >> bm::set_word_shift); // nword
3800 bitpos &= bm::set_word_mask;
3801
3802 if (bitcount == 1u) // special case (only 1 bit to set)
3803 {
3804 *dest &= ~(1u << bitpos);
3805 return;
3806 }
3807
3808 if (bitpos) // starting pos is not aligned
3809 {
3810 unsigned mask_r = maskFF << bitpos;
3811 unsigned right_margin = bitpos + bitcount;
3812 if (right_margin < 32)
3813 {
3814 *dest &= ~((maskFF >> (32 - right_margin)) & mask_r);
3815 return;
3816 }
3817 *dest++ &= ~~mask_r;
3818 bitcount -= 32 - bitpos;
3819 }
3820 for ( ;bitcount >= 64; bitcount-=64, dest+=2)
3821 dest[0] = dest[1] = 0u;
3822 if (bitcount >= 32)
3823 {
3824 *dest++ = 0u; bitcount -= 32;
3825 }
3826 if (bitcount)
3827 {
3828 *dest &= ~(maskFF >> (32 - bitcount));
3829 }
3830}
3831
3832
3833
3834/*!
3835 \brief XOR bit interval to 1 in the bitblock.
3836 \param dest - Bitset buffer.
3837 \param bitpos - Offset of the start bit.
3838 \param bitcount - number of bits to set.
3839
3840 @ingroup bitfunc
3841*/
3842inline void xor_bit_block(unsigned* dest,
3843 unsigned bitpos,
3844 unsigned bitcount) BMNOEXCEPT
3845{
3846 unsigned nbit = unsigned(bitpos & bm::set_block_mask);
3847 unsigned nword = unsigned(nbit >> bm::set_word_shift);
3848 nbit &= bm::set_word_mask;
3849
3850 bm::word_t* word = dest + nword;
3851
3852 if (bitcount == 1) // special case (only 1 bit to set)
3853 {
3854 *word ^= unsigned(1 << nbit);
3855 return;
3856 }
3857
3858 if (nbit) // starting position is not aligned
3859 {
3860 unsigned right_margin = nbit + bitcount;
3861
3862 // here we checking if we setting bits only in the current
3863 // word. Example: 00111000000000000000000000000000 (32 bits word)
3864
3865 if (right_margin < 32)
3866 {
3867 unsigned mask_r = bm::mask_r_u32(nbit);
3868 unsigned mask_l = bm::mask_l_u32(right_margin-1);
3869 unsigned mask = mask_r & mask_l;
3870 *word ^= mask;
3871 return;
3872 }
3873 *word ^= bm::mask_r_u32(nbit);
3874 bitcount -= 32 - nbit;
3875 ++word;
3876 }
3877 for ( ;bitcount >= 64; bitcount-=64, word+=2)
3878 {
3879 word[0] ^= ~0u; word[1] ^= ~0u;
3880 }
3881 if (bitcount >= 32)
3882 {
3883 *word++ ^= ~0u; bitcount -= 32;
3884 }
3885 if (bitcount)
3886 {
3887 *word ^= bm::mask_l_u32(bitcount-1);
3888 }
3889}
3890
3891
3892/*!
3893 \brief SUB (AND NOT) GAP block to bitblock.
3894 \param dest - bitblock buffer pointer.
3895 \param pcurr - GAP buffer pointer.
3896
3897 @ingroup gapfunc
3898*/
3899template<typename T>
3900void gap_sub_to_bitset(unsigned* BMRESTRICT dest,
3901 const T* BMRESTRICT pcurr) BMNOEXCEPT
3902{
3903 BM_ASSERT(dest && pcurr);
3904
3905 const T* pend = pcurr + (*pcurr >> 3);
3906 if (*pcurr & 1) // Starts with 1
3907 {
3908 bm::sub_bit_block(dest, 0, 1 + pcurr[1]);
3909 ++pcurr;
3910 }
3911 for (pcurr += 2; pcurr <= pend; pcurr += 2)
3912 {
3913 BM_ASSERT(*pcurr > pcurr[-1]);
3914 bm::sub_bit_block(dest, 1 + pcurr[-1], *pcurr - pcurr[-1]);
3915 }
3916}
3917
3918
3919/*!
3920 \brief SUB (AND NOT) GAP block to bitblock with digest assist
3921
3922 \param dest - bitblock buffer pointer.
3923 \param pcurr - GAP buffer pointer.
3924 \param digest0 - digest of 0 strides inside bit block
3925
3926 @ingroup gapfunc
3927*/
3928template<typename T>
3929void gap_sub_to_bitset(unsigned* BMRESTRICT dest,
3930 const T* BMRESTRICT pcurr, bm::id64_t digest0) BMNOEXCEPT
3931{
3932 BM_ASSERT(dest && pcurr);
3933
3934 const T* pend = pcurr + (*pcurr >> 3);
3935 if (*pcurr & 1) // Starts with 1
3936 {
3937 bool all_zero = bm::check_zero_digest(digest0, 0, pcurr[1]);
3938 if (!all_zero)
3939 bm::sub_bit_block(dest, 0, pcurr[1] + 1); // (not AND) - SUB [0] gaps
3940 pcurr += 3;
3941 }
3942 else
3943 pcurr += 2;
3944
3945 // wind forward to digest start
3946 {
3947 unsigned tz = bm::count_trailing_zeros_u64(digest0);
3948 unsigned start_pos = tz << set_block_digest_pos_shift;
3949 for (; pcurr <= pend; pcurr += 2) // now we are in GAP "0"
3950 {
3951 if (*pcurr >= start_pos)
3952 break;
3953 }
3954 }
3955
3956 unsigned lz = bm::count_leading_zeros_u64(digest0);
3957 unsigned stop_pos = (64u - lz) << set_block_digest_pos_shift;
3958
3959 unsigned bc, pos;
3960 T prev;
3961 for (; pcurr <= pend; pcurr += 2) // now we are in GAP "1" again
3962 {
3963 BM_ASSERT(*pcurr > *(pcurr-1));
3964 prev = pcurr[-1];
3965 bc = *pcurr - prev;
3966 pos = 1u + prev;
3967
3968 bool all_zero = bm::check_zero_digest(digest0, prev, *pcurr);
3969 if (!all_zero)
3970 bm::sub_bit_block(dest, pos, bc);
3971
3972 if (pos > stop_pos)
3973 break; // early break is possible based on digest tail
3974
3975 } // for
3976}
3977
3978
3979
3980/*!
3981 \brief XOR GAP block to bitblock.
3982 \param dest - bitblock buffer pointer.
3983 \param pcurr - GAP buffer pointer.
3984
3985 @ingroup gapfunc
3986*/
3987template<typename T>
3988void gap_xor_to_bitset(unsigned* BMRESTRICT dest,
3989 const T* BMRESTRICT pcurr) BMNOEXCEPT
3990{
3991 BM_ASSERT(dest && pcurr);
3992
3993 const T* pend = pcurr + (*pcurr >> 3);
3994 if (*pcurr & 1) // Starts with 1
3995 {
3996 bm::xor_bit_block(dest, 0, 1 + pcurr[1]);
3997 ++pcurr;
3998 }
3999 for (pcurr += 2; pcurr <= pend; pcurr += 2)
4000 {
4001 BM_ASSERT(*pcurr > pcurr[-1]);
4002 bm::xor_bit_block(dest, 1 + pcurr[-1], *pcurr - pcurr[-1]);
4003 }
4004}
4005
4006
4007/*!
4008 \brief Adds(OR) GAP block to bitblock.
4009 \param dest - bitblock buffer pointer.
4010 \param pcurr - GAP buffer pointer.
4011 \param len - gap length
4012
4013 @ingroup gapfunc
4014*/
4015template<typename T>
4016void gap_add_to_bitset(unsigned* BMRESTRICT dest,
4017 const T* BMRESTRICT pcurr, unsigned len) BMNOEXCEPT
4018{
4019 BM_ASSERT(dest && pcurr);
4020
4021 const T* pend = pcurr + len;
4022 BM_ASSERT(*pend == 65535);
4023 if (*pcurr & 1) // Starts with 1
4024 {
4025 bm::or_bit_block(dest, 0, 1 + pcurr[1]);
4026 pcurr += 3;
4027 }
4028 else
4029 pcurr += 2;
4030
4031 unsigned bc, pos;
4032 for (; pcurr <= pend; )
4033 {
4034 BM_ASSERT(*pcurr > pcurr[-1]);
4035 pos = 1u + pcurr[-1];
4036 bc = *pcurr - pcurr[-1];
4037 pcurr += 2;
4038 bm::or_bit_block(dest, pos, bc);
4039 }
4040}
4041
4042
4043/*!
4044 \brief Adds(OR) GAP block to bitblock.
4045 \param dest - bitblock buffer pointer.
4046 \param pcurr - GAP buffer pointer.
4047
4048 @ingroup gapfunc
4049*/
4050template<typename T>
4051void gap_add_to_bitset(unsigned* BMRESTRICT dest,
4052 const T* BMRESTRICT pcurr) BMNOEXCEPT
4053{
4054 unsigned len = (*pcurr >> 3);
4055 gap_add_to_bitset(dest, pcurr, len);
4056}
4057
4058
4059/*!
4060 \brief ANDs GAP block to bitblock.
4061 \param dest - bitblock buffer pointer.
4062 \param pcurr - GAP buffer pointer.
4063
4064 @ingroup gapfunc
4065*/
4066template<typename T>
4067void gap_and_to_bitset(unsigned* BMRESTRICT dest,
4068 const T* BMRESTRICT pcurr) BMNOEXCEPT
4069{
4070 BM_ASSERT(dest && pcurr);
4071
4072 const T* pend = pcurr + (*pcurr >> 3);
4073 if (!(*pcurr & 1) ) // Starts with 0
4074 {
4075 bm::sub_bit_block(dest, 0, pcurr[1] + 1); // (not AND) - SUB [0] gaps
4076 pcurr += 3;
4077 }
4078 else
4079 pcurr += 2;
4080
4081 unsigned bc, pos;
4082 for (; pcurr <= pend; ) // now we are in GAP "0" again
4083 {
4084 BM_ASSERT(*pcurr > *(pcurr-1));
4085 pos = 1u + pcurr[-1];
4086 bc = *pcurr - pcurr[-1];
4087 pcurr += 2;
4088 bm::sub_bit_block(dest, pos, bc);
4089 }
4090}
4091
4092
4093/*!
4094 \brief ANDs GAP block to bitblock with digest assist
4095 \param dest - bitblock buffer pointer.
4096 \param pcurr - GAP buffer pointer.
4097 \param digest0 - digest of 0 strides for the destination
4098
4099 @ingroup gapfunc
4100*/
4101template<typename T>
4102void gap_and_to_bitset(unsigned* BMRESTRICT dest,
4103 const T* BMRESTRICT pcurr, bm::id64_t digest0) BMNOEXCEPT
4104{
4105 BM_ASSERT(dest && pcurr);
4106 if (!digest0)
4107 return;
4108
4109 const T* pend = pcurr + (*pcurr >> 3);
4110 if (!(*pcurr & 1) ) // Starts with 0
4111 {
4112 bool all_zero = bm::check_zero_digest(digest0, 0, pcurr[1]);
4113 if (!all_zero)
4114 bm::sub_bit_block(dest, 0, pcurr[1] + 1); // (not AND) - SUB [0] gaps
4115 pcurr += 3;
4116 }
4117 else
4118 pcurr += 2;
4119
4120 // wind forward to digest start
4121 {
4122 unsigned tz = bm::count_trailing_zeros_u64(digest0);
4123 unsigned start_pos = tz << set_block_digest_pos_shift;
4124 for (; pcurr <= pend; pcurr += 2) // now we are in GAP "0"
4125 {
4126 if (*pcurr >= start_pos)
4127 break;
4128 }
4129 }
4130
4131 unsigned lz = bm::count_leading_zeros_u64(digest0);
4132 unsigned stop_pos = (64u - lz) << set_block_digest_pos_shift;
4133
4134 unsigned bc, pos;
4135 T prev;
4136 for (; pcurr <= pend; pcurr += 2) // now we are in GAP "0" again
4137 {
4138 BM_ASSERT(*pcurr > *(pcurr-1));
4139
4140 prev = pcurr[-1];
4141 bc = *pcurr - prev;
4142 pos = 1u + prev;
4143
4144 bool all_zero = bm::check_zero_digest(digest0, prev, *pcurr);
4145 if (!all_zero)
4146 bm::sub_bit_block(dest, pos, bc);
4147
4148 if (pos > stop_pos) // early break is possible based on digest tail
4149 break;
4150
4151 } // for
4152}
4153
4154
4155/*!
4156 \brief Compute bitcount of bit block AND masked by GAP block
4157 \param block - bitblock buffer pointer
4158 \param pcurr - GAP buffer pointer
4159 \return bitcount - cardinality of the AND product
4160
4161 @ingroup gapfunc
4162*/
4163template<typename T>
4165 const T* BMRESTRICT pcurr) BMNOEXCEPT
4166{
4167 BM_ASSERT(block);
4168 const T* pend = pcurr + (*pcurr >> 3);
4169 bm::id_t count = 0;
4170 if (*pcurr & 1) // Starts with 1
4171 {
4172 count += bm::bit_block_calc_count_range(block, 0, pcurr[1]);
4173 ++pcurr;
4174 }
4175 for (pcurr +=2 ;pcurr <= pend; pcurr += 2)
4176 {
4177 count += bm::bit_block_calc_count_range(block, pcurr[-1]+1, *pcurr);
4178 }
4179 return count;
4180}
4181
4182
4183/*!
4184 \brief Bitcount test of bit block AND masked by GAP block.
4185 \param block - bitblock buffer pointer
4186 \param pcurr - GAP buffer pointer
4187 \return non-zero value if AND produces any result
4188
4189 @ingroup gapfunc
4190*/
4191template<typename T>
4193 const T* BMRESTRICT pcurr) BMNOEXCEPT
4194{
4195 BM_ASSERT(block);
4196
4197 const T* pend = pcurr + (*pcurr >> 3);
4198 bm::id_t count = 0;
4199 if (*pcurr & 1) // Starts with 1
4200 {
4201 count = bm::bit_block_any_range(block, 0, pcurr[1]);
4202 ++pcurr;
4203 }
4204 for (pcurr +=2 ;!count && pcurr <= pend; pcurr += 2)
4205 {
4206 count = bm::bit_block_any_range(block, pcurr[-1]+1, *pcurr);
4207 }
4208 return count;
4209}
4210
4211
4212
4213/*!
4214 \brief Compute bitcount of bit block SUB masked by GAP block.
4215 \param block - bitblock buffer pointer.
4216 \param buf - GAP buffer pointer.
4217 \return bit-count result of AND NOT operation
4218
4219 @ingroup gapfunc
4220*/
4221template<typename T>
4223 const T* BMRESTRICT buf) BMNOEXCEPT
4224{
4225 BM_ASSERT(block);
4226
4227 const T* pcurr = buf;
4228 const T* pend = pcurr + (*pcurr >> 3);
4229 ++pcurr;
4230
4231 bm::id_t count = 0;
4232
4233 if (!(*buf & 1)) // Starts with 0
4234 {
4235 count += bit_block_calc_count_range(block, 0, *pcurr);
4236 ++pcurr;
4237 }
4238 ++pcurr; // now we are in GAP "0" again
4239
4240 for (;pcurr <= pend; pcurr+=2)
4241 {
4242 count += bm::bit_block_calc_count_range(block, *(pcurr-1)+1, *pcurr);
4243 }
4244 return count;
4245}
4246
4247
4248/*!
4249 \brief Compute bitcount test of bit block SUB masked by GAP block
4250 \param block - bitblock buffer pointer
4251 \param buf - GAP buffer pointer
4252 \return non-zero value if AND NOT produces any 1 bits
4253
4254 @ingroup gapfunc
4255*/
4256template<typename T>
4258 const T* BMRESTRICT buf) BMNOEXCEPT
4259{
4260 BM_ASSERT(block);
4261
4262 const T* pcurr = buf;
4263 const T* pend = pcurr + (*pcurr >> 3);
4264 ++pcurr;
4265
4266 bm::id_t count = 0;
4267
4268 if (!(*buf & 1)) // Starts with 0
4269 {
4270 count += bit_block_any_range(block, 0, *pcurr);
4271 if (count)
4272 return count;
4273 ++pcurr;
4274 }
4275 ++pcurr; // now we are in GAP "0" again
4276
4277 for (; !count && pcurr <= pend; pcurr+=2)
4278 {
4279 count += bm::bit_block_any_range(block, *(pcurr-1)+1, *pcurr);
4280 }
4281 return count;
4282}
4283
4284
4285
4286/*!
4287 \brief Compute bitcount of bit block XOR masked by GAP block
4288 \param block - bitblock buffer pointer
4289 \param buf - GAP buffer pointer
4290 \return bit count value of XOR operation
4291
4292 @ingroup gapfunc
4293*/
4294template<typename T>
4296 const T* BMRESTRICT buf) BMNOEXCEPT
4297{
4298 BM_ASSERT(block);
4299
4300 const T* pcurr = buf;
4301 const T* pend = pcurr + (*pcurr >> 3);
4302 ++pcurr;
4303
4304 unsigned bitval = *buf & 1;
4305
4306 bm::id_t count = bm::bit_block_calc_count_range(block, 0, *pcurr);
4307 if (bitval)
4308 {
4309 count = *pcurr + 1 - count;
4310 }
4311
4312 for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr)
4313 {
4314 T prev = (T)(*(pcurr-1)+1);
4315 bm::id_t c = bit_block_calc_count_range(block, prev, *pcurr);
4316
4317 if (bitval) // 1 gap; means Result = Total_Bits - BitCount;
4318 c = (*pcurr - prev + 1) - c;
4319 count += c;
4320 }
4321 return count;
4322}
4323
4324/*!
4325 \brief Compute bitcount test of bit block XOR masked by GAP block.
4326 \param block - bitblock buffer pointer
4327 \param buf - GAP buffer pointer
4328 \return non-zero value if XOR returns anything
4329
4330 @ingroup gapfunc
4331*/
4332template<typename T>
4334 const T* BMRESTRICT buf) BMNOEXCEPT
4335{
4336 BM_ASSERT(block);
4337
4338 const T* pcurr = buf;
4339 const T* pend = pcurr + (*pcurr >> 3);
4340 ++pcurr;
4341
4342 unsigned bitval = *buf & 1;
4343
4344 bm::id_t count = bit_block_any_range(block, 0, *pcurr);
4345 if (bitval)
4346 count = *pcurr + 1 - count;
4347
4348 for (bitval^=1, ++pcurr; !count && pcurr <= pend; bitval^=1, ++pcurr)
4349 {
4350 T prev = (T)(*(pcurr-1)+1);
4351 bm::id_t c = bit_block_any_range(block, prev, *pcurr);
4352
4353 if (bitval) // 1 gap; means Result = Total_Bits - BitCount;
4354 c = (*pcurr - prev + 1) - c;
4355 count += c;
4356 }
4357 return count;
4358}
4359
4360
4361
4362/*!
4363 \brief Compute bitcount of bit block OR masked by GAP block.
4364 \param block - bitblock buffer pointer.
4365 \param buf - GAP buffer pointer.
4366 \return bit count of OR
4367
4368 @ingroup gapfunc
4369*/
4370template<typename T>
4372 const T* BMRESTRICT buf) BMNOEXCEPT
4373{
4374 BM_ASSERT(block);
4375 const T* pcurr = buf;
4376 const T* pend = pcurr + (*pcurr >> 3);
4377 ++pcurr;
4378
4379 unsigned bitval = *buf & 1;
4380
4381 bm::id_t count = bitval ? *pcurr + 1
4382 : bm::bit_block_calc_count_range(block, 0, *pcurr);
4383 for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr)
4384 {
4385 T prev = (T)(*(pcurr-1)+1);
4386 bm::id_t c =
4387 bitval ? (*pcurr - prev + 1)
4388 : bm::bit_block_calc_count_range(block, prev, *pcurr);
4389 count += c;
4390 }
4391 return count;
4392}
4393
4394/*!
4395 \brief Compute bitcount test of bit block OR masked by GAP block
4396 \param block - bitblock buffer pointer
4397 \param buf - GAP buffer pointer
4398 \return non zero value if union (OR) returns anything
4399
4400 @ingroup gapfunc
4401*/
4402template<typename T>
4404 const T* BMRESTRICT buf) BMNOEXCEPT
4405{
4406 bool b = !bm::gap_is_all_zero(buf) ||
4407 !bm::bit_is_all_zero(block);
4408 return b;
4409}
4410
4411
4412
4413/*!
4414 \brief Bitblock memset operation.
4415
4416 \param dst - destination block.
4417 \param value - value to set.
4418
4419 @ingroup bitfunc
4420*/
4421inline
4423{
4424#ifdef BMVECTOPT
4425 VECT_SET_BLOCK(dst, value);
4426#else
4427 ::memset(dst, int(value), bm::set_block_size * sizeof(bm::word_t));
4428#endif
4429}
4430
4431
4432/*!
4433 \brief GAP block to bitblock conversion.
4434 \param dest - bitblock buffer pointer.
4435 \param buf - GAP buffer pointer.
4436 \param len - GAP length
4437
4438 @ingroup gapfunc
4439*/
4440template<typename T>
4442 const T* BMRESTRICT buf,
4443 unsigned len=0) BMNOEXCEPT
4444{
4445 bm::bit_block_set(dest, 0);
4446 if (!len)
4447 len = bm::gap_length(buf)-1;
4448 bm::gap_add_to_bitset(dest, buf, len);
4449}
4450
4451
4452
4453/*!
4454 \brief Smart GAP block to bitblock conversion.
4455
4456 Checks if GAP block is ALL-ZERO or ALL-ON. In those cases returns
4457 pointer on special static bitblocks.
4458
4459 \param dest - bitblock buffer pointer.
4460 \param buf - GAP buffer pointer.
4461 \param set_max - max possible bitset length
4462
4463 @ingroup gapfunc
4464*/
4465template<typename T>
4467 const T* BMRESTRICT buf,
4468 id_t set_max) BMNOEXCEPT
4469{
4470 if (buf[1] == set_max - 1)
4471 return (buf[0] & 1) ? FULL_BLOCK_REAL_ADDR : 0;
4472 bm::gap_convert_to_bitset(dest, buf);
4473 return dest;
4474}
4475
4476
4477/*!
4478 \brief Calculates sum of all words in GAP block. (For debugging purposes)
4479 \note For debugging and testing ONLY.
4480 \param buf - GAP buffer pointer.
4481 \return Sum of all words.
4482
4483 @ingroup gapfunc
4484 @internal
4485*/
4486template<typename T>
4487unsigned gap_control_sum(const T* buf) BMNOEXCEPT
4488{
4489 unsigned end = *buf >> 3;
4490
4491 const T* pcurr = buf;
4492 const T* pend = pcurr + (*pcurr >> 3);
4493 ++pcurr;
4494
4495 if (*buf & 1) // Starts with 1
4496 {
4497 ++pcurr;
4498 }
4499 ++pcurr; // now we are in GAP "1" again
4500 while (pcurr <= pend)
4501 {
4502 BM_ASSERT(*pcurr > *(pcurr-1));
4503 pcurr += 2;
4504 }
4505 return buf[end];
4506}
4507
4508
4509/*!
4510 \brief Sets all bits to 0 or 1 (GAP)
4511 \param buf - GAP buffer pointer.
4512 \param set_max - max possible bitset length
4513 \param value - value to set
4514
4515 @ingroup gapfunc
4516*/
4517template<class T>
4518void gap_set_all(T* buf, unsigned set_max, unsigned value) BMNOEXCEPT
4519{
4520 BM_ASSERT(value == 0 || value == 1);
4521 *buf = (T)((*buf & 6u) + (1u << 3) + value);
4522 *(++buf) = (T)(set_max - 1);
4523}
4524
4525
4526/*!
4527 \brief Init gap block so it has block in it (can be whole block)
4528 \param buf - GAP buffer pointer.
4529 \param from - one block start
4530 \param to - one block end
4531 \param value - (block value)1 or 0
4532
4533 @ingroup gapfunc
4534*/
4535template<class T>
4537 T from,
4538 T to,
4539 T value) BMNOEXCEPT
4540{
4541 BM_ASSERT(value == 0 || value == 1);
4542 const unsigned set_max = bm::bits_in_block;
4543
4544 unsigned gap_len;
4545 if (from == 0)
4546 {
4547 if (to == set_max - 1)
4548 {
4549 bm::gap_set_all(buf, set_max, value);
4550 }
4551 else
4552 {
4553 gap_len = 2;
4554 buf[1] = (T)to;
4555 buf[2] = (T)(set_max - 1);
4556 buf[0] = (T)((*buf & 6u) + (gap_len << 3) + value);
4557 }
4558 return;
4559 }
4560 // from != 0
4561
4562 value = !value;
4563 if (to == set_max - 1)
4564 {
4565 gap_len = 2;
4566 buf[1] = (T)(from - 1);
4567 buf[2] = (T)(set_max - 1);
4568 }
4569 else
4570 {
4571 gap_len = 3;
4572 buf[1] = (T) (from - 1);
4573 buf[2] = (T) to;
4574 buf[3] = (T)(set_max - 1);
4575 }
4576 buf[0] = (T)((*buf & 6u) + (gap_len << 3) + value);
4577}
4578
4579
4580/*!
4581 \brief Inverts all bits in the GAP buffer.
4582 \param buf - GAP buffer pointer.
4583
4584 @ingroup gapfunc
4585*/
4586template<typename T> void gap_invert(T* buf) BMNOEXCEPT
4587{
4588 *buf ^= 1;
4589}
4590
4591
4592#ifdef __GNUG__
4593#pragma GCC diagnostic push
4594#pragma GCC diagnostic ignored "-Wconversion"
4595#endif
4596
4597/*!
4598 \brief Sets GAP block capacity level.
4599 \param buf - GAP buffer pointer.
4600 \param level new GAP block capacity level.
4601
4602 @ingroup gapfunc
4603*/
4604template<typename T>
4605void set_gap_level(T* buf, int level) BMNOEXCEPT
4606{
4607 BM_ASSERT(level >= 0);
4608 BM_ASSERT(unsigned(level) < bm::gap_levels);
4609
4610 *buf = (T)(((level & 3) << 1) | (*buf & 1) | (*buf & ~7));
4611}
4612#ifdef __GNUG__
4613#pragma GCC diagnostic pop
4614#endif
4615
4616
4617
4618/*!
4619 \brief Calculates GAP block capacity level.
4620 \param len - GAP buffer length.
4621 \param glevel_len - GAP lengths table
4622 \return GAP block capacity level.
4623 -1 if block does not fit any level.
4624 @ingroup gapfunc
4625*/
4626template<typename T>
4627int gap_calc_level(unsigned len, const T* glevel_len) BMNOEXCEPT
4628{
4629 if (len <= unsigned(glevel_len[0]-4)) return 0;
4630 if (len <= unsigned(glevel_len[1]-4)) return 1;
4631 if (len <= unsigned(glevel_len[2]-4)) return 2;
4632 if (len <= unsigned(glevel_len[3]-4)) return 3;
4633
4635 return -1;
4636}
4637
4638/*! @brief Returns number of free elements in GAP block array.
4639 Difference between GAP block capacity on this level and actual GAP length.
4640
4641 @param buf - GAP buffer pointer
4642 @param glevel_len - GAP lengths table
4643
4644 @return Number of free GAP elements
4645 @ingroup gapfunc
4646*/
4647template<typename T>
4648inline unsigned gap_free_elements(const T* BMRESTRICT buf,
4649 const T* BMRESTRICT glevel_len) BMNOEXCEPT
4650{
4651 unsigned len = bm::gap_length(buf);
4652 unsigned capacity = bm::gap_capacity(buf, glevel_len);
4653 return capacity - len;
4654}
4655
4656/*!
4657 \brief Lexicographical comparison of BIT buffers.
4658 \param buf1 - First buffer pointer.
4659 \param buf2 - Second buffer pointer.
4660 \param len - Buffer length in elements (T).
4661 \return <0 - less, =0 - equal, >0 - greater.
4662
4663 @ingroup bitfunc
4664*/
4665template<typename T>
4666int bitcmp(const T* buf1, const T* buf2, unsigned len) BMNOEXCEPT
4667{
4668 BM_ASSERT(len);
4669 const T* pend1 = buf1 + len;
4670 do
4671 {
4672 T w1 = *buf1++;
4673 T w2 = *buf2++;
4674 T diff = w1 ^ w2;
4675 if (diff)
4676 return (w1 & diff & -diff) ? 1 : -1;
4677 } while (buf1 < pend1);
4678 return 0;
4679}
4680
4681/*!
4682 \brief Find first bit which is different between two bit-blocks
4683 \param blk1 - block 1
4684 \param blk2 - block 2
4685 \param pos - out - position of difference (undefined if blocks are equal)
4686 \return true if difference was found
4687
4688 @ingroup bitfunc
4689*/
4690inline
4692 const bm::word_t* BMRESTRICT blk2,
4693 unsigned* BMRESTRICT pos) BMNOEXCEPT
4694{
4695 BM_ASSERT(blk1 && blk2 && pos);
4696#ifdef VECT_BIT_FIND_DIFF
4697 bool f = VECT_BIT_FIND_DIFF(blk1, blk2, pos);
4698 return f;
4699#else
4700 #ifdef BM64OPT
4701 BM_ASSERT(sizeof(bm::wordop_t) == 8);
4702
4704 (const bm::bit_block_t::bunion_t*)(blk1);
4706 (const bm::bit_block_t::bunion_t*)(blk2);
4707
4708 for (unsigned i = 0; i < bm::set_block_size/2; ++i)
4709 {
4710 bm::wordop_t w1 = b1_u->w64[i];
4711 bm::wordop_t w2 = b2_u->w64[i];
4712 bm::wordop_t diff = w1 ^ w2;
4713 if (diff)
4714 {
4715 unsigned idx = bm::count_trailing_zeros_u64(diff);
4716 *pos = unsigned(idx + (i * 8u * unsigned(sizeof(bm::wordop_t))));
4717 return true;
4718 }
4719 } // for
4720 #else
4721 for (unsigned i = 0; i < bm::set_block_size; ++i)
4722 {
4723 bm::word_t w1 = blk1[i]; bm::word_t w2 = blk2[i];
4724 bm::word_t diff = w1 ^ w2;
4725 if (diff)
4726 {
4727 unsigned idx = bm::bit_scan_forward32(diff); // trailing zeros
4728 *pos = unsigned(idx + (i * 8u * sizeof(bm::word_t)));
4729 return true;
4730 }
4731 } // for
4732 #endif
4733 return false;
4734#endif
4735}
4736
4737
4738//#ifndef BMAVX2OPT
4739
4740/*!
4741 \brief Converts bit block to GAP.
4742 \param dest - Destinatio GAP buffer.
4743 \param block - Source bitblock buffer.
4744 \param dest_len - length of the destination buffer.
4745 \return New length of GAP block or 0 if conversion failed
4746 (insufficicent space).
4747
4748 @ingroup gapfunc
4749*/
4750inline
4752 const unsigned* BMRESTRICT block,
4753 unsigned dest_len) BMNOEXCEPT
4754{
4755 const unsigned* BMRESTRICT block_end = block + bm::set_block_size;
4756 gap_word_t* BMRESTRICT pcurr = dest;
4757 gap_word_t* BMRESTRICT end = dest + dest_len; (void)end;
4758
4759 unsigned bitval = (*block) & 1u;
4760 *pcurr++ = bm::gap_word_t(bitval);
4761 *pcurr = 0;
4762 unsigned bit_idx = 0;
4763
4764 do
4765 {
4766 unsigned val = *block;
4767 while (!val || val == ~0u)
4768 {
4769 if (bitval != unsigned(bool(val)))
4770 {
4771 *pcurr++ = (gap_word_t)(bit_idx-1);
4772 bitval ^= 1u;
4773 BM_ASSERT((pcurr-1) == (dest+1) || *(pcurr-1) > *(pcurr-2));
4774 BM_ASSERT(pcurr != end);
4775 }
4776 bit_idx += unsigned(sizeof(*block) * 8);
4777 if (++block >= block_end)
4778 goto complete;
4779 val = *block;
4780 } // while
4781
4782 // process "0100011" word
4783 //
4784 unsigned bits_consumed = 0;
4785 do
4786 {
4787 unsigned tz = 1u;
4788 if (bitval != (val & 1u))
4789 {
4790 *pcurr++ = (gap_word_t)(bit_idx-1);
4791 bitval ^= 1u;
4792 BM_ASSERT((pcurr-1) == (dest+1) || *(pcurr-1) > *(pcurr-2));
4793 BM_ASSERT(pcurr != end);
4794 }
4795 else // match, find the next idx
4796 {
4797 tz = bm::bit_scan_forward32(bitval ? ~val : val);
4798 // possible alternative:
4799 // tz = bm::count_trailing_zeros(bitval ? ~val : val);
4800 }
4801
4802 bits_consumed += tz;
4803 bit_idx += tz;
4804 val >>= tz;
4805
4806 if (!val)
4807 {
4808 if (bits_consumed < 32u)
4809 {
4810 *pcurr++ = (gap_word_t)(bit_idx-1);
4811 bitval ^= 1u;
4812 bit_idx += 32u - bits_consumed;
4813 BM_ASSERT((pcurr-1) == (dest+1) || *(pcurr-1) > *(pcurr-2));
4814 BM_ASSERT(pcurr != end);
4815 }
4816 break;
4817 }
4818 } while (1);
4819
4820 } while(++block < block_end);
4821
4822complete:
4823 *pcurr = (gap_word_t)(bit_idx-1);
4824 unsigned len = (unsigned)(pcurr - dest);
4825 *dest = (gap_word_t)((*dest & 7) + (len << 3));
4826 return len;
4827}
4828//#endif
4829
4830/**
4831 Convert bit block to GAP representation
4832 @internal
4833 @ingroup bitfunc
4834*/
4835inline
4837 const unsigned* BMRESTRICT block,
4838 unsigned dest_len) BMNOEXCEPT
4839{
4840#if defined(VECT_BIT_TO_GAP)
4841 return VECT_BIT_TO_GAP(dest, block, dest_len);
4842#else
4843 return bm::bit_block_to_gap(dest, block, dest_len);
4844#endif
4845}
4846
4847
4848/*!
4849 \brief Iterate gap block as delta-bits with a functor
4850 @ingroup gapfunc
4851*/
4852template<class T, class F>
4853void for_each_gap_dbit(const T* buf, F& func)
4854{
4855 const T* pcurr = buf;
4856 const T* pend = pcurr + (*pcurr >> 3);
4857
4858 ++pcurr;
4859
4860 unsigned prev = 0;
4861 unsigned first_inc;
4862
4863 if (*buf & 1)
4864 {
4865 first_inc = 0;
4866 unsigned to = *pcurr;
4867 for (unsigned i = 0; i <= to; ++i)
4868 {
4869 func(1);
4870 }
4871 prev = to;
4872 ++pcurr;
4873 }
4874 else
4875 {
4876 first_inc = 1;
4877 }
4878 ++pcurr; // set GAP to 1
4879
4880 while (pcurr <= pend)
4881 {
4882 unsigned from = *(pcurr-1)+1;
4883 unsigned to = *pcurr;
4884 if (first_inc)
4885 {
4886 func(from - prev + first_inc);
4887 first_inc = 0;
4888 }
4889 else
4890 {
4891 func(from - prev);
4892 }
4893
4894 for (unsigned i = from+1; i <= to; ++i)
4895 {
4896 func(1);
4897 }
4898 prev = to;
4899 pcurr += 2; // jump to the next positive GAP
4900 }
4901}
4902
4903/*!
4904 \brief Convert gap block into array of ints corresponding to 1 bits
4905 @ingroup gapfunc
4906*/
4907template<typename D, typename T>
4909 const T* BMRESTRICT buf,
4910 unsigned dest_len,
4911 bool invert = false) BMNOEXCEPT
4912{
4913 const T* BMRESTRICT pcurr = buf;
4914 const T* pend = pcurr + (*pcurr >> 3);
4915
4916 D* BMRESTRICT dest_curr = dest;
4917 ++pcurr;
4918
4919 int bitval = (*buf) & 1;
4920 if (invert)
4921 bitval = !bitval; // invert the GAP buffer
4922
4923 if (bitval)
4924 {
4925 if (unsigned(*pcurr + 1) >= dest_len)
4926 return 0; // insufficient space
4927 dest_len -= *pcurr;
4928 T to = *pcurr;
4929 for (T i = 0; ;++i)
4930 {
4931 *dest_curr++ = i;
4932 if (i == to) break;
4933 }
4934 ++pcurr;
4935 }
4936 ++pcurr; // set GAP to 1
4937
4938 while (pcurr <= pend)
4939 {
4940 unsigned pending = *pcurr - *(pcurr-1);
4941 if (pending >= dest_len)
4942 return 0;
4943 dest_len -= pending;
4944 T from = (T)(*(pcurr-1)+1);
4945 T to = *pcurr;
4946 for (T i = from; ;++i)
4947 {
4948 *dest_curr++ = i;
4949 if (i == to) break;
4950 }
4951 pcurr += 2; // jump to the next positive GAP
4952 }
4953 return (D) (dest_curr - dest);
4954}
4955
4956
4957/*!
4958 @brief Bitcount for bit block without agressive unrolling
4959 @ingroup bitfunc
4960*/
4963 const bm::word_t* BMRESTRICT block_end) BMNOEXCEPT
4964{
4965 unsigned count = 0;
4966#ifdef BM64OPT__
4967 do
4968 {
4970 (const bm::bit_block_t::bunion_t*)(block);
4971
4972 bm::id64_t x = src_u->w64[0]; bm::id64_t y = src_u->w64[1];
4973 bm::id64_t u = src_u->w64[2]; bm::id64_t v = src_u->w64[3];
4974
4975 #if defined(BM_USE_GCC_BUILD)
4976 count += unsigned(__builtin_popcountll(x) + __builtin_popcountll(y)
4977 + __builtin_popcountll(u) + __builtin_popcountll(v));
4978 #else
4979 // 64-bit optimized algorithm. No sparse vect opt
4980 // instead it uses 4-way parallel pipelined version
4981 if (x | y | u | v)
4982 {
4983 unsigned c = bitcount64_4way(x, y, u, v);
4984 BM_ASSERT(c);
4985 count += c;
4986 }
4987 #endif
4988 block += 8;
4989 } while (block < block_end);
4990#else
4991 do
4992 {
4993 unsigned c1= bm::word_bitcount(*block);
4994 unsigned c2 = bm::word_bitcount(block[1]);
4995 count += c1 + c2;
4996 c1= bm::word_bitcount(block[2]);
4997 c2 = bm::word_bitcount(block[3]);
4998 count += c1 + c2;
4999 block+=4;
5000 } while (block < block_end);
5001
5002#endif
5003 return count;
5004}
5005
5006
5007
5008/*!
5009 @brief Bitcount for bit block
5010
5011 Function calculates number of 1 bits in the given array of words.
5012 Make sure the addresses are aligned.
5013
5014 @ingroup bitfunc
5015*/
5016inline
5018{
5019 const bm::word_t* block_end = block + bm::set_block_size;
5020#ifdef BMVECTOPT
5021 return VECT_BITCOUNT(block, block_end);
5022#else
5023 return bm::bit_count_min_unroll(block, block_end);
5024#endif
5025}
5026
5027/*!
5028 @brief Bitcount for bit block
5029
5030 Function calculates number of 1 bits in the given array of words.
5031 uses digest to understand zero areas
5032
5033 @ingroup bitfunc
5034*/
5035inline
5037 bm::id64_t digest) BMNOEXCEPT
5038{
5039#ifdef VECT_BIT_COUNT_DIGEST
5040 return VECT_BIT_COUNT_DIGEST(block, digest);
5041#else
5042 bm::id_t count = 0;
5043 bm::id64_t d = digest;
5044
5045 // TODO: use platform neutral bitscan to decode digest here
5046
5047 while (d)
5048 {
5049 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
5050
5051 unsigned wave = bm::word_bitcount64(t - 1);
5052 unsigned off = wave * bm::set_block_digest_wave_size;
5053
5054#ifdef BM64OPT
5056 (const bm::bit_block_t::bunion_t*)(&block[off]);
5057 unsigned j = 0;
5058 do
5059 {
5060 bm::id64_t x = src_u->w64[0+j]; bm::id64_t y = src_u->w64[1+j];
5061 bm::id64_t u = src_u->w64[2+j]; bm::id64_t v = src_u->w64[3+j];
5062 #if defined(BM_USE_GCC_BUILD)
5063 count += unsigned(__builtin_popcountll(x) + __builtin_popcountll(y)
5064 + __builtin_popcountll(u) + __builtin_popcountll(v));
5065 #else
5066 // 64-bit optimized algorithm. No sparse vect opt
5067 // instead it uses 4-way parallel pipelined version
5068 if (x | y | u | v)
5069 {
5070 unsigned c = bm::bitcount64_4way(x, y, u, v);
5071 BM_ASSERT(c);
5072 count += c;
5073 }
5074 #endif
5075 j += 4;
5076 } while (j < bm::set_block_digest_wave_size/2);
5077#else // 32-bit version
5078 const bm::word_t* BMRESTRICT blk = &block[off];
5079 const bm::word_t* BMRESTRICT blk_end = &block[off+bm::set_block_digest_wave_size];
5080 do
5081 {
5082 unsigned c1= bm::word_bitcount(*blk);
5083 unsigned c2 = bm::word_bitcount(blk[1]);
5084 count += c1 + c2;
5085 c1= bm::word_bitcount(blk[2]);
5086 c2 = bm::word_bitcount(blk[3]);
5087 count += c1 + c2;
5088 blk+=4;
5089 } while (blk < blk_end);
5090#endif
5091
5092 d = bm::bmi_bslr_u64(d); // d &= d - 1;
5093 } // while
5094 return count;
5095#endif
5096}
5097
5098
5099/*!
5100 Function calculates number of times when bit value changed
5101 (1-0 or 0-1).
5102
5103 For 001 result is 2
5104 010 - 3
5105 011 - 2
5106 111 - 1
5107
5108 @ingroup bitfunc
5109*/
5110inline
5112{
5113 unsigned count = 1;
5114 w ^= (w >> 1);
5115
5116 count += bm::word_bitcount(w);
5117 count -= (w >> ((sizeof(w) * 8) - 1));
5118 return count;
5119}
5120
5121
5122/*!
5123 Function calculates number of times when bit value changed
5124 @internal
5125*/
5126inline
5128 unsigned size) BMNOEXCEPT
5129{
5130 unsigned gap_count = 1;
5131
5132 bm::word_t w, w0, w_prev, w_l;
5133 w = w0 = *block;
5134
5135 const int w_shift = int(sizeof(w) * 8 - 1);
5136 w ^= (w >> 1);
5137 gap_count += bm::word_bitcount(w);
5138 gap_count -= (w_prev = (w0 >> w_shift)); // negative value correction
5139
5140 const bm::word_t* block_end = block + size;
5141 for (++block; block < block_end; ++block)
5142 {
5143 w = w0 = *block;
5144 ++gap_count;
5145 if (!w)
5146 {
5147 gap_count -= !w_prev;
5148 w_prev = 0;
5149 }
5150 else
5151 {
5152 w ^= (w >> 1);
5153 gap_count += bm::word_bitcount(w);
5154 w_l = w0 & 1;
5155 gap_count -= (w0 >> w_shift); // negative value correction
5156 gap_count -= !(w_prev ^ w_l); // word border correction
5157
5158 w_prev = (w0 >> w_shift);
5159 }
5160 } // for
5161 return gap_count;
5162}
5163
5164/*!
5165 Function calculates number of times when bit value changed
5166 @internal
5167*/
5168inline
5170 unsigned size) BMNOEXCEPT
5171{
5172 unsigned gap_count = 1;
5173 const bm::id64_t* BMRESTRICT block = (const bm::id64_t*) in_block;
5174
5175 bm::id64_t w, w0, w_prev, w_l;
5176 w = w0 = *block;
5177
5178 const int w_shift = int(sizeof(w) * 8 - 1);
5179 w ^= (w >> 1);
5180 gap_count += bm::word_bitcount64(w);
5181 gap_count -= unsigned(w_prev = (w0 >> w_shift)); // negative value correction
5182
5183 const bm::id64_t* block_end = block + (size/2);
5184 for (++block; block < block_end; ++block)
5185 {
5186 w = w0 = *block;
5187 ++gap_count;
5188 if (!w)
5189 {
5190 gap_count -= !w_prev;
5191 w_prev = 0;
5192 }
5193 else
5194 {
5195 w ^= (w >> 1);
5196 gap_count += bm::word_bitcount64(w);
5197 w_l = w0 & 1;
5198 gap_count -= unsigned(w0 >> w_shift); // negative value correction
5199 gap_count -= !(w_prev ^ w_l); // word border correction
5200 w_prev = (w0 >> w_shift);
5201 }
5202 } // for
5203 return gap_count;
5204}
5205
5206
5207
5208/*!
5209 Function calculates basic bit-block statistics
5210 number of times when bit value changed (GAPS)
5211 and population count
5212 @param block - bit-block pointer
5213 @param gc - [output] gap_count
5214 @param bc - [output] bit count
5215 @internal
5216*/
5217inline
5219 unsigned* BMRESTRICT gc, unsigned* BMRESTRICT bc) BMNOEXCEPT
5220{
5221 BM_ASSERT(gc);
5222 BM_ASSERT(bc);
5223
5224 #ifdef VECT_BLOCK_CHANGE_BC
5225 VECT_BLOCK_CHANGE_BC(block, gc, bc);
5226 #else
5227 // TODO: one pass algo
5228 #ifdef BM64OPT
5230 #else
5232 #endif
5233 *bc = bm::bit_block_count(block);
5234 #endif
5235}
5236
5237
5238
5239/*!
5240 Function calculates number of times when bit value changed
5241 (1-0 or 0-1) in the bit block.
5242
5243 @param block - bit-block start pointer
5244 @return number of 1-0, 0-1 transitions
5245
5246 @ingroup bitfunc
5247*/
5248inline
5250{
5251#if defined(VECT_BLOCK_CHANGE)
5253#else
5254 #ifdef BM64OPT
5256 #else
5258 #endif
5259#endif
5260}
5261
5262/*!
5263 Check if all bits are 1 in [left, right] range
5264 @ingroup bitfunc
5265*/
5266inline
5268 bm::word_t left,
5269 bm::word_t right) BMNOEXCEPT
5270{
5271 BM_ASSERT(left <= right);
5272 BM_ASSERT(right <= bm::gap_max_bits-1);
5273
5274 unsigned nword, nbit, bitcount, temp;
5275 nbit = left & bm::set_word_mask;
5276 const bm::word_t* word =
5277 block + (nword = unsigned(left >> bm::set_word_shift));
5278 if (left == right) // special case (only 1 bit to check)
5279 return (*word >> nbit) & 1u;
5280
5281 if (nbit) // starting position is not aligned
5282 {
5283 unsigned right_margin = nbit + right - left;
5284 if (right_margin < 32)
5285 {
5286 unsigned mask_r = bm::mask_r_u32(nbit);
5287 unsigned mask_l = bm::mask_l_u32(right_margin);
5288 unsigned mask = mask_r & mask_l;
5289 return mask == (*word & mask);
5290 }
5291
5292 unsigned mask_r = bm::mask_r_u32(nbit);
5293 temp = *word & mask_r;
5294 if (temp != mask_r)
5295 return false;
5296 bitcount = (right - left + 1u) - (32 - nbit);
5297 ++word;
5298 }
5299 else
5300 {
5301 bitcount = right - left + 1u;
5302 }
5303
5304 const bm::word_t maskFF = ~0u;
5305 // loop unrolled to evaluate 4 words at a time
5306 // SIMD showed no advantage, unless evaluate sub-wave intervals
5307 //
5308 #if defined(BM64OPT) || defined(BM64_SSE4) || defined(BMAVX2OPT) || defined(BMAVX512OPT)
5309 const bm::id64_t maskFF64 = ~0ull;
5310 for ( ;bitcount >= 128; bitcount-=128, word+=4)
5311 {
5312 bm::id64_t w64_0 = bm::id64_t(word[0]) + (bm::id64_t(word[1]) << 32);
5313 bm::id64_t w64_1 = bm::id64_t(word[2]) + (bm::id64_t(word[3]) << 32);
5314 if ((w64_0 ^ maskFF64) | (w64_1 ^ maskFF64))
5315 return false;
5316 } // for
5317 #else
5318 for ( ;bitcount >= 128; bitcount-=128, word+=4)
5319 {
5320 bm::word_t m = (word[0] != maskFF) || (word[1] != maskFF) |
5321 (word[2] != maskFF) || (word[3] != maskFF);
5322 if (m)
5323 return false;
5324 } // for
5325 #endif
5326
5327 for ( ;bitcount >= 32; bitcount-=32, ++word)
5328 {
5329 if (*word != maskFF)
5330 return false;
5331 } // for
5332 BM_ASSERT(bitcount < 32);
5333 if (bitcount) // we have a tail to count
5334 {
5335 unsigned mask_l = bm::mask_l_u32(bitcount-1);
5336 temp = *word & mask_l;
5337 if (temp != mask_l)
5338 return false;
5339 }
5340 return true;
5341}
5342
5343
5344
5345
5346/*!
5347 Function calculates number of 1 bits in the given array of words in
5348 the range between left anf right bits (borders included)
5349 Make sure the addr is aligned.
5350
5351 LWA - left word aligned
5352 RWA - right word aligned
5353 @ingroup bitfunc
5354*/
5355template<bool LWA, bool RWA>
5357 bm::word_t left,
5358 bm::word_t right) BMNOEXCEPT
5359{
5360 BM_ASSERT(left <= right);
5361 BM_ASSERT(right <= bm::gap_max_bits-1);
5362
5363 unsigned nword, nbit, bitcount, count, right_margin;
5364 nbit = left & bm::set_word_mask;
5365 block += (nword = unsigned(left >> bm::set_word_shift));
5366 if (left == right) // special case (only 1 bit to check)
5367 return (*block >> nbit) & 1u;
5368
5369 bitcount = 1u + (right_margin = (right - left));
5370 if constexpr (LWA)
5371 {
5372 BM_ASSERT(!nbit);
5373 count = 0;
5374 }
5375 else
5376 if (nbit) // starting position is not aligned
5377 {
5378 right_margin += nbit;
5379 unsigned mask_r = bm::mask_r_u32(nbit);
5380 if (right_margin < 32)
5381 {
5382 unsigned mask_l = bm::mask_l_u32(right_margin);
5383 return bm::word_bitcount(mask_r & mask_l & *block);
5384 }
5385 count = bm::word_bitcount(*block++ & mask_r);
5386 bitcount -= 32 - nbit;
5387 }
5388 else
5389 count = 0;
5390
5391 // now when we are word aligned, we can count bits the usual way
5392 //
5393 #if defined(BM64_SSE4) || defined(BM64_AVX2) || defined(BM64_AVX512)
5394 for ( ;bitcount >= 128; bitcount-=128)
5395 {
5396 const bm::id64_t* p64 = (bm::id64_t*) block;
5397 bm::id64_t w64_0 = p64[0]; // x86 unaligned(!) read
5398 bm::id64_t w64_1 = p64[1];
5399 count += unsigned(_mm_popcnt_u64(w64_0));
5400 count += unsigned(_mm_popcnt_u64(w64_1));
5401 block += 4;
5402 }
5403 for ( ;bitcount >= 64; bitcount-=64)
5404 {
5405 bm::id64_t w64 = *((bm::id64_t*)block); // x86 unaligned(!) read
5406 count += unsigned(_mm_popcnt_u64(w64));
5407 block += 2;
5408 }
5409 if (bitcount >= 32)
5410 {
5411 count += bm::word_bitcount(*block++);
5412 bitcount-=32;
5413 }
5414 #else
5415 for ( ;bitcount >= 32; bitcount-=32)
5416 count += bm::word_bitcount(*block++);
5417 #endif
5418 BM_ASSERT(bitcount < 32);
5419
5420 if constexpr (RWA)
5421 {
5422 BM_ASSERT(!bitcount);
5423 }
5424 else
5425 if (bitcount) // we have a tail to count
5426 {
5427 unsigned mask_l = bm::mask_l_u32(bitcount-1);
5428 count += bm::word_bitcount(*block & mask_l);
5429 }
5430 return count;
5431}
5432
5433
5434/*!
5435 Function calculates number of 1 bits in the given array of words in
5436 the range between 0 anf right bits (borders included)
5437 Make sure the addr is aligned.
5438
5439 @ingroup bitfunc
5440*/
5441inline
5443 bm::word_t right) BMNOEXCEPT
5444{
5445 BM_ASSERT(block);
5446 if (!right) // special case, first bit check
5447 return *block & 1u;
5448 bm::id_t count = 0;
5449
5450 unsigned bitcount = right + 1;
5451
5452 // AVX2 or 64-bit loop unroll
5453 #if defined(BMAVX2OPT) || defined(BMAVX512OPT)
5455
5456 __m256i cnt = _mm256_setzero_si256();
5457 bm::id64_t* cnt64;
5458
5459 for ( ;bitcount >= 256; bitcount -= 256)
5460 {
5461 const __m256i* src = (__m256i*)block;
5462 __m256i xmm256 = _mm256_load_si256(src);
5463 BM_AVX2_BIT_COUNT(bc, xmm256);
5464 cnt = _mm256_add_epi64(cnt, bc);
5465
5466 block += 8;
5467 } // for
5468 cnt64 = (bm::id64_t*)&cnt;
5469 count += (unsigned)(cnt64[0] + cnt64[1] + cnt64[2] + cnt64[3]);
5470 #endif
5471
5472 for ( ;bitcount >= 64; bitcount -= 64)
5473 {
5474 bm::id64_t* p = (bm::id64_t*)block;
5475 count += bm::word_bitcount64(*p);
5476 block += 2;
5477 }
5478 if (bitcount >= 32)
5479 {
5480 count += bm::word_bitcount(*block++);
5481 bitcount-=32;
5482 }
5483
5484 if (bitcount) // we have a tail to count
5485 {
5486 unsigned mask_l = bm::mask_l_u32(bitcount-1);
5487 count += bm::word_bitcount(*block & mask_l);
5488 }
5489 return count;
5490}
5491
5492
5493
5494/*!
5495 Cyclic rotation of bit-block left by 1 bit
5496 @ingroup bitfunc
5497*/
5498inline
5500{
5501 bm::word_t co_flag = (block[0] >> 31) & 1; // carry over bit
5502 for (unsigned i = 0; i < bm::set_block_size-1; ++i)
5503 {
5504 block[i] = (block[i] << 1) | (block[i + 1] >> 31);
5505 }
5506 block[set_block_size - 1] = (block[set_block_size - 1] << 1) | co_flag;
5507}
5508
5509/*!
5510 @brief Unrolled cyclic rotation of bit-block left by 1 bit
5511 @param block - bit-block pointer
5512 @ingroup bitfunc
5513*/
5514inline
5516{
5517 bm::word_t co_flag = (block[0] >> 31) & 1; // carry over bit
5518 const unsigned unroll_factor = 4;
5519 bm::word_t w0, w1, w2, w3;
5520
5521 unsigned i;
5522 for (i = 0; i < bm::set_block_size - unroll_factor; i += unroll_factor)
5523 {
5524 w0 = block[i + 1] >> 31;
5525 w1 = block[i + 2] >> 31;
5526 w2 = block[i + 3] >> 31;
5527 w3 = block[i + 4] >> 31;
5528
5529 block[0 + i] = (block[0 + i] << 1) | w0;
5530 block[1 + i] = (block[1 + i] << 1) | w1;
5531 block[2 + i] = (block[2 + i] << 1) | w2;
5532 block[3 + i] = (block[3 + i] << 1) | w3;
5533 }
5534 block[i] = (block[i] << 1) | (block[i + 1] >> 31);
5535 block[i + 1] = (block[i + 1] << 1) | (block[i + 2] >> 31);
5536 block[i + 2] = (block[i + 2] << 1) | (block[i + 3] >> 31);
5537 block[set_block_size - 1] = (block[set_block_size - 1] << 1) | co_flag;
5538}
5539
5540/*!
5541 @brief insert bit into position and shift the rest right with carryover
5542
5543 @param block - bit-block pointer
5544 @param bitpos - bit position to insert
5545 @param value - bit value (0|1) to insert
5546
5547 @return carry over value
5548 @ingroup bitfunc
5549*/
5550inline
5552 unsigned bitpos, bool value) BMNOEXCEPT
5553{
5554 BM_ASSERT(block);
5555 BM_ASSERT(bitpos < 65536);
5556
5557 unsigned nbit = unsigned(bitpos & bm::set_block_mask);
5558 unsigned nword = unsigned(nbit >> bm::set_word_shift);
5559 nbit &= bm::set_word_mask;
5560
5561 bm::word_t co_flag = 0;
5562 if (nbit)
5563 {
5564 unsigned mask_r = bm::mask_r_u32(nbit);
5565 bm::word_t w = block[nword] & mask_r;
5566 bm::word_t wl = block[nword] & ~~mask_r;
5567 co_flag = w >> 31;
5568 w <<= 1u;
5569 block[nword] = w | (unsigned(value) << nbit) | wl;
5570 ++nword;
5571 }
5572 else
5573 {
5574 co_flag = value;
5575 }
5576
5577 for (unsigned i = nword; i < bm::set_block_size; ++i)
5578 {
5579 bm::word_t w = block[i];
5580 bm::word_t co_flag1 = w >> 31;
5581 w = (w << 1u) | co_flag;
5582 block[i] = w;
5583 co_flag = co_flag1;
5584 } // for i
5585 return co_flag;
5586}
5587
5588
5589
5590/*!
5591 @brief Right bit-shift bitblock by 1 bit (reference)
5592 @param block - bit-block pointer
5593 @param empty_acc - [out] contains 0 if block is empty
5594 @param co_flag - carry over from the previous block
5595
5596 @return carry over bit (1 or 0)
5597 @ingroup bitfunc
5598*/
5599inline
5601 bm::word_t* BMRESTRICT empty_acc,
5602 bm::word_t co_flag) BMNOEXCEPT
5603{
5604 BM_ASSERT(block);
5605 BM_ASSERT(empty_acc);
5606
5607 bm::word_t acc(0);
5608 for (unsigned i = 0; i < bm::set_block_size; ++i)
5609 {
5610 bm::word_t w = block[i];
5611 bm::word_t co_flag1 = w >> 31;
5612 acc |= w = (w << 1u) | co_flag;
5613
5614 block[i] = w;
5615 co_flag = co_flag1;
5616 } // for i
5617 *empty_acc = acc;
5618 return co_flag;
5619}
5620
5621/*!
5622 @brief Right bit-shift bitblock by 1 bit (minimum unroll)
5623 @param block - bit-block pointer
5624 @param empty_acc - [out] contains 0 if block is empty
5625 @param co_flag - carry over from the previous block
5626
5627 @return carry over bit (1 or 0)
5628 @ingroup bitfunc
5629*/
5630inline
5632 bm::word_t* BMRESTRICT empty_acc,
5633 bm::id64_t co_flag) BMNOEXCEPT
5634{
5635
5636#if defined(BM64OPT)
5637 // warning: all this code maybe not safe on big-endian
5639 (bm::bit_block_t::bunion_t*)(block);
5640
5641 bm::id64_t acc0(0), acc1(0);
5642 unsigned i = 0;
5643 do
5644 {
5645 bm::id64_t w, co_flag1;
5646 w = b_u->w64[i];
5647 co_flag1 = w >> 63;
5648 acc0 |= w = (w << 1u) | co_flag;
5649 b_u->w64[i++] = w;
5650 co_flag = co_flag1;
5651
5652 w = b_u->w64[i];
5653 co_flag1 = w >> 63;
5654 acc1 |= w = (w << 1u) | co_flag;
5655 b_u->w64[i] = w;
5656 co_flag = co_flag1;
5657
5658 } while(++i < bm::set_block_size/2);
5659 *empty_acc = bool(acc0 | acc1);
5660 return co_flag;
5661#else
5662 return bm::bit_block_shift_r1(block, empty_acc, unsigned(co_flag));
5663#endif
5664}
5665
5666
5667/*!
5668 @brief Right bit-shift of bit-block by 1 bit (loop unrolled)
5669 @param block - bit-block pointer
5670 @param empty_acc - [out] contains 0 if block is empty
5671 @param co_flag - carry over from the previous block
5672
5673 @return carry over bit (1 or 0)
5674 @ingroup bitfunc
5675*/
5676inline
5678 bm::word_t* BMRESTRICT empty_acc,
5679 bm::word_t co_flag) BMNOEXCEPT
5680{
5681 BM_ASSERT(block);
5682 BM_ASSERT(empty_acc);
5683 #if defined(VECT_SHIFT_R1)
5684 return VECT_SHIFT_R1(block, empty_acc, co_flag);
5685 #else
5686 return bm::bit_block_shift_r1_unr_min(block, empty_acc, co_flag);
5687 #endif
5688}
5689
5690
5691/*!
5692 @brief Left bit-shift bitblock by 1 bit (reference)
5693 @param block - bit-block pointer
5694 @param empty_acc - [out] contains 0 if block is empty
5695 @param co_flag - carry over from the prev/next block
5696
5697 @return carry over bit (1 or 0)
5698
5699 @ingroup bitfunc
5700*/
5701inline
5703 bm::word_t* empty_acc, bm::word_t co_flag) BMNOEXCEPT
5704{
5705 BM_ASSERT(block);
5706 BM_ASSERT(empty_acc);
5707
5708 bm::word_t acc = 0;
5709 for (int i = bm::set_block_size-1; i >= 0; --i)
5710 {
5711 bm::word_t w = block[i];
5712 bm::word_t co_flag1 = w & 1u;
5713 acc |= w = (w >> 1u) | (co_flag << 31u);
5714 block[i] = w;
5715 co_flag = co_flag1;
5716 }
5717
5718 *empty_acc = acc;
5719 return co_flag;
5720}
5721
5722/*!
5723 @brief Left bit-shift bitblock by 1 bit (minimum unroll)
5724 @param block - bit-block pointer
5725 @param empty_acc - [out] contains 0 if block is empty
5726 @param co_flag - carry over from the prev/next block
5727
5728 @return carry over bit (1 or 0)
5729
5730 @ingroup bitfunc
5731*/
5732inline
5734 bm::word_t* BMRESTRICT empty_acc,
5735 unsigned co_flag) BMNOEXCEPT
5736{
5737 bm::word_t acc = 0;
5738 for (int i = bm::set_block_size-1; i >= 0; i-=2)
5739 {
5740 bm::word_t w0, w1, co_flag1;
5741 w0 = block[i]; w1 = block[i-1];
5742 co_flag1 = w0 & 1u;
5743 acc |= w0 = (w0 >> 1u) | (co_flag << 31u);
5744 block[i] = w0;
5745 co_flag = co_flag1;
5746 co_flag1 = w1 & 1u;
5747 acc |= w1 = (w1 >> 1u) | (co_flag << 31u);
5748 block[i-1] = w1;
5749 co_flag = co_flag1;
5750
5751 i-=2;
5752 w0 = block[i]; w1 = block[i-1];
5753 co_flag1 = w0 & 1u;
5754 acc |= w0 = (w0 >> 1u) | (co_flag << 31u);
5755 block[i] = w0;
5756 co_flag = co_flag1;
5757 co_flag1 = w1 & 1u;
5758 acc |= w1 = (w1 >> 1u) | (co_flag << 31u);
5759 block[i-1] = w1;
5760 co_flag = co_flag1;
5761 } // for i
5762 *empty_acc = acc;
5763 return co_flag;
5764}
5765
5766
5767/*!
5768 @brief Left bit-shift of bit-block by 1 bit (loop unrolled)
5769 @param block - bit-block pointer
5770 @param empty_acc - [out] contains 0 if block is empty
5771 @param co_flag - carry over from the prev/next block
5772
5773 @return carry over bit (1 or 0)
5774 @ingroup bitfunc
5775*/
5776inline
5778 bm::word_t* empty_acc,
5779 bm::word_t co_flag) BMNOEXCEPT
5780{
5781 BM_ASSERT(block);
5782 BM_ASSERT(empty_acc);
5783 #if defined(VECT_SHIFT_L1)
5784 return VECT_SHIFT_L1(block, empty_acc, co_flag);
5785 #else
5786 return bm::bit_block_shift_l1_unr_min(block, empty_acc, co_flag);
5787 #endif
5788}
5789
5790/*!
5791 @brief erase bit from position and shift the rest right with carryover
5792
5793 @param block - bit-block pointer
5794 @param bitpos - bit position to insert
5795 @param carry_over - bit value to add to the end (0|1)
5796
5797 @ingroup bitfunc
5798*/
5799inline
5801 unsigned bitpos,
5802 bool carry_over) BMNOEXCEPT
5803{
5804 BM_ASSERT(block);
5805 BM_ASSERT(bitpos < 65536);
5806
5807 if (!bitpos)
5808 {
5809 bm::word_t acc;
5810 bm::bit_block_shift_l1_unr(block, &acc, carry_over);
5811 return;
5812 }
5813
5814 unsigned nbit = unsigned(bitpos & bm::set_block_mask);
5815 unsigned nword = unsigned(nbit >> bm::set_word_shift);
5816 nbit &= bm::set_word_mask;
5817
5818 bm::word_t co_flag = carry_over;
5819 for (unsigned i = bm::set_block_size-1; i > nword; --i)
5820 {
5821 bm::word_t w = block[i];
5822 bm::word_t co_flag1 = w & 1u;
5823 w = (w >> 1u) | (co_flag << 31u);
5824 block[i] = w;
5825 co_flag = co_flag1;
5826 }
5827
5828 if (nbit)
5829 {
5830 unsigned mask_r = bm::mask_r_u32(nbit);
5831 bm::word_t w = block[nword] & mask_r;
5832 bm::word_t wl = block[nword] & ~~mask_r;
5833 w &= ~(1 << nbit); // clear the removed bit
5834 w >>= 1u;
5835 w |= wl | (co_flag << 31u);
5836 block[nword] = w;
5837 }
5838 else
5839 {
5840 block[nword] = (block[nword] >> 1u) | (co_flag << 31u);
5841 }
5842}
5843
5844
5845/*!
5846 @brief Right bit-shift of bit-block by 1 bit (reference) + AND
5847 @param block - bit-block pointer
5848 @param co_flag - carry over from the previous block
5849 @param mask_block - mask bit-block pointer
5850 @param digest - block digest
5851
5852 @return carry over bit (1 or 0)
5853 @ingroup bitfunc
5854*/
5855inline
5857 bm::word_t co_flag,
5858 const bm::word_t* BMRESTRICT mask_block,
5860{
5861 BM_ASSERT(block);
5862 BM_ASSERT(mask_block);
5863 BM_ASSERT(digest && *digest);
5864
5865
5866 bm::id64_t d = *digest;
5867
5868 unsigned di = 0;
5869 if (!co_flag)
5870 {
5871 bm::id64_t t = d & -d;
5872 di = bm::word_bitcount64(t - 1); // find start bit-index
5873 }
5874
5875 for (; di < 64; ++di)
5876 {
5877 const unsigned d_base = di * bm::set_block_digest_wave_size;
5878 bm::id64_t dmask = (1ull << di);
5879 if (d & dmask) // digest stride not empty
5880 {
5881 bm::word_t acc = 0;
5882 for (unsigned i = d_base; i < d_base + bm::set_block_digest_wave_size; ++i)
5883 {
5885
5886 bm::word_t w = block[i];
5887 bm::word_t co_flag1 = w >> 31;
5888 w = (w << 1u) | co_flag;
5889 acc |= block[i] = w & mask_block[i];
5890 co_flag = co_flag1;
5891 }
5892 if (!acc)
5893 d &= ~~dmask; // update digest: clear stride bit
5894 }
5895 else // stride is empty
5896 {
5897 BM_ASSERT(block[d_base + bm::set_block_digest_wave_size -1]==0);
5898 BM_ASSERT(block[d_base]==0);
5899
5900 if (co_flag) // there is carry-over
5901 {
5902 BM_ASSERT(co_flag == 1);
5903 BM_ASSERT(block[d_base] == 0);
5904
5905 block[d_base] = co_flag & mask_block[d_base];
5906 if (block[d_base])
5907 d |= dmask; // update digest
5908 co_flag = 0;
5909 }
5910 }
5911 } // for di
5912
5913 *digest = d;
5914 return co_flag;
5915}
5916
5917/*!
5918 @brief Right bit-shift bitblock by 1 bit (reference) + AND
5919 @param block - bit-block pointer
5920 @param co_flag - carry over from the previous block
5921 @param mask_block - mask bit-block pointer
5922 @param digest - block digest
5923
5924 @return carry over bit (1 or 0)
5925 @ingroup bitfunc
5926*/
5927inline
5929 bm::word_t co_flag,
5930 const bm::word_t* BMRESTRICT mask_block,
5932{
5933 BM_ASSERT(block);
5934 BM_ASSERT(mask_block);
5935 BM_ASSERT(digest);
5936
5937 #if defined(VECT_SHIFT_R1_AND)
5938 return VECT_SHIFT_R1_AND(block, co_flag, mask_block, digest);
5939 #else
5940 return bm::bit_block_shift_r1_and(block, co_flag, mask_block, digest);
5941 #endif
5942}
5943
5944
5945/*!
5946 Function calculates if there is any number of 1 bits
5947 in the given array of words in the range between left anf right bits
5948 (borders included). Make sure the addresses are aligned.
5949
5950 @ingroup bitfunc
5951*/
5952inline
5954 bm::word_t left,
5955 bm::word_t right) BMNOEXCEPT
5956{
5957 BM_ASSERT(left <= right);
5958
5959 unsigned nbit = left; // unsigned(left & bm::set_block_mask);
5960 unsigned nword = unsigned(nbit >> bm::set_word_shift);
5961 nbit &= bm::set_word_mask;
5962
5963 const bm::word_t* word = block + nword;
5964
5965 if (left == right) // special case (only 1 bit to check)
5966 {
5967 return (*word >> nbit) & 1;
5968 }
5969 unsigned acc;
5970 unsigned bitcount = right - left + 1;
5971
5972 if (nbit) // starting position is not aligned
5973 {
5974 unsigned right_margin = nbit + (right - left);
5975 if (right_margin < 32)
5976 {
5977 unsigned mask_r = bm::mask_r_u32(nbit);
5978 unsigned mask_l = bm::mask_l_u32(right_margin);
5979 unsigned mask = mask_r & mask_l;
5980 return *word & mask;
5981 }
5982 else
5983 {
5984 unsigned mask_r = bm::mask_r_u32(nbit);
5985 acc = *word & mask_r;
5986 if (acc)
5987 return acc;
5988 bitcount -= 32 - nbit;
5989 }
5990 ++word;
5991 }
5992
5993 // loop unrolled to evaluate 4 words at a time
5994 // SIMD showed no advantage, unless evaluate sub-wave intervals
5995 //
5996 for ( ;bitcount >= 128; bitcount-=128, word+=4)
5997 {
5998 acc = word[0] | word[1] | word[2] | word[3];
5999 if (acc)
6000 return acc;
6001 } // for
6002
6003 acc = 0;
6004 for ( ;bitcount >= 32; bitcount -= 32)
6005 {
6006 acc |= *word++;
6007 } // for
6008
6009 if (bitcount) // we have a tail to count
6010 {
6011 unsigned mask_l = bm::mask_l_u32(bitcount-1);
6012 acc |= (*word) & mask_l;
6013 }
6014 return acc;
6015}
6016
6017// ----------------------------------------------------------------------
6018
6019/*! Function inverts block of bits
6020 @ingroup bitfunc
6021*/
6022template<typename T>
6024{
6026#ifdef BMVECTOPT
6027 VECT_INVERT_BLOCK(start);
6028#else
6029 T* end = (T*)((unsigned*)(start) + bm::set_block_size);
6030 do
6031 {
6032 start[0] = ~~start[0];
6033 start[1] = ~~start[1];
6034 start[2] = ~~start[2];
6035 start[3] = ~~start[3];
6036 start+=4;
6037 } while (start < end);
6038#endif
6039}
6040
6041// ----------------------------------------------------------------------
6042
6043/*! @brief Returns "true" if all bits in the block are 1
6044 @ingroup bitfunc
6045*/
6046inline
6048{
6049#if defined(VECT_IS_ONE_BLOCK)
6050 return VECT_IS_ONE_BLOCK(start);
6051#else
6052 const bm::word_t* BMRESTRICT src_end = (bm::word_t*)start + bm::set_block_size;
6053 const bm::wordop_t* end = (const bm::wordop_t*)src_end;
6054 do
6055 {
6056 bm::wordop_t tmp =
6057 start[0] & start[1] & start[2] & start[3];
6058 if (tmp != bm::all_bits_mask)
6059 return false;
6060 start += 4;
6061 } while (start < end);
6062 return true;
6063#endif
6064}
6065
6066// ----------------------------------------------------------------------
6067
6068/*! @brief Returns "true" if all bits are 1 in the block [left, right]
6069 Function check for block varieties
6070 @internal
6071*/
6072inline
6074 unsigned left, unsigned right) BMNOEXCEPT
6075{
6076 BM_ASSERT(left <= right);
6077 BM_ASSERT(right < bm::gap_max_bits);
6078 if (block)
6079 {
6080 if (BM_IS_GAP(block))
6081 return bm::gap_is_all_one_range(BMGAP_PTR(block), left, right);
6082 if (block == FULL_BLOCK_FAKE_ADDR)
6083 return true;
6084 return bm::bit_block_is_all_one_range(block, left, right);
6085 }
6086 return false;
6087}
6088
6089/*! @brief Returns "true" if all bits are 1 in the block [left, right]
6090 and border bits are 0
6091 @internal
6092*/
6093inline
6095 unsigned left, unsigned right) BMNOEXCEPT
6096{
6097 BM_ASSERT(left <= right);
6098 BM_ASSERT(right < bm::gap_max_bits-1);
6099
6100 if (block)
6101 {
6102 bool is_left, is_right, all_one;
6103 if (BM_IS_GAP(block))
6104 {
6105 const bm::gap_word_t* gap = BMGAP_PTR(block);
6106 all_one = bm::gap_is_interval(gap, left, right);
6107 return all_one;
6108 }
6109 else // bit-block
6110 {
6111 if (block == FULL_BLOCK_FAKE_ADDR)
6112 return false;
6113 unsigned nword = ((left-1) >> bm::set_word_shift);
6114 is_left = block[nword] & (1u << ((left-1) & bm::set_word_mask));
6115 if (is_left == false)
6116 {
6117 nword = ((right + 1) >> bm::set_word_shift);
6118 is_right = block[nword] & (1u << ((right + 1) & bm::set_word_mask));
6119 if (is_right == false)
6120 {
6121 all_one = bm::bit_block_is_all_one_range(block, left, right);
6122 return all_one;
6123 }
6124 }
6125 }
6126 }
6127
6128 return false;
6129}
6130
6131// ----------------------------------------------------------------------
6132
6133/**
6134 \brief Searches for the last 1 bit in the 111 interval of a BIT block
6135 \param block - BIT buffer
6136 \param nbit - bit index to start checking from
6137 \param pos - [out] found value
6138
6139 \return false if not found
6140 @ingroup bitfunc
6141*/
6142inline
6144 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
6145{
6146 BM_ASSERT(block);
6147 BM_ASSERT(pos);
6148
6149 unsigned nword = unsigned(nbit >> bm::set_word_shift);
6150 unsigned bit_pos = (nbit & bm::set_word_mask);
6151 bm::word_t w = block[nword];
6152 w &= (1u << bit_pos);
6153 if (!w)
6154 return false;
6155
6156 if (nbit == bm::gap_max_bits-1)
6157 {
6158 *pos = bm::gap_max_bits-1;
6159 return true;
6160 }
6161 *pos = nbit;
6162
6163 ++nbit;
6164 nword = unsigned(nbit >> bm::set_word_shift);
6165 bit_pos = (nbit & bm::set_word_mask);
6166
6167 w = (~~block[nword]) >> bit_pos;
6168 w <<= bit_pos; // clear the trailing bits
6169 if (w)
6170 {
6171 bit_pos = bm::bit_scan_forward32(w); // trailing zeros
6172 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t)))-1);
6173 return true;
6174 }
6175
6176 for (++nword; nword < bm::set_block_size; ++nword)
6177 {
6178 w = ~~block[nword];
6179 if (w)
6180 {
6181 bit_pos = bm::bit_scan_forward32(w); // trailing zeros
6182 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t)))-1);
6183 return true;
6184 }
6185 } // for nword
6186
6187 // 0 not found, all block is 1s...
6188 *pos = bm::gap_max_bits-1;
6189 return true;
6190}
6191
6192
6193/*! @brief Find end of the current 111 interval
6194 @return search result code 0 - not found, 1 found, 2 - found at the end
6195 @internal
6196*/
6197inline
6199 unsigned nbit_from,
6200 unsigned* BMRESTRICT found_nbit) BMNOEXCEPT
6201{
6202 BM_ASSERT(block && found_nbit);
6203 BM_ASSERT(nbit_from < bm::gap_max_bits);
6204
6205 bool b;
6206 if (BM_IS_GAP(block))
6207 {
6208 const bm::gap_word_t* gap = BMGAP_PTR(block);
6209 b = bm::gap_find_interval_end(gap, nbit_from, found_nbit);
6210 if (b && *found_nbit == bm::gap_max_bits-1)
6211 return 2; // end of block, keep searching
6212 }
6213 else // bit-block
6214 {
6215 if (IS_FULL_BLOCK(block))
6216 {
6217 *found_nbit = bm::gap_max_bits-1;
6218 return 2;
6219 }
6220 b = bm::bit_block_find_interval_end(block, nbit_from, found_nbit);
6221 if (b && *found_nbit == bm::gap_max_bits-1)
6222 return 2; // end of block, keep searching
6223 }
6224 return b;
6225}
6226
6227// ----------------------------------------------------------------------
6228
6229/**
6230 \brief Searches for the first 1 bit in the 111 interval of a BIT block
6231 \param block - BIT buffer
6232 \param nbit - bit index to start checking from
6233 \param pos - [out] found value
6234
6235 \return false if not found
6236 @ingroup bitfunc
6237*/
6238inline
6240 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
6241{
6242 BM_ASSERT(block);
6243 BM_ASSERT(pos);
6244
6245 unsigned nword = unsigned(nbit >> bm::set_word_shift);
6246 unsigned bit_pos = (nbit & bm::set_word_mask);
6247 bm::word_t w = block[nword];
6248 w &= (1u << bit_pos);
6249 if (!w)
6250 return false;
6251
6252 if (nbit == 0)
6253 {
6254 *pos = 0;
6255 return true;
6256 }
6257 *pos = nbit;
6258
6259 --nbit;
6260 nword = unsigned(nbit >> bm::set_word_shift);
6261 bit_pos = (nbit & bm::set_word_mask);
6262
6263 unsigned mask_l = bm::mask_l_u32(bit_pos);
6264 w = (~~block[nword]) & mask_l;
6265 if (w)
6266 {
6267 bit_pos = bm::bit_scan_reverse32(w);
6268 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t)))+1);
6269 return true;
6270 }
6271
6272 if (nword)
6273 {
6274 for (--nword; true; --nword)
6275 {
6276 w = ~~block[nword];
6277 if (w)
6278 {
6279 bit_pos = bm::bit_scan_reverse32(w); // trailing zeros
6280 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t)))+1);
6281 return true;
6282 }
6283 if (!nword)
6284 break;
6285 } // for nword
6286 }
6287
6288 // 0 not found, all block is 1s...
6289 *pos = 0;
6290 return true;
6291}
6292
6293/**
6294 \brief Reverse search for the previous 1 bit
6295 \param block - BIT buffer
6296 \param nbit - bit index to start checking from
6297 \param pos - [out] found value
6298
6299 \return false if not found
6300 @ingroup bitfunc
6301*/
6302inline
6304 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
6305{
6306 BM_ASSERT(block);
6307 BM_ASSERT(pos);
6308
6309 unsigned nword = unsigned(nbit >> bm::set_word_shift);
6310 unsigned bit_pos = (nbit & bm::set_word_mask);
6311 bm::word_t w = block[nword];
6312 w &= (1u << bit_pos);
6313 if (w)
6314 {
6315 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t))));
6316 return true;
6317 }
6318
6319 if (!nbit)
6320 return false;
6321
6322 --nbit;
6323 nword = unsigned(nbit >> bm::set_word_shift);
6324 bit_pos = (nbit & bm::set_word_mask);
6325
6326 unsigned mask_l = bm::mask_l_u32(bit_pos);
6327 w = block[nword] & mask_l;
6328 if (w)
6329 {
6330 bit_pos = bm::bit_scan_reverse32(w);
6331 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t))));
6332 return true;
6333 }
6334
6335 if (nword)
6336 {
6337 for (--nword; true; --nword)
6338 {
6339 w = block[nword];
6340 if (w)
6341 {
6342 bit_pos = bm::bit_scan_reverse32(w); // trailing zeros
6343 *pos =
6344 unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t))));
6345 return true;
6346 }
6347 if (!nword)
6348 break;
6349 } // for nword
6350 }
6351 return false;
6352}
6353
6354
6355// ----------------------------------------------------------------------
6356
6357/*! @brief Find start of the current 111 interval
6358 @return search result code 0 - not found, 1 found, 2 - found at the start
6359 @internal
6360*/
6361inline
6363 unsigned nbit_from,
6364 unsigned* BMRESTRICT found_nbit) BMNOEXCEPT
6365{
6366 BM_ASSERT(block && found_nbit);
6367 BM_ASSERT(nbit_from < bm::gap_max_bits);
6368 bool b;
6369 if (BM_IS_GAP(block))
6370 {
6371 const bm::gap_word_t* gap = BMGAP_PTR(block);
6372 b = bm::gap_find_interval_start(gap, nbit_from, found_nbit);
6373 if (b && *found_nbit == 0)
6374 return 2; // start of block, keep searching
6375 }
6376 else // bit-block
6377 {
6378 if (IS_FULL_BLOCK(block))
6379 {
6380 *found_nbit = 0;
6381 return 2;
6382 }
6383 b = bm::bit_block_find_interval_start(block, nbit_from, found_nbit);
6384 if (b && *found_nbit == 0)
6385 return 2; // start of block, keep searching
6386 }
6387 return b;
6388}
6389
6390// ----------------------------------------------------------------------
6391
6392/*! @brief Reverse find 1
6393 @return search result code 0 - not found, 1 found
6394 @internal
6395*/
6396inline
6398 unsigned nbit_from,
6399 unsigned* BMRESTRICT found_nbit) BMNOEXCEPT
6400{
6401 BM_ASSERT(block && found_nbit);
6402 BM_ASSERT(nbit_from < bm::gap_max_bits);
6403 bool b;
6404 if (BM_IS_GAP(block))
6405 {
6406 b = bm::gap_find_prev(BMGAP_PTR(block), nbit_from, found_nbit);
6407 }
6408 else // bit-block
6409 {
6410 if (IS_FULL_BLOCK(block))
6411 {
6412 *found_nbit = nbit_from;
6413 return true;
6414 }
6415 b = bm::bit_block_find_prev(block, nbit_from, found_nbit);
6416 }
6417 return b;
6418}
6419
6420// ----------------------------------------------------------------------
6421
6422/*! @brief Returns "true" if one bit is set in the block [left, right]
6423 Function check for block varieties
6424 @internal
6425*/
6426inline
6427bool block_any_range(const bm::word_t* const BMRESTRICT block,
6428 unsigned left, unsigned right) BMNOEXCEPT
6429{
6430 BM_ASSERT(left <= right);
6431 BM_ASSERT(right < bm::gap_max_bits);
6432 if (!block)
6433 return false;
6434 if (BM_IS_GAP(block))
6435 return bm::gap_any_range(BMGAP_PTR(block), left, right);
6436 if (IS_FULL_BLOCK(block))
6437 return true;
6438 return bm::bit_block_any_range(block, left, right);
6439}
6440
6441// ----------------------------------------------------------------------
6442
6443/*! @brief Returns "true" if one bit is set in the block
6444 Function check for block varieties
6445 @internal
6446*/
6447inline
6449{
6450 if (!block)
6451 return false;
6452 if (IS_FULL_BLOCK(block))
6453 return true;
6454 bool all_zero = (BM_IS_GAP(block)) ?
6456 : bm::bit_is_all_zero(block);
6457 return !all_zero;
6458}
6459
6460
6461
6462// ----------------------------------------------------------------------
6463
6464// GAP blocks manipulation functions:
6465
6466
6467/*!
6468 \brief GAP AND operation.
6469
6470 Function performs AND logical operation on gap vectors.
6471 If possible function put the result into vect1 and returns this
6472 pointer. Otherwise result is put into tmp_buf, which should be
6473 twice of the vector size.
6474
6475 \param vect1 - operand 1
6476 \param vect2 - operand 2
6477 \param tmp_buf - pointer on temporary buffer
6478 \param dsize - out size of the destination
6479 \return Result pointer (tmp_buf OR vect1)
6480
6481 @ingroup gapfunc
6482*/
6483inline
6485 const gap_word_t* BMRESTRICT vect2,
6486 gap_word_t* BMRESTRICT tmp_buf,
6487 unsigned& dsize) BMNOEXCEPT
6488{
6489 bm::gap_buff_op<bm::gap_word_t, bm::and_func>(
6490 tmp_buf, vect1, 0, vect2, 0, dsize);
6491 return tmp_buf;
6492}
6493
6494/*!
6495 \brief GAP AND operation test.
6496
6497 Function performs AND logical operation on gap vectors.
6498 If possible function put the result into vect1 and returns this
6499 pointer. Otherwise result is put into tmp_buf, which should be
6500 twice of the vector size.
6501
6502 \param vect1 - operand 1
6503 \param vect2 - operand 2
6504 \return non zero value if operation returns any 1 bit
6505
6506 @ingroup gapfunc
6507*/
6508inline
6510 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6511{
6512 return gap_buff_any_op<bm::gap_word_t, bm::and_func>(vect1, 0, vect2, 0);
6513}
6514
6515
6516/*!
6517 \brief GAP bitcount AND operation test.
6518
6519 \param vect1 - operand 1
6520 \param vect2 - operand 2
6521 \return bitcount of vect1 AND vect2
6522
6523 @ingroup gapfunc
6524*/
6525inline
6527 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6528{
6529 return bm::gap_buff_count_op<bm::gap_word_t, bm::and_func>(vect1, vect2);
6530}
6531
6532
6533
6534/*!
6535 \brief GAP XOR operation.
6536
6537 Function performs XOR logical operation on gap vectors.
6538 If possible function put the result into vect1 and returns this
6539 pointer. Otherwise result is put into tmp_buf, which should be
6540 twice of the vector size.
6541
6542 \param vect1 - operand 1
6543 \param vect2 - operand 2
6544 \param tmp_buf - pointer on temporary buffer
6545 \param dsize - out destination size
6546 \return Result pointer (tmp_buf)
6547
6548 @ingroup gapfunc
6549*/
6550inline
6552 const gap_word_t* BMRESTRICT vect2,
6553 gap_word_t* BMRESTRICT tmp_buf,
6554 unsigned& dsize) BMNOEXCEPT
6555{
6556 bm::gap_buff_op<bm::gap_word_t, bm::xor_func>(
6557 tmp_buf, vect1, 0, vect2, 0, dsize);
6558 return tmp_buf;
6559}
6560
6561/*! Light weight gap_operation_xor for len prediction
6562 @ingroup gapfunc
6563*/
6564/*
6565inline
6566bool gap_operation_dry_xor(const gap_word_t* BMRESTRICT vect1,
6567 const gap_word_t* BMRESTRICT vect2,
6568 unsigned& dsize,
6569 unsigned limit) BMNOEXCEPT
6570{
6571 return
6572 bm::gap_buff_dry_op<bm::gap_word_t, bm::xor_func>(vect1, vect2, dsize, limit);
6573}
6574*/
6575
6576/*!
6577 \brief GAP XOR operation test.
6578
6579 Function performs AND logical operation on gap vectors.
6580 If possible function put the result into vect1 and returns this
6581 pointer. Otherwise result is put into tmp_buf, which should be
6582 twice of the vector size.
6583
6584 \param vect1 - operand 1
6585 \param vect2 - operand 2
6586 \return non zero value if operation returns any 1 bit
6587
6588 @ingroup gapfunc
6589*/
6592 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6593{
6594 return gap_buff_any_op<bm::gap_word_t, bm::xor_func>(vect1, 0, vect2, 0);
6595}
6596
6597/*!
6598 \brief GAP bitcount XOR operation test.
6599
6600 \param vect1 - operand 1
6601 \param vect2 - operand 2
6602 \return bitcount of vect1 XOR vect2
6603
6604 @ingroup gapfunc
6605*/
6608 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6609{
6610 return bm::gap_buff_count_op<bm::gap_word_t, bm::xor_func>(vect1, vect2);
6611}
6612
6613
6614/*!
6615 \brief GAP OR operation.
6616
6617 Function performs OR logical oparation on gap vectors.
6618 If possible function put the result into vect1 and returns this
6619 pointer. Otherwise result is put into tmp_buf, which should be
6620 twice of the vector size.
6621
6622 \param vect1 - operand 1
6623 \param vect2 - operand 2
6624 \param tmp_buf - pointer on temporary buffer
6625 \param dsize - out destination size
6626
6627 \return Result pointer (tmp_buf)
6628
6629 @ingroup gapfunc
6630*/
6631inline
6633 const gap_word_t* BMRESTRICT vect2,
6634 gap_word_t* BMRESTRICT tmp_buf,
6635 unsigned& dsize) BMNOEXCEPT
6636{
6637 bm::gap_buff_op<bm::gap_word_t, bm::and_func>(tmp_buf, vect1, 1, vect2, 1, dsize);
6638 bm::gap_invert(tmp_buf);
6639 return tmp_buf;
6640}
6641
6642/*!
6643 \brief GAP bitcount OR operation test.
6644
6645 \param vect1 - operand 1
6646 \param vect2 - operand 2
6647 \return bitcount of vect1 OR vect2
6648
6649 @ingroup gapfunc
6650*/
6652unsigned gap_count_or(const gap_word_t* BMRESTRICT vect1,
6653 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6654{
6655 return gap_buff_count_op<bm::gap_word_t, bm::or_func>(vect1, vect2);
6656}
6657
6658
6659
6660/*!
6661 \brief GAP SUB (AND NOT) operation.
6662
6663 Function performs SUB logical operation on gap vectors.
6664 If possible function put the result into vect1 and returns this
6665 pointer. Otherwise result is put into tmp_buf, which should be
6666 twice of the vector size.
6667
6668 \param vect1 - operand 1
6669 \param vect2 - operand 2
6670 \param tmp_buf - pointer on temporary buffer
6671 \param dsize - out destination size
6672
6673 \return Result pointer (tmp_buf)
6674
6675 @ingroup gapfunc
6676*/
6677inline
6679 const gap_word_t* BMRESTRICT vect2,
6680 gap_word_t* BMRESTRICT tmp_buf,
6681 unsigned& dsize) BMNOEXCEPT
6682{
6683 bm::gap_buff_op<bm::gap_word_t, bm::and_func>( // no bug here
6684 tmp_buf, vect1, 0, vect2, 1, dsize);
6685 return tmp_buf;
6686}
6687
6688
6689/*!
6690 \brief GAP SUB operation test.
6691
6692 Function performs AND logical operation on gap vectors.
6693 If possible function put the result into vect1 and returns this
6694 pointer. Otherwise result is put into tmp_buf, which should be
6695 twice of the vector size.
6696
6697 \param vect1 - operand 1
6698 \param vect2 - operand 2
6699 \return non zero value if operation returns any 1 bit
6700
6701 @ingroup gapfunc
6702*/
6703inline
6705 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6706{
6707 return
6708 bm::gap_buff_any_op<bm::gap_word_t, bm::and_func>( // no bug here
6709 vect1, 0, vect2, 1);
6710}
6711
6712
6713/*!
6714\brief GAP bitcount SUB (AND NOT) operation test.
6715
6716\param vect1 - operand 1
6717\param vect2 - operand 2
6718\return bitcount of vect1 SUB (AND NOT) vect2
6719
6720@ingroup gapfunc
6721*/
6724 const gap_word_t* BMRESTRICT vect2) BMNOEXCEPT
6725{
6726 return bm::gap_buff_count_op<bm::gap_word_t, bm::sub_func>(vect1, vect2);
6727}
6728
6729
6730// ----------------------------------------------------------------------
6731
6732// BIT blocks manipulation functions:
6733
6734
6735/*!
6736 \brief Bitblock copy operation.
6737 \param dst [out] - destination block.
6738 \param src [in] - source block.
6739
6740 @ingroup bitfunc
6741*/
6742inline
6744 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
6745{
6746#ifdef BMVECTOPT
6747 VECT_COPY_BLOCK(dst, src);
6748#else
6749 ::memcpy(dst, src, bm::set_block_size * sizeof(bm::word_t));
6750#endif
6751}
6752
6753/*!
6754 \brief Bitblock copy operation (unaligned src)
6755 \param dst [out] - destination block.
6756 \param src [in] - source block.
6757
6758 @ingroup bitfunc
6759*/
6760inline
6762 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
6763{
6764#ifdef VECT_COPY_BLOCK_UNALIGN
6765 VECT_COPY_BLOCK_UNALIGN(dst, src);
6766#else
6767 ::memcpy(dst, src, bm::set_block_size * sizeof(bm::word_t));
6768#endif
6769}
6770
6771
6772
6773/*!
6774 \brief Bitblock copy/stream operation.
6775
6776 \param dst - destination block.
6777 \param src - source block.
6778
6779 @ingroup bitfunc
6780*/
6781inline
6783 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
6784{
6785#ifdef VECT_STREAM_BLOCK
6786 VECT_STREAM_BLOCK(dst, src);
6787#else
6788 ::memcpy(dst, src, bm::set_block_size * sizeof(bm::word_t));
6789#endif
6790}
6791
6792/*!
6793 \brief Bitblock copy/stream operation (unaligned src)
6794 \param dst [out] - destination block.
6795 \param src [in] - source block (unaligned address)
6796
6797 @ingroup bitfunc
6798*/
6799inline
6801 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
6802{
6803#ifdef VECT_STREAM_BLOCK_UNALIGN
6804 VECT_STREAM_BLOCK_UNALIGN(dst, src);
6805#else
6806 ::memcpy(dst, src, bm::set_block_size * sizeof(bm::word_t));
6807#endif
6808}
6809
6810
6811
6812/*!
6813 \brief Plain bitblock AND operation.
6814 Function does not analyse availability of source and destination blocks.
6815
6816 \param dst - destination block.
6817 \param src - source block.
6818
6819 \return 0 if AND operation did not produce anything (no 1s in the output)
6820
6821 @ingroup bitfunc
6822*/
6823inline
6825 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
6826{
6827 BM_ASSERT(dst);
6828 BM_ASSERT(src);
6829 BM_ASSERT(dst != src);
6830
6831#ifdef BMVECTOPT
6832 bm::id64_t acc = VECT_AND_BLOCK(dst, src);
6833#else
6834 unsigned arr_sz = bm::set_block_size / 2;
6837 bm::id64_t acc = 0;
6838 for (unsigned i = 0; i < arr_sz; i+=4)
6839 {
6840 acc |= (dst_u->w64[i] &= src_u->w64[i]) |
6841 (dst_u->w64[i+1] &= src_u->w64[i+1]) |
6842 (dst_u->w64[i+2] &= src_u->w64[i+2]) |
6843 (dst_u->w64[i+3] &= src_u->w64[i+3]);
6844 }
6845#endif
6846 return acc;
6847}
6848
6849/*!
6850 \brief digest based bit-block AND
6851
6852 \param dst - destination block.
6853 \param src - source block.
6854 \param digest - known digest of dst block
6855
6856 \return new digest
6857
6858 @ingroup bitfunc
6859*/
6860inline
6862 const bm::word_t* BMRESTRICT src,
6863 bm::id64_t digest) BMNOEXCEPT
6864{
6865 BM_ASSERT(dst);
6866 BM_ASSERT(src);
6867 BM_ASSERT(dst != src);
6868
6869 const bm::id64_t mask(1ull);
6870 bm::id64_t d = digest;
6871 while (d)
6872 {
6873 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
6874
6875 unsigned wave = bm::word_bitcount64(t - 1);
6876 unsigned off = wave * bm::set_block_digest_wave_size;
6877
6878 #if defined(VECT_AND_DIGEST)
6879 bool all_zero = VECT_AND_DIGEST(&dst[off], &src[off]);
6880 if (all_zero)
6881 digest &= ~(mask << wave);
6882 #else
6883 const bm::bit_block_t::bunion_t* BMRESTRICT src_u = (const bm::bit_block_t::bunion_t*)(&src[off]);
6885
6886 bm::id64_t acc = 0;
6887 unsigned j = 0;
6888 do
6889 {
6890 acc |= dst_u->w64[j+0] &= src_u->w64[j+0];
6891 acc |= dst_u->w64[j+1] &= src_u->w64[j+1];
6892 acc |= dst_u->w64[j+2] &= src_u->w64[j+2];
6893 acc |= dst_u->w64[j+3] &= src_u->w64[j+3];
6894 j+=4;
6895 } while (j < bm::set_block_digest_wave_size/2);
6896
6897 if (!acc) // all zero
6898 digest &= ~(mask << wave);
6899 #endif
6900
6901 d = bm::bmi_bslr_u64(d); // d &= d - 1;
6902 } // while
6903
6904 return digest;
6905}
6906
6907
6908/*!
6909 \brief digest based bit-block AND 5-way
6910
6911 \return new digest
6912
6913 @ingroup bitfunc
6914*/
6915inline
6917 const bm::word_t* BMRESTRICT src0,
6918 const bm::word_t* BMRESTRICT src1,
6919 const bm::word_t* BMRESTRICT src2,
6920 const bm::word_t* BMRESTRICT src3,
6921 bm::id64_t digest) BMNOEXCEPT
6922{
6923 BM_ASSERT(dst);
6924 BM_ASSERT(src0 && src1 && src2 && src3);
6925
6926 const bm::id64_t mask(1ull);
6927 bm::id64_t d = digest;
6928 while (d)
6929 {
6930 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
6931
6932 unsigned wave = bm::word_bitcount64(t - 1);
6933 unsigned off = wave * bm::set_block_digest_wave_size;
6934
6935#if defined(VECT_AND_DIGEST_5WAY)
6936 bool all_zero = VECT_AND_DIGEST_5WAY(&dst[off], &src0[off], &src1[off], &src2[off], &src3[off]);
6937 if (all_zero)
6938 digest &= ~(mask << wave);
6939#else
6940 const bm::bit_block_t::bunion_t* BMRESTRICT src_u0 = (const bm::bit_block_t::bunion_t*)(&src0[off]);
6941 const bm::bit_block_t::bunion_t* BMRESTRICT src_u1 = (const bm::bit_block_t::bunion_t*)(&src1[off]);
6942 const bm::bit_block_t::bunion_t* BMRESTRICT src_u2 = (const bm::bit_block_t::bunion_t*)(&src2[off]);
6943 const bm::bit_block_t::bunion_t* BMRESTRICT src_u3 = (const bm::bit_block_t::bunion_t*)(&src3[off]);
6945
6946 bm::id64_t acc = 0;
6947 unsigned j = 0;
6948 do
6949 {
6950 acc |= dst_u->w64[j + 0] &= src_u0->w64[j + 0] & src_u1->w64[j + 0] & src_u2->w64[j + 0] & src_u3->w64[j + 0];
6951 acc |= dst_u->w64[j + 1] &= src_u0->w64[j + 1] & src_u1->w64[j + 1] & src_u2->w64[j + 1] & src_u3->w64[j + 1];
6952 acc |= dst_u->w64[j + 2] &= src_u0->w64[j + 2] & src_u1->w64[j + 2] & src_u2->w64[j + 2] & src_u3->w64[j + 2];
6953 acc |= dst_u->w64[j + 3] &= src_u0->w64[j + 3] & src_u1->w64[j + 3] & src_u2->w64[j + 3] & src_u3->w64[j + 3];
6954 j += 4;
6955 } while (j < bm::set_block_digest_wave_size / 2);
6956
6957 if (!acc) // all zero
6958 digest &= ~(mask << wave);
6959#endif
6960
6961 d = bm::bmi_bslr_u64(d); // d &= d - 1;
6962 } // while
6963
6964 return digest;
6965}
6966
6967
6968/*!
6969 \brief digest based bit-block AND
6970
6971 dst = src1 AND src2
6972
6973 \param dst - destination block.
6974 \param src1 - source block.
6975 \param src2 - source block.
6976 \param digest - known initial digest
6977
6978 \return new digest
6979
6980 @ingroup bitfunc
6981*/
6982inline
6984 const bm::word_t* BMRESTRICT src1,
6985 const bm::word_t* BMRESTRICT src2,
6986 bm::id64_t digest) BMNOEXCEPT
6987{
6988 BM_ASSERT(dst);
6989 BM_ASSERT(src1 && src2);
6990 BM_ASSERT(dst != src1 && dst != src2);
6991
6992 const bm::id64_t mask(1ull);
6993 bm::id64_t d = digest;
6994 while (d)
6995 {
6996 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
6997
6998 unsigned wave = bm::word_bitcount64(t - 1);
6999 unsigned off = wave * bm::set_block_digest_wave_size;
7000
7001 #if defined(VECT_AND_DIGEST_2WAY)
7002 bool all_zero = VECT_AND_DIGEST_2WAY(&dst[off], &src1[off], &src2[off]);
7003 if (all_zero)
7004 digest &= ~(mask << wave);
7005 #else
7007 (const bm::bit_block_t::bunion_t*)(&src1[off]);
7009 (const bm::bit_block_t::bunion_t*)(&src2[off]);
7011 (bm::bit_block_t::bunion_t*)(&dst[off]);
7012
7013 bm::id64_t acc = 0;
7014 unsigned j = 0;
7015 do
7016 {
7017 acc |= dst_u->w64[j+0] = src_u1->w64[j+0] & src_u2->w64[j+0];
7018 acc |= dst_u->w64[j+1] = src_u1->w64[j+1] & src_u2->w64[j+1];
7019 acc |= dst_u->w64[j+2] = src_u1->w64[j+2] & src_u2->w64[j+2];
7020 acc |= dst_u->w64[j+3] = src_u1->w64[j+3] & src_u2->w64[j+3];
7021 j+=4;
7022 } while (j < bm::set_block_digest_wave_size/2);
7023
7024 if (!acc) // all zero
7025 digest &= ~(mask << wave);
7026 #endif
7027
7028 d = bm::bmi_bslr_u64(d); // d &= d - 1;
7029 } // while
7030
7031 return digest;
7032}
7033
7034
7035/*!
7036 \brief digest based bit-block AND - OR
7037
7038 dst =dst OR (src1 AND src2)
7039
7040 \param dst - destination block.
7041 \param src1 - source block.
7042 \param src2 - source block.
7043 \param digest - known initial digest
7044
7045 \return new digest (for the AND operation)
7046
7047 @ingroup bitfunc
7048*/
7049inline
7051 const bm::word_t* BMRESTRICT src1,
7052 const bm::word_t* BMRESTRICT src2,
7053 bm::id64_t digest) BMNOEXCEPT
7054{
7055 BM_ASSERT(dst);
7056 BM_ASSERT(src1 && src2);
7057 BM_ASSERT(dst != src1 && dst != src2);
7058
7059 const bm::id64_t mask(1ull);
7060 bm::id64_t d = digest;
7061 while (d)
7062 {
7063 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
7064
7065 unsigned wave = bm::word_bitcount64(t - 1);
7066 unsigned off = wave * bm::set_block_digest_wave_size;
7067
7068 #if defined(VECT_AND_OR_DIGEST_2WAY)
7069 bool all_zero =
7070 VECT_AND_OR_DIGEST_2WAY(&dst[off], &src1[off], &src2[off]);
7071 if (all_zero)
7072 digest &= ~(mask << wave);
7073 #else
7075 (const bm::bit_block_t::bunion_t*)(&src1[off]);
7077 (const bm::bit_block_t::bunion_t*)(&src2[off]);
7079 (bm::bit_block_t::bunion_t*)(&dst[off]);
7080
7081 bm::id64_t acc = 0;
7082 unsigned j = 0;
7083 do
7084 {
7085 acc |= dst_u->w64[j+0] |= src_u1->w64[j+0] & src_u2->w64[j+0];
7086 acc |= dst_u->w64[j+1] |= src_u1->w64[j+1] & src_u2->w64[j+1];
7087 acc |= dst_u->w64[j+2] |= src_u1->w64[j+2] & src_u2->w64[j+2];
7088 acc |= dst_u->w64[j+3] |= src_u1->w64[j+3] & src_u2->w64[j+3];
7089 j+=4;
7090 } while (j < bm::set_block_digest_wave_size/2);
7091
7092 if (!acc) // all zero
7093 digest &= ~(mask << wave);
7094 #endif
7095
7096 d = bm::bmi_bslr_u64(d); // d &= d - 1;
7097 } // while
7098
7099 return digest;
7100}
7101
7102
7103
7104/*!
7105 \brief Function ANDs two bitblocks and computes the bitcount.
7106 Function does not analyse availability of source blocks.
7107
7108 \param src1 - first bit block
7109 \param src2 - second bit block
7110
7111 @ingroup bitfunc
7112*/
7113inline
7115 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7116{
7117 unsigned count;
7118 const bm::word_t* src1_end = src1 + bm::set_block_size;
7119#ifdef BMVECTOPT
7120 count = VECT_BITCOUNT_AND(src1, src1_end, src2);
7121#else
7122 count = 0;
7123# ifdef BM64OPT
7124 const bm::id64_t* b1 = (bm::id64_t*) src1;
7125 const bm::id64_t* b1_end = (bm::id64_t*) src1_end;
7126 const bm::id64_t* b2 = (bm::id64_t*) src2;
7127 do
7128 {
7129 count += bm::bitcount64_4way(b1[0] & b2[0],
7130 b1[1] & b2[1],
7131 b1[2] & b2[2],
7132 b1[3] & b2[3]);
7133 b1 += 4; b2 += 4;
7134 } while (b1 < b1_end);
7135# else
7136 do
7137 {
7138 count +=
7139 bm::word_bitcount(src1[0] & src2[0]) +
7140 bm::word_bitcount(src1[1] & src2[1]) +
7141 bm::word_bitcount(src1[2] & src2[2]) +
7142 bm::word_bitcount(src1[3] & src2[3]);
7143 src1+=4; src2+=4;
7144 } while (src1 < src1_end);
7145# endif
7146#endif
7147 return count;
7148}
7149
7150
7151/*!
7152 \brief Function ANDs two bitblocks and tests for any bit.
7153 Function does not analyse availability of source blocks.
7154
7155 \param src1 - first bit block
7156 \param src2 - second bit block
7157
7158 @ingroup bitfunc
7159*/
7160inline
7161unsigned bit_block_and_any(const bm::word_t* src1,
7162 const bm::word_t* src2) BMNOEXCEPT
7163{
7164 unsigned count = 0;
7165 const bm::word_t* src1_end = src1 + bm::set_block_size;
7166 do
7167 {
7168 count = (src1[0] & src2[0]) |
7169 (src1[1] & src2[1]) |
7170 (src1[2] & src2[2]) |
7171 (src1[3] & src2[3]);
7172 src1+=4; src2+=4;
7173 } while ((src1 < src1_end) && !count);
7174 return count;
7175}
7176
7177
7178
7179
7180/*!
7181 \brief Function XORs two bitblocks and computes the bitcount.
7182 Function does not analyse availability of source blocks.
7183
7184 \param src1 - first bit block
7185 \param src2 - second bit block
7186
7187 @ingroup bitfunc
7188*/
7189inline
7191 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7192{
7193 unsigned count;
7194 const bm::word_t* BMRESTRICT src1_end = src1 + bm::set_block_size;
7195#ifdef BMVECTOPT
7196 count = VECT_BITCOUNT_XOR(src1, src1_end, src2);
7197#else
7198 count = 0;
7199# ifdef BM64OPT
7200 const bm::id64_t* b1 = (bm::id64_t*) src1;
7201 const bm::id64_t* b1_end = (bm::id64_t*) src1_end;
7202 const bm::id64_t* b2 = (bm::id64_t*) src2;
7203 do
7204 {
7205 count += bitcount64_4way(b1[0] ^ b2[0],
7206 b1[1] ^ b2[1],
7207 b1[2] ^ b2[2],
7208 b1[3] ^ b2[3]);
7209 b1 += 4;
7210 b2 += 4;
7211 } while (b1 < b1_end);
7212# else
7213 do
7214 {
7215 count +=
7216 bm::word_bitcount(src1[0] ^ src2[0]) +
7217 bm::word_bitcount(src1[1] ^ src2[1]) +
7218 bm::word_bitcount(src1[2] ^ src2[2]) +
7219 bm::word_bitcount(src1[3] ^ src2[3]);
7220 src1+=4; src2+=4;
7221 } while (src1 < src1_end);
7222# endif
7223#endif
7224 return count;
7225}
7226
7227
7228/*!
7229 \brief Function XORs two bitblocks and and tests for any bit.
7230 Function does not analyse availability of source blocks.
7231
7232 \param src1 - first bit block.
7233 \param src2 - second bit block.
7234
7235 @ingroup bitfunc
7236*/
7237inline
7239 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7240{
7241 unsigned count = 0;
7242 const bm::word_t* BMRESTRICT src1_end = src1 + bm::set_block_size;
7243 do
7244 {
7245 count = (src1[0] ^ src2[0]) |
7246 (src1[1] ^ src2[1]) |
7247 (src1[2] ^ src2[2]) |
7248 (src1[3] ^ src2[3]);
7249 src1+=4; src2+=4;
7250 } while (!count && (src1 < src1_end));
7251 return count;
7252}
7253
7254/*!
7255 \brief Function SUBs two bitblocks and computes the bitcount.
7256 Function does not analyse availability of source blocks.
7257
7258 \param src1 - first bit block.
7259 \param src2 - second bit block.
7260
7261 @ingroup bitfunc
7262*/
7263inline
7265 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7266{
7267 unsigned count;
7268 const bm::word_t* BMRESTRICT src1_end = src1 + bm::set_block_size;
7269#ifdef BMVECTOPT
7270 count = VECT_BITCOUNT_SUB(src1, src1_end, src2);
7271#else
7272 count = 0;
7273# ifdef BM64OPT
7274 const bm::id64_t* b1 = (bm::id64_t*) src1;
7275 const bm::id64_t* b1_end = (bm::id64_t*) src1_end;
7276 const bm::id64_t* b2 = (bm::id64_t*) src2;
7277 do
7278 {
7279 count += bitcount64_4way(b1[0] & ~b2[0],
7280 b1[1] & ~b2[1],
7281 b1[2] & ~b2[2],
7282 b1[3] & ~b2[3]);
7283 b1 += 4; b2 += 4;
7284 } while (b1 < b1_end);
7285# else
7286 do
7287 {
7288 count +=
7289 bm::word_bitcount(src1[0] & ~src2[0]) +
7290 bm::word_bitcount(src1[1] & ~src2[1]) +
7291 bm::word_bitcount(src1[2] & ~src2[2]) +
7292 bm::word_bitcount(src1[3] & ~src2[3]);
7293 src1+=4; src2+=4;
7294 } while (src1 < src1_end);
7295# endif
7296#endif
7297 return count;
7298}
7299
7300/*!
7301 \brief Function SUBs two bitblocks and and tests for any bit.
7302 Function does not analyse availability of source blocks.
7303
7304 \param src1 - first bit block.
7305 \param src2 - second bit block.
7306
7307 @ingroup bitfunc
7308*/
7309inline
7311 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7312{
7313 unsigned count = 0;
7314 const bm::word_t* BMRESTRICT src1_end = src1 + bm::set_block_size;
7315
7316 do
7317 {
7318 count = (src1[0] & ~~src2[0]) |
7319 (src1[1] & ~src2[1]) |
7320 (src1[2] & ~~src2[2]) |
7321 (src1[3] & ~src2[3]);
7322 src1+=4; src2+=4;
7323 } while ((src1 < src1_end) && (count == 0));
7324 return count;
7325}
7326
7327
7328/*!
7329 \brief Function ORs two bitblocks and computes the bitcount.
7330 Function does not analyse availability of source blocks.
7331
7332 \param src1 - first bit block
7333 \param src2 - second bit block.
7334
7335 @ingroup bitfunc
7336*/
7337inline
7338unsigned bit_block_or_count(const bm::word_t* src1,
7339 const bm::word_t* src2) BMNOEXCEPT
7340{
7341 unsigned count;
7342 const bm::word_t* src1_end = src1 + bm::set_block_size;
7343#ifdef BMVECTOPT
7344 count = VECT_BITCOUNT_OR(src1, src1_end, src2);
7345#else
7346 count = 0;
7347# ifdef BM64OPT
7348 const bm::id64_t* b1 = (bm::id64_t*) src1;
7349 const bm::id64_t* b1_end = (bm::id64_t*) src1_end;
7350 const bm::id64_t* b2 = (bm::id64_t*) src2;
7351 do
7352 {
7353 count += bitcount64_4way(b1[0] | b2[0],
7354 b1[1] | b2[1],
7355 b1[2] | b2[2],
7356 b1[3] | b2[3]);
7357 b1 += 4;
7358 b2 += 4;
7359 } while (b1 < b1_end);
7360# else
7361 do
7362 {
7363 count +=
7364 bm::word_bitcount(src1[0] | src2[0]) +
7365 bm::word_bitcount(src1[1] | src2[1]) +
7366 bm::word_bitcount(src1[2] | src2[2]) +
7367 bm::word_bitcount(src1[3] | src2[3]);
7368 src1+=4; src2+=4;
7369 } while (src1 < src1_end);
7370# endif
7371#endif
7372 return count;
7373}
7374
7375/*!
7376 \brief Function ORs two bitblocks and and tests for any bit.
7377 Function does not analyse availability of source blocks.
7378
7379 \param src1 - first bit block.
7380 \param src2 - second bit block.
7381
7382 @ingroup bitfunc
7383*/
7384inline
7386 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7387{
7388 unsigned count = 0;
7389 const bm::word_t* BMRESTRICT src1_end = src1 + bm::set_block_size;
7390 do
7391 {
7392 count = (src1[0] | src2[0]) |
7393 (src1[1] | src2[1]) |
7394 (src1[2] | src2[2]) |
7395 (src1[3] | src2[3]);
7396
7397 src1+=4; src2+=4;
7398 } while (!count && (src1 < src1_end));
7399 return count;
7400}
7401
7402
7403
7404
7405/*!
7406 \brief bitblock AND operation.
7407
7408 \param dst - destination block.
7409 \param src - source block.
7410
7411 \returns pointer on destination block.
7412 If returned value equal to src means that block mutation requested.
7413 NULL is valid return value.
7414
7415 @ingroup bitfunc
7416*/
7417inline
7419 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
7420{
7421 BM_ASSERT(dst || src);
7422 bm::word_t* ret = dst;
7423 if (IS_VALID_ADDR(dst)) // The destination block already exists
7424 {
7425 if (!IS_VALID_ADDR(src))
7426 {
7427 if (IS_EMPTY_BLOCK(src))
7428 return 0; //just clean the destination block
7429 }
7430 else
7431 {
7432 if (!bm::bit_block_and(dst, src))
7433 ret = 0;
7434 }
7435 }
7436 else // The destination block does not exist yet
7437 {
7438 if(!IS_VALID_ADDR(src))
7439 {
7440 if(IS_EMPTY_BLOCK(src))
7441 return 0; // One argument empty - all result is empty.
7442 // Src block is all ON, dst block remains as it is. nothing to do.
7443 }
7444 else // destination block does not exists, src - valid block
7445 {
7446 if (IS_FULL_BLOCK(dst))
7447 return const_cast<bm::word_t*>(src);
7448 // Dst block is all ZERO no combination required. Nothng to do.
7449 }
7450 }
7451 return ret;
7452}
7453
7454
7455/*!
7456 \brief Performs bitblock AND operation and calculates bitcount of the result.
7457
7458 \param src1 - first bit block.
7459 \param src2 - second bit block.
7460
7461 \returns bitcount value
7462
7463 @ingroup bitfunc
7464*/
7465inline
7467 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7468{
7469 if (IS_EMPTY_BLOCK(src1) || IS_EMPTY_BLOCK(src2))
7470 return 0;
7471 if (src1 == FULL_BLOCK_FAKE_ADDR)
7472 src1 = FULL_BLOCK_REAL_ADDR;
7473 if (src2 == FULL_BLOCK_FAKE_ADDR)
7474 src2 = FULL_BLOCK_REAL_ADDR;
7475
7476 return bit_block_and_count(src1, src2);
7477}
7478
7479/*!
7480 \brief Performs bitblock AND operation test.
7481
7482 \param src1 - first bit block.
7483 \param src2 - second bit block.
7484
7485 \returns non zero if there is any value
7486
7487 @ingroup bitfunc
7488*/
7489inline
7491 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7492{
7493 if (IS_EMPTY_BLOCK(src1) || IS_EMPTY_BLOCK(src2))
7494 return 0;
7495 if (src1 == FULL_BLOCK_FAKE_ADDR)
7496 src1 = FULL_BLOCK_REAL_ADDR;
7497 if (src2 == FULL_BLOCK_FAKE_ADDR)
7498 src2 = FULL_BLOCK_REAL_ADDR;
7499 return bit_block_and_any(src1, src2);
7500}
7501
7502
7503
7504/*!
7505 \brief Performs bitblock SUB operation and calculates bitcount of the result.
7506
7507 \param src1 - first bit block.
7508 \param src2 - second bit block
7509
7510 \returns bitcount value
7511
7512 @ingroup bitfunc
7513*/
7514inline
7516 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7517{
7518 if (src1 == src2)
7519 return 0;
7520 if (IS_EMPTY_BLOCK(src1))
7521 return 0;
7522 if (IS_EMPTY_BLOCK(src2)) // nothing to diff
7523 {
7524 if (IS_FULL_BLOCK(src1))
7525 return bm::gap_max_bits;
7526 return bm::bit_block_count(src1);
7527 }
7528 if (IS_FULL_BLOCK(src2))
7529 return 0;
7530
7531 if (src1 == FULL_BLOCK_FAKE_ADDR)
7532 src1 = FULL_BLOCK_REAL_ADDR;
7533 if (src2 == FULL_BLOCK_FAKE_ADDR)
7534 src2 = FULL_BLOCK_REAL_ADDR;
7535
7536 return bm::bit_block_sub_count(src1, src2);
7537}
7538
7539
7540/*!
7541 \brief Performs inverted bitblock SUB operation and calculates
7542 bitcount of the result.
7543
7544 \param src1 - first bit block.
7545 \param src2 - second bit block
7546
7547 \returns bitcount value
7548
7549 @ingroup bitfunc
7550*/
7551inline
7553 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7554{
7555 return bit_operation_sub_count(src2, src1);
7556}
7557
7558
7559/*!
7560 \brief Performs bitblock test of SUB operation.
7561
7562 \param src1 - first bit block.
7563 \param src2 - second bit block
7564
7565 \returns non zero value if there are any bits
7566
7567 @ingroup bitfunc
7568*/
7569inline
7571 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7572{
7573 if (IS_EMPTY_BLOCK(src1))
7574 return 0;
7575 if (src1 == src2)
7576 return 0;
7577
7578 if (IS_EMPTY_BLOCK(src2)) // nothing to diff
7579 return !bit_is_all_zero(src1);
7580
7581 if (IS_FULL_BLOCK(src2))
7582 return 0;
7583
7584 if (src1 == FULL_BLOCK_FAKE_ADDR)
7585 src1 = FULL_BLOCK_REAL_ADDR;
7586 if (src2 == FULL_BLOCK_FAKE_ADDR)
7587 src2 = FULL_BLOCK_REAL_ADDR;
7588
7589 return bm::bit_block_sub_any(src1, src2);
7590}
7591
7592
7593
7594/*!
7595 \brief Performs bitblock OR operation and calculates bitcount of the result.
7596
7597 \param src1 - first bit block.
7598 \param src2 - second bit block.
7599
7600 \returns bitcount value
7601
7602 @ingroup bitfunc
7603*/
7604inline
7606 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7607{
7608 if (IS_FULL_BLOCK(src1) || IS_FULL_BLOCK(src2))
7609 return bm::gap_max_bits;
7610
7611 if (IS_EMPTY_BLOCK(src1))
7612 {
7613 if (!IS_EMPTY_BLOCK(src2))
7614 return bm::bit_block_count(src2);
7615 else
7616 return 0; // both blocks are empty
7617 }
7618 else
7619 {
7620 if (IS_EMPTY_BLOCK(src2))
7621 return bm::bit_block_count(src1);
7622 }
7623 if (src1 == FULL_BLOCK_FAKE_ADDR)
7624 src1 = FULL_BLOCK_REAL_ADDR;
7625 if (src2 == FULL_BLOCK_FAKE_ADDR)
7626 src2 = FULL_BLOCK_REAL_ADDR;
7627
7628 return bm::bit_block_or_count(src1, src2);
7629}
7630
7631/*!
7632 \brief Performs bitblock OR operation test.
7633
7634 \param src1 - first bit block.
7635 \param src2 - second bit block.
7636
7637 \returns non zero value if there are any bits
7638
7639 @ingroup bitfunc
7640*/
7641inline
7643 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7644{
7645 if (IS_EMPTY_BLOCK(src1))
7646 {
7647 if (!IS_EMPTY_BLOCK(src2))
7648 return !bit_is_all_zero(src2);
7649 else
7650 return 0; // both blocks are empty
7651 }
7652 else
7653 {
7654 if (IS_EMPTY_BLOCK(src2))
7655 return !bit_is_all_zero(src1);
7656 }
7657 if (src1 == FULL_BLOCK_FAKE_ADDR)
7658 src1 = FULL_BLOCK_REAL_ADDR;
7659 if (src2 == FULL_BLOCK_FAKE_ADDR)
7660 src2 = FULL_BLOCK_REAL_ADDR;
7661
7662 return bit_block_or_any(src1, src2);
7663}
7664
7665/*!
7666 \brief Plain bitblock OR operation.
7667 Function does not analyse availability of source and destination blocks.
7668
7669 \param dst - destination block.
7670 \param src - source block.
7671
7672 @ingroup bitfunc
7673*/
7674inline
7676 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
7677{
7678#ifdef BMVECTOPT
7679 return VECT_OR_BLOCK(dst, src);
7680#else
7681 const bm::wordop_t* BMRESTRICT wrd_ptr = (wordop_t*)src;
7682 const bm::wordop_t* BMRESTRICT wrd_end = (wordop_t*)(src + bm::set_block_size);
7683 bm::wordop_t* BMRESTRICT dst_ptr = (wordop_t*)dst;
7684
7685 bm::wordop_t acc = 0;
7686 const bm::wordop_t not_acc = acc = ~~acc;
7687
7688 do
7689 {
7690 acc &= (dst_ptr[0] |= wrd_ptr[0]);
7691 acc &= (dst_ptr[1] |= wrd_ptr[1]);
7692 acc &= (dst_ptr[2] |= wrd_ptr[2]);
7693 acc &= (dst_ptr[3] |= wrd_ptr[3]);
7694
7695 dst_ptr+=4;wrd_ptr+=4;
7696
7697 } while (wrd_ptr < wrd_end);
7698 return acc == not_acc;
7699#endif
7700}
7701
7702/*!
7703 \brief 2 way (target := source1 | source2) bitblock OR operation.
7704 \param dst - dest block [out]
7705 \param src1 - source 1
7706 \param src2 - source 2
7707
7708 @return 1 if produced block of ALL ones
7709 @ingroup bitfunc
7710*/
7711inline
7713 const bm::word_t* BMRESTRICT src1,
7714 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7715{
7716#ifdef BMVECTOPT
7717 return VECT_OR_BLOCK_2WAY(dst, src1, src2);
7718#else
7719 const bm::wordop_t* BMRESTRICT wrd_ptr1 = (wordop_t*)src1;
7720 const bm::wordop_t* BMRESTRICT wrd_end1 = (wordop_t*)(src1 + set_block_size);
7721 const bm::wordop_t* BMRESTRICT wrd_ptr2 = (wordop_t*)src2;
7722 bm::wordop_t* BMRESTRICT dst_ptr = (wordop_t*)dst;
7723
7724 bm::wordop_t acc = 0;
7725 const bm::wordop_t not_acc = acc = ~~acc;
7726 do
7727 {
7728 acc &= (dst_ptr[0] = wrd_ptr1[0] | wrd_ptr2[0]);
7729 acc &= (dst_ptr[1] = wrd_ptr1[1] | wrd_ptr2[1]);
7730 acc &= (dst_ptr[2] = wrd_ptr1[2] | wrd_ptr2[2]);
7731 acc &= (dst_ptr[3] = wrd_ptr1[3] | wrd_ptr2[3]);
7732
7733 dst_ptr+=4; wrd_ptr1+=4; wrd_ptr2+=4;
7734
7735 } while (wrd_ptr1 < wrd_end1);
7736 return acc == not_acc;
7737#endif
7738}
7739
7740
7741/*!
7742 \brief 2 way (target := source1 ^ source2) bitblock XOR operation.
7743 \param dst - dest block [out]
7744 \param src1 - source 1
7745 \param src2 - source 2
7746
7747 @return OR accumulator
7748 @ingroup bitfunc
7749*/
7750inline
7752 const bm::word_t* BMRESTRICT src1,
7753 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7754{
7755#ifdef BMVECTOPT
7756 return VECT_XOR_BLOCK_2WAY(dst, src1, src2);
7757#else
7758 const bm::wordop_t* BMRESTRICT wrd_ptr1 = (wordop_t*)src1;
7759 const bm::wordop_t* BMRESTRICT wrd_end1 = (wordop_t*)(src1 + set_block_size);
7760 const bm::wordop_t* BMRESTRICT wrd_ptr2 = (wordop_t*)src2;
7761 bm::wordop_t* BMRESTRICT dst_ptr = (wordop_t*)dst;
7762
7763 bm::wordop_t acc = 0;
7764 do
7765 {
7766 acc |= (dst_ptr[0] = wrd_ptr1[0] ^ wrd_ptr2[0]);
7767 acc |= (dst_ptr[1] = wrd_ptr1[1] ^ wrd_ptr2[1]);
7768 acc |= (dst_ptr[2] = wrd_ptr1[2] ^ wrd_ptr2[2]);
7769 acc |= (dst_ptr[3] = wrd_ptr1[3] ^ wrd_ptr2[3]);
7770
7771 dst_ptr+=4; wrd_ptr1+=4; wrd_ptr2+=4;
7772
7773 } while (wrd_ptr1 < wrd_end1);
7774 return acc;
7775#endif
7776}
7777
7778
7779/*!
7780 \brief 3 way (target | source1 | source2) bitblock OR operation.
7781 Function does not analyse availability of source and destination blocks.
7782
7783 \param dst - sst-dest block [in,out]
7784 \param src1 - source 1
7785 \param src2 - source 2
7786
7787 @return 1 if produced block of ALL ones
7788
7789 @ingroup bitfunc
7790*/
7791inline
7793 const bm::word_t* BMRESTRICT src1,
7794 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
7795{
7796#ifdef BMVECTOPT
7797 return VECT_OR_BLOCK_3WAY(dst, src1, src2);
7798#else
7799 const bm::wordop_t* BMRESTRICT wrd_ptr1 = (wordop_t*)src1;
7800 const bm::wordop_t* BMRESTRICT wrd_end1 = (wordop_t*)(src1 + set_block_size);
7801 const bm::wordop_t* BMRESTRICT wrd_ptr2 = (wordop_t*)src2;
7802 bm::wordop_t* BMRESTRICT dst_ptr = (wordop_t*)dst;
7803
7804 bm::wordop_t acc = 0;
7805 const bm::wordop_t not_acc = acc = ~~acc;
7806 do
7807 {
7808 acc &= (dst_ptr[0] |= wrd_ptr1[0] | wrd_ptr2[0]);
7809 acc &= (dst_ptr[1] |= wrd_ptr1[1] | wrd_ptr2[1]);
7810 acc &= (dst_ptr[2] |= wrd_ptr1[2] | wrd_ptr2[2]);
7811 acc &= (dst_ptr[3] |= wrd_ptr1[3] | wrd_ptr2[3]);
7812
7813 dst_ptr+=4; wrd_ptr1+=4;wrd_ptr2+=4;
7814
7815 } while (wrd_ptr1 < wrd_end1);
7816 return acc == not_acc;
7817#endif
7818}
7819
7820
7821/*!
7822 \brief 5 way (target, source1, source2) bitblock OR operation.
7823 Function does not analyse availability of source and destination blocks.
7824
7825 \param dst - destination block.
7826 \param src1 - source1, etc
7827 \param src2 - source1, etc
7828 \param src3 - source1, etc
7829 \param src4 - source1, etc
7830
7831 @return 1 if produced block of ALL ones
7832
7833 @ingroup bitfunc
7834*/
7835inline
7837 const bm::word_t* BMRESTRICT src1,
7838 const bm::word_t* BMRESTRICT src2,
7839 const bm::word_t* BMRESTRICT src3,
7840 const bm::word_t* BMRESTRICT src4) BMNOEXCEPT
7841{
7842#ifdef BMVECTOPT
7843 return VECT_OR_BLOCK_5WAY(dst, src1, src2, src3, src4);
7844#else
7845 const bm::wordop_t* BMRESTRICT wrd_ptr1 = (wordop_t*)src1;
7846 const bm::wordop_t* BMRESTRICT wrd_end1 = (wordop_t*)(src1 + set_block_size);
7847 const bm::wordop_t* BMRESTRICT wrd_ptr2 = (wordop_t*)src2;
7848 const bm::wordop_t* BMRESTRICT wrd_ptr3 = (wordop_t*)src3;
7849 const bm::wordop_t* BMRESTRICT wrd_ptr4 = (wordop_t*)src4;
7850 bm::wordop_t* BMRESTRICT dst_ptr = (wordop_t*)dst;
7851
7852 bm::wordop_t acc = 0;
7853 const bm::wordop_t not_acc = acc = ~~acc;
7854 do
7855 {
7856 acc &= (dst_ptr[0] |= wrd_ptr1[0] | wrd_ptr2[0] | wrd_ptr3[0] | wrd_ptr4[0]);
7857 acc &= (dst_ptr[1] |= wrd_ptr1[1] | wrd_ptr2[1] | wrd_ptr3[1] | wrd_ptr4[1]);
7858 acc &= (dst_ptr[2] |= wrd_ptr1[2] | wrd_ptr2[2] | wrd_ptr3[2] | wrd_ptr4[2]);
7859 acc &= (dst_ptr[3] |= wrd_ptr1[3] | wrd_ptr2[3] | wrd_ptr3[3] | wrd_ptr4[3]);
7860
7861 dst_ptr+=4;
7862 wrd_ptr1+=4;wrd_ptr2+=4;wrd_ptr3+=4;wrd_ptr4+=4;
7863
7864 } while (wrd_ptr1 < wrd_end1);
7865 return acc == not_acc;
7866#endif
7867}
7868
7869
7870
7871
7872/*!
7873 \brief Block OR operation. Makes analysis if block is 0 or FULL.
7874
7875 \param dst - destination block.
7876 \param src - source block.
7877
7878 \returns pointer on destination block.
7879 If returned value equal to src means that block mutation requested.
7880 NULL is valid return value.
7881
7882 @ingroup bitfunc
7883*/
7884inline
7886 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
7887{
7888 BM_ASSERT(dst || src);
7889
7890 bm::word_t* ret = dst;
7891
7892 if (IS_VALID_ADDR(dst)) // The destination block already exists
7893 {
7894 if (!IS_VALID_ADDR(src))
7895 {
7896 if (IS_FULL_BLOCK(src))
7897 {
7898 // if the source block is all set
7899 // just set the destination block
7900 ::memset(dst, 0xFF, bm::set_block_size * sizeof(bm::word_t));
7901 }
7902 }
7903 else
7904 {
7905 // Regular operation OR on the whole block
7906 bm::bit_block_or(dst, src);
7907 }
7908 }
7909 else // The destination block does not exist yet
7910 {
7911 if (!IS_VALID_ADDR(src))
7912 {
7913 if (IS_FULL_BLOCK(src))
7914 {
7915 // The source block is all set, because dst does not exist
7916 // we can simply replace it.
7917 return const_cast<bm::word_t*>(FULL_BLOCK_FAKE_ADDR);
7918 }
7919 }
7920 else
7921 {
7922 if (dst == 0)
7923 {
7924 // The only case when we have to allocate the new block:
7925 // Src is all zero and Dst does not exist
7926 return const_cast<bm::word_t*>(src);
7927 }
7928 }
7929 }
7930 return ret;
7931}
7932
7933/*!
7934 \brief Plain bitblock SUB (AND NOT) operation.
7935 Function does not analyse availability of source and destination blocks.
7936
7937 \param dst - destination block.
7938 \param src - source block.
7939
7940 \return 0 if SUB operation did not produce anything (no 1s in the output)
7941
7942 @ingroup bitfunc
7943*/
7944inline
7946 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
7947{
7948#ifdef BMVECTOPT
7949 bm::id64_t acc = VECT_SUB_BLOCK(dst, src);
7950 return acc;
7951#else
7952 unsigned arr_sz = bm::set_block_size / 2;
7953
7956
7957 bm::id64_t acc = 0;
7958 for (unsigned i = 0; i < arr_sz; i+=4)
7959 {
7960 acc |= (dst_u->w64[i] &= ~~src_u->w64[i]) |
7961 (dst_u->w64[i+1] &= ~src_u->w64[i+1]) |
7962 (dst_u->w64[i+2] &= ~~src_u->w64[i+2]) |
7963 (dst_u->w64[i+3] &= ~src_u->w64[i+3]);
7964 }
7965 return acc;
7966#endif
7967}
7968
7969/*!
7970 \brief digest based bitblock SUB (AND NOT) operation
7971
7972 \param dst - destination block.
7973 \param src - source block.
7974 \param digest - known digest of dst block
7975
7976 \return new digest
7977
7978 @ingroup bitfunc
7979*/
7980inline
7982 const bm::word_t* BMRESTRICT src,
7983 bm::id64_t digest) BMNOEXCEPT
7984{
7985 BM_ASSERT(dst);
7986 BM_ASSERT(src);
7987 BM_ASSERT(dst != src);
7988
7989 const bm::id64_t mask(1ull);
7990
7991 bm::id64_t d = digest;
7992 while (d)
7993 {
7994 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
7995
7996 unsigned wave = bm::word_bitcount64(t - 1);
7997 unsigned off = wave * bm::set_block_digest_wave_size;
7998
7999 #if defined(VECT_SUB_DIGEST)
8000 bool all_zero = VECT_SUB_DIGEST(&dst[off], &src[off]);
8001 if (all_zero)
8002 digest &= ~(mask << wave);
8003 #else
8004 const bm::bit_block_t::bunion_t* BMRESTRICT src_u = (const bm::bit_block_t::bunion_t*)(&src[off]);
8006
8007 bm::id64_t acc = 0;
8008 unsigned j = 0;
8009 do
8010 {
8011 acc |= dst_u->w64[j+0] &= ~~src_u->w64[j+0];
8012 acc |= dst_u->w64[j+1] &= ~~src_u->w64[j+1];
8013 acc |= dst_u->w64[j+2] &= ~~src_u->w64[j+2];
8014 acc |= dst_u->w64[j+3] &= ~~src_u->w64[j+3];
8015 j+=4;
8016 } while (j < bm::set_block_digest_wave_size/2);
8017
8018 if (!acc) // all zero
8019 digest &= ~(mask << wave);
8020 #endif
8021
8022 d = bm::bmi_bslr_u64(d); // d &= d - 1;
8023 } // while
8024
8025 return digest;
8026}
8027
8028/*!
8029 \brief digest based bitblock SUB (AND NOT) operation (3 operand)
8030
8031 \param dst - destination block.
8032 \param src1 - source block 1
8033 \param src2 - source block 2
8034 \param digest - known digest of dst block
8035
8036 \return new digest
8037
8038 @ingroup bitfunc
8039*/
8040inline
8042 const bm::word_t* BMRESTRICT src1,
8043 const bm::word_t* BMRESTRICT src2,
8044 bm::id64_t digest) BMNOEXCEPT
8045{
8046 BM_ASSERT(dst);
8047 BM_ASSERT(src1 && src2);
8048 BM_ASSERT(dst != src1 && dst != src2);
8049
8050 const bm::id64_t mask(1ull);
8051
8052 bm::id64_t d = digest;
8053 while (d)
8054 {
8055 bm::id64_t t = bm::bmi_blsi_u64(d); // d & -d;
8056
8057 unsigned wave = bm::word_bitcount64(t - 1);
8058 unsigned off = wave * bm::set_block_digest_wave_size;
8059
8060 #if defined(VECT_SUB_DIGEST_2WAY)
8061 bool all_zero = VECT_SUB_DIGEST_2WAY(&dst[off], &src1[off], &src2[off]);
8062 if (all_zero)
8063 digest &= ~(mask << wave);
8064 #else
8066 (const bm::bit_block_t::bunion_t*)(&src1[off]);
8068 (const bm::bit_block_t::bunion_t*)(&src2[off]);
8070 (bm::bit_block_t::bunion_t*)(&dst[off]);
8071
8072 bm::id64_t acc = 0;
8073 unsigned j = 0;
8074 do
8075 {
8076 acc |= dst_u->w64[j+0] = src_u1->w64[j+0] & ~~src_u2->w64[j+0];
8077 acc |= dst_u->w64[j+1] = src_u1->w64[j+1] & ~~src_u2->w64[j+1];
8078 acc |= dst_u->w64[j+2] = src_u1->w64[j+2] & ~~src_u2->w64[j+2];
8079 acc |= dst_u->w64[j+3] = src_u1->w64[j+3] & ~~src_u2->w64[j+3];
8080 j+=4;
8081 } while (j < bm::set_block_digest_wave_size/2);
8082
8083 if (!acc) // all zero
8084 digest &= ~(mask << wave);
8085 #endif
8086
8087 d = bm::bmi_bslr_u64(d); // d &= d - 1;
8088 } // while
8089
8090 return digest;
8091}
8092
8093
8094
8095/*!
8096 \brief bitblock SUB operation.
8097
8098 \param dst - destination block.
8099 \param src - source block.
8100
8101 \returns pointer on destination block.
8102 If returned value equal to src means that block mutation requested.
8103 NULL is valid return value.
8104
8105 @ingroup bitfunc
8106*/
8107inline
8109 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
8110{
8111 BM_ASSERT(dst || src);
8112
8113 bm::word_t* ret = dst;
8114 if (IS_VALID_ADDR(dst)) // The destination block already exists
8115 {
8116 if (!IS_VALID_ADDR(src))
8117 {
8118 if (IS_FULL_BLOCK(src))
8119 {
8120 // If the source block is all set
8121 // just clean the destination block
8122 return 0;
8123 }
8124 }
8125 else
8126 {
8127 auto any = bm::bit_block_sub(dst, src);
8128 if (!any)
8129 ret = 0;
8130 }
8131 }
8132 else // The destination block does not exist yet
8133 {
8134 if (!IS_VALID_ADDR(src))
8135 {
8136 if (IS_FULL_BLOCK(src))
8137 {
8138 // The source block is full
8139 return 0;
8140 }
8141 }
8142 else
8143 {
8144 if (IS_FULL_BLOCK(dst))
8145 {
8146 // The only case when we have to allocate the new block:
8147 // dst is all set and src exists
8148 return const_cast<bm::word_t*>(src);
8149 }
8150 }
8151 }
8152 return ret;
8153}
8154
8155
8156/*!
8157 \brief Plain bitblock XOR operation.
8158 Function does not analyse availability of source and destination blocks.
8159
8160 \param dst - destination block.
8161 \param src - source block.
8162
8163 @ingroup bitfunc
8164*/
8165inline
8167 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
8168{
8169 BM_ASSERT(dst);
8170 BM_ASSERT(src);
8171 BM_ASSERT(dst != src);
8172
8173#ifdef BMVECTOPT
8174 bm::id64_t acc = VECT_XOR_BLOCK(dst, src);
8175#else
8176 unsigned arr_sz = bm::set_block_size / 2;
8177
8180
8181 bm::id64_t acc = 0;
8182 for (unsigned i = 0; i < arr_sz; i+=4)
8183 {
8184 acc |= dst_u->w64[i] ^= src_u->w64[i];
8185 acc |= dst_u->w64[i+1] ^= src_u->w64[i+1];
8186 acc |= dst_u->w64[i+2] ^= src_u->w64[i+2];
8187 acc |= dst_u->w64[i+3] ^= src_u->w64[i+3];
8188 }
8189#endif
8190 return acc;
8191}
8192
8193/*!
8194 \brief bitblock AND NOT with constant ~0 mask operation.
8195
8196 \param dst - destination block.
8197 \param src - source block.
8198
8199 @ingroup bitfunc
8200*/
8201inline
8203 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
8204{
8205 const bm::word_t* BMRESTRICT src_end = src + bm::set_block_size;
8206#ifdef BMVECTOPT
8207 VECT_ANDNOT_ARR_2_MASK(dst, src, src_end, ~0u);
8208#else
8209 bm::wordop_t* dst_ptr = (wordop_t*)dst;
8210 const bm::wordop_t* wrd_ptr = (wordop_t*) src;
8211 const bm::wordop_t* wrd_end = (wordop_t*) src_end;
8212
8213 do
8214 {
8215 dst_ptr[0] = bm::all_bits_mask & ~~wrd_ptr[0];
8216 dst_ptr[1] = bm::all_bits_mask & ~~wrd_ptr[1];
8217 dst_ptr[2] = bm::all_bits_mask & ~~wrd_ptr[2];
8218 dst_ptr[3] = bm::all_bits_mask & ~~wrd_ptr[3];
8219 dst_ptr+=4; wrd_ptr+=4;
8220 } while (wrd_ptr < wrd_end);
8221#endif
8222}
8223
8224/*!
8225 \brief bitblock XOR operation.
8226
8227 \param dst - destination block.
8228 \param src - source block.
8229
8230 \returns pointer on destination block.
8231 If returned value equal to src means that block mutation requested.
8232 NULL is valid return value.
8233
8234 @ingroup bitfunc
8235*/
8236inline
8238 const bm::word_t* BMRESTRICT src) BMNOEXCEPT
8239{
8240 BM_ASSERT(dst || src);
8241 if (src == dst) return 0; // XOR rule
8242
8243 bm::word_t* ret = dst;
8244
8245 if (IS_VALID_ADDR(dst)) // The destination block already exists
8246 {
8247 if (!src) return dst;
8248
8249 bit_block_xor(dst, src);
8250 }
8251 else // The destination block does not exist yet
8252 {
8253 if (!src) return dst; // 1 xor 0 = 1
8254
8255 // Here we have two cases:
8256 // if dest block is full or zero if zero we need to copy the source
8257 // otherwise XOR loop against 0xFF...
8258 //BM_ASSERT(dst == 0);
8259 return const_cast<bm::word_t*>(src); // src is the final result
8260 }
8261 return ret;
8262}
8263
8264/*!
8265 \brief Performs bitblock XOR operation and calculates bitcount of the result.
8266
8267 \param src1 - bit block start ptr
8268 \param src2 - second bit block
8269
8270 \returns bitcount value
8271
8272 @ingroup bitfunc
8273*/
8274inline
8276 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
8277{
8278 if (src1 == src2)
8279 return 0;
8280
8281 if (IS_EMPTY_BLOCK(src1) || IS_EMPTY_BLOCK(src2))
8282 {
8283 const bm::word_t* block = IS_EMPTY_BLOCK(src1) ? src2 : src1;
8284 if (IS_FULL_BLOCK(block))
8285 return bm::gap_max_bits;
8286 return bm::bit_block_count(block);
8287 }
8288 if (src1 == FULL_BLOCK_FAKE_ADDR)
8289 src1 = FULL_BLOCK_REAL_ADDR;
8290 if (src2 == FULL_BLOCK_FAKE_ADDR)
8291 src2 = FULL_BLOCK_REAL_ADDR;
8292
8293 return bit_block_xor_count(src1, src2);
8294}
8295
8296/*!
8297 \brief Performs bitblock XOR operation test.
8298
8299 \param src1 - bit block start ptr
8300 \param src2 - second bit block ptr
8301
8302 \returns non zero value if there are bits
8303
8304 @ingroup bitfunc
8305*/
8306inline
8308 const bm::word_t* BMRESTRICT src2) BMNOEXCEPT
8309{
8310 if (src1 == src2)
8311 return 0;
8312 if (IS_EMPTY_BLOCK(src1) || IS_EMPTY_BLOCK(src2))
8313 {
8314 const bm::word_t* block = IS_EMPTY_BLOCK(src1) ? src2 : src1;
8315 return !bit_is_all_zero(block);
8316 }
8317 return bm::bit_block_xor_any(src1, src2);
8318}
8319
8320
8321
8322/**
8323 \brief Inspects block for full zero words
8324
8325 \param blk - bit block pointer
8326 \param data_size - data size
8327
8328 \return size of all non-zero words
8329
8330 @ingroup bitfunc
8331*/
8332template<class T>
8333unsigned bit_count_nonzero_size(const T* blk, unsigned data_size) BMNOEXCEPT
8334{
8335 BM_ASSERT(blk && data_size);
8336 unsigned count = 0;
8337 const T* blk_end = blk + data_size - 2;
8338 do
8339 {
8340 if (*blk == 0) // scan fwd to find 0 island length
8341 {
8342 const T* blk_j = blk + 1;
8343 for (; blk_j < blk_end; ++blk_j)
8344 {
8345 if (*blk_j != 0)
8346 break;
8347 } // for
8348 blk = blk_j-1;
8349 count += (unsigned)sizeof(gap_word_t);
8350 }
8351 else
8352 {
8353 const T* blk_j = blk + 1; // scan fwd to find non-0 island len
8354 for ( ; blk_j < blk_end; ++blk_j)
8355 {
8356 if (*blk_j == 0)
8357 {
8358 if (blk_j[1] | blk_j[2]) // look ahead, ignore short 0-run
8359 {
8360 ++blk_j; // skip zero word
8361 continue;
8362 }
8363 break;
8364 }
8365 } // for
8366 count += unsigned(sizeof(gap_word_t));
8367 // count all bit-words now
8368 count += unsigned(blk_j - blk) * unsigned(sizeof(T));
8369 blk = blk_j;
8370 }
8371 ++blk;
8372 }
8373 while(blk < blk_end);
8374 return count + unsigned(2 * sizeof(T));
8375}
8376
8377
8378/**
8379 \brief Searches for the next 1 bit in the BIT block
8380 \param block - BIT buffer
8381 \param nbit - bit index to start checking from
8382 \param pos - [out] found value
8383
8384 \return 0 if not found
8385
8386 @ingroup bitfunc
8387*/
8388inline
8390 unsigned nbit, unsigned* BMRESTRICT pos) BMNOEXCEPT
8391{
8392 BM_ASSERT(block);
8393 BM_ASSERT(pos);
8394
8395 unsigned nword = unsigned(nbit >> bm::set_word_shift);
8396 unsigned bit_pos = (nbit & bm::set_word_mask);
8397
8398 bm::word_t w = block[nword];
8399 w &= (1u << bit_pos);
8400 if (w)
8401 {
8402 *pos = nbit;
8403 return 1;
8404 }
8405 w = block[nword] >> bit_pos;
8406 w <<= bit_pos; // clear the trailing bits
8407 if (w)
8408 {
8409 bit_pos = bm::bit_scan_forward32(w); // trailing zeros
8410 *pos = unsigned(bit_pos + (nword * 8u * unsigned(sizeof(bm::word_t))));
8411 return 1;
8412 }
8413
8414 for (unsigned i = nword+1; i < bm::set_block_size; ++i)
8415 {
8416 w = block[i];
8417 if (w)
8418 {
8419 bit_pos = bm::bit_scan_forward32(w); // trailing zeros
8420 *pos = unsigned(bit_pos + (i * 8u * unsigned(sizeof(bm::word_t))));
8421 return w;
8422 }
8423 } // for i
8424 return 0u;
8425}
8426
8427
8428
8429
8430/*!
8431 \brief BIT block find the last set bit (backward search)
8432
8433 \param block - bit block buffer pointer
8434 \param last - index of the last 1 bit (out)
8435 \return true if found
8436
8437 @ingroup bitfunc
8438*/
8439inline
8441 unsigned* BMRESTRICT last) BMNOEXCEPT
8442{
8443 BM_ASSERT(block);
8444 BM_ASSERT(last);
8445
8446 // TODO: SIMD version
8447
8448 for (unsigned i = bm::set_block_size-1; true; --i)
8449 {
8450 bm::word_t w = block[i];
8451 if (w)
8452 {
8453 unsigned idx = bm::bit_scan_reverse(w);
8454 *last = unsigned(idx + (i * 8u * unsigned(sizeof(bm::word_t))));
8455 return w;
8456 }
8457 if (i == 0)
8458 break;
8459 } // for i
8460 return 0u;
8461}
8462
8463/*!
8464 \brief BIT block find the first set bit
8465
8466 \param block - bit block buffer pointer
8467 \param pos - index of the first 1 bit (out)
8468 \return 0 if not found
8469
8470 @ingroup bitfunc
8471 @internal
8472*/
8473inline
8475 unsigned* BMRESTRICT pos) BMNOEXCEPT
8476{
8477 BM_ASSERT(block);
8478 BM_ASSERT(pos);
8479
8480#ifdef VECT_BIT_FIND_FIRST
8481 return VECT_BIT_FIND_FIRST(block, pos);
8482#else
8483 for (unsigned i = 0; i < bm::set_block_size; ++i)
8484 {
8485 bm::word_t w = block[i];
8486 if (w)
8487 {
8488 unsigned idx = bm::bit_scan_forward32(w); // trailing zeros
8489 *pos = unsigned(idx + (i * 8u * unsigned(sizeof(bm::word_t))));
8490 return w;
8491 }
8492 } // for i
8493 return false;
8494#endif
8495}
8496
8497/*!
8498 \brief BIT block find the first set bit
8499
8500 \param block - bit block buffer pointer
8501 \param first - index of the first 1 bit (out)
8502 \param digest - known digest of dst block
8503
8504 \return 0 if not found
8505
8506 @ingroup bitfunc
8507*/
8508inline
8510 unsigned* BMRESTRICT first,
8511 bm::id64_t digest) BMNOEXCEPT
8512{
8513 BM_ASSERT(block);
8514 BM_ASSERT(first);
8515 BM_ASSERT(digest);
8516
8517 bm::id64_t t = bm::bmi_blsi_u64(digest); // d & -d;
8518
8519 unsigned wave = bm::word_bitcount64(t - 1);
8520 unsigned off = wave * bm::set_block_digest_wave_size;
8521 for (unsigned i = off; i < bm::set_block_size; ++i)
8522 {
8523 bm::word_t w = block[i];
8524 if (w)
8525 {
8526 unsigned idx = bit_scan_forward32(w); // trailing zeros
8527 *first = unsigned(idx + (i * 8u * unsigned(sizeof(bm::word_t))));
8528 return w;
8529 }
8530 } // for i
8531 return 0u;
8532}
8533
8534
8535/*!
8536 \brief BIT block find the first set bit if only 1 bit is set
8537
8538 \param block - bit block buffer pointer
8539 \param first - index of the first 1 bit (out)
8540 \param digest - known digest of dst block
8541
8542 \return 0 if not found
8543
8544 @ingroup bitfunc
8545*/
8546inline
8548 unsigned* BMRESTRICT first,
8549 bm::id64_t digest) BMNOEXCEPT
8550{
8551 BM_ASSERT(block);
8552 BM_ASSERT(first);
8553 BM_ASSERT(bm::word_bitcount64(digest)==1);
8554
8555 bool found = false;
8556 bm::id64_t t = bm::bmi_blsi_u64(digest); // d & -d;
8557
8558 unsigned wave = bm::word_bitcount64(t - 1);
8559 unsigned off = wave * bm::set_block_digest_wave_size;
8560 unsigned i;
8561 for (i = off; i < off + bm::set_block_digest_wave_size; ++i)
8562 {
8563 bm::word_t w = block[i];
8564 if (w)
8565 {
8566 unsigned bc = bm::word_bitcount(w);
8567 if (bc != 1)
8568 return false;
8569
8570 unsigned idx = bit_scan_forward32(w); // trailing zeros
8571 *first = unsigned(idx + (i * 8u * sizeof(bm::word_t)));
8572 found = true;
8573 break;
8574 }
8575 } // for i
8576
8577 // check if all other bits are zero
8578 for (++i; i < off + bm::set_block_digest_wave_size; ++i)
8579 {
8580 if (block[i])
8581 return false;
8582 }
8583 return found;
8584}
8585
8586
8587/*!
8588 \brief BIT block find position for the rank
8589
8590 \param block - bit block buffer pointer
8591 \param rank - rank to find (must be > 0)
8592 \param nbit_from - start bit position in block
8593 \param nbit_pos - (out)found position
8594
8595 \return 0 if position with rank was found, or
8596 the remaining rank (rank - population count)
8597
8598 @ingroup bitfunc
8599*/
8600template<typename SIZE_TYPE>
8601SIZE_TYPE bit_find_rank(const bm::word_t* const block,
8602 SIZE_TYPE rank,
8603 unsigned nbit_from,
8604 unsigned& nbit_pos) BMNOEXCEPT
8605{
8606 BM_ASSERT(block);
8607 BM_ASSERT(rank);
8608
8609 unsigned nword = nbit_from >> bm::set_word_shift;
8611
8612 unsigned pos = nbit_from;
8613 bm::id_t nbit = (nbit_from & bm::set_word_mask);
8614
8615 if (nbit)
8616 {
8617 bm::id_t w = block[nword];
8618 w >>= nbit;
8619 unsigned bc = bm::word_bitcount(w);
8620 if (bc < rank) // skip this
8621 {
8622 rank -= bc; pos += unsigned(32u - nbit);
8623 ++nword;
8624 }
8625 else // target word
8626 {
8627 unsigned idx = bm::word_select32(w, unsigned(rank));
8628 nbit_pos = pos + idx;
8629 return 0;
8630 }
8631 }
8632
8633 #if defined(BM64OPT) || defined(BM64_SSE4) || defined(BMAVX2OPT) || defined(BMAVX512OPT)
8634 {
8635 for (; nword < bm::set_block_size-1; nword+=2)
8636 {
8637 bm::id64_t w =
8638 (bm::id64_t(block[nword+1]) << 32) | bm::id64_t(block[nword]);
8640 if (bc >= rank) // target
8641 {
8642 unsigned idx = bm::word_select64(w, unsigned(rank));
8643 nbit_pos = pos + idx;
8644 return 0;
8645 }
8646 rank -= bc;
8647 pos += 64u;
8648 }
8649 }
8650 #endif
8651
8652 for (; nword < bm::set_block_size; ++nword)
8653 {
8654 bm::id_t w = block[nword];
8656 if (rank > bc)
8657 {
8658 rank -= bc; pos += 32u;
8659 continue;
8660 }
8661 unsigned idx = bm::word_select32(w, unsigned(rank));
8662 nbit_pos = pos + idx;
8663 return 0;
8664 } // for nword
8665 return rank;
8666}
8667
8668/**
8669 \brief Find rank in block (GAP or BIT)
8670
8671 \param block - bit block buffer pointer
8672 \param rank - rank to find (must be > 0)
8673 \param nbit_from - start bit position in block
8674 \param nbit_pos - found position
8675
8676 \return 0 if position with rank was found, or
8677 the remaining rank (rank - population count)
8678
8679 @internal
8680*/
8681template<typename SIZE_TYPE>
8682SIZE_TYPE block_find_rank(const bm::word_t* const block,
8683 SIZE_TYPE rank,
8684 unsigned nbit_from,
8685 unsigned& nbit_pos) BMNOEXCEPT
8686{
8687 if (BM_IS_GAP(block))
8688 {
8689 const bm::gap_word_t* const gap_block = BMGAP_PTR(block);
8690 rank = bm::gap_find_rank(gap_block, rank, nbit_from, nbit_pos);
8691 }
8692 else
8693 {
8694 rank = bm::bit_find_rank(block, rank, nbit_from, nbit_pos);
8695 }
8696 return rank;
8697}
8698
8699
8700
8701/*!
8702 @brief Choose best representation for a bit-block
8703 @ingroup bitfunc
8704*/
8705inline
8707 unsigned total_possible_bitcount,
8708 unsigned gap_count,
8709 unsigned block_size) BMNOEXCEPT
8710{
8711 unsigned arr_size = unsigned(sizeof(bm::gap_word_t) * bit_count + sizeof(bm::gap_word_t));
8712 unsigned gap_size = unsigned(sizeof(bm::gap_word_t) * gap_count + sizeof(bm::gap_word_t));
8713 unsigned inv_arr_size = unsigned(sizeof(bm::gap_word_t) * (total_possible_bitcount - bit_count) + sizeof(bm::gap_word_t));
8714
8715 if ((gap_size < block_size) && (gap_size < arr_size) && (gap_size < inv_arr_size))
8716 {
8717 return bm::set_gap;
8718 }
8719
8720 if (arr_size < inv_arr_size)
8721 {
8722 if ((arr_size < block_size) && (arr_size < gap_size))
8723 {
8724 return bm::set_array1;
8725 }
8726 }
8727 else
8728 {
8729 if ((inv_arr_size < block_size) && (inv_arr_size < gap_size))
8730 {
8731 return bm::set_array0;
8732 }
8733 }
8734 return bm::set_bitset;
8735}
8736
8737/*!
8738 @brief Convert bit block into an array of ints corresponding to 1 bits
8739 @return destination size as a result of block decoding
8740 @ingroup bitfunc
8741*/
8742
8743/*!
8744 @brief Convert bit block into an array of ints corresponding to 1 bits
8745 @return destination size as a result of block decoding
8746 @ingroup bitfunc
8747*/
8748template<typename T>
8750 const unsigned* BMRESTRICT src,
8751 bool inverted) BMNOEXCEPT
8752{
8753 bm::id64_t imask64 = inverted ? ~0ull : 0;
8754 T* BMRESTRICT pcurr = dest;
8755 for (unsigned bit_idx = 0; bit_idx < bm::gap_max_bits;
8756 src+=2, bit_idx += unsigned(sizeof(*src) * 8 * 2))
8757 {
8758 bm::id64_t w =
8759 (bm::id64_t(src[0]) | (bm::id64_t(src[1]) << 32u)) ^ imask64;
8760 while (w)
8761 {
8762 bm::id64_t t = bmi_blsi_u64(w); // w & -w;
8763 *pcurr++ = (T)(bm::word_bitcount64(t - 1) + bit_idx);
8764 w = bmi_bslr_u64(w); // w &= w - 1;
8765 }
8766 } // for
8767 return (unsigned)(pcurr - dest);
8768}
8769
8770
8771/**
8772 \brief Checks all conditions and returns true if block consists of only 0 bits
8773 \param blk - Blocks's pointer
8774 \param deep_scan - flag to do full bit block verification (scan)
8775 when deep scan is not requested result can be approximate
8776 \returns true if all bits are in the block are 0
8777
8778 @internal
8779*/
8780inline
8781bool check_block_zero(const bm::word_t* blk, bool deep_scan) BMNOEXCEPT
8782{
8783 if (!blk) return true;
8784 if (IS_FULL_BLOCK(blk)) return false;
8785
8786 bool ret;
8787 if (BM_IS_GAP(blk))
8788 ret = gap_is_all_zero(BMGAP_PTR(blk));
8789 else
8790 ret = deep_scan ? bm::bit_is_all_zero(blk) : 0;
8791 return ret;
8792}
8793
8794
8795/**
8796 \brief Checks if block has only 1 bits
8797 \param blk - Block's pointer
8798 \param deep_scan - flag to do full bit block verification (scan)
8799 when deep scan is not requested result can be approximate
8800 \return true if block consists of 1 bits.
8801
8802 @internal
8803*/
8804inline
8805bool check_block_one(const bm::word_t* blk, bool deep_scan) BMNOEXCEPT
8806{
8807 if (blk == 0) return false;
8808
8809 if (BM_IS_GAP(blk))
8810 return bm::gap_is_all_one(BMGAP_PTR(blk));
8811
8812 if (IS_FULL_BLOCK(blk))
8813 return true;
8814
8815 if (!deep_scan)
8816 return false; // block exists - presume it has 0 bits
8817
8818 return bm::is_bits_one((wordop_t*)blk);
8819}
8820
8821
8822
8823/*! @brief Calculates memory overhead for number of gap blocks sharing
8824 the same memory allocation table (level lengths table).
8825 @ingroup gapfunc
8826*/
8827template<typename T>
8828unsigned gap_overhead(const T* length,
8829 const T* length_end,
8830 const T* glevel_len) BMNOEXCEPT
8831{
8832 BM_ASSERT(length && length_end && glevel_len);
8833
8834 unsigned overhead = 0;
8835 for (;length < length_end; ++length)
8836 {
8837 unsigned len = *length;
8838 int level = gap_calc_level(len, glevel_len);
8839 BM_ASSERT(level >= 0 && level < (int)bm::gap_levels);
8840 unsigned capacity = glevel_len[level];
8841 BM_ASSERT(capacity >= len);
8842 overhead += capacity - len;
8843 }
8844 return overhead;
8845}
8846
8847
8848/*! @brief Finds optimal gap blocks lengths.
8849 @param length - first element of GAP lengths array
8850 @param length_end - end of the GAP lengths array
8851 @param glevel_len - destination GAP lengths array
8852 @ingroup gapfunc
8853*/
8854template<typename T>
8855bool improve_gap_levels(const T* length,
8856 const T* length_end,
8857 T* glevel_len) BMNOEXCEPT
8858{
8859 BM_ASSERT(length && length_end && glevel_len);
8860
8861 size_t lsize = size_t(length_end - length);
8862
8863 BM_ASSERT(lsize);
8864
8865 gap_word_t max_len = 0;
8866 unsigned i;
8867 for (i = 0; i < lsize; ++i)
8868 {
8869 if (length[i] > max_len)
8870 max_len = length[i];
8871 }
8872 if (max_len < 5 || lsize <= bm::gap_levels)
8873 {
8874 glevel_len[0] = T(max_len + 4);
8875 for (i = 1; i < bm::gap_levels; ++i)
8876 {
8877 glevel_len[i] = bm::gap_max_buff_len;
8878 }
8879 return true;
8880 }
8881
8882 glevel_len[bm::gap_levels-1] = T(max_len + 5);
8883
8884 unsigned min_overhead = gap_overhead(length, length_end, glevel_len);
8885 bool is_improved = false;
8886
8887 // main problem solving loop
8888 //
8889 for (i = bm::gap_levels-2; ; --i)
8890 {
8891 unsigned opt_len = 0;
8892 unsigned j;
8893 bool imp_flag = false;
8894 gap_word_t gap_saved_value = glevel_len[i];
8895 for (j = 0; j < lsize; ++j)
8896 {
8897 glevel_len[i] = T(length[j] + 4);
8898 unsigned ov = gap_overhead(length, length_end, glevel_len);
8899 if (ov <= min_overhead)
8900 {
8901 min_overhead = ov;
8902 opt_len = length[j]+4;
8903 imp_flag = true;
8904 }
8905 }
8906 if (imp_flag)
8907 {
8908 glevel_len[i] = (T)opt_len; // length[opt_idx]+4;
8909 is_improved = true;
8910 }
8911 else
8912 {
8913 glevel_len[i] = gap_saved_value;
8914 }
8915 if (i == 0)
8916 break;
8917 }
8918
8919 // Remove duplicates
8920 //
8921 T val = *glevel_len;
8922 T* gp = glevel_len;
8923 T* res = glevel_len;
8924 for (i = 0; i < bm::gap_levels; ++i)
8925 {
8926 if (val != *gp)
8927 {
8928 val = *gp;
8929 *++res = val;
8930 }
8931 ++gp;
8932 }
8933
8934 // Filling the "unused" part with max. possible value
8935 while (++res < (glevel_len + bm::gap_levels))
8936 {
8937 *res = bm::gap_max_buff_len;
8938 }
8939
8940 return is_improved;
8941
8942}
8943
8944/*!
8945 \brief Find first bit which is different between two blocks (GAP or bit)
8946 \param blk - block 1
8947 \param arg_blk - block 2
8948 \param pos - out - position of difference (undefined if blocks are equal)
8949 \return true if difference was found
8950 @internal
8951*/
8952inline
8954 const bm::word_t* BMRESTRICT arg_blk,
8955 unsigned* BMRESTRICT pos) BMNOEXCEPT
8956{
8957 // If one block is zero we check if the other one has at least
8958 // one bit ON
8959
8960 if (!blk || !arg_blk)
8961 {
8962 const bm::word_t* pblk; bool is_gap;
8963 if (blk)
8964 {
8965 pblk = blk;
8966 is_gap = BM_IS_GAP(blk);
8967 }
8968 else
8969 {
8970 pblk = arg_blk;
8971 is_gap = BM_IS_GAP(arg_blk);
8972 }
8973
8974 if (is_gap)
8975 {
8976 unsigned found = bm::gap_find_first(BMGAP_PTR(pblk), pos);
8977 if (found)
8978 return true;
8979 }
8980 else
8981 {
8982 unsigned found = bm::bit_find_first(pblk, pos);
8983 if (found)
8984 return true;
8985 }
8986 return false;
8987 }
8988
8989 bool arg_gap = BM_IS_GAP(arg_blk);
8990 bool gap = BM_IS_GAP(blk);
8991
8992 if (arg_gap != gap)
8993 {
8994 //BM_DECLARE_TEMP_BLOCK(temp_blk)
8995 bm::bit_block_t temp_blk;
8996 bm::word_t* blk1; bm::word_t* blk2;
8997
8998 if (gap)
8999 {
9001 BMGAP_PTR(blk));
9002 blk1 = (bm::word_t*)temp_blk;
9003 blk2 = (bm::word_t*)arg_blk;
9004 }
9005 else
9006 {
9008 BMGAP_PTR(arg_blk));
9009 blk1 = (bm::word_t*)blk;
9010 blk2 = (bm::word_t*)temp_blk;
9011 }
9012 bool found = bm::bit_find_first_diff(blk1, blk2, pos);
9013 if (found)
9014 return true;
9015 }
9016 else
9017 {
9018 if (gap)
9019 {
9020 bool found =
9022 BMGAP_PTR(arg_blk), pos);
9023 if (found)
9024 return true;
9025 }
9026 else
9027 {
9028 bool found = bm::bit_find_first_diff(blk, arg_blk, pos);
9029 if (found)
9030 return true;
9031 }
9032 }
9033 return false;
9034}
9035
9036
9037
9038
9039/**
9040 Bit-block get adapter, takes bitblock and represents it as a
9041 get_32() accessor function
9042 \internal
9043*/
9045{
9046public:
9047 bitblock_get_adapter(const bm::word_t* bit_block) : b_(bit_block) {}
9048
9050 bm::word_t get_32() BMNOEXCEPT { return *b_++; }
9051private:
9052 const bm::word_t* b_;
9053};
9054
9055
9056/**
9057 Bit-block store adapter, takes bitblock and saves results into it
9058 \internal
9059*/
9061{
9062public:
9063 bitblock_store_adapter(bm::word_t* bit_block) : b_(bit_block) {}
9065 void push_back(bm::word_t w) { *b_++ = w; }
9066private:
9067 bm::word_t* b_;
9068};
9069
9070/**
9071 Bit-block sum adapter, takes values and sums it
9072 /internal
9073*/
9075{
9076public:
9079 void push_back(bm::word_t w) BMNOEXCEPT { this->sum_+= w; }
9080 /// Get accumulated sum
9081 bm::word_t sum() const BMNOEXCEPT { return this->sum_; }
9082private:
9083 bm::word_t sum_;
9084};
9085
9086/**
9087 Adapter to get words from a range stream
9088 (see range serialized bit-block)
9089 \internal
9090*/
9091template<class DEC> class decoder_range_adapter
9092{
9093public:
9094 decoder_range_adapter(DEC& dec, unsigned from_idx, unsigned to_idx)
9095 : decoder_(dec),
9096 from_(from_idx),
9097 to_(to_idx),
9098 cnt_(0)
9099 {}
9100
9102 {
9103 if (cnt_ < from_ || cnt_ > to_)
9104 {
9105 ++cnt_; return 0;
9106 }
9107 ++cnt_;
9108 return decoder_.get_32();
9109 }
9110
9111private:
9112 DEC& decoder_;
9113 unsigned from_;
9114 unsigned to_;
9115 unsigned cnt_;
9116};
9117
9118
9119/*!
9120 Abstract recombination algorithm for two bit-blocks
9121 Bit blocks can come as dserialization decoders or bit-streams
9122*/
9123template<class It1, class It2, class BinaryOp, class Encoder>
9124void bit_recomb(It1& it1, It2& it2,
9125 BinaryOp& op,
9126 Encoder& enc,
9127 unsigned block_size = bm::set_block_size) BMNOEXCEPT
9128{
9129 for (unsigned i = 0; i < block_size; ++i)
9130 {
9131 bm::word_t w1 = it1.get_32();
9132 bm::word_t w2 = it2.get_32();
9133 bm::word_t w = op(w1, w2);
9134 enc.push_back( w );
9135 } // for
9136}
9137
9138/// Bit AND functor
9139template<typename W> struct bit_AND
9140{
9141 W operator()(W w1, W w2) BMNOEXCEPT { return w1 & w2; }
9142};
9143
9144/// Bit OR functor
9145template<typename W> struct bit_OR
9146{
9147 W operator()(W w1, W w2) BMNOEXCEPT { return w1 | w2; }
9148};
9149
9150/// Bit SUB functor
9151template<typename W> struct bit_SUB
9152{
9153 W operator()(W w1, W w2) BMNOEXCEPT { return w1 & ~~w2; }
9154};
9155
9156/// Bit XOR functor
9157template<typename W> struct bit_XOR
9158{
9159 W operator()(W w1, W w2) BMNOEXCEPT { return w1 ^ w2; }
9160};
9161
9162/// Bit ASSIGN functor
9163template<typename W> struct bit_ASSIGN
9164{
9165 W operator()(W, W w2) BMNOEXCEPT { return w2; }
9166};
9167
9168/// Bit COUNT functor
9169template<typename W> struct bit_COUNT
9170{
9172 {
9173 w1 = 0; w1 += bm::word_bitcount(w2);
9174 return w1;
9175 }
9176};
9177
9178/// Bit COUNT AND functor
9179template<typename W> struct bit_COUNT_AND
9180{
9181 W operator()(W w1, W w2) BMNOEXCEPT { return bm::word_bitcount(w1 & w2); }
9182};
9183
9184/// Bit COUNT XOR functor
9185template<typename W> struct bit_COUNT_XOR
9186{
9187 W operator()(W w1, W w2) BMNOEXCEPT { return bm::word_bitcount(w1 ^ w2); }
9188};
9189
9190/// Bit COUNT OR functor
9191template<typename W> struct bit_COUNT_OR
9192{
9193 W operator()(W w1, W w2) BMNOEXCEPT { return bm::word_bitcount(w1 | w2); }
9194};
9195
9196
9197/// Bit COUNT SUB AB functor
9198template<typename W> struct bit_COUNT_SUB_AB
9199{
9200 W operator()(W w1, W w2) BMNOEXCEPT { return bm::word_bitcount(w1 & (~w2)); }
9201};
9202
9203/// Bit SUB BA functor
9204template<typename W> struct bit_COUNT_SUB_BA
9205{
9206 W operator()(W w1, W w2) BMNOEXCEPT { return bm::word_bitcount(w2 & (~w1)); }
9207};
9208
9209/// Bit COUNT A functor
9210template<typename W> struct bit_COUNT_A
9211{
9212 W operator()(W w1, W ) BMNOEXCEPT { return bm::word_bitcount(w1); }
9213};
9214
9215/// Bit COUNT B functor
9216template<typename W> struct bit_COUNT_B
9217{
9218 W operator()(W, W w2) BMNOEXCEPT { return bm::word_bitcount(w2); }
9219};
9220
9221typedef
9223 const gap_word_t*);
9224
9225typedef
9226gap_word_t* (*gap_operation_func_type)(const gap_word_t* BMRESTRICT,
9227 const gap_word_t* BMRESTRICT,
9229 unsigned& );
9230
9231typedef
9233 const bm::word_t* BMRESTRICT);
9234
9235
9236template<bool T>
9238{
9239 static
9241 static
9243 static
9245
9246 static
9248 {
9249 return gap2bit_table_[i];
9250 }
9251
9252 static
9254 {
9255 return gapop_table_[i];
9256 }
9257
9258 static
9260 {
9261 return bit_op_count_table_[i];
9262 }
9263};
9264
9265template<bool T>
9268 &gap_and_to_bitset<bm::gap_word_t>, // set_AND
9269 &gap_add_to_bitset<bm::gap_word_t>, // set_OR
9270 &gap_sub_to_bitset<bm::gap_word_t>, // set_SUB
9271 &gap_xor_to_bitset<bm::gap_word_t>, // set_XOR
9272 0
9273};
9274
9275template<bool T>
9278 &gap_operation_and, // set_AND
9279 &gap_operation_or, // set_OR
9280 &gap_operation_sub, // set_SUB
9281 &gap_operation_xor, // set_XOR
9282 0
9283};
9284
9285
9286template<bool T>
9289 0, // set_AND
9290 0, // set_OR
9291 0, // set_SUB
9292 0, // set_XOR
9293 0, // set_ASSIGN
9294 0, // set_COUNT
9295 &bit_operation_and_count, // set_COUNT_AND
9296 &bit_operation_xor_count, // set_COUNT_XOR
9297 &bit_operation_or_count, // set_COUNT_OR
9298 &bit_operation_sub_count, // set_COUNT_SUB_AB
9299 &bit_operation_sub_count_inv, // set_COUNT_SUB_BA
9300 0, // set_COUNT_A
9301 0, // set_COUNT_B
9302};
9303
9304/**
9305 Size of bit decode wave in words
9306 @internal
9307 */
9308const unsigned short set_bitscan_wave_size = 4;
9309/*!
9310 \brief Unpacks word wave (Nx 32-bit words)
9311 \param w_ptr - pointer on wave start
9312 \param bits - pointer on the result array
9313 \return number of bits in the list
9314
9315 @ingroup bitfunc
9316 @internal
9317*/
9318inline
9319unsigned short
9321 unsigned char* BMRESTRICT bits) BMNOEXCEPT
9322{
9323 bm::word_t w0, w1;
9324 unsigned int cnt0;
9325
9326 w0 = w_ptr[0]; w1 = w_ptr[1];
9327
9328#if defined(BMAVX512OPT) || defined(BMAVX2OPT) || defined(BM64OPT) || defined(BM64_SSE4)
9329 // combine into 64-bit word and scan (when HW popcnt64 is available)
9330 bm::id64_t w = (bm::id64_t(w1) << 32) | w0;
9331 cnt0 = bm::bitscan_popcnt64(w, bits);
9332
9333 w0 = w_ptr[2]; w1 = w_ptr[3];
9334 w = (bm::id64_t(w1) << 32) | w0;
9335 cnt0 += bm::bitscan_popcnt64(w, bits + cnt0, 64);
9336#else
9337 #if (defined(__arm__) || defined(__aarch64__))
9338 cnt0 = bm::bitscan_bsf(w0, bits, (unsigned short)0);
9339 cnt0 += bm::bitscan_bsf(w1, bits + cnt0, (unsigned short)32);
9340
9341 w0 = w_ptr[2]; w1 = w_ptr[3];
9342 cnt0 += bm::bitscan_bsf(w0, bits + cnt0, (unsigned short)64);
9343 cnt0 += bm::bitscan_bsf(w1, bits + cnt0, (unsigned short)(64+32));
9344 #else
9345 // decode wave as two 32-bit bitscan decodes
9346 cnt0 = bm::bitscan_popcnt(w0, bits);
9347 cnt0 += bm::bitscan_popcnt(w1, bits + cnt0, 32);
9348
9349 w0 = w_ptr[2]; w1 = w_ptr[3];
9350 cnt0 += bm::bitscan_popcnt(w0, bits + cnt0, 64);
9351 cnt0 += bm::bitscan_popcnt(w1, bits + cnt0, 64+32);
9352 #endif
9353#endif
9354 return static_cast<unsigned short>(cnt0);
9355}
9356
9357#if defined (BM64_SSE4) || defined(BM64_AVX2) || defined(BM64_AVX512)
9358/**
9359 bit index to word gather-scatter algorithm (SIMD)
9360 @ingroup bitfunc
9361 @internal
9362*/
9363inline
9365 const bm::word_t* BMRESTRICT blk,
9366 const unsigned* BMRESTRICT idx,
9367 unsigned size, unsigned start,
9368 unsigned bit_idx) BMNOEXCEPT
9369{
9370typedef unsigned TRGW;
9371typedef unsigned IDX;
9372#if defined(BM64_SSE4)
9373 // TODO: provide 16 and 64-bit optimized implementations
9374 // optimized for unsigned
9375 if constexpr (sizeof(TRGW)==4 && sizeof(IDX)==4)
9376 {
9377 sse4_bit_block_gather_scatter(arr, blk, idx, size, start, bit_idx);
9378 return;
9379 }
9380#elif defined(BM64_AVX2) || defined(BM64_AVX512)
9381 if constexpr (sizeof(TRGW)==4 && sizeof(IDX)==4)
9382 {
9383 avx2_bit_block_gather_scatter(arr, blk, idx, size, start, bit_idx);
9384 return;
9385 }
9386#else
9387 BM_ASSERT(0);
9388#endif
9389}
9390#endif
9391
9392/**
9393 bit index to word gather-scatter algorithm
9394 @ingroup bitfunc
9395 @internal
9396*/
9397template<typename TRGW, typename IDX, typename SZ>
9399 const bm::word_t* BMRESTRICT blk,
9400 const IDX* BMRESTRICT idx,
9401 SZ size, SZ start, unsigned bit_idx) BMNOEXCEPT
9402{
9403 // TODO: SIMD for 64-bit index sizes and 64-bit target value size
9404 //
9405 TRGW mask1 = 1;
9406 const SZ len = (size - start);
9407 const SZ len_unr = len - (len % 2);
9408 SZ k = 0;
9409 for (; k < len_unr; k+=2)
9410 {
9411 const SZ base = start + k;
9412 const unsigned nbitA = unsigned(idx[base] & bm::set_block_mask);
9413 arr[base] |= (TRGW(bool(blk[nbitA >> bm::set_word_shift] &
9414 (mask1 << (nbitA & bm::set_word_mask)))) << bit_idx);
9415 const unsigned nbitB = unsigned(idx[base + 1] & bm::set_block_mask);
9416 arr[base+1] |= (TRGW(bool(blk[nbitB >> bm::set_word_shift] &
9417 (mask1 << (nbitB & bm::set_word_mask)))) << bit_idx);
9418 } // for k
9419 for (; k < len; ++k)
9420 {
9421 unsigned nbit = unsigned(idx[start + k] & bm::set_block_mask);
9422 arr[start + k] |= (TRGW(bool(blk[nbit >> bm::set_word_shift] &
9423 (mask1 << (nbit & bm::set_word_mask)))) << bit_idx);
9424 } // for k
9425}
9426
9427/**
9428 @brief block boundaries look ahead U32
9429
9430 @param idx - array to look into
9431 @param size - array size
9432 @param nb - block number to look ahead
9433 @param start - start offset in idx
9434
9435 @return block boundary offset end (no more match at the returned offset)
9436
9437 @internal
9438*/
9439inline
9442{
9443 BM_ASSERT(idx);
9444 BM_ASSERT(start < size);
9445
9446 // TODO: SIMD for 64-bit index vector
9447 for (;(start < size) &&
9448 (nb == (idx[start] >> bm::set_block_shift)); ++start)
9449 {}
9450 return start;
9451}
9452
9453/**
9454 @brief block boundaries look ahead U32
9455
9456 @param idx - array to look into
9457 @param size - array size
9458 @param nb - block number to look ahead
9459 @param start - start offset in idx
9460
9461 @return block boundary offset end (no more match at the returned offset)
9462
9463 @internal
9464*/
9465inline
9466unsigned idx_arr_block_lookup_u32(const unsigned* idx,
9467 unsigned size, unsigned nb, unsigned start) BMNOEXCEPT
9468{
9469 BM_ASSERT(idx);
9470 BM_ASSERT(start < size);
9471
9472#if defined(VECT_ARR_BLOCK_LOOKUP)
9473 return VECT_ARR_BLOCK_LOOKUP(idx, size, nb, start);
9474#else
9475 for (;(start < size) &&
9476 (nb == unsigned(idx[start] >> bm::set_block_shift)); ++start)
9477 {}
9478 return start;
9479#endif
9480}
9481
9482// --------------------------------------------------------------
9483
9484
9485/**
9486 @brief set bits in a bit-block using global index
9487
9488 @param idx - array to look into
9489 @param block - block pointer to set bits
9490 @param start - index array start
9491 @param stop - index array stop in a range [start..stop)
9492
9493 @return block boundary offset end (no more match at the returned offset)
9494
9495 @internal
9496 @ingroup bitfunc
9497*/
9498inline
9500 const bm::id64_t* BMRESTRICT idx,
9501 bm::id64_t start, bm::id64_t stop) BMNOEXCEPT
9502{
9503 // TODO: SIMD for 64-bit mode
9504 for (bm::id64_t i = start; i < stop; ++i)
9505 {
9506 bm::id64_t n = idx[i];
9507 unsigned nbit = unsigned(n & bm::set_block_mask);
9508 unsigned nword = nbit >> bm::set_word_shift;
9509 nbit &= bm::set_word_mask;
9510 block[nword] |= (1u << nbit);
9511 } // for i
9512}
9513
9514
9515/**
9516 @brief set bits in a bit-block using global index
9517
9518 @param idx - array to look into
9519 @param block - block pointer to set bits
9520 @param start - index array start
9521 @param stop - index array stop in a range [start..stop)
9522
9523 @return block boundary offset end (no more match at the returned offset)
9524
9525 @internal
9526 @ingroup bitfunc
9527*/
9528inline
9530 const unsigned* BMRESTRICT idx,
9531 unsigned start, unsigned stop ) BMNOEXCEPT
9532{
9533 BM_ASSERT(start < stop);
9534#if defined(VECT_SET_BLOCK_BITS)
9535 VECT_SET_BLOCK_BITS(block, idx, start, stop);
9536#else
9537 do
9538 {
9539 unsigned n = idx[start++];
9540 unsigned nbit = unsigned(n & bm::set_block_mask);
9541 unsigned nword = nbit >> bm::set_word_shift;
9542 nbit &= bm::set_word_mask;
9543 block[nword] |= (1u << nbit);
9544 } while (start < stop);
9545#endif
9546}
9547
9548
9549
9550// --------------------------------------------------------------
9551
9552/**
9553 @brief array range detector
9554 @internal
9555*/
9556inline
9558 unsigned& left, unsigned& right) BMNOEXCEPT
9559{
9560 BM_ASSERT(arr);
9561
9562 unsigned i, j;
9563 for (i = 0; i < bm::set_sub_array_size; ++i)
9564 {
9565 if (arr[i])
9566 {
9567 left = i;
9568 break;
9569 }
9570 }
9571 if (i == bm::set_sub_array_size)
9572 {
9573 left = right = 0;
9574 return false; // nothing here
9575 }
9576 for (j = bm::set_sub_array_size-1; j != i; --j)
9577 if (arr[j])
9578 break;
9579 right = j;
9580 return true;
9581}
9582
9583// --------------------------------------------------------------
9584
9585/**
9586 Linear lower bound search in unsigned array
9587 @internal
9588*/
9589inline
9590unsigned lower_bound_linear_u32(const unsigned* arr, unsigned target,
9591 unsigned from, unsigned to) BMNOEXCEPT
9592{
9593 BM_ASSERT(arr);
9594 BM_ASSERT(from <= to);
9595
9596#if defined(VECT_LOWER_BOUND_SCAN_U32)
9597 return VECT_LOWER_BOUND_SCAN_U32(arr, target, from, to);
9598#else
9599 for (; from <= to; ++from)
9600 {
9601 if (arr[from] >= target)
9602 break;
9603 }
9604 return from;
9605#endif
9606}
9607
9608/**
9609 Linear lower bound search in unsigned LONG array
9610 @internal
9611*/
9612inline
9613unsigned lower_bound_linear_u64(const unsigned long long* arr,
9614 unsigned long long target,
9615 unsigned from, unsigned to) BMNOEXCEPT
9616{
9617 BM_ASSERT(arr);
9618 BM_ASSERT(from <= to);
9619
9620 // TODO: implement vectorized scan on u64 ints
9621 for (; from <= to; ++from)
9622 {
9623 if (arr[from] >= target)
9624 break;
9625 }
9626 return from;
9627}
9628
9629
9630
9631// --------------------------------------------------------------
9632
9633/**
9634 Hybrid, binary-linear lower bound search in unsigned array
9635 @internal
9636*/
9637inline
9638unsigned lower_bound_u32(const unsigned* arr, unsigned target,
9639 unsigned from, unsigned to) BMNOEXCEPT
9640{
9641 BM_ASSERT(arr);
9642 BM_ASSERT(from <= to);
9643 const unsigned linear_cutoff = 32;
9644
9645 unsigned l = from; unsigned r = to;
9646 unsigned dist = r - l;
9647 if (dist < linear_cutoff)
9648 {
9649 return bm::lower_bound_linear_u32(arr, target, l, r);
9650 }
9651
9652 while (l <= r)
9653 {
9654 unsigned mid = (r-l)/2+l;
9655 if (arr[mid] < target)
9656 l = mid+1;
9657 else
9658 r = mid-1;
9659 dist = r - l;
9660 if (dist < linear_cutoff)
9661 {
9662 return bm::lower_bound_linear_u32(arr, target, l, r);
9663 }
9664 }
9665 return l;
9666}
9667
9668/**
9669 Hybrid, binary-linear lower bound search in unsigned LONG array
9670 @internal
9671*/
9672inline
9673unsigned lower_bound_u64(const unsigned long long* arr,
9674 unsigned long long target,
9675 unsigned from, unsigned to) BMNOEXCEPT
9676{
9677 BM_ASSERT(arr);
9678 BM_ASSERT(from <= to);
9679 const unsigned linear_cutoff = 32;
9680
9681 unsigned l = from; unsigned r = to;
9682 unsigned dist = r - l;
9683 if (dist < linear_cutoff)
9684 {
9685 return bm::lower_bound_linear_u64(arr, target, l, r);
9686 }
9687
9688 while (l <= r)
9689 {
9690 unsigned mid = (r - l) / 2 + l;
9691 if (arr[mid] < target)
9692 l = mid + 1;
9693 else
9694 r = mid - 1;
9695 dist = r - l;
9696 if (dist < linear_cutoff)
9697 {
9698 return bm::lower_bound_linear_u64(arr, target, l, r);
9699 }
9700 }
9701 return l;
9702}
9703
9704/**
9705 Scan search for pointer value in unordered array
9706 @return found flag and index
9707 @internal
9708 */
9709inline
9710bool find_ptr(const void* const * p_arr, size_t arr_size,
9711 const void* ptr, size_t *idx) BMNOEXCEPT
9712{
9713 // TODO: SIMD?
9714 for (size_t i = 0; i < arr_size; ++i)
9715 if (ptr == p_arr[i])
9716 {
9717 *idx = i; return true;
9718 }
9719 return false;
9720}
9721
9722
9723/**
9724 calculate bvector<> global bit-index from block-local coords
9725 @return bit index in linear bit-vector coordinates
9726 @internal
9727*/
9728#ifdef BM64ADDR
9729inline
9730bm::id64_t block_to_global_index(unsigned i, unsigned j,
9731 unsigned block_idx) BMNOEXCEPT
9732{
9734 base_idx += j * bm::gap_max_bits;
9735 return block_idx + base_idx;
9736}
9737#else
9738inline
9739bm::id_t block_to_global_index(unsigned i, unsigned j,
9740 unsigned block_idx) BMNOEXCEPT
9741{
9742 unsigned base_idx = i * bm::set_sub_array_size * bm::gap_max_bits;
9743 base_idx += j * bm::gap_max_bits;
9744 return block_idx + base_idx;
9745}
9746#endif
9747
9748/**
9749 Calculate minimal delta between elements of sorted array
9750 @internal
9751 */
9752inline
9753unsigned min_delta_u32(const unsigned* arr, size_t arr_size)
9754{
9755 if (arr_size < 2)
9756 return 0;
9757
9758 unsigned md = arr[1] - arr[0]; // initial delta value
9759 for (size_t i = 1; i < arr_size; ++i)
9760 {
9761 unsigned prev = arr[i-1];
9762 unsigned curr = arr[i];
9763 BM_ASSERT(prev <= curr - 1);
9764 unsigned delta = curr - prev;
9765 if (delta < md)
9766 {
9767 md = delta;
9768 }
9769 } // for
9770 return md;
9771}
9772
9773/**
9774 Recalculate the array to decrement delta as
9775 arr[i] = arr[i] - delta + 1
9776 so that array remains monotonically growing (fit
9777 for interpolative compression)
9778
9779 @internal
9780 */
9781inline
9782void min_delta_apply(unsigned* arr, size_t arr_size, unsigned delta) BMNOEXCEPT
9783{
9784 BM_ASSERT(delta > 0);
9785 --delta;
9786 // TODO: SIMD and unroll
9787 for (size_t i = 1; i < arr_size; ++i)
9788 {
9789 arr[i] -= delta;
9790 BM_ASSERT(arr[i] > arr[i-1]);
9791 } // for
9792}
9793
9794/**
9795 Find max non-zero value in an array
9796 @internal
9797 */
9798template<typename VT, typename SZ>
9799bool find_max_nz(const VT* arr, SZ arr_size, SZ* found_idx) BMNOEXCEPT
9800{
9801 bool found = false;
9802 VT max_v = 0;
9803 for (SZ i = 0; i < arr_size; ++i)
9804 {
9805 VT v = arr[i];
9806 if (v > max_v)
9807 {
9808 max_v = v; *found_idx = i;
9809 found = true;
9810 }
9811 } // for i
9812 return found;
9813}
9814
9815/**
9816 Find max non-zero value in an array
9817 @internal
9818 */
9819template<typename VT, typename SZ>
9820bool find_first_nz(const VT* arr, SZ arr_size, SZ* found_idx) BMNOEXCEPT
9821{
9822 for (SZ i = 0; i < arr_size; ++i)
9823 {
9824 VT v = arr[i];
9825 if (v)
9826 {
9827 *found_idx = i;
9828 return true;
9829 }
9830 } // for i
9831 return false;
9832}
9833
9834/**
9835 Find count of non-zero elements in the array
9836 @internal
9837 */
9838template<typename VT, typename SZ>
9839SZ count_nz(const VT* arr, SZ arr_size) BMNOEXCEPT
9840{
9841 SZ cnt = 0;
9842 for (SZ i = 0; i < arr_size; ++i)
9843 cnt += (arr[i] != 0);
9844 return cnt;
9845}
9846
9847// --------------------------------------------------------------
9848// Best representation
9849// --------------------------------------------------------------
9850
9851/// Possible representations for bit sets
9852///
9853/// @internal
9855{
9856 e_bit_GAP = 0, ///< GAPs
9857 e_bit_INT, ///< Int list
9858 e_bit_IINT, ///< Inverted int list
9859 e_bit_1, ///< all 1s
9860 e_bit_0, ///< all 0s (empty block)
9861 e_bit_bit, ///< uncompressed bit-block
9862 e_bit_end
9864
9865/**
9866 Detect best representation for serialization for a block or sub-block
9867 @param gc - gap count
9868 @param bc - bit count
9869 @param max_bits - total number of bits in block
9870 @param bie_bits_per_int - number of bits per int in the compression scheme
9871 @param best_metric - [out] - best metric (number of bits or gaps)
9872
9873 @return representation metric
9874 */
9875inline
9877 unsigned bc,
9878 unsigned max_bits,
9879 float bie_bits_per_int,
9880 unsigned* best_metric) BMNOEXCEPT
9881{
9882 if (!bc)
9883 {
9884 *best_metric = bc;
9885 return e_bit_0;
9886 }
9887 if (bc == max_bits)
9888 {
9889 *best_metric = 0;
9890 return e_bit_1;
9891 }
9892
9893 unsigned ibc = max_bits - bc;
9894 if (gc < bc) // GC < BC
9895 {
9896 if (gc <= ibc)
9897 {
9898 *best_metric = gc;
9899 float cost_in_bits = float(gc) * bie_bits_per_int;
9900 if (cost_in_bits >= float(max_bits))
9901 return e_bit_bit;
9902 return e_bit_GAP;
9903 }
9904 }
9905 else // GC >= BC
9906 {
9907 if (bc <= ibc)
9908 {
9909 *best_metric = bc;
9910 float cost_in_bits = float(bc) * bie_bits_per_int;
9911 if (cost_in_bits >= float(max_bits))
9912 return e_bit_bit;
9913 return e_bit_INT;
9914 }
9915 }
9916 *best_metric = ibc;
9917 float cost_in_bits = float(ibc) * bie_bits_per_int;
9918 if (cost_in_bits >= float(max_bits))
9919 return e_bit_bit;
9920 return e_bit_IINT;
9921}
9922
9923// --------------------------------------------------------------
9924// Nibble array functions
9925// --------------------------------------------------------------
9926
9927/**
9928 @brief set nibble in the array
9929 @param arr - base array of characters
9930 @param idx - nibble index
9931 @param v - value to set
9932
9933 @internal
9934 */
9935inline
9936void set_nibble(unsigned char* arr, unsigned idx, unsigned char v) BMNOEXCEPT
9937{
9938 BM_ASSERT(arr);
9939 BM_ASSERT(v <= 0xF);
9940
9941 unsigned arr_idx = idx >> 1;
9942 if (idx & 1)
9943 {
9944 unsigned char old_val = arr[arr_idx];
9945 old_val &= 0x0F; // clear the upper bits
9946 arr[arr_idx] = (unsigned char)(old_val | (v << 4));
9947 }
9948 else
9949 {
9950 unsigned char old_val = arr[arr_idx];
9951 old_val &= 0xF0; // clear the lower bits
9952 arr[arr_idx] = (unsigned char)(old_val | (v & 0xF));
9953 }
9954}
9955
9956/**
9957 @brief get nibble from the array
9958 @param arr - base array of characters
9959 @param idx - nibble index
9960 @return value
9961
9962 @internal
9963 */
9964inline
9965unsigned char get_nibble(const unsigned char* arr, unsigned idx) BMNOEXCEPT
9966{
9967 BM_ASSERT(arr);
9968 unsigned char v = arr[idx >> 1];
9969 v >>= (idx & 1) * 4;
9970 v &= 0xF;
9971 return v;
9972}
9973
9974
9975// --------------------------------------------------------------
9976// Functions to work with int values stored in 64-bit pointers
9977// --------------------------------------------------------------
9978
9979/*!
9980 \brief helper union to interpret pointer as integers
9981 @internal
9982*/
9984{
9987 unsigned short i16[4];
9988};
9989
9990/*!
9991 Test presense of value in payload pointer
9992 @internal
9993*/
9994inline
9996{
9997 if (v == 0)
9998 {
9999 return (ptr.i16[1] == 0);
10000 }
10001 bm::id64_t r = (ptr.i16[1] == v) | (ptr.i16[2] == v) | (ptr.i16[3] == v);
10002 return r;
10003}
10004
10005// --------------------------------------------------------------------------
10006
10007} // namespace bm
10008
10009#endif
#define VECT_STREAM_BLOCK_UNALIGN(dst, src)
Definition: bmavx2.h:3278
#define VECT_COPY_BLOCK_UNALIGN(dst, src)
Definition: bmavx2.h:3272
#define VECT_SET_BLOCK(dst, value)
Definition: bmavx2.h:3281
#define VECT_BITCOUNT_OR(first, last, mask)
Definition: bmavx2.h:3212
#define VECT_BIT_FIND_DIFF(src1, src2, pos)
Definition: bmavx2.h:3329
#define VECT_AND_DIGEST_5WAY(dst, src1, src2, src3, src4)
Definition: bmavx2.h:3236
#define VECT_OR_BLOCK_5WAY(dst, src1, src2, src3, src4)
Definition: bmavx2.h:3251
#define VECT_COPY_BLOCK(dst, src)
Definition: bmavx2.h:3269
#define BM_AVX2_POPCNT_PROLOG
Definition: bmavx2.h:140
#define VECT_BITCOUNT_AND(first, last, mask)
Definition: bmavx2.h:3209
#define VECT_SHIFT_R1(b, acc, co)
Definition: bmavx2.h:3302
#define VECT_XOR_BLOCK_2WAY(dst, src1, src2)
Definition: bmavx2.h:3266
#define VECT_IS_ONE_BLOCK(dst)
Definition: bmavx2.h:3287
#define VECT_STREAM_BLOCK(dst, src)
Definition: bmavx2.h:3275
#define VECT_OR_BLOCK(dst, src)
Definition: bmavx2.h:3239
#define VECT_SHIFT_R1_AND(b, co, m, digest)
Definition: bmavx2.h:3305
#define VECT_SUB_BLOCK(dst, src)
Definition: bmavx2.h:3254
#define VECT_IS_ZERO_BLOCK(dst)
Definition: bmavx2.h:3284
#define VECT_BIT_TO_GAP(dest, src, dest_len)
Definition: bmavx2.h:3323
#define VECT_SUB_DIGEST_2WAY(dst, src1, src2)
Definition: bmavx2.h:3260
#define VECT_XOR_BLOCK(dst, src)
Definition: bmavx2.h:3263
#define VECT_IS_DIGEST_ZERO(start)
Definition: bmavx2.h:3290
#define VECT_ANDNOT_ARR_2_MASK(dst, src, src_end, mask)
Definition: bmavx2.h:3203
#define VECT_BLOCK_CHANGE_BC(block, gc, bc)
Definition: bmavx2.h:3320
#define VECT_BIT_COUNT_DIGEST(blk, d)
Definition: bmavx2.h:3341
#define VECT_SHIFT_L1(b, acc, co)
Definition: bmavx2.h:3299
#define VECT_LOWER_BOUND_SCAN_U32(arr, target, from, to)
Definition: bmavx2.h:3296
#define VECT_SET_BLOCK_BITS(block, idx, start, stop)
Definition: bmavx2.h:3311
#define VECT_BITCOUNT_SUB(first, last, mask)
Definition: bmavx2.h:3218
#define VECT_BITCOUNT_XOR(first, last, mask)
Definition: bmavx2.h:3215
#define VECT_AND_DIGEST(dst, src)
Definition: bmavx2.h:3227
#define VECT_BIT_FIND_FIRST(src1, pos)
Definition: bmavx2.h:3326
#define VECT_GAP_BFIND(buf, pos, is_set)
Definition: bmavx2.h:3338
#define VECT_INVERT_BLOCK(first)
Definition: bmavx2.h:3221
#define VECT_BLOCK_CHANGE(block, size)
Definition: bmavx2.h:3314
#define VECT_AND_DIGEST_2WAY(dst, src1, src2)
Definition: bmavx2.h:3230
#define VECT_AND_OR_DIGEST_2WAY(dst, src1, src2)
Definition: bmavx2.h:3233
#define VECT_BLOCK_SET_DIGEST(dst, val)
Definition: bmavx2.h:3293
#define BM_AVX2_BIT_COUNT(ret, v)
Definition: bmavx2.h:124
#define VECT_ARR_BLOCK_LOOKUP(idx, size, nb, start)
Definition: bmavx2.h:3308
#define VECT_BITCOUNT(first, last)
Definition: bmavx2.h:3206
#define VECT_SUB_DIGEST(dst, src)
Definition: bmavx2.h:3257
#define VECT_OR_BLOCK_3WAY(dst, src1, src2)
Definition: bmavx2.h:3248
#define VECT_OR_BLOCK_2WAY(dst, src1, src2)
Definition: bmavx2.h:3245
#define VECT_AND_BLOCK(dst, src)
Definition: bmavx2.h:3224
Definitions(internal)
#define IS_FULL_BLOCK(addr)
Definition: bmdef.h:162
#define IS_VALID_ADDR(addr)
Definition: bmdef.h:161
#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 BMFORCEINLINE
Definition: bmdef.h:213
#define BM_ASSERT
Definition: bmdef.h:139
#define FULL_BLOCK_FAKE_ADDR
Definition: bmdef.h:158
#define IS_EMPTY_BLOCK(addr)
Definition: bmdef.h:163
#define BMNOEXCEPT2
Definition: bmdef.h:108
#define FULL_BLOCK_REAL_ADDR
Definition: bmdef.h:157
#define BM_VECT_ALIGN
Definition: bmdef.h:320
Bit manipulation primitives (internal)
Bit-block get adapter, takes bitblock and represents it as a get_32() accessor function.
Definition: bmfunc.h:9045
bitblock_get_adapter(const bm::word_t *bit_block)
Definition: bmfunc.h:9047
BMFORCEINLINE bm::word_t get_32() BMNOEXCEPT
Definition: bmfunc.h:9050
Bit-block store adapter, takes bitblock and saves results into it.
Definition: bmfunc.h:9061
BMFORCEINLINE void push_back(bm::word_t w)
Definition: bmfunc.h:9065
bitblock_store_adapter(bm::word_t *bit_block)
Definition: bmfunc.h:9063
Bit-block sum adapter, takes values and sums it /internal.
Definition: bmfunc.h:9075
BMFORCEINLINE void push_back(bm::word_t w) BMNOEXCEPT
Definition: bmfunc.h:9079
bm::word_t sum() const BMNOEXCEPT
Get accumulated sum.
Definition: bmfunc.h:9081
Adaptor to copy 1 bits to array.
Definition: bmfunc.h:536
copy_to_array_functor(B *bits)
Definition: bmfunc.h:538
void operator()(unsigned bit_idx0, unsigned bit_idx1, unsigned bit_idx2) BMNOEXCEPT
Definition: bmfunc.h:552
void operator()(unsigned bit_idx0, unsigned bit_idx1, unsigned bit_idx2, unsigned bit_idx3) BMNOEXCEPT
Definition: bmfunc.h:560
void operator()(unsigned bit_idx0, unsigned bit_idx1) BMNOEXCEPT
Definition: bmfunc.h:545
void operator()(unsigned bit_idx) BMNOEXCEPT
Definition: bmfunc.h:543
Adapter to get words from a range stream (see range serialized bit-block)
Definition: bmfunc.h:9092
bm::word_t get_32() BMNOEXCEPT
Definition: bmfunc.h:9101
decoder_range_adapter(DEC &dec, unsigned from_idx, unsigned to_idx)
Definition: bmfunc.h:9094
BMFORCEINLINE bool avx2_test_all_zero_wave(const void *ptr)
check if wave of pointers is all NULL
Definition: bmavx2.h:1592
unsigned avx2_gap_test(const unsigned short *BMRESTRICT buf, unsigned pos)
Hybrid binary search, starts as binary, then switches to scan.
Definition: bmavx2.h:2823
unsigned sse2_gap_test(const unsigned short *BMRESTRICT buf, unsigned pos)
Hybrid binary search, starts as binary, then switches to scan.
Definition: bmsse2.h:1251
BMFORCEINLINE bool sse42_test_all_zero_wave(const void *ptr) BMNOEXCEPT
check if wave of pointers is all NULL
Definition: bmsse4.h:671
unsigned sse42_gap_test(const unsigned short *BMRESTRICT buf, unsigned pos) BMNOEXCEPT
Hybrid binary search, starts as binary, then switches to scan.
Definition: bmsse4.h:1208
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
bm::id64_t bit_block_and_5way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src0, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, const bm::word_t *BMRESTRICT src3, bm::id64_t digest) BMNOEXCEPT
digest based bit-block AND 5-way
Definition: bmfunc.h:6916
unsigned bit_block_find(const bm::word_t *BMRESTRICT block, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Searches for the next 1 bit in the BIT block.
Definition: bmfunc.h:8389
bool bit_block_or_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
2 way (target := source1 | source2) bitblock OR operation.
Definition: bmfunc.h:7712
unsigned bitcount64_4way(bm::id64_t x, bm::id64_t y, bm::id64_t u, bm::id64_t v) BMNOEXCEPT
Definition: bmfunc.h:240
bm::id_t bit_operation_sub_count_inv(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs inverted bitblock SUB operation and calculates bitcount of the result.
Definition: bmfunc.h:7552
BMFORCEINLINE bm::id_t word_bitcount(bm::id_t w) BMNOEXCEPT
Definition: bmutil.h:573
unsigned word_select32(unsigned w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:957
BMFORCEINLINE unsigned bit_count_min_unroll(const bm::word_t *BMRESTRICT block, const bm::word_t *BMRESTRICT block_end) BMNOEXCEPT
Bitcount for bit block without agressive unrolling.
Definition: bmfunc.h:4962
unsigned bit_block_and_any(const bm::word_t *src1, const bm::word_t *src2) BMNOEXCEPT
Function ANDs two bitblocks and tests for any bit. Function does not analyse availability of source b...
Definition: bmfunc.h:7161
unsigned bit_block_sub_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Function SUBs two bitblocks and computes the bitcount. Function does not analyse availability of sour...
Definition: bmfunc.h:7264
unsigned word_select64_bitscan_tz(bm::id64_t w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:846
unsigned bit_block_calc_change(const bm::word_t *block) BMNOEXCEPT
Definition: bmfunc.h:5249
void bit_block_copy(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Bitblock copy operation.
Definition: bmfunc.h:6743
bool bit_block_shift_r1_and(bm::word_t *BMRESTRICT block, bm::word_t co_flag, const bm::word_t *BMRESTRICT mask_block, bm::id64_t *BMRESTRICT digest) BMNOEXCEPT
Right bit-shift of bit-block by 1 bit (reference) + AND.
Definition: bmfunc.h:5856
unsigned bit_count_nonzero_size(const T *blk, unsigned data_size) BMNOEXCEPT
Inspects block for full zero words.
Definition: bmfunc.h:8333
bm::id_t bit_count_change(bm::word_t w) BMNOEXCEPT
Definition: bmfunc.h:5111
unsigned short bitscan_bsf(unsigned w, B *bits) BMNOEXCEPT
Unpacks word into list of ON bits (BSF/__builtin_ctz)
Definition: bmfunc.h:689
unsigned short bitscan(V w, B *bits) BMNOEXCEPT
Templated Bitscan with dynamic dispatch for best type.
Definition: bmfunc.h:761
bool bit_block_shift_r1_unr_min(bm::word_t *BMRESTRICT block, bm::word_t *BMRESTRICT empty_acc, bm::id64_t co_flag) BMNOEXCEPT
Right bit-shift bitblock by 1 bit (minimum unroll)
Definition: bmfunc.h:5631
unsigned bit_block_and_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Function ANDs two bitblocks and computes the bitcount. Function does not analyse availability of sour...
Definition: bmfunc.h:7114
bm::word_t * bit_operation_sub(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock SUB operation.
Definition: bmfunc.h:8108
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::word_t * bit_operation_xor(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock XOR operation.
Definition: bmfunc.h:8237
bm::id64_t bit_block_sub_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, bm::id64_t digest) BMNOEXCEPT
digest based bitblock SUB (AND NOT) operation (3 operand)
Definition: bmfunc.h:8041
void block_init_digest0(bm::word_t *const block, bm::id64_t digest) BMNOEXCEPT
Init block with 000111000 pattren based on digest.
Definition: bmfunc.h:1062
unsigned word_select32_bitscan_popcnt(unsigned w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:875
bool check_zero_digest(bm::id64_t digest, unsigned bitpos_from, unsigned bitpos_to) BMNOEXCEPT
check if all digest bits for the range [from..to] are 0
Definition: bmfunc.h:1046
void or_bit_block(unsigned *dest, unsigned bitpos, unsigned bitcount) BMNOEXCEPT
Sets bits to 1 in the bitblock.
Definition: bmfunc.h:3748
bm::id64_t bit_block_and(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock AND operation. Function does not analyse availability of source and destination blocks...
Definition: bmfunc.h:6824
bm::id_t bit_block_count(const bm::word_t *block) BMNOEXCEPT
Bitcount for bit block.
Definition: bmfunc.h:5017
bool bit_block_shift_l1_unr_min(bm::word_t *BMRESTRICT block, bm::word_t *BMRESTRICT empty_acc, unsigned co_flag) BMNOEXCEPT
Left bit-shift bitblock by 1 bit (minimum unroll)
Definition: bmfunc.h:5733
bool bit_block_is_all_one_range(const bm::word_t *const BMRESTRICT block, bm::word_t left, bm::word_t right) BMNOEXCEPT
Definition: bmfunc.h:5267
bool bit_block_or_5way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, const bm::word_t *BMRESTRICT src3, const bm::word_t *BMRESTRICT src4) BMNOEXCEPT
5 way (target, source1, source2) bitblock OR operation. Function does not analyse availability of sou...
Definition: bmfunc.h:7836
BMFORCEINLINE void clear_bit(unsigned *dest, unsigned bitpos) BMNOEXCEPT
Set 1 bit in a block.
Definition: bmfunc.h:3716
void xor_bit_block(unsigned *dest, unsigned bitpos, unsigned bitcount) BMNOEXCEPT
XOR bit interval to 1 in the bitblock.
Definition: bmfunc.h:3842
BMFORCEINLINE bm::id64_t widx_to_digest_mask(unsigned w_idx) BMNOEXCEPT
Compute digest mask for word address in block.
Definition: bmfunc.h:989
void bit_block_gather_scatter(unsigned *BMRESTRICT arr, const bm::word_t *BMRESTRICT blk, const unsigned *BMRESTRICT idx, unsigned size, unsigned start, unsigned bit_idx) BMNOEXCEPT
bit index to word gather-scatter algorithm (SIMD)
Definition: bmfunc.h:9364
bool bit_block_shift_r1_unr(bm::word_t *BMRESTRICT block, bm::word_t *BMRESTRICT empty_acc, bm::word_t co_flag) BMNOEXCEPT
Right bit-shift of bit-block by 1 bit (loop unrolled)
Definition: bmfunc.h:5677
bm::set_representation best_representation(unsigned bit_count, unsigned total_possible_bitcount, unsigned gap_count, unsigned block_size) BMNOEXCEPT
Choose best representation for a bit-block.
Definition: bmfunc.h:8706
bool bit_block_find_prev(const bm::word_t *BMRESTRICT block, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Reverse search for the previous 1 bit.
Definition: bmfunc.h:6303
bm::id_t bit_operation_or_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock OR operation and calculates bitcount of the result.
Definition: bmfunc.h:7605
bool bit_block_shift_r1_and_unr(bm::word_t *BMRESTRICT block, bm::word_t co_flag, const bm::word_t *BMRESTRICT mask_block, bm::id64_t *BMRESTRICT digest) BMNOEXCEPT
Right bit-shift bitblock by 1 bit (reference) + AND.
Definition: bmfunc.h:5928
void block_expand_by_digest(bm::word_t *t_block, const bm::word_t *block, bm::id64_t digest, bool zero_subs) BMNOEXCEPT
expand sub-blocks by digest (rank expansion)
Definition: bmfunc.h:1250
unsigned word_select64(bm::id64_t w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:930
BMFORCEINLINE unsigned word_bitcount64(bm::id64_t x) BMNOEXCEPT
Definition: bmutil.h:596
SIZE_TYPE bit_find_rank(const bm::word_t *const block, SIZE_TYPE rank, unsigned nbit_from, unsigned &nbit_pos) BMNOEXCEPT
BIT block find position for the rank.
Definition: bmfunc.h:8601
BMFORCEINLINE void set_bit(unsigned *dest, unsigned bitpos) BMNOEXCEPT
Set 1 bit in a block.
Definition: bmfunc.h:3703
unsigned bit_block_convert_to_arr(T *BMRESTRICT dest, const unsigned *BMRESTRICT src, bool inverted) BMNOEXCEPT
Convert bit block into an array of ints corresponding to 1 bits.
Definition: bmfunc.h:8749
bm::word_t * bit_operation_or(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Block OR operation. Makes analysis if block is 0 or FULL.
Definition: bmfunc.h:7885
unsigned word_select32_bitscan_tz(unsigned w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:904
bm::id_t bit_block_calc_count_to(const bm::word_t *block, bm::word_t right) BMNOEXCEPT
Definition: bmfunc.h:5442
int wordcmp(T a, T b) BMNOEXCEPT
Lexicographical comparison of two words as bit strings. Auxiliary implementation for testing and refe...
Definition: bmfunc.h:1504
void bit_block_erase(bm::word_t *block, unsigned bitpos, bool carry_over) BMNOEXCEPT
erase bit from position and shift the rest right with carryover
Definition: bmfunc.h:5800
bool bit_block_find_interval_end(const bm::word_t *BMRESTRICT block, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Searches for the last 1 bit in the 111 interval of a BIT block.
Definition: bmfunc.h:6143
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
void bit_for_each_4(T w, F &func)
Templated algorithm to unpacks octet based word into list of ON bit indexes.
Definition: bmfunc.h:281
unsigned bit_block_xor_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Function XORs two bitblocks and and tests for any bit. Function does not analyse availability of sour...
Definition: bmfunc.h:7238
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
bool bit_block_shift_l1_unr(bm::word_t *block, bm::word_t *empty_acc, bm::word_t co_flag) BMNOEXCEPT
Left bit-shift of bit-block by 1 bit (loop unrolled)
Definition: bmfunc.h:5777
unsigned word_select64_bitscan_popcnt(bm::id64_t w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:817
bm::id64_t calc_block_digest0(const bm::word_t *const block) BMNOEXCEPT
Compute digest for 64 non-zero areas.
Definition: bmfunc.h:1092
bm::id64_t bit_block_and_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, bm::id64_t digest) BMNOEXCEPT
digest based bit-block AND
Definition: bmfunc.h:6983
void sub_bit_block(unsigned *dest, unsigned bitpos, unsigned bitcount) BMNOEXCEPT
SUB (AND NOT) bit interval to 1 in the bitblock.
Definition: bmfunc.h:3795
void bit_block_stream_unalign(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Bitblock copy/stream operation (unaligned src)
Definition: bmfunc.h:6800
unsigned bit_scan_reverse(T value) BMNOEXCEPT
Definition: bmutil.h:453
void bit_for_each(T w, F &func)
Templated algorithm to unpacks word into list of ON bit indexes.
Definition: bmfunc.h:351
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
int wordcmp0(T w1, T w2) BMNOEXCEPT
Lexicographical comparison of two words as bit strings (reference) Auxiliary implementation for testi...
Definition: bmfunc.h:1475
bool bit_find_first(const bm::word_t *BMRESTRICT block, unsigned *BMRESTRICT pos) BMNOEXCEPT
BIT block find the first set bit.
Definition: bmfunc.h:8474
void bit_invert(T *start) BMNOEXCEPT
Definition: bmfunc.h:6023
unsigned bit_block_sub_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Function SUBs two bitblocks and and tests for any bit. Function does not analyse availability of sour...
Definition: bmfunc.h:7310
bool bit_find_first_diff(const bm::word_t *BMRESTRICT blk1, const bm::word_t *BMRESTRICT blk2, unsigned *BMRESTRICT pos) BMNOEXCEPT
Find first bit which is different between two bit-blocks.
Definition: bmfunc.h:4691
unsigned short bitscan_popcnt64(bm::id64_t w, B *bits) BMNOEXCEPT
Unpacks 64-bit word into list of ON bit indexes using popcnt method.
Definition: bmfunc.h:667
bool bit_block_or_3way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
3 way (target | source1 | source2) bitblock OR operation. Function does not analyse availability of s...
Definition: bmfunc.h:7792
int bitcmp(const T *buf1, const T *buf2, unsigned len) BMNOEXCEPT
Lexicographical comparison of BIT buffers.
Definition: bmfunc.h:4666
bm::id64_t bit_block_and_or_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, bm::id64_t digest) BMNOEXCEPT
digest based bit-block AND - OR
Definition: bmfunc.h:7050
unsigned bit_list_4(T w, B *bits) BMNOEXCEPT
Unpacks word into list of ON bit indexes (quad-bit based)
Definition: bmfunc.h:605
unsigned bit_block_or_any(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Function ORs two bitblocks and and tests for any bit. Function does not analyse availability of sourc...
Definition: bmfunc.h:7385
bm::id64_t bit_block_xor(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock XOR operation. Function does not analyse availability of source and destination blocks...
Definition: bmfunc.h:8166
void bit_block_set(bm::word_t *BMRESTRICT dst, bm::word_t value) BMNOEXCEPT
Bitblock memset operation.
Definition: bmfunc.h:4422
BMFORCEINLINE unsigned test_bit(const unsigned *block, unsigned bitpos) BMNOEXCEPT
Test 1 bit in a block.
Definition: bmfunc.h:3730
void bit_block_rotate_left_1_unr(bm::word_t *block) BMNOEXCEPT
Unrolled cyclic rotation of bit-block left by 1 bit.
Definition: bmfunc.h:5515
BMFORCEINLINE bm::id64_t digest_mask(unsigned from, unsigned to) BMNOEXCEPT
Compute digest mask for [from..to] positions.
Definition: bmfunc.h:1017
bool bit_block_or(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock OR operation. Function does not analyse availability of source and destination blocks.
Definition: bmfunc.h:7675
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
unsigned bit_find_last(const bm::word_t *BMRESTRICT block, unsigned *BMRESTRICT last) BMNOEXCEPT
BIT block find the last set bit (backward search)
Definition: bmfunc.h:8440
bool bit_find_first_if_1(const bm::word_t *BMRESTRICT block, unsigned *BMRESTRICT first, bm::id64_t digest) BMNOEXCEPT
BIT block find the first set bit if only 1 bit is set.
Definition: bmfunc.h:8547
bm::id64_t update_block_digest0(const bm::word_t *const block, bm::id64_t digest) BMNOEXCEPT
Compute digest for 64 non-zero areas based on existing digest (function revalidates zero areas)
Definition: bmfunc.h:1134
bool bit_block_shift_r1(bm::word_t *BMRESTRICT block, bm::word_t *BMRESTRICT empty_acc, bm::word_t co_flag) BMNOEXCEPT
Right bit-shift bitblock by 1 bit (reference)
Definition: bmfunc.h:5600
unsigned short bitscan_popcnt(bm::id_t w, B *bits, unsigned short offs) BMNOEXCEPT
Unpacks word into list of ON bit indexes using popcnt method.
Definition: bmfunc.h:624
bm::id_t bit_operation_xor_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Performs bitblock XOR operation and calculates bitcount of the result.
Definition: bmfunc.h:8275
unsigned bit_list(T w, B *bits) BMNOEXCEPT
Unpacks word into list of ON bit indexes.
Definition: bmfunc.h:587
void bit_block_copy_unalign(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Bitblock copy operation (unaligned src)
Definition: bmfunc.h:6761
void bit_block_rotate_left_1(bm::word_t *block) BMNOEXCEPT
Definition: bmfunc.h:5499
unsigned bit_block_or_count(const bm::word_t *src1, const bm::word_t *src2) BMNOEXCEPT
Function ORs two bitblocks and computes the bitcount. Function does not analyse availability of sourc...
Definition: bmfunc.h:7338
bm::id_t bit_block_calc_count_range(const bm::word_t *block, bm::word_t left, bm::word_t right) BMNOEXCEPT
Definition: bmfunc.h:5356
void bit_andnot_arr_ffmask(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock AND NOT with constant ~0 mask operation.
Definition: bmfunc.h:8202
unsigned bit_block_xor_count(const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
Function XORs two bitblocks and computes the bitcount. Function does not analyse availability of sour...
Definition: bmfunc.h:7190
unsigned word_select64_linear(bm::id64_t w, unsigned rank) BMNOEXCEPT
word find index of the rank-th bit set by bit-testing
Definition: bmfunc.h:791
void block_compact_by_digest(bm::word_t *t_block, const bm::word_t *block, bm::id64_t digest, bool zero_tail) BMNOEXCEPT
Compact sub-blocks by digest (rank compaction)
Definition: bmfunc.h:1183
void bit_block_stream(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Bitblock copy/stream operation.
Definition: bmfunc.h:6782
bm::word_t * bit_operation_and(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock AND operation.
Definition: bmfunc.h:7418
bm::word_t bit_block_insert(bm::word_t *BMRESTRICT block, unsigned bitpos, bool value) BMNOEXCEPT
insert bit into position and shift the rest right with carryover
Definition: bmfunc.h:5551
bool bit_block_find_interval_start(const bm::word_t *BMRESTRICT block, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Searches for the first 1 bit in the 111 interval of a BIT block.
Definition: bmfunc.h:6239
bm::id64_t bit_block_sub(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock SUB (AND NOT) operation. Function does not analyse availability of source and destinat...
Definition: bmfunc.h:7945
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
unsigned short bitscan_bsf64(bm::id64_t w, B *bits) BMNOEXCEPT
Unpacks word into list of ON bits (BSF/__builtin_ctz)
Definition: bmfunc.h:722
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
bm::id64_t bit_block_xor_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
2 way (target := source1 ^ source2) bitblock XOR operation.
Definition: bmfunc.h:7751
bool is_bits_one(const bm::wordop_t *start) BMNOEXCEPT
Returns "true" if all bits in the block are 1.
Definition: bmfunc.h:6047
bool bit_block_shift_l1(bm::word_t *block, bm::word_t *empty_acc, bm::word_t co_flag) BMNOEXCEPT
Left bit-shift bitblock by 1 bit (reference)
Definition: bmfunc.h:5702
operation
Bit operations.
Definition: bmconst.h:190
set_operation
Codes of set operations.
Definition: bmconst.h:167
@ set_OR
Definition: bmconst.h:169
@ set_SUB
Definition: bmconst.h:170
@ set_COUNT
Definition: bmconst.h:173
@ set_AND
Definition: bmconst.h:168
@ set_XOR
Definition: bmconst.h:171
@ set_END
Definition: bmconst.h:182
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
unsigned gap_bit_count_range(const T *const buf, unsigned left, unsigned right) BMNOEXCEPT
Counts 1 bits in GAP buffer in the closed [left, right] range.
Definition: bmfunc.h:2353
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_find_last(const T *BMRESTRICT buf, unsigned *BMRESTRICT last) BMNOEXCEPT
GAP block find the last set bit.
Definition: bmfunc.h:1639
unsigned gap_bit_count_unr(const T *buf) BMNOEXCEPT
Calculates number of bits ON in GAP buffer. Loop unrolled version.
Definition: bmfunc.h:2287
D gap_convert_to_arr(D *BMRESTRICT dest, const T *BMRESTRICT buf, unsigned dest_len, bool invert=false) BMNOEXCEPT
Convert gap block into array of ints corresponding to 1 bits.
Definition: bmfunc.h:4908
bool gap_find_prev(const T *const BMRESTRICT buf, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
reverse search for the first 1 bit of a GAP block
Definition: bmfunc.h:2577
void gap_and_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr) BMNOEXCEPT
ANDs GAP block to bitblock.
Definition: bmfunc.h:4067
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
gap_word_t * gap_operation_xor(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP XOR operation.
Definition: bmfunc.h:6551
T gap_level(const T *BMRESTRICT buf) BMNOEXCEPT
Returs GAP blocks capacity level.
Definition: bmfunc.h:1621
unsigned gap_buff_any_op(const T *BMRESTRICT vect1, unsigned vect1_mask, const T *BMRESTRICT vect2, unsigned vect2_mask) BMNOEXCEPT2
Abstract distance test operation for GAP buffers. Receives functor F as a template argument.
Definition: bmfunc.h:3026
unsigned gap_bit_count_to(const T *const buf, T right) BMNOEXCEPT
Counts 1 bits in GAP buffer in the closed [0, right] range.
Definition: bmfunc.h:2703
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
void gap_split(const T *buf, T *arr0, T *arr1, T &arr0_cnt, T &arr1_cnt) BMNOEXCEPT
Definition: bmfunc.h:2199
bool gap_find_interval_end(const T *const BMRESTRICT buf, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Searches for the last 1 bit in the 111 interval of a GAP block.
Definition: bmfunc.h:2524
unsigned gap_buff_count_op(const T *vect1, const T *vect2) BMNOEXCEPT2
Abstract distance(similarity) operation for GAP buffers. Receives functor F as a template argument.
Definition: bmfunc.h:3091
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
void gap_xor_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr) BMNOEXCEPT
XOR GAP block to bitblock.
Definition: bmfunc.h:3988
bool gap_shift_r1(T *BMRESTRICT buf, unsigned co_flag, unsigned *BMRESTRICT new_len) BMNOEXCEPT
Right shift GAP block by 1 bit.
Definition: bmfunc.h:3413
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 gapcmp(const T *buf1, const T *buf2) BMNOEXCEPT
Lexicographical comparison of GAP buffers.
Definition: bmfunc.h:2855
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
unsigned gap_find_first(const T *BMRESTRICT buf, unsigned *BMRESTRICT first) BMNOEXCEPT
GAP block find the first set bit.
Definition: bmfunc.h:1670
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
void for_each_gap_dbit(const T *buf, F &func)
Iterate gap block as delta-bits with a functor.
Definition: bmfunc.h:4853
bool gap_insert(T *BMRESTRICT buf, unsigned pos, unsigned val, unsigned *BMRESTRICT new_len) BMNOEXCEPT
isnert bit into GAP compressed block
Definition: bmfunc.h:3466
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
bool gap_find_interval_start(const T *const BMRESTRICT buf, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Searches for the first 1 bit in the 111 interval of a GAP block.
Definition: bmfunc.h:2549
unsigned gap_free_elements(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returns number of free elements in GAP block array. Difference between GAP block capacity on this lev...
Definition: bmfunc.h:4648
unsigned gap_test(const T *BMRESTRICT buf, unsigned pos) BMNOEXCEPT
Tests if bit = pos is true.
Definition: bmfunc.h:1741
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
void gap_invert(T *buf) BMNOEXCEPT
Inverts all bits in the GAP buffer.
Definition: bmfunc.h:4586
unsigned gap_set_array(T *buf, const T *arr, unsigned len) BMNOEXCEPT
Convert array to GAP buffer.
Definition: bmfunc.h:3583
void set_gap_level(T *buf, int level) BMNOEXCEPT
Sets GAP block capacity level.
Definition: bmfunc.h:4605
void gap_sub_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr) BMNOEXCEPT
SUB (AND NOT) GAP block to bitblock.
Definition: bmfunc.h:3900
gap_word_t * gap_operation_and(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP AND operation.
Definition: bmfunc.h:6484
unsigned gap_block_find(const T *BMRESTRICT buf, unsigned nbit, bm::id_t *BMRESTRICT prev) BMNOEXCEPT
Searches for the next 1 bit in the GAP block.
Definition: bmfunc.h:3676
void gap_init_range_block(T *buf, T from, T to, T value) BMNOEXCEPT
Init gap block so it has block in it (can be whole block)
Definition: bmfunc.h:4536
gap_word_t * gap_operation_sub(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP SUB (AND NOT) operation.
Definition: bmfunc.h:6678
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
unsigned gap_control_sum(const T *buf) BMNOEXCEPT
Calculates sum of all words in GAP block. (For debugging purposes)
Definition: bmfunc.h:4487
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
unsigned * gap_convert_to_bitset_smart(unsigned *BMRESTRICT dest, const T *BMRESTRICT buf, id_t set_max) BMNOEXCEPT
Smart GAP block to bitblock conversion.
Definition: bmfunc.h:4466
SIZE_TYPE gap_find_rank(const T *const block, SIZE_TYPE rank, unsigned nbit_from, unsigned &nbit_pos) BMNOEXCEPT
GAP block find position for the rank.
Definition: bmfunc.h:2614
BMFORCEINLINE bool gap_is_all_one(const bm::gap_word_t *BMRESTRICT buf) BMNOEXCEPT
Checks if GAP block is all-one.
Definition: bmfunc.h:1562
unsigned gap_bit_count(const T *buf, unsigned dsize=0) BMNOEXCEPT
Calculates number of bits ON in GAP buffer.
Definition: bmfunc.h:2259
bool gap_shift_l1(T *BMRESTRICT buf, unsigned co_flag, unsigned *BMRESTRICT new_len) BMNOEXCEPT
Left shift GAP block by 1 bit.
Definition: bmfunc.h:3522
void gap_add_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr, unsigned len) BMNOEXCEPT
Adds(OR) GAP block to bitblock.
Definition: bmfunc.h:4016
unsigned gap_overhead(const T *length, const T *length_end, const T *glevel_len) BMNOEXCEPT
Calculates memory overhead for number of gap blocks sharing the same memory allocation table (level l...
Definition: bmfunc.h:8828
bool gap_any_range(const T *const BMRESTRICT buf, unsigned left, unsigned right) BMNOEXCEPT
Test if any bits are 1 in GAP buffer in the [left, right] range.
Definition: bmfunc.h:2466
bool gap_is_all_one_range(const T *const BMRESTRICT buf, unsigned left, unsigned right) BMNOEXCEPT
Test if all bits are 1 in GAP buffer in the [left, right] range.
Definition: bmfunc.h:2443
bool gap_find_first_diff(const T *BMRESTRICT buf1, const T *BMRESTRICT buf2, unsigned *BMRESTRICT pos) BMNOEXCEPT
Find first bit which is different between two GAP-blocks.
Definition: bmfunc.h:2911
unsigned gap_bit_count_range_hint(const T *const buf, unsigned left, unsigned right, unsigned hint) BMNOEXCEPT
Counts 1 bits in GAP buffer in the closed [left, right] range using position hint to avoid bfind.
Definition: bmfunc.h:2401
void gap_set_all(T *buf, unsigned set_max, unsigned value) BMNOEXCEPT
Sets all bits to 0 or 1 (GAP)
Definition: bmfunc.h:4518
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
unsigned bit_array_compute_gaps(const T *arr, unsigned len) BMNOEXCEPT
Compute number of GAPs in bit-array.
Definition: bmfunc.h:3644
unsigned gap_add_value(T *buf, unsigned pos) BMNOEXCEPT
Add new value to the end of GAP buffer.
Definition: bmfunc.h:3343
unsigned bit_block_to_gap(gap_word_t *BMRESTRICT dest, const unsigned *BMRESTRICT block, unsigned dest_len) BMNOEXCEPT
Converts bit block to GAP.
Definition: bmfunc.h:4751
int gap_calc_level(unsigned len, const T *glevel_len) BMNOEXCEPT
Calculates GAP block capacity level.
Definition: bmfunc.h:4627
bool gap_is_interval(const T *const BMRESTRICT buf, unsigned left, unsigned right) BMNOEXCEPT
Test if any bits are 1 in GAP buffer in the [left, right] range and flanked with 0s.
Definition: bmfunc.h:2495
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
bool improve_gap_levels(const T *length, const T *length_end, T *glevel_len) BMNOEXCEPT
Finds optimal gap blocks lengths.
Definition: bmfunc.h:8855
unsigned gap_capacity(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returs GAP block capacity.
Definition: bmfunc.h:1591
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
BMFORCEINLINE bm::gap_word_t gap_length(const bm::gap_word_t *BMRESTRICT buf) BMNOEXCEPT
Returs GAP block length.
Definition: bmfunc.h:1575
Definition: bm.h:78
const unsigned set_array_mask
Definition: bmconst.h:97
bool block_any(const bm::word_t *const BMRESTRICT block) BMNOEXCEPT
Returns "true" if one bit is set in the block Function check for block varieties.
Definition: bmfunc.h:6448
bm::id_t(* bit_operation_count_func_type)(const bm::word_t *BMRESTRICT, const bm::word_t *BMRESTRICT)
Definition: bmfunc.h:9232
unsigned lower_bound_u32(const unsigned *arr, unsigned target, unsigned from, unsigned to) BMNOEXCEPT
Hybrid, binary-linear lower bound search in unsigned array.
Definition: bmfunc.h:9638
const id64_t all_bits_mask
Definition: bmconst.h:131
const unsigned set_block_digest_wave_size
Definition: bmconst.h:67
void for_each_nzblock(T ***root, unsigned size1, F &f)
Definition: bmfunc.h:1868
void bit_block_change_bc(const bm::word_t *BMRESTRICT block, unsigned *BMRESTRICT gc, unsigned *BMRESTRICT bc) BMNOEXCEPT
Definition: bmfunc.h:5218
bool block_is_interval(const bm::word_t *const BMRESTRICT block, unsigned left, unsigned right) BMNOEXCEPT
Returns "true" if all bits are 1 in the block [left, right] and border bits are 0.
Definition: bmfunc.h:6094
bool find_first_nz(const VT *arr, SZ arr_size, SZ *found_idx) BMNOEXCEPT
Find max non-zero value in an array.
Definition: bmfunc.h:9820
bool check_block_zero(const bm::word_t *blk, bool deep_scan) BMNOEXCEPT
Checks all conditions and returns true if block consists of only 0 bits.
Definition: bmfunc.h:8781
void set_nibble(unsigned char *arr, unsigned idx, unsigned char v) BMNOEXCEPT
set nibble in the array
Definition: bmfunc.h:9936
void min_delta_apply(unsigned *arr, size_t arr_size, unsigned delta) BMNOEXCEPT
Recalculate the array to decrement delta as arr[i] = arr[i] - delta + 1 so that array remains monoton...
Definition: bmfunc.h:9782
bool block_is_all_one_range(const bm::word_t *const BMRESTRICT block, unsigned left, unsigned right) BMNOEXCEPT
Returns "true" if all bits are 1 in the block [left, right] Function check for block varieties.
Definition: bmfunc.h:6073
unsigned int word_t
Definition: bmconst.h:39
const unsigned set_block_mask
Definition: bmconst.h:57
bm::id_t bit_block_any_range(const bm::word_t *block, bm::word_t left, bm::word_t right) BMNOEXCEPT
BMFORCEINLINE unsigned bit_scan_forward32(unsigned w) BMNOEXCEPT
Definition: bmutil.h:319
bm::id64_t sum_arr(const T *first, const T *last) BMNOEXCEPT
Definition: bmfunc.h:2181
bool check_block_one(const bm::word_t *blk, bool deep_scan) BMNOEXCEPT
Checks if block has only 1 bits.
Definition: bmfunc.h:8805
unsigned gap_bfind(const T *BMRESTRICT buf, unsigned pos, unsigned *BMRESTRICT is_set) BMNOEXCEPT
Definition: bmfunc.h:1697
SZ count_nz(const VT *arr, SZ arr_size) BMNOEXCEPT
Find count of non-zero elements in the array.
Definition: bmfunc.h:9839
BMFORCEINLINE RTYPE get_block_start(unsigned i, unsigned j) BMNOEXCEPT
Compute bit address of the first bit in a block.
Definition: bmfunc.h:193
unsigned bit_to_gap(gap_word_t *BMRESTRICT dest, const unsigned *BMRESTRICT block, unsigned dest_len) BMNOEXCEPT
Convert bit block to GAP representation.
Definition: bmfunc.h:4836
const unsigned set_sub_array_size
Definition: bmconst.h:95
unsigned bit_block_change64(const bm::word_t *BMRESTRICT in_block, unsigned size) BMNOEXCEPT
Definition: bmfunc.h:5169
void sse4_bit_block_gather_scatter(unsigned *BMRESTRICT arr, const unsigned *BMRESTRICT blk, const unsigned *BMRESTRICT idx, unsigned size, unsigned start, unsigned bit_idx) BMNOEXCEPT
Definition: bmsse4.h:1377
void for_each_dgap(const T *gap_buf, Func &func)
Definition: bmfunc.h:2746
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
unsigned lower_bound_u64(const unsigned long long *arr, unsigned long long target, unsigned from, unsigned to) BMNOEXCEPT
Hybrid, binary-linear lower bound search in unsigned LONG array.
Definition: bmfunc.h:9673
BMFORCEINLINE unsigned bit_scan_reverse32(unsigned w) BMNOEXCEPT
Definition: bmutil.h:304
set_representation
set representation variants
Definition: bmconst.h:216
@ set_bitset
Simple bitset.
Definition: bmconst.h:217
@ set_gap
GAP-RLE compression.
Definition: bmconst.h:218
@ set_array1
array of set 1 values
Definition: bmconst.h:219
@ set_array0
array of 0 values
Definition: bmconst.h:220
unsigned char get_nibble(const unsigned char *arr, unsigned idx) BMNOEXCEPT
get nibble from the array
Definition: bmfunc.h:9965
bool block_ptr_array_range(bm::word_t **arr, unsigned &left, unsigned &right) BMNOEXCEPT
array range detector
Definition: bmfunc.h:9557
gap_word_t *(* gap_operation_func_type)(const gap_word_t *BMRESTRICT, const gap_word_t *BMRESTRICT, gap_word_t *BMRESTRICT, unsigned &)
Definition: bmfunc.h:9226
unsigned block_find_interval_start(const bm::word_t *BMRESTRICT block, unsigned nbit_from, unsigned *BMRESTRICT found_nbit) BMNOEXCEPT
Find start of the current 111 interval.
Definition: bmfunc.h:6362
bool block_find_first_diff(const bm::word_t *BMRESTRICT blk, const bm::word_t *BMRESTRICT arg_blk, unsigned *BMRESTRICT pos) BMNOEXCEPT
Find first bit which is different between two blocks (GAP or bit)
Definition: bmfunc.h:8953
const unsigned gap_levels
Definition: bmconst.h:85
void for_each_nzblock2(T ***root, unsigned size1, F &f)
Definition: bmfunc.h:1977
F bmfor_each(T first, T last, F f)
Definition: bmfunc.h:2168
void bit_recomb(It1 &it1, It2 &it2, BinaryOp &op, Encoder &enc, unsigned block_size=bm::set_block_size) BMNOEXCEPT
Definition: bmfunc.h:9124
bm::operation setop2op(bm::set_operation op) BMNOEXCEPT
Convert set operation to operation.
Definition: bmfunc.h:1311
const unsigned set_word_shift
Definition: bmconst.h:72
bm::id64_t idx_arr_block_lookup_u64(const bm::id64_t *idx, bm::id64_t size, bm::id64_t nb, bm::id64_t start) BMNOEXCEPT
block boundaries look ahead U32
Definition: bmfunc.h:9440
const unsigned set_sub_total_bits
Definition: bmconst.h:100
const unsigned set_block_digest_pos_shift
Definition: bmconst.h:68
unsigned count_leading_zeros_u64(bm::id64_t w) BMNOEXCEPT
64-bit bit-scan reverse
Definition: bmutil.h:373
const unsigned set_block_size
Definition: bmconst.h:55
const bm::gap_word_t * avx2_gap_sum_arr(const bm::gap_word_t *pbuf, unsigned avx_vect_waves, unsigned *sum)
Definition: bmavx2.h:2239
unsigned long long int id64_t
Definition: bmconst.h:35
const unsigned block_waves
Definition: bmconst.h:66
unsigned bit_block_change32(const bm::word_t *BMRESTRICT block, unsigned size) BMNOEXCEPT
Definition: bmfunc.h:5127
bool block_any_range(const bm::word_t *const BMRESTRICT block, unsigned left, unsigned right) BMNOEXCEPT
Returns "true" if one bit is set in the block [left, right] Function check for block varieties.
Definition: bmfunc.h:6427
unsigned lower_bound_linear_u64(const unsigned long long *arr, unsigned long long target, unsigned from, unsigned to) BMNOEXCEPT
Linear lower bound search in unsigned LONG array.
Definition: bmfunc.h:9613
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
int parallel_popcnt_32(unsigned int n) BMNOEXCEPT
32-bit paralle, bitcount
Definition: bmfunc.h:224
BMFORCEINLINE RTYPE get_super_block_start(unsigned i) BMNOEXCEPT
Compute bit address of the first bit in a superblock.
Definition: bmfunc.h:183
bit_representation
Possible representations for bit sets.
Definition: bmfunc.h:9855
@ e_bit_INT
Int list.
Definition: bmfunc.h:9857
@ e_bit_GAP
GAPs.
Definition: bmfunc.h:9856
@ e_bit_bit
uncompressed bit-block
Definition: bmfunc.h:9861
@ e_bit_IINT
Inverted int list.
Definition: bmfunc.h:9858
@ e_bit_end
Definition: bmfunc.h:9862
@ e_bit_1
all 1s
Definition: bmfunc.h:9859
@ e_bit_0
all 0s (empty block)
Definition: bmfunc.h:9860
void set_block_bits_u32(bm::word_t *BMRESTRICT block, const unsigned *BMRESTRICT idx, unsigned start, unsigned stop) BMNOEXCEPT
set bits in a bit-block using global index
Definition: bmfunc.h:9529
void gap_buff_op(T *BMRESTRICT dest, const T *BMRESTRICT vect1, unsigned vect1_mask, const T *BMRESTRICT vect2, unsigned vect2_mask, unsigned &dlen) BMNOEXCEPT2
Abstract operation for GAP buffers. Receives functor F as a template argument.
Definition: bmfunc.h:2951
unsigned idx_arr_block_lookup_u32(const unsigned *idx, unsigned size, unsigned nb, unsigned start) BMNOEXCEPT
block boundaries look ahead U32
Definition: bmfunc.h:9466
BMFORCEINLINE unsigned long long bmi_bslr_u64(unsigned long long w) BMNOEXCEPT
Definition: bmutil.h:335
bm::id64_t ptrp_test(ptr_payload_t ptr, bm::gap_word_t v) BMNOEXCEPT
Definition: bmfunc.h:9995
bool find_ptr(const void *const *p_arr, size_t arr_size, const void *ptr, size_t *idx) BMNOEXCEPT
Scan search for pointer value in unordered array.
Definition: bmfunc.h:9710
const unsigned short set_bitscan_wave_size
Size of bit decode wave in words.
Definition: bmfunc.h:9308
bm::id64_t dm_control(unsigned from, unsigned to) BMNOEXCEPT
digest mask control generation (for debug and test only)
Definition: bmfunc.h:999
const unsigned set_array_shift
Definition: bmconst.h:96
unsigned min_delta_u32(const unsigned *arr, size_t arr_size)
Calculate minimal delta between elements of sorted array.
Definition: bmfunc.h:9753
void dgap_2_gap(const T *BMRESTRICT dgap_buf, T *BMRESTRICT gap_buf, T gap_header=0) BMNOEXCEPT
Convert D-GAP buffer into GAP buffer.
Definition: bmfunc.h:2813
bm::id_t block_to_global_index(unsigned i, unsigned j, unsigned block_idx) BMNOEXCEPT
calculate bvector<> global bit-index from block-local coords
Definition: bmfunc.h:9739
unsigned short gap_word_t
Definition: bmconst.h:78
bool find_max_nz(const VT *arr, SZ arr_size, SZ *found_idx) BMNOEXCEPT
Find max non-zero value in an array.
Definition: bmfunc.h:9799
unsigned count_trailing_zeros_u64(bm::id64_t w) BMNOEXCEPT
64-bit bit-scan fwd
Definition: bmutil.h:419
unsigned bitscan_nibble(unsigned w, unsigned *bits) BMNOEXCEPT
portable, switch based bitscan
Definition: bmfunc.h:374
void(* gap_operation_to_bitset_func_type)(unsigned *, const gap_word_t *)
Definition: bmfunc.h:9222
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
unsigned lower_bound_linear_u32(const unsigned *arr, unsigned target, unsigned from, unsigned to) BMNOEXCEPT
Linear lower bound search in unsigned array.
Definition: bmfunc.h:9590
const unsigned set_block_shift
Definition: bmconst.h:56
void for_each_nzblock_range(T ***root, N top_size, N nb_from, N nb_to, F &f) BMNOEXCEPT
Definition: bmfunc.h:1811
void avx2_bit_block_gather_scatter(unsigned *BMRESTRICT arr, const unsigned *BMRESTRICT blk, const unsigned *BMRESTRICT idx, unsigned size, unsigned start, unsigned bit_idx)
Definition: bmavx2.h:2909
const unsigned set_word_mask
Definition: bmconst.h:73
bool find_not_null_ptr(const bm::word_t *const *const *arr, N start, N size, N *pos) BMNOEXCEPT
Definition: bmfunc.h:1399
BMFORCEINLINE unsigned long long bmi_blsi_u64(unsigned long long w)
Definition: bmutil.h:345
const unsigned bits_in_block
Definition: bmconst.h:114
id64_t wordop_t
Definition: bmconst.h:130
unsigned block_find_interval_end(const bm::word_t *BMRESTRICT block, unsigned nbit_from, unsigned *BMRESTRICT found_nbit) BMNOEXCEPT
Find end of the current 111 interval.
Definition: bmfunc.h:6198
bool block_find_reverse(const bm::word_t *BMRESTRICT block, unsigned nbit_from, unsigned *BMRESTRICT found_nbit) BMNOEXCEPT
Reverse find 1.
Definition: bmfunc.h:6397
unsigned count_trailing_zeros_u32(unsigned w) BMNOEXCEPT
32-bit bit-scan fwd
Definition: bmutil.h:401
const bm::gap_word_t * sse2_gap_sum_arr(const bm::gap_word_t *BMRESTRICT pbuf, unsigned sse_vect_waves, unsigned *sum) BMNOEXCEPT
Gap block population count (array sum) utility.
Definition: bmsse_util.h:1071
T * gap_2_dgap(const T *BMRESTRICT gap_buf, T *BMRESTRICT dgap_buf, bool copy_head=true) BMNOEXCEPT
Convert GAP buffer into D-GAP buffer.
Definition: bmfunc.h:2787
void set_block_bits_u64(bm::word_t *BMRESTRICT block, const bm::id64_t *BMRESTRICT idx, bm::id64_t start, bm::id64_t stop) BMNOEXCEPT
set bits in a bit-block using global index
Definition: bmfunc.h:9499
bool for_each_nzblock_if(T ***root, BI size1, F &f) BMNOEXCEPT
Definition: bmfunc.h:2099
SIZE_TYPE block_find_rank(const bm::word_t *const block, SIZE_TYPE rank, unsigned nbit_from, unsigned &nbit_pos) BMNOEXCEPT
Find rank in block (GAP or BIT)
Definition: bmfunc.h:8682
bool is_const_set_operation(set_operation op) BMNOEXCEPT
Returns true if set operation is constant (bitcount)
Definition: bmfunc.h:1302
all_set_block() BMNOEXCEPT
Definition: bmfunc.h:1335
bm::word_t * _p_fullp
Definition: bmfunc.h:1333
bm::word_t BM_VECT_ALIGN _p[bm::set_block_size] BM_VECT_ALIGN_ATTR
Definition: bmfunc.h:1332
bm::word_t BM_VECT_ALIGN *_s[bm::set_sub_array_size] BM_VECT_ALIGN_ATTR
Definition: bmfunc.h:1331
Structure carries pointer on bit block with all bits 1.
Definition: bmfunc.h:1328
static BMFORCEINLINE bool is_valid_block_addr(const bm::word_t *bp) BMNOEXCEPT
Definition: bmfunc.h:1383
static all_set_block _block
Definition: bmfunc.h:1386
static BMFORCEINLINE bool is_full_block(const bm::word_t *bp) BMNOEXCEPT
Definition: bmfunc.h:1379
static bm::id64_t block_type(const bm::word_t *bp) BMNOEXCEPT
Definition: bmfunc.h:1358
Bit AND functor.
Definition: bmfunc.h:9140
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9141
Bit ASSIGN functor.
Definition: bmfunc.h:9164
W operator()(W, W w2) BMNOEXCEPT
Definition: bmfunc.h:9165
Bit COUNT AND functor.
Definition: bmfunc.h:9180
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9181
Bit COUNT A functor.
Definition: bmfunc.h:9211
W operator()(W w1, W) BMNOEXCEPT
Definition: bmfunc.h:9212
Bit COUNT B functor.
Definition: bmfunc.h:9217
W operator()(W, W w2) BMNOEXCEPT
Definition: bmfunc.h:9218
Bit COUNT OR functor.
Definition: bmfunc.h:9192
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9193
Bit COUNT SUB AB functor.
Definition: bmfunc.h:9199
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9200
Bit SUB BA functor.
Definition: bmfunc.h:9205
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9206
Bit COUNT XOR functor.
Definition: bmfunc.h:9186
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9187
Bit COUNT functor.
Definition: bmfunc.h:9170
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9171
Bit OR functor.
Definition: bmfunc.h:9146
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9147
Bit SUB functor.
Definition: bmfunc.h:9152
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9153
Bit XOR functor.
Definition: bmfunc.h:9158
W operator()(W w1, W w2) BMNOEXCEPT
Definition: bmfunc.h:9159
bit-block array wrapped into union for correct interpretation of 32-bit vs 64-bit access vs SIMD
Definition: bmutil.h:59
bit-decode cache structure
Definition: bmfunc.h:157
bm::id64_t cvalue
Definition: bmfunc.h:160
unsigned short bits[65]
Definition: bmfunc.h:158
Structure with statistical information about memory allocation for arena based vectors.
Definition: bmfunc.h:119
size_t bit_blocks_sz
Total size of bit blocks.
Definition: bmfunc.h:120
size_t gap_blocks_sz
Total size of gap blocks.
Definition: bmfunc.h:121
size_t ptr_sub_blocks_sz
Total size of sub-blocks ptrs.
Definition: bmfunc.h:122
size_t get_alloc_size() const BMNOEXCEPT
Get allocation size in bytes.
Definition: bmfunc.h:132
void reset() BMNOEXCEPT
Reset statisctics.
Definition: bmfunc.h:126
unsigned top_block_size
size of top descriptor
Definition: bmfunc.h:123
Structure with statistical information about memory allocation footprint, serialization projection,...
Definition: bmfunc.h:56
size_t gap_cap_overhead
gap memory overhead between length and capacity
Definition: bmfunc.h:63
size_t ptr_sub_blocks
Number of sub-blocks.
Definition: bmfunc.h:59
void add_gap_block(unsigned capacity, unsigned length, unsigned level) BMNOEXCEPT
count gap block
Definition: bmfunc.h:77
unsigned long long gaps_by_level[bm::gap_levels]
number of GAP blocks at each level
Definition: bmfunc.h:65
size_t gap_blocks
Number of GAP blocks.
Definition: bmfunc.h:58
size_t bit_blocks
Number of bit blocks.
Definition: bmfunc.h:57
size_t bv_count
Number of bit-vectors.
Definition: bmfunc.h:60
gap_word_t gap_levels[bm::gap_levels]
GAP block lengths in the bvect.
Definition: bmfunc.h:64
size_t max_serialize_mem
estimated maximum memory for serialization
Definition: bmfunc.h:61
void reset() BMNOEXCEPT
Reset statisctics.
Definition: bmfunc.h:92
void add_bit_block() BMNOEXCEPT
cound bit block
Definition: bmfunc.h:68
size_t memory_used
memory usage for all blocks and service tables
Definition: bmfunc.h:62
void add(const bv_statistics &st) BMNOEXCEPT
Sum data from another sttructure.
Definition: bmfunc.h:101
d-Gap copy functor
Definition: bmfunc.h:2766
d_copy_func(T *dg_buf)
Definition: bmfunc.h:2767
void operator()(T dgap)
Definition: bmfunc.h:2768
static bit_operation_count_func_type bit_operation_count(unsigned i)
Definition: bmfunc.h:9259
static gap_operation_to_bitset_func_type gap_op_to_bit(unsigned i)
Definition: bmfunc.h:9247
static bit_operation_count_func_type bit_op_count_table_[bm::set_END]
Definition: bmfunc.h:9244
static gap_operation_func_type gap_operation(unsigned i)
Definition: bmfunc.h:9253
static gap_operation_func_type gapop_table_[bm::set_END]
Definition: bmfunc.h:9242
static gap_operation_to_bitset_func_type gap2bit_table_[bm::set_END]
Definition: bmfunc.h:9240
Pair type.
Definition: bmfunc.h:146
Second second
Definition: bmfunc.h:148
pair(First f, Second s)
Definition: bmfunc.h:150
First first
Definition: bmfunc.h:147
helper union to interpret pointer as integers
Definition: bmfunc.h:9984
bm::word_t * blk
Definition: bmfunc.h:9985
bm::id64_t i64
Definition: bmfunc.h:9986
unsigned short i16[4]
Definition: bmfunc.h:9987