Skip to main content

msrtc_rans_core/
raw.rs

1// Copyright (c) Infinity Abundance.
2// Licensed under the MIT license.
3
4//! Raw rANS encoder/decoder implementations for both RansByte and Rans64 variants.
5//!
6//! The code is generated via a macro to avoid duplication while matching the
7//! C++ template structure exactly.
8//!
9//! # Scale-bits edge cases
10//!
11//! When `scale_bits == 32` (the maximum for Rans64), the expression `1u32 << scale_bits`
12//! overflows in Rust (and is undefined behavior in C++). The upstream C++ code also
13//! enters indefinite shift territory here. This implementation defines the behavior
14//! deterministically: `scale_bits == 32` is **rejected** for the prepared-symbol path
15//! where it would cause overflow, matching an intentional safety divergence.
16//! See residual `MSRTC.RAW.SCALE32`.
17
18use crate::Freq;
19use crate::arithmetic;
20#[allow(unused_imports)]
21use crate::sink::Sink;
22#[allow(unused_imports)]
23use crate::source::Source;
24
25// ###########################################################################
26// Macro: generate_rans_impl
27// ###########################################################################
28// Generates encoder, decoder, and symbol types for a given state/unit pair.
29
30macro_rules! generate_rans_impl {
31    (
32        $enc_symbol:ident,   // EncSymbol type name
33        $dec_symbol:ident,   // DecSymbol type name
34        $encoder:ident,      // Encoder type name
35        $decoder:ident,      // Decoder type name
36        $state_ty:ty,        // State type (u32, u64)
37        $unit_ty:ty,         // Unit type (u8, u32)
38        $state_bits:expr,    // STATE_BITS constant
39        $max_scale_bits:expr,// MAX_SCALE_BITS constant
40        $lower_bound:expr,   // LOWER_BOUND constant
41        $unit_bits:expr,     // UNIT_BITS constant
42        $units_per_state:expr, // UNITS_PER_STATE constant
43    ) => {
44        /// Prepared encoder symbol.
45        #[derive(Debug, Clone, Copy)]
46        pub struct $enc_symbol {
47            pub x_max_hi: Freq,
48            pub freq_rcp_shift: u32,
49            pub freq_rcp: $state_ty,
50            pub freq_cmpl: Freq,
51            pub bias: Freq,
52        }
53
54        impl $enc_symbol {
55            /// Create a new prepared encoder symbol.
56            #[inline]
57            pub fn new(start: Freq, freq: Freq, scale_bits: Freq) -> Self {
58                let scale = 1u32 << scale_bits;
59                debug_assert!(
60                    0 < scale_bits && scale_bits as u32 <= $max_scale_bits,
61                    "invalid scale_bits"
62                );
63                debug_assert!(start < scale, "start out of range");
64                debug_assert!(freq > 0 && freq <= scale - start, "freq out of range");
65
66                let min_bits =
67                    core::cmp::min($state_bits, (core::mem::size_of::<Freq>() * 8 - 1) as u32);
68                let x_max_hi = freq << (min_bits - scale_bits);
69
70                let (freq_rcp, mut freq_rcp_shift, bias) = if freq > 1 {
71                    let shift = arithmetic::reciprocal_shift(freq);
72                    let rcp: $state_ty = if core::mem::size_of::<$state_ty>() >= 8 {
73                        arithmetic::compute_reciprocal_u64(freq) as $state_ty
74                    } else {
75                        arithmetic::compute_reciprocal_u32(freq) as $state_ty
76                    };
77                    (rcp, shift - 1, start)
78                } else {
79                    let rcp: $state_ty = if core::mem::size_of::<$state_ty>() >= 8 {
80                        !0u64 as $state_ty
81                    } else {
82                        !0u32 as $state_ty
83                    };
84                    let bias_adj = start + scale - 1;
85                    (rcp, 0, bias_adj)
86                };
87
88                if core::mem::size_of::<$state_ty>() < 8 {
89                    freq_rcp_shift += (core::mem::size_of::<$state_ty>() * 8) as u32;
90                }
91
92                let freq_cmpl = scale - freq;
93
94                Self {
95                    x_max_hi,
96                    freq_rcp_shift,
97                    freq_rcp,
98                    freq_cmpl,
99                    bias,
100                }
101            }
102
103            /// Compute quotient: fast division using precomputed reciprocal.
104            #[inline]
105            pub fn quotient(&self, x: $state_ty) -> $state_ty {
106                if core::mem::size_of::<$state_ty>() >= 8 {
107                    let x_u64 = x as u64;
108                    let rcp_u64 = self.freq_rcp as u64;
109                    arithmetic::fast_quotient_u64(x_u64, rcp_u64, self.freq_rcp_shift) as $state_ty
110                } else {
111                    let x_u32 = x as u32;
112                    let rcp_u32 = self.freq_rcp as u32;
113                    arithmetic::fast_quotient_u32(x_u32, rcp_u32, self.freq_rcp_shift) as $state_ty
114                }
115            }
116        }
117
118        /// Prepared decoder symbol.
119        #[derive(Debug, Clone, Copy)]
120        pub struct $dec_symbol {
121            pub freq: Freq,
122            pub start: Freq,
123        }
124
125        impl $dec_symbol {
126            /// Create a new decoder symbol.
127            #[inline]
128            pub fn new(start: Freq, freq: Freq) -> Self {
129                debug_assert!(freq > 0, "frequency must be positive");
130                Self { freq, start }
131            }
132        }
133
134        /// Raw rANS encoder.
135        #[derive(Debug)]
136        pub struct $encoder<Sk: Sink<$unit_ty>> {
137            sink: Sk,
138            state: $state_ty,
139        }
140
141        impl<Sk: Sink<$unit_ty>> $encoder<Sk> {
142            #[inline]
143            pub fn new(sink: Sk) -> Self {
144                Self {
145                    sink,
146                    state: $lower_bound,
147                }
148            }
149
150            #[inline]
151            pub fn sink(&self) -> &Sk {
152                &self.sink
153            }
154            #[inline]
155            pub fn sink_mut(&mut self) -> &mut Sk {
156                &mut self.sink
157            }
158            #[inline]
159            pub fn into_sink(self) -> Sk {
160                self.sink
161            }
162            #[inline]
163            pub fn state(&self) -> $state_ty {
164                self.state
165            }
166            #[inline]
167            pub fn reset(&mut self) {
168                self.state = $lower_bound;
169            }
170
171            /// Put a raw symbol (start, freq, scale_bits) using division.
172            #[inline]
173            pub fn put_raw(&mut self, start: Freq, freq: Freq, scale_bits: Freq) {
174                debug_assert!(0 < scale_bits && scale_bits as u32 <= $max_scale_bits);
175                debug_assert!(start < (1u32 << scale_bits));
176                debug_assert!(freq > 0 && freq <= (1u32 << scale_bits) - start);
177
178                let x_max: $state_ty = (freq as $state_ty) << ($state_bits - scale_bits as u32);
179                let x = self.renormalize(x_max);
180
181                let shift = scale_bits as u32;
182                self.state = ((x / freq as $state_ty) << shift)
183                    + (start as $state_ty)
184                    + (x % freq as $state_ty);
185            }
186
187            /// Put a prepared symbol (fast reciprocal-multiply path).
188            #[inline]
189            pub fn put(&mut self, symbol: &$enc_symbol) {
190                let mut x_max = symbol.x_max_hi as $state_ty;
191                if $state_bits > (core::mem::size_of::<Freq>() * 8 - 1) as u32 {
192                    let shift =
193                        ($state_bits - (core::mem::size_of::<Freq>() * 8 - 1) as u32) as usize;
194                    x_max = x_max << shift;
195                }
196                let x = self.renormalize(x_max);
197
198                let q = symbol.quotient(x);
199                self.state = x + (q * symbol.freq_cmpl as $state_ty) + symbol.bias as $state_ty;
200            }
201
202            /// Flush the encoder state to the sink.
203            #[inline]
204            pub fn flush(&mut self) {
205                let x = self.state;
206                for i in (1..$units_per_state).rev() {
207                    let shift = i * $unit_bits as usize;
208                    self.sink.write((x >> shift) as $unit_ty);
209                }
210                self.sink.write(x as $unit_ty);
211            }
212
213            #[inline]
214            fn renormalize(&mut self, x_max: $state_ty) -> $state_ty {
215                let mut x = self.state;
216                while x >= x_max {
217                    self.sink.write(x as $unit_ty);
218                    x >>= $unit_bits;
219                    if $max_scale_bits <= $unit_bits {
220                        debug_assert!(x < x_max);
221                        break;
222                    }
223                }
224                x
225            }
226        }
227
228        /// Raw rANS decoder.
229        #[derive(Debug)]
230        pub struct $decoder<Sr: Source<$unit_ty>> {
231            source: Sr,
232            state: $state_ty,
233        }
234
235        impl<Sr: Source<$unit_ty>> $decoder<Sr> {
236            #[inline]
237            pub fn new(source: Sr) -> Self {
238                Self {
239                    source,
240                    state: $lower_bound,
241                }
242            }
243
244            #[inline]
245            pub fn source(&self) -> &Sr {
246                &self.source
247            }
248            #[inline]
249            pub fn source_mut(&mut self) -> &mut Sr {
250                &mut self.source
251            }
252            #[inline]
253            pub fn into_source(self) -> Sr {
254                self.source
255            }
256            #[inline]
257            pub fn state(&self) -> $state_ty {
258                self.state
259            }
260            #[inline]
261            pub fn check_eof(&self) -> bool {
262                self.state == $lower_bound
263            }
264
265            /// Initialize the decoder by reading the initial state from the source.
266            #[inline]
267            pub fn init(&mut self) -> bool {
268                let mut unit = <$unit_ty>::default();
269                if !self.source.read(&mut unit) {
270                    return false;
271                }
272                let mut x = unit as $state_ty;
273
274                for i in 1..$units_per_state {
275                    if !self.source.read(&mut unit) {
276                        return false;
277                    }
278                    x = x.wrapping_add((unit as $state_ty) << (i * $unit_bits as usize));
279                }
280
281                if x < $lower_bound {
282                    return false;
283                }
284                self.state = x;
285                true
286            }
287
288            /// Get the next symbol frequency (low `scale_bits` of state).
289            #[inline]
290            pub fn get(&self, scale_bits: Freq) -> Freq {
291                let mask = (1u32 << scale_bits) - 1;
292                (self.state as Freq) & mask
293            }
294
295            /// Advance the decoder past a symbol.
296            ///
297            /// Uses transactional state: computes into a local variable and only
298            /// assigns to `self.state` after renormalization succeeds.
299            ///
300            /// Equivalent to: `RansDecoder::Advance(start, freq, scale_bits)`.
301            #[inline]
302            pub fn advance(&mut self, start: Freq, freq: Freq, scale_bits: Freq) -> bool {
303                let scale = 1u32 << scale_bits;
304                debug_assert!(start < scale);
305                debug_assert!(freq > 0 && freq <= scale - start);
306
307                let x = self.state;
308                let mask = (scale - 1) as $state_ty;
309                let value = x & mask;
310                debug_assert!(value >= start as $state_ty);
311
312                // Compute new state into a LOCAL — do not mutate self.state yet
313                let shift = scale_bits as u32;
314                let mut x_new = (freq as $state_ty) * (x >> shift) + (value - start as $state_ty);
315
316                // Renormalize using local state; reads source but does not commit
317                let mut renorm_unit = <$unit_ty>::default();
318                while x_new < $lower_bound {
319                    if !self.source.read(&mut renorm_unit) {
320                        return false;
321                    }
322                    x_new = (x_new << $unit_bits) + renorm_unit as $state_ty;
323                    if $max_scale_bits <= $unit_bits {
324                        debug_assert!(x_new >= $lower_bound);
325                        break;
326                    }
327                }
328
329                // All reads succeeded — commit the new state
330                self.state = x_new;
331                true
332            }
333
334            /// Advance using a prepared decoder symbol.
335            #[inline]
336            pub fn advance_symbol(&mut self, symbol: &$dec_symbol, scale_bits: Freq) -> bool {
337                self.advance(symbol.start, symbol.freq, scale_bits)
338            }
339        }
340    };
341}
342
343// ###########################################################################
344// Generate implementations for both variants
345// ###########################################################################
346
347generate_rans_impl! {
348    RansByteEncSymbol,    // enc symbol name
349    RansByteDecSymbol,    // dec symbol name
350    RansByteEncoder,      // encoder name
351    RansByteDecoder,      // decoder name
352    u32, u8,              // state, unit types
353    31,                   // STATE_BITS
354    30,                   // MAX_SCALE_BITS
355    1u32 << 23,           // LOWER_BOUND
356    8,                    // UNIT_BITS
357    4,                    // UNITS_PER_STATE
358}
359
360generate_rans_impl! {
361    Rans64EncSymbol,    // enc symbol name
362    Rans64DecSymbol,    // dec symbol name
363    Rans64Encoder,      // encoder name
364    Rans64Decoder,      // decoder name
365    u64, u32,           // state, unit types
366    63,                 // STATE_BITS
367    32,                 // MAX_SCALE_BITS
368    1u64 << 31,         // LOWER_BOUND
369    32,                 // UNIT_BITS
370    2,                  // UNITS_PER_STATE
371}
372
373// ###########################################################################
374// Tests
375// ###########################################################################
376
377#[cfg(test)]
378mod tests {
379    use super::*;
380    use crate::sink::VecSink;
381    use crate::source::SliceSource;
382
383    // ---- RansByte tests ----
384
385    #[test]
386    fn test_ransbyte_initial_state() {
387        let sink = VecSink::<u8>::new(64);
388        let encoder = RansByteEncoder::new(sink);
389        assert_eq!(encoder.state(), 1u32 << 23);
390    }
391
392    #[test]
393    fn test_ransbyte_raw_roundtrip() {
394        let sink = VecSink::<u8>::new(64);
395        let mut encoder = RansByteEncoder::new(sink);
396        encoder.put_raw(0, 128, 8);
397        encoder.flush();
398        let encoded = encoder.into_sink().encoded().to_vec();
399        assert!(!encoded.is_empty());
400
401        let source = SliceSource::new(&encoded[..]);
402        let mut decoder = RansByteDecoder::new(source);
403        assert!(decoder.init());
404
405        let freq_val = decoder.get(8);
406        assert_eq!(freq_val, 0);
407        assert!(decoder.advance(0, 128, 8));
408        assert!(decoder.check_eof());
409    }
410
411    #[test]
412    fn test_ransbyte_prepared_symbol_matches_raw() {
413        let sink1 = VecSink::<u8>::new(64);
414        let mut enc1 = RansByteEncoder::new(sink1);
415        enc1.put_raw(0, 128, 8);
416        enc1.flush();
417        let out1 = enc1.into_sink().encoded().to_vec();
418
419        let sink2 = VecSink::<u8>::new(64);
420        let mut enc2 = RansByteEncoder::new(sink2);
421        let sym = RansByteEncSymbol::new(0, 128, 8);
422        enc2.put(&sym);
423        enc2.flush();
424        let out2 = enc2.into_sink().encoded().to_vec();
425
426        assert_eq!(out1, out2);
427    }
428
429    #[test]
430    fn test_ransbyte_decoder_rejects_empty() {
431        let data: [u8; 0] = [];
432        let source = SliceSource::new(&data[..]);
433        let mut decoder = RansByteDecoder::new(source);
434        assert!(!decoder.init());
435    }
436
437    #[test]
438    fn test_ransbyte_encoder_reset() {
439        let sink = VecSink::<u8>::new(64);
440        let mut encoder = RansByteEncoder::new(sink);
441        encoder.put_raw(0, 128, 8);
442        encoder.reset();
443        assert_eq!(encoder.state(), 1u32 << 23);
444    }
445
446    // ---- Rans64 tests ----
447
448    #[test]
449    fn test_rans64_initial_state() {
450        let sink = VecSink::<u32>::new(64);
451        let encoder = Rans64Encoder::new(sink);
452        assert_eq!(encoder.state(), 1u64 << 31);
453    }
454
455    #[test]
456    fn test_rans64_raw_roundtrip() {
457        let sink = VecSink::<u32>::new(64);
458        let mut encoder = Rans64Encoder::new(sink);
459        encoder.put_raw(0, 128, 8);
460        encoder.flush();
461        let encoded = encoder.into_sink().encoded().to_vec();
462        assert!(!encoded.is_empty());
463
464        let source = SliceSource::new(&encoded[..]);
465        let mut decoder = Rans64Decoder::new(source);
466        assert!(decoder.init());
467        assert!(decoder.advance(0, 128, 8));
468        assert!(decoder.check_eof());
469    }
470
471    #[test]
472    fn test_rans64_prepared_symbol_matches_raw() {
473        let sink1 = VecSink::<u32>::new(64);
474        let mut enc1 = Rans64Encoder::new(sink1);
475        enc1.put_raw(0, 128, 8);
476        enc1.flush();
477        let out1 = enc1.into_sink().encoded().to_vec();
478
479        let sink2 = VecSink::<u32>::new(64);
480        let mut enc2 = Rans64Encoder::new(sink2);
481        let sym = Rans64EncSymbol::new(0, 128, 8);
482        enc2.put(&sym);
483        enc2.flush();
484        let out2 = enc2.into_sink().encoded().to_vec();
485
486        assert_eq!(out1, out2);
487    }
488
489    #[test]
490    fn test_rans64_encoder_reset() {
491        let sink = VecSink::<u32>::new(64);
492        let mut encoder = Rans64Encoder::new(sink);
493        encoder.put_raw(0, 128, 8);
494        encoder.reset();
495        assert_eq!(encoder.state(), 1u64 << 31);
496    }
497}