From 2aff537cedda972b13daa20f581ae3b349442bcc Mon Sep 17 00:00:00 2001 From: Anthony Nicholls Date: Fri, 18 Aug 2023 12:37:55 +0100 Subject: [PATCH] approximatelyEqual: Fix unreachable code warning in MSVC --- modules/juce_core/maths/juce_MathsFunctions.h | 17 +++--- .../maths/juce_MathsFunctions_test.cpp | 60 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/modules/juce_core/maths/juce_MathsFunctions.h b/modules/juce_core/maths/juce_MathsFunctions.h index 186693af01..cf2d0676e3 100644 --- a/modules/juce_core/maths/juce_MathsFunctions.h +++ b/modules/juce_core/maths/juce_MathsFunctions.h @@ -268,10 +268,7 @@ static Tolerance relativeTolerance (Type tolerance) } -/** Returns true if the two numbers are approximately equal. This is useful for floating-point - comparisons. - - If a and b are not floating-point types, returns a == b. +/** Returns true if the two floating-point numbers are approximately equal. If either a or b are not finite, returns exactlyEqual (a, b). @@ -294,15 +291,12 @@ static Tolerance relativeTolerance (Type tolerance) @see exactlyEqual */ -template +template , int> = 0> constexpr bool approximatelyEqual (Type a, Type b, Tolerance tolerance = Tolerance{} .withAbsolute (std::numeric_limits::min()) .withRelative (std::numeric_limits::epsilon())) { - if constexpr (! std::is_floating_point_v) - return a == b; - if (! (juce_isfinite (a) && juce_isfinite (b))) return exactlyEqual (a, b); @@ -312,6 +306,13 @@ constexpr bool approximatelyEqual (Type a, Type b, || diff <= tolerance.getRelative() * std::max (std::abs (a), std::abs (b)); } +/** Special case for non-floating-point types that returns true if both are exactly equal. */ +template , int> = 0> +constexpr bool approximatelyEqual (Type a, Type b) +{ + return a == b; +} + //============================================================================== /** Returns the next representable value by FloatType in the direction of the largest representable value. */ template diff --git a/modules/juce_core/maths/juce_MathsFunctions_test.cpp b/modules/juce_core/maths/juce_MathsFunctions_test.cpp index 1dbed3d63d..2dcf427b9c 100644 --- a/modules/juce_core/maths/juce_MathsFunctions_test.cpp +++ b/modules/juce_core/maths/juce_MathsFunctions_test.cpp @@ -29,6 +29,9 @@ String getTemplatedMathsFunctionUnitTestName (const String& functionName) { const auto getTypeName = []() -> String { + if constexpr (std::is_same_v) + return "int"; + if constexpr (std::is_same_v) return "float"; @@ -358,6 +361,56 @@ public: } }; +template<> +class ApproximatelyEqualTests final : public UnitTest +{ +public: + ApproximatelyEqualTests() + : UnitTest { getTemplatedMathsFunctionUnitTestName ("approximatelyEqual"), UnitTestCategories::maths } + {} + + void runTest() final + { + beginTest ("Identical integers are always equal"); + { + expect (approximatelyEqual ( 0, 0)); + expect (approximatelyEqual (-0, -0)); + + expect (approximatelyEqual ( 1, 1)); + expect (approximatelyEqual (-1, -1)); + + using limits = std::numeric_limits; + constexpr auto min = limits::min(); + constexpr auto max = limits::max(); + + expect (approximatelyEqual (min, min)); + expect (approximatelyEqual (max, max)); + } + + beginTest ("Non-identical integers are never equal"); + { + expect (! approximatelyEqual ( 0, 1)); + expect (! approximatelyEqual ( 0, -1)); + + expect (! approximatelyEqual ( 1, 2)); + expect (! approximatelyEqual (-1, -2)); + + using limits = std::numeric_limits; + constexpr auto min = limits::min(); + constexpr auto max = limits::max(); + + expect (! approximatelyEqual (min, min + 1)); + expect (! approximatelyEqual (max, max - 1)); + } + + beginTest ("Zero is equal regardless of the sign"); + { + expect (approximatelyEqual ( 0, -0)); + expect (approximatelyEqual (-0, 0)); + } + } +}; + template class IsFiniteTests final : public UnitTest { @@ -471,8 +524,15 @@ struct MathsFloatingPointFunctionsTests ApproximatelyEqualTests approximatelyEqualTests; }; +template<> +struct MathsFloatingPointFunctionsTests +{ + ApproximatelyEqualTests approximatelyEqualTests; +}; + struct MathsFunctionsTests { + MathsFloatingPointFunctionsTests intFunctionTests; MathsFloatingPointFunctionsTests floatFunctionTests; MathsFloatingPointFunctionsTests doubleFunctionTests; MathsFloatingPointFunctionsTests longDoubleFunctionTests;