代碼
////// @brief 左右翻轉位。////// @note 翻轉后,最低位位將變為最高位,最高位將變為最低位。//////template <typename T>requires(std::is_same_v<T, uint8_t>)constexpr T Reverse(T value){int32_t bit_count = sizeof(T) * 8;for (int32_t i = 0; i < bit_count / 2; i++){int32_t left_index = bit_count - 1 - i;int32_t right_index = i;bool left_bit = base::bit::ReadBit(value, left_index);bool right_bit = base::bit::ReadBit(value, right_index);base::bit::WriteBit(value, left_index, right_bit);base::bit::WriteBit(value, right_index, left_bit);}return value;}////// @brief 左右翻轉位。////// @note 翻轉后,最低位位將變為最高位,最高位將變為最低位。//////template <typename T>requires(std::is_integral_v<T> && !std::is_same_v<T, uint8_t>)constexpr T Reverse(T value){if (std::is_constant_evaluated()){// 編譯時計算路徑int32_t bit_count = sizeof(T) * 8;for (int32_t i = 0; i < bit_count / 2; i++){int32_t left_index = bit_count - 1 - i;int32_t right_index = i;bool left_bit = base::bit::ReadBit(value, left_index);bool right_bit = base::bit::ReadBit(value, right_index);base::bit::WriteBit(value, left_index, right_bit);base::bit::WriteBit(value, right_index, left_bit);}return value;}// 運行時計算路徑class Table{private:std::array<uint8_t, 256> _table{};public:constexpr Table(){for (int32_t i = 0; i < 256; i++){_table[i] = base::bit::Reverse(static_cast<uint8_t>(i));}}constexpr uint8_t operator[](uint8_t index) const{return _table[index];}};constexpr Table table{};uint8_t *bytes = reinterpret_cast<uint8_t *>(&value);for (size_t i = 0; i < sizeof(T); i++){bytes[i] = table[bytes[i]];}std::reverse(bytes, bytes + sizeof(T));return value;}
先準備一個針對 uint8_t 的版本
template <typename T>requires(std::is_same_v<T, uint8_t>)constexpr T Reverse(T value)
后續表格的建立基于這個版本。
翻轉一個 8 位以上的整型的位,等價于逐個字節翻轉,然后翻轉字節序。這是可以用查表法優化的理論基礎。
使用 constexpr 生成一個表格
// 運行時計算路徑class Table{private:std::array<uint8_t, 256> _table{};public:constexpr Table(){for (int32_t i = 0; i < 256; i++){_table[i] = base::bit::Reverse(static_cast<uint8_t>(i));}}constexpr uint8_t operator[](uint8_t index) const{return _table[index];}};constexpr Table table{};
翻轉一個字節只需查表即可完成。對于 64 位整型,需要查表 8 次,然后翻轉 8 個字節。
針對非 uint8_t 的版本
template <typename T>requires(std::is_integral_v<T> && !std::is_same_v<T, uint8_t>)constexpr T Reverse(T value)
中使用了 std::is_constant_evaluated()
,為編譯時計算和運行時計算分別定制了邏輯。
測試
// 0b10100111 = 0xa7 重復 8 次。// 0xa7a7a7a7a7a7a7a7constexpr uint64_t num = base::bit::Reverse(static_cast<uint64_t>(0b1010011110100111101001111010011110100111101001111010011110100111));std::cout << base::ToHexString(num) << std::endl;
運行結果
0xa84
0xe5e5e5e5e5e5e5e5
使用計算器驗證