I need to shuffle a 16 bit unsigned integer in a way that the even indexes land in the lower byte, and the odd indexes land in the upper byte.
input:
fedcba9
Tables. But generate them at compile time!
namespace details {
constexpr uint8_t bit( unsigned byte, unsigned n ) {
return (byte>>n)&1;
}
constexpr uint8_t even_bits(uint8_t byte) {
return bit(byte, 0) | (bit(byte, 2)<<1) | (bit(byte, 4)<<2) | (bit(byte, 6)<<3);
}
constexpr uint8_t odd_bits(uint8_t byte) {
return even_bits(byte/2);
}
templatestruct indexes{using type=indexes;};
templatestruct make_indexes:make_indexes{};
templatestruct make_indexes<0,Is...>:indexes{};
templateusing make_indexes_t=typename make_indexes::type;
template
constexpr std::array< uint8_t, 256 > even_bit_table( indexes ) {
return { even_bits(Is)... };
}
template
constexpr std::array< uint8_t, 256 > odd_bit_table( indexes ) {
return { odd_bits(Is)... };
}
constexpr std::array< uint8_t, 256 > even_bit_table() {
return even_bit_table( make_indexes_t<256>{} );
}
constexpr std::array< uint8_t, 256 > odd_bit_table() {
return odd_bit_table( make_indexes_t<256>{} );
}
static constexpr auto etable = even_bit_table();
static constexpr auto otable = odd_bit_table();
}
uint8_t constexpr even_bits( uint16_t in ) {
return details::etable[(uint8_t)in] | ((details::etable[(uint8_t)(in>>8)])<<4);
}
uint8_t constexpr odd_bits( uint16_t in ) {
return details::otable[(uint8_t)in] | ((details::otable[(uint8_t)(in>>8)])<<4);
}
live example