annotate ezBAMQC/src/htslib/cram/rANS_byte.h @ 0:dfa3745e5fd8

Uploaded
author youngkim
date Thu, 24 Mar 2016 17:12:52 -0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
1 /* rans_byte.h originally from https://github.com/rygorous/ryg_rans
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
2 *
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
3 * This is a public-domain implementation of several rANS variants. rANS is an
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
4 * entropy coder from the ANS family, as described in Jarek Duda's paper
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
5 * "Asymmetric numeral systems" (http://arxiv.org/abs/1311.2540).
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
6 */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
7
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
8 /*-------------------------------------------------------------------------- */
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
9
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
10 // Simple byte-aligned rANS encoder/decoder - public domain - Fabian 'ryg' Giesen 2014
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
11 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
12 // Not intended to be "industrial strength"; just meant to illustrate the general
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
13 // idea.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
14
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
15 #ifndef RANS_BYTE_HEADER
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
16 #define RANS_BYTE_HEADER
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
17
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
18 #include <stdint.h>
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
19
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
20 #ifdef assert
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
21 #define RansAssert assert
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
22 #else
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
23 #define RansAssert(x)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
24 #endif
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
25
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
26 // READ ME FIRST:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
27 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
28 // This is designed like a typical arithmetic coder API, but there's three
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
29 // twists you absolutely should be aware of before you start hacking:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
30 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
31 // 1. You need to encode data in *reverse* - last symbol first. rANS works
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
32 // like a stack: last in, first out.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
33 // 2. Likewise, the encoder outputs bytes *in reverse* - that is, you give
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
34 // it a pointer to the *end* of your buffer (exclusive), and it will
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
35 // slowly move towards the beginning as more bytes are emitted.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
36 // 3. Unlike basically any other entropy coder implementation you might
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
37 // have used, you can interleave data from multiple independent rANS
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
38 // encoders into the same bytestream without any extra signaling;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
39 // you can also just write some bytes by yourself in the middle if
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
40 // you want to. This is in addition to the usual arithmetic encoder
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
41 // property of being able to switch models on the fly. Writing raw
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
42 // bytes can be useful when you have some data that you know is
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
43 // incompressible, and is cheaper than going through the rANS encode
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
44 // function. Using multiple rANS coders on the same byte stream wastes
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
45 // a few bytes compared to using just one, but execution of two
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
46 // independent encoders can happen in parallel on superscalar and
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
47 // Out-of-Order CPUs, so this can be *much* faster in tight decoding
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
48 // loops.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
49 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
50 // This is why all the rANS functions take the write pointer as an
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
51 // argument instead of just storing it in some context struct.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
52
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
53 // --------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
54
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
55 // L ('l' in the paper) is the lower bound of our normalization interval.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
56 // Between this and our byte-aligned emission, we use 31 (not 32!) bits.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
57 // This is done intentionally because exact reciprocals for 31-bit uints
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
58 // fit in 32-bit uints: this permits some optimizations during encoding.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
59 #define RANS_BYTE_L (1u << 23) // lower bound of our normalization interval
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
60
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
61 // State for a rANS encoder. Yep, that's all there is to it.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
62 typedef uint32_t RansState;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
63
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
64 // Initialize a rANS encoder.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
65 static inline void RansEncInit(RansState* r)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
66 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
67 *r = RANS_BYTE_L;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
68 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
69
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
70 // Renormalize the encoder. Internal function.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
71 static inline RansState RansEncRenorm(RansState x, uint8_t** pptr, uint32_t freq, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
72 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
73 uint32_t x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq; // this turns into a shift.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
74 if (x >= x_max) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
75 uint8_t* ptr = *pptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
76 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
77 *--ptr = (uint8_t) (x & 0xff);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
78 x >>= 8;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
79 } while (x >= x_max);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
80 *pptr = ptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
81 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
82 return x;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
83 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
84
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
85 // Encodes a single symbol with range start "start" and frequency "freq".
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
86 // All frequencies are assumed to sum to "1 << scale_bits", and the
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
87 // resulting bytes get written to ptr (which is updated).
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
88 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
89 // NOTE: With rANS, you need to encode symbols in *reverse order*, i.e. from
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
90 // beginning to end! Likewise, the output bytestream is written *backwards*:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
91 // ptr starts pointing at the end of the output buffer and keeps decrementing.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
92 static inline void RansEncPut(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
93 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
94 // renormalize
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
95 RansState x = RansEncRenorm(*r, pptr, freq, scale_bits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
96
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
97 // x = C(s,x)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
98 *r = ((x / freq) << scale_bits) + (x % freq) + start;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
99 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
100
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
101 // Flushes the rANS encoder.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
102 static inline void RansEncFlush(RansState* r, uint8_t** pptr)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
103 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
104 uint32_t x = *r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
105 uint8_t* ptr = *pptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
106
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
107 ptr -= 4;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
108 ptr[0] = (uint8_t) (x >> 0);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
109 ptr[1] = (uint8_t) (x >> 8);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
110 ptr[2] = (uint8_t) (x >> 16);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
111 ptr[3] = (uint8_t) (x >> 24);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
112
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
113 *pptr = ptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
114 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
115
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
116 // Initializes a rANS decoder.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
117 // Unlike the encoder, the decoder works forwards as you'd expect.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
118 static inline void RansDecInit(RansState* r, uint8_t** pptr)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
119 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
120 uint32_t x;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
121 uint8_t* ptr = *pptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
122
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
123 x = ptr[0] << 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
124 x |= ptr[1] << 8;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
125 x |= ptr[2] << 16;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
126 x |= ptr[3] << 24;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
127 ptr += 4;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
128
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
129 *pptr = ptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
130 *r = x;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
131 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
132
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
133 // Returns the current cumulative frequency (map it to a symbol yourself!)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
134 static inline uint32_t RansDecGet(RansState* r, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
135 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
136 return *r & ((1u << scale_bits) - 1);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
137 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
138
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
139 // Advances in the bit stream by "popping" a single symbol with range start
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
140 // "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits",
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
141 // and the resulting bytes get written to ptr (which is updated).
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
142 static inline void RansDecAdvance(RansState* r, uint8_t** pptr, uint32_t start, uint32_t freq, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
143 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
144 uint32_t mask = (1u << scale_bits) - 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
145
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
146 // s, x = D(x)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
147 uint32_t x = *r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
148 x = freq * (x >> scale_bits) + (x & mask) - start;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
149
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
150 // renormalize
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
151 if (x < RANS_BYTE_L) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
152 uint8_t* ptr = *pptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
153 do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
154 *pptr = ptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
155 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
156
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
157 *r = x;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
158 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
159
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
160 // --------------------------------------------------------------------------
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
161
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
162 // That's all you need for a full encoder; below here are some utility
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
163 // functions with extra convenience or optimizations.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
164
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
165 // Encoder symbol description
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
166 // This (admittedly odd) selection of parameters was chosen to make
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
167 // RansEncPutSymbol as cheap as possible.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
168 typedef struct {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
169 uint32_t x_max; // (Exclusive) upper bound of pre-normalization interval
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
170 uint32_t rcp_freq; // Fixed-point reciprocal frequency
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
171 uint32_t bias; // Bias
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
172 uint16_t cmpl_freq; // Complement of frequency: (1 << scale_bits) - freq
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
173 uint16_t rcp_shift; // Reciprocal shift
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
174 } RansEncSymbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
175
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
176 // Decoder symbols are straightforward.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
177 typedef struct {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
178 uint16_t start; // Start of range.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
179 uint16_t freq; // Symbol frequency.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
180 } RansDecSymbol;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
181
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
182 // Initializes an encoder symbol to start "start" and frequency "freq"
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
183 static inline void RansEncSymbolInit(RansEncSymbol* s, uint32_t start, uint32_t freq, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
184 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
185 RansAssert(scale_bits <= 16);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
186 RansAssert(start <= (1u << scale_bits));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
187 RansAssert(freq <= (1u << scale_bits) - start);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
188
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
189 // Say M := 1 << scale_bits.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
190 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
191 // The original encoder does:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
192 // x_new = (x/freq)*M + start + (x%freq)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
193 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
194 // The fast encoder does (schematically):
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
195 // q = mul_hi(x, rcp_freq) >> rcp_shift (division)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
196 // r = x - q*freq (remainder)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
197 // x_new = q*M + bias + r (new x)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
198 // plugging in r into x_new yields:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
199 // x_new = bias + x + q*(M - freq)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
200 // =: bias + x + q*cmpl_freq (*)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
201 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
202 // and we can just precompute cmpl_freq. Now we just need to
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
203 // set up our parameters such that the original encoder and
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
204 // the fast encoder agree.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
205
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
206 s->x_max = ((RANS_BYTE_L >> scale_bits) << 8) * freq;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
207 s->cmpl_freq = (uint16_t) ((1 << scale_bits) - freq);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
208 if (freq < 2) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
209 // freq=0 symbols are never valid to encode, so it doesn't matter what
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
210 // we set our values to.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
211 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
212 // freq=1 is tricky, since the reciprocal of 1 is 1; unfortunately,
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
213 // our fixed-point reciprocal approximation can only multiply by values
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
214 // smaller than 1.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
215 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
216 // So we use the "next best thing": rcp_freq=0xffffffff, rcp_shift=0.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
217 // This gives:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
218 // q = mul_hi(x, rcp_freq) >> rcp_shift
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
219 // = mul_hi(x, (1<<32) - 1)) >> 0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
220 // = floor(x - x/(2^32))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
221 // = x - 1 if 1 <= x < 2^32
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
222 // and we know that x>0 (x=0 is never in a valid normalization interval).
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
223 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
224 // So we now need to choose the other parameters such that
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
225 // x_new = x*M + start
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
226 // plug it in:
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
227 // x*M + start (desired result)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
228 // = bias + x + q*cmpl_freq (*)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
229 // = bias + x + (x - 1)*(M - 1) (plug in q=x-1, cmpl_freq)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
230 // = bias + 1 + (x - 1)*M
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
231 // = x*M + (bias + 1 - M)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
232 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
233 // so we have start = bias + 1 - M, or equivalently
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
234 // bias = start + M - 1.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
235 s->rcp_freq = ~0u;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
236 s->rcp_shift = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
237 s->bias = start + (1 << scale_bits) - 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
238 } else {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
239 // Alverson, "Integer Division using reciprocals"
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
240 // shift=ceil(log2(freq))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
241 uint32_t shift = 0;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
242 while (freq > (1u << shift))
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
243 shift++;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
244
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
245 s->rcp_freq = (uint32_t) (((1ull << (shift + 31)) + freq-1) / freq);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
246 s->rcp_shift = shift - 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
247
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
248 // With these values, 'q' is the correct quotient, so we
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
249 // have bias=start.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
250 s->bias = start;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
251 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
252
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
253 s->rcp_shift += 32; // Avoid the extra >>32 in RansEncPutSymbol
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
254 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
255
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
256 // Initialize a decoder symbol to start "start" and frequency "freq"
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
257 static inline void RansDecSymbolInit(RansDecSymbol* s, uint32_t start, uint32_t freq)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
258 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
259 RansAssert(start <= (1 << 16));
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
260 RansAssert(freq <= (1 << 16) - start);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
261 s->start = (uint16_t) start;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
262 s->freq = (uint16_t) freq;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
263 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
264
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
265 // Encodes a given symbol. This is faster than straight RansEnc since we can do
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
266 // multiplications instead of a divide.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
267 //
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
268 // See RansEncSymbolInit for a description of how this works.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
269 static inline void RansEncPutSymbol(RansState* r, uint8_t** pptr, RansEncSymbol const* sym)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
270 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
271 RansAssert(sym->x_max != 0); // can't encode symbol with freq=0
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
272
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
273 // renormalize
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
274 uint32_t x = *r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
275 uint32_t x_max = sym->x_max;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
276
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
277 if (x >= x_max) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
278 uint8_t* ptr = *pptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
279 do {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
280 *--ptr = (uint8_t) (x & 0xff);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
281 x >>= 8;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
282 } while (x >= x_max);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
283 *pptr = ptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
284 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
285
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
286 // x = C(s,x)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
287 // NOTE: written this way so we get a 32-bit "multiply high" when
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
288 // available. If you're on a 64-bit platform with cheap multiplies
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
289 // (e.g. x64), just bake the +32 into rcp_shift.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
290 //uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> 32) >> sym->rcp_shift;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
291
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
292 // The extra >>32 has already been added to RansEncSymbolInit
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
293 uint32_t q = (uint32_t) (((uint64_t)x * sym->rcp_freq) >> sym->rcp_shift);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
294 *r = x + sym->bias + q * sym->cmpl_freq;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
295 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
296
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
297 // Equivalent to RansDecAdvance that takes a symbol.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
298 static inline void RansDecAdvanceSymbol(RansState* r, uint8_t** pptr, RansDecSymbol const* sym, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
299 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
300 RansDecAdvance(r, pptr, sym->start, sym->freq, scale_bits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
301 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
302
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
303 // Advances in the bit stream by "popping" a single symbol with range start
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
304 // "start" and frequency "freq". All frequencies are assumed to sum to "1 << scale_bits".
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
305 // No renormalization or output happens.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
306 static inline void RansDecAdvanceStep(RansState* r, uint32_t start, uint32_t freq, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
307 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
308 uint32_t mask = (1u << scale_bits) - 1;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
309
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
310 // s, x = D(x)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
311 uint32_t x = *r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
312 *r = freq * (x >> scale_bits) + (x & mask) - start;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
313 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
314
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
315 // Equivalent to RansDecAdvanceStep that takes a symbol.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
316 static inline void RansDecAdvanceSymbolStep(RansState* r, RansDecSymbol const* sym, uint32_t scale_bits)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
317 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
318 RansDecAdvanceStep(r, sym->start, sym->freq, scale_bits);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
319 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
320
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
321 // Renormalize.
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
322 static inline void RansDecRenorm(RansState* r, uint8_t** pptr)
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
323 {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
324 // renormalize
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
325 uint32_t x = *r;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
326
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
327 if (x < RANS_BYTE_L) {
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
328 uint8_t* ptr = *pptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
329 do x = (x << 8) | *ptr++; while (x < RANS_BYTE_L);
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
330 *pptr = ptr;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
331 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
332
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
333 *r = x;
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
334 }
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
335
dfa3745e5fd8 Uploaded
youngkim
parents:
diff changeset
336 #endif // RANS_BYTE_HEADER