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