dsi_bitstream/codes/
delta.rs1use super::{GammaReadParam, GammaWriteParam, delta_tables, len_gamma_param};
31use crate::traits::*;
32
33#[must_use]
35#[inline(always)]
36pub fn len_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(n: u64) -> usize {
37 debug_assert!(n < u64::MAX);
38 if USE_DELTA_TABLE {
39 if let Some(idx) = delta_tables::LEN.get(n as usize) {
40 return *idx as usize;
41 }
42 }
43 let λ = (n + 1).ilog2();
44 λ as usize + len_gamma_param::<USE_GAMMA_TABLE>(λ as _)
45}
46
47#[inline(always)]
50pub fn len_delta(n: u64) -> usize {
51 #[cfg(target_arch = "arm")]
52 return len_delta_param::<false, false>(n);
53 #[cfg(not(target_arch = "arm"))]
54 return len_delta_param::<false, true>(n);
55}
56
57pub trait DeltaRead<E: Endianness>: BitRead<E> {
61 fn read_delta(&mut self) -> Result<u64, Self::Error>;
62}
63
64pub trait DeltaReadParam<E: Endianness>: GammaReadParam<E> {
73 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
74 &mut self,
75 ) -> Result<u64, Self::Error>;
76}
77
78#[inline(always)]
81fn default_read_delta<E: Endianness, B: GammaReadParam<E>, const USE_GAMMA_TABLE: bool>(
82 backend: &mut B,
83) -> Result<u64, B::Error> {
84 let len = backend.read_gamma_param::<USE_GAMMA_TABLE>()?;
85 debug_assert!(len < 64);
86 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
87}
88
89impl<B: GammaReadParam<BE>> DeltaReadParam<BE> for B {
90 #[inline(always)]
91 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
92 &mut self,
93 ) -> Result<u64, B::Error> {
94 if USE_DELTA_TABLE {
95 if let Some((res, _)) = delta_tables::read_table_be(self) {
96 return Ok(res);
97 }
98 }
99 default_read_delta::<BE, _, USE_GAMMA_TABLE>(self)
100 }
101}
102
103impl<B: GammaReadParam<LE>> DeltaReadParam<LE> for B {
104 #[inline(always)]
105 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
106 &mut self,
107 ) -> Result<u64, B::Error> {
108 if USE_DELTA_TABLE {
109 if let Some((res, _)) = delta_tables::read_table_le(self) {
110 return Ok(res);
111 }
112 }
113 default_read_delta::<LE, _, USE_GAMMA_TABLE>(self)
114 }
115}
116
117pub trait DeltaWrite<E: Endianness>: BitWrite<E> {
121 fn write_delta(&mut self, n: u64) -> Result<usize, Self::Error>;
122}
123
124pub trait DeltaWriteParam<E: Endianness>: GammaWriteParam<E> {
133 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
134 &mut self,
135 n: u64,
136 ) -> Result<usize, Self::Error>;
137}
138
139impl<B: GammaWriteParam<BE>> DeltaWriteParam<BE> for B {
140 #[inline(always)]
141 #[allow(clippy::collapsible_if)]
142 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
143 &mut self,
144 n: u64,
145 ) -> Result<usize, Self::Error> {
146 if USE_DELTA_TABLE {
147 if let Some(len) = delta_tables::write_table_be(self, n)? {
148 return Ok(len);
149 }
150 }
151 default_write_delta::<BE, _, USE_GAMMA_TABLE>(self, n)
152 }
153}
154
155impl<B: GammaWriteParam<LE>> DeltaWriteParam<LE> for B {
156 #[inline(always)]
157 #[allow(clippy::collapsible_if)]
158 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
159 &mut self,
160 n: u64,
161 ) -> Result<usize, Self::Error> {
162 if USE_DELTA_TABLE {
163 if let Some(len) = delta_tables::write_table_le(self, n)? {
164 return Ok(len);
165 }
166 }
167 default_write_delta::<LE, _, USE_GAMMA_TABLE>(self, n)
168 }
169}
170
171#[inline(always)]
174fn default_write_delta<E: Endianness, B: GammaWriteParam<E>, const USE_GAMMA_TABLE: bool>(
175 backend: &mut B,
176 mut n: u64,
177) -> Result<usize, B::Error> {
178 debug_assert!(n < u64::MAX);
179 n += 1;
180 let λ = n.ilog2();
181
182 #[cfg(feature = "checks")]
183 {
184 n ^= 1 << λ;
186 }
187
188 Ok(backend.write_gamma_param::<USE_GAMMA_TABLE>(λ as _)? + backend.write_bits(n, λ as _)?)
189}