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š 13 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 <algorithm>
#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<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
@ -134,10 +203,7 @@ template<class Integral, class FloatingPoint> inline constexpr typename std::ena
}
#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 "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<float> Vector3;
typedef Math::Vector3<std::int32_t> 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<float, std::uint8_t>(0)), 0.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);
}
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);

Loading…
Cancel
Save