Home | History | Annotate | Download | only in internal
      1 /*
      2  *  Created by Phil on 28/04/2011.
      3  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
      4  *
      5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
      6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      7  */
      8 #ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
      9 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
     10 
     11 #include "catch_tostring.h"
     12 
     13 #include <type_traits>
     14 
     15 namespace Catch {
     16 namespace Detail {
     17 
     18     class Approx {
     19     private:
     20         bool equalityComparisonImpl(double other) const;
     21         // Validates the new margin (margin >= 0)
     22         // out-of-line to avoid including stdexcept in the header
     23         void setMargin(double margin);
     24         // Validates the new epsilon (0 < epsilon < 1)
     25         // out-of-line to avoid including stdexcept in the header
     26         void setEpsilon(double epsilon);
     27 
     28     public:
     29         explicit Approx ( double value );
     30 
     31         static Approx custom();
     32 
     33         Approx operator-() const;
     34 
     35         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     36         Approx operator()( T const& value ) {
     37             Approx approx( static_cast<double>(value) );
     38             approx.m_epsilon = m_epsilon;
     39             approx.m_margin = m_margin;
     40             approx.m_scale = m_scale;
     41             return approx;
     42         }
     43 
     44         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     45         explicit Approx( T const& value ): Approx(static_cast<double>(value))
     46         {}
     47 
     48 
     49         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     50         friend bool operator == ( const T& lhs, Approx const& rhs ) {
     51             auto lhs_v = static_cast<double>(lhs);
     52             return rhs.equalityComparisonImpl(lhs_v);
     53         }
     54 
     55         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     56         friend bool operator == ( Approx const& lhs, const T& rhs ) {
     57             return operator==( rhs, lhs );
     58         }
     59 
     60         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     61         friend bool operator != ( T const& lhs, Approx const& rhs ) {
     62             return !operator==( lhs, rhs );
     63         }
     64 
     65         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     66         friend bool operator != ( Approx const& lhs, T const& rhs ) {
     67             return !operator==( rhs, lhs );
     68         }
     69 
     70         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     71         friend bool operator <= ( T const& lhs, Approx const& rhs ) {
     72             return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
     73         }
     74 
     75         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     76         friend bool operator <= ( Approx const& lhs, T const& rhs ) {
     77             return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
     78         }
     79 
     80         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     81         friend bool operator >= ( T const& lhs, Approx const& rhs ) {
     82             return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
     83         }
     84 
     85         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     86         friend bool operator >= ( Approx const& lhs, T const& rhs ) {
     87             return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
     88         }
     89 
     90         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     91         Approx& epsilon( T const& newEpsilon ) {
     92             double epsilonAsDouble = static_cast<double>(newEpsilon);
     93             setEpsilon(epsilonAsDouble);
     94             return *this;
     95         }
     96 
     97         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
     98         Approx& margin( T const& newMargin ) {
     99             double marginAsDouble = static_cast<double>(newMargin);
    100             setMargin(marginAsDouble);
    101             return *this;
    102         }
    103 
    104         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
    105         Approx& scale( T const& newScale ) {
    106             m_scale = static_cast<double>(newScale);
    107             return *this;
    108         }
    109 
    110         std::string toString() const;
    111 
    112     private:
    113         double m_epsilon;
    114         double m_margin;
    115         double m_scale;
    116         double m_value;
    117     };
    118 } // end namespace Detail
    119 
    120 namespace literals {
    121     Detail::Approx operator "" _a(long double val);
    122     Detail::Approx operator "" _a(unsigned long long val);
    123 } // end namespace literals
    124 
    125 template<>
    126 struct StringMaker<Catch::Detail::Approx> {
    127     static std::string convert(Catch::Detail::Approx const& value);
    128 };
    129 
    130 } // end namespace Catch
    131 
    132 #endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
    133