oxihuman_core/
packed_array.rs1#![allow(dead_code)]
4
5pub struct PackedArray {
6 pub data: Vec<u64>,
7 pub bits: usize,
8 pub len: usize,
9}
10
11pub fn new_packed_array(len: usize, bits: usize) -> PackedArray {
12 let bits = bits.clamp(1, 64);
13 let total_bits = len * bits;
14 let words = total_bits.div_ceil(64);
15 PackedArray {
16 data: vec![0u64; words.max(1)],
17 bits,
18 len,
19 }
20}
21
22pub fn packed_get(a: &PackedArray, i: usize) -> u64 {
23 if i >= a.len {
24 return 0;
25 }
26 let bit_idx = i * a.bits;
27 let word = bit_idx / 64;
28 let offset = bit_idx % 64;
29 let mask = if a.bits == 64 {
30 u64::MAX
31 } else {
32 (1u64 << a.bits) - 1
33 };
34 if offset + a.bits <= 64 {
35 (a.data[word] >> offset) & mask
36 } else {
37 let lo = a.data[word] >> offset;
38 let hi_bits = a.bits - (64 - offset);
39 let hi = if word + 1 < a.data.len() {
40 a.data[word + 1] << (64 - offset)
41 } else {
42 0
43 };
44 let hi_mask = (1u64 << hi_bits) - 1;
45 lo | ((hi >> (64 - offset - hi_bits)) & hi_mask) << (64 - offset)
46 }
47}
48
49pub fn packed_set(a: &mut PackedArray, i: usize, val: u64) {
50 if i >= a.len {
51 return;
52 }
53 let bit_idx = i * a.bits;
54 let word = bit_idx / 64;
55 let offset = bit_idx % 64;
56 let mask = if a.bits == 64 {
57 u64::MAX
58 } else {
59 (1u64 << a.bits) - 1
60 };
61 let val = val & mask;
62 a.data[word] &= !(mask << offset);
63 a.data[word] |= val << offset;
64 if offset + a.bits > 64 && word + 1 < a.data.len() {
65 let spill = a.bits - (64 - offset);
66 let spill_mask = (1u64 << spill) - 1;
67 a.data[word + 1] &= !spill_mask;
68 a.data[word + 1] |= val >> (a.bits - spill);
69 }
70}
71
72pub fn packed_len(a: &PackedArray) -> usize {
73 a.len
74}
75pub fn packed_bits_per_elem(a: &PackedArray) -> usize {
76 a.bits
77}
78pub fn packed_storage_bytes(a: &PackedArray) -> usize {
79 a.data.len() * 8
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn set_and_get() {
88 let mut a = new_packed_array(10, 4);
90 packed_set(&mut a, 3, 0b1010);
91 assert_eq!(packed_get(&a, 3), 0b1010);
92 }
93
94 #[test]
95 fn initial_zero() {
96 let a = new_packed_array(8, 3);
98 for i in 0..8 {
99 assert_eq!(packed_get(&a, i), 0);
100 }
101 }
102
103 #[test]
104 fn multiple_elements() {
105 let mut a = new_packed_array(4, 8);
107 packed_set(&mut a, 0, 10);
108 packed_set(&mut a, 1, 20);
109 assert_eq!(packed_get(&a, 0), 10);
110 assert_eq!(packed_get(&a, 1), 20);
111 }
112
113 #[test]
114 fn len_correct() {
115 let a = new_packed_array(7, 5);
117 assert_eq!(packed_len(&a), 7);
118 }
119
120 #[test]
121 fn bits_per_elem() {
122 let a = new_packed_array(5, 6);
124 assert_eq!(packed_bits_per_elem(&a), 6);
125 }
126
127 #[test]
128 fn storage_bytes_positive() {
129 let a = new_packed_array(10, 4);
131 assert!(packed_storage_bytes(&a) > 0);
132 }
133
134 #[test]
135 fn out_of_bounds_get() {
136 let a = new_packed_array(4, 4);
138 assert_eq!(packed_get(&a, 100), 0);
139 }
140}