]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
macro: add macro for checking if integer is power of 2
authorLennart Poettering <lennart@poettering.net>
Fri, 5 Aug 2022 11:16:27 +0000 (13:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 5 Aug 2022 11:34:11 +0000 (13:34 +0200)
src/fundamental/macro-fundamental.h
src/test/test-macro.c

index e5f6dc7f8c1c2d605efffaf0707c96b3dccea874..5c67d3e2f79711ecf6a93f2aacb6df7d79cc6870 100644 (file)
                 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)                         \
         ({                                              \
index c39f64b385edfb7995e05fd1c219b9ccd71f524a..049ea2c14e1d3d39230df0a83f66528c6cf8302c 100644 (file)
@@ -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);