diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 034af3e60..4e9b1a881 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -332,6 +332,39 @@ template std::pair, Vector> } #endif +namespace Implementation { + template inline typename std::enable_if::value, void>::type minmax(T& min, T& max, T value) { + if(value < min) + min = value; + else if(value > max) + max = value; + } + template inline void minmax(Vector& min, Vector& max, const Vector& value) { + for(std::size_t i = 0; i != size; ++i) + minmax(min[i], max[i], value[i]); + } +} + +/** +@brief Minimum and maximum of a range + +If the range is empty, returns default-constructed values. +*/ +template std::pair minmax(Corrade::Containers::ArrayView range) { + if(range.empty()) return {}; + + T min{range[0]}, max{range[0]}; + for(std::size_t i = 1; i != range.size(); ++i) + Implementation::minmax(min, max, range[i]); + + return {min, max}; +} + +/** @overload */ +template inline std::pair minmax(std::initializer_list list) { + return minmax(Corrade::Containers::ArrayView{list.begin(), list.size()}); +} + /** @brief Clamp value diff --git a/src/Magnum/Math/Test/FunctionsTest.cpp b/src/Magnum/Math/Test/FunctionsTest.cpp index 24744e009..38234644b 100644 --- a/src/Magnum/Math/Test/FunctionsTest.cpp +++ b/src/Magnum/Math/Test/FunctionsTest.cpp @@ -42,6 +42,7 @@ struct FunctionsTest: Corrade::TestSuite::Tester { void max(); void maxList(); void minmax(); + void minmaxList(); void clamp(); void nanPropagation(); @@ -86,6 +87,7 @@ FunctionsTest::FunctionsTest() { &FunctionsTest::max, &FunctionsTest::maxList, &FunctionsTest::minmax, + &FunctionsTest::minmaxList, &FunctionsTest::clamp, &FunctionsTest::nanPropagation, @@ -171,6 +173,24 @@ void FunctionsTest::minmax() { CORRADE_COMPARE_AS(Math::minmax(b, a), expectedVector, std::pair); } +void FunctionsTest::minmaxList() { + const auto expected = std::make_pair(-3.0f, 2.0f); + CORRADE_COMPARE(Math::minmax({-1.0f, 2.0f, -3.0f}), expected); + CORRADE_COMPARE(Math::minmax({-1.0f, -3.0f, 2.0f}), expected); + CORRADE_COMPARE(Math::minmax({2.0f, -1.0f, -3.0f}), expected); + CORRADE_COMPARE(Math::minmax({2.0f, -3.0f, -1.0f}), expected); + CORRADE_COMPARE(Math::minmax({-3.0f, 2.0f, -1.0f}), expected); + CORRADE_COMPARE(Math::minmax({-3.0f, -1.0f, 2.0f}), expected); + + const std::pair expectedVec{Vector2{-3.0f, -2.0f}, Vector2{2.0f, 3.0f}}; + CORRADE_COMPARE(Math::minmax({Vector2{-1.0f, 3.0f}, Vector2{2.0f, 1.0f}, Vector2{-3.0f, -2.0f}}), expectedVec); + CORRADE_COMPARE(Math::minmax({Vector2{-1.0f, 1.0f}, Vector2{-3.0f, 3.0f}, Vector2{2.0f, -2.0f}}), expectedVec); + CORRADE_COMPARE(Math::minmax({Vector2{2.0f, -2.0f}, Vector2{-1.0f, 1.0f}, Vector2{-3.0f, 3.0f}}), expectedVec); + CORRADE_COMPARE(Math::minmax({Vector2{2.0f, 1.0f}, Vector2{-3.0f, -2.0f}, Vector2{-1.0f, 3.0f}}), expectedVec); + CORRADE_COMPARE(Math::minmax({Vector2{-3.0f, 3.0f}, Vector2{2.0f, -2.0f}, Vector2{-1.0f, 1.0f}}), expectedVec); + CORRADE_COMPARE(Math::minmax({Vector2{-3.0f, -2.0f}, Vector2{-1.0f, 3.0f}, Vector2{2.0f, 1.0f}}), expectedVec); +} + void FunctionsTest::clamp() { CORRADE_COMPARE(Math::clamp(0.5f, -1.0f, 5.0f), 0.5f); CORRADE_COMPARE(Math::clamp(-1.6f, -1.0f, 5.0f), -1.0f);