diff --git a/.github/actions/spelling/allow/math.txt b/.github/actions/spelling/allow/math.txt index 096fc197473..bf8960f0089 100644 --- a/.github/actions/spelling/allow/math.txt +++ b/.github/actions/spelling/allow/math.txt @@ -8,3 +8,4 @@ LStep powf RSub sqrtf +ULP diff --git a/src/buffer/out/TextColor.cpp b/src/buffer/out/TextColor.cpp index dcd0a8df342..7c05dd20043 100644 --- a/src/buffer/out/TextColor.cpp +++ b/src/buffer/out/TextColor.cpp @@ -4,6 +4,8 @@ #include "precomp.h" #include "TextColor.h" +#include + // clang-format off // A table mapping 8-bit RGB colors, in the form RRRGGGBB, @@ -186,7 +188,7 @@ COLORREF TextColor::GetColor(const std::array& colorTable, const // the result will be something like 0b00100000. // 5. Use BitScanForward (bsf) to find the index of the most significant 1 bit. const auto haystack = _mm256_loadu_si256(reinterpret_cast(colorTable.data())); // 1. - const auto needle = _mm256_set1_epi32(__builtin_bit_cast(int, defaultColor)); // 2. + const auto needle = _mm256_set1_epi32(til::bit_cast(defaultColor)); // 2. const auto result = _mm256_cmpeq_epi32(haystack, needle); // 3. const auto mask = _mm256_movemask_ps(_mm256_castsi256_ps(result)); // 4. unsigned long index; @@ -203,7 +205,7 @@ COLORREF TextColor::GetColor(const std::array& colorTable, const // --> the index returned by _BitScanForward must be divided by 2. const auto haystack1 = _mm_loadu_si128(reinterpret_cast(colorTable.data() + 0)); const auto haystack2 = _mm_loadu_si128(reinterpret_cast(colorTable.data() + 4)); - const auto needle = _mm_set1_epi32(__builtin_bit_cast(int, defaultColor)); + const auto needle = _mm_set1_epi32(til::bit_cast(defaultColor)); const auto result1 = _mm_cmpeq_epi32(haystack1, needle); const auto result2 = _mm_cmpeq_epi32(haystack2, needle); const auto result = _mm_packs_epi32(result1, result2); // 3.5 diff --git a/src/cascadia/ut_app/ColorHelperTests.cpp b/src/cascadia/ut_app/ColorHelperTests.cpp index 3f6166ee188..03ec18d57ea 100644 --- a/src/cascadia/ut_app/ColorHelperTests.cpp +++ b/src/cascadia/ut_app/ColorHelperTests.cpp @@ -6,6 +6,9 @@ #include "../TerminalSettingsModel/Profile.h" #include "../TerminalApp/ColorHelper.h" +// Import some templates to compare floats using approximate matching. +#include + using namespace Microsoft::Console; using namespace winrt::TerminalApp; using namespace WEX::Logging; diff --git a/src/common.build.pre.props b/src/common.build.pre.props index 24e8903d5b9..ca15b0a0436 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -119,6 +119,7 @@ stdcpp17 /utf-8 %(AdditionalOptions) Guard + Fast EXTERNAL_BUILD;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -145,6 +146,10 @@ Disabled _DEBUG;DBG;%(PreprocessorDefinitions) + + false + DebugFastLink + diff --git a/src/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index a4e5e82ff8b..a3b9b39aebc 100644 --- a/src/inc/consoletaeftemplates.hpp +++ b/src/inc/consoletaeftemplates.hpp @@ -17,6 +17,8 @@ Revision History: #pragma once +#include + // Helper for declaring a variable to store a TEST_METHOD_PROPERTY and get it's value from the test metadata #define INIT_TEST_PROPERTY(type, identifer, description) \ type identifer; \ @@ -43,6 +45,45 @@ Revision History: namespace WEX::TestExecution { + // Compare two floats using a ULP (unit last place) tolerance of up to 4. + // Allows you to compare two floats that are almost equal. + // Think of: 0.200000000000000 vs. 0.200000000000001. + template + bool CompareFloats(T a, T b) noexcept + { + if (std::isnan(a)) + { + return std::isnan(b); + } + + if (a == b) + { + return true; + } + + const auto nDiff = static_cast>(til::bit_cast(a) - til::bit_cast(b)); + const auto uDiff = static_cast(nDiff < 0 ? -nDiff : nDiff); + return uDiff <= 4; + } + + template<> + struct VerifyCompareTraits + { + static bool AreEqual(float a, float b) noexcept + { + return CompareFloats(a, b); + } + }; + + template<> + struct VerifyCompareTraits + { + static bool AreEqual(double a, double b) noexcept + { + return CompareFloats(a, b); + } + }; + template<> class VerifyOutputTraits { diff --git a/src/inc/til/bit.h b/src/inc/til/bit.h new file mode 100644 index 00000000000..fd8d9c44ff3 --- /dev/null +++ b/src/inc/til/bit.h @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +namespace til +{ + template, std::is_trivially_copyable, std::is_trivially_copyable>, int> = 0> + [[nodiscard]] constexpr To bit_cast(const From& _Val) noexcept + { +#ifdef __cpp_lib_bit_cast +#warning "Replace til::bit_cast and __builtin_bit_cast with std::bit_cast" +#endif + return __builtin_bit_cast(To, _Val); + } +} diff --git a/src/project.inc b/src/project.inc index 8c3f92206e3..4a0c674ab59 100644 --- a/src/project.inc +++ b/src/project.inc @@ -29,7 +29,7 @@ USE_NATIVE_EH = 1 # ------------------------------------- MSC_WARNING_LEVEL = /W4 /WX -USER_C_FLAGS = $(USER_C_FLAGS) /utf-8 +USER_C_FLAGS = $(USER_C_FLAGS) /fp:fast /utf-8 # ------------------------------------- # Common Console Includes and Libraries