From 8f3db74be87990c8cb420b3898c97380e99b19bf Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 13 Dec 2025 08:46:14 +0100 Subject: [PATCH] Various cleanup (#1238) * Fix typo for remainder in rounded_integral_division.h * Use etl::make_unsigned instead of std::make_unsigned * Fix divide_round_half_down and divide_round_half_odd --- include/etl/rounded_integral_division.h | 39 ++++++++++++++++--------- test/test_rounded_integral_division.cpp | 4 +-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index 417b3143..ea277db3 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -414,7 +414,7 @@ namespace etl const T quotient = numerator / denominator; // Work with magnitudes in unsigned form (avoids abs() overflow) - typedef typename std::make_unsigned::type utype; + typedef typename etl::make_unsigned::type utype; utype abs_remainder = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder); utype abs_denominator = denominator < 0 ? utype(0) - utype(denominator) : utype(denominator); @@ -519,16 +519,18 @@ namespace etl T>::type divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = numerator / denominator; - const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; + + typedef typename etl::make_unsigned::type utype; + const utype abs_denominator = etl::absolute_unsigned(denominator); + const utype abs_remainder = etl::absolute_unsigned(remainder); // Direction: +1 if result should be more positive, -1 if more negative - const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; + const T direction = private_rounded_integral_division::are_same_sign(numerator, denominator) ? 1 : -1; // Only round away from zero if remainder is strictly greater than half the divisor - return abs_remainderainder > (abs_denominator / 2) ? quotient + direction : quotient; + return abs_remainder > (abs_denominator / 2U) ? quotient + direction : quotient; } //*************************************************************************** @@ -730,17 +732,26 @@ namespace etl T>::type divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = numerator / denominator; - const T remainder = numerator % denominator; - const T abs_denominator = etl::absolute(denominator); - const T abs_remainderainder = etl::absolute(remainder); - const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; - if ((abs_remainderainder * 2) < abs_denominator) + typedef typename etl::make_unsigned::type utype; + const utype abs_denominator = etl::absolute_unsigned(denominator); + const utype abs_remainder = etl::absolute_unsigned(remainder); + const utype half = abs_denominator / 2U; + const T direction = private_rounded_integral_division::are_same_sign(numerator, denominator) ? 1 : -1; + + // Odd divisor => no exact-half case; 'half' is floor(abs_denominator/2). + if ((abs_denominator & 1U) != 0U) + { + return (abs_remainder > half) ? quotient + direction : quotient; + } + + if (abs_remainder < half) { return quotient; } - else if ((abs_remainderainder * 2) > abs_denominator) + else if (abs_remainder > half) { return quotient + direction; } diff --git a/test/test_rounded_integral_division.cpp b/test/test_rounded_integral_division.cpp index dc91390b..67cc28b9 100644 --- a/test/test_rounded_integral_division.cpp +++ b/test/test_rounded_integral_division.cpp @@ -624,7 +624,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_down(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_down(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_down(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_down(int32_t(1), std::numeric_limits::min())); } //************************************************************************* @@ -840,7 +840,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), etl::divide_round_half_odd(std::numeric_limits::max(), int32_t(1))); CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::max())); CHECK_EQUAL(std::numeric_limits::min(), etl::divide_round_half_odd(std::numeric_limits::min(), int32_t(1))); - CHECK_EQUAL(int32_t(-1), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::min())); + CHECK_EQUAL(int32_t(0), etl::divide_round_half_odd(int32_t(1), std::numeric_limits::min())); } //*************************************************************************