/* ((val & bits) == bits) is uncommon */
#define HAS_ALL_BITS(val,bits) ((~(val) & (bits)) == 0)
+/* negation implemented without using the subtraction operator
+ ~(x - 1) = 1 + ~x these are equivalent by -(-x) == ~(~(x)) == x */
+#define UNSIGNED_MINUS(x) (1 + ~(x))
+
/* Returns x, such that x is the smallest power of 2 >= num. */
size_t nearest_power(size_t num) ATTR_CONST;
{
const unsigned int mask = CHAR_BIT*sizeof(num) - 1;
count &= mask;
- return (num << count) | (num >> (-count & mask));
+ return (num << count) | (num >> (UNSIGNED_MINUS(count) & mask));
}
static inline uint32_t ATTR_NO_SANITIZE_INTEGER
{
const unsigned int mask = CHAR_BIT*sizeof(num) - 1;
count &= mask;
- return (num << count) | (num >> (-count & mask));
+ return (num << count) | (num >> (UNSIGNED_MINUS(count) & mask));
}
static inline uint64_t ATTR_NO_SANITIZE_INTEGER
{
const unsigned int mask = CHAR_BIT*sizeof(num) - 1;
count &= mask;
- return (num >> count) | (num << (-count & mask));
+ return (num >> count) | (num << (UNSIGNED_MINUS(count) & mask));
}
static inline uint32_t ATTR_NO_SANITIZE_INTEGER
{
const unsigned int mask = CHAR_BIT*sizeof(num) - 1;
count &= mask;
- return (num >> count) | (num << (-count & mask));
+ return (num >> count) | (num << (UNSIGNED_MINUS(count) & mask));
}
/* These functions look too big to be inline, but in almost all expected
#include <stdio.h>
+static void test_bits_unsigned_minus(void)
+{
+ test_begin("bits_unsigned_minus()");
+
+ // 32 bit
+ test_assert(UNSIGNED_MINUS(0x00000000U) == 0x00000000U);
+
+ test_assert(UNSIGNED_MINUS(0x00000001U) == 0xffffffffU);
+ test_assert(UNSIGNED_MINUS(0x00000002U) == 0xfffffffeU);
+ test_assert(UNSIGNED_MINUS(0x00000003U) == 0xfffffffdU);
+ //..
+ test_assert(UNSIGNED_MINUS(0x7fffffffU) == 0x80000001U);
+ test_assert(UNSIGNED_MINUS(0x80000000U) == 0x80000000U);
+ test_assert(UNSIGNED_MINUS(0x80000001U) == 0x7fffffffU);
+ //..
+ test_assert(UNSIGNED_MINUS(0xffffffffU) == 0x00000001U);
+ test_assert(UNSIGNED_MINUS(0xfffffffeU) == 0x00000002U);
+ test_assert(UNSIGNED_MINUS(0xfffffffdU) == 0x00000003U);
+
+ // 64 bit
+ test_assert(UNSIGNED_MINUS(0x0000000000000000ULL) == 0x0000000000000000ULL);
+
+ test_assert(UNSIGNED_MINUS(0x0000000000000001ULL) == 0xffffffffffffffffULL);
+ test_assert(UNSIGNED_MINUS(0x0000000000000002ULL) == 0xfffffffffffffffeULL);
+ test_assert(UNSIGNED_MINUS(0x0000000000000003ULL) == 0xfffffffffffffffdULL);
+ //..
+ test_assert(UNSIGNED_MINUS(0x7fffffffffffffffULL) == 0x8000000000000001ULL);
+ test_assert(UNSIGNED_MINUS(0x8000000000000000ULL) == 0x8000000000000000ULL);
+ test_assert(UNSIGNED_MINUS(0x8000000000000001ULL) == 0x7fffffffffffffffULL);
+ //..
+ test_assert(UNSIGNED_MINUS(0xffffffffffffffffULL) == 0x0000000000000001ULL);
+ test_assert(UNSIGNED_MINUS(0xfffffffffffffffeULL) == 0x0000000000000002ULL);
+ test_assert(UNSIGNED_MINUS(0xfffffffffffffffdULL) == 0x0000000000000003ULL);
+
+ test_end();
+}
+
+
/* nearest_power(0) = error bits_requiredXX(0) = 0
nearest_power(1) = 1 = 1<<0 bits_requiredXX(1) = 1
nearest_power(2) = 2 = 1<<1 bits_requiredXX(2) = 2
test_assert(bits_rotl32(0x1c00000eU, 3) == 0xe0000070U);
test_assert(bits_rotl32(0xe0000070U, 5) == 0x00000e1cU);
test_assert(bits_rotl32(0x00000e1cU, 0) == 0x00000e1cU);
+ test_assert(bits_rotl32(0x1c00000eU, 3 + 32) == 0xe0000070U);
test_end();
}
test_assert(bits_rotl64(0x1c0000000000000eUL, 3) == 0xe000000000000070UL);
test_assert(bits_rotl64(0xe000000000000070UL, 5) == 0x0000000000000e1cUL);
test_assert(bits_rotl64(0x0000000000000e1cUL, 0) == 0x0000000000000e1cUL);
+ test_assert(bits_rotl64(0x1c0000000000000eUL, 3 + 64) == 0xe000000000000070UL);
test_end();
}
test_assert(bits_rotr32(0x1c00000eU, 3) == 0xc3800001U);
test_assert(bits_rotr32(0xc3800001U, 5) == 0x0e1c0000U);
test_assert(bits_rotr32(0x00000e1cU, 0) == 0x00000e1cU);
+ test_assert(bits_rotr32(0x1c00000eU, 3 + 32) == 0xc3800001U);
test_end();
}
test_assert(bits_rotr64(0x1c0000000000000eUL, 3) == 0xc380000000000001UL);
test_assert(bits_rotr64(0xc380000000000001UL, 5) == 0x0e1c000000000000UL);
test_assert(bits_rotr64(0x0000000000000e1cUL, 0) == 0x0000000000000e1cUL);
+ test_assert(bits_rotr64(0x1c0000000000000eUL, 3 + 64) == 0xc380000000000001UL);
test_end();
}
void test_bits(void)
{
+ test_bits_unsigned_minus();
test_nearest_power();
test_bits_is_power_of_two();
test_bits_requiredXX();