dsi_bitstream/codes/
delta.rs1use super::{GammaReadParam, GammaWriteParam, delta_tables, 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 let Some(idx) = delta_tables::LEN.get(n as usize) {
50 return *idx as usize;
51 }
52 }
53 let λ = (n + 1).ilog2();
54 λ as usize + len_gamma_param::<USE_GAMMA_TABLE>(λ as _)
55}
56
57#[inline(always)]
60pub fn len_delta(n: u64) -> usize {
61 #[cfg(target_arch = "arm")]
62 return len_delta_param::<false, false>(n);
63 #[cfg(not(target_arch = "arm"))]
64 return len_delta_param::<false, true>(n);
65}
66
67pub trait DeltaRead<E: Endianness>: BitRead<E> {
71 fn read_delta(&mut self) -> Result<u64, Self::Error>;
72}
73
74pub trait DeltaReadParam<E: Endianness>: GammaReadParam<E> {
83 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
84 &mut self,
85 ) -> Result<u64, Self::Error>;
86}
87
88#[inline(always)]
91fn default_read_delta<E: Endianness, B: GammaReadParam<E>, const USE_GAMMA_TABLE: bool>(
92 backend: &mut B,
93) -> Result<u64, B::Error> {
94 let len = backend.read_gamma_param::<USE_GAMMA_TABLE>()?;
95 debug_assert!(len < 64);
96 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
97}
98
99impl<B: GammaReadParam<BE>> DeltaReadParam<BE> for B {
100 #[inline(always)]
101 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
102 &mut self,
103 ) -> Result<u64, B::Error> {
104 if USE_DELTA_TABLE {
105 let (len_with_flag, value_or_gamma) = delta_tables::read_table_be(self);
106 if len_with_flag > 0 {
107 return Ok(value_or_gamma);
109 } else if len_with_flag < 0 {
110 let gamma_len = value_or_gamma;
113 debug_assert!(gamma_len < 64);
114 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
115 }
116 }
118 default_read_delta::<BE, _, USE_GAMMA_TABLE>(self)
119 }
120}
121
122impl<B: GammaReadParam<LE>> DeltaReadParam<LE> for B {
123 #[inline(always)]
124 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
125 &mut self,
126 ) -> Result<u64, B::Error> {
127 if USE_DELTA_TABLE {
128 let (len_with_flag, value_or_gamma) = delta_tables::read_table_le(self);
129 if len_with_flag > 0 {
130 return Ok(value_or_gamma);
132 } else if len_with_flag < 0 {
133 let gamma_len = value_or_gamma;
136 debug_assert!(gamma_len < 64);
137 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
138 }
139 }
141 default_read_delta::<LE, _, USE_GAMMA_TABLE>(self)
142 }
143}
144
145pub trait DeltaWrite<E: Endianness>: BitWrite<E> {
149 fn write_delta(&mut self, n: u64) -> Result<usize, Self::Error>;
150}
151
152pub trait DeltaWriteParam<E: Endianness>: GammaWriteParam<E> {
161 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
162 &mut self,
163 n: u64,
164 ) -> Result<usize, Self::Error>;
165}
166
167impl<B: GammaWriteParam<BE>> DeltaWriteParam<BE> for B {
168 #[inline(always)]
169 #[allow(clippy::collapsible_if)]
170 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
171 &mut self,
172 n: u64,
173 ) -> Result<usize, Self::Error> {
174 if USE_DELTA_TABLE {
175 if let Some(len) = delta_tables::write_table_be(self, n)? {
176 return Ok(len);
177 }
178 }
179 default_write_delta::<BE, _, USE_GAMMA_TABLE>(self, n)
180 }
181}
182
183impl<B: GammaWriteParam<LE>> DeltaWriteParam<LE> for B {
184 #[inline(always)]
185 #[allow(clippy::collapsible_if)]
186 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
187 &mut self,
188 n: u64,
189 ) -> Result<usize, Self::Error> {
190 if USE_DELTA_TABLE {
191 if let Some(len) = delta_tables::write_table_le(self, n)? {
192 return Ok(len);
193 }
194 }
195 default_write_delta::<LE, _, USE_GAMMA_TABLE>(self, n)
196 }
197}
198
199#[inline(always)]
202fn default_write_delta<E: Endianness, B: GammaWriteParam<E>, const USE_GAMMA_TABLE: bool>(
203 backend: &mut B,
204 mut n: u64,
205) -> Result<usize, B::Error> {
206 debug_assert!(n < u64::MAX);
207 n += 1;
208 let λ = n.ilog2();
209
210 #[cfg(feature = "checks")]
211 {
212 n ^= 1 << λ;
214 }
215
216 Ok(backend.write_gamma_param::<USE_GAMMA_TABLE>(λ as _)? + backend.write_bits(n, λ as _)?)
217}