123 std::sort(boundaries.
begin(),
130 std::sort(boundaries.
begin(),
133 return a.index < b.index;
142 const int64_t prev_boundary_index,
143 const int64_t current_boundary_index,
146 const int64_t size = current_boundary_index - prev_boundary_index;
152 return *prev_segment;
159 return *prev_segment;
165 return result.segments.last();
170 const int64_t prev_boundary_index,
171 const int64_t current_boundary_index,
179 return *prev_segment;
185 return result.segments.last();
190 const int64_t prev_boundary_index,
191 const int64_t current_boundary_index,
198 prev_segment->
mask == ©_from_mask)
202 return *prev_segment;
208 return *prev_segment;
214 return result.segments.last();
226 int64_t prev_boundary_index = boundaries[0].index;
229 if (prev_boundary_index < boundary.index) {
232 bool has_full =
false;
233 bool has_unknown =
false;
234 bool copy_from_single_mask =
true;
235 const IndexMask *copy_from_mask =
nullptr;
236 for (
const CoarseSegment *active_segment : active_segments) {
237 switch (active_segment->type) {
247 if (!
ELEM(copy_from_mask,
nullptr, active_segment->mask)) {
248 copy_from_single_mask =
false;
250 copy_from_mask = active_segment->mask;
258 prev_segment, prev_boundary_index, boundary.index,
result);
260 else if (has_unknown || !copy_from_single_mask) {
262 prev_segment, prev_boundary_index, boundary.index,
result);
264 else if (copy_from_mask !=
nullptr && copy_from_single_mask) {
266 prev_segment, prev_boundary_index, boundary.index, *copy_from_mask,
result);
269 prev_boundary_index = boundary.index;
273 if (boundary.is_begin) {
274 active_segments.
append(boundary.segment);
293 int64_t prev_boundary_index = boundaries[0].index;
296 if (prev_boundary_index < boundary.index) {
299 if (active_segments.
size() == terms_num) {
303 int unknown_count = 0;
305 bool copy_from_single_mask =
true;
306 const IndexMask *copy_from_mask =
nullptr;
307 for (
const CoarseSegment *active_segment : active_segments) {
308 switch (active_segment->type) {
319 if (!
ELEM(copy_from_mask,
nullptr, active_segment->mask)) {
320 copy_from_single_mask =
false;
322 copy_from_mask = active_segment->mask;
328 BLI_assert(full_count + unknown_count + copy_count == terms_num);
329 if (full_count == terms_num) {
331 prev_segment, prev_boundary_index, boundary.index,
result);
333 else if (unknown_count > 0 || copy_count < terms_num || !copy_from_single_mask) {
335 prev_segment, prev_boundary_index, boundary.index,
result);
337 else if (copy_count == terms_num && copy_from_single_mask) {
339 prev_segment, prev_boundary_index, boundary.index, *copy_from_mask,
result);
343 prev_boundary_index = boundary.index;
347 if (boundary.is_begin) {
348 active_segments.
append(boundary.segment);
367 int64_t prev_boundary_index = boundaries[0].index;
370 if (prev_boundary_index < boundary.index) {
373 if (active_main_segments.
size() == 1) {
374 const CoarseSegment &active_main_segment = *active_main_segments[0];
377 bool has_subtract_full =
false;
378 bool has_subtract_same_mask =
false;
379 for (
const CoarseSegment *active_subtract_segment : active_subtract_segments) {
380 switch (active_subtract_segment->type) {
385 has_subtract_full =
true;
390 if (active_main_segment.
mask == active_subtract_segment->mask) {
391 has_subtract_same_mask =
true;
399 if (has_subtract_full) {
403 switch (active_main_segment.
type) {
406 prev_segment, prev_boundary_index, boundary.index,
result);
410 if (active_subtract_segments.is_empty()) {
412 prev_segment, prev_boundary_index, boundary.index,
result);
416 prev_segment, prev_boundary_index, boundary.index,
result);
421 if (active_subtract_segments.is_empty()) {
425 *active_main_segment.
mask,
428 else if (has_subtract_same_mask) {
433 prev_segment, prev_boundary_index, boundary.index,
result);
441 prev_boundary_index = boundary.index;
445 if (boundary.is_main) {
446 if (boundary.is_begin) {
447 active_main_segments.
append(boundary.segment);
454 if (boundary.is_begin) {
455 active_subtract_segments.
append(boundary.segment);
482 const std::optional<IndexRange> eval_bounds = std::nullopt)
489 for (
const Expr *expression : eval_order) {
490 CoarseResult &expr_result = expression_results[expression->index].emplace();
491 switch (expression->type) {
496 if (eval_bounds.has_value()) {
503 if (!
mask.is_empty()) {
505 if (
const std::optional<IndexRange> range =
mask.to_range()) {
520 boundaries.
append({segment.bounds.first(),
true, &segment});
521 boundaries.
append({segment.bounds.one_after_last(),
false, &segment});
534 boundaries.
append({segment.bounds.first(),
true, &segment});
535 boundaries.
append({segment.bounds.one_after_last(),
false, &segment});
545 const CoarseResult &main_term_result = *expression_results[expr.
terms[0]->index];
547 boundaries.
append({{segment.bounds.first(),
true, &segment},
true});
548 boundaries.
append({{segment.bounds.one_after_last(),
false, &segment},
true});
550 for (
const Expr *term : expr.
terms.as_span().drop_front(1)) {
551 const CoarseResult &term_result = *expression_results[term->index];
553 boundaries.
append({{segment.bounds.first(),
true, &segment},
false});
554 boundaries.
append({{segment.bounds.one_after_last(),
false, &segment},
false});
565 return std::move(final_result);
605 for (
const Expr *expression : eval_order) {
607 switch (expression->type) {
611 mask.to_bits(expr_result, -bounds_min);
615 for (
const Expr *term : expression->
terms) {
616 expr_result |= expression_results[term->
index];
622 for (
const Expr *term : expression->
terms.as_span().drop_front(1)) {
623 expr_result &= expression_results[term->index];
629 for (
const Expr *term : expression->
terms.as_span().drop_front(1)) {
633 expression_results[term->index]);
652 if (segments.
size() == 1) {
655 if (segments.
size() == 2) {
660 return {bounds_min, {r_values,
size}};
667 sorted_segments.
begin(),
668 sorted_segments.
end(),
671 std::array<int16_t, max_segment_size> tmp_indices;
674 int16_t *buffer_a = r_values;
675 int16_t *buffer_b = tmp_indices.data();
677 if (sorted_segments.
size() % 2 == 1) {
679 std::swap(buffer_a, buffer_b);
687 int16_t *dst = buffer_a;
688 count = std::set_union(a.
begin(), a.
end(),
b.begin(),
b.end(), dst) - dst;
695 const int16_t *a = buffer_a;
697 int16_t *dst = buffer_b;
698 count = std::set_union(a, a +
count,
b.begin(),
b.end(), dst) - dst;
699 std::swap(buffer_a, buffer_b);
701 return {bounds_min, {r_values,
count}};
712 if (segments.
size() == 1) {
715 if (segments.
size() == 2) {
720 return {bounds_min, {r_values,
size}};
727 sorted_segments.
begin(),
728 sorted_segments.
end(),
731 std::array<int16_t, max_segment_size> tmp_indices_1;
732 std::array<int16_t, max_segment_size> tmp_indices_2;
733 int16_t *buffer_a = tmp_indices_1.data();
734 int16_t *buffer_b = tmp_indices_2.data();
741 int16_t *dst = buffer_a;
742 count = std::set_intersection(a.
begin(), a.
end(),
b.begin(),
b.end(), dst) - dst;
746 const int16_t *a = buffer_a;
750 int16_t *dst = (segment_i == sorted_segments.
size() - 1) ? r_values : buffer_b;
751 count = std::set_intersection(a, a +
count,
b.begin(),
b.end(), dst) - dst;
752 std::swap(buffer_a, buffer_b);
754 return {bounds_min, {r_values,
count}};
773 if (subtract_segments.
size() == 1) {
775 const IndexMaskSegment subtract_segment = subtract_segments[0].shift(-bounds_min);
777 shifted_main_segment.
end(),
778 subtract_segment.
begin(),
779 subtract_segment.
end(),
782 return {bounds_min, {r_values,
size}};
787 subtract_count += segment.size();
789 if (subtract_count < main_segment.
size() / 2) {
792 std::array<int16_t, max_segment_size> union_indices;
798 shifted_main_segment.
end(),
799 unioned_subtract_segment.
begin(),
800 unioned_subtract_segment.
end(),
803 return {bounds_min, {r_values,
size}};
809 sorted_subtract_segments.
begin(),
810 sorted_subtract_segments.
end(),
813 std::array<int16_t, max_segment_size> tmp_indices_1;
814 std::array<int16_t, max_segment_size> tmp_indices_2;
815 int16_t *buffer_a = tmp_indices_1.data();
816 int16_t *buffer_b = tmp_indices_2.data();
822 const IndexMaskSegment subtract_segment = sorted_subtract_segments[0].shift(-bounds_min);
823 int16_t *dst = buffer_a;
824 count = std::set_difference(shifted_main_segment.
begin(),
825 shifted_main_segment.
end(),
826 subtract_segment.
begin(),
827 subtract_segment.
end(),
833 const IndexMaskSegment &subtract_segment = sorted_subtract_segments[segment_i].shift(
836 int16_t *dst = (segment_i == sorted_subtract_segments.
size() - 1) ? r_values : buffer_b;
837 count = std::set_difference(buffer_a,
839 subtract_segment.
begin(),
840 subtract_segment.
end(),
843 std::swap(buffer_a, buffer_b);
845 return {bounds_min, {r_values,
count}};
862 for (
const Expr *expression : eval_order) {
863 switch (expression->type) {
869 if (
mask.segments_num() == 1) {
870 results[expression->index] =
mask.segment(0);
877 int64_t result_size_upper_bound = 0;
878 bool used_short_circuit =
false;
885 results[expression->index] = term_segment;
886 used_short_circuit =
true;
889 term_segments[term_i] = term_segment;
890 result_size_upper_bound += term_segment.
size();
892 if (used_short_circuit) {
895 result_size_upper_bound = std::min(result_size_upper_bound,
bounds.size());
898 term_segments, bounds_min, dst.
data());
900 result_segment.base_span().end());
901 results[expression->index] = result_segment;
908 bool used_short_circuit =
false;
914 results[expression->index] = {};
915 used_short_circuit =
true;
918 result_size_upper_bound = std::min(result_size_upper_bound, term_segment.
size());
919 term_segments[term_i] = term_segment;
921 if (used_short_circuit) {
926 term_segments, bounds_min, dst.
data());
928 result_segment.base_span().end());
929 results[expression->index] = result_segment;
938 results[expression->index] = {};
941 int64_t result_size_upper_bound = main_segment.
size();
942 bool used_short_circuit =
false;
944 for (
const int64_t term_i : expr.
terms.index_range().drop_front(1)) {
945 const Expr &subtract_term = *expr.
terms[term_i];
950 results[expression->index] = {};
951 used_short_circuit =
true;
954 result_size_upper_bound = std::min(result_size_upper_bound,
956 subtract_segments[term_i - 1] = term_segment;
958 if (used_short_circuit) {
963 main_segment, subtract_segments, bounds_min, dst.
data());
965 result_segment.base_span().end());
966 results[expression->index] = result_segment;
971 return results[root_expression.
index];
983 switch (evaluated_segment.type) {
990 evaluated_segment.bounds);
996 result_mask_segments.
append(evaluated_segment.indices);
1001 return result_mask_segments;
1012 eval_order.
append(&root_expression);
1019 expr_stack.
push(&root_expression);
1022 const Expr &expression = *expr_stack.
peek();
1023 bool &is_evaluated = is_evaluated_states[expression.
index];
1028 bool all_terms_evaluated =
true;
1029 for (
const Expr *term : expression.
terms) {
1030 bool &term_evaluated = is_evaluated_states[term->
index];
1031 if (!term_evaluated) {
1034 term_evaluated =
true;
1037 expr_stack.
push(term);
1038 all_terms_evaluated =
false;
1042 if (all_terms_evaluated) {
1043 eval_order.
append(&expression);
1044 is_evaluated =
true;
1055 for (
const Expr *term : root_expression.
terms) {
1056 if (!term->
terms.is_empty()) {
1065 const Expr &root_expression,
1080 auto handle_coarse_result = [&](
const CoarseResult &coarse_result) {
1081 for (
const CoarseSegment &segment : coarse_result.segments) {
1082 switch (segment.type) {
1084 if (segment.bounds.size() > coarse_segment_size_threshold) {
1085 long_unknown_segments.
push(segment.bounds);
1088 r_short_unknown_segments.
append(segment.bounds);
1094 r_evaluated_segments.
append(
1109 handle_coarse_result(initial_coarse_result);
1112 while (!long_unknown_segments.
is_empty()) {
1113 const IndexRange unknown_bounds = long_unknown_segments.
pop();
1114 const int64_t split_pos = unknown_bounds.
size() / 2;
1119 handle_coarse_result(left_result);
1120 handle_coarse_result(right_result);
1125 const Expr &root_expression,
1137 switch (exact_eval_mode) {
1140 root_expression, allocator,
bounds, eval_order);
1142 r_local_evaluated_segments.append(
1154 const Expr &expr = *eval_order[eval_order_i];
1161 if (segments_num <= 1) {
1171 split_indices.
append(segment[0]);
1174 std::sort(split_indices.
begin(), split_indices.
end());
1177 split_indices[boundary_i + 1]);
1182 root_expression, allocator, sub_bounds, eval_order);
1184 r_local_evaluated_segments.append(
1195 const int64_t unknown_segment_eval_grain_size = 8;
1196 if (short_unknown_segments.
size() < unknown_segment_eval_grain_size) {
1198 evaluate_unknown_segment(
bounds, memory, r_evaluated_segments);
1210 unknown_segment_eval_grain_size,
1212 LocalData &data = data_by_thread.local();
1213 for (const IndexRange &bounds : short_unknown_segments.slice(range))
1215 evaluate_unknown_segment(
1216 bounds, data.allocator, data.evaluated_segments);
1219 for (LocalData &
data : data_by_thread) {
1220 if (!
data.evaluated_segments.is_empty()) {
1221 r_evaluated_segments.
extend(
data.evaluated_segments);
1231 if (evaluated_segments.
is_empty()) {
1234 if (evaluated_segments.
size() == 1) {
1236 switch (evaluated_segment.
type) {
1249 std::sort(evaluated_segments.
begin(),
1250 evaluated_segments.
end(),
1252 return a.bounds.start() < b.bounds.start();
1274 root_expression, eval_order, evaluated_segments, short_unknown_segments);
1278 short_unknown_segments,
1280 evaluated_segments);
1304 for (
const Term &term : terms) {
1305 term_expressions.
append(&this->term_to_expr(term));
1309 expr.
index = expr_count_++;
1310 expr.
terms = std::move(term_expressions);
1317 term_expressions.
append(&this->term_to_expr(main_term));
1318 for (
const Term &subtract_term : subtract_terms) {
1319 term_expressions.
append(&this->term_to_expr(subtract_term));
1323 expr.
index = expr_count_++;
1324 expr.
terms = std::move(term_expressions);
1331 for (
const Term &term : terms) {
1332 term_expressions.
append(&this->term_to_expr(term));
1336 expr.
index += expr_count_++;
1337 expr.
terms = std::move(term_expressions);
1341const Expr &ExprBuilder::term_to_expr(
const Term &term)
1343 if (
const Expr *
const *expr = std::get_if<const Expr *>(&term)) {
1346 AtomicExpr &expr = scope_.construct<AtomicExpr>();
1347 expr.
type = Expr::Type::Atomic;
1348 expr.index = expr_count_++;
1349 if (
const IndexRange *range = std::get_if<IndexRange>(&term)) {
1350 expr.mask = &scope_.construct<
IndexMask>(*range);
1353 expr.mask = std::get<const IndexMask *>(term);
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static IndexMask from_segments(Span< IndexMaskSegment > segments, IndexMaskMemory &memory)
constexpr int64_t one_after_last() const
constexpr IndexRange drop_back(int64_t n) 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)
constexpr IndexRange with_new_end(const int64_t new_end) const
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
constexpr int64_t start() const
constexpr IndexRange take_front(int64_t n) const
constexpr IndexRange drop_front(int64_t n) const
MutableSpan< T > allocate_array(int64_t size)
void free_end_of_previous_allocation(const int64_t original_allocation_size, const void *free_after)
MutableSpan< T > construct_array_copy(Span< T > src)
void transfer_ownership_from(LinearAllocator<> &other)
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr T * data() const
constexpr int64_t size_in_bytes() const
constexpr T * end() const
constexpr T * begin() const
constexpr const T * data() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
void push(const T &value)
void append(const T &value)
void remove_first_occurrence_and_reorder(const T &value)
IndexRange index_range() const
void append_unchecked(const T &value)
void extend(Span< T > array)
std::variant< const Expr *, const IndexMask *, IndexRange > Term
const IntersectionExpr & intersect(const Span< Term > terms)
const UnionExpr & merge(const Span< Term > terms)
const DifferenceExpr & subtract(const Term &main_term, const Span< Term > subtract_terms)
IndexMaskSegment shift(const int64_t shift) const
IndexMask slice_content(IndexRange range) const
void foreach_segment(Fn &&fn) const
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static constexpr int64_t BitsPerInt
void mix_into_first_expr(ExprFn &&expr, FirstBitSpanT &&first_arg, const BitSpanT &...args)
void copy_from_or(FirstBitSpanT &first_arg, const BitSpanT &...args)
void foreach_1_index(const BitSpanT &data, Fn &&fn)
static CoarseSegment & add_coarse_segment__full(CoarseSegment *prev_segment, const int64_t prev_boundary_index, const int64_t current_boundary_index, CoarseResult &result)
static IndexMaskSegment evaluate_exact_with_indices(const Expr &root_expression, LinearAllocator<> &allocator, const IndexRange bounds, const Span< const Expr * > eval_order)
static void evaluate_coarse_and_split_until_segments_are_short(const Expr &root_expression, const Span< const Expr * > eval_order, Vector< EvaluatedSegment, 16 > &r_evaluated_segments, Vector< IndexRange, 16 > &r_short_unknown_segments)
IndexMask evaluate_expression(const Expr &expression, IndexMaskMemory &memory)
static void evaluate_short_unknown_segments_exactly(const Expr &root_expression, const ExactEvalMode exact_eval_mode, const Span< const Expr * > eval_order, const Span< IndexRange > short_unknown_segments, IndexMaskMemory &memory, Vector< EvaluatedSegment, 16 > &r_evaluated_segments)
static IndexMaskSegment union_index_mask_segments(const Span< IndexMaskSegment > segments, const int64_t bounds_min, int16_t *r_values)
static constexpr int64_t segment_size_threshold
static void sort_course_boundaries(MutableSpan< CourseBoundary > boundaries)
static ExactEvalMode determine_exact_eval_mode(const Expr &root_expression)
static CoarseResult evaluate_coarse(const Expr &root_expression, const Span< const Expr * > eval_order, const std::optional< IndexRange > eval_bounds=std::nullopt)
static IndexMaskSegment evaluate_exact_with_bits(const Expr &root_expression, LinearAllocator<> &allocator, const IndexRange bounds, const Span< const Expr * > eval_order)
static IndexMask evaluated_segments_to_index_mask(MutableSpan< EvaluatedSegment > evaluated_segments, IndexMaskMemory &memory)
void index_range_to_mask_segments(const IndexRange range, Vector< IndexMaskSegment, N > &r_segments)
static Span< int16_t > bits_to_indices(const BoundedBitSpan bits, LinearAllocator<> &allocator)
static constexpr int64_t max_segment_size
static Vector< const Expr *, inline_expr_array_size > compute_eval_order(const Expr &root_expression)
static IndexMaskSegment intersect_index_mask_segments(const Span< IndexMaskSegment > segments, const int64_t bounds_min, int16_t *r_values)
static CoarseSegment & add_coarse_segment__unknown(CoarseSegment *prev_segment, const int64_t prev_boundary_index, const int64_t current_boundary_index, CoarseResult &result)
static Vector< IndexMaskSegment > build_result_mask_segments(const Span< EvaluatedSegment > evaluated_segments)
static void evaluate_coarse_difference(const Span< DifferenceCourseBoundary > boundaries, CoarseResult &r_result)
static IndexMask evaluate_expression_impl(const Expr &root_expression, IndexMaskMemory &memory, const ExactEvalMode exact_eval_mode)
static CoarseSegment & add_coarse_segment__copy(CoarseSegment *prev_segment, const int64_t prev_boundary_index, const int64_t current_boundary_index, const IndexMask ©_from_mask, CoarseResult &result)
static IndexMaskSegment difference_index_mask_segments(const IndexMaskSegment main_segment, const Span< IndexMaskSegment > subtract_segments, const int64_t bounds_min, int16_t *r_values)
static void evaluate_coarse_intersection(const Span< CourseBoundary > boundaries, const int64_t terms_num, CoarseResult &r_result)
static void evaluate_coarse_union(const Span< CourseBoundary > boundaries, CoarseResult &r_result)
constexpr int64_t inline_expr_array_size
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
constexpr IntT ceil_division(const IntT x, const IntT y)
Vector< CoarseSegment > segments
const CoarseSegment * segment
const IndexMask * copy_mask
const DifferenceExpr & as_difference() const
const IntersectionExpr & as_intersection() const
const AtomicExpr & as_atomic() const
int expression_array_size() const
const UnionExpr & as_union() const
Vector< const Expr * > terms