Added remaining limits tests

Fixed divide_round_half_odd and added tests
This commit is contained in:
John Wellbelove 2025-08-11 20:19:18 +01:00
parent 5c52fd19cc
commit ddfd3fa443
2 changed files with 199 additions and 12 deletions

View File

@ -656,22 +656,22 @@ namespace etl
{
const T quotient = num / den;
const T remainder = num % den;
const T common_den = etl::absolute(common_den);
const T abs_den = etl::absolute(den);
const T abs_remainder = etl::absolute(remainder);
const T direction = ((num >= 0) == (common_den >= 0)) ? 1 : -1;
const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1;
if ((abs_remainder * 2) < common_den)
if ((abs_remainder * 2) < abs_den)
{
return quotient;
}
else if ((abs_remainder * 2) > common_den)
else if ((abs_remainder * 2) > abs_den)
{
return quotient + direction;
}
else
{
// Exactly halfway, round to odd
return (quotient & 1) == 1 ? quotient : quotient + direction;
return (quotient & 1) != 0 ? quotient : quotient + direction;
}
}
@ -706,23 +706,22 @@ namespace etl
T>::type
divide_round_half_odd(T num, T den) ETL_NOEXCEPT
{
const T quotient = num / den;
const T remainder = num % den;
const T quotient = num / den;
const T remainder = num % den;
const T direction = ((num >= 0U) == (den >= 0U)) ? 1 : -1;
if ((remainder * 2U) < den)
{
// Less than halfway, round down
return quotient;
}
else if ((remainder * 2U) > den)
{
// More than halfway, round up
return quotient + 1U;
return quotient + direction;
}
else
{
// Exactly halfway, round to odd
return (quotient & 1U) == 1U ? quotient : quotient + 1U;
return (quotient & 1U) != 0U ? quotient : quotient + direction;
}
}

View File

