Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions include/zephyr/sys/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,81 @@
return cnt;
}

/**
* @brief Returns the sign of a number.
*
* @param x The input value to determine the sign
*
* @retval 1 if x is positive
* @retval -1 if x is negative
* @retval 0 if x is zero
*/
#define SIGN(x) (((x) > 0) - ((x) < 0))

/**
* @brief Compute the Greatest Common Divisor (GCD) of two integers
* using the Euclidean algorithm.
*
* @param a First integer
* @param b Second integer
*
* @return The greatest common divisor of a and b, always returns an unsigned value.
* If one of the parameters is 0, returns the absolute value of the other parameter.
*/
#define gcd(a, b) ((((__typeof__(a))-1) < 0) ? gcd_s(a, b) : gcd_u(a, b))

static ALWAYS_INLINE uint32_t gcd_u(uint32_t a, uint32_t b)
{
uint32_t c;

if (a == 0) {
return b;
}

if (b == 0) {
return a;
}

c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}

return b;
}

static ALWAYS_INLINE uint32_t gcd_s(int32_t a, int32_t b)
{
return gcd_u(a < 0 ? -(uint32_t)a : (uint32_t)a, b < 0 ? -(uint32_t)b : (uint32_t)b);

Check warning on line 1077 in include/zephyr/sys/util.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unary minus operator or change the expression's underlying type.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa0LOpBzk1Md8j0n&open=AZrqLa0LOpBzk1Md8j0n&pullRequest=98875

Check warning on line 1077 in include/zephyr/sys/util.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unary minus operator or change the expression's underlying type.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa0MOpBzk1Md8j0o&open=AZrqLa0MOpBzk1Md8j0o&pullRequest=98875
}

/**
* @brief Compute the Least Common Multiple (LCM) of two integers.
*
* @param a First integer
* @param b Second integer
*
* @retval The least common multiple of a and b.
* @retval 0 if either input is 0.
*/
#define lcm(a, b) ((((__typeof__(a))-1) < 0) ? lcm_s(a, b) : lcm_u(a, b))

static ALWAYS_INLINE uint64_t lcm_u(uint32_t a, uint32_t b)
{
if (a == 0 || b == 0) {
return 0;
}

return (uint64_t)(a / gcd_u(a, b)) * (uint64_t)b;
}

static ALWAYS_INLINE uint64_t lcm_s(int32_t a, int32_t b)
{
return lcm_u(a < 0 ? -(uint32_t)a : (uint32_t)a, b < 0 ? -(uint32_t)b : (uint32_t)b);

Check warning on line 1102 in include/zephyr/sys/util.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unary minus operator or change the expression's underlying type.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa0MOpBzk1Md8j0q&open=AZrqLa0MOpBzk1Md8j0q&pullRequest=98875

Check warning on line 1102 in include/zephyr/sys/util.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unary minus operator or change the expression's underlying type.

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa0MOpBzk1Md8j0p&open=AZrqLa0MOpBzk1Md8j0p&pullRequest=98875
}

#ifdef __cplusplus
}
#endif
Expand Down
65 changes: 65 additions & 0 deletions tests/unit/util/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,25 +253,25 @@
/* C++ has its own std::min() and std::max(), min and max are not available. */
ztest_test_skip();
#else
zassert_equal(max(inc_func(true), 0), 1, "Unexpected macro result");

Check warning on line 256 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0r&open=AZrqLa5hOpBzk1Md8j0r&pullRequest=98875
/* max should have call inc_func only once */
zassert_equal(inc_func(false), 2, "Unexpected return value");

zassert_equal(min(inc_func(false), 2), 2, "Unexpected macro result");

Check warning on line 260 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0s&open=AZrqLa5hOpBzk1Md8j0s&pullRequest=98875
/* min should have call inc_func only once */
zassert_equal(inc_func(false), 4, "Unexpected return value");

zassert_equal(clamp(inc_func(false), 1, 3), 3, "Unexpected macro result");

