diff --git a/maths.hpp b/maths.hpp index 62e8a86d..6e1a2aba 100644 --- a/maths.hpp +++ b/maths.hpp @@ -23,10 +23,11 @@ #include "debug.hpp" #include "types/traits.hpp" +#include #include +#include #include #include -#include template T @@ -307,6 +308,34 @@ smoothstep [[gnu::pure]] (T a, T b, T x) return x * x * (3 - 2 * x); } +#include "types/string.hpp" + +//----------------------------------------------------------------------------- +template +U +renormalise [[gnu::pure]] (T t) +{ + static const T T_max = std::numeric_limits::max (); + static const U U_max = std::numeric_limits::max (); + static const bool shrinking = sizeof (U) < sizeof (T); + static const bool T_float = std::is_floating_point::value; + static const bool U_float = std::is_floating_point::value; + + if (T_float && U_float) + return U (t); + + if (T_float) { + return U (limit (t, 0, 1) * U_max); + } + + if (U_float) + return U (t) / T_max; + + if (shrinking) + return U (t / (sizeof (T) / sizeof (U))); + else + return U (t) * (sizeof (U) / sizeof (T)); +} #include "maths.ipp" diff --git a/test/maths.cpp b/test/maths.cpp index ed081040..50258ed1 100644 --- a/test/maths.cpp +++ b/test/maths.cpp @@ -51,6 +51,39 @@ test_comparisons (void) } +void +test_normalisations (void) +{ + // u8 to float + { + auto a = renormalise (255); + CHECK_EQ (a, 1.f); + + auto b = renormalise (0); + CHECK_EQ (b, 0.f); + } + + // float to u8 + { + struct { + float a; + uint8_t b; + } TESTS[] = { + { 1.f, 255 }, + { 0.f, 0 }, + { 2.f, 255 }, + { -1.f, 0 } + }; + + for (auto i: TESTS) { + std::cerr << "x"; + auto v = renormalise (i.a); + CHECK_EQ ((unsigned)v, (unsigned)i.b); + } + } +} + + int main (int, char **) { // Max out the precision in case we trigger debug output @@ -59,6 +92,8 @@ main (int, char **) { test_comparisons (); + test_normalisations (); + CHECK_EQ (util::min (-2, 0, 2), -2); CHECK_EQ (util::max (-2, 0, 2), 2);