From 86f76933c1b0f70314bfd59e0411c81bf8fad8b5 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 12 Aug 2025 15:13:03 +0100 Subject: [PATCH] Added full rounded integral division --- include/etl/rounded_integral_division.h | 334 ++++++++++++++++-------- support/Release notes.txt | 1 + test/CMakeLists.txt | 1 + test/vs2022/etl.vcxproj.filters | 3 + 4 files changed, 225 insertions(+), 114 deletions(-) diff --git a/include/etl/rounded_integral_division.h b/include/etl/rounded_integral_division.h index 5b02a2be..751ff04e 100644 --- a/include/etl/rounded_integral_division.h +++ b/include/etl/rounded_integral_division.h @@ -9,7 +9,7 @@ https://www.etlcpp.com Copyright(c) 2025 John Wellbelove -Permission is hereby granted, free of charge, to any person obtaining num copy +Permission is hereby granted, free of charge, to any person obtaining numerator copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell @@ -40,8 +40,8 @@ namespace etl namespace private_rounded_integral_division { //***************************************************************************** - ///\brief Checks if two values have the same sign. - /// For signed integral types. + // Checks if two values have the same sign. + // For signed integral types. //***************************************************************************** template ETL_CONSTEXPR @@ -52,13 +52,13 @@ namespace etl } //***************************************************************************** - ///\brief Checks if two values have the same sign. - /// For unsigned integral types. + // Checks if two values have the same sign. + // For unsigned integral types. //***************************************************************************** template ETL_CONSTEXPR typename etl::enable_if::value && etl::is_unsigned::value, bool>::type - are_same_sign(T a, T b) ETL_NOEXCEPT + are_same_sign(T /*a*/, T /*b*/) ETL_NOEXCEPT { return true; } @@ -68,15 +68,18 @@ namespace etl ///\brief Integral division with rounding to ceiling. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to ceiling. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_to_ceiling(T num, T den) ETL_NOEXCEPT + divide_round_to_ceiling(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; // If remainder is zero, already exact if (remainder == 0) @@ -85,13 +88,17 @@ namespace etl } // If signs are the same, increment quotient - return private_rounded_integral_division::are_same_sign(num, den) ? quotient + 1 : quotient; + return private_rounded_integral_division::are_same_sign(numerator, denominator) ? quotient + 1 : quotient; } //*************************************************************************** ///\brief Integral division with rounding to ceiling. /// For signed integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to ceiling. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -100,28 +107,31 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_to_ceiling(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_ceiling(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_to_ceiling(static_cast(num), static_cast(den)); + return divide_round_to_ceiling(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to ceiling. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to ceiling. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_to_ceiling(T num, T den) ETL_NOEXCEPT + divide_round_to_ceiling(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; // If remainder is zero, already exact, otherwise, increment quotient return remainder == 0U ? quotient : quotient + 1U; @@ -131,6 +141,10 @@ namespace etl ///\brief Integral division with rounding to ceiling. /// For unsigned integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to ceiling. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -139,28 +153,31 @@ namespace etl etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_to_ceiling(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_ceiling(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_to_ceiling(static_cast(num), static_cast(den)); + return divide_round_to_ceiling(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to floor. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to floor. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_to_floor(T num, T den) ETL_NOEXCEPT + divide_round_to_floor(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; // If remainder is zero, already exact if (remainder == 0) @@ -169,13 +186,17 @@ namespace etl } // If signs are different, decrement quotient - return private_rounded_integral_division::are_same_sign(num, den) ? quotient : quotient - 1; + return private_rounded_integral_division::are_same_sign(numerator, denominator) ? quotient : quotient - 1; } //*************************************************************************** ///\brief Integral division with rounding to floor. /// For signed integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to floor. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -184,33 +205,40 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_to_floor(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_floor(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_to_floor(static_cast(num), static_cast(den)); + return divide_round_to_floor(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to floor. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to floor. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_to_floor(T num, T den) ETL_NOEXCEPT + divide_round_to_floor(T numerator, T denominator) ETL_NOEXCEPT { - return num / den; + return numerator / denominator; } //*************************************************************************** ///\brief Integral division with rounding to floor. /// For unsigned integral types. /// For different argument types. - //*************************************************************************** + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to floor. + /// Return type is the etl::common_type::type. + /// //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && @@ -218,33 +246,36 @@ namespace etl etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_to_floor(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_floor(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - const type common_num = num; - const type common_den = den; + const type common_numerator = numerator; + const type common_denominator = denominator; - return common_num / common_den; + return common_numerator / common_denominator; } //*************************************************************************** ///\brief Integral division with rounding towards infinity. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to infinity. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_to_infinity(T num, T den) ETL_NOEXCEPT + divide_round_to_infinity(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; - if (private_rounded_integral_division::are_same_sign(num, den)) + if (private_rounded_integral_division::are_same_sign(numerator, denominator)) { // Same sign, round towards +infinity quotient = remainder ? quotient + 1 : quotient; @@ -262,6 +293,10 @@ namespace etl ///\brief Integral division with rounding towards infinity. /// For signed integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to infinity. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -270,28 +305,31 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_to_infinity(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_infinity(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_to_infinity(static_cast(num), static_cast(den)); + return divide_round_to_infinity(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding towards infinity. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to infinity. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_to_infinity(T num, T den) ETL_NOEXCEPT + divide_round_to_infinity(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; return remainder ? quotient + 1U : quotient; } @@ -300,6 +338,10 @@ namespace etl ///\brief Integral division with rounding towards infinity. /// For unsigned integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to infinity. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -308,77 +350,88 @@ namespace etl etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_to_infinity(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_infinity(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_to_infinity(static_cast(num), static_cast(den)); + return divide_round_to_infinity(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding towards zero. /// For integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to zero. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_to_zero(T num, T den) ETL_NOEXCEPT + divide_round_to_zero(T numerator, T denominator) ETL_NOEXCEPT { - return num / den; + return numerator / denominator; } //*************************************************************************** ///\brief Integral division with rounding towards zero. /// For integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to zero. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_integral::value, typename etl::common_type::type>::type - divide_round_to_zero(T1 num, T2 den) ETL_NOEXCEPT + divide_round_to_zero(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; // Cast to common type to avoid overflow. - const type common_num = num; - const type common_den = den; + const type common_numerator = numerator; + const type common_denominator = denominator; - return common_num / common_den; + return common_numerator / common_denominator; } //*************************************************************************** ///\brief Integral division with rounding to half up. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half up. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_half_up(T num, T den) ETL_NOEXCEPT + divide_round_half_up(T numerator, T denominator) ETL_NOEXCEPT { // Normal division - T quotient = num / den; - T remainder = num % den; + T quotient = numerator / denominator; + + const T remainder = numerator % denominator; // Work with magnitudes in unsigned form (avoids abs() overflow) typedef typename std::make_unsigned::type utype; - utype abs_rem = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder); - utype abs_den = den < 0 ? utype(0) - utype(den) : utype(den); + utype abs_remainder = remainder < 0 ? utype(0) - utype(remainder) : utype(remainder); + utype abs_denominator = denominator < 0 ? utype(0) - utype(denominator) : utype(denominator); - // Threshold for rounding up (half the denominator, rounded up) - utype half_den = (abs_den + 1) / 2; + // Threshold for rounding up (half the denominatorominator, rounded up) + utype half_denominator = (abs_denominator + 1) / 2; - if (abs_rem >= half_den) + if (abs_remainder >= half_denominator) { // Round away from zero - if (private_rounded_integral_division::are_same_sign(num, den)) + if (private_rounded_integral_division::are_same_sign(numerator, denominator)) { ++quotient; // same sign ? increment } @@ -395,6 +448,10 @@ namespace etl ///\brief Integral division with rounding to half up. /// For signed integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half up. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -403,31 +460,34 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_half_up(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_up(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_up(static_cast(num), static_cast(den)); + return divide_round_half_up(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half up. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half up. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_half_up(T num, T den) ETL_NOEXCEPT + divide_round_half_up(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; // If remainder is at least half the divisor, round up - if (remainder >= (den / 2U) + (den % 2U)) + if (remainder >= (denominator / 2U) + (denominator % 2U)) { ++quotient; } @@ -439,6 +499,10 @@ namespace etl ///\brief Integral division with rounding to half up. /// For unsigned integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half up. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -446,41 +510,48 @@ namespace etl etl::is_integral::value && etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_half_up(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_up(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_up(static_cast(num), static_cast(den)); + return divide_round_half_up(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half down. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half down. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_half_down(T num, T den) ETL_NOEXCEPT + divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = num / den; - const T remainder = num % den; - const T abs_den = etl::absolute(den); - const T abs_remainder = etl::absolute(remainder); + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; + const T abs_denominator = etl::absolute(denominator); + const T abs_remainderainder = etl::absolute(remainder); // Direction: +1 if result should be more positive, -1 if more negative - const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1; + const T direction = ((numerator >= 0) == (denominator >= 0)) ? 1 : -1; // Only round away from zero if remainder is strictly greater than half the divisor - return abs_remainder > (abs_den / 2) ? quotient + direction : quotient; + return abs_remainderainder > (abs_denominator / 2) ? quotient + direction : quotient; } //*************************************************************************** ///\brief Integral division with rounding to half down. /// For signed integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half down. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -489,31 +560,34 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_half_down(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_down(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_down(static_cast(num), static_cast(den)); + return divide_round_half_down(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half down. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half down. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_half_down(T num, T den) ETL_NOEXCEPT + divide_round_half_down(T numerator, T denominator) ETL_NOEXCEPT { - const T remainder = num % den; + const T remainder = numerator % denominator; - T quotient = num / den; + T quotient = numerator / denominator; // If remainder is at least half the divisor, round down - if (remainder > (den / 2U)) + if (remainder > (denominator / 2U)) { ++quotient; } @@ -525,6 +599,10 @@ namespace etl ///\brief Integral division with rounding to half down. /// For unsigned integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half down. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -532,36 +610,39 @@ namespace etl etl::is_integral::value && etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_half_down(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_down(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_down(static_cast(num), static_cast(den)); + return divide_round_half_down(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half even. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half even. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_half_even(T num, T den) ETL_NOEXCEPT + divide_round_half_even(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = num / den; - const T remainder = num % den; - const T abs_den = etl::absolute(den); - const T abs_remainder = etl::absolute(remainder); - const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1; + 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; - if ((abs_remainder * 2) < abs_den) + if ((abs_remainderainder * 2) < abs_denominator) { return quotient; } - else if ((abs_remainder * 2) > abs_den) + else if ((abs_remainderainder * 2) > abs_denominator) { return quotient + direction; } @@ -576,6 +657,10 @@ namespace etl ///\brief Integral division with rounding to half even. /// For signed integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half even. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -584,34 +669,37 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_half_even(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_even(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_even(static_cast(num), static_cast(den)); + return divide_round_half_even(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half even. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half even. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_half_even(T num, T den) ETL_NOEXCEPT + divide_round_half_even(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = num / den; - const T remainder = num % den; + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; - if ((remainder * 2U) < den) + if ((remainder * 2U) < denominator) { // Less than halfway, round down return quotient; } - else if ((remainder * 2U) > den) + else if ((remainder * 2U) > denominator) { // More than halfway, round up return quotient + 1U; @@ -627,6 +715,10 @@ namespace etl ///\brief Integral division with rounding to half even. /// For unsigned integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half even. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -635,36 +727,39 @@ namespace etl etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_half_even(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_even(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_even(static_cast(num), static_cast(den)); + return divide_round_half_even(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half odd. /// For signed integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half odd. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_signed::value, T>::type - divide_round_half_odd(T num, T den) ETL_NOEXCEPT + divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = num / den; - const T remainder = num % den; - const T abs_den = etl::absolute(den); - const T abs_remainder = etl::absolute(remainder); - const T direction = ((num >= 0) == (den >= 0)) ? 1 : -1; + 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; - if ((abs_remainder * 2) < abs_den) + if ((abs_remainderainder * 2) < abs_denominator) { return quotient; } - else if ((abs_remainder * 2) > abs_den) + else if ((abs_remainderainder * 2) > abs_denominator) { return quotient + direction; } @@ -679,6 +774,10 @@ namespace etl ///\brief Integral division with rounding to half odd. /// For signed integral types. /// For different parameter types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half odd. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -687,34 +786,37 @@ namespace etl etl::is_signed::value && etl::is_signed::value, typename etl::common_type::type>::type - divide_round_half_odd(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_odd(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_odd(static_cast(num), static_cast(den)); + return divide_round_half_odd(static_cast(numerator), static_cast(denominator)); } //*************************************************************************** ///\brief Integral division with rounding to half odd. /// For unsigned integral types. /// For identical argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half odd. //*************************************************************************** template ETL_CONSTEXPR14 typename etl::enable_if::value && etl::is_unsigned::value, T>::type - divide_round_half_odd(T num, T den) ETL_NOEXCEPT + divide_round_half_odd(T numerator, T denominator) ETL_NOEXCEPT { - const T quotient = num / den; - const T remainder = num % den; - const T direction = ((num >= 0U) == (den >= 0U)) ? 1 : -1; + const T quotient = numerator / denominator; + const T remainder = numerator % denominator; + const T direction = ((numerator >= 0U) == (denominator >= 0U)) ? 1 : -1; - if ((remainder * 2U) < den) + if ((remainder * 2U) < denominator) { return quotient; } - else if ((remainder * 2U) > den) + else if ((remainder * 2U) > denominator) { return quotient + direction; } @@ -729,6 +831,10 @@ namespace etl ///\brief Integral division with rounding to half odd. /// For unsigned integral types. /// For different argument types. + ///\param numerator The numerator. + ///\param denominator The denominator. + ///\return The result of the division rounded to half odd. + /// Return type is the etl::common_type::type. //*************************************************************************** template ETL_CONSTEXPR14 @@ -737,11 +843,11 @@ namespace etl etl::is_unsigned::value && etl::is_unsigned::value, typename etl::common_type::type>::type - divide_round_half_odd(T1 num, T2 den) ETL_NOEXCEPT + divide_round_half_odd(T1 numerator, T2 denominator) ETL_NOEXCEPT { typedef typename etl::common_type::type type; - return divide_round_half_odd(static_cast(num), static_cast(den)); + return divide_round_half_odd(static_cast(numerator), static_cast(denominator)); } } diff --git a/support/Release notes.txt b/support/Release notes.txt index 120bffe6..b15a0039 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -12,6 +12,7 @@ Made invocation of delegate consrexpr for C++14 #1132 Request: Make type_def Methods Noexcept #1054 Using #pragma once #1159 etl::fsm helper to check states id sequence at compile time +#1160 Feature request: rounded division (similar to scaled rounding) Fixes: Fix gamma tests (removed integral tests) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0acc4c26..a60856f7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -267,6 +267,7 @@ add_executable(etl_tests test_rescale.cpp test_result.cpp test_rms.cpp + test_rounded_integral_division.cpp test_scaled_rounding.cpp test_set.cpp test_shared_message.cpp diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index ce7fbbdf..5449ae35 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3698,6 +3698,9 @@ Tests\Callbacks & Delegates + + Tests\Maths +