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 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#[must_use]
60#[inline(always)]
61pub fn len_delta(n: u64) -> usize {
62 #[cfg(target_arch = "arm")]
63 return len_delta_param::<false, false>(n);
64 #[cfg(not(target_arch = "arm"))]
65 return len_delta_param::<false, true>(n);
66}
67
68pub trait DeltaRead<E: Endianness>: BitRead<E> {
72 fn read_delta(&mut self) -> Result<u64, Self::Error>;
73}
74
75pub trait DeltaReadParam<E: Endianness>: GammaReadParam<E> {
84 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
85 &mut self,
86 ) -> Result<u64, Self::Error>;
87}
88
89#[inline(always)]
92fn default_read_delta<E: Endianness, B: GammaReadParam<E>, const USE_GAMMA_TABLE: bool>(
93 backend: &mut B,
94) -> Result<u64, B::Error> {
95 let len = backend.read_gamma_param::<USE_GAMMA_TABLE>()?;
96 debug_assert!(len < 64);
97 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
98}
99
100impl<B: GammaReadParam<BE>> DeltaReadParam<BE> for B {
101 #[inline(always)]
102 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
103 &mut self,
104 ) -> Result<u64, B::Error> {
105 const {
106 if USE_DELTA_TABLE {
107 delta_tables::check_read_table(B::PEEK_BITS)
108 }
109 }
110 if USE_DELTA_TABLE {
111 let (len_with_flag, value_or_gamma) = delta_tables::read_table_be(self);
112 if len_with_flag > 0 {
113 return Ok(value_or_gamma);
115 } else if len_with_flag < 0 {
116 let gamma_len = value_or_gamma;
119 debug_assert!(gamma_len < 64);
120 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
121 }
122 }
124 default_read_delta::<BE, _, USE_GAMMA_TABLE>(self)
125 }
126}
127
128impl<B: GammaReadParam<LE>> DeltaReadParam<LE> for B {
129 #[inline(always)]
130 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
131 &mut self,
132 ) -> Result<u64, B::Error> {
133 const {
134 if USE_DELTA_TABLE {
135 delta_tables::check_read_table(B::PEEK_BITS)
136 }
137 }
138 if USE_DELTA_TABLE {
139 let (len_with_flag, value_or_gamma) = delta_tables::read_table_le(self);
140 if len_with_flag > 0 {
141 return Ok(value_or_gamma);
143 } else if len_with_flag < 0 {
144 let gamma_len = value_or_gamma;
147 debug_assert!(gamma_len < 64);
148 return Ok(self.read_bits(gamma_len as usize)? + (1 << gamma_len) - 1);
149 }
150 }
152 default_read_delta::<LE, _, USE_GAMMA_TABLE>(self)
153 }
154}
155
156pub trait DeltaWrite<E: Endianness>: BitWrite<E> {
160 fn write_delta(&mut self, n: u64) -> Result<usize, Self::Error>;
161}
162
163pub trait DeltaWriteParam<E: Endianness>: GammaWriteParam<E> {
172 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
173 &mut self,
174 n: u64,
175 ) -> Result<usize, Self::Error>;
176}
177
178impl<B: GammaWriteParam<BE>> DeltaWriteParam<BE> for B {
179 #[inline(always)]
180 #[allow(clippy::collapsible_if)]
181 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
182 &mut self,
183 n: u64,
184 ) -> Result<usize, Self::Error> {
185 if USE_DELTA_TABLE {
186 if let Some(len) = delta_tables::write_table_be(self, n)? {
187 return Ok(len);
188 }
189 }
190 default_write_delta::<BE, _, USE_GAMMA_TABLE>(self, n)
191 }
192}
193
194impl<B: GammaWriteParam<LE>> DeltaWriteParam<LE> for B {
195 #[inline(always)]
196 #[allow(clippy::collapsible_if)]
197 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
198 &mut self,
199 n: u64,
200 ) -> Result<usize, Self::Error> {
201 if USE_DELTA_TABLE {
202 if let Some(len) = delta_tables::write_table_le(self, n)? {
203 return Ok(len);
204 }
205 }
206 default_write_delta::<LE, _, USE_GAMMA_TABLE>(self, n)
207 }
208}
209
210#[inline(always)]
213fn default_write_delta<E: Endianness, B: GammaWriteParam<E>, const USE_GAMMA_TABLE: bool>(
214 backend: &mut B,
215 mut n: u64,
216) -> Result<usize, B::Error> {
217 debug_assert!(n < u64::MAX);
218 n += 1;
219 let λ = n.ilog2();
220
221 #[cfg(feature = "checks")]
222 {
223 n ^= 1 << λ;
225 }
226
227 Ok(backend.write_gamma_param::<USE_GAMMA_TABLE>(λ as _)? + backend.write_bits(n, λ as _)?)
228}