Allow GetBitMaskSC to be used with mask size equal to type size

This commit is contained in:
Jonathan G Rennison 2024-06-19 01:17:07 +01:00
parent 0129b2c9d3
commit c76a7f4349
2 changed files with 18 additions and 7 deletions

View File

@ -11,6 +11,7 @@
#define BITMATH_FUNC_HPP #define BITMATH_FUNC_HPP
#include <bit> #include <bit>
#include <limits>
#include <type_traits> #include <type_traits>
/** /**
@ -192,14 +193,16 @@ constexpr T ToggleBit(T &x, const uint8_t y)
* *
* @param start The start bit * @param start The start bit
* @param count The number of bits * @param count The number of bits
* @pre start + count < sizeof(T) * 8
* @return The bit mask * @return The bit mask
*/ */
template <typename T> template <typename T>
constexpr T GetBitMaskSC(const uint8_t start, const uint8_t count) constexpr T GetBitMaskSC(const uint8_t start, const uint8_t count)
{ {
typename std::make_unsigned<T>::type mask = 1; using U = typename std::make_unsigned<T>::type;
return (T)(((mask << count) - 1) << start); constexpr uint BIT_WIDTH = std::numeric_limits<U>::digits;
U mask = ((static_cast<U>(1) << (count & (BIT_WIDTH - 1))) - 1) | (count >= BIT_WIDTH ? ~static_cast<U>(0) : 0);
return (T)(mask << start);
} }
/** /**

View File

@ -71,8 +71,12 @@ TEST_CASE("SetBitIterator tests")
TEST_CASE("GetBitMaskSC tests") TEST_CASE("GetBitMaskSC tests")
{ {
CHECK(GetBitMaskSC<uint>(4, 4) == 0xF0); CHECK(GetBitMaskSC<uint64_t>(36, 4) == 0xF000000000ULL);
CHECK(GetBitMaskSC<uint>(28, 4) == 0xF0000000); CHECK(GetBitMaskSC<uint64_t>(60, 4) == 0xF000000000000000ULL);
CHECK(GetBitMaskSC<uint64_t>(0, 64) == 0xFFFFFFFFFFFFFFFFULL);
CHECK(GetBitMaskSC<uint32_t>(4, 4) == 0xF0);
CHECK(GetBitMaskSC<uint32_t>(28, 4) == 0xF0000000);
CHECK(GetBitMaskSC<uint32_t>(0, 32) == 0xFFFFFFFF);
CHECK(GetBitMaskSC<uint8_t>(7, 1) == 0x80); CHECK(GetBitMaskSC<uint8_t>(7, 1) == 0x80);
CHECK(GetBitMaskSC<uint8_t>(0, 1) == 1); CHECK(GetBitMaskSC<uint8_t>(0, 1) == 1);
CHECK(GetBitMaskSC<uint8_t>(0, 0) == 0); CHECK(GetBitMaskSC<uint8_t>(0, 0) == 0);
@ -81,8 +85,12 @@ TEST_CASE("GetBitMaskSC tests")
TEST_CASE("GetBitMaskFL tests") TEST_CASE("GetBitMaskFL tests")
{ {
CHECK(GetBitMaskFL<uint>(4, 7) == 0xF0); CHECK(GetBitMaskFL<uint64_t>(36, 39) == 0xF000000000ULL);
CHECK(GetBitMaskFL<uint>(28, 31) == 0xF0000000); CHECK(GetBitMaskFL<uint64_t>(60, 63) == 0xF000000000000000ULL);
CHECK(GetBitMaskFL<uint64_t>(0, 63) == 0xFFFFFFFFFFFFFFFFULL);
CHECK(GetBitMaskFL<uint32_t>(4, 7) == 0xF0);
CHECK(GetBitMaskFL<uint32_t>(28, 31) == 0xF0000000);
CHECK(GetBitMaskFL<uint32_t>(0, 31) == 0xFFFFFFFF);
CHECK(GetBitMaskFL<uint8_t>(7, 7) == 0x80); CHECK(GetBitMaskFL<uint8_t>(7, 7) == 0x80);
CHECK(GetBitMaskFL<uint8_t>(0, 0) == 1); CHECK(GetBitMaskFL<uint8_t>(0, 0) == 1);
CHECK(GetBitMaskFL<uint8_t>(3, 4) == 0x18); CHECK(GetBitMaskFL<uint8_t>(3, 4) == 0x18);