maths: tighten up type requirements for almost_equal

almost_equal only operates on two reals, or two integers (and even then
only on the same signedness).
This commit is contained in:
Danny Robson 2015-11-13 17:10:10 +11:00
parent c76e0716c4
commit 7b083df977
21 changed files with 151 additions and 140 deletions

View File

@ -109,7 +109,7 @@ template <size_t S, typename T>
bool
extent<S,T>::empty (void) const
{
return almost_equal (area(), 0);
return almost_zero (area());
}

View File

@ -110,7 +110,7 @@ ieee_float<E, S>::almost_equal (floating_t _a,
{
// Ensure ULPs is small enough that the default NaNs won't compare as
// equal to anything else.
CHECK_LE (ulps, 4 * 1024 * 1024);
CHECK_LE (ulps, 4 * 1024 * 1024u);
union {
floating_t f;

View File

@ -29,7 +29,7 @@ plane<S,T>::plane (point<S,T> _p,
p (_p),
n (_n)
{
CHECK_EQ (n.magnitude2 (), 1);
CHECK_EQ (n.magnitude2 (), T{1});
}

View File

@ -324,7 +324,7 @@ void
RIPEMD::finish (void) {
// Ensure the length wouldn't overflow if converted to bits. We need to
// grab this before there's a chance it gets overwritten.
CHECK_EQ (m_length >> sizeof(m_length) * 8 - 3, 0);
CHECK_EQ (m_length >> sizeof(m_length) * 8 - 3, 0u);
uint64_t length = m_length * 8;
// Push a padding byte into the buffer
@ -338,7 +338,7 @@ RIPEMD::finish (void) {
update (ZEROES, remaining);
CHECK_EQ (m_buffer.size, 0);
CHECK_EQ (m_buffer.size, 0u);
remaining = sizeof (m_buffer.d08);
}

View File

@ -132,7 +132,7 @@ SHA1::update (const uint8_t *data, size_t size) {
//-----------------------------------------------------------------------------
void
SHA1::process (void) {
CHECK_EQ (total % BLOCK_BYTES, 0);
CHECK_EQ (total % BLOCK_BYTES, 0u);
// Byteswap the raw input we have buffered ready for arithmetic
std::transform (std::begin (W),

View File

@ -220,7 +220,7 @@ SHA256::finish (void) {
void
SHA256::process (void) {
CHECK_EQ (m_total % sizeof (M), 0);
CHECK_EQ (m_total % sizeof (M), 0u);
// Initialise the message schedule, W
uint32_t W[64];

View File

@ -113,19 +113,6 @@ digits (const uint32_t &v) {
}
//-----------------------------------------------------------------------------
template <>
bool
almost_equal (const float &a, const float &b)
{ return ieee_single::almost_equal (a, b); }
template <>
bool
almost_equal (const double &a, const double &b)
{ return ieee_double::almost_equal (a, b); }
//-----------------------------------------------------------------------------
template <typename T>
T

View File

@ -158,67 +158,89 @@ identity (const T& t)
}
//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
// Comparisons
template <typename T>
bool
almost_equal [[gnu::const]] (const T &a, const T &b)
{ return a == b; }
template <>
bool
almost_equal [[gnu::const]] (const float &a, const float &b);
template <>
bool
almost_equal [[gnu::const]] (const double &a, const double &b);
template <typename Ta, typename Tb>
typename std::enable_if<
std::is_arithmetic<Ta>::value && std::is_arithmetic<Tb>::value,
bool
>::type
almost_equal [[gnu::const]] (Ta a, Tb b) {
return almost_equal <decltype(a + b)> (static_cast<decltype(a + b)>(a),
static_cast<decltype(a + b)>(b));
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>
typename std::enable_if_t<
std::is_floating_point<A>::value &&
std::is_floating_point<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>
typename std::enable_if_t<
std::is_integral<A>::value &&
std::is_integral<B>::value &&
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>
typename std::enable_if<
!std::is_arithmetic<Ta>::value || !std::is_arithmetic<Tb>::value,
!std::is_arithmetic<Ta>::value ||
!std::is_arithmetic<Tb>::value,
bool
>::type
almost_equal [[gnu::const]] (const Ta &a, const Tb &b)
almost_equal (const Ta &a, const Tb &b)
{ return a == b; }
//-----------------------------------------------------------------------------
// Useful for explictly ignore equality warnings
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
template <typename T, typename U>
bool
exactly_equal [[gnu::const]] (const T &a, const U &b)
exactly_equal (const T &a, const U &b)
{ return a == b; }
#pragma GCC diagnostic pop
//-----------------------------------------------------------------------------
template <typename T>
bool
almost_zero [[gnu::const]] (T a)
{ return almost_equal (a, 0); }
template <typename T>
bool
exactly_zero [[gnu::const]] (T a)
{ return exactly_equal (a, static_cast<T> (0)); }
almost_zero (T a)
{ return almost_equal (a, T{0}); }
//-----------------------------------------------------------------------------
template <typename T>
bool
exactly_zero (T a)
{ return exactly_equal (a, T{0}); }
///////////////////////////////////////////////////////////////////////////////
// angles, trig
template <typename T>

View File

@ -44,9 +44,9 @@ namespace util { namespace noise { namespace fractal {
m_invAH (std::pow (_amplitude, -_H)),
m_invGH (std::pow (_gain, _H))
{
CHECK_NEQ (m_octaves, 0);
CHECK_NEQ (m_frequency, 0);
CHECK_NEQ (m_amplitude, 0);
CHECK_NEZ (m_octaves);
CHECK_NEZ (m_frequency);
CHECK_NEZ (m_amplitude);
}

View File

@ -32,9 +32,9 @@ fill (util::image::buffer<1,T> &img,
float persistence,
float sides)
{
CHECK_EQ (target.e.w % 2, 1);
CHECK_EQ (target.e.h % 2, 1);
CHECK_GE (target.area (), 9);
CHECK_EQ (target.e.w % 2, 1u);
CHECK_EQ (target.e.h % 2, 1u);
CHECK_GE (target.area (), 9u);
CHECK_GT (scale, 0);
CHECK_GT (persistence, 0);

View File

@ -257,7 +257,7 @@ template <typename T>
matrix4<T>
quaternion<T>::rotation_matrix (void) const
{
CHECK_EQ (1, norm ());
CHECK_EQ (T{1}, norm ());
const T wx = w * x, wy = w * y, wz = w * z;
const T xx = x * x, xy = x * y, xz = x * z;

View File

@ -129,22 +129,22 @@ test_intersect<2> (util::TAP::logger &tap)
{100.f, 100.f}});
// Through the centre
tap.expect_eq (b2.intersections ({100.f, 0.f}, {0.f, 100.f}), 1, "intersect bezier-2 centre");
tap.expect_eq (b2.intersections ({0.f, 100.f}, {100.f, 0.f}), 1, "intersect bezier-2 centre");
tap.expect_eq (b2.intersections ({100.f, 0.f}, {0.f, 100.f}), 1u, "intersect bezier-2 centre");
tap.expect_eq (b2.intersections ({0.f, 100.f}, {100.f, 0.f}), 1u, "intersect bezier-2 centre");
// Coincident with endpoints
tap.expect_eq (b2.intersections ({0.f, 0.f}, {0.f,100.f}), 1, "intersect bezier-2 endpoint");
tap.expect_eq (b2.intersections ({0.f, 0.f}, {100.f,0.f}), 1, "intersect bezier-2 endpoint");
tap.expect_eq (b2.intersections ({100.f, 100.f}, {100.f,0.f}), 1, "intersect bezier-2 endpoint");
tap.expect_eq (b2.intersections ({0.f, 0.f}, {0.f,100.f}), 1u, "intersect bezier-2 endpoint");
tap.expect_eq (b2.intersections ({0.f, 0.f}, {100.f,0.f}), 1u, "intersect bezier-2 endpoint");
tap.expect_eq (b2.intersections ({100.f, 100.f}, {100.f,0.f}), 1u, "intersect bezier-2 endpoint");
// Co-planar
tap.expect_eq (b2.intersections ({0.f, 0.f}, {1.f, 1.f}), 1, "intersect bezier-2 co-planar");
tap.expect_eq (b2.intersections ({0.f, 0.f}, {1.f, 1.f}), 1u, "intersect bezier-2 co-planar");
// Underneath
tap.expect_eq (b2.intersections ({1000.f, -10.f}, {-1000.f, -10.f}), 0, "intersect bezier-2 under");
tap.expect_eq (b2.intersections ({1000.f, -10.f}, {-1000.f, -10.f}), 0u, "intersect bezier-2 under");
// Above
tap.expect_eq (b2.intersections ({1000.f, 110.f}, {-1000.f, 110.f}), 0, "intersect bezier-2 above");
tap.expect_eq (b2.intersections ({1000.f, 110.f}, {-1000.f, 110.f}), 0u, "intersect bezier-2 above");
}
@ -160,21 +160,21 @@ test_intersect<3> (util::TAP::logger &tap)
{ 100.f, 100.f }});
// Through the centre
tap.expect_eq (b3.intersections ({100.f, 0.f}, {0.f, 100.f}), 1, "intersect bezier-3 centre");
tap.expect_eq (b3.intersections ({100.f, 0.f}, {0.f, 100.f}), 1u, "intersect bezier-3 centre");
// Coincident with endpoints
tap.expect_eq (b3.intersections ({0.f, 0.f}, {0.f,100.f}), 1, "intersect bezier-3 endpoint");
tap.expect_eq (b3.intersections ({0.f, 0.f}, {100.f,0.f}), 1, "intersect bezier-3 endpoint");
tap.expect_eq (b3.intersections ({100.f, 100.f}, {100.f,0.f}), 1, "intersect bezier-3 endpoint");
tap.expect_eq (b3.intersections ({0.f, 0.f}, {0.f,100.f}), 1u, "intersect bezier-3 endpoint");
tap.expect_eq (b3.intersections ({0.f, 0.f}, {100.f,0.f}), 1u, "intersect bezier-3 endpoint");
tap.expect_eq (b3.intersections ({100.f, 100.f}, {100.f,0.f}), 1u, "intersect bezier-3 endpoint");
// Co-planar
tap.expect_eq (b3.intersections ({0.f, 0.f}, {1.f, 1.f}), 1, "intersect bezier-3 co-planar");
tap.expect_eq (b3.intersections ({0.f, 0.f}, {1.f, 1.f}), 1u, "intersect bezier-3 co-planar");
// Underneath
tap.expect_eq (b3.intersections ({1000.f, -10.f}, {-1000.f, -10.f}), 0, "intersect bezier-3 under");
tap.expect_eq (b3.intersections ({1000.f, -10.f}, {-1000.f, -10.f}), 0u, "intersect bezier-3 under");
// Above
tap.expect_eq (b3.intersections ({1000.f, 110.f}, {-1000.f, 110.f}), 0, "intersect bezier-3 above");
tap.expect_eq (b3.intersections ({1000.f, 110.f}, {-1000.f, 110.f}), 0u, "intersect bezier-3 above");
}

View File

@ -6,33 +6,33 @@
static void
test_rotate (util::TAP::logger &tap)
{
tap.expect_eq (rotatel (uint8_t (0x0F), 0), 0x0F, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0x0F), 4), 0xF0, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0xF0), 4), 0x0F, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0x0F), 8), 0x0F, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0x0F), 0), 0x0Fu, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0x0F), 4), 0xF0u, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0xF0), 4), 0x0Fu, "rotate-left u8");
tap.expect_eq (rotatel (uint8_t (0x0F), 8), 0x0Fu, "rotate-left u8");
tap.expect_eq (rotater (uint8_t (0x0F), 0), 0x0F, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0x0F), 4), 0xF0, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0xF0), 4), 0x0F, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0x0F), 8), 0x0F, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0x0F), 0), 0x0Fu, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0x0F), 4), 0xF0u, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0xF0), 4), 0x0Fu, "rotate-right u8");
tap.expect_eq (rotater (uint8_t (0x0F), 8), 0x0Fu, "rotate-right u8");
tap.expect_eq (rotatel (uint16_t (0xABCD), 0), 0xABCD, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 4), 0xBCDA, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 8), 0xCDAB, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 12), 0xDABC, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 16), 0xABCD, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 0), 0xABCDu, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 4), 0xBCDAu, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 8), 0xCDABu, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 12), 0xDABCu, "rotate-left u16");
tap.expect_eq (rotatel (uint16_t (0xABCD), 16), 0xABCDu, "rotate-left u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 0), 0xABCD, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 4), 0xDABC, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 8), 0xCDAB, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 12), 0xBCDA, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 16), 0xABCD, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 0), 0xABCDu, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 4), 0xDABCu, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 8), 0xCDABu, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 12), 0xBCDAu, "rotate-right u16");
tap.expect_eq (rotater (uint16_t (0xABCD), 16), 0xABCDu, "rotate-right u16");
tap.expect_eq (rotatel (uint32_t (0x12345670), 12), 0x45670123, "rotate-left u32");
tap.expect_eq (rotater (uint32_t (0x12345670), 12), 0x67012345, "rotate-right u32");
tap.expect_eq (rotatel (uint32_t (0x12345670), 12), 0x45670123u, "rotate-left u32");
tap.expect_eq (rotater (uint32_t (0x12345670), 12), 0x67012345u, "rotate-right u32");
tap.expect_eq (rotatel (uint64_t (0x1234567890ABCDEF), 12), 0x4567890ABCDEF123, "rotate-left u64");
tap.expect_eq (rotater (uint64_t (0x1234567890ABCDEF), 12), 0xDEF1234567890ABC, "rotate-right u64");
tap.expect_eq (rotatel (uint64_t (0x1234567890ABCDEF), 12), 0x4567890ABCDEF123u, "rotate-left u64");
tap.expect_eq (rotater (uint64_t (0x1234567890ABCDEF), 12), 0xDEF1234567890ABCu, "rotate-right u64");
}
@ -48,7 +48,7 @@ test_reverse (util::TAP::logger &tap)
matches++;
}
tap.expect_eq (matches, 256, "exhaustive 8 bit reverse");
tap.expect_eq (matches, 256u, "exhaustive 8 bit reverse");
}

