diff --git a/src/catch2/matchers/catch_matchers_floating.cpp b/src/catch2/matchers/catch_matchers_floating.cpp index 071c10a3..ca20110d 100644 --- a/src/catch2/matchers/catch_matchers_floating.cpp +++ b/src/catch2/matchers/catch_matchers_floating.cpp @@ -99,13 +99,15 @@ void write(std::ostream& out, FloatingPoint num) { } // end anonymous namespace namespace Matchers { -namespace Floating { +namespace Detail { enum class FloatingPointKind : uint8_t { Float, Double }; +} // end namespace Detail + WithinAbsMatcher::WithinAbsMatcher(double target, double margin) :m_target{ target }, m_margin{ margin } { @@ -124,9 +126,9 @@ namespace Floating { } - WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType) + WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType) :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { - CATCH_ENFORCE(m_type == FloatingPointKind::Double + CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double || m_ulps < (std::numeric_limits::max)(), "Provided ULP is impossibly large for a float comparison."); } @@ -139,12 +141,12 @@ namespace Floating { bool WithinUlpsMatcher::match(double const& matchee) const { switch (m_type) { - case FloatingPointKind::Float: + case Detail::FloatingPointKind::Float: return almostEqualUlps(static_cast(matchee), static_cast(m_target), m_ulps); - case FloatingPointKind::Double: + case Detail::FloatingPointKind::Double: return almostEqualUlps(matchee, m_target, m_ulps); default: - CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" ); + CATCH_INTERNAL_ERROR( "Unknown Detail::FloatingPointKind value" ); } } @@ -157,7 +159,7 @@ namespace Floating { ret << "is within " << m_ulps << " ULPs of "; - if (m_type == FloatingPointKind::Float) { + if (m_type == Detail::FloatingPointKind::Float) { write(ret, static_cast(m_target)); ret << 'f'; } else { @@ -165,7 +167,7 @@ namespace Floating { } ret << " (["; - if (m_type == FloatingPointKind::Double) { + if (m_type == Detail::FloatingPointKind::Double) { write(ret, step(m_target, static_cast(-INFINITY), m_ulps)); ret << ", "; write(ret, step(m_target, static_cast( INFINITY), m_ulps)); @@ -199,39 +201,35 @@ namespace Floating { return sstr.str(); } -}// namespace Floating - - -Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) { - return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); +WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) { + return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Double); } -Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) { - return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); +WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) { + return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Float); } -Floating::WithinAbsMatcher WithinAbs(double target, double margin) { - return Floating::WithinAbsMatcher(target, margin); +WithinAbsMatcher WithinAbs(double target, double margin) { + return WithinAbsMatcher(target, margin); } -Floating::WithinRelMatcher WithinRel(double target, double eps) { - return Floating::WithinRelMatcher(target, eps); +WithinRelMatcher WithinRel(double target, double eps) { + return WithinRelMatcher(target, eps); } -Floating::WithinRelMatcher WithinRel(double target) { - return Floating::WithinRelMatcher(target, std::numeric_limits::epsilon() * 100); +WithinRelMatcher WithinRel(double target) { + return WithinRelMatcher(target, std::numeric_limits::epsilon() * 100); } -Floating::WithinRelMatcher WithinRel(float target, float eps) { - return Floating::WithinRelMatcher(target, eps); +WithinRelMatcher WithinRel(float target, float eps) { + return WithinRelMatcher(target, eps); } -Floating::WithinRelMatcher WithinRel(float target) { - return Floating::WithinRelMatcher(target, std::numeric_limits::epsilon() * 100); +WithinRelMatcher WithinRel(float target) { + return WithinRelMatcher(target, std::numeric_limits::epsilon() * 100); } } // namespace Matchers } // namespace Catch - diff --git a/src/catch2/matchers/catch_matchers_floating.hpp b/src/catch2/matchers/catch_matchers_floating.hpp index bead3a04..221fa42d 100644 --- a/src/catch2/matchers/catch_matchers_floating.hpp +++ b/src/catch2/matchers/catch_matchers_floating.hpp @@ -12,57 +12,59 @@ namespace Catch { namespace Matchers { - namespace Floating { - + namespace Detail { enum class FloatingPointKind : uint8_t; + } - struct WithinAbsMatcher final : MatcherBase { - WithinAbsMatcher(double target, double margin); - bool match(double const& matchee) const override; - std::string describe() const override; - private: - double m_target; - double m_margin; - }; + struct WithinAbsMatcher final : MatcherBase { + WithinAbsMatcher(double target, double margin); + bool match(double const& matchee) const override; + std::string describe() const override; + private: + double m_target; + double m_margin; + }; - struct WithinUlpsMatcher final : MatcherBase { - WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); - bool match(double const& matchee) const override; - std::string describe() const override; - private: - double m_target; - uint64_t m_ulps; - FloatingPointKind m_type; - }; + struct WithinUlpsMatcher final : MatcherBase { + WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType); + bool match(double const& matchee) const override; + std::string describe() const override; + private: + double m_target; + uint64_t m_ulps; + Detail::FloatingPointKind m_type; + }; - // Given IEEE-754 format for floats and doubles, we can assume - // that float -> double promotion is lossless. Given this, we can - // assume that if we do the standard relative comparison of - // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get - // the same result if we do this for floats, as if we do this for - // doubles that were promoted from floats. - struct WithinRelMatcher final : MatcherBase { - WithinRelMatcher(double target, double epsilon); - bool match(double const& matchee) const override; - std::string describe() const override; - private: - double m_target; - double m_epsilon; - }; + // Given IEEE-754 format for floats and doubles, we can assume + // that float -> double promotion is lossless. Given this, we can + // assume that if we do the standard relative comparison of + // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get + // the same result if we do this for floats, as if we do this for + // doubles that were promoted from floats. + struct WithinRelMatcher final : MatcherBase { + WithinRelMatcher(double target, double epsilon); + bool match(double const& matchee) const override; + std::string describe() const override; + private: + double m_target; + double m_epsilon; + }; - } // namespace Floating + //! Creates a matcher that accepts doubles within certain ULP range of target + WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); + //! Creates a matcher that accepts floats within certain ULP range of target + WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); + //! Creates a matcher that accepts numbers within certain range of target + WithinAbsMatcher WithinAbs(double target, double margin); - // The following functions create the actual matcher objects. - // This allows the types to be inferred - Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); - Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); - Floating::WithinAbsMatcher WithinAbs(double target, double margin); - Floating::WithinRelMatcher WithinRel(double target, double eps); - // defaults epsilon to 100*numeric_limits::epsilon() - Floating::WithinRelMatcher WithinRel(double target); - Floating::WithinRelMatcher WithinRel(float target, float eps); - // defaults epsilon to 100*numeric_limits::epsilon() - Floating::WithinRelMatcher WithinRel(float target); + //! Creates a matcher that accepts doubles within certain relative range of target + WithinRelMatcher WithinRel(double target, double eps); + //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target + WithinRelMatcher WithinRel(double target); + //! Creates a matcher that accepts doubles within certain relative range of target + WithinRelMatcher WithinRel(float target, float eps); + //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target + WithinRelMatcher WithinRel(float target); } // namespace Matchers } // namespace Catch