7 namespace itk::itkpix::endec::codec {
10 template <
bool USE_LUT = true>
17 static inline constexpr uint32_t LUT_LEN = 16;
19 static inline constexpr uint32_t encode(uint32_t decoded, uint32_t &encoded) {
20 if constexpr (USE_LUT) {
21 uint64_t _encoded = lut_encode[decoded & 0xffff];
22 encoded = _encoded & 0xffffffff;
23 return _encoded >> 32;
25 return encode_(decoded, encoded);
28 [[gnu::always_inline]]
static inline constexpr uint32_t decode(uint32_t encoded, uint32_t &decoded) {
29 if constexpr (USE_LUT) {
30 auto _encoded = encoded & 0x3fffffff;
31 auto [_decoded, _offset, _length] = lut_top[_encoded >> (30 - LUT_LEN)];
32 uint32_t hitmap = _decoded;
34 if (_offset == 0xff)
return _length;
35 _encoded = (_encoded >> _offset) & 0x3fff;
36 auto [_hitmap, length2] = lut_bottom[_encoded];
38 decoded |= uint16_t(_hitmap) << 8;
39 return _length + length2;
41 return decode_(encoded, decoded);
44 using HitLutEntry = std::pair<uint8_t,uint8_t>;
45 using HitLutRow = std::array<HitLutEntry, 16>;
46 using HitLutType = std::array<HitLutRow, 1<<16>;
47 static inline constexpr
auto create_hit_lut_length_() {
48 std::array<uint8_t, 1<<16> result{};
49 for(uint32_t i = 0; i < (1<<16); i++)
50 result[i] = std::popcount(i);
53 static inline constexpr
auto create_hit_lut_() {
55 for (uint32_t hitmap = 0; hitmap < (1 << 16); ++hitmap) {
57 for (uint8_t bit = 0; bit < 16; ++bit) {
58 if((hitmap & (1<< bit)) == 0)
continue;
59 result[hitmap][index++] = {bit % 8, bit / 8};
65 static inline HitLutType hit_lut {create_hit_lut_()};
66 static inline std::array<uint8_t, (1<<16)> hit_lut_length{create_hit_lut_length_()};
68 using LUT1_entry = std::tuple<uint16_t, uint8_t, uint8_t>;
69 using LUT2_entry = std::tuple<uint8_t, uint8_t>;
70 using LUT1_type = std::conditional_t<USE_LUT, std::array<LUT1_entry, 1 << LUT_LEN>,
void *>;
71 using LUT2_type = std::conditional_t<USE_LUT, std::array<LUT2_entry, 1 << (30 - LUT_LEN)>,
void *>;
72 using LUT_ENCODE_type = std::conditional_t<USE_LUT, std::array<uint64_t, (1 << 16)>,
void *>;
74 static inline constexpr
auto create_lut_top_() {
76 for (uint32_t i = 0; i < (1 << LUT_LEN); i++) {
78 auto length = decode_(i << (30 - LUT_LEN), decoded);
79 uint32_t offset = 0xff;
81 uint32_t shift = decoded & 0xff;
83 length = encode_(shift, encoded);
86 lut[i] = {decoded & 0xffff, offset & 0xff, length & 0xff};
92 static inline LUT1_type lut_top{create_lut_top_()};
94 static inline constexpr
auto create_lut_bottom_() {
96 for (uint32_t i = 0; i < 1 << (30 - LUT_LEN); i++) {
98 auto length = decode_bottom_(i << LUT_LEN, decoded);
99 lut[i] = {decoded >> 8, length};
104 static inline LUT2_type lut_bottom{create_lut_bottom_()};
106 static inline constexpr
auto create_lut_encode_() {
109 for (uint32_t i = 1; i < 1 << 16; i++) {
111 uint64_t len = encode_(i, encoded);
112 lut[i] = encoded | (len << 32);
117 static inline LUT_ENCODE_type lut_encode{create_lut_encode_()};
119 static inline constexpr uint32_t encode_(uint32_t decoded, uint32_t &encoded) {
121 for (
int i = 0; i < 8; i++) {
122 b[i] = ((decoded >> (2 * i)) & 0x1) << 1 | ((decoded >> (2 * i + 1)) & 0x1);
124 auto one_bit = [](uint32_t value) -> uint32_t {
return value != 0 ? 1 : 0; };
125 uint32_t S1 = (one_bit(b[0] | b[1] | b[2] | b[3]) << 1) | one_bit(b[4] | b[5] | b[6] | b[7]);
126 uint32_t S2t = (one_bit(b[0] | b[1]) << 1) | one_bit(b[2] | b[3]);
127 uint32_t S2b = (one_bit(b[4] | b[5]) << 1) | one_bit(b[6] | b[7]);
128 uint32_t S3tl = (one_bit(b[0]) << 1) | one_bit(b[1]);
129 uint32_t S3tr = (one_bit(b[2]) << 1) | one_bit(b[3]);
130 uint32_t S3bl = (one_bit(b[4]) << 1) | one_bit(b[5]);
131 uint32_t S3br = (one_bit(b[6]) << 1) | one_bit(b[7]);
136 auto writeTwo = [&](uint32_t src) {
138 encoded |= (0b0) << (28 - pos);
141 encoded |= (src & 0x3) << (28 - pos);
145 for (
auto val : {S1, S2t, S3tl, S3tr, b[0], b[1], b[2], b[3], S2b, S3bl, S3br, b[4], b[5], b[6], b[7]})
146 if (val) writeTwo(val);
150 [[gnu::always_inline]]
static constexpr uint32_t decode_(uint32_t encoded, uint32_t &decoded) {
151 return decode_impl_<true>(encoded, decoded);
154 template <
bool DECODE_ALL = true>
155 [[gnu::always_inline]]
static constexpr uint32_t decode_impl_(uint32_t encoded, uint32_t &decoded) {
166 auto readTwo = [&](uint32_t &dst) {
167 uint32_t val = (encoded >> (28 - pos)) & 0x3;
168 if (val == 0b00 or val == 0b01) {
177 auto read = [&](uint32_t branch, uint32_t index) {
178 auto &left = b[index];
179 auto &right = b[index + 1];
180 switch (branch & 3) {
194 auto read_bottom = [&]() {
214 auto read_all = [&] {
261 if constexpr (DECODE_ALL)
267 for (
int i = 0; i < 8; i++) {
268 decoded |= ((b[i] >> 1) & 0x1) << (i * 2);
269 decoded |= ((b[i] >> 0) & 0x1) << (i * 2 + 1);
274 static inline constexpr uint32_t decode_bottom_(uint32_t encoded, uint32_t &decoded) {
275 return decode_impl_<false>(encoded, decoded);
Definition: bintree.hpp:11