254 template<
typename Fn>
274 template<
typename T,
typename Fn>
277 Fn &&get_group_index,
309 std::optional<RawMaskIterator>
find(
int64_t query_index)
const;
411 template<
typename IndexT,
typename Fn>
471 std::optional<IndexRange>
to_range()
const;
486 template<
int64_t N = 4>
506 const int16_t *segment_indices_;
507 std::array<int64_t, 2> cumulative_segment_sizes_;
518 cumulative_segment_sizes_[0] = 0;
519 data.segments_num_ = 1;
520 data.indices_by_segment_ = &segment_indices_;
521 data.segment_offsets_ = &segment_offset_;
522 data.cumulative_segment_sizes_ = cumulative_segment_sizes_.data();
523 data.begin_index_in_segment_ = 0;
530 BLI_assert(std::is_sorted(indices.begin(), indices.end()));
533 const int64_t indices_num = indices.size();
536 segment_offset_ = segment.offset();
537 segment_indices_ = indices.data();
538 cumulative_segment_sizes_[1] =
int16_t(indices_num);
539 data.indices_num_ = indices_num;
540 data.end_index_in_segment_ = indices_num;
555 alignas(64)
static const std::array<int16_t, max_segment_size> data =
563 mask.foreach_index_optimized<
int64_t>([&](
const int64_t i) { data[i] = value; });
589 return a.segment_i !=
b.segment_i || a.index_in_segment !=
b.index_in_segment;
629 static constexpr int64_t cumulative_sizes_for_empty_mask[1] = {0};
631 data.indices_num_ = 0;
632 data.segments_num_ = 0;
633 data.cumulative_segment_sizes_ = cumulative_sizes_for_empty_mask;
658 if (range.is_empty()) {
662 const int64_t one_after_last = range.one_after_last();
721 return this->
last() + 1;
734 [&](
const int64_t cumulative_size) {
return cumulative_size > full_index; });
775 const int64_t segment_size = end_index - begin_index;
782 return this->
slice(range.
start(), range.size());
792 std::is_invocable_r_v<void, Fn, IndexMaskSegment, int64_t> ||
793 std::is_invocable_r_v<void, Fn, IndexRange, int64_t>;
799 if constexpr (std::is_invocable_r_v<void, Fn, int64_t, int64_t>) {
800 for (
const int64_t i : indices.index_range()) {
801 fn(indices[i], start_segment_pos + i);
816 const IndexMask sub_mask = this->slice(range);
817 sub_mask.foreach_index([&](const int64_t i, [[maybe_unused]] const int64_t index_pos) {
818 if constexpr (std::is_invocable_r_v<void, Fn, int64_t, int64_t>) {
819 fn(i, index_pos + range.start());
828template<
typename T,
typename Fn>
829#if (defined(__GNUC__) && !defined(__clang__))
830[[gnu::optimize(
"O3")]]
835 BLI_assert(segment.last() < std::numeric_limits<T>::max());
837 const T start =
T(segment[0]);
838 const T last =
T(segment.last());
839 for (T i = start; i <= last; i++) {
844 for (
const int64_t i : segment) {
850template<
typename T,
typename Fn>
851#if (defined(__GNUC__) && !defined(__clang__))
852[[gnu::optimize(
"O3")]]
859 BLI_assert(segment.last() < std::numeric_limits<T>::max());
860 BLI_assert(segment.size() + segment_pos < std::numeric_limits<T>::max());
862 const T start =
T(segment[0]);
863 const T last =
T(segment.last());
864 for (T i = start,
pos =
T(segment_pos); i <= last; i++,
pos++) {
869 T
pos =
T(segment_pos);
870 for (
const int64_t i : segment.index_range()) {
871 const T index =
T(segment[i]);
878template<
typename IndexT,
typename Fn>
883 if constexpr (std::is_invocable_r_v<void, Fn, IndexT, IndexT>) {
892template<
typename IndexT,
typename Fn>
896 const IndexMask sub_mask = this->slice(range);
897 sub_mask.foreach_segment(
898 [&](const IndexMaskSegment segment, [[maybe_unused]] const int64_t segment_pos) {
899 if constexpr (std::is_invocable_r_v<void, Fn, IndexT, IndexT>) {
900 optimized_foreach_index_with_pos<IndexT>(segment, segment_pos + range.start(), fn);
903 optimized_foreach_index<IndexT>(segment, fn);
914 const IndexRange range(segment[0], segment.size());
915 if constexpr (has_segment_and_start_parameter<Fn>) {
916 fn(range, start_segment_pos);
924 fn(segment, start_segment_pos);
937 const IndexMask sub_mask = this->slice(range);
938 sub_mask.foreach_segment_optimized(
939 [&fn, range_start = range.start()](const auto segment,
940 [[maybe_unused]] const int64_t start_segment_pos) {
941 if constexpr (has_segment_and_start_parameter<Fn>) {
942 fn(segment, start_segment_pos + range_start);
953 [[maybe_unused]]
int64_t segment_pos = 0;
957 fn(segment, segment_pos);
958 segment_pos += segment.size();
970 const IndexMask sub_mask = this->slice(range);
971 sub_mask.foreach_segment(
972 [&fn, range_start = range.start()](const IndexMaskSegment mask_segment,
973 [[maybe_unused]] const int64_t segment_pos) {
974 if constexpr (has_segment_and_start_parameter<Fn>) {
975 fn(mask_segment, segment_pos + range_start);
989 const int64_t next_range_size = unique_sorted_indices::find_size_of_next_range(base_indices);
990 const IndexRange range(int64_t(base_indices[0]) + indices.offset(), next_range_size);
991 if constexpr (has_segment_and_start_parameter<Fn>) {
992 fn(range, segment_pos);
997 segment_pos += next_range_size;
998 base_indices = base_indices.
drop_front(next_range_size);
1011template<
typename Fn>
1022 int16_t *r_current = r_true_indices;
1023 const int16_t *in_end = indices.base_span().end();
1024 const int64_t offset = indices.offset();
1025 for (
const int16_t *in_current = indices.base_span().data(); in_current < in_end;
1027 const int16_t local_index = *in_current;
1029 const bool condition = predicate(global_index);
1030 *r_current = local_index;
1035 r_current += condition;
1037 const int16_t true_indices_num =
int16_t(r_current - r_true_indices);
1038 return true_indices_num;
1042template<
typename T,
typename Fn>
1045 Fn &&get_group_index,
1050 const int group_index = get_group_index(i);
1051 indices_by_group[group_index].
append(
T(i));
1068 return std::nullopt;
constexpr int64_t start() const
static constexpr IndexRange from_begin_end_inclusive(const int64_t begin, const int64_t last)
void provide_buffer(void *buffer, const int64_t size)
constexpr int64_t size() const
constexpr IndexRange index_range() const
Span< int16_t > base_span() const
constexpr Span drop_front(int64_t n) const
constexpr bool is_empty() const
void append(const T &value)
const IndexMask & update(IndexMaskSegment segment)
IndexMaskSegment slice(const IndexRange &range) const
IndexMaskSegment shift(const int64_t shift) const
IndexMaskSegment(const OffsetSpan< int64_t, int16_t > span)
IndexMask slice_and_shift(IndexRange range, int64_t offset, IndexMaskMemory &memory) const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_every_nth(int64_t n, int64_t indices_num, const int64_t initial_offset, IndexMaskMemory &memory)
static IndexMask from_bools_inverse(const IndexMask &universe, Span< bool > bools, IndexMaskMemory &memory)
IndexMaskSegment segment(int64_t segment_i) const
void to_indices(MutableSpan< T > r_indices) const
IndexMask slice_content(IndexRange range) const
Vector< IndexRange > to_ranges_invert(IndexRange universe) const
static IndexMask from_bits(BitSpan bits, IndexMaskMemory &memory)
Vector< IndexRange > to_ranges() const
std::optional< RawMaskIterator > find(int64_t query_index) const
std::optional< IndexRange > to_range() const
static Vector< IndexMask, 4 > from_group_ids(const VArray< int > &group_ids, IndexMaskMemory &memory, VectorSet< int > &r_index_by_group_id)
static IndexMask from_repeating(const IndexMask &mask_to_repeat, int64_t repetitions, int64_t stride, int64_t initial_offset, IndexMaskMemory &memory)
static IndexMask from_union(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
IndexMask shift(const int64_t offset, IndexMaskMemory &memory) const
void foreach_index_optimized(Fn &&fn) const
std::optional< RawMaskIterator > find_larger_equal(int64_t query_index) const
IndexMask slice(IndexRange range) const
static IndexMask from_intersection(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
IndexRange bounds() const
int64_t operator[](int64_t i) const
int64_t iterator_to_index(const RawMaskIterator &it) const
static IndexMask from_segments(Span< IndexMaskSegment > segments, IndexMaskMemory &memory)
int64_t min_array_size() const
static void from_groups(const IndexMask &universe, IndexMaskMemory &memory, Fn &&get_group_index, MutableSpan< IndexMask > r_masks)
static IndexMask from_batch_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, FunctionRef< int64_t(const IndexMaskSegment &universe_segment, IndexRangesBuilder< int16_t > &builder)> batch_predicate)
static IndexMask from_initializers(const Span< Initializer > initializers, IndexMaskMemory &memory)
IndexRange index_range() const
void set_bits(MutableBitSpan r_bits, int64_t offset=0) const
Vector< std::variant< IndexRange, IndexMaskSegment >, N > to_spans_and_ranges() const
std::optional< RawMaskIterator > find_smaller_equal(int64_t query_index) const
friend bool operator!=(const IndexMask &a, const IndexMask &b)
IndexMaskData & data_for_inplace_construction()
bool contains(int64_t query_index) const
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_range(Fn &&fn) const
void to_bits(MutableBitSpan r_bits, int64_t offset=0) const
void foreach_segment_optimized(Fn &&fn) const
friend bool operator==(const IndexMask &a, const IndexMask &b)
void to_bools(MutableSpan< bool > r_bools) const
void foreach_index(Fn &&fn) const
RawMaskIterator index_to_iterator(int64_t index) const
static void foreach_segment_zipped(Span< IndexMask > masks, FunctionRef< bool(Span< IndexMaskSegment > segments)> fn)
int64_t segments_num() const
static IndexMask from_difference(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
std::variant< IndexRange, Span< int64_t >, Span< int >, int64_t > Initializer
void foreach_segment(Fn &&fn) const
local_group_size(16, 16) .push_constant(Type b
int64_t find_predicate_begin(Iterator begin, Iterator end, Predicate &&predicate)
IndexMask from_predicate_impl(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, FunctionRef< int64_t(IndexMaskSegment indices, int16_t *r_true_indices)> filter_indices)
constexpr bool has_segment_and_start_parameter
static constexpr int64_t max_segment_size
static constexpr int64_t max_segment_size_mask_high
void build_reverse_map(const IndexMask &mask, MutableSpan< T > r_map)
static constexpr int64_t max_segment_size_mask_low
std::ostream & operator<<(std::ostream &stream, const IndexMask &mask)
void optimized_foreach_index(const IndexMaskSegment segment, const Fn fn)
bool operator==(const RawMaskIterator &a, const RawMaskIterator &b)
std::array< int16_t, max_segment_size > build_static_indices_array()
void optimized_foreach_index_with_pos(const IndexMaskSegment segment, const int64_t segment_pos, const Fn fn)
const IndexMask & get_static_index_mask_for_min_size(const int64_t min_size)
int64_t consolidate_index_mask_segments(MutableSpan< IndexMaskSegment > segments, IndexMaskMemory &memory)
bool operator!=(const RawMaskIterator &a, const RawMaskIterator &b)
const std::array< int16_t, max_segment_size > & get_static_indices_array()
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
void init_empty_mask(IndexMaskData &data)
static constexpr int64_t max_segment_size_shift
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
bool non_empty_is_range(const Span< T > indices)
const int64_t * cumulative_segment_sizes_
const int16_t ** indices_by_segment_
int64_t end_index_in_segment_
int64_t begin_index_in_segment_
const int64_t * segment_offsets_