From e0baed850fcf75c6920e41f627fb06048a85985a Mon Sep 17 00:00:00 2001 From: Tillmann Karras Date: Mon, 24 Mar 2014 03:11:11 +0100 Subject: [PATCH] MathUtilTest: add test for FlushToZero --- Source/UnitTests/Common/MathUtilTest.cpp | 43 +++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/Source/UnitTests/Common/MathUtilTest.cpp b/Source/UnitTests/Common/MathUtilTest.cpp index 56ade34522..d2056df3f9 100644 --- a/Source/UnitTests/Common/MathUtilTest.cpp +++ b/Source/UnitTests/Common/MathUtilTest.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "Common/MathUtil.h" @@ -29,7 +30,7 @@ TEST(MathUtil, Clamp) TEST(MathUtil, IsINF) { - EXPECT_TRUE(MathUtil::IsINF( std::numeric_limits::infinity())); + EXPECT_TRUE(MathUtil::IsINF(+std::numeric_limits::infinity())); EXPECT_TRUE(MathUtil::IsINF(-std::numeric_limits::infinity())); } @@ -63,3 +64,43 @@ TEST(MathUtil, Log2) EXPECT_EQ(3, Log2(15)); EXPECT_EQ(63, Log2(0xFFFFFFFFFFFFFFFFull)); } + +TEST(MathUtil, FlushToZero) +{ + // To test the software implementation we need to make sure FTZ and DAZ are disabled. + // Using volatile here to ensure the compiler doesn't constant-fold it, + // we want the multiplication to occur at test runtime. + volatile float s = std::numeric_limits::denorm_min(); + volatile double d = std::numeric_limits::denorm_min(); + EXPECT_LT(0, s * 2); + EXPECT_LT(0, d * 2); + + EXPECT_EQ(+0, MathUtil::FlushToZero(+std::numeric_limits::denorm_min())); + EXPECT_EQ(-0, MathUtil::FlushToZero(-std::numeric_limits::denorm_min())); + EXPECT_EQ(+0, MathUtil::FlushToZero(+std::numeric_limits::min() / 2)); + EXPECT_EQ(-0, MathUtil::FlushToZero(-std::numeric_limits::min() / 2)); + EXPECT_EQ(std::numeric_limits::min(), MathUtil::FlushToZero(std::numeric_limits::min())); + EXPECT_EQ(std::numeric_limits::max(), MathUtil::FlushToZero(std::numeric_limits::max())); + EXPECT_EQ(+std::numeric_limits::infinity(), MathUtil::FlushToZero(+std::numeric_limits::infinity())); + EXPECT_EQ(-std::numeric_limits::infinity(), MathUtil::FlushToZero(-std::numeric_limits::infinity())); + + // Test all subnormals as well as an equally large set of random normal floats. + std::default_random_engine engine(0); + std::uniform_int_distribution dist(0x00800000u, 0x7fffffffu); + for (u32 i = 0; i <= 0x007fffffu; ++i) + { + MathUtil::IntFloat x(i); + EXPECT_EQ(+0, MathUtil::FlushToZero(x.f)); + + x.i = i | 0x80000000u; + EXPECT_EQ(-0, MathUtil::FlushToZero(x.f)); + + x.i = dist(engine); + MathUtil::IntFloat y(MathUtil::FlushToZero(x.f)); + EXPECT_EQ(x.i, y.i); + + x.i |= 0x80000000u; + y.f = MathUtil::FlushToZero(x.f); + EXPECT_EQ(x.i, y.i); + } +}