Check warning on line 264 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0t&open=AZrqLa5hOpBzk1Md8j0t&pullRequest=98875
/* clamp should have call inc_func only once */
zassert_equal(inc_func(false), 6, "Unexpected return value");

zassert_equal(clamp(inc_func(false), 10, 15), 10,

Check warning on line 268 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0u&open=AZrqLa5hOpBzk1Md8j0u&pullRequest=98875
"Unexpected macro result");
/* clamp should have call inc_func only once */
zassert_equal(inc_func(false), 8, "Unexpected return value");

/* Nested calls do not generate build warnings */
zassert_equal(max(inc_func(false),

Check warning on line 274 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0v&open=AZrqLa5hOpBzk1Md8j0v&pullRequest=98875
max(inc_func(false),
min(inc_func(false),
inc_func(false)))), 11, "Unexpected macro result");
Expand All @@ -281,22 +281,22 @@

ZTEST(util, test_max3_min3) {
/* check for single call */
zassert_equal(max3(inc_func(true), 0, 0), 1, "Unexpected macro result");

Check warning on line 284 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0w&open=AZrqLa5hOpBzk1Md8j0w&pullRequest=98875
zassert_equal(inc_func(false), 2, "Unexpected return value");

zassert_equal(min3(inc_func(false), 9, 10), 3, "Unexpected macro result");

Check warning on line 287 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0x&open=AZrqLa5hOpBzk1Md8j0x&pullRequest=98875
zassert_equal(inc_func(false), 4, "Unexpected return value");

/* test the general functionality */
zassert_equal(max3(1, 2, 3), 3, "Unexpected macro result");

Check warning on line 291 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0y&open=AZrqLa5hOpBzk1Md8j0y&pullRequest=98875
zassert_equal(max3(3, 1, 2), 3, "Unexpected macro result");

Check warning on line 292 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j0z&open=AZrqLa5hOpBzk1Md8j0z&pullRequest=98875
zassert_equal(max3(2, 3, 1), 3, "Unexpected macro result");

Check warning on line 293 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j00&open=AZrqLa5hOpBzk1Md8j00&pullRequest=98875
zassert_equal(max3(-1, 0, 1), 1, "Unexpected macro result");

Check warning on line 294 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j01&open=AZrqLa5hOpBzk1Md8j01&pullRequest=98875

zassert_equal(min3(1, 2, 3), 1, "Unexpected macro result");

Check warning on line 296 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j02&open=AZrqLa5hOpBzk1Md8j02&pullRequest=98875
zassert_equal(min3(3, 1, 2), 1, "Unexpected macro result");

Check warning on line 297 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j03&open=AZrqLa5hOpBzk1Md8j03&pullRequest=98875
zassert_equal(min3(2, 3, 1), 1, "Unexpected macro result");

Check warning on line 298 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j04&open=AZrqLa5hOpBzk1Md8j04&pullRequest=98875
zassert_equal(min3(-1, 0, 1), -1, "Unexpected macro result");

Check warning on line 299 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j05&open=AZrqLa5hOpBzk1Md8j05&pullRequest=98875
}

ZTEST(util, test_max_from_list_macro) {
Expand Down Expand Up @@ -615,7 +615,7 @@
size_t array[] = {0, 1, 2, 3};

for (i = 0; i < ARRAY_SIZE(array); ++i) {
zassert_equal(array[ARRAY_INDEX(array, &array[i])], i);

Check warning on line 618 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j06&open=AZrqLa5hOpBzk1Md8j06&pullRequest=98875
}
}

Expand Down Expand Up @@ -673,10 +673,10 @@
uint8_t *const alias = (uint8_t *)array;

for (i = 0; i < ARRAY_SIZE(array); ++i) {
zassert_equal(array[ARRAY_INDEX_FLOOR(array, &array[i])], i);

Check warning on line 676 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j07&open=AZrqLa5hOpBzk1Md8j07&pullRequest=98875
}

