Skip to main content

dsi_bitstream/codes/
params.rs

1/*
2 * SPDX-FileCopyrightText: 2023 Tommaso Fontana
3 * SPDX-FileCopyrightText: 2023 Inria
4 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
5 *
6 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
7 */
8
9/*!
10
11Mechanisms for selecting parameters.
12
13Traits and structures in this file are of no interest for the standard
14user. Their purpose is to provide a systematic way, and in particular
15a default way, to select parameters for parameterized traits
16such as [`GammaReadParam`] and [`GammaWriteParam`].
17
18The traits and structure in this module work closely with the
19bitstream readers and writers in [`impls`](crate::impls), which have an
20additional type parameter `RP`/`WP` that must
21implement marker traits [`ReadParams`] or [`WriteParams`], respectively.
22The type is then used as a selector type to provide blanket implementations
23of parameterless traits in [`codes`](crate::codes) such as [`GammaRead`],
24[`GammaWrite`], [`DeltaRead`], [`DeltaWrite`], and so on.
25
26This module provides default selector types [`DefaultReadParams`] and [`DefaultWriteParams`]
27which are also the default value for the parameter `RP`/`WP` in the bitstream
28readers and writers in [`crate::impls`]. Type-selected blanket implementations
29of all parameterless traits in [`crate::codes`] are provided for the bitstream
30readers and writers in [`impls`](crate::impls). Thus, if you not specify a value for the
31parameter `RP`/`WP`, you will obtain automatically
32the blanket implementations for parameterless traits contained in this module.
33
34However, you can also create new selector types implementing [`ReadParams`]/[`WriteParams`] and
35write blanket implementations for the bitstream readers and writers in [`crate::impls`]
36where `RP`/`WP` is set to your selector types. Then, by specifying your type as value of the
37parameter `RP`/`WP` when creating such readers and writers you will use
38automatically your blanket implementations instead of the ones provided by this module.
39
40Note that the default implementations provided by this module are targeted at
41`u32` read words and `u64` write words. If you use different word sizes,
42you may want to write your own selector types.
43
44*/
45
46use crate::codes::*;
47use crate::impls::*;
48use crate::traits::*;
49use common_traits::*;
50use core::error::Error;
51#[cfg(feature = "mem_dbg")]
52use mem_dbg::{MemDbg, MemSize};
53
54/// Marker trait for read-parameters selector types.
55///
56/// Note that in principle marker traits are not necessary to use
57/// selector types, but they are useful to avoid that the user specifies
58/// a nonsensical type, and to document the meaning of type parameters.
59pub trait ReadParams {}
60
61/// A selector type for read parameters providing reasonable defaults.
62///
63/// If you want to optimize these choices for your architecture, we suggest to
64/// run the benchmarks in the `benchmarks` directory and write your
65/// own implementation.
66#[derive(Debug, Clone)]
67#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
68pub struct DefaultReadParams;
69impl ReadParams for DefaultReadParams {}
70
71macro_rules! impl_default_read_codes {
72    ($($endianess:ident),*) => {$(
73        impl<WR: WordRead> GammaRead<$endianess>
74            for BufBitReader<$endianess, WR, DefaultReadParams>
75        where
76            WR:: Word: DoubleType + UpcastableInto<u64>,
77            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
78        {
79            #[inline(always)]
80            fn read_gamma(&mut self) -> Result<u64, Self::Error> {
81                // From our tests on all architectures ɣ codes are faster
82                // without tables
83                self.read_gamma_param::<false>()
84            }
85        }
86
87        impl<WR: WordRead> DeltaRead<$endianess>
88            for BufBitReader<$endianess, WR, DefaultReadParams>
89        where
90            WR:: Word: DoubleType + UpcastableInto<u64>,
91            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
92        {
93            #[inline(always)]
94            fn read_delta(&mut self) -> Result<u64, Self::Error> {
95                self.read_delta_param::<false, true>()
96            }
97        }
98
99        impl<WR: WordRead> OmegaRead<$endianess>
100            for BufBitReader<$endianess, WR, DefaultReadParams>
101        where
102            WR:: Word: DoubleType + UpcastableInto<u64>,
103            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
104        {
105            #[inline(always)]
106            fn read_omega(&mut self) -> Result<u64, Self::Error> {
107                self.read_omega_param::<true>()
108            }
109        }
110
111        impl<WR: WordRead> ZetaRead<$endianess>
112            for BufBitReader<$endianess, WR, DefaultReadParams>
113        where
114            WR:: Word: DoubleType + UpcastableInto<u64>,
115            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
116        {
117            #[inline(always)]
118            fn read_zeta(&mut self, k: usize) -> Result<u64, Self::Error> {
119                self.read_zeta_param(k)
120            }
121
122            #[inline(always)]
123            fn read_zeta3(&mut self) -> Result<u64, Self::Error> {
124                self.read_zeta3_param::<true>()
125            }
126        }
127
128        impl<WR: WordRead> PiRead<$endianess>
129            for BufBitReader<$endianess, WR, DefaultReadParams>
130        where
131            WR:: Word: DoubleType + UpcastableInto<u64>,
132            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
133        {
134            #[inline(always)]
135            fn read_pi(&mut self, k: usize) -> Result<u64, Self::Error> {
136                self.read_pi_param(k)
137            }
138
139            #[inline(always)]
140            fn read_pi2(&mut self) -> Result<u64, Self::Error> {
141                self.read_pi2_param::<true>()
142            }
143        }
144
145        impl<E: Error + Send + Sync + 'static, WR: WordRead<Error = E, Word = u64> + WordSeek<Error = E>> GammaRead<$endianess>
146            for BitReader<$endianess, WR, DefaultReadParams>
147        where
148            WR:: Word: DoubleType + UpcastableInto<u64>,
149            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
150        {
151            #[inline(always)]
152            fn read_gamma(&mut self) -> Result<u64, Self::Error> {
153                // From our tests, the ARM architecture is faster
154                // without tables for ɣ codes.
155                self.read_gamma_param::<false>()
156            }
157        }
158
159        impl<E: Error + Send + Sync + 'static, WR: WordRead<Error = E, Word = u64> + WordSeek<Error = E>> DeltaRead<$endianess>
160            for BitReader<$endianess, WR, DefaultReadParams>
161        where
162            WR:: Word: DoubleType + UpcastableInto<u64>,
163            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
164        {
165            #[inline(always)]
166            fn read_delta(&mut self) -> Result<u64, Self::Error> {
167                self.read_delta_param::<false, true>()
168            }
169        }
170
171        impl<E: Error + Send + Sync + 'static, WR: WordRead<Error = E, Word = u64> + WordSeek<Error = E>> OmegaRead<$endianess>
172            for BitReader<$endianess, WR, DefaultReadParams>
173        where
174            WR:: Word: DoubleType + UpcastableInto<u64>,
175            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
176        {
177            #[inline(always)]
178            fn read_omega(&mut self) -> Result<u64, Self::Error> {
179                self.read_omega_param::<true>()
180            }
181        }
182
183        impl<E: Error + Send + Sync + 'static, WR: WordRead<Error = E, Word = u64> + WordSeek<Error = E>> ZetaRead<$endianess>
184            for BitReader<$endianess, WR, DefaultReadParams>
185        where
186            WR:: Word: DoubleType + UpcastableInto<u64>,
187            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
188        {
189            #[inline(always)]
190            fn read_zeta(&mut self, k: usize) -> Result<u64, Self::Error> {
191                self.read_zeta_param(k)
192            }
193
194            #[inline(always)]
195            fn read_zeta3(&mut self) -> Result<u64, Self::Error> {
196                self.read_zeta3_param::<true>()
197            }
198        }
199
200        impl<E: Error + Send + Sync + 'static, WR: WordRead<Error = E, Word = u64> + WordSeek<Error = E>> PiRead<$endianess>
201            for BitReader<$endianess, WR, DefaultReadParams>
202        where
203            WR:: Word: DoubleType + UpcastableInto<u64>,
204            <WR::Word as DoubleType>::DoubleType: CastableInto<u64>,
205        {
206            #[inline(always)]
207            fn read_pi(&mut self, k: usize) -> Result<u64, Self::Error> {
208                self.read_pi_param(k)
209            }
210
211            #[inline(always)]
212            fn read_pi2(&mut self) -> Result<u64, Self::Error> {
213                self.read_pi2_param::<true>()
214            }
215        }
216    )*};
217}
218
219impl_default_read_codes! {LittleEndian, BigEndian}
220
221/// Marker trait for write-parameters selector types.
222///
223/// Note that in principle marker traits are not necessary to use
224/// selector types, but they are useful to avoid that the user specifies
225/// a nonsensical type, and to document the meaning of type parameters.
226pub trait WriteParams {}
227
228/// A selector type for write parameters providing reasonable defaults.
229///
230/// If you want to optimize these choices for your architecture, we suggest to
231/// run the benchmarks in the `benchmarks` directory and write your
232/// own implementation.
233#[derive(Debug, Clone)]
234#[cfg_attr(feature = "mem_dbg", derive(MemDbg, MemSize))]
235pub struct DefaultWriteParams;
236impl WriteParams for DefaultWriteParams {}
237
238macro_rules! impl_default_write_codes {
239    ($($endianess:ident),*) => {$(
240        impl<WR: WordWrite> GammaWrite<$endianess>
241            for BufBitWriter<$endianess, WR, DefaultWriteParams>
242            where u64: CastableInto<WR::Word>,
243        {
244            #[inline(always)]
245            fn write_gamma(&mut self, value: u64) -> Result<usize, Self::Error> {
246                self.write_gamma_param::<true>(value)
247            }
248        }
249
250        impl<WR: WordWrite, DC: WriteParams> DeltaWrite<$endianess>
251            for BufBitWriter<$endianess, WR, DC>
252            where u64: CastableInto<WR::Word>,
253        {
254            #[inline(always)]
255            fn write_delta(&mut self, value: u64) -> Result<usize, Self::Error> {
256                self.write_delta_param::<true, true>(value)
257            }
258        }
259
260        impl<WR: WordWrite, WP: WriteParams> OmegaWrite<$endianess>
261            for BufBitWriter<$endianess, WR, WP>
262            where u64: CastableInto<WR::Word>,
263        {
264            #[inline(always)]
265            fn write_omega(&mut self, value: u64) -> Result<usize, Self::Error> {
266                self.write_omega_param::<true>(value)
267            }
268        }
269
270        impl<WR: WordWrite, DC: WriteParams> ZetaWrite<$endianess>
271            for BufBitWriter<$endianess, WR, DC>
272            where u64: CastableInto<WR::Word>,
273        {
274            #[inline(always)]
275            fn write_zeta(&mut self, value: u64, k: usize) -> Result<usize, Self::Error> {
276                self.write_zeta_param::<true>(value, k)
277            }
278
279            #[inline(always)]
280            fn write_zeta3(&mut self, value: u64) -> Result<usize, Self::Error> {
281                self.write_zeta3_param::<true>(value)
282            }
283        }
284
285        impl<WR: WordWrite, DC: WriteParams> PiWrite<$endianess>
286            for BufBitWriter<$endianess, WR, DC>
287            where u64: CastableInto<WR::Word>,
288        {
289            #[inline(always)]
290            fn write_pi(&mut self, value: u64, k: usize) -> Result<usize, Self::Error> {
291                self.write_pi_param::<true>(value, k)
292            }
293
294            #[inline(always)]
295            fn write_pi2(&mut self, value: u64) -> Result<usize, Self::Error> {
296                self.write_pi2_param::<true>(value)
297            }
298        }
299
300    )*};
301}
302
303impl_default_write_codes! {LittleEndian, BigEndian}