// Copyright 2018 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include #include #include "Common/BitUtils.h" #include "Common/FloatUtils.h" TEST(FloatUtils, IsQNAN) { EXPECT_TRUE(Common::IsQNAN(std::numeric_limits::quiet_NaN())); EXPECT_FALSE(Common::IsQNAN(Common::SNANConstant())); } TEST(FloatUtils, IsSNAN) { EXPECT_FALSE(Common::IsSNAN(std::numeric_limits::quiet_NaN())); EXPECT_TRUE(Common::IsSNAN(Common::SNANConstant())); } TEST(FloatUtils, 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.f, s * 2); EXPECT_LT(0.0, d * 2); EXPECT_EQ(+0.0, Common::FlushToZero(+std::numeric_limits::denorm_min())); EXPECT_EQ(-0.0, Common::FlushToZero(-std::numeric_limits::denorm_min())); EXPECT_EQ(+0.0, Common::FlushToZero(+std::numeric_limits::min() / 2)); EXPECT_EQ(-0.0, Common::FlushToZero(-std::numeric_limits::min() / 2)); EXPECT_EQ(std::numeric_limits::min(), Common::FlushToZero(std::numeric_limits::min())); EXPECT_EQ(std::numeric_limits::max(), Common::FlushToZero(std::numeric_limits::max())); EXPECT_EQ(+std::numeric_limits::infinity(), Common::FlushToZero(+std::numeric_limits::infinity())); EXPECT_EQ(-std::numeric_limits::infinity(), Common::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) { u32 i_tmp = i; EXPECT_EQ(+0.f, Common::FlushToZero(Common::BitCast(i_tmp))); i_tmp |= 0x80000000u; EXPECT_EQ(-0.f, Common::FlushToZero(Common::BitCast(i_tmp))); i_tmp = dist(engine); EXPECT_EQ(i_tmp, Common::BitCast(Common::FlushToZero(Common::BitCast(i_tmp)))); i_tmp |= 0x80000000u; EXPECT_EQ(i_tmp, Common::BitCast(Common::FlushToZero(Common::BitCast(i_tmp)))); } }