1use crate::traits::*;
41
42use super::{RiceRead, RiceWrite, len_rice, pi_tables};
43
44#[must_use]
46#[inline(always)]
47#[allow(clippy::collapsible_if)]
48pub fn len_pi_param<const USE_TABLE: bool>(mut n: u64, k: usize) -> usize {
49 debug_assert!(k < 64);
50 if USE_TABLE {
51 if k == pi_tables::K {
52 if let Some(idx) = pi_tables::LEN.get(n as usize) {
53 return *idx as usize;
54 }
55 }
56 }
57 debug_assert!(n < u64::MAX);
58 n += 1;
59 let λ = n.ilog2() as usize;
60 len_rice(λ as u64, k) + λ
61}
62
63#[must_use]
110#[inline(always)]
111pub fn len_pi(n: u64, k: usize) -> usize {
112 len_pi_param::<true>(n, k)
113}
114
115pub trait PiRead<E: Endianness>: BitRead<E> {
119 fn read_pi(&mut self, k: usize) -> Result<u64, Self::Error>;
120 fn read_pi2(&mut self) -> Result<u64, Self::Error>;
121}
122
123pub trait PiReadParam<E: Endianness>: BitRead<E> + RiceRead<E> {
132 fn read_pi_param(&mut self, k: usize) -> Result<u64, Self::Error>;
133 fn read_pi2_param<const USE_TABLE: bool>(&mut self) -> Result<u64, Self::Error>;
134}
135
136impl<B: BitRead<BE> + RiceRead<BE>> PiReadParam<BE> for B {
137 #[inline(always)]
138 fn read_pi_param(&mut self, k: usize) -> Result<u64, B::Error> {
139 default_read_pi(self, k)
140 }
141
142 #[inline(always)]
143 fn read_pi2_param<const USE_TABLE: bool>(&mut self) -> Result<u64, B::Error> {
144 if USE_TABLE {
145 if let Some((res, _)) = pi_tables::read_table_be(self) {
146 return Ok(res);
147 }
148 }
149 default_read_pi(self, 2)
150 }
151}
152
153impl<B: BitRead<LE> + RiceRead<LE>> PiReadParam<LE> for B {
154 #[inline(always)]
155 fn read_pi_param(&mut self, k: usize) -> Result<u64, B::Error> {
156 default_read_pi(self, k)
157 }
158
159 #[inline(always)]
160 fn read_pi2_param<const USE_TABLE: bool>(&mut self) -> Result<u64, B::Error> {
161 if USE_TABLE {
162 if let Some((res, _)) = pi_tables::read_table_le(self) {
163 return Ok(res);
164 }
165 }
166 default_read_pi(self, 2)
167 }
168}
169
170#[inline(always)]
173fn default_read_pi<E: Endianness, B: BitRead<E> + RiceRead<E>>(
174 backend: &mut B,
175 k: usize,
176) -> Result<u64, B::Error> {
177 debug_assert!(k < 64);
178 let λ = backend.read_rice(k)?;
179 debug_assert!(λ < 64);
180 Ok((1 << λ) + backend.read_bits(λ as usize)? - 1)
181}
182
183pub trait PiWrite<E: Endianness>: BitWrite<E> {
187 fn write_pi(&mut self, n: u64, k: usize) -> Result<usize, Self::Error>;
188 fn write_pi2(&mut self, n: u64) -> Result<usize, Self::Error>;
189}
190
191pub trait PiWriteParam<E: Endianness>: BitWrite<E> + RiceWrite<E> {
200 fn write_pi_param<const USE_TABLE: bool>(
201 &mut self,
202 n: u64,
203 k: usize,
204 ) -> Result<usize, Self::Error>;
205 fn write_pi2_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error>;
206}
207
208impl<B: BitWrite<BE> + RiceWrite<BE>> PiWriteParam<BE> for B {
209 #[inline(always)]
210 fn write_pi_param<const USE_TABLE: bool>(
211 &mut self,
212 n: u64,
213 k: usize,
214 ) -> Result<usize, Self::Error> {
215 default_write_pi(self, n, k)
216 }
217
218 #[inline(always)]
219 #[allow(clippy::collapsible_if)]
220 fn write_pi2_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error> {
221 if USE_TABLE {
222 if let Some(len) = pi_tables::write_table_be(self, n)? {
223 return Ok(len);
224 }
225 }
226 default_write_pi(self, n, 2)
227 }
228}
229
230impl<B: BitWrite<LE> + RiceWrite<LE>> PiWriteParam<LE> for B {
231 #[inline(always)]
232 fn write_pi_param<const USE_TABLE: bool>(
233 &mut self,
234 n: u64,
235 k: usize,
236 ) -> Result<usize, Self::Error> {
237 default_write_pi(self, n, k)
238 }
239
240 #[inline(always)]
241 #[allow(clippy::collapsible_if)]
242 fn write_pi2_param<const USE_TABLE: bool>(&mut self, n: u64) -> Result<usize, Self::Error> {
243 if USE_TABLE {
244 if let Some(len) = pi_tables::write_table_le(self, n)? {
245 return Ok(len);
246 }
247 }
248 default_write_pi(self, n, 2)
249 }
250}
251
252#[inline(always)]
255fn default_write_pi<E: Endianness, B: BitWrite<E> + RiceWrite<E>>(
256 backend: &mut B,
257 mut n: u64,
258 k: usize,
259) -> Result<usize, B::Error> {
260 debug_assert!(k < 64);
261 debug_assert!(n < u64::MAX);
262
263 n += 1;
264 let λ = n.ilog2() as usize;
265
266 #[cfg(feature = "checks")]
267 {
268 n ^= 1 << λ;
270 }
271
272 Ok(backend.write_rice(λ as u64, k)? + backend.write_bits(n, λ)?)
273}
274
275#[cfg(test)]
276mod test {
277 use crate::prelude::*;
278
279 #[test]
280 fn test_roundtrip() {
281 let k = 3;
282 for value in (0..64).map(|i| 1 << i).chain(0..1024).chain([u64::MAX - 1]) {
283 let mut data = [0_u64; 10];
284 let mut writer = <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data));
285 let code_len = writer.write_pi(value, k).unwrap();
286 assert_eq!(code_len, len_pi(value, k));
287 drop(writer);
288 let mut reader = <BufBitReader<BE, _>>::new(MemWordReader::new(&data));
289 assert_eq!(
290 reader.read_pi(k).unwrap(),
291 value,
292 "for value: {} with k {}",
293 value,
294 k
295 );
296 }
297 }
298
299 #[test]
300 fn test_roundtrip_pi2() {
301 for value in (0..64).map(|i| 1 << i).chain(0..1024).chain([u64::MAX - 1]) {
303 let mut data = [0_u64; 10];
305 let mut writer = <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data));
306 let code_len = writer.write_pi2(value).unwrap();
307 assert_eq!(code_len, len_pi(value, 2));
308 drop(writer);
309 let mut reader = <BufBitReader<BE, _>>::new(MemWordReader::new(&data));
310 assert_eq!(reader.read_pi2().unwrap(), value, "BE for value: {}", value,);
311
312 let mut data = [0_u64; 10];
314 let mut writer = <BufBitWriter<LE, _>>::new(MemWordWriterSlice::new(&mut data));
315 let code_len = writer.write_pi2(value).unwrap();
316 assert_eq!(code_len, len_pi(value, 2));
317 drop(writer);
318 let mut reader = <BufBitReader<LE, _>>::new(MemWordReader::new(&data));
319 assert_eq!(reader.read_pi2().unwrap(), value, "LE for value: {}", value,);
320 }
321 }
322
323 #[test]
324 fn test_roundtrip_pi2_param() {
325 for value in (0..64).map(|i| 1 << i).chain(0..1024).chain([u64::MAX - 1]) {
327 let mut data = [0_u64; 10];
329 let mut writer = <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data));
330 let code_len = writer.write_pi2_param::<true>(value).unwrap();
331 assert_eq!(code_len, len_pi(value, 2));
332 drop(writer);
333 let mut reader = <BufBitReader<BE, _>>::new(MemWordReader::new(&data));
334 assert_eq!(
335 reader.read_pi2_param::<true>().unwrap(),
336 value,
337 "BE table for value: {}",
338 value,
339 );
340
341 let mut data = [0_u64; 10];
343 let mut writer = <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data));
344 let code_len = writer.write_pi2_param::<false>(value).unwrap();
345 assert_eq!(code_len, len_pi(value, 2));
346 drop(writer);
347 let mut reader = <BufBitReader<BE, _>>::new(MemWordReader::new(&data));
348 assert_eq!(
349 reader.read_pi2_param::<false>().unwrap(),
350 value,
351 "BE no table for value: {}",
352 value,
353 );
354
355 let mut data = [0_u64; 10];
357 let mut writer = <BufBitWriter<LE, _>>::new(MemWordWriterSlice::new(&mut data));
358 let code_len = writer.write_pi2_param::<true>(value).unwrap();
359 assert_eq!(code_len, len_pi(value, 2));
360 drop(writer);
361 let mut reader = <BufBitReader<LE, _>>::new(MemWordReader::new(&data));
362 assert_eq!(
363 reader.read_pi2_param::<true>().unwrap(),
364 value,
365 "LE table for value: {}",
366 value,
367 );
368
369 let mut data = [0_u64; 10];
371 let mut writer = <BufBitWriter<LE, _>>::new(MemWordWriterSlice::new(&mut data));
372 let code_len = writer.write_pi2_param::<false>(value).unwrap();
373 assert_eq!(code_len, len_pi(value, 2));
374 drop(writer);
375 let mut reader = <BufBitReader<LE, _>>::new(MemWordReader::new(&data));
376 assert_eq!(
377 reader.read_pi2_param::<false>().unwrap(),
378 value,
379 "LE no table for value: {}",
380 value,
381 );
382 }
383 }
384
385 #[test]
386 #[allow(clippy::unusual_byte_groupings)]
387 fn test_bits() {
388 for (k, value, expected) in [
389 (2, 20, 0b01_00_0101 << (64 - 8)),
390 (2, 0, 0b100 << (64 - 3)),
391 (2, 1, 0b1010 << (64 - 4)),
392 (2, 2, 0b1011 << (64 - 4)),
393 (2, 3, 0b1_1000 << (64 - 5)),
394 (2, 4, 0b1_1001 << (64 - 5)),
395 (2, 5, 0b1_1010 << (64 - 5)),
396 (2, 6, 0b1_1011 << (64 - 5)),
397 (2, 7, 0b11_1000 << (64 - 6)),
398 (3, 0, 0b1000 << (64 - 4)),
399 (3, 1, 0b1_0010 << (64 - 5)),
400 (3, 2, 0b1_0011 << (64 - 5)),
401 (3, 3, 0b1_01000 << (64 - 6)),
402 (3, 4, 0b1_01001 << (64 - 6)),
403 (3, 5, 0b1_01010 << (64 - 6)),
404 (3, 6, 0b1_01011 << (64 - 6)),
405 (3, 7, 0b101_1000 << (64 - 7)),
406 ] {
407 let mut data = [0_u64; 10];
408 let mut writer = <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data));
409 let code_len = writer.write_pi(value, k).unwrap();
410 assert_eq!(code_len, len_pi(value, k));
411 drop(writer);
412 assert_eq!(
413 data[0].to_be(),
414 expected,
415 "\nfor value: {} with k {}\ngot: {:064b}\nexp: {:064b}\ngot_len: {} exp_len: {}\n",
416 value,
417 k,
418 data[0].to_be(),
419 expected,
420 code_len,
421 len_pi(value, k),
422 );
423 }
424 }
425
426 #[test]
427 fn test_against_zeta() {
428 for k in 0..2 {
430 for value in 0..100 {
431 let mut data_pi = [0_u64; 10];
432 let mut data_zeta = [0_u64; 10];
433
434 let mut writer = <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data_pi));
435 let code_len = writer.write_pi(value, k).unwrap();
436 assert_eq!(code_len, len_pi(value, k));
437 drop(writer);
438
439 let mut writer =
440 <BufBitWriter<BE, _>>::new(MemWordWriterSlice::new(&mut data_zeta));
441 let code_len = writer.write_zeta(value, 1 << k).unwrap();
442 assert_eq!(code_len, len_zeta(value, 1 << k));
443 drop(writer);
444
445 assert_eq!(data_pi[0], data_zeta[0]);
446 }
447 }
448
449 for value in 0..100 {
451 let mut data_pi = [0_u64; 10];
452 let mut data_zeta = [0_u64; 10];
453
454 let mut writer = <BufBitWriter<LE, _>>::new(MemWordWriterSlice::new(&mut data_pi));
455 let code_len = writer.write_pi(value, 0).unwrap();
456 assert_eq!(code_len, len_pi(value, 0));
457 drop(writer);
458
459 let mut writer = <BufBitWriter<LE, _>>::new(MemWordWriterSlice::new(&mut data_zeta));
460 let code_len = writer.write_zeta(value, 1).unwrap();
461 assert_eq!(code_len, len_zeta(value, 1));
462 drop(writer);
463
464 assert_eq!(data_pi[0], data_zeta[0]);
465 }
466
467 for value in 0..100 {
468 assert_eq!(len_pi(value, 1), len_zeta(value, 2));
469 }
470 }
471}