1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
const SIMPLE8B_BITS: [usize; 16] = [0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 15, 20, 30, 60];
const SIMPLE8B_N: [usize; 16] = [240, 120, 60, 30, 20, 15, 12, 10, 8, 7, 6, 5, 4, 3, 2, 1];
fn get_min_selector(i: u64) -> Result<usize, &'static str> {
let bits = 64 - i.leading_zeros();
if bits == 0 {
return Ok(0);
} else if bits <= 8 {
return Ok((bits + 1) as usize);
} else if bits <= 10 {
return Ok(10);
} else if bits <= 12 {
return Ok(11);
} else if bits <= 15 {
return Ok(12);
} else if bits <= 20 {
return Ok(13);
} else if bits <= 30 {
return Ok(14);
} else if bits <= 60 {
return Ok(15);
}
Err("value too large")
}
pub fn pack(data: &[u64], result: &mut u64) -> Result<usize, &'static str> {
let mut selector = 0;
let mut count: usize = 0;
for &v in data.iter() {
let selector_next = usize::max(get_min_selector(v)?, selector);
if count >= SIMPLE8B_N[selector_next] {
break;
}
selector = selector_next;
count += 1;
}
if count != data.len() {
while SIMPLE8B_N[selector] > count {
selector += 1;
}
}
let mut packed = 0;
for &v in data.iter().take(SIMPLE8B_N[selector]).rev() {
packed <<= SIMPLE8B_BITS[selector];
packed |= v;
}
*result = packed | (selector as u64) << 60;
Ok(count)
}
pub fn count_packed(v: u64) -> usize {
SIMPLE8B_N[(v >> 60) as usize]
}
pub fn unpack(v: u64, output: &mut [u64]) -> usize {
let count = usize::min(count_packed(v), output.len());
let bits = SIMPLE8B_BITS[(v >> 60) as usize];
let mask = u64::max_value() >> (64 - bits);
let mut v = v;
for i in 0..count {
output[i] = v & mask;
v >>= bits;
}
count
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_too_large() {
let values = [2, 76, 3, (u64::max_value() >> 4) + 1, 7, 2];
let mut r = 0;
let res = pack(&values, &mut r);
match res {
Ok(_) => panic!("no error"),
Err(_) => (),
}
}
}