mod bitpacker; mod blocked_bitpacker; pub use crate::bitpacker::{BitPacker, BitUnpacker}; pub use crate::blocked_bitpacker::BlockedBitpacker; /// Computes the number of bits that will be used for bitpacking. /// /// In general the target is the minimum number of bits /// required to express the amplitude given in argument. /// /// e.g. If the amplitude is 10, we can store all ints on simply 4bits. /// /// The logic is slightly more convoluted here as for optimization /// reasons, we want to ensure that a value spawns over at most 8 bytes /// of aligned bytes. /// /// Spanning over 9 bytes is possible for instance, if we do /// bitpacking with an amplitude of 63 bits. /// In this case, the second int will start on bit /// 63 (which belongs to byte 7) and ends at byte 15; /// Hence 9 bytes (from byte 7 to byte 15 included). /// /// To avoid this, we force the number of bits to 64bits /// when the result is greater than `64-8 = 56 bits`. /// /// Note that this only affects rare use cases spawning over /// a very large range of values. Even in this case, it results /// in an extra cost of at most 12% compared to the optimal /// number of bits. pub fn compute_num_bits(n: u64) -> u8 { let amplitude = (64u32 - n.leading_zeros()) as u8; if amplitude <= 64 - 8 { amplitude } else { 64 } } pub fn minmax(mut vals: I) -> Option<(T, T)> where I: Iterator, T: Copy + Ord, { if let Some(first_el) = vals.next() { return Some(vals.fold((first_el, first_el), |(min_val, max_val), el| { (min_val.min(el), max_val.max(el)) })); } None } #[test] fn test_compute_num_bits() { assert_eq!(compute_num_bits(1), 1u8); assert_eq!(compute_num_bits(0), 0u8); assert_eq!(compute_num_bits(2), 2u8); assert_eq!(compute_num_bits(3), 2u8); assert_eq!(compute_num_bits(4), 3u8); assert_eq!(compute_num_bits(255), 8u8); assert_eq!(compute_num_bits(256), 9u8); assert_eq!(compute_num_bits(5_000_000_000), 33u8); } #[test] fn test_minmax_empty() { let vals: Vec = vec![]; assert_eq!(minmax(vals.into_iter()), None); } #[test] fn test_minmax_one() { assert_eq!(minmax(vec![1].into_iter()), Some((1, 1))); } #[test] fn test_minmax_two() { assert_eq!(minmax(vec![1, 2].into_iter()), Some((1, 2))); assert_eq!(minmax(vec![2, 1].into_iter()), Some((1, 2))); }