35struct Converter<float> {
36 static_assert(
sizeof(float) ==
sizeof(
int32_t),
"Important ULP matcher assumption violated");
38 std::memcpy(&i, &
f,
sizeof(
f));
44struct Converter<double> {
45 static_assert(
sizeof(double) ==
sizeof(
int64_t),
"Important ULP matcher assumption violated");
47 std::memcpy(&i, &d,
sizeof(d));
53auto convert(
T t) -> Converter<T> {
54 return Converter<T>(t);
58bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
65 auto lc = convert(lhs);
66 auto rc = convert(rhs);
68 if ((lc.i < 0) != (
rc.i < 0)) {
73 auto ulpDiff = std::abs(lc.i -
rc.i);
74 return ulpDiff <= maxUlpDiff;
84 :m_target{ target }, m_margin{ margin } {
85 CATCH_ENFORCE(margin >= 0,
"Invalid margin: " << margin <<
'.'
86 <<
" Margin has to be non-negative.");
92 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
101 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
102 CATCH_ENFORCE(ulps >= 0,
"Invalid ULP setting: " << ulps <<
'.'
103 <<
" ULPs have to be non-negative.");
106#if defined(__clang__)
107#pragma clang diagnostic push
109#pragma clang diagnostic ignored "-Wunreachable-code"
115 return almostEqualUlps<float>(
static_cast<float>(matchee),
static_cast<float>(m_target), m_ulps);
117 return almostEqualUlps<double>(matchee, m_target, m_ulps);
123#if defined(__clang__)
124#pragma clang diagnostic pop
#define CATCH_INTERNAL_ERROR(msg)
#define CATCH_ENFORCE(condition, msg)
std::string stringify(const T &e)
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff)
std::string to_string(T const &t)
#define T(meth, val, expected)
std::string describe() const override
WithinAbsMatcher(double target, double margin)
bool match(double const &matchee) const override
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
bool match(double const &matchee) const override
std::string describe() const override