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#[must_use]
49#[inline(always)]
50pub fn len_gamma(n: u64) -> usize {
51 #[cfg(target_arch = "arm")]
52 return len_gamma_param::<false>(n);
53 #[cfg(not(target_arch = "arm"))]
54 return len_gamma_param::<true>(n);
55}
56
57pub trait GammaRead<E: Endianness>: BitRead<E> {
61 fn read_gamma(&mut self) -> Result<u64, Self::Error>;
62}
63
64pub trait GammaReadParam<E: Endianness>: BitRead<E> {
73 fn read_gamma_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error>;
74}
75
76#[inline(always)]
79fn default_read_gamma<E: Endianness, B: BitRead<E>>(backend: &mut B) -> Result<u64, B::Error> {
80 let len = backend.read_unary()?;
81 debug_assert!(len < 64);
82 Ok(backend.read_bits(len as usize)? + (1 << len) - 1)
83}
84
85impl<B: BitRead<BE>> GammaReadParam<BE> for B {
86 #[inline(always)]
87 fn read_gamma_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error> {
88 const {
89 if USE_TABLE {
90 gamma_tables::check_read_table(B::PEEK_BITS)
91 }
92 }
93 if USE_TABLE {
94 if let Some((res, _)) = gamma_tables::read_table_be(self) {
95 return Ok(res);
96 }
97 }
98 default_read_gamma(self)
99 }
100}
101
102impl<B: BitRead<LE>> GammaReadParam<LE> for B {
103 #[inline(always)]
104 fn read_gamma_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error> {
105 const {
106 if USE_TABLE {
107 gamma_tables::check_read_table(B::PEEK_BITS)
108 }
109 }
110 if USE_TABLE {
111 if let Some((res, _)) = gamma_tables::read_table_le(self) {
112 return Ok(res);
113 }
114 }
115 default_read_gamma(self)
116 }
117}
118
119pub trait GammaWrite<E: Endianness>: BitWrite<E> {
123 fn write_gamma(&mut self, n: u64) -> Result<usize, Self::Error>;
124}
125
126pub trait GammaWriteParam<E: Endianness>: BitWrite<E> {
135 fn write_gamma_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error>;
136}
137
138impl<B: BitWrite<BE>> GammaWriteParam<BE> for B {
139 #[inline(always)]
140 #[allow(clippy::collapsible_if)]
141 fn write_gamma_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error> {
142 if USE_TABLE {
143 if let Some(len) = gamma_tables::write_table_be(self, n)? {
144 return Ok(len);
145 }
146 }
147 default_write_gamma(self, n)
148 }
149}
150
151impl<B: BitWrite<LE>> GammaWriteParam<LE> for B {
152 #[inline(always)]
153 #[allow(clippy::collapsible_if)]
154 fn write_gamma_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error> {
155 if USE_TABLE {
156 if let Some(len) = gamma_tables::write_table_le(self, n)? {
157 return Ok(len);
158 }
159 }
160 default_write_gamma(self, n)
161 }
162}
163
164#[inline(always)]
167fn default_write_gamma<E: Endianness, B: BitWrite<E>>(
168 backend: &mut B,
169 mut n: u64,
170) -> Result<usize, B::Error> {
171 debug_assert!(n < u64::MAX);
172 n += 1;
173 let λ = n.ilog2();
174
175 #[cfg(feature = "checks")]
176 {
177 n ^= 1 << λ;
179 }
180
181 Ok(backend.write_unary(λ as _)? + backend.write_bits(n, λ as _)?)
182}