Grok 20.3.2
mqc_dec_inl.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20const uint32_t A_MIN = 0x8000;
21
22const uint8_t B1_POS = 1;
23const uint8_t B2_POS = 2;
24const uint8_t B3_POS = 3;
25const uint8_t B4_POS = 4;
26const uint8_t B5_POS = 5;
27const uint8_t B6_POS = 6;
28const uint8_t B7_POS = 7;
29const uint8_t B8_POS = 8;
30const uint8_t B9_POS = 9;
31const uint8_t B10_POS = 10;
32const uint8_t B11_POS = 11;
33const uint8_t B12_POS = 12;
34
35#define DEC_PASS_LOCAL_VARIABLES(flagsStride) \
36 const int32_t one = 1 << bpno; \
37 const auto mqc = &coder; \
38 auto dataPtr = uncompressedData_; \
39 auto flagsPtr = flags_ + flagsStride + 1; \
40 grk_flag _flags = 0; \
41 uint16_t i = 0, j = 0, k = 0; \
42 bool approaching_red; \
43 (void)approaching_red; \
44 PUSH_MQC();
45
46#define DEC_PASS_LOCAL_VARIABLES_DIFF(flagsStride) \
47 const int32_t one = 1 << bpno; \
48 const auto mqc = &coder; \
49 auto dataPtr = uncompressedData_; \
50 auto flagsPtr = flags_ + flagsStride + 1; \
51 grk_flag _flags = 0; \
52 uint16_t i = 0, j = 0, k = 0; \
53 const mqc_state** curctx; \
54 uint32_t c, a; \
55 uint8_t ct; \
56 bool approaching_red = (coder.backup_->i == BACKUP_DISABLED) && \
57 mqc->bp + red_zone >= mqc->end && \
58 ((coder.cur_buffer_index + 1 >= coder.num_buffers) || \
59 coder.buffer_lengths[coder.cur_buffer_index + 1] <= red_zone); \
60 (void)approaching_red;
61
62// BACKUP/RESTORE ///////////////////////////////////////////////////////
63
64const uint8_t red_zone = 6;
65
66#define DEC_PASS_HAS_BACKUP_FOR_CURRENT_PASS(coder) \
67 (coder.backup_->i != BACKUP_DISABLED) && (passno == coder.backup_->passno_)
68
69#define DEC_PASS_MQC_BACKUP_LOCAL(coder) \
70 coder.backup_->a = a; \
71 coder.backup_->c = c; \
72 coder.backup_->ct = ct; \
73 coder.backup_->curctx_index_ = curctx - &coder.ctxs[0]; \
74 coder.backup_->curctx = &coder.backup_->ctxs[coder.backup_->curctx_index_];
75
76#define DEC_PASS_MQC_RESTORE_LOCAL(coder) \
77 a = coder.backup_->a; \
78 c = coder.backup_->c; \
79 ct = coder.backup_->ct; \
80 coder.curctx_index_ = coder.backup_->curctx_index_; \
81 curctx = &coder.ctxs[coder.curctx_index_]; \
82 coder.curctx = curctx; \
83 coder.a = a; \
84 coder.c = c; \
85 coder.ct = ct;
86
87#define DEC_PASS_DO_BACKUP(coder, p) \
88 decompressBackup(); \
89 DEC_PASS_MQC_BACKUP_LOCAL(coder); \
90 auto b = coder.backup_; \
91 b->position = p; \
92 b->i = i; \
93 b->j = j; \
94 b->k = k; \
95 b->flagsPtr_ = flagsPtr; \
96 b->_flags = _flags; \
97 b->dataPtr_ = dataPtr; \
98 b->passno_ = passno; \
99 b->passtype_ = passtype; \
100 b->numBpsToDecompress_ = (uint8_t)bpno; \
101 approaching_red = false; \
102 b->layer_ = (uint16_t)coder.cur_buffer_index;
103
104#define DEC_PASS_BACKUP(coder, p) \
105 if(approaching_red) \
106 { \
107 DEC_PASS_DO_BACKUP(coder, p) \
108 }
109
110#define DEC_PASS_CLN_BACKUP(p) \
111 if(approaching_red) \
112 { \
113 DEC_PASS_DO_BACKUP(coder, p); \
114 coder.backup_->runlen = runlen; \
115 coder.backup_->partial = partial; \
116 }
117
118#define DEC_PASS_RESTORE(coder) \
119 do \
120 { \
121 if(DEC_PASS_HAS_BACKUP_FOR_CURRENT_PASS(coder)) \
122 { \
123 DEC_PASS_MQC_RESTORE_LOCAL(coder); \
124 auto b = coder.backup_; \
125 i = b->i; \
126 j = b->j; \
127 k = b->k; \
128 flagsPtr = b->flagsPtr_; \
129 _flags = b->_flags; \
130 dataPtr = b->dataPtr_; \
131 coder.cur_buffer_index = b->layer_; \
132 coder.end = \
133 coder.buffers[coder.cur_buffer_index] + coder.buffer_lengths[coder.cur_buffer_index]; \
134 approaching_red = mqc->bp + red_zone >= mqc->end && \
135 ((coder.cur_buffer_index + 1 >= coder.num_buffers) || \
136 coder.buffer_lengths[coder.cur_buffer_index + 1] <= red_zone); \
137 b->i = BACKUP_DISABLED; \
138 assert(b->passno_ == passno); \
139 assert(b->passtype_ == passtype); \
140 assert(b->numBpsToDecompress_ == (uint8_t)bpno); \
141 switch(b->position) \
142 { \
143 case B1_POS: \
144 goto B1; \
145 case B2_POS: \
146 goto B2; \
147 case B3_POS: \
148 goto B3; \
149 case B4_POS: \
150 goto B4; \
151 case B5_POS: \
152 goto B5; \
153 } \
154 } \
155 else \
156 { \
157 curctx = coder.curctx; \
158 c = coder.c; \
159 a = coder.a; \
160 ct = coder.ct; \
161 } \
162 } while(0)
163
164#define DEC_PASS_CLN_RESTORE(coder) \
165 do \
166 { \
167 if(DEC_PASS_HAS_BACKUP_FOR_CURRENT_PASS(coder)) \
168 { \
169 DEC_PASS_MQC_RESTORE_LOCAL(coder); \
170 auto b = coder.backup_; \
171 i = b->i; \
172 j = b->j; \
173 k = b->k; \
174 runlen = coder.backup_->runlen; \
175 partial = coder.backup_->partial; \
176 flagsPtr = b->flagsPtr_; \
177 _flags = b->_flags; \
178 dataPtr = b->dataPtr_; \
179 coder.cur_buffer_index = b->layer_; \
180 coder.end = \
181 coder.buffers[coder.cur_buffer_index] + coder.buffer_lengths[coder.cur_buffer_index]; \
182 approaching_red = mqc->bp + red_zone >= mqc->end && \
183 ((coder.cur_buffer_index + 1 >= coder.num_buffers) || \
184 coder.buffer_lengths[coder.cur_buffer_index + 1] <= red_zone); \
185 b->i = BACKUP_DISABLED; \
186 assert(b->passno_ == passno); \
187 assert(b->passtype_ == passtype); \
188 assert(b->numBpsToDecompress_ == (uint8_t)bpno); \
189 switch(b->position) \
190 { \
191 case B1_POS: \
192 goto B1; \
193 case B2_POS: \
194 goto B2; \
195 case B3_POS: \
196 goto B3; \
197 case B4_POS: \
198 goto B4; \
199 case B5_POS: \
200 goto B5; \
201 case B6_POS: \
202 goto B6; \
203 case B7_POS: \
204 goto B7; \
205 case B8_POS: \
206 goto B8; \
207 case B9_POS: \
208 goto B9; \
209 case B10_POS: \
210 goto B10; \
211 case B11_POS: \
212 goto B11; \
213 case B12_POS: \
214 goto B12; \
215 } \
216 } \
217 else \
218 { \
219 curctx = coder.curctx; \
220 c = coder.c; \
221 a = coder.a; \
222 ct = coder.ct; \
223 } \
224 } while(0)
225
227
235#define DEC_BYTEIN(mqc, c, ct) \
236 { \
237 uint8_t cur = 0xff; \
238 if(mqc->bp >= mqc->end) \
239 { \
240 if(mqc->cur_buffer_index + 1 < mqc->num_buffers) \
241 { \
242 /* Move to the next buffer */ \
243 mqc->cur_buffer_index++; \
244 mqc->bp = mqc->buffers[mqc->cur_buffer_index]; \
245 mqc->end = mqc->bp + mqc->buffer_lengths[mqc->cur_buffer_index]; \
246 cur = *mqc->bp; \
247 approaching_red = mqc->backup_ && (mqc->backup_->i == BACKUP_DISABLED) && \
248 mqc->bp + red_zone >= mqc->end && \
249 ((mqc->cur_buffer_index + 1 >= mqc->num_buffers) || \
250 mqc->buffer_lengths[mqc->cur_buffer_index + 1] <= red_zone); \
251 } \
252 } \
253 else \
254 { \
255 cur = *mqc->bp; \
256 } \
257 uint8_t next = 0xff; \
258 if(mqc->bp + 1 >= mqc->end) \
259 { \
260 if(mqc->cur_buffer_index + 1 < mqc->num_buffers) \
261 { \
262 /* Peek into the next buffer for the next byte */ \
263 next = *mqc->buffers[mqc->cur_buffer_index + 1]; \
264 } \
265 else \
266 { \
267 mqc->overflow_ = true; \
268 } \
269 } \
270 else \
271 { \
272 next = *(mqc->bp + 1); \
273 } \
274 uint8_t curff = (cur == 0xff); \
275 uint8_t is_end = curff & (next > 0x8f); \
276 if(is_end) \
277 { \
278 c += 0xff00; \
279 ct = 8; \
280 mqc->end_of_byte_stream_counter++; \
281 } \
282 else \
283 { \
284 mqc->bp++; \
285 approaching_red = mqc->backup_ && (mqc->backup_->i == BACKUP_DISABLED) && \
286 mqc->bp + red_zone >= mqc->end && \
287 ((mqc->cur_buffer_index + 1 >= mqc->num_buffers) || \
288 mqc->buffer_lengths[mqc->cur_buffer_index + 1] <= red_zone); \
289 c += next << (8 + curff); \
290 ct = 8 - curff; \
291 } \
292 }
293
294#define DEC_RENORM(mqc, a, c, ct) \
295 { \
296 do \
297 { \
298 if(ct == 0) \
299 { \
300 if(mqc->start == mqc->end) \
301 { \
302 c += 0xff00; \
303 ct = 8; \
304 mqc->end_of_byte_stream_counter++; \
305 } \
306 else \
307 DEC_BYTEIN(mqc, c, ct); \
308 } \
309 a <<= 1; \
310 c <<= 1; \
311 ct--; \
312 } while(a < A_MIN); \
313 }
314
324#define DEC_SYMBOL(d, mqc, curctx, a, c, ct) \
325 do \
326 { \
327 auto ctx = *(curctx); \
328 a -= ctx->qeval; \
329 uint32_t qeval_shift = ctx->qeval << 16; \
330 if(c < qeval_shift) \
331 { \
332 uint32_t mask = (uint32_t)-(a < ctx->qeval); \
333 a = ctx->qeval; \
334 d = ctx->mps ^ (~mask & 1); \
335 *curctx = mask ? ctx->nmps : ctx->nlps; \
336 DEC_RENORM(mqc, a, c, ct); \
337 } \
338 else \
339 { \
340 c -= qeval_shift; \
341 if(a < A_MIN) \
342 { \
343 uint32_t mask = (uint32_t)-(a < ctx->qeval); \
344 d = ctx->mps ^ (mask & 1); \
345 *curctx = mask ? ctx->nlps : ctx->nmps; \
346 DEC_RENORM(mqc, a, c, ct); \
347 } \
348 else \
349 { \
350 d = ctx->mps; \
351 } \
352 } \
353 } while(0)
354
356
359#define DEC_SYMBOL_RAW() \
360 { \
361 if(coder.ct == 0) \
362 { \
363 uint8_t curr = 0xff; \
364 if(coder.bp >= coder.end) \
365 { \
366 if(coder.cur_buffer_index + 1 < coder.num_buffers) \
367 { \
368 coder.cur_buffer_index++; \
369 coder.bp = coder.buffers[coder.cur_buffer_index]; \
370 coder.end = coder.bp + coder.buffer_lengths[coder.cur_buffer_index]; \
371 curr = *coder.bp; \
372 } \
373 } \
374 else \
375 { \
376 curr = *coder.bp; \
377 } \
378 if(coder.c == 0xff) \
379 { \
380 if(curr > 0x8f) \
381 { \
382 coder.c = 0xff; \
383 coder.ct = 8; \
384 } \
385 else \
386 { \
387 coder.c = curr; \
388 coder.bp++; \
389 coder.ct = 7; \
390 } \
391 } \
392 else \
393 { \
394 coder.c = curr; \
395 coder.bp++; \
396 coder.ct = 8; \
397 } \
398 } \
399 coder.ct--; \
400 v = ((uint8_t)coder.c >> coder.ct) & 0x1U; \
401 }
const uint8_t B12_POS
Definition mqc_dec_inl.h:33
const uint8_t B11_POS
Definition mqc_dec_inl.h:32
const uint8_t B4_POS
Definition mqc_dec_inl.h:25
const uint8_t B9_POS
Definition mqc_dec_inl.h:30
const uint32_t A_MIN
Definition mqc_dec_inl.h:20
const uint8_t B5_POS
Definition mqc_dec_inl.h:26
const uint8_t B8_POS
Definition mqc_dec_inl.h:29
const uint8_t B6_POS
Definition mqc_dec_inl.h:27
const uint8_t B7_POS
Definition mqc_dec_inl.h:28
const uint8_t red_zone
Definition mqc_dec_inl.h:64
const uint8_t B10_POS
Definition mqc_dec_inl.h:31
const uint8_t B1_POS
Definition mqc_dec_inl.h:22
const uint8_t B3_POS
Definition mqc_dec_inl.h:24
const uint8_t B2_POS
Definition mqc_dec_inl.h:23