dsi_bitstream/codes/
delta.rs1use super::delta_tables;
44use super::gamma::{GammaReadParam, GammaWriteParam, len_gamma_param};
45use crate::traits::*;
46
47#[must_use]
49#[inline(always)]
50pub const fn len_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
51 n: u64,
52) -> usize {
53 debug_assert!(n < u64::MAX);
54 if USE_DELTA_TABLE {
55 if n < delta_tables::LEN.len() as u64 {
57 return delta_tables::LEN[n as usize] as usize;
58 }
59 }
60 let λ = (n + 1).ilog2();
61 λ as usize + len_gamma_param::<USE_GAMMA_TABLE>(λ as _)
62}
63
64#[must_use]
67#[inline(always)]
68pub const fn len_delta(n: u64) -> usize {
69 #[cfg(target_arch = "arm")]
70 return len_delta_param::<false, false>(n);
71 #[cfg(not(target_arch = "arm"))]
72 return len_delta_param::<false, true>(n);
73}
74
75pub trait DeltaRead<E: Endianness>: BitRead<E> {
79 fn read_delta(&mut self) -> Result<u64, Self::Error>;
80}
81
82pub trait DeltaReadParam<E: Endianness>: GammaReadParam<E> {
91 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
92 &mut self,
93 ) -> Result<u64, Self::Error>;
94}
95
96#[inline(always)]
99fn default_read_delta<E: Endianness, B: GammaReadParam<E>, const USE_GAMMA_TABLE: bool>(
100 backend: &mut B,
101) -> Result<u64, B::Error> {
102 let len = backend.read_gamma_param::<USE_GAMMA_TABLE>()?;
103 debug_assert!(len < 64);
104 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
105}
106
107impl<B: GammaReadParam<BE>> DeltaReadParam<BE> for B {
108 #[inline(always)]
109 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
110 &mut self,
111 ) -> Result<u64, B::Error> {
112 const {
113 if USE_DELTA_TABLE {
114 delta_tables::check_read_table(B::PEEK_BITS)
115 }
116 }
117 if USE_DELTA_TABLE {
118 let (len_with_flag, value_or_gamma) = delta_tables::read_table_be(self);
119 if len_with_flag > 0 {
120 return Ok(value_or_gamma);
122 } else if len_with_flag < 0 {
123 let gamma_len = value_or_gamma;
126 debug_assert!(gamma_len < 64);
127 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
128 }
129 }
131 default_read_delta::<BE, _, USE_GAMMA_TABLE>(self)
132 }
133}
134
135impl<B: GammaReadParam<LE>> DeltaReadParam<LE> for B {
136 #[inline(always)]
137 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
138 &mut self,
139 ) -> Result<u64, B::Error> {
140 const {
141 if USE_DELTA_TABLE {
142 delta_tables::check_read_table(B::PEEK_BITS)
143 }
144 }
145 if USE_DELTA_TABLE {
146 let (len_with_flag, value_or_gamma) = delta_tables::read_table_le(self);
147 if len_with_flag > 0 {
148 return Ok(value_or_gamma);
150 } else if len_with_flag < 0 {
151 let gamma_len = value_or_gamma;
154 debug_assert!(gamma_len < 64);
155 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
156 }
157 }
159 default_read_delta::<LE, _, USE_GAMMA_TABLE>(self)
160 }
161}
162
163pub trait DeltaWrite<E: Endianness>: BitWrite<E> {
167 fn write_delta(&mut self, n: u64) -> Result<usize, Self::Error>;
168}
169
170pub trait DeltaWriteParam<E: Endianness>: GammaWriteParam<E> {
179 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
180 &mut self,
181 n: u64,
182 ) -> Result<usize, Self::Error>;
183}
184
185impl<B: GammaWriteParam<BE>> DeltaWriteParam<BE> for B {
186 #[inline(always)]
187 #[allow(clippy::collapsible_if)]
188 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
189 &mut self,
190 n: u64,
191 ) -> Result<usize, Self::Error> {
192 if USE_DELTA_TABLE {
193 if let Some(len) = delta_tables::write_table_be(self, n)? {
194 return Ok(len);
195 }
196 }
197 default_write_delta::<BE, _, USE_GAMMA_TABLE>(self, n)
198 }
199}
200
201impl<B: GammaWriteParam<LE>> DeltaWriteParam<LE> for B {
202 #[inline(always)]
203 #[allow(clippy::collapsible_if)]
204 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
205 &mut self,
206 n: u64,
207 ) -> Result<usize, Self::Error> {
208 if USE_DELTA_TABLE {
209 if let Some(len) = delta_tables::write_table_le(self, n)? {
210 return Ok(len);
211 }
212 }
213 default_write_delta::<LE, _, USE_GAMMA_TABLE>(self, n)
214 }
215}
216
217#[inline(always)]
220fn default_write_delta<E: Endianness, B: GammaWriteParam<E>, const USE_GAMMA_TABLE: bool>(
221 backend: &mut B,
222 mut n: u64,
223) -> Result<usize, B::Error> {
224 debug_assert!(n < u64::MAX);
225 n += 1;
226 let λ = n.ilog2();
227
228 #[cfg(feature = "checks")]
229 {
230 n ^= 1 << λ;
232 }
233
234 Ok(backend.write_gamma_param::<USE_GAMMA_TABLE>(λ as _)? + backend.write_bits(n, λ as _)?)
235}