Browse Source

Math: scalar/vector implementation of min(), max() and clamp().

This is gonna be some ugly template hell.
pull/7/head
Vladimír Vondruš 14 years ago
parent
commit
4d6d3fde88
  1. 74
      src/Math/Functions.h
  2. 39
      src/Math/Test/FunctionsTest.cpp

74
src/Math/Functions.h

@ -20,6 +20,8 @@
#include <limits> #include <limits>
#include <algorithm> #include <algorithm>
#include "Math/Vector.h"
#include "magnumVisibility.h" #include "magnumVisibility.h"
/** @file /** @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); 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<class T> inline T min(T a, T b);
#else
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type min(T a, T b) {
return std::min(a, b);
}
template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size, T>& a, const Vector<size, T>& b) {
Vector<size, T> 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<class T> inline T max(const T& a, const T& b);
#else
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type max(T a, T b) {
return std::max(a, b);
}
template<std::size_t size, class T> Vector<size, T> max(const Vector<size, T>& a, const Vector<size, T>& b) {
Vector<size, T> 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<class T, class U> inline T clamp(const T& value, U min, U max);
#else
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type clamp(T value, T min, T max) {
return std::min(std::max(value, min), max);
}
template<std::size_t size, class T> Vector<size, T> clamp(const Vector<size, T>& value, T min, T max) {
Vector<size, T> 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 @brief Normalize integral value
@ -134,10 +203,7 @@ template<class Integral, class FloatingPoint> inline constexpr typename std::ena
} }
#endif #endif
/** @brief Clamp value */ /*@}*/
template<class T> inline T clamp(T value, T min, T max) {
return std::min(std::max(value, min), max);
}
}} }}

39
src/Math/Test/FunctionsTest.cpp

@ -16,6 +16,7 @@
#include <TestSuite/Tester.h> #include <TestSuite/Tester.h>
#include "Math/Functions.h" #include "Math/Functions.h"
#include "Math/Vector3.h"
namespace Magnum { namespace Math { namespace Test { namespace Magnum { namespace Math { namespace Test {
@ -23,31 +24,57 @@ class FunctionsTest: public Corrade::TestSuite::Tester {
public: public:
FunctionsTest(); FunctionsTest();
void min();
void max();
void clamp();
void normalizeUnsigned(); void normalizeUnsigned();
void normalizeSigned(); void normalizeSigned();
void denormalizeUnsigned(); void denormalizeUnsigned();
void denormalizeSigned(); void denormalizeSigned();
void renormalizeUnsinged(); void renormalizeUnsinged();
void renormalizeSinged(); void renormalizeSinged();
void clamp();
void pow(); void pow();
void log(); void log();
void log2(); void log2();
}; };
typedef Math::Vector3<float> Vector3;
typedef Math::Vector3<std::int32_t> Vector3i;
FunctionsTest::FunctionsTest() { FunctionsTest::FunctionsTest() {
addTests(&FunctionsTest::normalizeUnsigned, addTests(&FunctionsTest::min,
&FunctionsTest::max,
&FunctionsTest::clamp,
&FunctionsTest::normalizeUnsigned,
&FunctionsTest::normalizeSigned, &FunctionsTest::normalizeSigned,
&FunctionsTest::denormalizeUnsigned, &FunctionsTest::denormalizeUnsigned,
&FunctionsTest::denormalizeSigned, &FunctionsTest::denormalizeSigned,
&FunctionsTest::renormalizeUnsinged, &FunctionsTest::renormalizeUnsinged,
&FunctionsTest::renormalizeSinged, &FunctionsTest::renormalizeSinged,
&FunctionsTest::clamp,
&FunctionsTest::pow, &FunctionsTest::pow,
&FunctionsTest::log, &FunctionsTest::log,
&FunctionsTest::log2); &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() { void FunctionsTest::normalizeUnsigned() {
CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(0)), 0.0f); CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(255)), 1.0f); CORRADE_COMPARE((Math::normalize<float, std::uint8_t>(255)), 1.0f);
@ -156,12 +183,6 @@ void FunctionsTest::renormalizeSinged() {
CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::int64_t>(1.0l)), 1.0l); CORRADE_COMPARE(Math::normalize<long double>(Math::denormalize<std::int64_t>(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() { void FunctionsTest::pow() {
CORRADE_COMPARE(Math::pow<10>(2ul), 1024ul); CORRADE_COMPARE(Math::pow<10>(2ul), 1024ul);
CORRADE_COMPARE(Math::pow<0>(3ul), 1ul); CORRADE_COMPARE(Math::pow<0>(3ul), 1ul);

Loading…
Cancel
Save