xref: /aosp_15_r20/external/mesa3d/src/compiler/rust/bitset.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker // Copyright © 2022 Collabora, Ltd.
2*61046927SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker 
4*61046927SAndroid Build Coastguard Worker use std::ops::{
5*61046927SAndroid Build Coastguard Worker     BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Range,
6*61046927SAndroid Build Coastguard Worker };
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #[derive(Clone)]
9*61046927SAndroid Build Coastguard Worker pub struct BitSet {
10*61046927SAndroid Build Coastguard Worker     words: Vec<u32>,
11*61046927SAndroid Build Coastguard Worker }
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker impl BitSet {
new() -> BitSet14*61046927SAndroid Build Coastguard Worker     pub fn new() -> BitSet {
15*61046927SAndroid Build Coastguard Worker         BitSet { words: Vec::new() }
16*61046927SAndroid Build Coastguard Worker     }
17*61046927SAndroid Build Coastguard Worker 
reserve_words(&mut self, words: usize)18*61046927SAndroid Build Coastguard Worker     fn reserve_words(&mut self, words: usize) {
19*61046927SAndroid Build Coastguard Worker         if self.words.len() < words {
20*61046927SAndroid Build Coastguard Worker             self.words.resize(words, 0);
21*61046927SAndroid Build Coastguard Worker         }
22*61046927SAndroid Build Coastguard Worker     }
23*61046927SAndroid Build Coastguard Worker 
reserve(&mut self, bits: usize)24*61046927SAndroid Build Coastguard Worker     pub fn reserve(&mut self, bits: usize) {
25*61046927SAndroid Build Coastguard Worker         self.reserve_words(bits.div_ceil(32));
26*61046927SAndroid Build Coastguard Worker     }
27*61046927SAndroid Build Coastguard Worker 
clear(&mut self)28*61046927SAndroid Build Coastguard Worker     pub fn clear(&mut self) {
29*61046927SAndroid Build Coastguard Worker         for w in self.words.iter_mut() {
30*61046927SAndroid Build Coastguard Worker             *w = 0;
31*61046927SAndroid Build Coastguard Worker         }
32*61046927SAndroid Build Coastguard Worker     }
33*61046927SAndroid Build Coastguard Worker 
get(&self, idx: usize) -> bool34*61046927SAndroid Build Coastguard Worker     pub fn get(&self, idx: usize) -> bool {
35*61046927SAndroid Build Coastguard Worker         let w = idx / 32;
36*61046927SAndroid Build Coastguard Worker         let b = idx % 32;
37*61046927SAndroid Build Coastguard Worker         if w < self.words.len() {
38*61046927SAndroid Build Coastguard Worker             self.words[w] & (1_u32 << b) != 0
39*61046927SAndroid Build Coastguard Worker         } else {
40*61046927SAndroid Build Coastguard Worker             false
41*61046927SAndroid Build Coastguard Worker         }
42*61046927SAndroid Build Coastguard Worker     }
43*61046927SAndroid Build Coastguard Worker 
is_empty(&self) -> bool44*61046927SAndroid Build Coastguard Worker     pub fn is_empty(&self) -> bool {
45*61046927SAndroid Build Coastguard Worker         for w in self.words.iter() {
46*61046927SAndroid Build Coastguard Worker             if *w != 0 {
47*61046927SAndroid Build Coastguard Worker                 return false;
48*61046927SAndroid Build Coastguard Worker             }
49*61046927SAndroid Build Coastguard Worker         }
50*61046927SAndroid Build Coastguard Worker         true
51*61046927SAndroid Build Coastguard Worker     }
52*61046927SAndroid Build Coastguard Worker 
iter(&self) -> BitSetIter<'_>53*61046927SAndroid Build Coastguard Worker     pub fn iter(&self) -> BitSetIter<'_> {
54*61046927SAndroid Build Coastguard Worker         BitSetIter::new(self, 0)
55*61046927SAndroid Build Coastguard Worker     }
56*61046927SAndroid Build Coastguard Worker 
get_word(&self, word: usize) -> u3257*61046927SAndroid Build Coastguard Worker     pub fn get_word(&self, word: usize) -> u32 {
58*61046927SAndroid Build Coastguard Worker         self.words.get(word).cloned().unwrap_or(0)
59*61046927SAndroid Build Coastguard Worker     }
60*61046927SAndroid Build Coastguard Worker 
next_unset(&self, start: usize) -> usize61*61046927SAndroid Build Coastguard Worker     pub fn next_unset(&self, start: usize) -> usize {
62*61046927SAndroid Build Coastguard Worker         if start >= self.words.len() * 32 {
63*61046927SAndroid Build Coastguard Worker             return start;
64*61046927SAndroid Build Coastguard Worker         }
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker         let mut w = start / 32;
67*61046927SAndroid Build Coastguard Worker         let mut mask = !(u32::MAX << (start % 32));
68*61046927SAndroid Build Coastguard Worker         while w < self.words.len() {
69*61046927SAndroid Build Coastguard Worker             let b = (self.words[w] | mask).trailing_ones();
70*61046927SAndroid Build Coastguard Worker             if b < 32 {
71*61046927SAndroid Build Coastguard Worker                 return w * 32 + usize::try_from(b).unwrap();
72*61046927SAndroid Build Coastguard Worker             }
73*61046927SAndroid Build Coastguard Worker             mask = 0;
74*61046927SAndroid Build Coastguard Worker             w += 1;
75*61046927SAndroid Build Coastguard Worker         }
76*61046927SAndroid Build Coastguard Worker         self.words.len() * 32
77*61046927SAndroid Build Coastguard Worker     }
78*61046927SAndroid Build Coastguard Worker 
insert(&mut self, idx: usize) -> bool79*61046927SAndroid Build Coastguard Worker     pub fn insert(&mut self, idx: usize) -> bool {
80*61046927SAndroid Build Coastguard Worker         let w = idx / 32;
81*61046927SAndroid Build Coastguard Worker         let b = idx % 32;
82*61046927SAndroid Build Coastguard Worker         self.reserve_words(w + 1);
83*61046927SAndroid Build Coastguard Worker         let exists = self.words[w] & (1_u32 << b) != 0;
84*61046927SAndroid Build Coastguard Worker         self.words[w] |= 1_u32 << b;
85*61046927SAndroid Build Coastguard Worker         !exists
86*61046927SAndroid Build Coastguard Worker     }
87*61046927SAndroid Build Coastguard Worker 
remove(&mut self, idx: usize) -> bool88*61046927SAndroid Build Coastguard Worker     pub fn remove(&mut self, idx: usize) -> bool {
89*61046927SAndroid Build Coastguard Worker         let w = idx / 32;
90*61046927SAndroid Build Coastguard Worker         let b = idx % 32;
91*61046927SAndroid Build Coastguard Worker         self.reserve_words(w + 1);
92*61046927SAndroid Build Coastguard Worker         let exists = self.words[w] & (1_u32 << b) != 0;
93*61046927SAndroid Build Coastguard Worker         self.words[w] &= !(1_u32 << b);
94*61046927SAndroid Build Coastguard Worker         exists
95*61046927SAndroid Build Coastguard Worker     }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker     #[inline]
set_word( &mut self, w: usize, mask: u32, f: &mut impl FnMut(usize) -> u32, )98*61046927SAndroid Build Coastguard Worker     fn set_word(
99*61046927SAndroid Build Coastguard Worker         &mut self,
100*61046927SAndroid Build Coastguard Worker         w: usize,
101*61046927SAndroid Build Coastguard Worker         mask: u32,
102*61046927SAndroid Build Coastguard Worker         f: &mut impl FnMut(usize) -> u32,
103*61046927SAndroid Build Coastguard Worker     ) {
104*61046927SAndroid Build Coastguard Worker         self.words[w] = (self.words[w] & !mask) | (f(w) & mask);
105*61046927SAndroid Build Coastguard Worker     }
106*61046927SAndroid Build Coastguard Worker 
set_words( &mut self, bits: Range<usize>, mut f: impl FnMut(usize) -> u32, )107*61046927SAndroid Build Coastguard Worker     pub fn set_words(
108*61046927SAndroid Build Coastguard Worker         &mut self,
109*61046927SAndroid Build Coastguard Worker         bits: Range<usize>,
110*61046927SAndroid Build Coastguard Worker         mut f: impl FnMut(usize) -> u32,
111*61046927SAndroid Build Coastguard Worker     ) {
112*61046927SAndroid Build Coastguard Worker         if bits.is_empty() {
113*61046927SAndroid Build Coastguard Worker             return;
114*61046927SAndroid Build Coastguard Worker         }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker         let first_word = bits.start / 32;
117*61046927SAndroid Build Coastguard Worker         let last_word = (bits.end - 1) / 32;
118*61046927SAndroid Build Coastguard Worker         let start_mask = !0_u32 << (bits.start % 32);
119*61046927SAndroid Build Coastguard Worker         let end_mask = !0_u32 >> (31 - ((bits.end - 1) % 32));
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker         self.reserve(last_word + 1);
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker         if first_word == last_word {
124*61046927SAndroid Build Coastguard Worker             self.set_word(first_word, start_mask & end_mask, &mut f);
125*61046927SAndroid Build Coastguard Worker         } else {
126*61046927SAndroid Build Coastguard Worker             self.set_word(first_word, start_mask, &mut f);
127*61046927SAndroid Build Coastguard Worker             for w in (first_word + 1)..last_word {
128*61046927SAndroid Build Coastguard Worker                 self.set_word(w, !0, &mut f);
129*61046927SAndroid Build Coastguard Worker             }
130*61046927SAndroid Build Coastguard Worker             self.set_word(last_word, end_mask, &mut f);
131*61046927SAndroid Build Coastguard Worker         }
132*61046927SAndroid Build Coastguard Worker     }
133*61046927SAndroid Build Coastguard Worker 
union_with(&mut self, other: &BitSet) -> bool134*61046927SAndroid Build Coastguard Worker     pub fn union_with(&mut self, other: &BitSet) -> bool {
135*61046927SAndroid Build Coastguard Worker         let mut added_bits = false;
136*61046927SAndroid Build Coastguard Worker         self.reserve_words(other.words.len());
137*61046927SAndroid Build Coastguard Worker         for w in 0..other.words.len() {
138*61046927SAndroid Build Coastguard Worker             let uw = self.words[w] | other.words[w];
139*61046927SAndroid Build Coastguard Worker             if uw != self.words[w] {
140*61046927SAndroid Build Coastguard Worker                 added_bits = true;
141*61046927SAndroid Build Coastguard Worker                 self.words[w] = uw;
142*61046927SAndroid Build Coastguard Worker             }
143*61046927SAndroid Build Coastguard Worker         }
144*61046927SAndroid Build Coastguard Worker         added_bits
145*61046927SAndroid Build Coastguard Worker     }
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker impl Default for BitSet {
default() -> BitSet149*61046927SAndroid Build Coastguard Worker     fn default() -> BitSet {
150*61046927SAndroid Build Coastguard Worker         BitSet::new()
151*61046927SAndroid Build Coastguard Worker     }
152*61046927SAndroid Build Coastguard Worker }
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker impl BitAndAssign for BitSet {
bitand_assign(&mut self, rhs: BitSet)155*61046927SAndroid Build Coastguard Worker     fn bitand_assign(&mut self, rhs: BitSet) {
156*61046927SAndroid Build Coastguard Worker         self.reserve_words(rhs.words.len());
157*61046927SAndroid Build Coastguard Worker         for w in 0..rhs.words.len() {
158*61046927SAndroid Build Coastguard Worker             self.words[w] &= rhs.words[w];
159*61046927SAndroid Build Coastguard Worker         }
160*61046927SAndroid Build Coastguard Worker     }
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker impl BitAnd<BitSet> for BitSet {
164*61046927SAndroid Build Coastguard Worker     type Output = BitSet;
165*61046927SAndroid Build Coastguard Worker 
bitand(self, rhs: BitSet) -> BitSet166*61046927SAndroid Build Coastguard Worker     fn bitand(self, rhs: BitSet) -> BitSet {
167*61046927SAndroid Build Coastguard Worker         let mut res = self;
168*61046927SAndroid Build Coastguard Worker         res.bitand_assign(rhs);
169*61046927SAndroid Build Coastguard Worker         res
170*61046927SAndroid Build Coastguard Worker     }
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker impl BitOrAssign for BitSet {
bitor_assign(&mut self, rhs: BitSet)174*61046927SAndroid Build Coastguard Worker     fn bitor_assign(&mut self, rhs: BitSet) {
175*61046927SAndroid Build Coastguard Worker         self.reserve_words(rhs.words.len());
176*61046927SAndroid Build Coastguard Worker         for w in 0..rhs.words.len() {
177*61046927SAndroid Build Coastguard Worker             self.words[w] |= rhs.words[w];
178*61046927SAndroid Build Coastguard Worker         }
179*61046927SAndroid Build Coastguard Worker     }
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker impl BitOr<BitSet> for BitSet {
183*61046927SAndroid Build Coastguard Worker     type Output = BitSet;
184*61046927SAndroid Build Coastguard Worker 
bitor(self, rhs: BitSet) -> BitSet185*61046927SAndroid Build Coastguard Worker     fn bitor(self, rhs: BitSet) -> BitSet {
186*61046927SAndroid Build Coastguard Worker         let mut res = self;
187*61046927SAndroid Build Coastguard Worker         res.bitor_assign(rhs);
188*61046927SAndroid Build Coastguard Worker         res
189*61046927SAndroid Build Coastguard Worker     }
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker impl BitXorAssign for BitSet {
bitxor_assign(&mut self, rhs: BitSet)193*61046927SAndroid Build Coastguard Worker     fn bitxor_assign(&mut self, rhs: BitSet) {
194*61046927SAndroid Build Coastguard Worker         self.reserve_words(rhs.words.len());
195*61046927SAndroid Build Coastguard Worker         for w in 0..rhs.words.len() {
196*61046927SAndroid Build Coastguard Worker             self.words[w] ^= rhs.words[w];
197*61046927SAndroid Build Coastguard Worker         }
198*61046927SAndroid Build Coastguard Worker     }
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker impl BitXor<BitSet> for BitSet {
202*61046927SAndroid Build Coastguard Worker     type Output = BitSet;
203*61046927SAndroid Build Coastguard Worker 
bitxor(self, rhs: BitSet) -> BitSet204*61046927SAndroid Build Coastguard Worker     fn bitxor(self, rhs: BitSet) -> BitSet {
205*61046927SAndroid Build Coastguard Worker         let mut res = self;
206*61046927SAndroid Build Coastguard Worker         res.bitxor_assign(rhs);
207*61046927SAndroid Build Coastguard Worker         res
208*61046927SAndroid Build Coastguard Worker     }
209*61046927SAndroid Build Coastguard Worker }
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker impl Not for BitSet {
212*61046927SAndroid Build Coastguard Worker     type Output = BitSet;
213*61046927SAndroid Build Coastguard Worker 
not(self) -> BitSet214*61046927SAndroid Build Coastguard Worker     fn not(self) -> BitSet {
215*61046927SAndroid Build Coastguard Worker         let mut res = self;
216*61046927SAndroid Build Coastguard Worker         for w in 0..res.words.len() {
217*61046927SAndroid Build Coastguard Worker             res.words[w] = !res.words[w];
218*61046927SAndroid Build Coastguard Worker         }
219*61046927SAndroid Build Coastguard Worker         res
220*61046927SAndroid Build Coastguard Worker     }
221*61046927SAndroid Build Coastguard Worker }
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker pub struct BitSetIter<'a> {
224*61046927SAndroid Build Coastguard Worker     set: &'a BitSet,
225*61046927SAndroid Build Coastguard Worker     w: usize,
226*61046927SAndroid Build Coastguard Worker     mask: u32,
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker impl<'a> BitSetIter<'a> {
new(set: &'a BitSet, start: usize) -> Self230*61046927SAndroid Build Coastguard Worker     fn new(set: &'a BitSet, start: usize) -> Self {
231*61046927SAndroid Build Coastguard Worker         Self {
232*61046927SAndroid Build Coastguard Worker             set,
233*61046927SAndroid Build Coastguard Worker             w: start / 32,
234*61046927SAndroid Build Coastguard Worker             mask: u32::MAX << (start % 32),
235*61046927SAndroid Build Coastguard Worker         }
236*61046927SAndroid Build Coastguard Worker     }
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker impl<'a> Iterator for BitSetIter<'a> {
240*61046927SAndroid Build Coastguard Worker     type Item = usize;
241*61046927SAndroid Build Coastguard Worker 
next(&mut self) -> Option<usize>242*61046927SAndroid Build Coastguard Worker     fn next(&mut self) -> Option<usize> {
243*61046927SAndroid Build Coastguard Worker         while self.w < self.set.words.len() {
244*61046927SAndroid Build Coastguard Worker             let b = (self.set.words[self.w] & self.mask).trailing_zeros();
245*61046927SAndroid Build Coastguard Worker             if b < 32 {
246*61046927SAndroid Build Coastguard Worker                 return Some(self.w * 32 + usize::try_from(b).unwrap());
247*61046927SAndroid Build Coastguard Worker             }
248*61046927SAndroid Build Coastguard Worker             self.mask = u32::MAX;
249*61046927SAndroid Build Coastguard Worker             self.w += 1;
250*61046927SAndroid Build Coastguard Worker         }
251*61046927SAndroid Build Coastguard Worker         None
252*61046927SAndroid Build Coastguard Worker     }
253*61046927SAndroid Build Coastguard Worker }
254