From 263d8351b6bf2112e66ce3ea330546bd7032eb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 17 Jan 2013 00:47:21 +0100 Subject: [PATCH] Math: vector overloads for normalize() and denormalize(). --- src/Math/Functions.h | 45 +++++++++++++++++++++++++-------- src/Math/Test/FunctionsTest.cpp | 10 ++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/Math/Functions.h b/src/Math/Functions.h index c22d70c10..e4416e90d 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -144,9 +144,9 @@ template Vector clamp(const Vector& 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('\127'); @see denormalize() */ #ifdef DOXYGEN_GENERATING_OUTPUT -template inline constexpr FloatingPoint normalize(Integral value); +template inline FloatingPoint normalize(const Integral& value); #else -template inline constexpr typename std::enable_if::value && std::is_integral::value && std::is_unsigned::value, FloatingPoint>::type normalize(Integral value) { +template inline typename std::enable_if::value && std::is_unsigned::value, FloatingPoint>::type normalize(Integral value) { + static_assert(std::is_floating_point::value && std::is_integral::value, + "Math::normalize(): normalization must be done from integral to floating-point type"); return value/FloatingPoint(std::numeric_limits::max()); } - -template inline constexpr typename std::enable_if::value && std::is_integral::value && std::is_signed::value, FloatingPoint>::type normalize(Integral value) { - return std::max(value/FloatingPoint(std::numeric_limits::max()), FloatingPoint(-1)); +template inline typename std::enable_if::value && std::is_signed::value, FloatingPoint>::type normalize(Integral value) { + static_assert(std::is_floating_point::value && std::is_integral::value, + "Math::normalize(): normalization must be done from integral to floating-point type"); + return Math::max(value/FloatingPoint(std::numeric_limits::max()), FloatingPoint(-1)); +} +template inline typename std::enable_if::value, FloatingPoint>::type normalize(const Integral& value) { + static_assert(std::is_floating_point::value && std::is_integral::value, + "Math::normalize(): normalization must be done from integral to floating-point type"); + return FloatingPoint::from(value)/typename FloatingPoint::Type(std::numeric_limits::max()); +} +template inline typename std::enable_if::value, FloatingPoint>::type normalize(const Integral& value) { + static_assert(std::is_floating_point::value && std::is_integral::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::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 inline constexpr typename Integral denormalize(FloatingPoint value); +template inline Integral denormalize(const FloatingPoint& value); #else -template inline constexpr typename std::enable_if::value && std::is_integral::value, Integral>::type denormalize(FloatingPoint value) { +template inline typename std::enable_if::value, Integral>::type denormalize(FloatingPoint value) { + static_assert(std::is_floating_point::value && std::is_integral::value, + "Math::denormalize(): denormalization must be done from floating-point to integral type"); return value*std::numeric_limits::max(); } +template inline typename std::enable_if::value, Integral>::type denormalize(const FloatingPoint& value) { + static_assert(std::is_floating_point::value && std::is_integral::value, + "Math::denormalize(): denormalization must be done from floating-point to integral type"); + return Integral::from(value*std::numeric_limits::max()); +} #endif /*@}*/ diff --git a/src/Math/Test/FunctionsTest.cpp b/src/Math/Test/FunctionsTest.cpp index eff4ff119..f71362c65 100644 --- a/src/Math/Test/FunctionsTest.cpp +++ b/src/Math/Test/FunctionsTest.cpp @@ -40,6 +40,8 @@ class FunctionsTest: public Corrade::TestSuite::Tester { }; typedef Math::Vector3 Vector3; +typedef Math::Vector3 Vector3ub; +typedef Math::Vector3 Vector3b; typedef Math::Vector3 Vector3i; FunctionsTest::FunctionsTest() { @@ -90,6 +92,8 @@ void FunctionsTest::normalizeUnsigned() { CORRADE_COMPARE((Math::normalize(8192)), 0.125002f); CORRADE_COMPARE((Math::normalize(49152)), 0.750011f); + + CORRADE_COMPARE(Math::normalize(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(16384)), 0.500015f); CORRADE_COMPARE((Math::normalize(-16384)), -0.500015f); + + CORRADE_COMPARE(Math::normalize(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(0.33f), 21626); CORRADE_COMPARE(Math::denormalize(0.66f), 43253); + + CORRADE_COMPARE(Math::denormalize(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(-0.33f), -10813); CORRADE_COMPARE(Math::denormalize(0.66f), 21626); + + CORRADE_COMPARE(Math::denormalize(Vector3(0.0f, -1.0f, 0.5f)), Vector3b(0, -127, 63)); } void FunctionsTest::renormalizeUnsinged() {