#include <type_traits>
#include <limits>
constexpr bool native_asr = (-2 >> 1) == -1;
template <typename T>
constexpr inline typename std::make_signed<T>::type sign_extend_shift(const T value, const std::size_t shift) noexcept
{
return (value << shift) >> shift;
}
template <typename T>
constexpr inline typename std::make_signed<T>::type sign_extend_mask(const T value, const T mask) noexcept
{
return (value ^ mask) - mask;
}
template <typename T>
constexpr inline typename std::make_signed<T>::type sign_extend(const T value, const std::size_t bit_count) noexcept
{
return (native_asr)
? sign_extend_shift(value, std::numeric_limits<typename std::make_unsigned<T>::type>::digits - bit_count)
: sign_extend_mask<T>(value, static_cast<typename std::make_unsigned<T>::type>(1) << (bit_count - 1));
}
template <typename T>
constexpr inline T arithmetic_shift_right(const T value, const std::size_t shift) noexcept
{
return (native_asr)
? (value >> shift)
: sign_extend<T>(
static_cast<typename std::make_unsigned<T>::type>(value) >> shift,
std::numeric_limits<typename std::make_unsigned<T>::type>::digits - shift);
}
Comments
0 B
|👍
/👎