1use core::mem::size_of;
2
3pub fn align_down(x: usize, alignment: usize) -> usize {
4 x & !(alignment - 1)
5}
6
7pub fn align_up(x: usize, alignment: usize) -> usize {
8 x.wrapping_add(alignment.wrapping_sub(1)) & !(alignment - 1)
9}
10
11pub fn bit_vector_get_bit(buf: &[u32], index: usize) -> bool {
12 let vec_index = index / 32;
13 let bit_index = index % 32;
14
15 ((buf[vec_index] >> bit_index) & 1) != 0
16}
17
18pub fn bit_vector_set_bit(buf: &mut [u32], index: usize, value: bool) {
19 let vec_index = index / 32;
20 let bit_index = index % 32;
21
22 if value {
23 buf[vec_index] |= 1 << bit_index;
24 } else {
25 buf[vec_index] &= !(1 << bit_index);
26 }
27}
28
29pub fn bit_vector_flip_bit(buf: &mut [u32], index: usize) {
30 let vec_index = index / 32;
31 let bit_index = index % 32;
32
33 buf[vec_index] ^= 1 << bit_index;
34}
35
36macro_rules! bitvector_op {
37 ($name: ident, $op: expr, $opf: expr) => {
38 pub fn $name(mut buf: &mut [u32], index: usize, mut count: usize) {
39 if count == 0 {
40 return;
41 }
42
43 let vec_index = index / 32;
44 let bit_index = index % 32;
45
46 buf = &mut buf[vec_index..];
47
48 const FILL_MASK: u32 = u32::MAX;
49
50 let first_n_bits = (32usize.wrapping_sub(bit_index)).min(count);
51
52 buf[0] = $op(
53 buf[0],
54 (FILL_MASK >> (32 - first_n_bits as u32)) << bit_index as u32,
55 );
56
57 buf = &mut buf[1..];
58
59 count -= first_n_bits;
60
61 while count >= 32 {
62 buf[0] = $opf(buf[0], FILL_MASK);
63 buf = &mut buf[1..];
64 count -= 32;
65 }
66
67 if count != 0 {
68 buf[0] = $op(buf[0], FILL_MASK >> (32 - count as u32));
69 }
70 }
71 };
72}
73
74bitvector_op!(bit_vector_fill, |x, y| x | y, |_, x| x);
75bitvector_op!(bit_vector_clear, |x: u32, y: u32| x & !y, |_, y: u32| !y);
76
77pub fn bit_vector_index_of(buf: &[u32], start: usize, value: bool) -> usize {
78 let vec_index = start / 32;
79 let bit_index = start % 32;
80
81 let mut p = &buf[vec_index..];
82 const FILL_MASK: u32 = u32::MAX;
83
84 let flip_mask = if value { 0 } else { FILL_MASK };
85
86 let mut bits = (p[0] ^ flip_mask) & (FILL_MASK << bit_index as u32);
87
88 loop {
89 if bits != 0 {
90 return ((p.as_ptr() as usize - buf.as_ptr() as usize) / size_of::<u32>()) * 32
91 + bits.trailing_zeros() as usize;
92 }
93
94 p = &p[1..];
95
96 if p.is_empty() {
97 return buf.len() * 32;
98 }
99
100 bits = p[0] ^ flip_mask;
101 }
102}