|  | /* | 
|  | *  Created by Phil on 28/04/2011. | 
|  | *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved. | 
|  | * | 
|  | *  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_APPROX_HPP_INCLUDED | 
|  | #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED | 
|  |  | 
|  | #include "catch_tostring.h" | 
|  |  | 
|  | #include <type_traits> | 
|  |  | 
|  | namespace Catch { | 
|  | namespace Detail { | 
|  |  | 
|  | class Approx { | 
|  | private: | 
|  | bool equalityComparisonImpl(double other) const; | 
|  | // Validates the new margin (margin >= 0) | 
|  | // out-of-line to avoid including stdexcept in the header | 
|  | void setMargin(double margin); | 
|  | // Validates the new epsilon (0 < epsilon < 1) | 
|  | // out-of-line to avoid including stdexcept in the header | 
|  | void setEpsilon(double epsilon); | 
|  |  | 
|  | public: | 
|  | explicit Approx ( double value ); | 
|  |  | 
|  | static Approx custom(); | 
|  |  | 
|  | Approx operator-() const; | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | Approx operator()( T const& value ) { | 
|  | Approx approx( static_cast<double>(value) ); | 
|  | approx.m_epsilon = m_epsilon; | 
|  | approx.m_margin = m_margin; | 
|  | approx.m_scale = m_scale; | 
|  | return approx; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | explicit Approx( T const& value ): Approx(static_cast<double>(value)) | 
|  | {} | 
|  |  | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator == ( const T& lhs, Approx const& rhs ) { | 
|  | auto lhs_v = static_cast<double>(lhs); | 
|  | return rhs.equalityComparisonImpl(lhs_v); | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator == ( Approx const& lhs, const T& rhs ) { | 
|  | return operator==( rhs, lhs ); | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator != ( T const& lhs, Approx const& rhs ) { | 
|  | return !operator==( lhs, rhs ); | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator != ( Approx const& lhs, T const& rhs ) { | 
|  | return !operator==( rhs, lhs ); | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator <= ( T const& lhs, Approx const& rhs ) { | 
|  | return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator <= ( Approx const& lhs, T const& rhs ) { | 
|  | return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator >= ( T const& lhs, Approx const& rhs ) { | 
|  | return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | friend bool operator >= ( Approx const& lhs, T const& rhs ) { | 
|  | return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | Approx& epsilon( T const& newEpsilon ) { | 
|  | double epsilonAsDouble = static_cast<double>(newEpsilon); | 
|  | setEpsilon(epsilonAsDouble); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | Approx& margin( T const& newMargin ) { | 
|  | double marginAsDouble = static_cast<double>(newMargin); | 
|  | setMargin(marginAsDouble); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | 
|  | Approx& scale( T const& newScale ) { | 
|  | m_scale = static_cast<double>(newScale); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | std::string toString() const; | 
|  |  | 
|  | private: | 
|  | double m_epsilon; | 
|  | double m_margin; | 
|  | double m_scale; | 
|  | double m_value; | 
|  | }; | 
|  | } // end namespace Detail | 
|  |  | 
|  | namespace literals { | 
|  | Detail::Approx operator "" _a(long double val); | 
|  | Detail::Approx operator "" _a(unsigned long long val); | 
|  | } // end namespace literals | 
|  |  | 
|  | template<> | 
|  | struct StringMaker<Catch::Detail::Approx> { | 
|  | static std::string convert(Catch::Detail::Approx const& value); | 
|  | }; | 
|  |  | 
|  | } // end namespace Catch | 
|  |  | 
|  | #endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED |