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