File indexing completed on 2025-01-18 09:54:08
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef CATCH_APPROX_HPP_INCLUDED
0009 #define CATCH_APPROX_HPP_INCLUDED
0010
0011 #include <catch2/catch_tostring.hpp>
0012
0013 #include <type_traits>
0014
0015 namespace Catch {
0016
0017 class Approx {
0018 private:
0019 bool equalityComparisonImpl(double other) const;
0020
0021 void setMargin(double margin);
0022
0023 void setEpsilon(double epsilon);
0024
0025 public:
0026 explicit Approx ( double value );
0027
0028 static Approx custom();
0029
0030 Approx operator-() const;
0031
0032 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0033 Approx operator()( T const& value ) const {
0034 Approx approx( static_cast<double>(value) );
0035 approx.m_epsilon = m_epsilon;
0036 approx.m_margin = m_margin;
0037 approx.m_scale = m_scale;
0038 return approx;
0039 }
0040
0041 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0042 explicit Approx( T const& value ): Approx(static_cast<double>(value))
0043 {}
0044
0045
0046 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0047 friend bool operator == ( const T& lhs, Approx const& rhs ) {
0048 auto lhs_v = static_cast<double>(lhs);
0049 return rhs.equalityComparisonImpl(lhs_v);
0050 }
0051
0052 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0053 friend bool operator == ( Approx const& lhs, const T& rhs ) {
0054 return operator==( rhs, lhs );
0055 }
0056
0057 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0058 friend bool operator != ( T const& lhs, Approx const& rhs ) {
0059 return !operator==( lhs, rhs );
0060 }
0061
0062 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0063 friend bool operator != ( Approx const& lhs, T const& rhs ) {
0064 return !operator==( rhs, lhs );
0065 }
0066
0067 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0068 friend bool operator <= ( T const& lhs, Approx const& rhs ) {
0069 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
0070 }
0071
0072 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0073 friend bool operator <= ( Approx const& lhs, T const& rhs ) {
0074 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
0075 }
0076
0077 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0078 friend bool operator >= ( T const& lhs, Approx const& rhs ) {
0079 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
0080 }
0081
0082 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0083 friend bool operator >= ( Approx const& lhs, T const& rhs ) {
0084 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
0085 }
0086
0087 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0088 Approx& epsilon( T const& newEpsilon ) {
0089 const auto epsilonAsDouble = static_cast<double>(newEpsilon);
0090 setEpsilon(epsilonAsDouble);
0091 return *this;
0092 }
0093
0094 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0095 Approx& margin( T const& newMargin ) {
0096 const auto marginAsDouble = static_cast<double>(newMargin);
0097 setMargin(marginAsDouble);
0098 return *this;
0099 }
0100
0101 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
0102 Approx& scale( T const& newScale ) {
0103 m_scale = static_cast<double>(newScale);
0104 return *this;
0105 }
0106
0107 std::string toString() const;
0108
0109 private:
0110 double m_epsilon;
0111 double m_margin;
0112 double m_scale;
0113 double m_value;
0114 };
0115
0116 namespace literals {
0117 Approx operator ""_a(long double val);
0118 Approx operator ""_a(unsigned long long val);
0119 }
0120
0121 template<>
0122 struct StringMaker<Catch::Approx> {
0123 static std::string convert(Catch::Approx const& value);
0124 };
0125
0126 }
0127
0128 #endif