dsi_bitstream/codes/
delta.rs1use super::{delta_tables, len_gamma_param, GammaReadParam, GammaWriteParam};
29use crate::traits::*;
30
31#[must_use]
33#[inline(always)]
34pub fn len_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(n: u64) -> usize {
35 if USE_DELTA_TABLE {
36 if let Some(idx) = delta_tables::LEN.get(n as usize) {
37 return *idx as usize;
38 }
39 }
40 let λ = (n + 1).ilog2();
41 λ as usize + len_gamma_param::<USE_GAMMA_TABLE>(λ as _)
42}
43
44#[inline(always)]
47pub fn len_delta(n: u64) -> usize {
48 #[cfg(target_arch = "arm")]
49 return len_delta_param::<false, false>(n);
50 #[cfg(not(target_arch = "arm"))]
51 return len_delta_param::<false, true>(n);
52}
53
54pub trait DeltaRead<E: Endianness>: BitRead<E> {
58 fn read_delta(&mut self) -> Result<u64, Self::Error>;
59}
60
61pub trait DeltaReadParam<E: Endianness>: GammaReadParam<E> {
70 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
71 &mut self,
72 ) -> Result<u64, Self::Error>;
73}
74
75#[inline(always)]
78fn default_read_delta<E: Endianness, B: GammaReadParam<E>, const USE_GAMMA_TABLE: bool>(
79 backend: &mut B,
80) -> Result<u64, B::Error> {
81 let len = backend.read_gamma_param::<USE_GAMMA_TABLE>()?;
82 debug_assert!(len <= 64);
83 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
84}
85
86impl<B: GammaReadParam<BE>> DeltaReadParam<BE> for B {
87 #[inline(always)]
88 fn read_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
89 &mut self,
90 ) -> Result<u64, B::Error> {
91 if USE_DELTA_TABLE {
92 if let Some((res, _)) = delta_tables::read_table_be(self) {
93 return Ok(res);
94 }
95 }
96 default_read_delta::<BE, _, USE_GAMMA_TABLE>(self)
97 }
98}
99
100impl<B: GammaReadParam<LE>> DeltaReadParam<LE> 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 if USE_DELTA_TABLE {
106 if let Some((res, _)) = delta_tables::read_table_le(self) {
107 return Ok(res);
108 }
109 }
110 default_read_delta::<LE, _, USE_GAMMA_TABLE>(self)
111 }
112}
113
114pub trait DeltaWrite<E: Endianness>: BitWrite<E> {
118 fn write_delta(&mut self, n: u64) -> Result<usize, Self::Error>;
119}
120
121pub trait DeltaWriteParam<E: Endianness>: GammaWriteParam<E> {
130 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
131 &mut self,
132 n: u64,
133 ) -> Result<usize, Self::Error>;
134}
135
136impl<B: GammaWriteParam<BE>> DeltaWriteParam<BE> for B {
137 #[inline(always)]
138 #[allow(clippy::collapsible_if)]
139 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
140 &mut self,
141 n: u64,
142 ) -> Result<usize, Self::Error> {
143 if USE_DELTA_TABLE {
144 if let Some(len) = delta_tables::write_table_be(self, n)? {
145 return Ok(len);
146 }
147 }
148 default_write_delta::<BE, _, USE_GAMMA_TABLE>(self, n)
149 }
150}
151
152impl<B: GammaWriteParam<LE>> DeltaWriteParam<LE> for B {
153 #[inline(always)]
154 #[allow(clippy::collapsible_if)]
155 fn write_delta_param<const USE_DELTA_TABLE: bool, const USE_GAMMA_TABLE: bool>(
156 &mut self,
157 n: u64,
158 ) -> Result<usize, Self::Error> {
159 if USE_DELTA_TABLE {
160 if let Some(len) = delta_tables::write_table_le(self, n)? {
161 return Ok(len);
162 }
163 }
164 default_write_delta::<LE, _, USE_GAMMA_TABLE>(self, n)
165 }
166}
167
168#[inline(always)]
171fn default_write_delta<E: Endianness, B: GammaWriteParam<E>, const USE_GAMMA_TABLE: bool>(
172 backend: &mut B,
173 mut n: u64,
174) -> Result<usize, B::Error> {
175 n += 1;
176 let λ = n.ilog2();
177
178 #[cfg(feature = "checks")]
179 {
180 n ^= 1 << λ;
182 }
183
184 Ok(backend.write_gamma_param::<USE_GAMMA_TABLE>(λ as _)? + backend.write_bits(n, λ as _)?)
185}