diff options
-rw-r--r-- | src/fundamental/macro-fundamental.h | 13 | ||||
-rw-r--r-- | src/test/test-macro.c | 56 |
2 files changed, 69 insertions, 0 deletions
diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index e5f6dc7f8c..5c67d3e2f7 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -200,6 +200,19 @@ MIN(_c, z); \ }) +/* Returns true if the passed integer is a positive power of two */ +#define CONST_ISPOWEROF2(x) \ + ((x) > 0 && ((x) & ((x) - 1)) == 0) + +#define ISPOWEROF2(x) \ + __builtin_choose_expr( \ + __builtin_constant_p(x), \ + CONST_ISPOWEROF2(x), \ + ({ \ + const typeof(x) _x = (x); \ + CONST_ISPOWEROF2(_x); \ + })) + #define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b)) #define __LESS_BY(aq, a, bq, b) \ ({ \ diff --git a/src/test/test-macro.c b/src/test/test-macro.c index c39f64b385..049ea2c14e 100644 --- a/src/test/test-macro.c +++ b/src/test/test-macro.c @@ -465,4 +465,60 @@ TEST(PTR_SUB1) { assert_se(!p); } +TEST(ISPOWEROF2) { + uint64_t u; + int64_t i; + + /* First, test constant expressions */ + assert_se(!ISPOWEROF2(-2)); + assert_se(!ISPOWEROF2(-1)); + assert_se(!ISPOWEROF2(0)); + assert_se(ISPOWEROF2(1)); + assert_se(ISPOWEROF2(2)); + assert_se(!ISPOWEROF2(3)); + assert_se(ISPOWEROF2(4)); + assert_se(!ISPOWEROF2(5)); + assert_se(!ISPOWEROF2(6)); + assert_se(!ISPOWEROF2(7)); + assert_se(ISPOWEROF2(8)); + assert_se(!ISPOWEROF2(9)); + assert_se(!ISPOWEROF2(1022)); + assert_se(ISPOWEROF2(1024)); + assert_se(!ISPOWEROF2(1025)); + assert_se(!ISPOWEROF2(UINT64_C(0xffffffff))); + assert_se(ISPOWEROF2(UINT64_C(0x100000000))); + assert_se(!ISPOWEROF2(UINT64_C(0x100000001))); + + /* Then, test dynamic expressions, and if they are side-effect free */ + i = -2; + assert_se(!ISPOWEROF2(i++)); + assert_se(i == -1); + assert_se(!ISPOWEROF2(i++)); + assert_se(i == 0); + assert_se(!ISPOWEROF2(i++)); + assert_se(i == 1); + assert_se(ISPOWEROF2(i++)); + assert_se(i == 2); + assert_se(ISPOWEROF2(i++)); + assert_se(i == 3); + assert_se(!ISPOWEROF2(i++)); + assert_se(i == 4); + assert_se(ISPOWEROF2(i++)); + assert_se(i == 5); + assert_se(!ISPOWEROF2(i)); + + u = 0; + assert_se(!ISPOWEROF2(u++)); + assert_se(u == 1); + assert_se(ISPOWEROF2(u++)); + assert_se(u == 2); + assert_se(ISPOWEROF2(u++)); + assert_se(u == 3); + assert_se(!ISPOWEROF2(u++)); + assert_se(u == 4); + assert_se(ISPOWEROF2(u++)); + assert_se(u == 5); + assert_se(!ISPOWEROF2(u)); +} + DEFINE_TEST_MAIN(LOG_INFO); |