text: /*
   *  Created by Martin on 07/11/2017.
   *
   * Distributed under the Boost Software License, Version 1.0. (See accompanying
   * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
   */
  #ifndef TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED
  #define TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED
  
  #include "catch_matchers.h"
  
  namespace Catch {
  namespace Matchers {
  
      namespace Floating {
  
          enum class FloatingPointKind : uint8_t;
  
          struct WithinAbsMatcher : MatcherBase<double> {
              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 : MatcherBase<double> {
              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;
          };
  
          // 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 : MatcherBase<double> {
              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
  
      // 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<double>::epsilon()
      Floating::WithinRelMatcher WithinRel(double target);
      Floating::WithinRelMatcher WithinRel(float target, float eps);
      // defaults epsilon to 100*numeric_limits<float>::epsilon()
      Floating::WithinRelMatcher WithinRel(float target);
  
  } // namespace Matchers
  } // namespace Catch
  
  #endif // TWOBLUECUBES_CATCH_MATCHERS_FLOATING_H_INCLUDED
  