Mercurial > libjeffpc
changeset 795:952b4ab949eb
int: add is_p2 function to check if an integer is a power of two
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sat, 28 Mar 2020 10:36:52 -0400 |
parents | d018af7c979c |
children | cf1cd2707dfb |
files | include/jeffpc/int.h tests/.hgignore tests/CMakeLists.txt tests/test_is_p2.c |
diffstat | 4 files changed, 94 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/include/jeffpc/int.h Sun Mar 15 15:52:09 2020 +0200 +++ b/include/jeffpc/int.h Sat Mar 28 10:36:52 2020 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2016-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,7 @@ #include <stdint.h> #include <stddef.h> #include <stdlib.h> +#include <stdbool.h> #include <errno.h> #include <jeffpc/config.h> @@ -108,6 +109,15 @@ #define str2u8(s, i) str2u8_full((s), (i), 10, '\0') /* + * Powers of 2 mangling + */ +/* is the value a power of two? */ +static inline bool is_p2(uint64_t val) +{ + return !(val & (val - 1)); +} + +/* * These prototypes exist to catch bugs in the code generating macros below. */ /* return byte swapped input */
--- a/tests/.hgignore Sun Mar 15 15:52:09 2020 +0200 +++ b/tests/.hgignore Sat Mar 28 10:36:52 2020 -0400 @@ -14,6 +14,7 @@ test_endian test_errno test_hexdump +test_is_p2 test_list test_mutex-destroy-held test_mutex-destroy-memcpy
--- a/tests/CMakeLists.txt Sun Mar 15 15:52:09 2020 +0200 +++ b/tests/CMakeLists.txt Sat Mar 28 10:36:52 2020 -0400 @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> +# Copyright (c) 2016-2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -40,6 +40,7 @@ build_test_bin_and_run(endian) build_test_bin_and_run(errno) build_test_bin_and_run(hexdump) +build_test_bin_and_run(is_p2) build_test_bin_and_run(list) build_test_bin_and_run(mutex-destroy-memcpy) build_test_bin_and_run(mutex-destroy-null)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test_is_p2.c Sat Mar 28 10:36:52 2020 -0400 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <jeffpc/int.h> + +#include "test.c" + +#define CHECK(name, idx, _val, exp) \ + do { \ + const uint64_t v = (_val); \ + \ + fprintf(stderr, "%s: %2d: is_p2(%#018"PRIx64")...", \ + (name), (idx), v); \ + \ + if (is_p2(v) != (exp)) \ + fail("expected %s, got %s", \ + (exp) ? "true" : "false", \ + (exp) ? "false" : "true"); \ + \ + fprintf(stderr, "ok.\n"); \ + } while (0) + +static void test_powers(void) +{ + int i; + + CHECK("powers", 0, 0ul, true); + + for (i = 0; i < 64; i++) + CHECK("powers", i + 1, 1ull << i, true); +} + +static void test_nonpowers(void) +{ + int i; + + /* + * There are many non-powers, so we cannot test them all. + * Therefore, we check only a subset. + */ + + /* all powers of two + 1 */ + for (i = 0; i < 64; i++) { + const uint64_t val = (1ull << i) + 1; + + CHECK("p2+1", i + 1, val, val <= 2); + } + + /* all powers of two - 1 */ + for (i = 0; i < 64; i++) { + const uint64_t val = (1ull << i) - 1; + + CHECK("p2-1", i + 1, val, val <= 2); + } +} + +void test(void) +{ + test_powers(); + test_nonpowers(); +}