133 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  *  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
 |