zassert_equal(array[ARRAY_INDEX_FLOOR(array, &alias[1])], 0);

Check warning on line 679 in tests/unit/util/main.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

use of GNU statement expression extension from macro expansion

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZrqLa5hOpBzk1Md8j08&open=AZrqLa5hOpBzk1Md8j08&pullRequest=98875
}

ZTEST(util, test_BIT_MASK)
Expand Down Expand Up @@ -1209,4 +1209,69 @@
test_single_bitmask_find_gap(0x0000000F, 2, 6, false, 4, __LINE__);
}

ZTEST(util, test_gcd)
{
/* Zero cases */
zassert_equal(gcd(0, 0), 0, "should be 0");
zassert_equal(gcd(0, INT_MAX), INT_MAX, "should be 0");
zassert_equal(gcd(INT_MAX, 0), INT_MAX, "should be 0");

/* Normal cases */
zassert_equal(gcd(12, 8), 4, "should be 4");

/* Negative number cases */
zassert_equal(gcd(-12, 8), 4, "should be 4");
zassert_equal(gcd(-12, -8), 4, "should be 4");

/* Prime numbers */
zassert_equal(gcd(17, 13), 1, "should be 1");
zassert_equal(gcd(25, 49), 1, "should be 1");

/* Boundary values */
zassert_equal(gcd(INT_MAX, INT_MAX), INT_MAX, "should be INT_MAX");
zassert_equal(gcd(INT_MIN, INT_MIN), (uint32_t)(-(int64_t)INT_MIN),
"should be INT_MAX + 1");
zassert_equal(gcd(INT_MIN, INT_MAX), 1, "should be 1");
zassert_equal(gcd(UINT32_MAX, UINT32_MAX), UINT32_MAX, "should be UINT32_MAX");

/* Macro expansion */
int a = 12, b = 8;

zassert_equal(gcd(a++, b++), 4, "should be 4");
zassert_equal(a, 13, "should be 13");
zassert_equal(b, 9, "should be 9");
}

ZTEST(util, test_lcm)
{
/* Zero cases - lcm with 0 should be 0 */
zassert_equal(lcm(0, 0), 0, "should be 0");
zassert_equal(lcm(0, INT_MAX), 0, "should be 0");

/* Normal cases */
zassert_equal(lcm(12, 8), 24, "should be 24");
zassert_equal(lcm(8, 12), 24, "should be 24");

/* Negative number cases - lcm should always be positive */
zassert_equal(lcm(-12, 8), 24, "should be 24");

/* Prime numbers (gcd = 1, so lcm = a * b) */
zassert_equal(lcm(17, 13), 221, "should be 221");

/* Boundary values */
zassert_equal(lcm(INT_MAX, INT_MAX - 1), (uint64_t)INT_MAX * (INT_MAX - 1),
"should be INT_MAX * (INT_MAX - 1)");
zassert_equal(lcm(INT_MIN, INT_MIN), (uint64_t)INT_MAX + 1, "should be INT_MAX + 1");
zassert_equal(lcm(INT_MIN, INT_MAX), (uint64_t)INT_MAX * (uint64_t)(-(int64_t)INT_MIN),
"should be INT_MAX * (INT_MAX + 1)");
zassert_equal(lcm(UINT32_MAX, UINT32_MAX), UINT32_MAX, "should be UINT32_MAX");

/* Macro expansion */
int a = 12, b = 8;

zassert_equal(lcm(a++, b++), 24, "should be 4");
zassert_equal(a, 13, "should be 13");
zassert_equal(b, 9, "should be 9");
}

ZTEST_SUITE(util, NULL, NULL, NULL, NULL, NULL);
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ manifest:
groups:
- hal
- name: hal_stm32
revision: 286dd285b5bb4fddafdfff27b5405264e5a61bfe
revision: 2c18f2b49d66d23cabfbd20dd7dbbaef8ee9520b
path: modules/hal/stm32
groups:
- hal
Expand Down