View File

@ -166,9 +166,9 @@ test_bytes (util::TAP::logger &tap)
size_t val;
} commands[] = {
{ "1", 1 },
{ "1k", pow (1024, 1) },
{ "1M", pow (1024, 2) },
{ "1G", pow (1024, 3) }
{ "1k", util::pow (1024u, 1u) },
{ "1M", util::pow (1024u, 2u) },
{ "1G", util::pow (1024u, 3u) }
};
const char *argv[] = {

View File

@ -26,7 +26,7 @@ main (void)
for (auto p: util::extent_range2u ({3, 3}))
success += EXPECTED[offset++] == p ? 1 : 0;
tap.expect (success == elems (EXPECTED), "extent_range2u iteration");
tap.expect_eq (success, elems (EXPECTED), "extent_range2u iteration");
}
return tap.status ();

View File

@ -118,10 +118,10 @@ test_normalisations (util::TAP::logger &tap)
tap.expect (success, "float-u32 normalisation");
}
tap.expect_eq (renormalise<uint8_t,uint32_t> (0xff), 0xffffffff, "normalise hi u8-to-u32");
tap.expect_eq (renormalise<uint8_t,uint32_t> (0x00), 0x00000000, "normalise lo u8-to-u32");
tap.expect_eq (renormalise<uint8_t,uint32_t> (0xff), 0xffffffffu, "normalise hi u8-to-u32");
tap.expect_eq (renormalise<uint8_t,uint32_t> (0x00), 0x00000000u, "normalise lo u8-to-u32");
tap.expect_eq (renormalise<uint32_t,uint8_t> (0xffffffff), 0xff, "normalise hi u32-to-u8");
tap.expect_eq (renormalise<uint32_t,uint8_t> (0xffffffff), 0xffu, "normalise hi u32-to-u8");
}
@ -141,7 +141,7 @@ main (void)
tap.expect_eq (util::min (-2, 0, 2), -2, "variadic min");
tap.expect_eq (util::max (-2, 0, 2), 2, "variadic max");
tap.expect_eq (pow2 (4), 16, "pow2");
tap.expect_eq (util::pow2 (4u), 16u, "pow2");
tap.expect_eq (rootsquare (2, 2), sqrt (8), "rootsquare");
@ -150,23 +150,23 @@ main (void)
tap.expect_eq (sign (-1), -1, "sign(-1)");
tap.expect_eq (sign ( 1), 1, "sign( 1)");
tap.expect_eq (sign (POS_ZERO), 1, "sign (POS_ZERO)");
tap.expect_eq (sign (NEG_ZERO), -1, "sign (NEG_ZERO)");
tap.expect_eq (sign ( numeric_limits<double>::infinity ()), 1, "sign +inf");
tap.expect_eq (sign (-numeric_limits<double>::infinity ()), -1, "sign -inf");
tap.expect_eq (sign (POS_ZERO), 1., "sign (POS_ZERO)");
tap.expect_eq (sign (NEG_ZERO), -1., "sign (NEG_ZERO)");
tap.expect_eq (sign ( numeric_limits<double>::infinity ()), 1., "sign +inf");
tap.expect_eq (sign (-numeric_limits<double>::infinity ()), -1., "sign -inf");
tap.expect_eq (to_degrees (PI< float>), 180.f, "to_degrees float");
tap.expect_eq (to_degrees (PI<double>), 180.0, "to_degrees double");
tap.expect_eq (to_radians (180.f), PI<float>, "to_radians float");
tap.expect_eq (to_radians (180.0), PI<double>, "to_radians double");
tap.expect_eq (log2 (8u), 3, "log2 +ve");
tap.expect_eq (log2 (1u), 0, "log2 zero");
tap.expect_eq (log2 (8u), 3u, "log2 +ve");
tap.expect_eq (log2 (1u), 0u, "log2 zero");
//tap.expect_eq (log2 (9u), 3, "log2up 9");
tap.expect_eq (log2up (9u), 4, "log2up 9");
tap.expect_eq (log2up (8u), 3, "log2up 9");
tap.expect_eq (log2up (1u), 0, "log2up 9");
tap.expect_eq (log2up (9u), 4u, "log2up 9");
tap.expect_eq (log2up (8u), 3u, "log2up 9");
tap.expect_eq (log2up (1u), 0u, "log2up 9");
return tap.status ();
}

