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
88
89
90
91
92
93
94
const BIT_MASKS: [u8; 8] = [
0x80,
0x40,
0x20,
0x10,
0x08,
0x04,
0x02,
0x01,
];
#[inline(always)]
pub fn byte_to_bits(byte: u8) -> [bool; 8] {
let mut res: [bool; 8];
unsafe {
res = std::mem::MaybeUninit::uninit().assume_init();
}
for i in 0..8 {
res[i] = (byte & BIT_MASKS[i]) > 0
}
res
}
pub fn bytes_to_bits(bytes: Vec<u8>) -> Vec<bool> {
let mut res = Vec::with_capacity(8 * bytes.len());
for b in &bytes {
res.extend(&byte_to_bits(*b));
}
res
}
pub fn bits_to_bytes(bits: Vec<bool>) -> Vec<u8> {
let mut res = Vec::new();
let mut i = 0;
while i < bits.len() {
let mut byte = 0 as u8;
for _ in 0..8 {
byte <<= 1;
if i < bits.len() {
if bits[i] {
byte |= 1;
}
i += 1;
}
}
res.push(byte);
}
return res;
}
pub fn bits_to_usize_truncated(bits: &Vec<bool>, max_depth: u32) -> usize {
let pow = 1_usize << (max_depth - 1);
let mut res = 0;
for i in 0..bits.len() {
if bits[i] {
res |= pow >> i;
}
}
res
}
pub fn usize_to_bits(x: usize, n_bits: u32) -> Vec<bool> {
u64_to_bits(x as u64, n_bits)
}
pub fn u64_to_bits(x: u64, n_bits: u32) -> Vec<bool> {
let mut res = Vec::with_capacity(n_bits as usize);
for i in 1..n_bits + 1 {
let shift = n_bits - i;
res.push(((x >> shift) & 1) > 0);
}
res
}
pub fn bits_to_string(bits: &Vec<bool>) -> String {
return bits
.iter()
.map(|b| if *b {"1"} else {"0"})
.collect::<Vec<&str>>()
.join("");
}
pub fn avg_base2_bits(upper_lower_diff: u64) -> f64 {
let n = upper_lower_diff as f64 + 1.0;
let k = n.log2().floor();
let two_to_k = (2.0 as f64).powf(k);
let overshoot = n - two_to_k;
return k + (2.0 * overshoot) / n;
}
pub fn depth_bits(weight: u64, total_weight: usize) -> f64 {
return -(weight as f64 / total_weight as f64).log2();
}