mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-25 18:30:21 +00:00
63 lines
1.5 KiB
C++
63 lines
1.5 KiB
C++
|
//
|
||
|
// BitReverse.hpp
|
||
|
// Clock Signal
|
||
|
//
|
||
|
// Created by Thomas Harte on 05/01/2023.
|
||
|
// Copyright © 2023 Thomas Harte. All rights reserved.
|
||
|
//
|
||
|
|
||
|
#ifndef BitReverse_hpp
|
||
|
#define BitReverse_hpp
|
||
|
|
||
|
#include <cstdint>
|
||
|
|
||
|
namespace Numeric {
|
||
|
|
||
|
/// @returns @c source with the order of its bits reversed. E.g. if @c IntT is @c uint8_t then
|
||
|
/// the reverse of bit pattern abcd efgh is hgfd dcba.
|
||
|
template <typename IntT> constexpr IntT bit_reverse(IntT source);
|
||
|
|
||
|
// The single-byte specialisation uses a lookup table.
|
||
|
template<> constexpr uint8_t bit_reverse<uint8_t>(uint8_t source) {
|
||
|
struct ReverseTable {
|
||
|
static constexpr std::array<uint8_t, 256> reverse_table() {
|
||
|
std::array<uint8_t, 256> map{};
|
||
|
for(std::size_t c = 0; c < 256; ++c) {
|
||
|
map[c] = uint8_t(
|
||
|
((c & 0x80) >> 7) |
|
||
|
((c & 0x40) >> 5) |
|
||
|
((c & 0x20) >> 3) |
|
||
|
((c & 0x10) >> 1) |
|
||
|
((c & 0x08) << 1) |
|
||
|
((c & 0x04) << 3) |
|
||
|
((c & 0x02) << 5) |
|
||
|
((c & 0x01) << 7)
|
||
|
);
|
||
|
}
|
||
|
return map;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const std::array<uint8_t, 256> map = ReverseTable::reverse_table();
|
||
|
return map[source];
|
||
|
}
|
||
|
|
||
|
// All other versions just call the byte-level reverse the appropriate number of times.
|
||
|
template <typename IntT> constexpr IntT bit_reverse(IntT source) {
|
||
|
IntT result;
|
||
|
|
||
|
uint8_t *src = reinterpret_cast<uint8_t *>(&source);
|
||
|
uint8_t *dest = reinterpret_cast<uint8_t *>(&result) + sizeof(result) - 1;
|
||
|
for(size_t c = 0; c < sizeof(source); c++) {
|
||
|
*dest = bit_reverse(*src);
|
||
|
++src;
|
||
|
--dest;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif /* BitReverse_hpp */
|