Commit 8fc91337 authored by Kornel Dulęba's avatar Kornel Dulęba Committed by Fabio Baltieri
Browse files

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: default avatarKornel Dulęba <mindal@semihalf.com>
parent ecbaac60
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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.
+10 −0
Original line number Diff line number Diff line
@@ -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);
+13 −0
Original line number Diff line number Diff line
@@ -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);
}