1 #ifndef BM__H__INCLUDED__
2 #define BM__H__INCLUDED__
30 # include <initializer_list>
37 #pragma warning( push )
38 #pragma warning( disable : 4311 4312 4127)
47 # define BM_DECLARE_TEMP_BLOCK(x) bm::bit_block_t x;
113 template<
class Alloc>
297 if (this->
bv_ != ib.bv_)
return false;
298 if (this->
position_ != ib.position_)
return false;
299 if (this->
block_ != ib.block_)
return false;
300 if (this->
block_type_ != ib.block_type_)
return false;
301 if (this->
block_idx_ != ib.block_idx_)
return false;
303 const block_descr& bd = this->
bdescr_;
304 const block_descr& ib_db = ib.bdescr_;
308 if (bd.bit_.ptr != ib_db.bit_.ptr)
return false;
309 if (bd.bit_.idx != ib_db.bit_.idx)
return false;
310 if (bd.bit_.cnt != ib_db.bit_.cnt)
return false;
311 if (bd.bit_.pos != ib_db.bit_.pos)
return false;
312 for (
unsigned i = 0;
i < bd.bit_.cnt; ++
i)
314 if (bd.bit_.bits[
i] != ib_db.bit_.bits[
i])
return false;
319 if (bd.gap_.ptr != ib_db.gap_.ptr)
return false;
320 if (bd.gap_.gap_len != ib_db.gap_.gap_len)
return false;
517 buf_ = iit.buf_; iit.buf_ = 0;
538 buf_ = ii.buf_; ii.buf_ = 0;
695 return this->
valid();
743 bit_count_ = this->
valid();
751 this->bit_count_ = 1;
758 this->bit_count_ += this->
valid();
764 counted_enumerator
tmp(*
this);
766 this->bit_count_ += this->
valid();
811 : strat(s), glevel_len(glevels)
924 void init(
unsigned top_size,
bool alloc_subs);
956 std::initializer_list<size_type>::const_iterator it_start = il.begin();
957 std::initializer_list<size_type>::const_iterator it_end = il.end();
958 for (; it_start < it_end; ++it_start)
1287 insert_iterator
inserter() {
return insert_iterator(*
this); }
1944 statistics* stat = 0);
2081 const size_type ids_size,
bool opt_flag);
2207 unsigned nbit_right,
2217 unsigned nbit_right,
2234 template<class
Alloc>
2245 template<
class Alloc>
2256 template<
class Alloc>
2267 template<
class Alloc>
2279 template<
typename Alloc>
2288 template<
typename Alloc>
2295 for (
unsigned nb = 0; nb < top_size; ++nb)
2302 template<
typename Alloc>
2339 template<
typename Alloc>
2352 template<
class Alloc>
2367 template<
typename Alloc>
2400 template<
typename Alloc>
2411 for (
unsigned i = 0;
i < top_blocks; ++
i)
2420 blk_blk = blk_root[
i];
2450 template<
typename Alloc>
2462 template<
typename Alloc>
2467 if (
size_ == new_size)
return;
2468 if (
size_ < new_size)
2485 template<
typename Alloc>
2500 template<
typename Alloc>
2540 for (
unsigned i = 0;
i < max_top_blocks; ++
i)
2566 bcount[j] = 0; sub_count[j] = 0;
2569 unsigned local_first, local_second, local_third;
2591 if (is_set) aux0 |= 1;
2594 if (is_set) aux1 |= 1;
2613 unsigned cnt = local_first + local_second + local_third;
2617 if (bv_blocks &&
cnt)
2621 sub_count[j] =
bm::id64_t(local_first | (local_second << 16)) |
2622 (aux0 << 32) | (aux1 << 48);
2635 template<
typename Alloc>
2649 #define BM_BORDER_TEST(blk, idx) bool(blk[idx >> bm::set_word_shift] & (1u << (idx & bm::set_word_mask)))
2652 #if (defined(BMSSE42OPT) || defined(BMAVX2OPT) || defined(BMAVX512OPT) || \
2653 defined(BMWASMSIMDOPT) || defined(BMNEONOPT))
2656 template<
typename Alloc>
2660 unsigned nbit_right,
2667 unsigned sub_cnt = unsigned(sub);
2668 unsigned first = sub_cnt & 0xFFFF;
2669 unsigned second = sub_cnt >> 16;
2678 unsigned cnt1, aux1(
bm::gap_word_t(sub >> 48)); (void)aux1; (void) cnt1;
2683 #if defined(BM64_SSE4) || defined(BM64_AVX2) || defined(BM64_AVX512)
2686 const unsigned cutoff_bias = 0;
2689 unsigned sub_range = rs_idx.find_sub_range(nbit_right);
2699 c = bm::bit_block_calc_count_range<true, false>(block, 0, nbit_right);
2723 bm::bit_block_calc_count_range<true, false>(block,
2730 unsigned bc_second_range =
first + second;
2734 c = bc_second_range;
2748 c = bc_second_range - c;
2753 c = bm::bit_block_calc_count_range<true, false>(
2774 c = bm::bit_block_calc_count_range<true, false>(block,
2777 c +=
first + second;
2802 c = rs_idx.count(nb);
2822 c = bm::bit_block_calc_count_range<true, false>(block,
2844 template<
typename Alloc>
2848 unsigned nbit_right,
2854 unsigned sub_cnt = unsigned(sub);
2855 unsigned first = sub_cnt & 0xFFFF;
2856 unsigned second = sub_cnt >> 16;
2865 unsigned cnt1, aux1(
bm::gap_word_t(sub >> 48)); (void)aux1; (void) cnt1;
2870 unsigned sub_choice =
2876 c = bm::bit_block_calc_count_range<true, false>(block, 0, nbit_right);
2886 c = bm::bit_block_calc_count_range<true, false>(block,
2896 c =
first + second - c;
2899 c = bm::bit_block_calc_count_range<true, false>(
2907 c = bm::bit_block_calc_count_range<true, false>(block,
2910 c +=
first + second;
2923 c = rs_idx.count(nb);
2929 c = rs_idx.count(nb) - c;
2932 c = bm::bit_block_calc_count_range<true, false>(block,
2946 #undef BM_BORDER_TEST
2950 template<
typename Alloc>
2954 unsigned nbit_right,
2986 unsigned sub_cnt = unsigned(sub);
2988 unsigned second = (sub_cnt >> 16);
2997 unsigned sub_range = rs_idx.find_sub_range(nbit_right);
3043 c =
first + second - c;
3055 c +=
first + second;
3062 c = rs_idx.count(nb);
3067 c = bm::gap_bit_count_range<bm::gap_word_t, true> (gap_block,
3086 template<
typename Alloc>
3100 if (nb_right >= rs_idx.get_total())
3102 cnt = rs_idx.count();
3105 cnt = nb_right ? rs_idx.rcount(nb_right-1) : 0;
3118 c = this->
gap_count_to(gap_block, nb_right, nbit_right, rs_idx);
3124 return cnt + nbit_right + 1;
3139 template<
typename Alloc>
3189 cnt += nb_right ? rs_idx.rcount(nb_right - 1) : 0;
3195 template<
typename Alloc>
3207 size_type cnt = nblock_right ? rs_idx.rcount(nblock_right - 1) : 0;
3219 cnt += bm::gap_bit_count_to<bm::gap_word_t, true>(
3240 template<
typename Alloc>
3256 template<
typename Alloc>
3302 if (nblock_left == nblock_right)
3312 nblock_left+1, nblock_right-1, func);
3337 template<
typename Alloc>
3360 if (nblock_left == nblock_right)
3390 if (nblock_left <= nblock_right)
3392 unsigned i_from, j_from, i_to, j_to;
3398 for (
unsigned i = i_from;
i <= i_to; ++
i)
3406 unsigned j = (
i == i_from) ? j_from : 0;
3413 }
while (++j < j_limit);
3421 template<
typename Alloc>
3443 if (nblock_left == nblock_right)
3473 if (nblock_left <= nblock_right)
3475 unsigned i_from, j_from, i_to, j_to;
3482 if (i_from >= top_size)
3484 if (i_to >= top_size)
3486 i_to = unsigned(top_size-1);
3491 for (
unsigned i = i_from;
i <= i_to; ++
i)
3499 unsigned j = (
i == i_from) ? j_from : 0;
3506 }
while (++j < j_limit);
3514 template<
typename Alloc>
3528 template<
typename Alloc>
3536 return this->
test(left);
3539 cnt_l = this->
count_to(left-1, rs_idx);
3542 cnt_r = this->
count_to(right, rs_idx);
3544 return cnt_r - cnt_l;
3549 template<
typename Alloc>
3559 for (
unsigned i = 0;
i < top_blocks; ++
i)
3601 template<
typename Alloc>
3618 if (!blk_blk)
return false;
3634 template<
typename Alloc>
3670 template<
typename Alloc>
3684 for (; nblock_left <= nblock_right; ++nblock_left)
3699 template<
typename Alloc>
3713 ::memcpy(opt_glen, st.gap_levels, bm::gap_levels * sizeof(*opt_glen));
3716 st.gap_length + st.gap_blocks,
3725 template<typename Alloc>
3743 template<
typename Alloc>
3748 unsigned bvect_top_blocks = bv.blockman_.top_block_size();
3750 if (bvect_top_blocks > top_blocks) top_blocks = bvect_top_blocks;
3752 for (
unsigned i = 0;
i < top_blocks; ++
i)
3755 const bm::word_t*
const* arg_blk_blk = bv.blockman_.get_topblock(
i);
3757 if (blk_blk == arg_blk_blk)
3767 arg_blk = arg_blk_blk ? arg_blk_blk[j] : 0;
3775 blk = blk_blk ? blk_blk[j] : 0;
3779 if (blk == arg_blk)
continue;
3784 if (!blk || !arg_blk)
3861 template<
typename Alloc>
3869 if (!top_blocks || !top_root)
3874 unsigned i_to, j_to;
3877 if (!bvect_top_blocks || !arg_top_root)
3879 bool f = this->
find(pos);
3882 if (pos > search_to)
3888 if (bvect_top_blocks > top_blocks)
3889 top_blocks = bvect_top_blocks;
3893 if (i_to < top_blocks)
3894 top_blocks = i_to+1;
3896 for (
unsigned i = 0;
i < top_blocks; ++
i)
3901 if (blk_blk == arg_blk_blk)
3945 if (pos > search_to)
3965 template<
typename Alloc>
3977 template<
typename Alloc>
3984 ::memcpy(st->gap_levels,
3987 st->max_serialize_mem = unsigned(
sizeof(
bm::id_t) * 4);
3993 blocks_mem +=
sizeof(
bm::word_t**) * top_size;
3998 for (
unsigned i = 0;
i < top_size; ++
i)
4007 blk_blk = blk_root[
i];
4014 st->ptr_sub_blocks++;
4028 st->add_gap_block(cap,
len, level);
4031 st->add_bit_block();
4037 st->max_serialize_mem += full_null_size;
4041 size_t safe_inc = st->max_serialize_mem / 10;
4042 if (!safe_inc) safe_inc = 256;
4043 st->max_serialize_mem += safe_inc;
4046 st->memory_used += unsigned(
sizeof(*
this) -
sizeof(
blockman_));
4048 st->memory_used += blocks_mem;
4057 template<
typename Alloc>
4066 for (
unsigned i = 0;
i < top_size; ++
i)
4087 template<
class Alloc>
4093 if (!ids || !ids_size)
4098 import(ids, ids_size, so);
4104 template<
class Alloc>
4116 bv_tmp.
import(ids, ids_size, so);
4134 template<
class Alloc>
4148 template<
class Alloc>
4159 bv_tmp.
import(ids, ids_size, so);
4176 template<
class Alloc>
4187 template<
class Alloc>
4198 template<
class Alloc>
4201 if (
val == condition)
return false;
4212 template<
class Alloc>
4226 template<
class Alloc>
4244 template<
class Alloc>
4261 if (nblock == nblock_end)
4284 }
while (start < size_in);
4289 template<
class Alloc>
4305 if (nblock == nblock_end)
4309 if (opt_flag && nbit == 65535)
4331 }
while (start < size_in);
4340 nblock_end +=
bool(nbit == 65535);
4346 }
while (nblock < nblock_end);
4355 template<
class Alloc>
4370 if (stop-start == 1)
4390 template<
class Alloc>
4401 unsigned nbit1, nbit2;
4422 if (block1 == block2)
4432 bool b1 = block1[nword1] & (1u << nbit1);
4433 bool b2 = block1[nword2] & (1u << nbit2);
4436 nbit1 = 1u << nbit1; nbit2 = 1u << nbit2;
4437 auto w = block1[nword1];
4438 (b2) ? w |= nbit1 : w &= ~nbit1;
4441 (b1) ? w |= nbit2 : w &= ~nbit2;
4454 if (block1 == block2)
4458 unsigned cpos1{ 0 }, cpos2{ 0 };
4459 bool b1, b2, b1real, b2real;
4463 b1 =
false; b1real =
false;
4468 b1 =
true; b1real =
false;
4490 b2 =
false; b2real =
false;
4495 b2 =
true; b2real =
false;
4522 unsigned new_len, old_len;
4523 unsigned is_set = b1;
4526 if (old_len < new_len)
4529 if (new_len > threshold)
4537 auto w = block1[nword1];
4538 (b2) ? w |= nbit1 : w &= ~nbit1;
4551 unsigned new_len, old_len;
4552 unsigned is_set = b2;
4555 if (old_len < new_len)
4558 if (new_len > threshold)
4566 auto w = block2[nword2];
4567 (b1) ? w |= nbit2 : w &= ~nbit2;
4581 template<
class Alloc>
4630 template<
class Alloc>
4636 const bool val =
true;
4658 blk[nword] |= (1u << nbit);
4664 template<
class Alloc>
4670 const bool val =
false;
4691 blk[nword] &= ~(1u << nbit);
4698 template<
class Alloc>
4703 unsigned is_set, new_len, old_len;
4706 if (old_len < new_len)
4709 if (new_len > threshold)
4717 template<
class Alloc>
4721 unsigned new_len, old_len;
4724 if (old_len < new_len)
4727 if (new_len > threshold)
4735 template<
class Alloc>
4760 is_set = ((*word) &
mask);
4768 template<
class Alloc>
4787 if (block_type == 1)
4800 bool is_set = ((*word) &
mask) != 0;
4802 if (is_set != condition)
4820 template<
class Alloc>
4839 if (block_type == 1)
4844 bool new_val =
val & old_val;
4845 if (new_val != old_val)
4859 bool is_set = ((*word) &
mask) != 0;
4861 bool new_val = is_set &
val;
4880 template<
class Alloc>
4895 template<
class Alloc>
4903 for (
unsigned i = top_blocks-1;
true; --
i)
4934 pos = base_idx + block_pos;
4952 template<
class Alloc>
4961 return this->
test(from);
4972 unsigned found_nbit;
4977 base_idx = bm::get_block_start<size_type>(i0, j0);
4978 pos = base_idx + found_nbit;
4994 for (
unsigned j = j0;
true; --j)
5017 pos = base_idx + block_pos;
5030 for (
unsigned i = i0;
true; --
i)
5060 pos = base_idx + block_pos;
5077 template<
class Alloc>
5083 for (
unsigned i = 0;
i < top_blocks; ++
i)
5099 found =
true; block_pos = 0;
5111 pos = base_idx + block_pos;
5123 template<
class Alloc>
5127 bool found =
find(in_first);
5136 in_first = in_last = 0;
5143 template<
class Alloc>
5157 unsigned bit_pos = 0;
5196 template<
class Alloc>
5208 (rs_idx.count() < rank_in))
5216 nb = rs_idx.find(rank_in);
5217 BM_ASSERT(rs_idx.rcount(nb) >= rank_in);
5219 rank_in -= rs_idx.rcount(nb-1);
5223 unsigned bit_pos = 0;
5225 for (; nb < rs_idx.get_total(); ++nb)
5233 unsigned block_bc = rs_idx.count(nb);
5234 if (rank_in <= block_bc)
5236 nbit = rs_idx.select_sub_range(nb, rank_in);
5242 rank_in -= block_bc;
5267 template<
class Alloc>
5275 (rs_idx.count() < rank_in))
5280 bool found = rs_idx.find(&rank_in, &nb, &sub_range_from);
5290 unsigned bit_pos = 0;
5294 bit_pos = sub_range_from + unsigned(rank_in) - 1;
5307 template<
class Alloc>
5348 for (;
i < top_blocks; ++
i)
5365 found =
true; block_pos = 0;
5377 prev = base_idx + block_pos;