]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-macro: add ROUND_UP() macro for rounding up to next multiple
authorLennart Poettering <lennart@poettering.net>
Fri, 2 Jun 2023 14:34:32 +0000 (16:34 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 2 Jun 2023 14:41:36 +0000 (16:41 +0200)
In case of overflow will return -1 cast to the first parameter type.

src/fundamental/macro-fundamental.h
src/test/test-macro.c

index e901e8fb596a2e0f49803002fe72b153cde8ae64..1d49765fce910a06f3bab8e9806607364f53f1cd 100644 (file)
 
 #define assert_cc(expr) static_assert(expr, #expr)
 
-
 #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
 #define UNIQ __COUNTER__
 
                 (UNIQ_T(X, xq) / UNIQ_T(Y, yq) + !!(UNIQ_T(X, xq) % UNIQ_T(Y, yq))); \
         })
 
+/* Rounds up x to the next multiple of y. Resolves to typeof(x) -1 in case of overflow */
+#define __ROUND_UP(q, x, y)                                             \
+        ({                                                              \
+                const typeof(y) UNIQ_T(A, q) = (y);                     \
+                const typeof(x) UNIQ_T(B, q) = DIV_ROUND_UP((x), UNIQ_T(A, q)); \
+                typeof(x) UNIQ_T(C, q);                                 \
+                __builtin_mul_overflow(UNIQ_T(B, q), UNIQ_T(A, q), &UNIQ_T(C, q)) ? (typeof(x)) -1 : UNIQ_T(C, q); \
+        })
+#define ROUND_UP(x, y) __ROUND_UP(UNIQ, (x), (y))
+
 #define  CASE_F_1(X)      case X:
 #define  CASE_F_2(X, ...) case X:  CASE_F_1( __VA_ARGS__)
 #define  CASE_F_3(X, ...) case X:  CASE_F_2( __VA_ARGS__)
index 637d6f1a49ab1135f79616d02f564ebf612fc5cd..810ebc580e7acb0d97b43b78ffa2fd6cf652d96e 100644 (file)
@@ -818,4 +818,70 @@ TEST(FOREACH_ARRAY) {
         assert_se(n == 0);
 }
 
+#define TEST_ROUND_UP_BY_TYPE(type, max_value)                          \
+        ({                                                              \
+                type x, y;                                              \
+                x = 0, y = 1;                                           \
+                assert_se(ROUND_UP(x, y) == 0);                         \
+                x = 0, y = 2;                                           \
+                assert_se(ROUND_UP(x, y) == 0);                         \
+                x = 0, y = 3;                                           \
+                assert_se(ROUND_UP(x, y) == 0);                         \
+                x = 0, y = 4;                                           \
+                assert_se(ROUND_UP(x, y) == 0);                         \
+                x = 1, y = 1;                                           \
+                assert_se(ROUND_UP(x, y) == 1);                         \
+                x = 1, y = 2;                                           \
+                assert_se(ROUND_UP(x, y) == 2);                         \
+                x = 1, y = 3;                                           \
+                assert_se(ROUND_UP(x, y) == 3);                         \
+                x = 1, y = 4;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = 2, y = 1;                                           \
+                assert_se(ROUND_UP(x, y) == 2);                         \
+                x = 2, y = 2;                                           \
+                assert_se(ROUND_UP(x, y) == 2);                         \
+                x = 2, y = 3;                                           \
+                assert_se(ROUND_UP(x, y) == 3);                         \
+                x = 2, y = 4;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = 3, y = 1;                                           \
+                assert_se(ROUND_UP(x, y) == 3);                         \
+                x = 3, y = 2;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = 3, y = 3;                                           \
+                assert_se(ROUND_UP(x, y) == 3);                         \
+                x = 3, y = 4;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = 4, y = 1;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = 4, y = 2;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = 4, y = 3;                                           \
+                assert_se(ROUND_UP(x, y) == 6);                         \
+                x = 4, y = 4;                                           \
+                assert_se(ROUND_UP(x, y) == 4);                         \
+                x = max_value, y = 1;                                   \
+                assert_se(ROUND_UP(x, y) == max_value);                 \
+                x = max_value, y = 2;                                   \
+                assert_se(ROUND_UP(x, y) == max_value);                 \
+                x = max_value, y = 3;                                   \
+                assert_se(ROUND_UP(x, y) == max_value);                 \
+                x = max_value, y = 4;                                   \
+                assert_se(ROUND_UP(x, y) == max_value);                 \
+                x = max_value-1, y = 1;                                 \
+                assert_se(ROUND_UP(x, y) == max_value-1);               \
+                x = max_value-1, y = 2;                                 \
+                assert_se(ROUND_UP(x, y) == max_value-1);               \
+                x = max_value-1, y = 4;                                 \
+                assert_se(ROUND_UP(x, y) == max_value);                 \
+        })
+
+TEST(round_up) {
+        TEST_ROUND_UP_BY_TYPE(uint8_t, UINT8_MAX);
+        TEST_ROUND_UP_BY_TYPE(uint16_t, UINT16_MAX);
+        TEST_ROUND_UP_BY_TYPE(uint32_t, UINT32_MAX);
+        TEST_ROUND_UP_BY_TYPE(uint64_t, UINT64_MAX);
+}
+
 DEFINE_TEST_MAIN(LOG_INFO);