|
24 | 24 | #include "adt/Casts.h" |
25 | 25 | #include "adt/Invariant.h" |
26 | 26 | #include <algorithm> |
| 27 | +#include <array> |
27 | 28 | #include <bit> |
28 | 29 | #include <climits> |
29 | 30 | #include <concepts> |
30 | 31 | #include <cstdint> |
| 32 | +#include <cstring> |
31 | 33 | #include <type_traits> |
32 | 34 |
|
33 | 35 | namespace rawspeed { |
@@ -134,4 +136,40 @@ constexpr typename std::make_signed_t<T> |
134 | 136 | return static_cast<SignedT>(value << SpareSignBits) >> SpareSignBits; |
135 | 137 | } |
136 | 138 |
|
| 139 | +template <class T> |
| 140 | + requires std::same_as<T, uint8_t> |
| 141 | +T bitreverse(const T v) { |
| 142 | +#if __has_builtin(__builtin_bitreverse8) |
| 143 | + return __builtin_bitreverse8(v); |
| 144 | +#endif |
| 145 | + // Reverse the order of bits within each byte using a bit-twiddle trick. |
| 146 | + // Three operation bit reversal from: |
| 147 | + // https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv |
| 148 | + return uint8_t((uint8_t(v) * 0x0202020202ULL & 0x010884422010ULL) % 1023); |
| 149 | +} |
| 150 | + |
| 151 | +#if __has_builtin(__builtin_bitreverse32) |
| 152 | +template <class T> |
| 153 | + requires std::same_as<T, uint32_t> |
| 154 | +T bitreverse(const T v) { |
| 155 | + return __builtin_bitreverse32(v); |
| 156 | +} |
| 157 | +#endif |
| 158 | + |
| 159 | +template <class T> |
| 160 | + requires std::same_as<T, uint8_t> |
| 161 | +std::array<T, 4> bitreverse_each(std::array<T, 4> x) { |
| 162 | +#if !__has_builtin(__builtin_bitreverse32) |
| 163 | + for (T& e : x) |
| 164 | + e = bitreverse(e); |
| 165 | +#else |
| 166 | + uint32_t tmp; |
| 167 | + std::memcpy(&tmp, x.data(), sizeof(uint32_t)); |
| 168 | + tmp = bitreverse(tmp); |
| 169 | + tmp = __builtin_bswap32(tmp); |
| 170 | + std::memcpy(x.data(), &tmp, sizeof(uint32_t)); |
| 171 | +#endif |
| 172 | + return x; |
| 173 | +} |
| 174 | + |
137 | 175 | } // namespace rawspeed |
0 commit comments