pub const BITS_7: usize = 1 << 7; pub const BITS_10: usize = 1 << 10; pub const BITS_11: usize = 1 << 11; pub const BITS_13: usize = 1 << 13; pub const BITS_14: usize = 1 << 14; pub const MASK_EVEN_32: u32 = 0x55555555; pub const MASK_ODD_32: u32 = 0xAAAAAAAA; // Helper function that returns tag of 16-bit input pub fn get_tag(input: u16) -> u8 { let input = input as usize; if input < BITS_7 { 0 } else if input < BITS_10 { 1 } else if input < BITS_11 { 2 } else if input < BITS_13 { 3 } else if input < BITS_14 { 4 } else { 5 } } /// Helper function that returns 32-bit spread version of 16-bit input. pub fn interleave_u16_with_zeros(word: u16) -> u32 { let mut word: u32 = word.into(); word = (word ^ (word << 8)) & 0x00ff00ff; word = (word ^ (word << 4)) & 0x0f0f0f0f; word = (word ^ (word << 2)) & 0x33333333; word = (word ^ (word << 1)) & 0x55555555; word } // Reverses interleaving function by removing interleaved zeros. pub fn compress_u32(word: u32) -> u16 { let mut word = word; assert_eq!(word & MASK_EVEN_32, word); word = (word | (word >> 1)) & 0x33333333; word = (word | (word >> 2)) & 0x0f0f0f0f; word = (word | (word >> 4)) & 0x00ff00ff; word = (word | (word >> 8)) & 0x0000ffff; word as u16 } // Chops a 32-bit word into pieces of given length. The lengths are specified // starting from the little end. pub fn chop_u32(word: u32, lengths: &[u8]) -> Vec { assert_eq!(lengths.iter().sum::(), 32u8); let mut pieces: Vec = Vec::with_capacity(lengths.len()); for i in 0..lengths.len() { assert!(lengths[i] > 0); // lengths[i] bitstring of all 1's let mask: u32 = (1 << lengths[i]) as u32 - 1; // Shift mask by bits already shifted let offset: u8 = lengths[0..i].iter().sum(); let mask: u32 = mask << offset; pieces.push((word & mask) >> offset as u32); } pieces } // Chops a 64-bit word into pieces of given length. The lengths are specified // starting from the little end. pub fn chop_u64(word: u64, lengths: &[u8]) -> Vec { assert_eq!(lengths.iter().sum::(), 64u8); let mut pieces: Vec = Vec::with_capacity(lengths.len()); for i in 0..lengths.len() { assert!(lengths[i] > 0); // lengths[i] bitstring of all 1's let mask: u64 = (1u64 << lengths[i]) - 1; // Shift mask by bits already shifted let offset: u8 = lengths[0..i].iter().sum(); let mask: u64 = mask << offset; pieces.push((word & mask) >> offset as u64); } pieces } // Returns compressed even and odd bits of 32-bit word pub fn get_even_and_odd_bits_u32(word: u32) -> (u16, u16) { let even = word & MASK_EVEN_32; let odd = (word & MASK_ODD_32) >> 1; (compress_u32(even), compress_u32(odd)) } // Split 4-bit value into 2-bit lo and hi halves pub fn bisect_four_bit(word: u32) -> (u32, u32) { assert!(word < 16); // 4-bit range-check let word_hi = (word & 0b1100) >> 2; let word_lo = word & 0b0011; (word_lo, word_hi) }