summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-04-12 05:43:32 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-04-12 05:43:32 +0000
commit056d59e862a11c9f841a08fbbdfd1a805b098f29 (patch)
treeaa75d303f59ce556d4b0064967c10a181e9cfa8e
parentMade FastRand and FastRandReal ctors explicit (diff)
downloadDiligentCore-056d59e862a11c9f841a08fbbdfd1a805b098f29.tar.gz
DiligentCore-056d59e862a11c9f841a08fbbdfd1a805b098f29.zip
MathLib: improved FastFloat implementation
-rw-r--r--Common/interface/BasicMath.hpp23
-rw-r--r--Tests/DiligentCoreTest/src/Common/MathLibTest.cpp28
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