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) +
" less than min (" + std::to_string(min) +
")");
46 throw std::runtime_error(
"value " + std::to_string(value) +
" greater than max (" + std::to_string(max) +
")");
48 dest &= UINT32_MAX & ~mask;
49 dest |= (uvalue << shift) & mask;
52static inline void insert_bit(uint32_t &dest,
bool value, uint32_t mask)
54 assert(std::popcount(mask) == 1);
61static inline bool get_bit(uint32_t value, uint32_t mask)
63 assert(std::popcount(mask) == 1);
67template<
typename Signed>
68static inline int32_t sign_extend(uint32_t value)
70 typedef typename std::make_unsigned<Signed>::type Unsigned;
71 return (Signed)(Unsigned)value;
74static inline int32_t sign_extend(uint32_t value,
unsigned width)
78 return sign_extend<int8_t>(value);
80 return sign_extend<int16_t>(value);
82 return sign_extend<int32_t>(value);
84 throw std::logic_error(
"invalid width should have been caught elsewhere");
88static inline int32_t extract_value(uint32_t value, uint32_t mask,
bool is_signed=
false)
90 unsigned shift = std::countr_zero(mask);
91 unsigned popcount = std::popcount(mask);
96 assert(popcount == 32 - shift - std::countl_zero(mask));
98 uint32_t intermediary = (value & mask) >> shift;
100 return sign_extend(intermediary, popcount);
108static inline T extract_value(uint32_t value, uint32_t mask)
110 return extract_value(value, mask, std::is_signed_v<T>);