diff options
Diffstat (limited to 'core/fxcrt')
-rw-r--r-- | core/fxcrt/fx_extension.h | 17 | ||||
-rw-r--r-- | core/fxcrt/fx_extension_unittest.cpp | 30 |
2 files changed, 47 insertions, 0 deletions
diff --git a/core/fxcrt/fx_extension.h b/core/fxcrt/fx_extension.h index cef943fc99..dcdd64e1fc 100644 --- a/core/fxcrt/fx_extension.h +++ b/core/fxcrt/fx_extension.h @@ -8,6 +8,7 @@ #define CORE_FXCRT_FX_EXTENSION_H_ #include <cctype> +#include <cmath> #include <cwctype> #include <memory> @@ -92,4 +93,20 @@ void FXSYS_IntToFourHexChars(uint16_t c, char* buf); size_t FXSYS_ToUTF16BE(uint32_t unicode, char* buf); +// Strict order over floating types where NaNs may be present. +template <typename T> +bool FXSYS_SafeEQ(const T& lhs, const T& rhs) { + return (std::isnan(lhs) && std::isnan(rhs)) || + (!std::isnan(lhs) && !std::isnan(rhs) && lhs == rhs); +} + +template <typename T> +bool FXSYS_SafeLT(const T& lhs, const T& rhs) { + if (std::isnan(lhs) && std::isnan(rhs)) + return false; + if (std::isnan(lhs) || std::isnan(rhs)) + return std::isnan(lhs) < std::isnan(rhs); + return lhs < rhs; +} + #endif // CORE_FXCRT_FX_EXTENSION_H_ diff --git a/core/fxcrt/fx_extension_unittest.cpp b/core/fxcrt/fx_extension_unittest.cpp index 39f26b534b..d84071b83a 100644 --- a/core/fxcrt/fx_extension_unittest.cpp +++ b/core/fxcrt/fx_extension_unittest.cpp @@ -3,6 +3,9 @@ // found in the LICENSE file. #include "core/fxcrt/fx_extension.h" + +#include <limits> + #include "testing/gtest/include/gtest/gtest.h" TEST(fxcrt, FXSYS_HexCharToInt) { @@ -134,3 +137,30 @@ TEST(fxcrt, FXSYS_wcstof) { FXSYS_wcstof(L"99999999999999999", 17, &used_len)); EXPECT_EQ(17, used_len); } + +TEST(fxcrt, FXSYS_SafeOps) { + const float fMin = std::numeric_limits<float>::min(); + const float fMax = std::numeric_limits<float>::max(); + const float fInf = std::numeric_limits<float>::infinity(); + const float fNan = std::numeric_limits<float>::quiet_NaN(); + const float ascending[] = {fMin, 1.0f, 2.0f, fMax, fInf, fNan}; + + for (size_t i = 0; i < FX_ArraySize(ascending); ++i) { + for (size_t j = 0; j < FX_ArraySize(ascending); ++j) { + if (i == j) { + EXPECT_TRUE(FXSYS_SafeEQ(ascending[i], ascending[j])) + << " at " << i << " " << j; + } else { + EXPECT_FALSE(FXSYS_SafeEQ(ascending[i], ascending[j])) + << " at " << i << " " << j; + } + if (i < j) { + EXPECT_TRUE(FXSYS_SafeLT(ascending[i], ascending[j])) + << " at " << i << " " << j; + } else { + EXPECT_FALSE(FXSYS_SafeLT(ascending[i], ascending[j])) + << " at " << i << " " << j; + } + } + } +} |