// (bitStart < sizeof(T) * 8, bitStart + count <= sizeof(T) * 8)
static UnderlyingType innerGet(const T* p, size_t bitStart, size_t count);
+ static constexpr UnderlyingType zero = UnderlyingType(0);
static constexpr UnderlyingType one = UnderlyingType(1);
+
+ static constexpr UnderlyingType ones(size_t count) {
+ return count < bitsPerBlock ? (one << count) - 1 : ~zero;
+ }
};
template <class T, class Traits>
inline void Bits<T, Traits>::set(T* p, size_t bitStart, size_t count,
UnderlyingType value) {
assert(count <= sizeof(UnderlyingType) * 8);
- assert(count == sizeof(UnderlyingType) ||
- (value & ~((one << count) - 1)) == 0);
size_t idx = blockIndex(bitStart);
size_t offset = bitOffset(bitStart);
if (offset + count <= bitsPerBlock) {
UnderlyingType value) {
// Mask out bits and set new value
UnderlyingType v = Traits::loadRMW(*p);
- v &= ~(((one << count) - 1) << offset);
+ v &= ~(ones(count) << offset);
v |= (value << offset);
Traits::store(*p, v);
}
template <class T, class Traits>
inline auto Bits<T, Traits>::innerGet(const T* p, size_t offset, size_t count)
-> UnderlyingType {
- return (Traits::load(*p) >> offset) & ((one << count) - 1);
+ return (Traits::load(*p) >> offset) & ones(count);
}
template <class T, class Traits>
auto load = detail::BitsTraits<T>::load;
T buf[] = {0x123456789abcdef0, 0x13579bdf2468ace0};
+ EXPECT_EQ(0x123456789abcdef0, load(Bits<T>::get(buf, 0, 64)));
EXPECT_EQ(0xf0, load(Bits<T>::get(buf, 0, 8)));
EXPECT_EQ(0x89abcdef, load(Bits<T>::get(buf, 4, 32)));
EXPECT_EQ(0x189abcdef, load(Bits<T>::get(buf, 4, 33)));
EXPECT_EQ(0xd5555555, load(Bits<T>::get(buf, 4, 32)));
EXPECT_EQ(0x1d5555555, load(Bits<T>::get(buf, 4, 33)));
EXPECT_EQ(0xd55555550, load(Bits<T>::get(buf, 0, 36)));
+
+ Bits<T>::set(buf, 0, 64, 0x23456789abcdef01);
+ EXPECT_EQ(0x23456789abcdef01, load(Bits<T>::get(buf, 0, 64)));
}
TEST(Bits, MultiBit64) {