GameApi 28
Library used by GameApi Builder tool
Loading...
Searching...
No Matches
ans.h
Go to the documentation of this file.
1// Copyright 2016 The Draco Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15#ifndef DRACO_COMPRESSION_ENTROPY_ANS_H_
16#define DRACO_COMPRESSION_ENTROPY_ANS_H_
17// An implementation of Asymmetric Numeral Systems (rANS).
18// See http://arxiv.org/abs/1311.2540v2 for more information on rANS.
19// This file is based off libvpx's ans.h.
20
21#include <vector>
22
23#define DRACO_ANS_DIVIDE_BY_MULTIPLY 1
24#if DRACO_ANS_DIVIDE_BY_MULTIPLY
25#include "draco/core/divide.h"
26#endif
27#include "draco/core/macros.h"
28
29namespace draco {
30
31#if DRACO_ANS_DIVIDE_BY_MULTIPLY
32
33#define DRACO_ANS_DIVREM(quotient, remainder, dividend, divisor) \
34 do { \
35 quotient = fastdiv(dividend, divisor); \
36 remainder = dividend - quotient * divisor; \
37 } while (0)
38#define DRACO_ANS_DIV(dividend, divisor) fastdiv(dividend, divisor)
39#else
40#define DRACO_ANS_DIVREM(quotient, remainder, dividend, divisor) \
41 do { \
42 quotient = dividend / divisor; \
43 remainder = dividend % divisor; \
44 } while (0)
45#define DRACO_ANS_DIV(dividend, divisor) ((dividend) / (divisor))
46#endif
47
48struct AnsCoder {
49 AnsCoder() : buf(nullptr), buf_offset(0), state(0) {}
50 uint8_t *buf;
52 uint32_t state;
53};
54
55struct AnsDecoder {
56 AnsDecoder() : buf(nullptr), buf_offset(0), state(0) {}
57 const uint8_t *buf;
59 uint32_t state;
60};
61
62typedef uint8_t AnsP8;
63#define DRACO_ANS_P8_PRECISION 256u
64#define DRACO_ANS_L_BASE (4096u)
65#define DRACO_ANS_IO_BASE 256
66
67static uint32_t mem_get_le16(const void *vmem) {
68 uint32_t val;
69 const uint8_t *mem = (const uint8_t *)vmem;
70
71 val = mem[1] << 8;
72 val |= mem[0];
73 return val;
74}
75
76static uint32_t mem_get_le24(const void *vmem) {
77 uint32_t val;
78 const uint8_t *mem = (const uint8_t *)vmem;
79
80 val = mem[2] << 16;
81 val |= mem[1] << 8;
82 val |= mem[0];
83 return val;
84}
85
86static inline uint32_t mem_get_le32(const void *vmem) {
87 uint32_t val;
88 const uint8_t *mem = (const uint8_t *)vmem;
89
90 val = mem[3] << 24;
91 val |= mem[2] << 16;
92 val |= mem[1] << 8;
93 val |= mem[0];
94 return val;
95}
96
97static inline void mem_put_le16(void *vmem, uint32_t val) {
98 uint8_t *mem = reinterpret_cast<uint8_t *>(vmem);
99
100 mem[0] = (val >> 0) & 0xff;
101 mem[1] = (val >> 8) & 0xff;
102}
103
104static inline void mem_put_le24(void *vmem, uint32_t val) {
105 uint8_t *mem = reinterpret_cast<uint8_t *>(vmem);
106
107 mem[0] = (val >> 0) & 0xff;
108 mem[1] = (val >> 8) & 0xff;
109 mem[2] = (val >> 16) & 0xff;
110}
111
112static inline void mem_put_le32(void *vmem, uint32_t val) {
113 uint8_t *mem = reinterpret_cast<uint8_t *>(vmem);
114
115 mem[0] = (val >> 0) & 0xff;
116 mem[1] = (val >> 8) & 0xff;
117 mem[2] = (val >> 16) & 0xff;
118 mem[3] = (val >> 24) & 0xff;
119}
120
121static inline void ans_write_init(struct AnsCoder *const ans,
122 uint8_t *const buf) {
123 ans->buf = buf;
124 ans->buf_offset = 0;
125 ans->state = DRACO_ANS_L_BASE;
126}
127
128static inline int ans_write_end(struct AnsCoder *const ans) {
129 uint32_t state;
132 state = ans->state - DRACO_ANS_L_BASE;
133 if (state < (1 << 6)) {
134 ans->buf[ans->buf_offset] = (0x00 << 6) + state;
135 return ans->buf_offset + 1;
136 } else if (state < (1 << 14)) {
137 mem_put_le16(ans->buf + ans->buf_offset, (0x01 << 14) + state);
138 return ans->buf_offset + 2;
139 } else if (state < (1 << 22)) {
140 mem_put_le24(ans->buf + ans->buf_offset, (0x02 << 22) + state);
141 return ans->buf_offset + 3;
142 } else {
143 DRACO_DCHECK(0 && "State is too large to be serialized");
144 return ans->buf_offset;
145 }
146}
147
148// rABS with descending spread.
149// p or p0 takes the place of l_s from the paper.
150// DRACO_ANS_P8_PRECISION is m.
151static inline void rabs_desc_write(struct AnsCoder *ans, int val, AnsP8 p0) {
152 const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
153 const unsigned l_s = val ? p : p0;
154 unsigned quot, rem;
155 if (ans->state >=
157 ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE;
158 ans->state /= DRACO_ANS_IO_BASE;
159 }
160 DRACO_ANS_DIVREM(quot, rem, ans->state, l_s);
161 ans->state = quot * DRACO_ANS_P8_PRECISION + rem + (val ? 0 : p);
162}
163
164#define DRACO_ANS_IMPL1 0
165#define UNPREDICTABLE(x) x
166static inline int rabs_desc_read(struct AnsDecoder *ans, AnsP8 p0) {
167 int val;
168#if DRACO_ANS_IMPL1
169 unsigned l_s;
170#else
171 unsigned quot, rem, x, xn;
172#endif
173 const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
174 if (ans->state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
175 ans->state = ans->state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
176 }
177#if DRACO_ANS_IMPL1
178 val = ans->state % DRACO_ANS_P8_PRECISION < p;
179 l_s = val ? p : p0;
180 ans->state = (ans->state / DRACO_ANS_P8_PRECISION) * l_s +
181 ans->state % DRACO_ANS_P8_PRECISION - (!val * p);
182#else
183 x = ans->state;
184 quot = x / DRACO_ANS_P8_PRECISION;
185 rem = x % DRACO_ANS_P8_PRECISION;
186 xn = quot * p;
187 val = rem < p;
188 if (UNPREDICTABLE(val)) {
189 ans->state = xn + rem;
190 } else {
191 // ans->state = quot * p0 + rem - p;
192 ans->state = x - xn - p;
193 }
194#endif
195 return val;
196}
197
198// rABS with ascending spread.
199// p or p0 takes the place of l_s from the paper.
200// DRACO_ANS_P8_PRECISION is m.
201static inline void rabs_asc_write(struct AnsCoder *ans, int val, AnsP8 p0) {
202 const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
203 const unsigned l_s = val ? p : p0;
204 unsigned quot, rem;
205 if (ans->state >=
207 ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE;
208 ans->state /= DRACO_ANS_IO_BASE;
209 }
210 DRACO_ANS_DIVREM(quot, rem, ans->state, l_s);
211 ans->state = quot * DRACO_ANS_P8_PRECISION + rem + (val ? p0 : 0);
212}
213
214static inline int rabs_asc_read(struct AnsDecoder *ans, AnsP8 p0) {
215 int val;
216#if DRACO_ANS_IMPL1
217 unsigned l_s;
218#else
219 unsigned quot, rem, x, xn;
220#endif
221 const AnsP8 p = DRACO_ANS_P8_PRECISION - p0;
222 if (ans->state < DRACO_ANS_L_BASE) {
223 ans->state = ans->state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
224 }
225#if DRACO_ANS_IMPL1
226 val = ans->state % DRACO_ANS_P8_PRECISION < p;
227 l_s = val ? p : p0;
228 ans->state = (ans->state / DRACO_ANS_P8_PRECISION) * l_s +
229 ans->state % DRACO_ANS_P8_PRECISION - (!val * p);
230#else
231 x = ans->state;
232 quot = x / DRACO_ANS_P8_PRECISION;
233 rem = x % DRACO_ANS_P8_PRECISION;
234 xn = quot * p;
235 val = rem >= p0;
236 if (UNPREDICTABLE(val)) {
237 ans->state = xn + rem - p0;
238 } else {
239 // ans->state = quot * p0 + rem - p0;
240 ans->state = x - xn;
241 }
242#endif
243 return val;
244}
245
246#define rabs_read rabs_desc_read
247#define rabs_write rabs_desc_write
248
249// uABS with normalization.
250static inline void uabs_write(struct AnsCoder *ans, int val, AnsP8 p0) {
252 const unsigned l_s = val ? p : p0;
253 while (ans->state >=
255 ans->buf[ans->buf_offset++] = ans->state % DRACO_ANS_IO_BASE;
256 ans->state /= DRACO_ANS_IO_BASE;
257 }
258 if (!val) {
259 ans->state = DRACO_ANS_DIV(ans->state * DRACO_ANS_P8_PRECISION, p0);
260 } else {
261 ans->state =
262 DRACO_ANS_DIV((ans->state + 1) * DRACO_ANS_P8_PRECISION + p - 1, p) - 1;
263 }
264}
265
266static inline int uabs_read(struct AnsDecoder *ans, AnsP8 p0) {
268 int s;
269 // unsigned int xp1;
270 unsigned xp, sp;
271 unsigned state = ans->state;
272 while (state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
273 state = state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
274 }
275 sp = state * p;
276 // xp1 = (sp + p) / DRACO_ANS_P8_PRECISION;
277 xp = sp / DRACO_ANS_P8_PRECISION;
278 // s = xp1 - xp;
279 s = (sp & 0xFF) >= p0;
280 if (UNPREDICTABLE(s)) {
281 ans->state = xp;
282 } else {
283 ans->state = state - xp;
284 }
285 return s;
286}
287
288static inline int uabs_read_bit(struct AnsDecoder *ans) {
289 int s;
290 unsigned state = ans->state;
291 while (state < DRACO_ANS_L_BASE && ans->buf_offset > 0) {
292 state = state * DRACO_ANS_IO_BASE + ans->buf[--ans->buf_offset];
293 }
294 s = static_cast<int>(state & 1);
295 ans->state = state >> 1;
296 return s;
297}
298
299static inline int ans_read_init(struct AnsDecoder *const ans,
300 const uint8_t *const buf, int offset) {
301 unsigned x;
302 if (offset < 1) {
303 return 1;
304 }
305 ans->buf = buf;
306 x = buf[offset - 1] >> 6;
307 if (x == 0) {
308 ans->buf_offset = offset - 1;
309 ans->state = buf[offset - 1] & 0x3F;
310 } else if (x == 1) {
311 if (offset < 2) {
312 return 1;
313 }
314 ans->buf_offset = offset - 2;
315 ans->state = mem_get_le16(buf + offset - 2) & 0x3FFF;
316 } else if (x == 2) {
317 if (offset < 3) {
318 return 1;
319 }
320 ans->buf_offset = offset - 3;
321 ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
322 } else {
323 return 1;
324 }
325 ans->state += DRACO_ANS_L_BASE;
326 if (ans->state >= DRACO_ANS_L_BASE * DRACO_ANS_IO_BASE) {
327 return 1;
328 }
329 return 0;
330}
331
332static inline int ans_read_end(struct AnsDecoder *const ans) {
333 return ans->state == DRACO_ANS_L_BASE;
334}
335
336static inline int ans_reader_has_error(const struct AnsDecoder *const ans) {
337 return ans->state < DRACO_ANS_L_BASE && ans->buf_offset == 0;
338}
339
340struct rans_sym {
341 uint32_t prob;
342 uint32_t cum_prob; // not-inclusive.
343};
344
345// Class for performing rANS encoding using a desired number of precision bits.
346// The max number of precision bits is currently 19. The actual number of
347// symbols in the input alphabet should be (much) smaller than that, otherwise
348// the compression rate may suffer.
349template <int rans_precision_bits_t>
351 public:
353
354 // Provides the input buffer where the data is going to be stored.
355 inline void write_init(uint8_t *const buf) {
356 ans_.buf = buf;
357 ans_.buf_offset = 0;
358 ans_.state = l_rans_base;
359 }
360
361 // Needs to be called after all symbols are encoded.
362 inline int write_end() {
363 uint32_t state;
364 DRACO_DCHECK_GE(ans_.state, l_rans_base);
365 DRACO_DCHECK_LT(ans_.state, l_rans_base * DRACO_ANS_IO_BASE);
366 state = ans_.state - l_rans_base;
367 if (state < (1 << 6)) {
368 ans_.buf[ans_.buf_offset] = (0x00 << 6) + state;
369 return ans_.buf_offset + 1;
370 } else if (state < (1 << 14)) {
371 mem_put_le16(ans_.buf + ans_.buf_offset, (0x01 << 14) + state);
372 return ans_.buf_offset + 2;
373 } else if (state < (1 << 22)) {
374 mem_put_le24(ans_.buf + ans_.buf_offset, (0x02 << 22) + state);
375 return ans_.buf_offset + 3;
376 } else if (state < (1 << 30)) {
377 mem_put_le32(ans_.buf + ans_.buf_offset, (0x03u << 30u) + state);
378 return ans_.buf_offset + 4;
379 } else {
380 DRACO_DCHECK(0 && "State is too large to be serialized");
381 return ans_.buf_offset;
382 }
383 }
384
385 // rANS with normalization.
386 // sym->prob takes the place of l_s from the paper.
387 // rans_precision is m.
388 inline void rans_write(const struct rans_sym *const sym) {
389 const uint32_t p = sym->prob;
390 while (ans_.state >= l_rans_base / rans_precision * DRACO_ANS_IO_BASE * p) {
391 ans_.buf[ans_.buf_offset++] = ans_.state % DRACO_ANS_IO_BASE;
392 ans_.state /= DRACO_ANS_IO_BASE;
393 }
394 ans_.state =
395 (ans_.state / p) * rans_precision + ans_.state % p + sym->cum_prob;
396 }
397
398 private:
399 static constexpr int rans_precision = 1 << rans_precision_bits_t;
400 static constexpr int l_rans_base = rans_precision * 4;
401 AnsCoder ans_;
402};
403
405 uint32_t val;
406 uint32_t prob;
407 uint32_t cum_prob; // not-inclusive.
408};
409
410// Class for performing rANS decoding using a desired number of precision bits.
411// The number of precision bits needs to be the same as with the RAnsEncoder
412// that was used to encode the input data.
413template <int rans_precision_bits_t>
415 public:
417
418 // Initializes the decoder from the input buffer. The |offset| specifies the
419 // number of bytes encoded by the encoder. A non zero return value is an
420 // error.
421 inline int read_init(const uint8_t *const buf, int offset) {
422 unsigned x;
423 if (offset < 1) {
424 return 1;
425 }
426 ans_.buf = buf;
427 x = buf[offset - 1] >> 6;
428 if (x == 0) {
429 ans_.buf_offset = offset - 1;
430 ans_.state = buf[offset - 1] & 0x3F;
431 } else if (x == 1) {
432 if (offset < 2) {
433 return 1;
434 }
435 ans_.buf_offset = offset - 2;
436 ans_.state = mem_get_le16(buf + offset - 2) & 0x3FFF;
437 } else if (x == 2) {
438 if (offset < 3) {
439 return 1;
440 }
441 ans_.buf_offset = offset - 3;
442 ans_.state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
443 } else if (x == 3) {
444 ans_.buf_offset = offset - 4;
445 ans_.state = mem_get_le32(buf + offset - 4) & 0x3FFFFFFF;
446 } else {
447 return 1;
448 }
449 ans_.state += l_rans_base;
450 if (ans_.state >= l_rans_base * DRACO_ANS_IO_BASE) {
451 return 1;
452 }
453 return 0;
454 }
455
456 inline int read_end() { return ans_.state == l_rans_base; }
457
458 inline int reader_has_error() {
459 return ans_.state < l_rans_base && ans_.buf_offset == 0;
460 }
461
462 inline int rans_read() {
463 unsigned rem;
464 unsigned quo;
465 struct rans_dec_sym sym;
466 while (ans_.state < l_rans_base && ans_.buf_offset > 0) {
467 ans_.state = ans_.state * DRACO_ANS_IO_BASE + ans_.buf[--ans_.buf_offset];
468 }
469 // |rans_precision| is a power of two compile time constant, and the below
470 // division and modulo are going to be optimized by the compiler.
471 quo = ans_.state / rans_precision;
472 rem = ans_.state % rans_precision;
473 fetch_sym(&sym, rem);
474 ans_.state = quo * sym.prob + rem - sym.cum_prob;
475 return sym.val;
476 }
477
478 // Construct a lookup table with |rans_precision| number of entries.
479 // Returns false if the table couldn't be built (because of wrong input data).
480 inline bool rans_build_look_up_table(const uint32_t token_probs[],
481 uint32_t num_symbols) {
482 lut_table_.resize(rans_precision);
483 probability_table_.resize(num_symbols);
484 uint32_t cum_prob = 0;
485 uint32_t act_prob = 0;
486 for (uint32_t i = 0; i < num_symbols; ++i) {
487 probability_table_[i].prob = token_probs[i];
488 probability_table_[i].cum_prob = cum_prob;
489 cum_prob += token_probs[i];
490 if (cum_prob > rans_precision) {
491 return false;
492 }
493 for (uint32_t j = act_prob; j < cum_prob; ++j) {
494 lut_table_[j] = i;
495 }
496 act_prob = cum_prob;
497 }
498 if (cum_prob != rans_precision) {
499 return false;
500 }
501 return true;
502 }
503
504 private:
505 inline void fetch_sym(struct rans_dec_sym *out, uint32_t rem) {
506 uint32_t symbol = lut_table_[rem];
507 out->val = symbol;
508 out->prob = probability_table_[symbol].prob;
509 out->cum_prob = probability_table_[symbol].cum_prob;
510 }
511
512 static constexpr int rans_precision = 1 << rans_precision_bits_t;
513 static constexpr int l_rans_base = rans_precision * 4;
514 std::vector<uint32_t> lut_table_;
515 std::vector<rans_sym> probability_table_;
516 AnsDecoder ans_;
517};
518
519#undef DRACO_ANS_DIVREM
520#undef DRACO_ANS_P8_PRECISION
521#undef DRACO_ANS_L_BASE
522#undef DRACO_ANS_IO_BASE
523
524} // namespace draco
525
526#endif // DRACO_COMPRESSION_ENTROPY_ANS_H_
#define UNPREDICTABLE(x)
Definition ans.h:165
#define DRACO_ANS_DIVREM(quotient, remainder, dividend, divisor)
Definition ans.h:33
#define DRACO_ANS_DIV(dividend, divisor)
Definition ans.h:38
#define DRACO_ANS_IO_BASE
Definition ans.h:65
#define DRACO_ANS_P8_PRECISION
Definition ans.h:63
#define DRACO_ANS_L_BASE
Definition ans.h:64
bool rans_build_look_up_table(const uint32_t token_probs[], uint32_t num_symbols)
Definition ans.h:480
int read_init(const uint8_t *const buf, int offset)
Definition ans.h:421
int read_end()
Definition ans.h:456
RAnsDecoder()
Definition ans.h:416
int rans_read()
Definition ans.h:462
int reader_has_error()
Definition ans.h:458
void rans_write(const struct rans_sym *const sym)
Definition ans.h:388
RAnsEncoder()
Definition ans.h:352
void write_init(uint8_t *const buf)
Definition ans.h:355
int write_end()
Definition ans.h:362
#define DRACO_DCHECK_LT(a, b)
Definition macros.h:86
#define DRACO_DCHECK(x)
Definition macros.h:80
#define DRACO_DCHECK_GE(a, b)
Definition macros.h:83
Definition attribute_octahedron_transform.cc:21
uint8_t AnsP8
Definition ans.h:62
Definition ans.h:48
int buf_offset
Definition ans.h:51
uint32_t state
Definition ans.h:52
AnsCoder()
Definition ans.h:49
uint8_t * buf
Definition ans.h:50
Definition ans.h:55
uint32_t state
Definition ans.h:59
const uint8_t * buf
Definition ans.h:57
int buf_offset
Definition ans.h:58
AnsDecoder()
Definition ans.h:56
Definition ans.h:404
uint32_t prob
Definition ans.h:406
uint32_t val
Definition ans.h:405
uint32_t cum_prob
Definition ans.h:407
Definition ans.h:340
uint32_t cum_prob
Definition ans.h:342
uint32_t prob
Definition ans.h:341