dsi_bitstream/codes/
gamma.rs1use super::gamma_tables;
29use crate::traits::*;
30
31#[must_use]
33#[inline(always)]
34pub fn len_gamma_param<const USE_TABLE: bool>(mut n: u64) -> usize {
35 debug_assert!(n < u64::MAX);
36 if USE_TABLE {
37 if let Some(idx) = gamma_tables::LEN.get(n as usize) {
38 return *idx as usize;
39 }
40 }
41 n += 1;
42 let λ = n.ilog2();
43 2 * λ as usize + 1
44}
45
46#[inline(always)]
49pub fn len_gamma(n: u64) -> usize {
50 #[cfg(target_arch = "arm")]
51 return len_gamma_param::<false>(n);
52 #[cfg(not(target_arch = "arm"))]
53 return len_gamma_param::<true>(n);
54}
55
56pub trait GammaRead<E: Endianness>: BitRead<E> {
60 fn read_gamma(&mut self) -> Result<u64, Self::Error>;
61}
62
63pub trait GammaReadParam<E: Endianness>: BitRead<E> {
72 fn read_gamma_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error>;
73}
74
75#[inline(always)]
78fn default_read_gamma<E: Endianness, B: BitRead<E>>(backend: &mut B) -> Result<u64, B::Error> {
79 let len = backend.read_unary()?;
80 debug_assert!(len < 64);
81 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
82}
83
84impl<B: BitRead<BE>> GammaReadParam<BE> for B {
85 #[inline(always)]
86 fn read_gamma_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error> {
87 if USE_TABLE {
88 if let Some((res, _)) = gamma_tables::read_table_be(self) {
89 return Ok(res);
90 }
91 }
92 default_read_gamma(self)
93 }
94}
95
96impl<B: BitRead<LE>> GammaReadParam<LE> for B {
97 #[inline(always)]
98 fn read_gamma_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error> {
99 if USE_TABLE {
100 if let Some((res, _)) = gamma_tables::read_table_le(self) {
101 return Ok(res);
102 }
103 }
104 default_read_gamma(self)
105 }
106}
107
108pub trait GammaWrite<E: Endianness>: BitWrite<E> {
112 fn write_gamma(&mut self, n: u64) -> Result<usize, Self::Error>;
113}
114
115pub trait GammaWriteParam<E: Endianness>: BitWrite<E> {
124 fn write_gamma_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error>;
125}
126
127impl<B: BitWrite<BE>> GammaWriteParam<BE> for B {
128 #[inline(always)]
129 #[allow(clippy::collapsible_if)]
130 fn write_gamma_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error> {
131 if USE_TABLE {
132 if let Some(len) = gamma_tables::write_table_be(self, n)? {
133 return Ok(len);
134 }
135 }
136 default_write_gamma(self, n)
137 }
138}
139
140impl<B: BitWrite<LE>> GammaWriteParam<LE> for B {
141 #[inline(always)]
142 #[allow(clippy::collapsible_if)]
143 fn write_gamma_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error> {
144 if USE_TABLE {
145 if let Some(len) = gamma_tables::write_table_le(self, n)? {
146 return Ok(len);
147 }
148 }
149 default_write_gamma(self, n)
150 }
151}
152
153#[inline(always)]
156fn default_write_gamma<E: Endianness, B: BitWrite<E>>(
157 backend: &mut B,
158 mut n: u64,
159) -> Result<usize, B::Error> {
160 debug_assert!(n < u64::MAX);
161 n += 1;
162 let λ = n.ilog2();
163
164 #[cfg(feature = "checks")]
165 {
166 n ^= 1 << λ;
168 }
169
170 Ok(backend.write_unary(λ as _)? + backend.write_bits(n, λ as _)?)
171}