26template<
typename IntT>
29 if (
bits.is_empty()) {
34 constexpr int64_t max_index = std::numeric_limits<IntT>::max() - 1;
37 auto append_range = [&](
const IndexRange range) {
39 builder.
add_range(IntT(range.start()), IntT(range.one_after_last()));
42 auto process_bit_int = [&](
const BitInt value,
49 if (masked_value == 0) {
53 if (masked_value ==
mask) {
58 const int64_t bit_i_to_output_offset = start - start_bit;
64 BitInt current_value = masked_value;
65 while (current_value != 0) {
71 if (find_unset_value == 0) {
74 append_range(range.
shift(bit_i_to_output_offset));
81 append_range(range.
shift(bit_i_to_output_offset));
110 for (; int_i + 1 < ints_to_check; int_i += 2) {
112 const __m128i group = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(start + int_i));
114 const bool group_is_zero = _mm_testz_si128(group, group);
119 for (
int j = 0; j < 2; j++) {
127 for (; int_i < ints_to_check; int_i++) {
MINLINE unsigned int bitscan_forward_uint64(unsigned long long a)
#define UNUSED_VARS_NDEBUG(...)
BMesh const char void * data
constexpr IndexRange shift(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
constexpr int64_t start() const
bool add_range(const T start, const T end)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static constexpr BitInt BitIndexMask
static constexpr int64_t BitsPerInt
BitInt * int_containing_bit(BitInt *data, const int64_t bit_index)
void bits_to_index_ranges(const BitSpan bits, IndexRangesBuilder< IntT > &builder)
BitInt mask_first_n_bits(const int64_t n)
BitInt mask_range_bits(const int64_t start, const int64_t size)
AlignedIndexRanges split_index_range_by_alignment(const IndexRange range, const int64_t alignment)