diff --git a/core/bitarithm.c b/core/bitarithm.c index 8bff87707c3c..72a4cb386e87 100644 --- a/core/bitarithm.c +++ b/core/bitarithm.c @@ -15,36 +15,47 @@ * * @author Kaspar Schleiser * @author Martin Lenders - * @author René Kijewski * * @} */ #include -#include "bitarithm.h" - unsigned bitarithm_msb(unsigned v) { - if ((signed) v >= 0) { - v &= -v; - return bitarithm_lsb(v); - } - else { - return sizeof (v) * 8 - 1; + register unsigned r; // result of log2(v) will go here + +#if ARCH_32_BIT + register unsigned shift; + + r = (v > 0xFFFF) << 4; v >>= r; + shift = (v > 0xFF ) << 3; v >>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; + r |= (v >> 1); +#else + r = 0; + while (v >>= 1) { // unroll for more speed... + r++; } -} -unsigned bitarithm_lsb(unsigned v) +#endif + + return r; +} +/*---------------------------------------------------------------------------*/ +unsigned bitarithm_lsb(register unsigned v) { - unsigned r = 0; - while ((v & 1) == 0) { + register unsigned r = 0; + + while ((v & 0x01) == 0) { v >>= 1; r++; - } + }; + return r; } - +/*---------------------------------------------------------------------------*/ unsigned bitarithm_bits_set(unsigned v) { unsigned c; // c accumulates the total bits set in v diff --git a/tests/unittests/tests-core/tests-core-bitarithm.c b/tests/unittests/tests-core/tests-core-bitarithm.c index 788e6317dda9..a8cc7f2e0dda 100644 --- a/tests/unittests/tests-core/tests-core-bitarithm.c +++ b/tests/unittests/tests-core/tests-core-bitarithm.c @@ -7,6 +7,7 @@ */ #include +#include #include "embUnit/embUnit.h" @@ -153,14 +154,14 @@ static void test_bitarithm_msb_limit(void) static void test_bitarithm_msb_random(void) { - TEST_ASSERT_EQUAL_INT(2, bitarithm_msb(4)); /* randomized by fair + TEST_ASSERT_EQUAL_INT(4, bitarithm_msb(19)); /* randomized by fair dice roll ;-) */ } -static void test_bitarithm_msb_all(void) +static void test_bitarithm_msb_16bit(void) { - for (unsigned shift = 0; shift < sizeof(unsigned) * 8 - 1; ++shift) { - TEST_ASSERT_EQUAL_INT(shift, bitarithm_msb(1 << shift)); + for (unsigned i = 1; i < UINT16_MAX; i++) { + TEST_ASSERT_EQUAL_INT(((sizeof(unsigned) * 8) - __builtin_clz(i) - 1), bitarithm_msb(i)); } } @@ -177,14 +178,14 @@ static void test_bitarithm_lsb_limit(void) static void test_bitarithm_lsb_random(void) { - TEST_ASSERT_EQUAL_INT(3, bitarithm_lsb(8)); /* randomized by fair + TEST_ASSERT_EQUAL_INT(3, bitarithm_lsb(24)); /* randomized by fair dice roll ;-) */ } static void test_bitarithm_lsb_all(void) { - for (unsigned shift = 0; shift < sizeof(unsigned) * 8 - 1; ++shift) { - TEST_ASSERT_EQUAL_INT(shift, bitarithm_lsb(1u << shift)); + for (unsigned i = 1; i < UINT16_MAX; i++) { + TEST_ASSERT_EQUAL_INT(__builtin_ctz(i), bitarithm_lsb(i)); } } @@ -232,7 +233,7 @@ Test *tests_core_bitarithm_tests(void) new_TestFixture(test_bitarithm_msb_one), new_TestFixture(test_bitarithm_msb_limit), new_TestFixture(test_bitarithm_msb_random), - new_TestFixture(test_bitarithm_msb_all), + new_TestFixture(test_bitarithm_msb_16bit), new_TestFixture(test_bitarithm_lsb_one), new_TestFixture(test_bitarithm_lsb_limit),