@ -194,6 +194,15 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_floor_signed_limits)
{
CHECK_EQUAL(std::numeric_limits<int32_t>::max(), etl::divide_round_to_floor(std::numeric_limits<int32_t>::max(), int32_t(1)));
CHECK_EQUAL(int32_t(0), etl::divide_round_to_floor(int32_t(1), std::numeric_limits<int32_t>::max()));
CHECK_EQUAL(std::numeric_limits<int32_t>::min(), etl::divide_round_to_floor(std::numeric_limits<int32_t>::min(), int32_t(1)));
CHECK_EQUAL(int32_t(-1), etl::divide_round_to_floor(int32_t(1), std::numeric_limits<int32_t>::min()));
}
//*************************************************************************
TEST(test_round_to_floor_unsigned_different_types)
{
@ -232,6 +241,13 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_floor_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_to_floor(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(0), etl::divide_round_to_floor(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
//*************************************************************************
TEST(test_round_to_zero_signed_different_types)
{
@ -282,6 +298,15 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_zero_signed_limits)
{
CHECK_EQUAL(std::numeric_limits<int32_t>::max(), etl::divide_round_to_zero(std::numeric_limits<int32_t>::max(), int32_t(1)));
CHECK_EQUAL(int32_t(0), etl::divide_round_to_zero(int32_t(1), std::numeric_limits<int32_t>::max()));
CHECK_EQUAL(std::numeric_limits<int32_t>::min(), etl::divide_round_to_zero(std::numeric_limits<int32_t>::min(), int32_t(1)));
CHECK_EQUAL(int32_t(0), etl::divide_round_to_zero(int32_t(1), std::numeric_limits<int32_t>::min()));
}
//*************************************************************************
TEST(test_round_to_zero_unsigned_different_types)
{
@ -320,6 +345,13 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_zero_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_to_zero(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(0), etl::divide_round_to_zero(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
//*************************************************************************
TEST(test_round_to_infinity_signed_different_types)
{
@ -370,6 +402,15 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_infinity_signed_limits)
{
CHECK_EQUAL(std::numeric_limits<int32_t>::max(), etl::divide_round_to_infinity(std::numeric_limits<int32_t>::max(), int32_t(1)));
CHECK_EQUAL(int32_t(1), etl::divide_round_to_infinity(int32_t(1), std::numeric_limits<int32_t>::max()));
CHECK_EQUAL(std::numeric_limits<int32_t>::min(), etl::divide_round_to_infinity(std::numeric_limits<int32_t>::min(), int32_t(1)));
CHECK_EQUAL(int32_t(-1), etl::divide_round_to_infinity(int32_t(1), std::numeric_limits<int32_t>::min()));
}
//*************************************************************************
TEST(test_round_to_infinity_unsigned_different_types)
{
@ -412,6 +453,13 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_infinity_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_to_infinity(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(1), etl::divide_round_to_infinity(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
//*************************************************************************
TEST(test_round_to_half_up_signed_different_types)
{
@ -517,7 +565,7 @@ namespace
TEST(test_round_to_half_up_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_half_up(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(0U), etl::divide_round_half_up(uint32_t(1), std::numeric_limits<uint32_t>::max()));
CHECK_EQUAL(uint32_t(0U), etl::divide_round_half_up(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
//*************************************************************************
@ -570,6 +618,15 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_down_signed_limits)
{
CHECK_EQUAL(std::numeric_limits<int32_t>::max(), etl::divide_round_half_down(std::numeric_limits<int32_t>::max(), int32_t(1)));
CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits<int32_t>::max()));
CHECK_EQUAL(std::numeric_limits<int32_t>::min(), etl::divide_round_half_down(std::numeric_limits<int32_t>::min(), int32_t(1)));
CHECK_EQUAL(int32_t(-1), etl::divide_round_half_down(int32_t(1), std::numeric_limits<int32_t>::min()));
}
//*************************************************************************
TEST(test_round_to_half_down_unsigned_different_types)
{
@ -612,6 +669,13 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_down_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_half_down(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(0U), etl::divide_round_half_down(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
//*************************************************************************
TEST(test_round_to_half_even_signed_different_types)
{
@ -662,6 +726,15 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_even_signed_limits)
{
CHECK_EQUAL(std::numeric_limits<int32_t>::max(), etl::divide_round_half_even(std::numeric_limits<int32_t>::max(), int32_t(1)));
CHECK_EQUAL(int32_t(0), etl::divide_round_half_even(int32_t(1), std::numeric_limits<int32_t>::max()));
CHECK_EQUAL(std::numeric_limits<int32_t>::min(), etl::divide_round_half_even(std::numeric_limits<int32_t>::min(), int32_t(1)));
CHECK_EQUAL(int32_t(-1), etl::divide_round_half_even(int32_t(1), std::numeric_limits<int32_t>::min()));
}
//*************************************************************************
TEST(test_round_to_half_even_unsigned_different_types)
{
@ -703,5 +776,120 @@ namespace
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_even_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_half_even(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(0U), etl::divide_round_half_even(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
//*************************************************************************
TEST(test_round_to_half_odd_signed_different_types)
{
const std::array<int16_t, 42> numerator{ 0, 49, 50, 51, 99, 100, 149, 150, 151, 199, 200, 249, 250, 251, 299, 300, 349, 350, 351, 399, 400,
0, -49, -50, -51, -99, -100, -149, -150, -151, -199, -200, -249, -250, -251, -299, -300, -349, -350, -351, -399, -400 };
const std::array<int32_t, 2> denominator{ 100, -100 };
const std::array<int32_t, 84> expected{ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4,
0, 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -4, -4, -4,
0, 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -4, -4, -4,
0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4 };
std::array<int32_t, 84> actual{};
for (size_t i = 0; i < denominator.size(); ++i)
{
for (size_t j = 0; j < numerator.size(); ++j)
{
size_t index = j + (i * numerator.size());
actual[index] = etl::divide_round_half_odd(numerator[j], denominator[i]);
}
}
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_odd_signed_same_types)
{
const std::array<int32_t, 42> numerator{ 0, 49, 50, 51, 99, 100, 149, 150, 151, 199, 200, 249, 250, 251, 299, 300, 349, 350, 351, 399, 400,
0, -49, -50, -51, -99, -100, -149, -150, -151, -199, -200, -249, -250, -251, -299, -300, -349, -350, -351, -399, -400 };
const std::array<int32_t, 2> denominator{ 100, -100 };
const std::array<int32_t, 84> expected{ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4,
0, 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -4, -4, -4,
0, 0, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -4, -4, -4,
0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4 };
std::array<int32_t, 84> actual{};
for (size_t i = 0; i < denominator.size(); ++i)
{
for (size_t j = 0; j < numerator.size(); ++j)
{
size_t index = j + (i * numerator.size());
actual[index] = etl::divide_round_half_odd(numerator[j], denominator[i]);
}
}
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_odd_signed_limits)
{
CHECK_EQUAL(std::numeric_limits<int32_t>::max(), etl::divide_round_half_odd(std::numeric_limits<int32_t>::max(), int32_t(1)));
CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits<int32_t>::max()));
CHECK_EQUAL(std::numeric_limits<int32_t>::min(), etl::divide_round_half_odd(std::numeric_limits<int32_t>::min(), int32_t(1)));
CHECK_EQUAL(int32_t(-1), etl::divide_round_half_odd(int32_t(1), std::numeric_limits<int32_t>::min()));
}
//*************************************************************************
TEST(test_round_to_half_odd_unsigned_different_types)
{
const std::array<uint16_t, 21> numerator{ 0, 49, 50, 51, 99, 100, 149, 150, 151, 199, 200, 249, 250, 251, 299, 300, 349, 350, 351, 399, 400 };
const std::array<uint32_t, 1> denominator{ 100 };
const std::array<uint32_t, 21> expected{ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4 };
std::array<uint32_t, 42> actual{};
for (size_t i = 0; i < denominator.size(); ++i)
{
for (size_t j = 0; j < numerator.size(); ++j)
{
size_t index = j + (i * numerator.size());
actual[index] = etl::divide_round_half_odd(numerator[j], denominator[i]);
}
}
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_odd_unsigned_same_types)
{
const std::array<uint32_t, 21> numerator{ 0, 49, 50, 51, 99, 100, 149, 150, 151, 199, 200, 249, 250, 251, 299, 300, 349, 350, 351, 399, 400 };
const std::array<uint32_t, 1> denominator{ 100 };
const std::array<uint32_t, 21> expected{ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4 };
std::array<uint32_t, 42> actual{};
for (size_t i = 0; i < denominator.size(); ++i)
{
for (size_t j = 0; j < numerator.size(); ++j)
{
size_t index = j + (i * numerator.size());
actual[index] = etl::divide_round_half_odd(numerator[j], denominator[i]);
}
}
CHECK_ARRAY_EQUAL(expected.data(), actual.data(), expected.size());
}
//*************************************************************************
TEST(test_round_to_half_odd_unsigned_limits)
{
CHECK_EQUAL(std::numeric_limits<uint32_t>::max(), etl::divide_round_half_odd(std::numeric_limits<uint32_t>::max(), uint32_t(1)));
CHECK_EQUAL(uint32_t(0U), etl::divide_round_half_odd(uint32_t(1), std::numeric_limits<uint32_t>::max()));
}
};
}