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