diff --git a/Source/Core/Common/MathUtil.h b/Source/Core/Common/MathUtil.h index 3ca5c1b770..236c554437 100644 --- a/Source/Core/Common/MathUtil.h +++ b/Source/Core/Common/MathUtil.h @@ -12,6 +12,32 @@ namespace MathUtil { + +template +constexpr T SNANConstant() +{ + return std::numeric_limits::signaling_NaN(); +} + +#ifdef _MSC_VER + +// MSVC needs a workaround, because its std::numeric_limits::signaling_NaN() +// will use __builtin_nans, which is improperly handled by the compiler and generates +// a bad constant. Here we go back to the version MSVC used before the builtin. +// TODO: Remove this and use numeric_limits directly whenever this bug is fixed. +template <> +constexpr double SNANConstant() +{ + return (_CSTD _Snan._Double); +} +template <> +constexpr float SNANConstant() +{ + return (_CSTD _Snan._Float); +} + +#endif + template constexpr T Clamp(const T val, const T& min, const T& max) { diff --git a/Source/UnitTests/Common/MathUtilTest.cpp b/Source/UnitTests/Common/MathUtilTest.cpp index f7427cc8c3..0eabd14694 100644 --- a/Source/UnitTests/Common/MathUtilTest.cpp +++ b/Source/UnitTests/Common/MathUtilTest.cpp @@ -23,13 +23,13 @@ TEST(MathUtil, Clamp) TEST(MathUtil, IsQNAN) { EXPECT_TRUE(MathUtil::IsQNAN(std::numeric_limits::quiet_NaN())); - EXPECT_FALSE(MathUtil::IsQNAN(std::numeric_limits::signaling_NaN())); + EXPECT_FALSE(MathUtil::IsQNAN(MathUtil::SNANConstant())); } TEST(MathUtil, IsSNAN) { EXPECT_FALSE(MathUtil::IsSNAN(std::numeric_limits::quiet_NaN())); - EXPECT_TRUE(MathUtil::IsSNAN(std::numeric_limits::signaling_NaN())); + EXPECT_TRUE(MathUtil::IsSNAN(MathUtil::SNANConstant())); } TEST(MathUtil, IntLog2)