maths, view: rationalise equal,almost_equal,==
views should not do elementwise comparisons for equality operators. they are pairs of iterators and are only equal if their iterators are equal. instead, use `equal` for elementwise equality. we update the name of exactly_equal to perform this operation too.
This commit is contained in:
parent
5d32408126
commit
35e3f69ad2
@ -909,7 +909,7 @@ json::tree::number::sint (void) const
|
||||
return m_value.s;
|
||||
|
||||
case REAL:
|
||||
if (!::util::exactly_equal (real_t (sint_t (m_value.r)), m_value.r))
|
||||
if (!::util::equal (real_t (sint_t (m_value.r)), m_value.r))
|
||||
throw type_error ("number is not a sint");
|
||||
return sint_t (m_value.r);
|
||||
|
||||
@ -932,7 +932,7 @@ json::tree::number::uint (void) const
|
||||
return m_value.u;
|
||||
|
||||
case REAL:
|
||||
if (!::util::exactly_equal (real_t (uint_t (m_value.r)), m_value.r))
|
||||
if (!::util::equal (real_t (uint_t (m_value.r)), m_value.r))
|
||||
throw type_error ("number is not a uint");
|
||||
return uint_t (m_value.r);
|
||||
|
||||
|
114
maths.hpp
114
maths.hpp
@ -43,67 +43,6 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace util {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Comparisons
|
||||
inline bool
|
||||
almost_equal (const float &a, const float &b)
|
||||
{
|
||||
return ieee_single::almost_equal (a, b);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool
|
||||
almost_equal (const double &a, const double &b)
|
||||
{
|
||||
return ieee_double::almost_equal (a, b);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename A, typename B>
|
||||
inline
|
||||
typename std::enable_if_t<
|
||||
std::is_floating_point<A>::value &&
|
||||
std::is_floating_point<B>::value &&
|
||||
!std::is_same<A,B>::value ,
|
||||
bool
|
||||
>
|
||||
almost_equal (const A &a, const B &b)
|
||||
{
|
||||
using common_t = std::common_type_t<A,B>;
|
||||
return almost_equal<common_t> (static_cast<common_t> (a),
|
||||
static_cast<common_t> (b));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename A, typename B>
|
||||
inline
|
||||
typename std::enable_if_t<
|
||||
std::is_integral_v<A> &&
|
||||
std::is_integral_v<B> &&
|
||||
std::is_signed<A>::value == std::is_signed<B>::value,
|
||||
bool
|
||||
>
|
||||
almost_equal (const A &a, const B &b) {
|
||||
using common_t = std::common_type_t<A,B>;
|
||||
return static_cast<common_t> (a) == static_cast<common_t> (b);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename Ta, typename Tb>
|
||||
constexpr inline
|
||||
typename std::enable_if<
|
||||
!std::is_arithmetic<Ta>::value ||
|
||||
!std::is_arithmetic<Tb>::value,
|
||||
bool
|
||||
>::type
|
||||
almost_equal (const Ta &a, const Tb &b)
|
||||
{ return a == b; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Useful for explictly ignore equality warnings
|
||||
#pragma GCC diagnostic push
|
||||
@ -115,7 +54,7 @@ namespace util {
|
||||
std::is_arithmetic<Tb>::value,
|
||||
bool
|
||||
>
|
||||
exactly_equal (const Ta &a, const Tb &b)
|
||||
equal (const Ta &a, const Tb &b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
@ -128,13 +67,50 @@ namespace util {
|
||||
!std::is_arithmetic<Tb>::value,
|
||||
bool
|
||||
>
|
||||
exactly_equal (const Ta &a, const Tb &b)
|
||||
equal (const Ta &a, const Tb &b)
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Comparisons
|
||||
inline bool
|
||||
almost_equal (float a, float b)
|
||||
{
|
||||
return ieee_single::almost_equal (a, b);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool
|
||||
almost_equal (double a, double b)
|
||||
{
|
||||
return ieee_double::almost_equal (a, b);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename ValueA, typename ValueB>
|
||||
constexpr auto
|
||||
almost_equal (const ValueA &a, const ValueB &b)
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<ValueA> && std::is_floating_point_v<ValueB>) {
|
||||
using common_t = std::common_type_t<ValueA,ValueB>;
|
||||
return almost_equal (common_t {a}, common_t{b});
|
||||
} else if constexpr (std::is_integral_v<ValueA> &&
|
||||
std::is_integral_v<ValueB> &&
|
||||
std::is_signed_v<ValueA> == std::is_signed_v<ValueB>)
|
||||
{
|
||||
using common_t = std::common_type_t<ValueA,ValueB>;
|
||||
return static_cast<common_t> (a) == static_cast<common_t> (b);
|
||||
} else {
|
||||
return equal (a, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr
|
||||
@ -146,12 +122,16 @@ namespace util {
|
||||
return t == 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
std::enable_if_t<
|
||||
!std::is_integral<T>::value, bool
|
||||
>
|
||||
almost_zero (T a)
|
||||
{ return almost_equal (a, T{0}); }
|
||||
{
|
||||
return almost_equal (a, T{0});
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -162,7 +142,7 @@ namespace util {
|
||||
>
|
||||
exactly_zero (T t)
|
||||
{
|
||||
return exactly_equal (t, T{0});
|
||||
return equal (t, T{0});
|
||||
}
|
||||
|
||||
|
||||
@ -173,7 +153,7 @@ namespace util {
|
||||
>
|
||||
exactly_zero (T t)
|
||||
{
|
||||
return exactly_equal (t, T{0});
|
||||
return equal (t, T{0});
|
||||
}
|
||||
|
||||
|
||||
@ -337,7 +317,7 @@ namespace util {
|
||||
is_integer (T t)
|
||||
{
|
||||
T i = 0;
|
||||
return exactly_equal (std::modf (t, &i), T{0});
|
||||
return equal (std::modf (t, &i), T{0});
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,7 +126,7 @@ matrix<Rows,Cols,T>::is_affine (void) const
|
||||
if (!exactly_zero (values[Rows-1][i]))
|
||||
return false;
|
||||
|
||||
return exactly_equal (values[Rows-1][Rows-1], T{1});
|
||||
return equal (values[Rows-1][Rows-1], T{1});
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ test_double (util::TAP::logger &tap)
|
||||
util::ieee_double val;
|
||||
val.set_bits (tests[i].bits);
|
||||
|
||||
success = success && util::exactly_equal (val, tests[i].floating);
|
||||
success = success && util::equal (val, tests[i].floating);
|
||||
}
|
||||
|
||||
tap.expect (success, "double precision bitwise equality");
|
||||
@ -74,7 +74,7 @@ test_single (util::TAP::logger &tap)
|
||||
util::ieee_single val;
|
||||
val.set_bits (tests[i].bits);
|
||||
|
||||
success = success && util::exactly_equal (val, tests[i].floating);
|
||||
success = success && util::equal (val, tests[i].floating);
|
||||
}
|
||||
|
||||
tap.expect (success, "single precision bitwise equality");
|
||||
|
@ -46,8 +46,8 @@ int main ()
|
||||
foo d_foo { 7, 42.0 };
|
||||
auto f_tuple = util::as_tuple (d_foo);
|
||||
|
||||
tap.expect (util::exactly_equal (d_foo.a, std::get<0> (f_tuple)) &&
|
||||
util::exactly_equal (d_foo.b, std::get<1> (f_tuple)),
|
||||
tap.expect (util::equal (d_foo.a, std::get<0> (f_tuple)) &&
|
||||
util::equal (d_foo.b, std::get<1> (f_tuple)),
|
||||
"dynamic member access after conversion to tuple");
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ main (int, char**)
|
||||
for (const auto &[i, v, a, c]: util::izip (v_int, a_float, c_char)) {
|
||||
success = success &&
|
||||
v_int[i] == v &&
|
||||
util::exactly_equal (a_float[i], a) &&
|
||||
util::equal (a_float[i], a) &&
|
||||
c_char[i] == c;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ main (void)
|
||||
tap.expect (!ref["integer"].is_object (), "integer not is_object");
|
||||
tap.expect (!ref["integer"].is_string (), "integer not is_string");
|
||||
tap.expect (
|
||||
util::exactly_equal (
|
||||
util::equal (
|
||||
(unsigned)ref["integer"].as_number ().as_uint (),
|
||||
1u
|
||||
),
|
||||
@ -101,7 +101,7 @@ main (void)
|
||||
tap.expect (!ref["double"].is_object (), "double not is_object");
|
||||
tap.expect (!ref["double"].is_string (), "double not is_string");
|
||||
tap.expect (
|
||||
util::exactly_equal (
|
||||
util::equal (
|
||||
ref["double"].as_number ().as<double> (),
|
||||
3.14
|
||||
),
|
||||
|
@ -69,10 +69,10 @@ main (void)
|
||||
const point4f q = p.homog<4> ();
|
||||
|
||||
tap.expect (
|
||||
almost_equal (q.x, 3.f) &&
|
||||
almost_equal (q.y, 4.f) &&
|
||||
almost_equal (q.z, 0.f) &&
|
||||
almost_equal (q.w, 1.f),
|
||||
equal (q.x, 3.f) &&
|
||||
equal (q.y, 4.f) &&
|
||||
equal (q.z, 0.f) &&
|
||||
equal (q.w, 1.f),
|
||||
|
||||
"homogenous redim"
|
||||
);
|
||||
|
@ -29,11 +29,9 @@ main (int, char**)
|
||||
{ "", "trailing empty" }
|
||||
};
|
||||
|
||||
for (const auto tok: util::tokeniser (csv.c_str (), ','))
|
||||
std::cout << '"' << tok << "\"\n";
|
||||
|
||||
for (const auto &[tok, expected]: util::zip (util::tokeniser (csv.c_str (), ','), TESTS))
|
||||
tap.expect_eq (tok, expected.value, "%s", expected.message);
|
||||
util::view src { csv.c_str (), csv.size () };
|
||||
for (const auto &[tok, expected]: util::zip (util::tokeniser (src, ','), TESTS))
|
||||
tap.expect (equal (tok, expected.value), "%s", expected.message);
|
||||
|
||||
return tap.status ();
|
||||
}
|
19
view.hpp
19
view.hpp
@ -589,7 +589,7 @@ namespace util {
|
||||
typename BeginB, typename EndB
|
||||
>
|
||||
constexpr bool
|
||||
operator== (const view<BeginA,EndA> &a, const view<BeginB,EndB> &b)
|
||||
equal (const view<BeginA,EndA> &a, const view<BeginB,EndB> &b)
|
||||
{
|
||||
return a.size () == b.size () &&
|
||||
std::equal (std::begin (a), std::end (a), std::begin (b));
|
||||
@ -608,9 +608,9 @@ namespace util {
|
||||
>
|
||||
>
|
||||
constexpr bool
|
||||
operator== (const view<IteratorA,IteratorB> &a, const ValueT &b)
|
||||
equal (const view<IteratorA,IteratorB> &a, const ValueT &b)
|
||||
{
|
||||
return a == make_view (b);
|
||||
return equal (a, make_view (b));
|
||||
}
|
||||
|
||||
|
||||
@ -628,15 +628,24 @@ namespace util {
|
||||
>
|
||||
>
|
||||
constexpr bool
|
||||
operator== (const ValueT &a, const view<IteratorA,IteratorB> &b)
|
||||
equal (const ValueT &a, const view<IteratorA,IteratorB> &b)
|
||||
{
|
||||
return b == a;
|
||||
return equal (b, a);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename IteratorA, typename IteratorB>
|
||||
constexpr bool
|
||||
operator== (const view<IteratorA,IteratorB> &a, const view<IteratorA,IteratorB> &b)
|
||||
{
|
||||
return a.begin () == b.begin () && a.end () == b.end ();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename IteratorA, typename IteratorB>
|
||||
constexpr bool
|
||||
operator!= (const view<IteratorA,IteratorB> &a, const view<IteratorA,IteratorB> &b)
|
||||
{
|
||||
return !(a == b);
|
||||
|
Loading…
Reference in New Issue
Block a user