From 7c07c3c7a6fbc54cf589623fa33c5746224d758b Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Fri, 8 Oct 2021 21:38:21 +0200 Subject: [PATCH 1/8] Enable fast floating point model and fast debug linking --- src/common.build.pre.props | 5 +++++ src/project.inc | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) 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/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 From ccff6f68beb041189c2b8bd5c04d6ac3674eb79e Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Sat, 9 Oct 2021 00:50:21 +0200 Subject: [PATCH 2/8] Introduce ULP based float comparisons --- src/cascadia/ut_app/ColorHelperTests.cpp | 5 +++ src/inc/consoletaeftemplates.hpp | 42 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/cascadia/ut_app/ColorHelperTests.cpp b/src/cascadia/ut_app/ColorHelperTests.cpp index 3f6166ee188..2da39a81b50 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; @@ -27,6 +30,8 @@ namespace TerminalAppUnitTests void ColorHelperTests::ConvertHslToRgb() { + //DebugBreak(); + auto red = winrt::Windows::UI::Colors::Red(); auto redHsl = ColorHelper::RgbToHsl(red); VERIFY_ARE_EQUAL(0.f, redHsl.H); diff --git a/src/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index a4e5e82ff8b..544d26fabb5 100644 --- a/src/inc/consoletaeftemplates.hpp +++ b/src/inc/consoletaeftemplates.hpp @@ -43,6 +43,48 @@ Revision History: namespace WEX::TestExecution { + namespace details + { + // 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>(*reinterpret_cast(&a) - *reinterpret_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 details::CompareFloats(a, b); + } + }; + + template<> + struct VerifyCompareTraits + { + static bool AreEqual(double a, double b) noexcept + { + return details::CompareFloats(a, b); + } + }; + template<> class VerifyOutputTraits { From ac7c7c2b23744b66d7c0f2913a94375e2634965d Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Sat, 9 Oct 2021 00:52:23 +0200 Subject: [PATCH 3/8] Fix formatting --- src/inc/consoletaeftemplates.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index 544d26fabb5..0e427d3865a 100644 --- a/src/inc/consoletaeftemplates.hpp +++ b/src/inc/consoletaeftemplates.hpp @@ -75,7 +75,7 @@ namespace WEX::TestExecution return details::CompareFloats(a, b); } }; - + template<> struct VerifyCompareTraits { From f92ccba9c010d5e6d1e320230a6f5cd492e392eb Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Sat, 9 Oct 2021 00:56:33 +0200 Subject: [PATCH 4/8] Fix spellcheck --- .github/actions/spelling/allow/math.txt | 1 + 1 file changed, 1 insertion(+) 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 From 30eede7f5341c70c52fb68f2cc233a7038a14c80 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Sat, 9 Oct 2021 01:22:06 +0200 Subject: [PATCH 5/8] Fix build error --- src/inc/consoletaeftemplates.hpp | 37 +++++++++++++++----------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index 0e427d3865a..2f38062e752 100644 --- a/src/inc/consoletaeftemplates.hpp +++ b/src/inc/consoletaeftemplates.hpp @@ -43,28 +43,25 @@ Revision History: namespace WEX::TestExecution { - namespace details + // 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 { - // 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)) { - if (std::isnan(a)) - { - return std::isnan(b); - } - - if (a == b) - { - return true; - } + return std::isnan(b); + } - const auto nDiff = static_cast>(*reinterpret_cast(&a) - *reinterpret_cast(&b)); - const auto uDiff = static_cast(nDiff < 0 ? -nDiff : nDiff); - return uDiff <= 4; + if (a == b) + { + return true; } + + const auto nDiff = static_cast>(*reinterpret_cast(&a) - *reinterpret_cast(&b)); + const auto uDiff = static_cast(nDiff < 0 ? -nDiff : nDiff); + return uDiff <= 4; } template<> @@ -72,7 +69,7 @@ namespace WEX::TestExecution { static bool AreEqual(float a, float b) noexcept { - return details::CompareFloats(a, b); + return CompareFloats(a, b); } }; @@ -81,7 +78,7 @@ namespace WEX::TestExecution { static bool AreEqual(double a, double b) noexcept { - return details::CompareFloats(a, b); + return CompareFloats(a, b); } }; From 4948902d791b9e3add6b95a2f42143eb693b6d88 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Sat, 9 Oct 2021 03:19:43 +0200 Subject: [PATCH 6/8] Remove accidential comment --- src/cascadia/ut_app/ColorHelperTests.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cascadia/ut_app/ColorHelperTests.cpp b/src/cascadia/ut_app/ColorHelperTests.cpp index 2da39a81b50..03ec18d57ea 100644 --- a/src/cascadia/ut_app/ColorHelperTests.cpp +++ b/src/cascadia/ut_app/ColorHelperTests.cpp @@ -30,8 +30,6 @@ namespace TerminalAppUnitTests void ColorHelperTests::ConvertHslToRgb() { - //DebugBreak(); - auto red = winrt::Windows::UI::Colors::Red(); auto redHsl = ColorHelper::RgbToHsl(red); VERIFY_ARE_EQUAL(0.f, redHsl.H); From 75441d6889dddbe3fcd69e5480b6e01880759d8c Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Mon, 11 Oct 2021 17:15:25 +0200 Subject: [PATCH 7/8] Replaced reinterpret_cast hack with til::bit_cast --- src/buffer/out/TextColor.cpp | 6 ++++-- src/inc/consoletaeftemplates.hpp | 4 +++- src/inc/til/bit.h | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/inc/til/bit.h 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/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index 2f38062e752..f701eca3598 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; \ @@ -59,7 +61,7 @@ namespace WEX::TestExecution return true; } - const auto nDiff = static_cast>(*reinterpret_cast(&a) - *reinterpret_cast(&b)); + 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; } 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); + } +} From 397178257c1dcb8564bb5b40c7b01102514b03e9 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Mon, 11 Oct 2021 22:03:36 +0200 Subject: [PATCH 8/8] Fix build error again --- src/inc/consoletaeftemplates.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/consoletaeftemplates.hpp b/src/inc/consoletaeftemplates.hpp index f701eca3598..a3b9b39aebc 100644 --- a/src/inc/consoletaeftemplates.hpp +++ b/src/inc/consoletaeftemplates.hpp @@ -61,7 +61,7 @@ namespace WEX::TestExecution return true; } - const auto nDiff = static_cast>(til::bit_cast(&a) - til::bit_cast(&b)); + 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; }