range_encoding/
lib.rs

1/// Implementation of the Opus range encoder.
2pub mod opus {
3    /// A c2rust-ified version of the Opus range decoder.
4    mod imported_decode;
5    mod imported_encode;
6
7    mod decode;
8    mod encode;
9
10    pub use self::decode::Reader;
11    pub use self::encode::Writer;
12}
13
14#[derive(Clone)]
15pub struct Segment {
16    /// First value part of the segment.
17    low: u32,
18
19    /// First value >= low **not** part of the segment.
20    next: u32,
21}
22impl Segment {
23    pub fn new(low: u32, next: u32) -> Segment {
24        Segment { low, next }
25    }
26    pub fn width(&self) -> u32 {
27        self.next - self.low
28    }
29}
30
31pub struct IndexedSegment {
32    pub segment: Segment,
33    pub index: usize,
34}
35
36pub struct CumulativeDistributionFrequency {
37    /// Ordered, contiguous list of segments, starting at 0.
38    segments: Box<[Segment]>,
39
40    /// The width, which is exactly `segments.last.width`.
41    width: u32,
42}
43impl CumulativeDistributionFrequency {
44    pub fn new(probabilities: Vec<u32>) -> Self {
45        let mut segments = Vec::with_capacity(probabilities.len());
46        let mut start = 0;
47        for probability in probabilities {
48            let next = start + probability;
49            segments.push(Segment::new(start, next));
50            start = next;
51        }
52        Self {
53            segments: segments.into_boxed_slice(),
54            width: start,
55        }
56    }
57
58    /// Return the total frequency of symbols in this distribution.
59    pub fn width(&self) -> u32 {
60        self.width
61    }
62
63    /// Iterate through the widths of the symbols.
64    pub fn widths<'a>(&'a self) -> impl Iterator<Item = u32> + 'a {
65        self.segments.iter().map(Segment::width)
66    }
67
68    /// Find a value from its frequency.
69    pub fn find(&self, probability: u32) -> Option<IndexedSegment> {
70        if probability >= self.width {
71            return None;
72        }
73        let index = self
74            .segments
75            .binary_search_by(|segment| {
76                use std::cmp::Ordering;
77                if segment.low > probability {
78                    return Ordering::Greater;
79                }
80                if segment.next <= probability {
81                    return Ordering::Less;
82                }
83                Ordering::Equal
84            })
85            .ok()?;
86        Some(IndexedSegment {
87            index,
88            segment: self.segments[index].clone(),
89        })
90    }
91
92    /// Find a value from its index
93    pub fn at_index<'a>(&'a self, index: usize) -> Option<&'a Segment> {
94        if index >= self.segments.len() {
95            return None;
96        }
97        Some(&self.segments[index])
98    }
99
100    /// Return the number of values in this CDF
101    pub fn len(&self) -> usize {
102        self.segments.len()
103    }
104}