mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 03:43:28 +01:00
Cleanup for floating point matchers
Removed the `Floating` nested namespace and added Doxygen comments for the factory methods.
This commit is contained in:
parent
a6baa6dda6
commit
afc8b28c07
@ -99,13 +99,15 @@ void write(std::ostream& out, FloatingPoint num) {
|
|||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
namespace Floating {
|
namespace Detail {
|
||||||
|
|
||||||
enum class FloatingPointKind : uint8_t {
|
enum class FloatingPointKind : uint8_t {
|
||||||
Float,
|
Float,
|
||||||
Double
|
Double
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace Detail
|
||||||
|
|
||||||
|
|
||||||
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
|
||||||
:m_target{ target }, m_margin{ margin } {
|
:m_target{ target }, m_margin{ margin } {
|
||||||
@ -124,9 +126,9 @@ namespace Floating {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
|
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType)
|
||||||
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
|
||||||
CATCH_ENFORCE(m_type == FloatingPointKind::Double
|
CATCH_ENFORCE(m_type == Detail::FloatingPointKind::Double
|
||||||
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
|| m_ulps < (std::numeric_limits<uint32_t>::max)(),
|
||||||
"Provided ULP is impossibly large for a float comparison.");
|
"Provided ULP is impossibly large for a float comparison.");
|
||||||
}
|
}
|
||||||
@ -139,12 +141,12 @@ namespace Floating {
|
|||||||
|
|
||||||
bool WithinUlpsMatcher::match(double const& matchee) const {
|
bool WithinUlpsMatcher::match(double const& matchee) const {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case FloatingPointKind::Float:
|
case Detail::FloatingPointKind::Float:
|
||||||
return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
|
return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
|
||||||
case FloatingPointKind::Double:
|
case Detail::FloatingPointKind::Double:
|
||||||
return almostEqualUlps<double>(matchee, m_target, m_ulps);
|
return almostEqualUlps<double>(matchee, m_target, m_ulps);
|
||||||
default:
|
default:
|
||||||
CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
|
CATCH_INTERNAL_ERROR( "Unknown Detail::FloatingPointKind value" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +159,7 @@ namespace Floating {
|
|||||||
|
|
||||||
ret << "is within " << m_ulps << " ULPs of ";
|
ret << "is within " << m_ulps << " ULPs of ";
|
||||||
|
|
||||||
if (m_type == FloatingPointKind::Float) {
|
if (m_type == Detail::FloatingPointKind::Float) {
|
||||||
write(ret, static_cast<float>(m_target));
|
write(ret, static_cast<float>(m_target));
|
||||||
ret << 'f';
|
ret << 'f';
|
||||||
} else {
|
} else {
|
||||||
@ -165,7 +167,7 @@ namespace Floating {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret << " ([";
|
ret << " ([";
|
||||||
if (m_type == FloatingPointKind::Double) {
|
if (m_type == Detail::FloatingPointKind::Double) {
|
||||||
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
|
write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
|
||||||
ret << ", ";
|
ret << ", ";
|
||||||
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
|
write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
|
||||||
@ -199,39 +201,35 @@ namespace Floating {
|
|||||||
return sstr.str();
|
return sstr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
}// namespace Floating
|
|
||||||
|
|
||||||
|
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
|
||||||
|
return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Double);
|
||||||
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
|
|
||||||
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
|
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
|
||||||
return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
|
return WithinUlpsMatcher(target, maxUlpDiff, Detail::FloatingPointKind::Float);
|
||||||
}
|
}
|
||||||
|
|
||||||
Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
|
WithinAbsMatcher WithinAbs(double target, double margin) {
|
||||||
return Floating::WithinAbsMatcher(target, margin);
|
return WithinAbsMatcher(target, margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
Floating::WithinRelMatcher WithinRel(double target, double eps) {
|
WithinRelMatcher WithinRel(double target, double eps) {
|
||||||
return Floating::WithinRelMatcher(target, eps);
|
return WithinRelMatcher(target, eps);
|
||||||
}
|
}
|
||||||
|
|
||||||
Floating::WithinRelMatcher WithinRel(double target) {
|
WithinRelMatcher WithinRel(double target) {
|
||||||
return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
|
return WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
Floating::WithinRelMatcher WithinRel(float target, float eps) {
|
WithinRelMatcher WithinRel(float target, float eps) {
|
||||||
return Floating::WithinRelMatcher(target, eps);
|
return WithinRelMatcher(target, eps);
|
||||||
}
|
}
|
||||||
|
|
||||||
Floating::WithinRelMatcher WithinRel(float target) {
|
WithinRelMatcher WithinRel(float target) {
|
||||||
return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
|
return WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace Matchers
|
} // namespace Matchers
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@ -12,57 +12,59 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
namespace Matchers {
|
namespace Matchers {
|
||||||
|
|
||||||
namespace Floating {
|
namespace Detail {
|
||||||
|
|
||||||
enum class FloatingPointKind : uint8_t;
|
enum class FloatingPointKind : uint8_t;
|
||||||
|
}
|
||||||
|
|
||||||
struct WithinAbsMatcher final : MatcherBase<double> {
|
struct WithinAbsMatcher final : MatcherBase<double> {
|
||||||
WithinAbsMatcher(double target, double margin);
|
WithinAbsMatcher(double target, double margin);
|
||||||
bool match(double const& matchee) const override;
|
bool match(double const& matchee) const override;
|
||||||
std::string describe() const override;
|
std::string describe() const override;
|
||||||
private:
|
private:
|
||||||
double m_target;
|
double m_target;
|
||||||
double m_margin;
|
double m_margin;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WithinUlpsMatcher final : MatcherBase<double> {
|
struct WithinUlpsMatcher final : MatcherBase<double> {
|
||||||
WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
|
WithinUlpsMatcher(double target, uint64_t ulps, Detail::FloatingPointKind baseType);
|
||||||
bool match(double const& matchee) const override;
|
bool match(double const& matchee) const override;
|
||||||
std::string describe() const override;
|
std::string describe() const override;
|
||||||
private:
|
private:
|
||||||
double m_target;
|
double m_target;
|
||||||
uint64_t m_ulps;
|
uint64_t m_ulps;
|
||||||
FloatingPointKind m_type;
|
Detail::FloatingPointKind m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Given IEEE-754 format for floats and doubles, we can assume
|
// Given IEEE-754 format for floats and doubles, we can assume
|
||||||
// that float -> double promotion is lossless. Given this, we can
|
// that float -> double promotion is lossless. Given this, we can
|
||||||
// assume that if we do the standard relative comparison of
|
// assume that if we do the standard relative comparison of
|
||||||
// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
|
// |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
|
||||||
// the same result if we do this for floats, as if we do this for
|
// the same result if we do this for floats, as if we do this for
|
||||||
// doubles that were promoted from floats.
|
// doubles that were promoted from floats.
|
||||||
struct WithinRelMatcher final : MatcherBase<double> {
|
struct WithinRelMatcher final : MatcherBase<double> {
|
||||||
WithinRelMatcher(double target, double epsilon);
|
WithinRelMatcher(double target, double epsilon);
|
||||||
bool match(double const& matchee) const override;
|
bool match(double const& matchee) const override;
|
||||||
std::string describe() const override;
|
std::string describe() const override;
|
||||||
private:
|
private:
|
||||||
double m_target;
|
double m_target;
|
||||||
double m_epsilon;
|
double m_epsilon;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Floating
|
//! Creates a matcher that accepts doubles within certain ULP range of target
|
||||||
|
WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
||||||
|
//! Creates a matcher that accepts floats within certain ULP range of target
|
||||||
|
WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
||||||
|
//! Creates a matcher that accepts numbers within certain range of target
|
||||||
|
WithinAbsMatcher WithinAbs(double target, double margin);
|
||||||
|
|
||||||
// The following functions create the actual matcher objects.
|
//! Creates a matcher that accepts doubles within certain relative range of target
|
||||||
// This allows the types to be inferred
|
WithinRelMatcher WithinRel(double target, double eps);
|
||||||
Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
|
//! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
|
||||||
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
|
WithinRelMatcher WithinRel(double target);
|
||||||
Floating::WithinAbsMatcher WithinAbs(double target, double margin);
|
//! Creates a matcher that accepts doubles within certain relative range of target
|
||||||
Floating::WithinRelMatcher WithinRel(double target, double eps);
|
WithinRelMatcher WithinRel(float target, float eps);
|
||||||
// defaults epsilon to 100*numeric_limits<double>::epsilon()
|
//! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
|
||||||
Floating::WithinRelMatcher WithinRel(double target);
|
WithinRelMatcher WithinRel(float target);
|
||||||
Floating::WithinRelMatcher WithinRel(float target, float eps);
|
|
||||||
// defaults epsilon to 100*numeric_limits<float>::epsilon()
|
|
||||||
Floating::WithinRelMatcher WithinRel(float target);
|
|
||||||
|
|
||||||
} // namespace Matchers
|
} // namespace Matchers
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
Loading…
Reference in New Issue
Block a user