mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-17 11:12:25 +01:00
parent
37e1e24309
commit
5a9072d01e
@ -13,6 +13,10 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#if defined(CATCH_CPP11_OR_GREATER)
|
||||||
|
#include <type_traits>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Detail {
|
namespace Detail {
|
||||||
|
|
||||||
@ -41,6 +45,53 @@ namespace Detail {
|
|||||||
return approx;
|
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 ) {
|
friend bool operator == ( double lhs, Approx const& rhs ) {
|
||||||
// Thanks to Richard Harris for his help refining this formula
|
// 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) ) );
|
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;
|
return lhs.m_value > rhs || lhs == rhs;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Approx& epsilon( double newEpsilon ) {
|
Approx& epsilon( double newEpsilon ) {
|
||||||
m_epsilon = 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.001 ) );
|
||||||
REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) );
|
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
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user