diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-04-12 05:43:32 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-04-12 05:43:32 +0000 |
| commit | 056d59e862a11c9f841a08fbbdfd1a805b098f29 (patch) | |
| tree | aa75d303f59ce556d4b0064967c10a181e9cfa8e | |
| parent | Made FastRand and FastRandReal ctors explicit (diff) | |
| download | DiligentCore-056d59e862a11c9f841a08fbbdfd1a805b098f29.tar.gz DiligentCore-056d59e862a11c9f841a08fbbdfd1a805b098f29.zip | |
MathLib: improved FastFloat implementation
| -rw-r--r-- | Common/interface/BasicMath.hpp | 23 | ||||
| -rw-r--r-- | 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 <typename T> +struct _FastFloatIntermediateType +{ +}; + +template <> +struct _FastFloatIntermediateType<float> +{ + // All floats that have fractional part are representable as 32-bit int + using Type = Int32; +}; + +template <> +struct _FastFloatIntermediateType<double> +{ + // 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 <typename T> T FastFloor(T x) { - auto i = static_cast<Int64>(x); + auto i = static_cast<typename _FastFloatIntermediateType<T>::Type>(x); auto flr = static_cast<T>(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 |
