mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-29 16:53:30 +01:00
Approx rework: default scale == 0, epsilon applies to Approx::value
Also adds check to Approx::epsilon that the new epsilon has a valid (ie one between 0 and 1) Based on http://realtimecollisiondetection.net/blog/?p=89 https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html https://en.wikipedia.org/wiki/Approximation_error#Formal_Definition The given epsilon should refer to the target value, otherwise the result would be unexpected, e.g. 101.02 == Approx(100).epsilon(0.01) is true. The default scale should be invisible, thus, e.g. 101.01 == Approx(100).epsilon(0.01) gets false. Finally even 101.000001 == Approx(100).epsilon(0.01) is false
This commit is contained in:
parent
ae21020640
commit
00af677577
@ -23,7 +23,7 @@ namespace Detail {
|
|||||||
Approx::Approx ( double value )
|
Approx::Approx ( double value )
|
||||||
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
|
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
|
||||||
m_margin( 0.0 ),
|
m_margin( 0.0 ),
|
||||||
m_scale( 1.0 ),
|
m_scale( 0.0 ),
|
||||||
m_value( value )
|
m_value( value )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -44,8 +44,9 @@ namespace Detail {
|
|||||||
friend bool operator == ( const T& lhs, Approx const& rhs ) {
|
friend bool operator == ( const T& lhs, Approx const& rhs ) {
|
||||||
// Thanks to Richard Harris for his help refining this formula
|
// Thanks to Richard Harris for his help refining this formula
|
||||||
auto lhs_v = static_cast<double>(lhs);
|
auto lhs_v = static_cast<double>(lhs);
|
||||||
bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale +
|
|
||||||
dmax(std::fabs(lhs_v), std::fabs(rhs.m_value)));
|
bool relativeOK = std::fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + std::fabs(rhs.m_value) );
|
||||||
|
|
||||||
if (relativeOK) {
|
if (relativeOK) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -89,7 +90,11 @@ namespace Detail {
|
|||||||
|
|
||||||
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
|
||||||
Approx& epsilon( T const& newEpsilon ) {
|
Approx& epsilon( T const& newEpsilon ) {
|
||||||
m_epsilon = static_cast<double>(newEpsilon);
|
double asDouble = static_cast<double>(newEpsilon);
|
||||||
|
CATCH_ENFORCE(asDouble >= 0 && asDouble <= 1.0,
|
||||||
|
"Invalid Approx::epsilon: " << m_epsilon <<
|
||||||
|
", Approx::epsilon has to be between 0 and 1");
|
||||||
|
m_epsilon = asDouble;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user