1use crate::bitio::{unzigzag, zigzag, BitReader, BitWriter, ByteReader, ByteWriter, DecodeError};
19
20pub const SCALE_BITS: u32 = 14;
22const M: u32 = 1 << SCALE_BITS;
23const RANS_L: u32 = 1 << 23;
24
25pub fn split_uint(u: u64) -> (u32, u64, u32) {
27 if u < 16 {
28 return (u as u32, 0, 0);
29 }
30 let nb = 63 - u.leading_zeros();
31 let m = ((u >> (nb - 2)) & 3) as u32;
32 let token = 16 + 4 * (nb - 4) + m;
33 let extra = nb - 2;
34 (token, u & ((1u64 << extra) - 1), extra)
35}
36
37fn token_base(token: u32) -> (u64, u32) {
39 if token < 16 {
40 return (token as u64, 0);
41 }
42 let t = token - 16;
43 let nb = t / 4 + 4;
44 let m = (t % 4) as u64;
45 (((4 | m) << (nb - 2)), nb - 2)
46}
47
48fn normalize(counts: &[u64]) -> Vec<u32> {
50 let total: u64 = counts.iter().sum();
51 let mut f: Vec<u32> = counts
52 .iter()
53 .map(|&c| {
54 if c == 0 {
55 0
56 } else {
57 (((c as u128) * (M as u128) / (total as u128)) as u32).max(1)
58 }
59 })
60 .collect();
61 let mut sum: i64 = f.iter().map(|&x| x as i64).sum();
62 while sum != M as i64 {
64 let mut order: Vec<usize> = (0..f.len()).filter(|&i| f[i] > 0).collect();
65 order.sort_by(|&a, &b| f[b].cmp(&f[a]).then(a.cmp(&b)));
66 if sum < M as i64 {
67 f[order[0]] += (M as i64 - sum) as u32;
68 sum = M as i64;
69 } else {
70 for &i in &order {
71 if sum == M as i64 {
72 break;
73 }
74 let can = (f[i] - 1) as i64;
75 let take = can.min(sum - M as i64);
76 f[i] -= take as u32;
77 sum -= take;
78 }
79 }
80 }
81 f
82}
83
84struct Model {
86 freq: Vec<u32>,
87 start: Vec<u32>,
88 lut: Vec<u16>,
90}
91
92impl Model {
93 fn new(freq: Vec<u32>) -> Result<Self, DecodeError> {
94 let mut start = Vec::with_capacity(freq.len());
95 let mut acc = 0u32;
96 for &f in &freq {
97 start.push(acc);
98 acc = acc.checked_add(f).ok_or(DecodeError::Invalid("freq sum"))?;
99 }
100 if acc != M {
101 return Err(DecodeError::Invalid("freq table does not sum to 2^14"));
102 }
103 let mut lut = vec![0u16; M as usize];
104 for (s, (&st, &f)) in start.iter().zip(&freq).enumerate() {
105 for slot in lut.iter_mut().skip(st as usize).take(f as usize) {
106 *slot = s as u16;
107 }
108 }
109 Ok(Self { freq, start, lut })
110 }
111}
112
113fn write_table(w: &mut ByteWriter, freq: &[u32]) {
114 w.varint(freq.len() as u64);
115 for &f in freq {
116 w.varint(f as u64);
117 }
118}
119
120fn read_table(r: &mut ByteReader) -> Result<Vec<u32>, DecodeError> {
121 let n = r.varint()? as usize;
122 if n == 0 || n > 300 {
123 return Err(DecodeError::Invalid("alphabet size"));
124 }
125 (0..n).map(|_| Ok(r.varint()? as u32)).collect()
126}
127
128fn token_counts<'a>(vals: impl Iterator<Item = &'a i64>) -> Vec<u64> {
129 let mut counts = vec![0u64; 16];
130 for &v in vals {
131 let (t, _, _) = split_uint(zigzag(v));
132 if t as usize >= counts.len() {
133 counts.resize(t as usize + 1, 0);
134 }
135 counts[t as usize] += 1;
136 }
137 while counts.len() > 1 && *counts.last().unwrap() == 0 {
138 counts.pop();
139 }
140 counts
141}
142
143fn encode_with(vals: &[i64], model: &Model) -> (Vec<u8>, Vec<u8>) {
145 let mut bits = BitWriter::new();
146 let mut toks = Vec::with_capacity(vals.len());
147 for &v in vals {
148 let (t, e, n) = split_uint(zigzag(v));
149 bits.put(e, n);
150 toks.push(t);
151 }
152 let mut out = Vec::new();
153 let mut x: u32 = RANS_L;
154 for &t in toks.iter().rev() {
155 let f = model.freq[t as usize];
156 let x_max = ((RANS_L >> SCALE_BITS) << 8) * f;
157 while x >= x_max {
158 out.push(x as u8);
159 x >>= 8;
160 }
161 x = ((x / f) << SCALE_BITS) + (x % f) + model.start[t as usize];
162 }
163 out.extend_from_slice(&x.to_le_bytes());
164 out.reverse();
165 (out, bits.finish())
166}
167
168fn decode_with(n: usize, model: &Model, rans: &[u8], raw: &[u8]) -> Result<Vec<i64>, DecodeError> {
169 if rans.len() < 4 {
170 return Err(DecodeError::Truncated);
171 }
172 let mut x = u32::from_be_bytes(rans[..4].try_into().unwrap());
173 let mut pos = 4;
174 let mut bits = BitReader::new(raw);
175 let mut out = Vec::with_capacity(n);
176 for _ in 0..n {
177 let slot = x & (M - 1);
178 let t = model.lut[slot as usize] as u32;
179 x = model.freq[t as usize] * (x >> SCALE_BITS) + slot - model.start[t as usize];
180 while x < RANS_L {
181 let b = *rans.get(pos).ok_or(DecodeError::Truncated)?;
182 pos += 1;
183 x = (x << 8) | b as u32;
184 }
185 let (base, nextra) = token_base(t);
186 let u = base + bits.get(nextra)?;
187 out.push(unzigzag(u));
188 }
189 Ok(out)
190}
191
192fn encode_single(w: &mut ByteWriter, vals: &[i64]) {
194 let freq = normalize(&token_counts(vals.iter()));
195 write_table(w, &freq);
196 let model = Model::new(freq).expect("normalised table");
197 let (rans, raw) = encode_with(vals, &model);
198 w.block(&rans);
199 w.block(&raw);
200}
201
202pub fn encode_blocks(w: &mut ByteWriter, blocks: &[&[i64]]) {
206 let total: usize = blocks.iter().map(|b| b.len()).sum();
207 if total == 0 {
208 return;
209 }
210 let mut shared = ByteWriter::new();
212 {
213 let all: Vec<i64> = blocks.iter().flat_map(|b| b.iter().copied()).collect();
214 encode_single(&mut shared, &all);
215 }
216 let mut per = ByteWriter::new();
218 for b in blocks {
219 if !b.is_empty() {
220 encode_single(&mut per, b);
221 }
222 }
223 if shared.buf.len() <= per.buf.len() {
224 w.u8(0);
225 w.bytes(&shared.buf);
226 } else {
227 w.u8(1);
228 w.bytes(&per.buf);
229 }
230}
231
232fn decode_single(r: &mut ByteReader, n: usize) -> Result<Vec<i64>, DecodeError> {
233 let model = Model::new(read_table(r)?)?;
234 let rans = r.block()?;
235 let raw = r.block()?;
236 decode_with(n, &model, rans, raw)
237}
238
239pub fn decode_blocks(r: &mut ByteReader, lens: &[usize]) -> Result<Vec<Vec<i64>>, DecodeError> {
241 let total: usize = lens.iter().sum();
242 if total == 0 {
243 return Ok(lens.iter().map(|_| Vec::new()).collect());
244 }
245 match r.u8()? {
246 0 => {
247 let all = decode_single(r, total)?;
248 let mut out = Vec::with_capacity(lens.len());
249 let mut off = 0;
250 for &l in lens {
251 out.push(all[off..off + l].to_vec());
252 off += l;
253 }
254 Ok(out)
255 }
256 1 => lens
257 .iter()
258 .map(|&l| {
259 if l == 0 {
260 Ok(Vec::new())
261 } else {
262 decode_single(r, l)
263 }
264 })
265 .collect(),
266 _ => Err(DecodeError::Invalid("table mode")),
267 }
268}
269
270pub fn empirical_bits(vals: &[i64]) -> f64 {
273 let counts = token_counts(vals.iter());
274 let n = vals.len() as f64;
275 let mut h = 0.0;
276 for &c in &counts {
277 if c > 0 {
278 let p = c as f64 / n;
279 h -= c as f64 * p.log2();
280 }
281 }
282 let raw: u64 = vals.iter().map(|&v| split_uint(zigzag(v)).2 as u64).sum();
283 h + raw as f64
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289
290 fn lcg(seed: &mut u64) -> u64 {
291 *seed = seed
292 .wrapping_mul(6364136223846793005)
293 .wrapping_add(1442695040888963407);
294 *seed >> 33
295 }
296
297 #[test]
298 fn token_split_is_invertible() {
299 for u in (0..5000u64).chain([1 << 20, (1 << 40) + 12345, u32::MAX as u64]) {
300 let (t, e, n) = split_uint(u);
301 let (base, nb) = token_base(t);
302 assert_eq!(nb, n);
303 assert_eq!(base + e, u, "u={u}");
304 }
305 }
306
307 #[test]
308 fn rans_roundtrip_and_near_entropy() {
309 let mut seed = 7u64;
310 let a: Vec<i64> = (0..20000)
312 .map(|_| {
313 let r = lcg(&mut seed) % 1000;
314 let mag = (-(1.0 - r as f64 / 1000.0).ln() * 3.0) as i64;
315 if lcg(&mut seed) & 1 == 0 {
316 mag
317 } else {
318 -mag
319 }
320 })
321 .collect();
322 let b: Vec<i64> = vec![5; 300];
323 let c: Vec<i64> = (0..500).map(|i| (i * i) as i64 - 100_000).collect();
324 let mut w = ByteWriter::new();
325 encode_blocks(&mut w, &[&a, &b, &[], &c]);
326 let mut r = ByteReader::new(&w.buf);
327 let out = decode_blocks(&mut r, &[a.len(), b.len(), 0, c.len()]).unwrap();
328 assert_eq!(out[0], a);
329 assert_eq!(out[1], b);
330 assert!(out[2].is_empty());
331 assert_eq!(out[3], c);
332 assert_eq!(r.position(), w.buf.len());
333 let mut wa = ByteWriter::new();
335 encode_blocks(&mut wa, &[&a]);
336 let ideal = empirical_bits(&a) / 8.0;
337 let actual = wa.buf.len() as f64;
338 assert!(
339 actual < ideal * 1.02 + 64.0,
340 "actual {actual} ideal {ideal}"
341 );
342 }
343
344 #[test]
345 fn rans_is_deterministic() {
346 let v: Vec<i64> = (0..1000).map(|i| (i % 17) - 8).collect();
347 let mut w1 = ByteWriter::new();
348 let mut w2 = ByteWriter::new();
349 encode_blocks(&mut w1, &[&v]);
350 encode_blocks(&mut w2, &[&v]);
351 assert_eq!(w1.buf, w2.buf);
352 }
353}