/* SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once /** \file * \ingroup bli * * Generic algorithms for finding the largest and smallest elements in a span. */ #include #include "BLI_math_vector.hh" #include "BLI_task.hh" namespace blender::bounds { template struct MinMaxResult { T min; T max; }; /** * Find the smallest and largest values element-wise in the span. */ template static std::optional> min_max(Span values) { if (values.is_empty()) { return std::nullopt; } return threading::parallel_reduce( values.index_range(), 1024, MinMaxResult(), [&](IndexRange range, const MinMaxResult &init) { MinMaxResult result = init; for (const int i : range) { math::min_max(values[i], result.min, result.max); } return result; }, [](const MinMaxResult &a, const MinMaxResult &b) { return MinMaxResult{math::min(a.min, b.min), math::max(a.max, b.max)}; }); } /** * Find the smallest and largest values element-wise in the span, adding the radius to each element * first. The template type T is expected to have an addition operator implemented with RadiusT. */ template static std::optional> min_max_with_radii(Span values, Span radii) { BLI_assert(values.size() == radii.size()); if (values.is_empty()) { return std::nullopt; } return threading::parallel_reduce( values.index_range(), 1024, MinMaxResult(), [&](IndexRange range, const MinMaxResult &init) { MinMaxResult result = init; for (const int i : range) { result.min = math::min(values[i] - radii[i], result.min); result.max = math::max(values[i] + radii[i], result.max); } return result; }, [](const MinMaxResult &a, const MinMaxResult &b) { return MinMaxResult{math::min(a.min, b.min), math::max(a.max, b.max)}; }); } } // namespace blender::bounds