fuzzcheck/
bitset.rs

1// Note: The following file is largely derived from the fixedbitset
2// crate, (crates.io/crates/fixedbitset) of which I have copied the
3// license (MIT) below:
4//
5// Copyright (c) 2015-2017
6//
7// Permission is hereby granted, free of charge, to any
8// person obtaining a copy of this software and associated
9// documentation files (the "Software"), to deal in the
10// Software without restriction, including without
11// limitation the rights to use, copy, modify, merge,
12// publish, distribute, sublicense, and/or sell copies of
13// the Software, and to permit persons to whom the Software
14// is furnished to do so, subject to the following
15// conditions:
16//
17// The above copyright notice and this permission notice
18// shall be included in all copies or substantial portions
19// of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
23// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
24// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
25// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
28// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30
31use 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/// `FixedBitSet` is a simple fixed size set of bits that each can
43/// be enabled (1 / **true**) or disabled (0 / **false**).
44///
45/// The bit set has a fixed capacity in terms of enabling bits (and the
46/// capacity can grow using the `grow` method).
47#[derive(Clone, Debug, Default)]
48pub struct FixedBitSet {
49    data: Vec<Block>,
50    /// length in bits
51    length: usize,
52}
53
54impl FixedBitSet {
55    /// Create a new empty **FixedBitSet**.
56    #[coverage(off)]
57    pub const fn new() -> Self {
58        FixedBitSet {
59            data: Vec::new(),
60            length: 0,
61        }
62    }
63
64    /// Create a new **FixedBitSet** with a specific number of bits,
65    /// all initially clear.
66    #[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    /// Grow capacity to **bits**, all new bits initialized to zero
77    #[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    /// Return the length of the [`FixedBitSet`] in bits.
88    #[inline]
89    #[coverage(off)]
90    pub fn len(&self) -> usize {
91        self.length
92    }
93
94    /// Return if the [`FixedBitSet`] is empty.
95    #[inline]
96    #[coverage(off)]
97    pub fn is_empty(&self) -> bool {
98        self.len() == 0
99    }
100
101    /// Return **true** if the bit is enabled in the **FixedBitSet**,
102    /// **false** otherwise.
103    ///
104    /// Note: bits outside the capacity are always disabled.
105    ///
106    /// Note: Also available with index syntax: `bitset[bit]`.
107    #[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    /// Clear all bits.
118    #[inline]
119    #[coverage(off)]
120    pub fn clear(&mut self) {
121        for elt in &mut self.data {
122            *elt = 0
123        }
124    }
125
126    /// Enable `bit`.
127    ///
128    /// **Panics** if **bit** is out of bounds.
129    #[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    /// Enable `bit`, and return its previous value.
145    ///
146    /// **Panics** if **bit** is out of bounds.
147    #[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    /// Toggle `bit` (inverting its state).
165    ///
166    /// ***Panics*** if **bit** is out of bounds
167    #[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    /// Count the number of set bits in the given bit range.
183    ///
184    /// Use `..` to count the whole content of the bitset.
185    ///
186    /// **Panics** if the range extends past the end of the bitset.
187    #[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    /// Iterates over all enabled bits.
198    ///
199    /// Iterator element is the index of the `1` bit, type `usize`.
200    #[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    /// View the bitset as a slice of `u64` blocks
218    #[inline]
219    #[coverage(off)]
220    pub fn as_slice(&self) -> &[u64] {
221        &self.data
222    }
223
224    /// In-place union of two `FixedBitSet`s.
225    ///
226    /// On calling this method, `self`'s capacity may be increased to match `other`'s.
227    #[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    /// In-place intersection of two `FixedBitSet`s.
238    ///
239    /// On calling this method, `self`'s capacity will remain the same as before.
240    #[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    /// In-place difference of two `FixedBitSet`s.
252    ///
253    /// On calling this method, `self`'s capacity will remain the same as before.
254    #[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        // There's no need to grow self or do any other adjustments.
261        //
262        // * If self is longer than other, the bits at the end of self won't be affected since other
263        //   has them implicitly set to 0.
264        // * If other is longer than self, the bits at the end of other are irrelevant since self
265        //   has them set to 0 anyway.
266    }
267
268    /// In-place symmetric difference of two `FixedBitSet`s.
269    ///
270    /// On calling this method, `self`'s capacity may be increased to match `other`'s.
271    #[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
282/// An  iterator producing the indices of the set bit in a set.
283///
284/// This struct is created by the [`FixedBitSet::ones`] method.
285pub 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; // the bit position of the '1'
293
294    #[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}