diff --git a/src/core/common/bit_utils.cpp b/src/core/common/bit_utils.cpp index 508d5a8a0..41aafc72c 100644 --- a/src/core/common/bit_utils.cpp +++ b/src/core/common/bit_utils.cpp @@ -79,4 +79,17 @@ exit: return matchedLen; } +uint8_t DetermineMinBitSizeFor(uint32_t aValue) +{ + uint8_t bitSize = 0; + + do + { + bitSize++; + aValue >>= 1; + } while (aValue != 0); + + return bitSize; +} + } // namespace ot diff --git a/src/core/common/bit_utils.hpp b/src/core/common/bit_utils.hpp index 9e0080807..9da52444a 100644 --- a/src/core/common/bit_utils.hpp +++ b/src/core/common/bit_utils.hpp @@ -102,6 +102,17 @@ template uint8_t CountBitsInMask(UintType aMask) */ uint16_t CountMatchingBits(const uint8_t *aFirst, const uint8_t *aSecond, uint16_t aMaxBitLength); +/** + * Determines the minimum number of bits required to represent a given integer value. + * + * @note For a value of `0`, this function returns `1`. + * + * @param[in] aValue The 32-bit unsigned integer value. + * + * @returns The minimum number of bits required to represent @p aValue. + */ +uint8_t DetermineMinBitSizeFor(uint32_t aValue); + /** * Sets the specified bit in a given integer to 1. * diff --git a/tests/unit/test_bit_utils.cpp b/tests/unit/test_bit_utils.cpp index a141a850f..4e32df927 100644 --- a/tests/unit/test_bit_utils.cpp +++ b/tests/unit/test_bit_utils.cpp @@ -130,6 +130,47 @@ void TestCountMatchingBitsExamples(void) printf("TestCountMatchingBitsExamples() passed\n"); } +void TestDetermineMinBitSize(void) +{ + VerifyOrQuit(DetermineMinBitSizeFor(0) == 1); + VerifyOrQuit(DetermineMinBitSizeFor(1) == 1); + + VerifyOrQuit(DetermineMinBitSizeFor(2) == 2); + VerifyOrQuit(DetermineMinBitSizeFor(3) == 2); + + VerifyOrQuit(DetermineMinBitSizeFor(4) == 3); + VerifyOrQuit(DetermineMinBitSizeFor(6) == 3); + VerifyOrQuit(DetermineMinBitSizeFor(7) == 3); + + VerifyOrQuit(DetermineMinBitSizeFor(8) == 4); + VerifyOrQuit(DetermineMinBitSizeFor(11) == 4); + VerifyOrQuit(DetermineMinBitSizeFor(15) == 4); + + VerifyOrQuit(DetermineMinBitSizeFor(16) == 5); + VerifyOrQuit(DetermineMinBitSizeFor(30) == 5); + VerifyOrQuit(DetermineMinBitSizeFor(32) == 6); + + VerifyOrQuit(DetermineMinBitSizeFor(127) == 7); + VerifyOrQuit(DetermineMinBitSizeFor(128) == 8); + VerifyOrQuit(DetermineMinBitSizeFor(255) == 8); + VerifyOrQuit(DetermineMinBitSizeFor(256) == 9); + VerifyOrQuit(DetermineMinBitSizeFor(500) == 9); + + VerifyOrQuit(DetermineMinBitSizeFor(1000) == 10); + VerifyOrQuit(DetermineMinBitSizeFor(1023) == 10); + VerifyOrQuit(DetermineMinBitSizeFor(1024) == 11); + VerifyOrQuit(DetermineMinBitSizeFor(2000) == 11); + + VerifyOrQuit(DetermineMinBitSizeFor(0xffff) == 16); + VerifyOrQuit(DetermineMinBitSizeFor(0x10000) == 17); + + VerifyOrQuit(DetermineMinBitSizeFor(0x7fffffff) == 31); + VerifyOrQuit(DetermineMinBitSizeFor(0x80000000) == 32); + VerifyOrQuit(DetermineMinBitSizeFor(0xffffffff) == 32); + + printf("TestDetermineMinBitSize() passed\n"); +} + } // namespace ot int main(void) @@ -137,6 +178,7 @@ int main(void) ot::TestCountBitsInMask(); ot::TestCountMatchingBitsAllCombinations(); ot::TestCountMatchingBitsExamples(); + ot::TestDetermineMinBitSize(); printf("All tests passed\n"); return 0;