1use crate::utils;
2use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
3use std::io;
4
5#[derive(Clone)]
6pub struct IntVector {
7 chunks: Vec<u64>,
8 len: usize,
9 bits: usize,
10 mask: u64,
11}
12
13impl IntVector {
14 pub fn build(input: &[u64]) -> Self {
15 let len = input.len();
16 let bits = utils::needed_bits(*input.iter().max().unwrap());
17 let mask = (1 << bits) - 1;
18
19 let mut chunks = vec![0; Self::words_for(len * bits)];
20
21 for (i, &x) in input.iter().enumerate() {
22 let (q, m) = Self::decompose(i * bits);
23 chunks[q] &= !(mask << m);
24 chunks[q] |= (x & mask) << m;
25 if 64 < m + bits {
26 let diff = 64 - m;
27 chunks[q + 1] &= !(mask >> diff);
28 chunks[q + 1] |= (x & mask) >> diff;
29 }
30 }
31
32 Self {
33 chunks,
34 len,
35 bits,
36 mask,
37 }
38 }
39
40 #[inline(always)]
41 pub fn get(&self, i: usize) -> u64 {
42 let (q, m) = Self::decompose(i * self.bits);
43 if m + self.bits <= 64 {
44 (self.chunks[q] >> m) & self.mask
45 } else {
46 ((self.chunks[q] >> m) | (self.chunks[q + 1] << (64 - m))) & self.mask
47 }
48 }
49
50 #[inline(always)]
51 pub const fn len(&self) -> usize {
52 self.len
53 }
54
55 pub fn size_in_bytes(&self) -> usize {
56 8 + self.chunks.len() * 8 + 8 * 3
57 }
58
59 pub fn serialize_into<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
60 writer.write_u64::<LittleEndian>(self.chunks.len() as u64)?;
61 for &x in &self.chunks {
62 writer.write_u64::<LittleEndian>(x)?;
63 }
64 writer.write_u64::<LittleEndian>(self.len as u64)?;
65 writer.write_u64::<LittleEndian>(self.bits as u64)?;
66 writer.write_u64::<LittleEndian>(self.mask as u64)?;
67 Ok(())
68 }
69
70 pub fn deserialize_from<R: io::Read>(mut reader: R) -> io::Result<Self> {
71 let chunks = {
72 let len = reader.read_u64::<LittleEndian>()? as usize;
73 let mut chunks = vec![0; len];
74 for x in chunks.iter_mut() {
75 *x = reader.read_u64::<LittleEndian>()?;
76 }
77 chunks
78 };
79 let len = reader.read_u64::<LittleEndian>()? as usize;
80 let bits = reader.read_u64::<LittleEndian>()? as usize;
81 let mask = reader.read_u64::<LittleEndian>()?;
82 Ok(Self {
83 chunks,
84 len,
85 bits,
86 mask,
87 })
88 }
89
90 #[inline(always)]
91 const fn words_for(bits: usize) -> usize {
92 (bits + 63) / 64
93 }
94
95 #[inline(always)]
96 const fn decompose(x: usize) -> (usize, usize) {
97 (x / 64, x % 64)
98 }
99}