8 namespace itk::itkpix::endec::codec {
11 [[gnu::always_inline]]
static inline constexpr T bit_extract(T value, std::size_t start, std::size_t len)
12 requires(std::is_unsigned_v<T>)
15 result = (value >> start) & ((T(1) << len) - 1);
20 [[gnu::always_inline]]
static inline constexpr
void bit_insert(T value, T &dst, std::size_t start,
22 requires(std::is_unsigned_v<T>)
24 T extracted_bits = bit_extract(value, 0, len);
25 T mask = ((T(1) << len) - 1) << start;
27 dst |= (extracted_bits << start);
47 template <
typename Buffer>
56 nBitsInWord(other.nBitsInWord) {}
58 using value_type = uint64_t;
59 using result_type = std::pair<bool, value_type>;
61 static constexpr std::size_t nBits = 64;
62 explicit BitStreamReader(
const std::span<const uint64_t> data, std::size_t offset)
63 : data(data), size(data.size() * nBits), Offset(offset) {}
65 [[gnu::always_inline]] [[nodiscard]] uint64_t first_word()
const {
return data[0]; }
67 [[gnu::always_inline]] [[nodiscard]] std::size_t left()
const {
68 return (_index > size) ? 0 : size - _index;
71 [[gnu::always_inline]] [[nodiscard]] std::size_t index()
const {
return _index; }
73 [[gnu::always_inline]]
bool set(std::size_t N) {
74 if (N >= size)
return false;
79 [[gnu::always_inline]]
inline bool advance(std::size_t
const N) {
80 if (_index + N > size)
return false;
81 auto i_bit = _index % nBits;
82 auto left = nBits - i_bit;
86 if (N == left) _index += Offset;
90 if (w2 <= nBitsInWord) {
91 _index += (N + Offset);
92 if (w2 == nBitsInWord) _index += Offset;
95 _index += (2 * Offset + N);
99 template <
bool Advance>
100 [[gnu::always_inline]]
inline result_type _fetch(std::size_t
const N) {
102 if (_index + N > size)
return {
false, value};
103 auto i_word = _index / nBits;
104 auto i_bit = _index % nBits;
105 auto left = nBits - i_bit;
107 value = bit_extract(data[i_word], left - N, N);
108 if constexpr (Advance) {
110 if (N == left) _index += Offset;
112 return {
true, value};
115 if (w2 <= nBitsInWord) {
116 auto word_1 = bit_extract(data[i_word], 0, left);
117 auto word_2 = bit_extract(data[i_word + 1], nBitsInWord - w2, w2);
118 value = word_2 | (word_1 << w2);
119 if constexpr (Advance) {
120 _index += (N + Offset);
121 if (w2 == nBitsInWord) _index += Offset;
123 return {
true, value};
125 auto w3 = (N - left) - nBitsInWord;
126 auto word_1 = bit_extract(data[i_word], 0, left);
127 auto word_2 = bit_extract(data[i_word + 1], 0, nBitsInWord);
128 auto word_3 = bit_extract(data[i_word + 2], nBitsInWord - w3, w3);
129 value = (word_1 << i_bit) | (word_2 << (i_bit - nBitsInWord)) | word_3;
130 if constexpr (Advance) {
131 _index += (2 * Offset + N);
133 return {
true, value};
136 [[gnu::always_inline]]
inline result_type prefetch(
const std::size_t sz) {
137 return _fetch<false>(sz);
140 [[gnu::always_inline]]
inline result_type fetch(
const std::size_t sz) {
141 return _fetch<true>(sz);
144 std::span<const uint64_t> data;
145 const std::size_t size;
146 const std::size_t Offset;
147 std::size_t _index{Offset};
148 const std::size_t nBitsInWord = nBits - Offset;
Definition: bitstream.hpp:49