View File

@ -32,10 +32,10 @@ main (void)
auto r = m * v;
tap.expect (
almost_equal (r.x, 30) &&
almost_equal (r.y, 70) &&
almost_equal (r.z, 110) &&
almost_equal (r.w, 150),
almost_equal (r.x, 30.f) &&
almost_equal (r.y, 70.f) &&
almost_equal (r.z, 110.f) &&
almost_equal (r.w, 150.f),
"simple matrix-vector multiplication"
);
}
@ -79,9 +79,9 @@ main (void)
for (size_t r = 0; r < m.rows; ++r)
for (size_t c = 0; c < m.cols; ++c)
if (r == c)
success = success && almost_equal (m.values[r][c], 1);
success = success && almost_equal (m.values[r][c], 1.f);
else
success = success && almost_equal (m.values[r][c], 0);
success = success && almost_equal (m.values[r][c], 0.f);
tap.expect (success, "identity inversion");
}
@ -93,7 +93,7 @@ main (void)
{ 3, 4 }
} };
tap.expect_eq (-2, m.determinant (), "2x2 determinant");
tap.expect_eq (-2.f, m.determinant (), "2x2 determinant");
util::matrix2f r { {
{ -4, 2 },
@ -111,7 +111,7 @@ main (void)
{ 4, 0, 2 }
} };
tap.expect_eq (-6, m.determinant (), "3x3 determinant");
tap.expect_eq (-6.f, m.determinant (), "3x3 determinant");
util::matrix3f r { {
{ -6, 2, 5 },

View File

@ -65,10 +65,10 @@ main (void)
const point4f q = p.homog<4> ();
tap.expect (
almost_equal (q.x, 3) &&
almost_equal (q.y, 4) &&
almost_equal (q.z, 0) &&
almost_equal (q.w, 1),
almost_equal (q.x, 3.f) &&
almost_equal (q.y, 4.f) &&
almost_equal (q.z, 0.f) &&
almost_equal (q.w, 1.f),
"homogenous redim"
);

View File

@ -32,7 +32,7 @@ test_single (void)
auto raii = void_signal.connect (increment_uint);
void_signal (val);
CHECK_EQ (val, 1);
CHECK_EQ (val, 1u);
}
@ -47,7 +47,7 @@ test_double (void)
auto raii = void_signal.connect (increment_uint);
void_signal (val);
CHECK_EQ (val, 2);
CHECK_EQ (val, 2u);
}
@ -65,11 +65,11 @@ void
test_value_signal (void)
{
util::value_signal<unsigned> val;
auto raii = val.connect ([] (unsigned v) { CHECK_EQ (v, 42); });
auto raii = val.connect ([] (unsigned v) { CHECK_EQ (v, 42u); });
val = 42u;
unsigned check = val;
CHECK_EQ (check, 42);
CHECK_EQ (check, 42u);
}
@ -86,7 +86,7 @@ test_combiner (void)
auto raii = sig.connect ([&] (void) { ++count; return true; });
CHECK (sig ());
CHECK_EQ (count, 3);
CHECK_EQ (count, 3u);
}
{
@ -98,7 +98,7 @@ test_combiner (void)
auto raii = sig.connect ([&] (void) { ++count; return true; });
CHECK (!sig ());
CHECK_EQ (count, 2);
CHECK_EQ (count, 2u);
}
}

View File

@ -79,7 +79,7 @@ template <size_t S, typename T>
bool
vector<S,T>::is_normalised (void) const
{
return almost_equal (magnitude2 (), 1.f);
return almost_equal (magnitude2 (), T{1});
}
@ -323,5 +323,7 @@ template <>
bool
almost_equal [[gnu::pure]] (const util::vector2f &a, const util::vector2f &b)
{
return std::equal (a.begin (), a.end (), b.begin (), almost_equal<float>);
bool (*comparator) (const float&, const float&) = almost_equal;
return std::equal (a.begin (), a.end (), b.begin (), comparator);
}

View File

@ -180,7 +180,7 @@ version::operator== (const version &rhs) const {
std::ostream&
operator <<(std::ostream& os, const util::version& rhs) {
size_t elements = rhs.size;
CHECK_GT (elements, 0);
CHECK_GT (elements, 0u);
os << rhs.major ();
if (!--elements)
@ -195,7 +195,7 @@ operator <<(std::ostream& os, const util::version& rhs) {
goto done;
os << "." << rhs.build ();
CHECK_EQ (--elements, 0);
CHECK_EQ (elements - 1, 0u);
done:
os << release_to_string (rhs.release);