adder_codec_core/codec/compressed/fenwick/
simple.rs

1// From https://github.com/danieleades/arithmetic-coding. Only temporary, for initial testing.
2#![allow(missing_docs, unused)]
3//! simple adaptive model using a fenwick tree
4
5use arithmetic_coding_adder_dep::Model;
6
7use super::Weights;
8use crate::codec::compressed::fenwick::ValueError;
9
10#[derive(Debug, Clone)]
11pub struct FenwickModel {
12    weights: Weights,
13    max_denominator: u64,
14    panic_on_saturation: bool,
15}
16
17#[must_use]
18pub struct Builder {
19    model: FenwickModel,
20}
21
22impl Builder {
23    fn new(n_symbols: usize, max_denominator: u64) -> Self {
24        let weights = Weights::new(n_symbols);
25        let model = FenwickModel {
26            weights,
27            max_denominator,
28            panic_on_saturation: false,
29        };
30        Self { model }
31    }
32
33    pub fn panic_on_saturation(mut self) -> Self {
34        self.model.panic_on_saturation = true;
35        self
36    }
37
38    #[must_use]
39    pub fn build(self) -> FenwickModel {
40        self.model
41    }
42}
43
44impl FenwickModel {
45    pub fn builder(n_symbols: usize, max_denominator: u64) -> Builder {
46        Builder::new(n_symbols, max_denominator)
47    }
48}
49
50impl Model for FenwickModel {
51    type B = u64;
52    type Symbol = usize;
53    type ValueError = ValueError;
54
55    fn probability(
56        &self,
57        symbol: Option<&Self::Symbol>,
58    ) -> Result<std::ops::Range<Self::B>, Self::ValueError> {
59        if let Some(s) = symbol.copied() {
60            if s >= self.weights.len() {
61                Err(ValueError(s))
62            } else {
63                Ok(self.weights.range(Some(s)))
64            }
65        } else {
66            Ok(self.weights.range(None))
67        }
68    }
69
70    fn max_denominator(&self) -> Self::B {
71        self.max_denominator
72    }
73
74    fn symbol(&self, value: Self::B) -> Option<Self::Symbol> {
75        self.weights.symbol(value)
76    }
77
78    fn denominator(&self) -> Self::B {
79        self.weights.total()
80    }
81
82    fn update(&mut self, symbol: Option<&Self::Symbol>) {
83        if self.panic_on_saturation {
84            debug_assert!(
85                self.denominator() < self.max_denominator,
86                "hit max denominator!"
87            );
88        }
89        if self.denominator() < self.max_denominator {
90            self.weights.update(symbol.copied(), 1);
91        }
92    }
93}