23#include "pasta/bit_vector/bit_vector.hpp"
24#include "pasta/bit_vector/support/find_l2_wide_with.hpp"
28#include "pasta/bit_vector/support/wide_rank.hpp"
33#include <tlx/container/simple_vector.hpp>
34#include <tlx/math.hpp>
61 typename VectorType = BitVector>
65 using WideRank<optimized_for>::data_size_;
68 using WideRank<optimized_for>::data_;
77 using Array = tlx::SimpleVector<T, tlx::SimpleVectorMode::NoInitNoDestroy>;
81 std::vector<uint32_t> samples0_;
83 std::vector<uint32_t> samples1_;
113 [[nodiscard(
"select0 computed but not used")]]
size_t
115 size_t const l1_end = l1_.size();
116 size_t const l2_end = l2_.size();
119 size_t l1_pos = l2_pos / 128;
122 while (l1_pos + 1 < l1_end &&
130 while (l1_pos + 1 < l1_end && l1_[l1_pos + 1] < rank) {
136 l2_pos = std::max(l1_pos * 128, l2_pos);
141 while (l2_pos + 1 < l2_end &&
150 while (l2_pos + 1 < l2_end && l2_[l2_pos + 1] < rank) {
156 size_t const end = std::min((l1_pos + 1) * 128, l2_end);
157 size_t const iterations = tlx::integer_log2_ceil(end - l2_pos + 1);
158 size_t size = 1ULL << (iterations - 1);
159 size_t mid = end - size;
163 size_t start_next_left = l2_pos;
164 size_t start_next_right = mid + 1;
167 size_t const offset = (128 * l1_pos);
176 __builtin_prefetch(&l2_[start_next_left + size], 0, 0);
177 __builtin_prefetch(&l2_[start_next_right + size], 0, 0);
184 start_next_right = start_next_left + size;
185 mid = start_next_left + size - 1;
203 __builtin_prefetch(&l2_[start_next_left + size], 0, 0);
204 __builtin_prefetch(&l2_[start_next_right + size], 0, 0);
207 (rank > l2_[mid]) ? start_next_right : start_next_left;
208 start_next_right = start_next_left + size;
209 mid = start_next_left + size - 1;
212 l2_pos = (rank > l2_[mid]) ? mid : start_next_left - 1;
220 while ((
popcount = pasta::popcount_zeros<1>(data_ + last_pos)) < rank) {
224 return (last_pos * 64) +
select(~data_[last_pos], rank - 1);
232 [[nodiscard(
"select1 computed but not used")]]
size_t
234 size_t const l1_end = l1_.size();
235 size_t const l2_end = l2_.size();
238 size_t l1_pos = l2_pos / 128;
241 while (l1_pos + 1 < l1_end && l1_[l1_pos + 1] < rank) {
246 while (l1_pos + 1 < l1_end &&
255 l2_pos = std::max(l1_pos * 128, l2_pos);
259 while (l2_pos + 1 < l2_end && l2_[l2_pos + 1] < rank) {
265 while (l2_pos + 1 < l2_end &&
275 size_t const end = std::min((l1_pos + 1) * 128, l2_end);
276 size_t const iterations = tlx::integer_log2_ceil(end - l2_pos + 1);
277 size_t size = 1ULL << (iterations - 1);
278 size_t mid = end - size;
282 size_t start_next_left = l2_pos;
283 size_t start_next_right = mid + 1;
294 __builtin_prefetch(&l2_[start_next_left + size], 0, 0);
295 __builtin_prefetch(&l2_[start_next_right + size], 0, 0);
298 (rank > l2_[mid]) ? start_next_right : start_next_left;
299 start_next_right = start_next_left + size;
300 mid = start_next_left + size - 1;
303 l2_pos = (rank > l2_[mid]) ? mid : start_next_left - 1;
306 size_t const offset = (128 * l1_pos);
315 __builtin_prefetch(&l2_[start_next_left + size], 0, 0);
316 __builtin_prefetch(&l2_[start_next_right + size], 0, 0);
323 start_next_right = start_next_left + size;
324 mid = start_next_left + size - 1;
339 while ((
popcount = pasta::popcount<1>(data_ + last_pos)) < rank) {
343 return (last_pos * 64) +
select(data_[last_pos], rank - 1);
350 [[nodiscard(
"space usage computed but not used")]]
size_t
352 return samples0_.size() *
sizeof(uint32_t) +
353 samples1_.size() *
sizeof(uint32_t) +
360 size_t const l2_end = l2_.size();
361 size_t next_sample0_value = 1;
362 size_t next_sample1_value = 1;
363 for (
size_t l2_pos = 0, offset = 0; l2_pos < l2_end; ++l2_pos) {
364 offset = l1_[l2_pos / 128];
367 (offset + l2_[l2_pos] >= next_sample1_value)) {
368 samples0_.push_back(l2_pos - 1);
371 if (offset + l2_[l2_pos] >= next_sample1_value) {
372 samples1_.push_back(l2_pos - 1);
376 if (offset + l2_[l2_pos] >= next_sample1_value) {
377 samples0_.push_back(l2_pos - 1);
381 (offset + l2_[l2_pos] >= next_sample1_value)) {
382 samples1_.push_back(l2_pos - 1);
Select support for BitVector.
Definition wide_rank_select.hpp:62
WideRankSelect(WideRankSelect &&other)=default
Default move constructor.
size_t space_usage() const override
Estimate for the space usage.
Definition wide_rank_select.hpp:351
WideRankSelect(VectorType &bv)
Constructor. Creates the auxiliary information for efficient rank and select queries.
Definition wide_rank_select.hpp:95
size_t select0(size_t rank) const
Get position of specific zero, i.e., select.
Definition wide_rank_select.hpp:114
size_t select1(size_t rank) const
Get position of specific one, i.e., select.
Definition wide_rank_select.hpp:233
WideRankSelect()=default
Default constructor w/o parameter.
WideRankSelect & operator=(WideRankSelect &&other)=default
Default move assignment.
~WideRankSelect()=default
Destructor. Deleting manually created arrays.
Rank support for BitVector that can be used as an alternative to Rank for bit vectors up to length 2^...
Definition wide_rank.hpp:76
OptimizedFor
Enum used to specify which queries the rank (and select) data structures should be optimized for.
Definition optimized_for.hpp:40
constexpr bool use_linear_search(FindL2FlatWith const find_with)
Helper function indicating whether a linear search function should be used.
Definition find_l2_flat_with.hpp:48
constexpr bool optimize_one_or_dont_care(OptimizedFor const optimized_for)
Helper function indicating if queries should be optimized for one queries or the caller does not care...
Definition optimized_for.hpp:59
constexpr bool use_binary_search(FindL2FlatWith const find_with)
Helper function indicating whether a binary search function should be used.
Definition find_l2_flat_with.hpp:59
FindL2WideWith
Enum used to specify whether intrinsic functions should be used.
Definition find_l2_wide_with.hpp:35
@ DONT_CARE
It does not matter (both types are called equally often).
uint64_t popcount(uint64_t const *const buffer)
Compute popcount of a specific number of 64-bit words.
Definition popcount.hpp:41
uint64_t select(uint64_t x, uint64_t k)
Select set bit in 64-bit word and return its position starting from the LSB (starting from the left).
Definition select.hpp:144
static constexpr size_t L2_WORD_SIZE
Number of 64-bit words covered by an L2-block.
Definition wide_rank.hpp:46
static constexpr size_t L1_BIT_SIZE
Bits covered by an L1-block.
Definition wide_rank.hpp:43
static constexpr size_t SELECT_SAMPLE_RATE
Sample rate of positions for faster select queries.
Definition wide_rank.hpp:51
static constexpr size_t L2_BIT_SIZE
Bits covered by an L2-block.
Definition wide_rank.hpp:41