diff options
author | Paul Masurel <paul.masurel@gmail.com> | 2017-05-15 22:30:18 +0900 |
---|---|---|
committer | Paul Masurel <paul.masurel@gmail.com> | 2017-05-15 22:30:18 +0900 |
commit | 4c8f9742f882dd1366f4130ac11a5ce4a786180f (patch) | |
tree | af07264eadf34f1dd55898e90ff23388734324f9 /src/common/bitpacker.rs | |
parent | a23b7a181541f00d0a8b437af8617951526d23a6 (diff) |
format
Diffstat (limited to 'src/common/bitpacker.rs')
-rw-r--r-- | src/common/bitpacker.rs | 81 |
1 files changed, 33 insertions, 48 deletions
diff --git a/src/common/bitpacker.rs b/src/common/bitpacker.rs index f765a39..e16df39 100644 --- a/src/common/bitpacker.rs +++ b/src/common/bitpacker.rs @@ -6,19 +6,19 @@ use std::mem; /// Computes the number of bits that will be used for bitpacking. /// -/// In general the target is the minimum number of bits +/// 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 aligns bytes. -/// -/// Spawning over 9 bytes is possible for instance, if we do +/// +/// Spawning 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; +/// 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 @@ -30,12 +30,7 @@ use std::mem; /// number of bits. pub fn compute_num_bits(amplitude: u64) -> u8 { let amplitude = (64u32 - amplitude.leading_zeros()) as u8; - if amplitude <= 64 - 8 { - amplitude - } - else { - 64 - } + if amplitude <= 64 - 8 { amplitude } else { 64 } } pub struct BitPacker { @@ -46,7 +41,6 @@ pub struct BitPacker { } impl BitPacker { - pub fn new(num_bits: usize) -> BitPacker { BitPacker { mini_buffer: 0u64, @@ -55,7 +49,7 @@ impl BitPacker { written_size: 0, } } - + pub fn write<TWrite: Write>(&mut self, val: u64, output: &mut TWrite) -> io::Result<()> { let val_u64 = val as u64; if self.mini_buffer_written + self.num_bits > 64 { @@ -63,30 +57,29 @@ impl BitPacker { self.written_size += self.mini_buffer.serialize(output)?; self.mini_buffer = val_u64.wrapping_shr((64 - self.mini_buffer_written) as u32); self.mini_buffer_written = self.mini_buffer_written + (self.num_bits as usize) - 64; - } - else { + } else { self.mini_buffer |= val_u64 << self.mini_buffer_written; self.mini_buffer_written += self.num_bits; if self.mini_buffer_written == 64 { self.written_size += self.mini_buffer.serialize(output)?; self.mini_buffer_written = 0; self.mini_buffer = 0u64; - } + } } Ok(()) } - - fn flush<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()>{ + + fn flush<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<()> { if self.mini_buffer_written > 0 { let num_bytes = (self.mini_buffer_written + 7) / 8; - let arr: [u8; 8] = unsafe { mem::transmute::<u64, [u8; 8]>(self.mini_buffer) }; + let arr: [u8; 8] = unsafe { mem::transmute::<u64, [u8; 8]>(self.mini_buffer) }; output.write_all(&arr[..num_bytes])?; self.written_size += num_bytes; self.mini_buffer_written = 0; } Ok(()) } - + pub fn close<TWrite: Write>(&mut self, output: &mut TWrite) -> io::Result<usize> { self.flush(output)?; Ok(self.written_size) @@ -99,26 +92,24 @@ pub struct BitUnpacker { num_bits: usize, mask: u64, data_ptr: *const u8, - data_len: usize, + data_len: usize, } impl BitUnpacker { pub fn new(data: &[u8], num_bits: usize) -> BitUnpacker { - let mask: u64 = - if num_bits == 64 { - !0u64 - } - else { - (1u64 << num_bits) - 1u64 - }; + let mask: u64 = if num_bits == 64 { + !0u64 + } else { + (1u64 << num_bits) - 1u64 + }; BitUnpacker { num_bits: num_bits, mask: mask, data_ptr: data.as_ptr(), - data_len: data.len() + data_len: data.len(), } } - + pub fn get(&self, idx: usize) -> u64 { if self.num_bits == 0 { return 0; @@ -127,13 +118,13 @@ impl BitUnpacker { let bit_shift = idx * self.num_bits - addr * 8; let val_unshifted_unmasked: u64; if addr + 8 <= self.data_len { - val_unshifted_unmasked = unsafe { * (self.data_ptr.offset(addr as isize) as *const u64) }; - } - else { + val_unshifted_unmasked = + unsafe { *(self.data_ptr.offset(addr as isize) as *const u64) }; + } else { let mut arr = [0u8; 8]; if addr < self.data_len { for i in 0..self.data_len - addr { - arr[i] = unsafe { *self.data_ptr.offset( (addr + i) as isize) }; + arr[i] = unsafe { *self.data_ptr.offset((addr + i) as isize) }; } } val_unshifted_unmasked = unsafe { mem::transmute::<[u8; 8], u64>(arr) }; @@ -141,7 +132,6 @@ impl BitUnpacker { let val_shifted = (val_unshifted_unmasked >> bit_shift) as u64; (val_shifted & self.mask) } - } @@ -150,7 +140,7 @@ impl BitUnpacker { #[cfg(test)] mod test { use super::{BitPacker, BitUnpacker, compute_num_bits}; - + #[test] fn test_compute_num_bits() { assert_eq!(compute_num_bits(1), 1u8); @@ -162,31 +152,26 @@ mod test { assert_eq!(compute_num_bits(256), 9u8); assert_eq!(compute_num_bits(5_000_000_000), 33u8); } - + fn test_bitpacker_util(len: usize, num_bits: usize) { let mut data = Vec::new(); let mut bitpacker = BitPacker::new(num_bits); let max_val: u64 = (1 << num_bits) - 1; - let vals: Vec<u64> = (0u64..len as u64).map(|i| { - if max_val == 0 { - 0 - } - else { - i % max_val - } - }).collect(); + let vals: Vec<u64> = (0u64..len as u64) + .map(|i| if max_val == 0 { 0 } else { i % max_val }) + .collect(); for &val in &vals { bitpacker.write(val, &mut data).unwrap(); } let num_bytes = bitpacker.close(&mut data).unwrap(); - assert_eq!(num_bytes, (num_bits * len + 7) / 8); + assert_eq!(num_bytes, (num_bits * len + 7) / 8); assert_eq!(data.len(), num_bytes); let bitunpacker = BitUnpacker::new(&data, num_bits); for (i, val) in vals.iter().enumerate() { assert_eq!(bitunpacker.get(i), *val); } } - + #[test] fn test_bitpacker() { test_bitpacker_util(10, 3); @@ -195,4 +180,4 @@ mod test { test_bitpacker_util(6, 14); test_bitpacker_util(1000, 14); } -}
\ No newline at end of file +} |