From 4059bd752f36e862c0cdbd1ddf891933631660ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 23 Nov 2013 10:43:54 +0100 Subject: [PATCH] Math: added minmax() and Vector2::minmax(). No Vector and std::initializer_list versions yet, as the algorithm for it is pretty complicated and I'm not sure that they will be used frequently enough to deserve their existence. --- src/Math/Functions.h | 26 +++++++++++++++++++++++--- src/Math/Test/FunctionsTest.cpp | 14 ++++++++++++++ src/Math/Test/Vector2Test.cpp | 8 ++++++++ src/Math/Vector.h | 4 ++-- src/Math/Vector2.h | 9 +++++++++ 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/Math/Functions.h b/src/Math/Functions.h index 25f6776be..e7bf0228c 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -25,8 +25,9 @@ */ #include -#include #include +#include +#include #include "Math/Vector.h" @@ -124,7 +125,7 @@ perform the operations component-wise. /** @brief Minimum -@see min(), clamp(), Vector::min() +@see @ref max(), @ref minmax(), @ref clamp(), @ref Vector::min() */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline T min(T a, T b); @@ -151,7 +152,7 @@ template inline T min(std::initializer_list list) { /** @brief Maximum -@see max(), clamp(), Vector::max() +@see @ref min(), @ref minmax(), @ref clamp(), @ref Vector::max() */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline T max(const T& a, const T& b); @@ -175,6 +176,25 @@ template inline T max(std::initializer_list list) { return out; } +/** +@brief Minimum and maximum of two values + +@see @ref min(), @ref max(), @ref clamp(), @ref Vector2::minmax() +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template inline std::pair minmax(const T& a, const T& b); +#else +template inline typename std::enable_if::value, std::pair>::type minmax(T a, T b) { + return a < b ? std::make_pair(a, b) : std::make_pair(b, a); +} +template std::pair, Vector> minmax(const Vector& a, const Vector& b) { + std::pair, Vector> out{a, b}; + for(std::size_t i = 0; i != size; ++i) + if(out.first[i] > out.second[i]) std::swap(out.first[i], out.second[i]); + return out; +} +#endif + /** @brief Sign diff --git a/src/Math/Test/FunctionsTest.cpp b/src/Math/Test/FunctionsTest.cpp index 1b86f1985..dc682e664 100644 --- a/src/Math/Test/FunctionsTest.cpp +++ b/src/Math/Test/FunctionsTest.cpp @@ -37,6 +37,7 @@ class FunctionsTest: public Corrade::TestSuite::Tester { void minList(); void max(); void maxList(); + void minmax(); void sign(); void abs(); @@ -79,6 +80,7 @@ FunctionsTest::FunctionsTest() { &FunctionsTest::minList, &FunctionsTest::max, &FunctionsTest::maxList, + &FunctionsTest::minmax, &FunctionsTest::sign, &FunctionsTest::abs, @@ -132,6 +134,18 @@ void FunctionsTest::maxList() { Vector3i(9, -5, 18)}), Vector3i(9, 14, 18)); } +void FunctionsTest::minmax() { + const auto expectedScalar = std::make_pair(-5.0f, 4.0f); + CORRADE_COMPARE(Math::minmax(-5.0f, 4.0f), expectedScalar); + CORRADE_COMPARE(Math::minmax(4.0f, -5.0f), expectedScalar); + + const Vector3 a(5.0f, -4.0f, 1.0f); + const Vector3 b(7.0f, -3.0f, 1.0f); + const std::pair expectedVector{{5.0f, -4.0f, 1.0f}, {7.0f, -3.0f, 1.0f}}; + CORRADE_COMPARE_AS(Math::minmax(a, b), expectedVector, std::pair); + CORRADE_COMPARE_AS(Math::minmax(b, a), expectedVector, std::pair); +} + void FunctionsTest::sign() { CORRADE_COMPARE(Math::sign(3516), 1); CORRADE_COMPARE(Math::sign(0.0f), 0.0f); diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index f2b2a9873..69c67c879 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -68,6 +68,7 @@ class Vector2Test: public Corrade::TestSuite::Tester { void scales(); void perpendicular(); void aspectRatio(); + void minmax(); void swizzleType(); void debug(); @@ -93,6 +94,7 @@ Vector2Test::Vector2Test() { &Vector2Test::scales, &Vector2Test::perpendicular, &Vector2Test::aspectRatio, + &Vector2Test::minmax, &Vector2Test::swizzleType, &Vector2Test::debug, @@ -202,6 +204,12 @@ void Vector2Test::aspectRatio() { CORRADE_COMPARE(Vector2(3.0f, 4.0f).aspectRatio(), 0.75f); } +void Vector2Test::minmax() { + const auto expected = std::make_pair(-5.0f, 4.0f); + CORRADE_COMPARE(Vector2(-5.0f, 4.0f).minmax(), expected); + CORRADE_COMPARE(Vector2(4.0f, -5.0f).minmax(), expected); +} + void Vector2Test::swizzleType() { constexpr Vector<4, Int> orig; constexpr auto a = swizzle<'y', 'a'>(orig); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index de6c77881..5f13d62ba 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -514,14 +514,14 @@ template class Vector { /** * @brief Minimal value in the vector * - * @see Math::min() + * @see @ref Math::min(), @ref Vector2::minmax() */ T min() const; /** * @brief Maximal value in the vector * - * @see Math::max() + * @see @ref Math::max(), @ref Vector2::minmax() */ T max() const; diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 0d77e00e4..4eac0abb7 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -143,6 +143,15 @@ template class Vector2: public Vector<2, T> { */ T aspectRatio() const { return x()/y(); } + /** + * @brief Minimum and maximum value + * + * @see @ref min(), @ref max(), @ref Math::minmax() + */ + std::pair minmax() const { + return x() < y() ? std::make_pair(x(), y()) : std::make_pair(y(), x()); + } + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2) };