Browse Source

Math: vector overloads for normalize() and denormalize().

pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
263d8351b6
  1. 45
      src/Math/Functions.h
  2. 10
      src/Math/Test/FunctionsTest.cpp

45
src/Math/Functions.h

@ -144,9 +144,9 @@ template<std::size_t size, class T> Vector<size, T> clamp(const Vector<size, T>&
Converts integral value from full range of given *unsigned* integral type to
value in range @f$ [0, 1] @f$ or from *signed* integral to range @f$ [-1, 1] @f$.
@note For best precision, `FloatingPoint` type should be always larger that
resulting `Integral` type (e.g. `double` to `std::int32_t`, `long double`
to `std::int64_t`).
@note For best precision, resulting `FloatingPoint` type should be always
larger that `Integral` type (e.g. `double` from `std::int32_t`, `long double`
from `std::int64_t` and similarly for vector types).
@attention To ensure the integral type is correctly detected when using
literals, this function should be called with both template parameters
@ -162,14 +162,27 @@ float b = normalize<float, std::int8_t>('\127');
@see denormalize()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class FloatingPoint, class Integral> inline constexpr FloatingPoint normalize(Integral value);
template<class FloatingPoint, class Integral> inline FloatingPoint normalize(const Integral& value);
#else
template<class FloatingPoint, class Integral> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value && std::is_unsigned<Integral>::value, FloatingPoint>::type normalize(Integral value) {
template<class FloatingPoint, class Integral> inline typename std::enable_if<std::is_arithmetic<Integral>::value && std::is_unsigned<Integral>::value, FloatingPoint>::type normalize(Integral value) {
static_assert(std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value,
"Math::normalize(): normalization must be done from integral to floating-point type");
return value/FloatingPoint(std::numeric_limits<Integral>::max());
}
template<class FloatingPoint, class Integral> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value && std::is_signed<Integral>::value, FloatingPoint>::type normalize(Integral value) {
return std::max(value/FloatingPoint(std::numeric_limits<Integral>::max()), FloatingPoint(-1));
template<class FloatingPoint, class Integral> inline typename std::enable_if<std::is_arithmetic<Integral>::value && std::is_signed<Integral>::value, FloatingPoint>::type normalize(Integral value) {
static_assert(std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value,
"Math::normalize(): normalization must be done from integral to floating-point type");
return Math::max(value/FloatingPoint(std::numeric_limits<Integral>::max()), FloatingPoint(-1));
}
template<class FloatingPoint, class Integral> inline typename std::enable_if<std::is_unsigned<typename Integral::Type>::value, FloatingPoint>::type normalize(const Integral& value) {
static_assert(std::is_floating_point<typename FloatingPoint::Type>::value && std::is_integral<typename Integral::Type>::value,
"Math::normalize(): normalization must be done from integral to floating-point type");
return FloatingPoint::from(value)/typename FloatingPoint::Type(std::numeric_limits<typename Integral::Type>::max());
}
template<class FloatingPoint, class Integral> inline typename std::enable_if<std::is_signed<typename Integral::Type>::value, FloatingPoint>::type normalize(const Integral& value) {
static_assert(std::is_floating_point<typename FloatingPoint::Type>::value && std::is_integral<typename Integral::Type>::value,
"Math::normalize(): normalization must be done from integral to floating-point type");
return Math::max(FloatingPoint::from(value)/typename FloatingPoint::Type(std::numeric_limits<typename Integral::Type>::max()), FloatingPoint(-1));
}
#endif
@ -182,16 +195,26 @@ integral type.
@note For best precision, `FloatingPoint` type should be always larger that
resulting `Integral` type (e.g. `double` to `std::int32_t`, `long double`
to `std::int64_t`).
to `std::int64_t` and similarly for vector types).
@attention Return value for floating point numbers outside the normalized
range is undefined.
@see normalize()
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class Integral, class FloatingPoint> inline constexpr typename Integral denormalize(FloatingPoint value);
template<class Integral, class FloatingPoint> inline Integral denormalize(const FloatingPoint& value);
#else
template<class Integral, class FloatingPoint> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value, Integral>::type denormalize(FloatingPoint value) {
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_arithmetic<FloatingPoint>::value, Integral>::type denormalize(FloatingPoint value) {
static_assert(std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value,
"Math::denormalize(): denormalization must be done from floating-point to integral type");
return value*std::numeric_limits<Integral>::max();
}
template<class Integral, class FloatingPoint> inline typename std::enable_if<std::is_arithmetic<typename Integral::Type>::value, Integral>::type denormalize(const FloatingPoint& value) {
static_assert(std::is_floating_point<typename FloatingPoint::Type>::value && std::is_integral<typename Integral::Type>::value,
"Math::denormalize(): denormalization must be done from floating-point to integral type");
return Integral::from(value*std::numeric_limits<typename Integral::Type>::max());
}
#endif
/*@}*/

10
src/Math/Test/FunctionsTest.cpp

@ -40,6 +40,8 @@ class FunctionsTest: public Corrade::TestSuite::Tester {
};
typedef Math::Vector3<float> Vector3;
typedef Math::Vector3<std::uint8_t> Vector3ub;
typedef Math::Vector3<std::int8_t> Vector3b;
typedef Math::Vector3<std::int32_t> Vector3i;
FunctionsTest::FunctionsTest() {
@ -90,6 +92,8 @@ void FunctionsTest::normalizeUnsigned() {
CORRADE_COMPARE((Math::normalize<float, std::uint16_t>(8192)), 0.125002f);
CORRADE_COMPARE((Math::normalize<float, std::uint16_t>(49152)), 0.750011f);
CORRADE_COMPARE(Math::normalize<Vector3>(Vector3ub(0, 127, 255)), Vector3(0.0f, 0.498039f, 1.0f));
}
void FunctionsTest::normalizeSigned() {
@ -111,6 +115,8 @@ void FunctionsTest::normalizeSigned() {
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(16384)), 0.500015f);
CORRADE_COMPARE((Math::normalize<float, std::int16_t>(-16384)), -0.500015f);
CORRADE_COMPARE(Math::normalize<Vector3>(Vector3b(0, -127, 64)), Vector3(0.0f, -1.0f, 0.503937f));
}
void FunctionsTest::denormalizeUnsigned() {
@ -128,6 +134,8 @@ void FunctionsTest::denormalizeUnsigned() {
CORRADE_COMPARE(Math::denormalize<std::uint16_t>(0.33f), 21626);
CORRADE_COMPARE(Math::denormalize<std::uint16_t>(0.66f), 43253);
CORRADE_COMPARE(Math::denormalize<Vector3ub>(Vector3(0.0f, 0.5f, 1.0f)), Vector3ub(0, 127, 255));
}
void FunctionsTest::denormalizeSigned() {
@ -149,6 +157,8 @@ void FunctionsTest::denormalizeSigned() {
CORRADE_COMPARE(Math::denormalize<std::int16_t>(-0.33f), -10813);
CORRADE_COMPARE(Math::denormalize<std::int16_t>(0.66f), 21626);
CORRADE_COMPARE(Math::denormalize<Vector3b>(Vector3(0.0f, -1.0f, 0.5f)), Vector3b(0, -127, 63));
}
void FunctionsTest::renormalizeUnsinged() {

Loading…
Cancel
Save