diff --git a/src/Math/Functions.h b/src/Math/Functions.h index c80fd1eab..ad9066195 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -20,6 +20,8 @@ #include #include +#include "Math/Vector.h" + #include "magnumVisibility.h" /** @file @@ -78,6 +80,73 @@ std::uint32_t MAGNUM_EXPORT log2(std::uint32_t number); */ std::uint32_t MAGNUM_EXPORT log(std::uint32_t base, std::uint32_t number); +/** +@{ @name Scalar/vector functions + +These functions are overloaded for both scalar and vector types. Scalar +versions function exactly as their possible STL equivalents, vector overloads +perform the operations component-wise. +*/ + +/** +@brief Minimum + +@see min(), clamp() +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template inline T min(T a, T b); +#else +template inline typename std::enable_if::value, T>::type min(T a, T b) { + return std::min(a, b); +} +template inline Vector min(const Vector& a, const Vector& b) { + Vector out; + for(std::size_t i = 0; i != size; ++i) + out[i] = std::min(a[i], b[i]); + return out; +} +#endif + +/** +@brief Maximum + +@see max(), clamp() +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template inline T max(const T& a, const T& b); +#else +template inline typename std::enable_if::value, T>::type max(T a, T b) { + return std::max(a, b); +} +template Vector max(const Vector& a, const Vector& b) { + Vector out; + for(std::size_t i = 0; i != size; ++i) + out[i] = std::max(a[i], b[i]); + return out; +} +#endif + +/** +@brief Clamp value + +Values smaller than @p min are set to @p min, values larger than @p max are +set to @p max. +@see min(), max() +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template inline T clamp(const T& value, U min, U max); +#else +template inline typename std::enable_if::value, T>::type clamp(T value, T min, T max) { + return std::min(std::max(value, min), max); +} +template Vector clamp(const Vector& value, T min, T max) { + Vector out; + for(std::size_t i = 0; i != size; ++i) + out[i] = std::min(std::max(value[i], min), max); + return out; +} +#endif + /** @brief Normalize integral value @@ -134,10 +203,7 @@ template inline constexpr typename std::ena } #endif -/** @brief Clamp value */ -template inline T clamp(T value, T min, T max) { - return std::min(std::max(value, min), max); -} +/*@}*/ }} diff --git a/src/Math/Test/FunctionsTest.cpp b/src/Math/Test/FunctionsTest.cpp index 9b55ae7e2..eff4ff119 100644 --- a/src/Math/Test/FunctionsTest.cpp +++ b/src/Math/Test/FunctionsTest.cpp @@ -16,6 +16,7 @@ #include #include "Math/Functions.h" +#include "Math/Vector3.h" namespace Magnum { namespace Math { namespace Test { @@ -23,31 +24,57 @@ class FunctionsTest: public Corrade::TestSuite::Tester { public: FunctionsTest(); + void min(); + void max(); + void clamp(); void normalizeUnsigned(); void normalizeSigned(); void denormalizeUnsigned(); void denormalizeSigned(); void renormalizeUnsinged(); void renormalizeSinged(); - void clamp(); + void pow(); void log(); void log2(); }; +typedef Math::Vector3 Vector3; +typedef Math::Vector3 Vector3i; + FunctionsTest::FunctionsTest() { - addTests(&FunctionsTest::normalizeUnsigned, + addTests(&FunctionsTest::min, + &FunctionsTest::max, + &FunctionsTest::clamp, + &FunctionsTest::normalizeUnsigned, &FunctionsTest::normalizeSigned, &FunctionsTest::denormalizeUnsigned, &FunctionsTest::denormalizeSigned, &FunctionsTest::renormalizeUnsinged, &FunctionsTest::renormalizeSinged, - &FunctionsTest::clamp, &FunctionsTest::pow, &FunctionsTest::log, &FunctionsTest::log2); } +void FunctionsTest::min() { + CORRADE_COMPARE(Math::min(5, 9), 5); + CORRADE_COMPARE(Math::min(Vector3i(5, -3, 2), Vector3i(9, -5, 18)), Vector3i(5, -5, 2)); +} + +void FunctionsTest::max() { + CORRADE_COMPARE(Math::max(5, 9), 9); + CORRADE_COMPARE(Math::max(Vector3i(5, -3, 2), Vector3i(9, -5, 18)), Vector3i(9, -3, 18)); +} + +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); + CORRADE_COMPARE(Math::clamp(9.5f, -1.0f, 5.0f), 5.0f); + + CORRADE_COMPARE(Math::clamp(Vector3(0.5f, -1.6f, 9.5f), -1.0f, 5.0f), Vector3(0.5f, -1.0f, 5.0f)); +} + void FunctionsTest::normalizeUnsigned() { CORRADE_COMPARE((Math::normalize(0)), 0.0f); CORRADE_COMPARE((Math::normalize(255)), 1.0f); @@ -156,12 +183,6 @@ void FunctionsTest::renormalizeSinged() { CORRADE_COMPARE(Math::normalize(Math::denormalize(1.0l)), 1.0l); } -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); - CORRADE_COMPARE(Math::clamp(9.5f, -1.0f, 5.0f), 5.0f); -} - void FunctionsTest::pow() { CORRADE_COMPARE(Math::pow<10>(2ul), 1024ul); CORRADE_COMPARE(Math::pow<0>(3ul), 1ul);