1 /* 2 * Created by Martin on 07/11/2017. 3 * 4 * Distributed under the Boost Software License, Version 1.0. (See accompanying 5 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 #ifndef TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED 8 #define TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED 9 10 #include "catch_matchers.h" 11 12 namespace Catch { 13 namespace Matchers { 14 15 namespace Floating { 16 17 enum class FloatingPointKind : uint8_t; 18 19 struct WithinAbsMatcher : MatcherBase<double> { 20 WithinAbsMatcher(double target, double margin); 21 bool match(double const& matchee) const override; 22 std::string describe() const override; 23 private: 24 double m_target; 25 double m_margin; 26 }; 27 28 struct WithinUlpsMatcher : MatcherBase<double> { 29 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType); 30 bool match(double const& matchee) const override; 31 std::string describe() const override; 32 private: 33 double m_target; 34 uint64_t m_ulps; 35 FloatingPointKind m_type; 36 }; 37 38 // Given IEEE-754 format for floats and doubles, we can assume 39 // that float -> double promotion is lossless. Given this, we can 40 // assume that if we do the standard relative comparison of 41 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get 42 // the same result if we do this for floats, as if we do this for 43 // doubles that were promoted from floats. 44 struct WithinRelMatcher : MatcherBase<double> { 45 WithinRelMatcher(double target, double epsilon); 46 bool match(double const& matchee) const override; 47 std::string describe() const override; 48 private: 49 double m_target; 50 double m_epsilon; 51 }; 52 53 } // namespace Floating 54 55 // The following functions create the actual matcher objects. 56 // This allows the types to be inferred 57 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); 58 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); 59 Floating::WithinAbsMatcher WithinAbs(double target, double margin); 60 Floating::WithinRelMatcher WithinRel(double target, double eps); 61 // defaults epsilon to 100*numeric_limits<double>::epsilon() 62 Floating::WithinRelMatcher WithinRel(double target); 63 Floating::WithinRelMatcher WithinRel(float target, float eps); 64 // defaults epsilon to 100*numeric_limits<float>::epsilon() 65 Floating::WithinRelMatcher WithinRel(float target); 66 67 } // namespace Matchers 68 } // namespace Catch 69 70 #endif // TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED 71