include: util: Add DIV_ROUND_CLOSEST helper

It's similar to DIV_ROUND_UP, but rounds to the nearest integer.
Some basic unit tests were introduced to check that it works as
intended.

Signed-off-by: Kornel Dulęba <mindal@semihalf.com>
This commit is contained in:
Kornel Dulęba 2023-07-17 08:36:52 +00:00 committed by Fabio Baltieri
commit 8fc913374f
3 changed files with 42 additions and 0 deletions

View file

@ -259,6 +259,25 @@ extern "C" {
*/
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
/**
* @brief Divide and round to the nearest integer.
*
* Example:
* @code{.c}
* DIV_ROUND_CLOSEST(5, 2); // 3
* DIV_ROUND_CLOSEST(5, -2); // -3
* DIV_ROUND_CLOSEST(5, 3); // 2
* @endcode
*
* @param n Numerator.
* @param d Denominator.
*
* @return The result of @p n / @p d, rounded to the nearest integer.
*/
#define DIV_ROUND_CLOSEST(n, d) \
((((n) < 0) ^ ((d) < 0)) ? ((n) - ((d) / 2)) / (d) : \
((n) + ((d) / 2)) / (d))
/**
* @brief Ceiling function applied to @p numerator / @p divider as a fraction.
* @deprecated Use DIV_ROUND_UP() instead.

View file

@ -151,6 +151,11 @@ ZTEST(util_cxx, test_DIV_ROUND_UP)
run_DIV_ROUND_UP();
}
ZTEST(util_cxx, test_DIV_ROUND_CLOSEST)
{
run_DIV_ROUND_CLOSEST();
}
ZTEST_SUITE(util_cxx, NULL, NULL, NULL, NULL, NULL);
#if __cplusplus
@ -294,4 +299,9 @@ ZTEST(util_cc, test_DIV_ROUND_UP)
run_DIV_ROUND_UP();
}
ZTEST(util_cc, test_DIV_ROUND_CLOSEST)
{
run_DIV_ROUND_CLOSEST();
}
ZTEST_SUITE(util_cc, NULL, NULL, NULL, NULL, NULL);

View file

@ -615,3 +615,16 @@ void run_DIV_ROUND_UP(void)
zassert_equal(DIV_ROUND_UP(1, 2), 1);
zassert_equal(DIV_ROUND_UP(3, 2), 2);
}
void run_DIV_ROUND_CLOSEST(void)
{
zassert_equal(DIV_ROUND_CLOSEST(0, 1), 0);
/* 5 / 2 = 2.5 -> 3 */
zassert_equal(DIV_ROUND_CLOSEST(5, 2), 3);
zassert_equal(DIV_ROUND_CLOSEST(5, -2), -3);
zassert_equal(DIV_ROUND_CLOSEST(-5, 2), -3);
zassert_equal(DIV_ROUND_CLOSEST(-5, -2), 3);
/* 7 / 3 = 2.(3) -> 2 */
zassert_equal(DIV_ROUND_CLOSEST(7, 3), 2);
zassert_equal(DIV_ROUND_CLOSEST(-7, 3), -2);
}