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