float: use ULP based comparison
This commit is contained in:
parent
f64e232201
commit
ca6fa4ad3e
56
float.cpp
56
float.cpp
@ -76,22 +76,58 @@ ieee_float<E, S>::operator==(floating_t _floating) const {
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
//template <unsigned int E, unsigned int S>
|
||||||
|
//bool
|
||||||
|
//ieee_float<E, S>::almost_equal (floating_t a,
|
||||||
|
// floating_t b) {
|
||||||
|
// // Static cast to avoid integer casting warnings when using uint16_t for half
|
||||||
|
// static const floating_t epsilon = static_cast<floating_t> (0.001);
|
||||||
|
// const floating_t diff = static_cast<floating_t> (std::fabs (a - b));
|
||||||
|
//
|
||||||
|
// // * Use an exact equality first so that infinities are not indirectly compared. This would generate NaNs in the diff.
|
||||||
|
// // * Do not use gte or lte. This stops an infinite from making infinities on both sides of the inequality.
|
||||||
|
// return exactly_equal (a, b) ||
|
||||||
|
// diff < epsilon * std::fabs (a) ||
|
||||||
|
// diff < epsilon * std::fabs (b);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
template <unsigned int E, unsigned int S>
|
template <unsigned int E, unsigned int S>
|
||||||
bool
|
bool
|
||||||
ieee_float<E, S>::almost_equal (floating_t a,
|
ieee_float<E, S>::almost_equal (floating_t a,
|
||||||
floating_t b) {
|
floating_t b)
|
||||||
// Static cast to avoid integer casting warnings when using uint16_t for half
|
{
|
||||||
static const floating_t epsilon = static_cast<floating_t> (0.001);
|
return almost_equal (a, b, 10000);
|
||||||
const floating_t diff = static_cast<floating_t> (std::fabs (a - b));
|
|
||||||
|
|
||||||
// * Use an exact equality first so that infinities are not indirectly compared. This would generate NaNs in the diff.
|
|
||||||
// * Do not use gte or lte. This stops an infinite from making infinities on both sides of the inequality.
|
|
||||||
return exactly_equal (a, b) ||
|
|
||||||
diff < epsilon * std::fabs (a) ||
|
|
||||||
diff < epsilon * std::fabs (b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <unsigned int E, unsigned int S>
|
||||||
|
bool
|
||||||
|
ieee_float<E, S>::almost_equal (floating_t _a,
|
||||||
|
floating_t _b,
|
||||||
|
uint_t ulps)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
floating_t f;
|
||||||
|
sint_t s;
|
||||||
|
} a, b;
|
||||||
|
|
||||||
|
a.f = _a;
|
||||||
|
b.f = _b;
|
||||||
|
|
||||||
|
if (std::isnan (a.f) || std::isnan (b.f))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (a.s == b.s)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
uint_t diff = std::abs (a.s - b.s);
|
||||||
|
std::cerr << "diff: " << diff << '\n';
|
||||||
|
return diff <= ulps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template class ieee_float< 5, 10>; // ieee_half
|
template class ieee_float< 5, 10>; // ieee_half
|
||||||
template class ieee_float< 8, 23>; // ieee_single;
|
template class ieee_float< 8, 23>; // ieee_single;
|
||||||
template class ieee_float<11, 52>; // ieee_double;
|
template class ieee_float<11, 52>; // ieee_double;
|
||||||
|
@ -14,6 +14,7 @@ class ieee_float {
|
|||||||
|
|
||||||
static const unsigned int BIAS = (1 << (EXPONENT - 1)) - 1;
|
static const unsigned int BIAS = (1 << (EXPONENT - 1)) - 1;
|
||||||
|
|
||||||
|
typedef typename bits_type<TOTAL_BITS>::sint sint_t;
|
||||||
typedef typename bits_type<TOTAL_BITS>::uint uint_t;
|
typedef typename bits_type<TOTAL_BITS>::uint uint_t;
|
||||||
typedef typename bits_type<TOTAL_BITS>::floating floating_t;
|
typedef typename bits_type<TOTAL_BITS>::floating floating_t;
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ class ieee_float {
|
|||||||
bool operator== (floating_t) const;
|
bool operator== (floating_t) const;
|
||||||
|
|
||||||
static bool almost_equal (floating_t, floating_t);
|
static bool almost_equal (floating_t, floating_t);
|
||||||
|
static bool almost_equal (floating_t, floating_t, uint_t ulps);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user