| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #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; |
| | |
| | |
| | void setMargin(double margin); |
| | |
| | |
| | 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 ) const { |
| | 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; |
| | }; |
| | } |
| |
|
| | namespace literals { |
| | Detail::Approx operator "" _a(long double val); |
| | Detail::Approx operator "" _a(unsigned long long val); |
| | } |
| |
|
| | template<> |
| | struct StringMaker<Catch::Detail::Approx> { |
| | static std::string convert(Catch::Detail::Approx const& value); |
| | }; |
| |
|
| | } |
| |
|
| | #endif |
| |
|