mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	 Jonathan Coe
					Jonathan Coe
				
			
				
					committed by
					
						 Martin Hořeňovský
						Martin Hořeňovský
					
				
			
			
				
	
			
			
			 Martin Hořeňovský
						Martin Hořeňovský
					
				
			
						parent
						
							73872207db
						
					
				
				
					commit
					c06afe438e
				
			| @@ -13,6 +13,10 @@ | ||||
| #include <cmath> | ||||
| #include <limits> | ||||
|  | ||||
| #if defined(CATCH_CPP11_OR_GREATER) | ||||
| #include <type_traits> | ||||
| #endif | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Detail { | ||||
|  | ||||
| @@ -41,6 +45,53 @@ namespace Detail { | ||||
|             return approx; | ||||
|         } | ||||
|  | ||||
| #if defined(CATCH_CPP11_OR_GREATER) | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator == ( const T& lhs, Approx const& rhs ) { | ||||
|             // Thanks to Richard Harris for his help refining this formula | ||||
|             auto lhs_v = double(lhs); | ||||
|             return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) ); | ||||
|         } | ||||
|  | ||||
|         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 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 rhs ) { | ||||
|             return !operator==( rhs, lhs ); | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator <= ( T lhs, Approx const& rhs ) | ||||
|         { | ||||
|           return 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 rhs ) | ||||
|         { | ||||
|           return lhs.m_value < double(rhs) || lhs == rhs; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator >= ( T lhs, Approx const& rhs ) | ||||
|         { | ||||
|           return 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 rhs ) | ||||
|         { | ||||
|           return lhs.m_value > double(rhs) || lhs == rhs; | ||||
|         } | ||||
| #else | ||||
|         friend bool operator == ( double lhs, Approx const& rhs ) { | ||||
|             // Thanks to Richard Harris for his help refining this formula | ||||
|             return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); | ||||
| @@ -77,6 +128,7 @@ namespace Detail { | ||||
|         { | ||||
|           return lhs.m_value > rhs || lhs == rhs; | ||||
|         } | ||||
| #endif | ||||
|  | ||||
|         Approx& epsilon( double newEpsilon ) { | ||||
|             m_epsilon = newEpsilon; | ||||
|   | ||||
| @@ -140,3 +140,44 @@ TEST_CASE( "Approximate PI", "[Approx][PI]" ) | ||||
|     REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ); | ||||
|     REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #if defined(CATCH_CPP11_OR_GREATER) | ||||
| class StrongDoubleTypedef | ||||
| { | ||||
|   double d_ = 0.0; | ||||
|  | ||||
|   public: | ||||
|     explicit StrongDoubleTypedef(double d) : d_(d) {} | ||||
|     explicit operator double() const { return d_; } | ||||
| }; | ||||
|  | ||||
| TEST_CASE | ||||
| ( | ||||
|  "Comparison with explicitly convertible types", | ||||
|  "[Approx]" | ||||
| ) | ||||
| { | ||||
|   StrongDoubleTypedef td(10.0); | ||||
|  | ||||
|   REQUIRE(td == Approx(10.0)); | ||||
|   REQUIRE(Approx(10.0) == td); | ||||
|  | ||||
|   REQUIRE(td != Approx(11.0)); | ||||
|   REQUIRE(Approx(11.0) != td); | ||||
|    | ||||
|   REQUIRE(td <= Approx(10.0)); | ||||
|   REQUIRE(td <= Approx(11.0)); | ||||
|   REQUIRE(Approx(10.0) <= td); | ||||
|   REQUIRE(Approx(9.0) <= td); | ||||
|    | ||||
|   REQUIRE(td >= Approx(9.0)); | ||||
|   REQUIRE(td >= Approx(10.0)); | ||||
|   REQUIRE(Approx(10.0) >= td); | ||||
|   REQUIRE(Approx(11.0) >= td); | ||||
|    | ||||
| } | ||||
| #endif | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|   | ||||
		Reference in New Issue
	
	Block a user