11static_assert(__cpp_lib_bitops >= 201907L);
14static inline void clear_and_insert(uint32_t &dest, T value, uint32_t mask)
16 static_assert(std::is_integral_v<T>);
18 unsigned shift = std::countr_zero(mask);
19 uint32_t shifted_mask = mask >> shift;
23 if constexpr (std::is_signed_v<T>) {
24 typedef typename std::make_unsigned<T>::type U;
26 uint32_t umax = shifted_mask >> 1;
31 int64_t umin = shifted_mask ^ umax;
44 throw std::runtime_error(
"value " + std::to_string(value)
45 +
" less than min (" + std::to_string(min) +
")");
47 throw std::runtime_error(
"value " + std::to_string(value)
48 +
" greater than max (" + std::to_string(max) +
")");
50 dest &= UINT32_MAX & ~mask;
51 dest |= (uvalue << shift) & mask;
54static inline void insert_bit(uint32_t &dest,
bool value, uint32_t mask)
56 assert(std::popcount(mask) == 1);
63static inline bool get_bit(uint32_t value, uint32_t mask)
65 assert(std::popcount(mask) == 1);
69template <
typename Signed>
static inline int32_t sign_extend(uint32_t value)
71 typedef typename std::make_unsigned<Signed>::type Unsigned;
72 return (Signed)(Unsigned)value;
75static inline int32_t sign_extend(uint32_t value,
unsigned width)
79 return sign_extend<int8_t>(value);
81 return sign_extend<int16_t>(value);
83 return sign_extend<int32_t>(value);
85 throw std::logic_error(
86 "invalid width should have been caught elsewhere");
90static inline int32_t extract_value(
91 uint32_t value, uint32_t mask,
bool is_signed =
false)
93 unsigned shift = std::countr_zero(mask);
94 unsigned popcount = std::popcount(mask);
99 assert(popcount == 32 - shift - std::countl_zero(mask));
101 uint32_t intermediary = (value & mask) >> shift;
103 return sign_extend(intermediary, popcount);
111static inline T extract_value(uint32_t value, uint32_t mask)
113 return extract_value(value, mask, std::is_signed_v<T>);