#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__)
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);