|
26 | 26 | #include <zephyr/types.h>
|
27 | 27 | #include <stddef.h>
|
28 | 28 |
|
| 29 | +/** @brief Number of bits that make up a type */ |
| 30 | +#define NUM_BITS(t) (sizeof(t) * 8) |
| 31 | + |
| 32 | +#ifdef __cplusplus |
| 33 | +template <typename T> static inline constexpr int __z_log2_impl(T x) |
| 34 | +{ |
| 35 | + if (sizeof(x) < sizeof(unsigned int)) { |
| 36 | + return ((x) < 1) * (-1) + |
| 37 | + ((x) >= 1) * (NUM_BITS(unsigned int) - __builtin_clz(x) - 1); |
| 38 | + } else if (sizeof(x) <= sizeof(unsigned long long)) { |
| 39 | + return ((x) < 1) * (-1) + |
| 40 | + ((x) >= 1) * (NUM_BITS(unsigned long long) - __builtin_clzll(x) - 1); |
| 41 | + } |
| 42 | + |
| 43 | + /* No declaration of __ASSERT is available here */ |
| 44 | + static_assert(sizeof(x) <= sizeof(unsigned long long), "unsupported type for LOG2()"); |
| 45 | + |
| 46 | + return -1; |
| 47 | +} |
| 48 | + |
| 49 | +template <typename T> static inline constexpr int __z_log2ceil_impl(T x) |
| 50 | +{ |
| 51 | + if (sizeof(x) < sizeof(unsigned int)) { |
| 52 | + return (x > 1) * (NUM_BITS(unsigned int) - __builtin_clz(x - 1)); |
| 53 | + } else if (sizeof(x) <= sizeof(unsigned long long)) { |
| 54 | + return (x > 1) * (NUM_BITS(unsigned long long) - __builtin_clzll(x - 1)); |
| 55 | + } |
| 56 | + |
| 57 | + /* No declaration of __ASSERT is available here */ |
| 58 | + static_assert(sizeof(x) <= sizeof(unsigned long long), "unsupported type for LOG2CEIL()"); |
| 59 | + |
| 60 | + return -1; |
| 61 | +} |
| 62 | + |
| 63 | +template <typename T> static inline constexpr uint64_t __z_nhpot_impl(T x) |
| 64 | +{ |
| 65 | + int l2c = __z_log2ceil_impl(x); |
| 66 | + |
| 67 | + return (l2c != NUM_BITS(unsigned long long)) * (1ULL << l2c); |
| 68 | +} |
| 69 | +#else |
| 70 | +#define __z_log2_impl(x) \ |
| 71 | + (((x) < 1) * (-1) + \ |
| 72 | + ((x) >= 1) * _Generic((x), char \ |
| 73 | + : (NUM_BITS(unsigned int) - __builtin_clz(x) - 1), unsigned char \ |
| 74 | + : (NUM_BITS(unsigned int) - __builtin_clz(x) - 1), short \ |
| 75 | + : (NUM_BITS(unsigned int) - __builtin_clz(x) - 1), unsigned short \ |
| 76 | + : (NUM_BITS(unsigned int) - __builtin_clz(x) - 1), int \ |
| 77 | + : (NUM_BITS(unsigned int) - __builtin_clz(x) - 1), unsigned int \ |
| 78 | + : (NUM_BITS(unsigned int) - __builtin_clz(x) - 1), long \ |
| 79 | + : (NUM_BITS(unsigned long) - __builtin_clzl(x) - 1), unsigned long \ |
| 80 | + : (NUM_BITS(unsigned long) - __builtin_clzl(x) - 1), long long \ |
| 81 | + : (NUM_BITS(unsigned long long) - __builtin_clzll(x) - 1), \ |
| 82 | + unsigned long long \ |
| 83 | + : (NUM_BITS(unsigned long long) - __builtin_clzll(x) - 1))) |
| 84 | + |
| 85 | +#define __z_log2ceil_impl(x) \ |
| 86 | + (((x) > 1) * \ |
| 87 | + _Generic((x), char \ |
| 88 | + : (NUM_BITS(unsigned int) - __builtin_clz((x)-1)), unsigned char \ |
| 89 | + : (NUM_BITS(unsigned int) - __builtin_clz((x)-1)), short \ |
| 90 | + : (NUM_BITS(unsigned int) - __builtin_clz((x)-1)), unsigned short \ |
| 91 | + : (NUM_BITS(unsigned int) - __builtin_clz((x)-1)), int \ |
| 92 | + : (NUM_BITS(unsigned int) - __builtin_clz((x)-1)), unsigned int \ |
| 93 | + : (NUM_BITS(unsigned int) - __builtin_clz((x)-1)), long \ |
| 94 | + : (NUM_BITS(unsigned long) - __builtin_clzl((x)-1)), unsigned long \ |
| 95 | + : (NUM_BITS(unsigned long) - __builtin_clzl((x)-1)), long long \ |
| 96 | + : (NUM_BITS(unsigned long long) - __builtin_clzll((x)-1)), unsigned long long \ |
| 97 | + : (NUM_BITS(unsigned long long) - __builtin_clzll((x)-1)))) |
| 98 | + |
| 99 | +#define __z_nhpot_impl(x) \ |
| 100 | + _Generic((x), char \ |
| 101 | + : (1UL << LOG2CEIL(x)), unsigned char \ |
| 102 | + : (1UL << LOG2CEIL(x)), short \ |
| 103 | + : (1UL << LOG2CEIL(x)), unsigned short \ |
| 104 | + : (1ULL << LOG2CEIL(x)), int \ |
| 105 | + : (1ULL << LOG2CEIL(x)), unsigned int \ |
| 106 | + : (1ULL << LOG2CEIL(x)), long \ |
| 107 | + : (1ULL << LOG2CEIL(x)), unsigned long \ |
| 108 | + : (1ULL << LOG2CEIL(x)), long long \ |
| 109 | + : (1ULL << LOG2CEIL(x)), unsigned long long \ |
| 110 | + : (1ULL << LOG2CEIL(x))) |
| 111 | +#endif |
| 112 | + |
29 | 113 | #ifdef __cplusplus
|
30 | 114 | extern "C" {
|
31 | 115 | #endif
|
@@ -314,7 +398,7 @@ extern "C" {
|
314 | 398 | */
|
315 | 399 | static inline bool is_power_of_two(unsigned int x)
|
316 | 400 | {
|
317 |
| - return (x != 0U) && ((x & (x - 1U)) == 0U); |
| 401 | + return IS_POWER_OF_TWO(x); |
318 | 402 | }
|
319 | 403 |
|
320 | 404 | /**
|
@@ -508,6 +592,35 @@ char *utf8_trunc(char *utf8_str);
|
508 | 592 | */
|
509 | 593 | char *utf8_lcpy(char *dst, const char *src, size_t n);
|
510 | 594 |
|
| 595 | +/** |
| 596 | + * @brief Compute log2(x) |
| 597 | + * |
| 598 | + * @param x An unsigned integral value |
| 599 | + * |
| 600 | + * @param x value to compute logarithm of (positive only) |
| 601 | + * |
| 602 | + * @return log2(x) when 1 <= x <= max(x), -1 when x < 1 |
| 603 | + */ |
| 604 | +#define LOG2(x) __z_log2_impl(x) |
| 605 | + |
| 606 | +/** |
| 607 | + * @brief Compute ceil(log2(x)) |
| 608 | + * |
| 609 | + * @param x An unsigned integral value |
| 610 | + * |
| 611 | + * @return ceil(log2(x)) when 1 <= x <= max(type(x)), 0 when x < 1 |
| 612 | + */ |
| 613 | +#define LOG2CEIL(x) __z_log2ceil_impl(x) |
| 614 | + |
| 615 | +/** |
| 616 | + * @brief Compute 2^ceil(log2(x)) |
| 617 | + * |
| 618 | + * @param x An unsigned integral value |
| 619 | + * |
| 620 | + * @return 2^ceil(log2(x)) or 0 if 2^ceil(log2(x)) would saturate 64-bits |
| 621 | + */ |
| 622 | +#define NHPOT(x) __z_nhpot_impl(x) |
| 623 | + |
511 | 624 | #ifdef __cplusplus
|
512 | 625 | }
|
513 | 626 | #endif
|
@@ -548,7 +661,7 @@ char *utf8_lcpy(char *dst, const char *src, size_t n);
|
548 | 661 | */
|
549 | 662 | #define WAIT_FOR(expr, timeout, delay_stmt) \
|
550 | 663 | ({ \
|
551 |
| - uint32_t cycle_count = k_us_to_cyc_ceil32(timeout); \ |
| 664 | + uint32_t cycle_count = k_us_to_cyc_ceil32(timeout); \ |
552 | 665 | uint32_t start = k_cycle_get_32(); \
|
553 | 666 | while (!(expr) && (cycle_count > (k_cycle_get_32() - start))) { \
|
554 | 667 | delay_stmt; \
|
|
0 commit comments