Browse Source

Functions for normalizing and denormalizing numeric values.

vectorfields
Vladimír Vondruš 14 years ago
parent
commit
2553e50444
  1. 39
      src/Math/Math.h
  2. 50
      src/Math/Test/MathTest.cpp
  3. 2
      src/Math/Test/MathTest.h

39
src/Math/Math.h

@ -16,6 +16,8 @@
*/
#include <cstddef>
#include <type_traits>
#include <limits>
#include "magnumVisibility.h"
@ -85,6 +87,43 @@ template<size_t exponent, class T> inline constexpr T pow(T base) {
*/
size_t MAGNUM_EXPORT log(size_t base, size_t number);
/**
@brief Normalize floating-point value
Converts integral value from full range of given (signed/unsigned) integral
type to value in range @f$ [0, 1] @f$.
@attention To ensure the integral type is correctly detected when using
literals, this function should be called with both template parameters
explicit, e.g.:
@code
// Even if this is char literal, integral type is `int`, thus a = 0.1f
float a = normalize<float>('\127');
// b = 1.0f
float b = normalize<float, char>('\127');
@endcode
*/
template<class FloatingPoint, class Integral> inline constexpr typename std::enable_if<std::is_floating_point<FloatingPoint>::value && std::is_integral<Integral>::value, FloatingPoint>::type normalize(Integral value) {
return (FloatingPoint(value)-FloatingPoint(std::numeric_limits<Integral>::min()))/
(FloatingPoint(std::numeric_limits<Integral>::max()) - FloatingPoint(std::numeric_limits<Integral>::min()));
}
/**
@brief Denormalize floating-point value
Converts floating-point value in range @f$ [0, 1] @f$ to full range of given
integral type.
@note For best precision, `FloatingPoint` type should be always larger that
resulting `Integral` type (e.g. `double` to `int`, `long double` to `long long`).
*/
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) {
return std::numeric_limits<Integral>::min() +
Integral(value*std::numeric_limits<Integral>::max()) -
Integral(value*std::numeric_limits<Integral>::min());
}
/**
* @brief Angle in degrees
*

50
src/Math/Test/MathTest.cpp

@ -17,12 +17,16 @@
#include "Math.h"
using namespace std;
CORRADE_TEST_MAIN(Magnum::Math::Test::MathTest)
namespace Magnum { namespace Math { namespace Test {
MathTest::MathTest() {
addTests(&MathTest::degrad,
&MathTest::normalize,
&MathTest::denormalize,
&MathTest::pow,
&MathTest::log);
}
@ -33,6 +37,52 @@ void MathTest::degrad() {
CORRADE_COMPARE(rad(Constants<double>::pi()/2), Constants<double>::pi()/2);
}
void MathTest::normalize() {
/* Range for signed and unsigned */
CORRADE_COMPARE((Math::normalize<float, char>(-128)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, char>(127)), 1.0f);
CORRADE_COMPARE((Math::normalize<float, unsigned char>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, unsigned char>(255)), 1.0f);
/* Between */
CORRADE_COMPARE((Math::normalize<float, short>(16384)), 0.750011f);
CORRADE_COMPARE((Math::normalize<float, short>(-16384)), 0.250004f);
/* Test overflow for large types */
CORRADE_COMPARE((Math::normalize<float, int>(numeric_limits<int>::min())), 0.0f);
CORRADE_COMPARE((Math::normalize<float, int>(numeric_limits<int>::max())), 1.0f);
CORRADE_COMPARE((Math::normalize<float, unsigned int>(0)), 0.0f);
CORRADE_COMPARE((Math::normalize<float, unsigned int>(numeric_limits<unsigned int>::max())), 1.0f);
CORRADE_COMPARE((Math::normalize<double, long long>(numeric_limits<long long>::min())), 0.0);
CORRADE_COMPARE((Math::normalize<double, long long>(numeric_limits<long long>::max())), 1.0);
CORRADE_COMPARE((Math::normalize<double, unsigned long long>(0)), 0.0);
CORRADE_COMPARE((Math::normalize<double, unsigned long long>(numeric_limits<unsigned long long>::max())), 1.0);
}
void MathTest::denormalize() {
/* Range for signed and unsigned */
CORRADE_COMPARE(Math::denormalize<char>(0.0f), -128);
CORRADE_COMPARE(Math::denormalize<char>(1.0f), 127);
CORRADE_COMPARE(Math::denormalize<unsigned char>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<unsigned char>(1.0f), 255);
/* Between */
CORRADE_COMPARE(Math::denormalize<short>(0.33f), -11142);
CORRADE_COMPARE(Math::denormalize<short>(0.66f), 10484);
/* Test overflow for large types */
CORRADE_COMPARE(Math::denormalize<int>(0.0f), numeric_limits<int>::min());
CORRADE_COMPARE(Math::denormalize<unsigned int>(0.0f), 0);
CORRADE_COMPARE(Math::denormalize<long long>(0.0), numeric_limits<long long>::min());
CORRADE_COMPARE(Math::denormalize<unsigned long long>(0.0), 0);
CORRADE_COMPARE(Math::denormalize<int>(1.0), numeric_limits<int>::max());
CORRADE_COMPARE(Math::denormalize<unsigned int>(1.0), numeric_limits<unsigned int>::max());
CORRADE_COMPARE((Math::denormalize<long long, long double>(1.0)), numeric_limits<long long>::max());
CORRADE_COMPARE((Math::denormalize<unsigned long long, long double>(1.0)), numeric_limits<unsigned long long>::max());
}
void MathTest::pow() {
CORRADE_COMPARE(Math::pow<10>(2ul), 1024ul);
CORRADE_COMPARE(Math::pow<0>(3ul), 1ul);

2
src/Math/Test/MathTest.h

@ -24,6 +24,8 @@ class MathTest: public Corrade::TestSuite::Tester<MathTest> {
MathTest();
void degrad();
void normalize();
void denormalize();
void pow();
void log();
};

Loading…
Cancel
Save