From 056d59e862a11c9f841a08fbbdfd1a805b098f29 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 11 Apr 2020 22:43:32 -0700 Subject: MathLib: improved FastFloat implementation --- Common/interface/BasicMath.hpp | 23 +++++++++++++++++-- Tests/DiligentCoreTest/src/Common/MathLibTest.cpp | 28 +++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Common/interface/BasicMath.hpp b/Common/interface/BasicMath.hpp index 757244e1..25e99240 100644 --- a/Common/interface/BasicMath.hpp +++ b/Common/interface/BasicMath.hpp @@ -1942,13 +1942,32 @@ inline Uint32 F4Color_To_RGBA8Unorm(const float4& f4Color) return RGBA8U; } +template +struct _FastFloatIntermediateType +{ +}; + +template <> +struct _FastFloatIntermediateType +{ + // All floats that have fractional part are representable as 32-bit int + using Type = Int32; +}; + +template <> +struct _FastFloatIntermediateType +{ + // All doubles that have fractional part are representable as 64-bit int + using Type = Int64; +}; // At least on MSVC std::floor is an actual function call into ucrtbase.dll. -// For floats/doubles that fit into Int64 representable range we can do much better. +// All floats/doubles that have fractional parts also fit into integer +// representable range, so we can do much better. template T FastFloor(T x) { - auto i = static_cast(x); + auto i = static_cast::Type>(x); auto flr = static_cast(i); // x flr floor(x) flr <= x // +1.0 -> 1.0 1.0 true diff --git a/Tests/DiligentCoreTest/src/Common/MathLibTest.cpp b/Tests/DiligentCoreTest/src/Common/MathLibTest.cpp index 4a3da8a2..f7fa48be 100644 --- a/Tests/DiligentCoreTest/src/Common/MathLibTest.cpp +++ b/Tests/DiligentCoreTest/src/Common/MathLibTest.cpp @@ -1272,6 +1272,7 @@ TEST(Common_AdvancedMath, TraceLineThroughGrid) TEST(Common_BasicMath, FastFloor) { + // float EXPECT_EQ(FastFloor(0.f), 0.f); EXPECT_EQ(FastFloor(-0.0625f), -1.f); @@ -1283,10 +1284,24 @@ TEST(Common_BasicMath, FastFloor) EXPECT_EQ(FastFloor(0.975f), 0.f); EXPECT_EQ(FastFloor(1.f), 1.f); EXPECT_EQ(FastFloor(1.125f), 1.f); + + // double + EXPECT_EQ(FastFloor(0.0), 0.0); + + EXPECT_EQ(FastFloor(-0.03125), -1.0); + EXPECT_EQ(FastFloor(-0.96875), -1.0); + EXPECT_EQ(FastFloor(-1.0), -1.0); + EXPECT_EQ(FastFloor(-1.03125), -2.0); + + EXPECT_EQ(FastFloor(0.03125), 0.0); + EXPECT_EQ(FastFloor(0.96875), 0.0); + EXPECT_EQ(FastFloor(1.0), 1.0); + EXPECT_EQ(FastFloor(1.03125), 1.0); } TEST(Common_BasicMath, FastCeil) { + // float EXPECT_EQ(FastCeil(0.f), 0.f); EXPECT_EQ(FastCeil(-0.0625f), 0.f); @@ -1298,6 +1313,19 @@ TEST(Common_BasicMath, FastCeil) EXPECT_EQ(FastCeil(0.975f), 1.f); EXPECT_EQ(FastCeil(1.f), 1.f); EXPECT_EQ(FastCeil(1.125f), 2.f); + + // double + EXPECT_EQ(FastCeil(0.0), 0.0); + + EXPECT_EQ(FastCeil(-0.03125), 0.0); + EXPECT_EQ(FastCeil(-0.96875), 0.0); + EXPECT_EQ(FastCeil(-1.0), -1.0); + EXPECT_EQ(FastCeil(-1.03125), -1.0); + + EXPECT_EQ(FastCeil(0.03125), 1.0); + EXPECT_EQ(FastCeil(0.96875), 1.0); + EXPECT_EQ(FastCeil(1.0), 1.0); + EXPECT_EQ(FastCeil(1.03125), 2.0); } } // namespace -- cgit v1.2.3