dsi_bitstream/codes/
delta.rs1use super::delta_tables;
40use super::gamma::{GammaReadParam, GammaWriteParam, len_gamma_param};
41use crate::traits::*;
42
43#[must_use]
45#[inline(always)]
46pub fn len_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(n: u64) -> usize {
47 debug_assert!(n < u64::MAX);
48 if USE_DELTA_TABLE {
49 if n < delta_tables::LEN.len() as u64 {
51 return delta_tables::LEN[n as usize] as usize;
52 }
53 }
54 let λ = (n + 1).ilog2();
55 λ as usize + len_gamma_param::<USE_GAMMA_TABLE>(λ as _)
56}
57
58#[must_use]
61#[inline(always)]
62pub fn len_delta(n: u64) -> usize {
63 #[cfg(target_arch = "arm")]
64 return len_delta_param::<false, false>(n);
65 #[cfg(not(target_arch = "arm"))]
66 return len_delta_param::<false, true>(n);
67}
68
69pub trait DeltaRead<E: Endianness>: BitRead<E> {
73 fn read_delta(&mut self) -> Result<u64, Self::Error>;
74}
75
76pub trait DeltaReadParam<E: Endianness>: GammaReadParam<E> {
85 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
86 &mut self,
87 ) -> Result<u64, Self::Error>;
88}
89
90#[inline(always)]
93fn default_read_delta<E: Endianness, B: GammaReadParam<E>, const USE_GAMMA_TABLE: bool>(
94 backend: &mut B,
95) -> Result<u64, B::Error> {
96 let len = backend.read_gamma_param::<USE_GAMMA_TABLE>()?;
97 debug_assert!(len < 64);
98 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
99}
100
101impl<B: GammaReadParam<BE>> DeltaReadParam<BE> for B {
102 #[inline(always)]
103 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
104 &mut self,
105 ) -> Result<u64, B::Error> {
106 const {
107 if USE_DELTA_TABLE {
108 delta_tables::check_read_table(B::PEEK_BITS)
109 }
110 }
111 if USE_DELTA_TABLE {
112 let (len_with_flag, value_or_gamma) = delta_tables::read_table_be(self);
113 if len_with_flag > 0 {
114 return Ok(value_or_gamma);
116 } else if len_with_flag < 0 {
117 let gamma_len = value_or_gamma;
120 debug_assert!(gamma_len < 64);
121 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
122 }
123 }
125 default_read_delta::<BE, _, USE_GAMMA_TABLE>(self)
126 }
127}
128
129impl<B: GammaReadParam<LE>> DeltaReadParam<LE> for B {
130 #[inline(always)]
131 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
132 &mut self,
133 ) -> Result<u64, B::Error> {
134 const {
135 if USE_DELTA_TABLE {
136 delta_tables::check_read_table(B::PEEK_BITS)
137 }
138 }
139 if USE_DELTA_TABLE {
140 let (len_with_flag, value_or_gamma) = delta_tables::read_table_le(self);
141 if len_with_flag > 0 {
142 return Ok(value_or_gamma);
144 } else if len_with_flag < 0 {
145 let gamma_len = value_or_gamma;
148 debug_assert!(gamma_len < 64);
149 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
150 }
151 }
153 default_read_delta::<LE, _, USE_GAMMA_TABLE>(self)
154 }
155}
156
157pub trait DeltaWrite<E: Endianness>: BitWrite<E> {
161 fn write_delta(&mut self, n: u64) -> Result<usize, Self::Error>;
162}
163
164pub trait DeltaWriteParam<E: Endianness>: GammaWriteParam<E> {
173 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
174 &mut self,
175 n: u64,
176 ) -> Result<usize, Self::Error>;
177}
178
179impl<B: GammaWriteParam<BE>> DeltaWriteParam<BE> for B {
180 #[inline(always)]
181 #[allow(clippy::collapsible_if)]
182 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
183 &mut self,
184 n: u64,
185 ) -> Result<usize, Self::Error> {
186 if USE_DELTA_TABLE {
187 if let Some(len) = delta_tables::write_table_be(self, n)? {
188 return Ok(len);
189 }
190 }
191 default_write_delta::<BE, _, USE_GAMMA_TABLE>(self, n)
192 }
193}
194
195impl<B: GammaWriteParam<LE>> DeltaWriteParam<LE> for B {
196 #[inline(always)]
197 #[allow(clippy::collapsible_if)]
198 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
199 &mut self,
200 n: u64,
201 ) -> Result<usize, Self::Error> {
202 if USE_DELTA_TABLE {
203 if let Some(len) = delta_tables::write_table_le(self, n)? {
204 return Ok(len);
205 }
206 }
207 default_write_delta::<LE, _, USE_GAMMA_TABLE>(self, n)
208 }
209}
210
211#[inline(always)]
214fn default_write_delta<E: Endianness, B: GammaWriteParam<E>, const USE_GAMMA_TABLE: bool>(
215 backend: &mut B,
216 mut n: u64,
217) -> Result<usize, B::Error> {
218 debug_assert!(n < u64::MAX);
219 n += 1;
220 let λ = n.ilog2();
221
222 #[cfg(feature = "checks")]
223 {
224 n ^= 1 << λ;
226 }
227
228 Ok(backend.write_gamma_param::<USE_GAMMA_TABLE>(λ as _)? + backend.write_bits(n, λ as _)?)
229}