1use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign};
32
33const BITS: usize = 64;
34type Block = u64;
35
36#[inline(always)]
37#[coverage(off)]
38fn div_rem(x: usize, d: usize) -> (usize, usize) {
39 (x / d, x % d)
40}
41
42#[derive(Clone, Debug, Default)]
48pub struct FixedBitSet {
49 data: Vec<Block>,
50 length: usize,
52}
53
54impl FixedBitSet {
55 #[coverage(off)]
57 pub const fn new() -> Self {
58 FixedBitSet {
59 data: Vec::new(),
60 length: 0,
61 }
62 }
63
64 #[coverage(off)]
67 pub fn with_capacity(bits: usize) -> Self {
68 let (mut blocks, rem) = div_rem(bits, BITS);
69 blocks += (rem > 0) as usize;
70 FixedBitSet {
71 data: vec![0; blocks],
72 length: bits,
73 }
74 }
75
76 #[coverage(off)]
78 pub fn grow(&mut self, bits: usize) {
79 if bits > self.length {
80 let (mut blocks, rem) = div_rem(bits, BITS);
81 blocks += (rem > 0) as usize;
82 self.length = bits;
83 self.data.resize(blocks, 0);
84 }
85 }
86
87 #[inline]
89 #[coverage(off)]
90 pub fn len(&self) -> usize {
91 self.length
92 }
93
94 #[inline]
96 #[coverage(off)]
97 pub fn is_empty(&self) -> bool {
98 self.len() == 0
99 }
100
101 #[inline]
108 #[coverage(off)]
109 pub fn contains(&self, bit: usize) -> bool {
110 let (block, i) = div_rem(bit, BITS);
111 match self.data.get(block) {
112 None => false,
113 Some(b) => (b & (1 << i)) != 0,
114 }
115 }
116
117 #[inline]
119 #[coverage(off)]
120 pub fn clear(&mut self) {
121 for elt in &mut self.data {
122 *elt = 0
123 }
124 }
125
126 #[inline(always)]
130 #[coverage(off)]
131 pub fn insert(&mut self, bit: usize) {
132 assert!(
133 bit < self.length,
134 "insert at index {} exceeds fixbitset size {}",
135 bit,
136 self.length
137 );
138 let (block, i) = div_rem(bit, BITS);
139 unsafe {
140 *self.data.get_unchecked_mut(block) |= 1 << i;
141 }
142 }
143
144 #[inline]
148 #[coverage(off)]
149 pub fn put(&mut self, bit: usize) -> bool {
150 assert!(
151 bit < self.length,
152 "put at index {} exceeds fixbitset size {}",
153 bit,
154 self.length
155 );
156 let (block, i) = div_rem(bit, BITS);
157 unsafe {
158 let word = self.data.get_unchecked_mut(block);
159 let prev = *word & (1 << i) != 0;
160 *word |= 1 << i;
161 prev
162 }
163 }
164 #[inline]
168 #[coverage(off)]
169 pub fn toggle(&mut self, bit: usize) {
170 assert!(
171 bit < self.length,
172 "toggle at index {} exceeds fixbitset size {}",
173 bit,
174 self.length
175 );
176 let (block, i) = div_rem(bit, BITS);
177 unsafe {
178 *self.data.get_unchecked_mut(block) ^= 1 << i;
179 }
180 }
181
182 #[inline]
188 #[coverage(off)]
189 pub fn count_ones(&self) -> usize {
190 let mut sum = 0;
191 for block in &self.data {
192 sum += block.count_ones();
193 }
194 sum as usize
195 }
196
197 #[inline]
201 #[coverage(off)]
202 pub fn ones(&self) -> Ones {
203 match self.as_slice().split_first() {
204 Some((&block, rem)) => Ones {
205 bitset: block,
206 block_idx: 0,
207 remaining_blocks: rem,
208 },
209 None => Ones {
210 bitset: 0,
211 block_idx: 0,
212 remaining_blocks: &[],
213 },
214 }
215 }
216
217 #[inline]
219 #[coverage(off)]
220 pub fn as_slice(&self) -> &[u64] {
221 &self.data
222 }
223
224 #[coverage(off)]
228 pub fn union_with(&mut self, other: &FixedBitSet) {
229 if other.len() >= self.len() {
230 self.grow(other.len());
231 }
232 for (x, y) in self.data.iter_mut().zip(other.data.iter()) {
233 *x |= *y;
234 }
235 }
236
237 #[coverage(off)]
241 pub fn intersect_with(&mut self, other: &FixedBitSet) {
242 for (x, y) in self.data.iter_mut().zip(other.data.iter()) {
243 *x &= *y;
244 }
245 let mn = std::cmp::min(self.data.len(), other.data.len());
246 for wd in &mut self.data[mn..] {
247 *wd = 0;
248 }
249 }
250
251 #[coverage(off)]
255 pub fn difference_with(&mut self, other: &FixedBitSet) {
256 for (x, y) in self.data.iter_mut().zip(other.data.iter()) {
257 *x &= !*y;
258 }
259
260 }
267
268 #[coverage(off)]
272 pub fn symmetric_difference_with(&mut self, other: &FixedBitSet) {
273 if other.len() >= self.len() {
274 self.grow(other.len());
275 }
276 for (x, y) in self.data.iter_mut().zip(other.data.iter()) {
277 *x ^= *y;
278 }
279 }
280}
281
282pub struct Ones<'a> {
286 bitset: Block,
287 block_idx: usize,
288 remaining_blocks: &'a [Block],
289}
290
291impl<'a> Iterator for Ones<'a> {
292 type Item = usize; #[inline]
295 #[coverage(off)]
296 fn next(&mut self) -> Option<Self::Item> {
297 while self.bitset == 0 {
298 if self.remaining_blocks.is_empty() {
299 return None;
300 }
301 self.bitset = self.remaining_blocks[0];
302 self.remaining_blocks = &self.remaining_blocks[1..];
303 self.block_idx += 1;
304 }
305 #[allow(clippy::unnecessary_cast)]
306 let t = self.bitset & (0 as Block).wrapping_sub(self.bitset);
307 let r = self.bitset.trailing_zeros() as usize;
308 self.bitset ^= t;
309 Some(self.block_idx * BITS + r)
310 }
311}
312
313impl<'a> BitAnd for &'a FixedBitSet {
314 type Output = FixedBitSet;
315 #[coverage(off)]
316 fn bitand(self, other: &FixedBitSet) -> FixedBitSet {
317 let (short, long) = {
318 if self.len() <= other.len() {
319 (&self.data, &other.data)
320 } else {
321 (&other.data, &self.data)
322 }
323 };
324 let mut data = short.clone();
325 for (data, block) in data.iter_mut().zip(long.iter()) {
326 *data &= *block;
327 }
328 let len = std::cmp::min(self.len(), other.len());
329 FixedBitSet { data, length: len }
330 }
331}
332
333impl BitAndAssign for FixedBitSet {
334 #[coverage(off)]
335 fn bitand_assign(&mut self, other: Self) {
336 self.intersect_with(&other);
337 }
338}
339
340impl BitAndAssign<&Self> for FixedBitSet {
341 #[coverage(off)]
342 fn bitand_assign(&mut self, other: &Self) {
343 self.intersect_with(other);
344 }
345}
346
347impl<'a> BitOr for &'a FixedBitSet {
348 type Output = FixedBitSet;
349 #[coverage(off)]
350 fn bitor(self, other: &FixedBitSet) -> FixedBitSet {
351 let (short, long) = {
352 if self.len() <= other.len() {
353 (&self.data, &other.data)
354 } else {
355 (&other.data, &self.data)
356 }
357 };
358 let mut data = long.clone();
359 for (data, block) in data.iter_mut().zip(short.iter()) {
360 *data |= *block;
361 }
362 let len = std::cmp::max(self.len(), other.len());
363 FixedBitSet { data, length: len }
364 }
365}
366
367impl BitOrAssign for FixedBitSet {
368 #[coverage(off)]
369 fn bitor_assign(&mut self, other: Self) {
370 self.union_with(&other);
371 }
372}
373
374impl BitOrAssign<&Self> for FixedBitSet {
375 #[coverage(off)]
376 fn bitor_assign(&mut self, other: &Self) {
377 self.union_with(other);
378 }
379}
380
381impl<'a> BitXor for &'a FixedBitSet {
382 type Output = FixedBitSet;
383 #[coverage(off)]
384 fn bitxor(self, other: &FixedBitSet) -> FixedBitSet {
385 let (short, long) = {
386 if self.len() <= other.len() {
387 (&self.data, &other.data)
388 } else {
389 (&other.data, &self.data)
390 }
391 };
392 let mut data = long.clone();
393 for (data, block) in data.iter_mut().zip(short.iter()) {
394 *data ^= *block;
395 }
396 let len = std::cmp::max(self.len(), other.len());
397 FixedBitSet { data, length: len }
398 }
399}
400
401impl BitXorAssign for FixedBitSet {
402 #[coverage(off)]
403 fn bitxor_assign(&mut self, other: Self) {
404 self.symmetric_difference_with(&other);
405 }
406}
407
408impl BitXorAssign<&Self> for FixedBitSet {
409 #[coverage(off)]
410 fn bitxor_assign(&mut self, other: &Self) {
411 self.symmetric_difference_with(other);
412 }
413}