• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vigna / sux-rs / 18418886435

10 Oct 2025 09:29PM UTC coverage: 65.341% (-1.8%) from 67.111%
18418886435

push

github

vigna
Lifted bit-vector operation to anything implementing AsRef/BitLen

52 of 65 new or added lines in 3 files covered. (80.0%)

102 existing lines in 1 file now uncovered.

3729 of 5707 relevant lines covered (65.34%)

117669419.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.01
/src/bits/bit_vec.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Inria
3
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
4
 *
5
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6
 */
7

8
//! Bit vector implementations.
9
//!
10
//! There are two flavors: [`BitVec`], a mutable bit vector, and
11
//! [`AtomicBitVec`], a mutable, thread-safe bit vector.
12
//!
13
//! These flavors depends on a backend, and presently we provide:
14
//!
15
//! - `BitVec<Vec<usize>>`: a mutable, growable and resizable bit vector;
16
//! - `BitVec<AsRef<[usize]>>`: an immutable bit vector, useful for
17
//!   [ε-serde](epserde) support;
18
//! - `BitVec<AsRef<[usize]> + AsMut<[usize]>>`: a mutable (but not resizable)
19
//!   bit vector;
20
//! - `AtomicBitVec<AsRef<[AtomicUsize]>>`: a thread-safe, mutable (but not
21
//!   resizable) bit vector.
22
//!
23
//! Note that nothing is assumed about the content of the backend outside the
24
//! bits of the bit vector. Moreover, the content of the backend outside of
25
//! the bit vector is never modified by the methods of this structure.
26
//!
27
//! It is possible to juggle between the three flavors using [`From`]/[`Into`].
28
//!
29
//! # Examples
30
//!
31
//! ```rust
32
//! use sux::bit_vec;
33
//! use sux::traits::{BitCount, BitLength, NumBits, AddNumBits};
34
//! use sux::bits::{BitVec, AtomicBitVec};
35
//! use core::sync::atomic::Ordering;
36
//!
37
//! // Convenience macro
38
//! let b = bit_vec![0, 1, 0, 1, 1, 0, 1, 0];
39
//! assert_eq!(b.len(), 8);
40
//! // Not constant time
41
//! assert_eq!(b.count_ones(), 4);
42
//! assert_eq!(b[0], false);
43
//! assert_eq!(b[1], true);
44
//! assert_eq!(b[2], false);
45
//!
46
//! let b: AddNumBits<_> = b.into();
47
//! // Constant time, but now b is immutable
48
//! assert_eq!(b.num_ones(), 4);
49
//!
50
//! let mut b = BitVec::new(0);
51
//! b.push(true);
52
//! b.push(false);
53
//! b.push(true);
54
//! assert_eq!(b.len(), 3);
55
//!
56
//! // Let's make it atomic
57
//! let mut a: AtomicBitVec = b.into();
58
//! a.set(1, true, Ordering::Relaxed);
59
//! assert!(a.get(0, Ordering::Relaxed));
60
//!
61
//! // Back to normal, but immutable size
62
//! let b: BitVec<Vec<usize>> = a.into();
63
//! let mut b: BitVec<Box<[usize]>> = b.into();
64
//! b.set(2, false);
65
//!
66
//! // If we create an artificially dirty bit vector, everything still works.
67
//! let ones = [usize::MAX; 2];
68
//! assert_eq!(unsafe { BitVec::from_raw_parts(ones, 1) }.count_ones(), 1);
69
//! ```
70

71
use common_traits::{IntoAtomic, SelectInWord};
72
#[allow(unused_imports)] // this is in the std prelude but not in no_std!
73
use core::borrow::BorrowMut;
74
use core::fmt;
75
use mem_dbg::*;
76
#[cfg(feature = "rayon")]
77
use rayon::prelude::*;
78
use std::{
79
    ops::Index,
80
    sync::atomic::{AtomicUsize, Ordering},
81
};
82

83
use crate::{
84
    traits::rank_sel::*,
85
    utils::{
86
        CannotCastToAtomicError, transmute_boxed_slice_from_atomic,
87
        transmute_boxed_slice_into_atomic, transmute_vec_from_atomic, transmute_vec_into_atomic,
88
    },
89
};
90

91
#[cfg(feature = "rayon")]
92
use crate::RAYON_MIN_LEN;
93

94
const BITS: usize = usize::BITS as usize;
95

96
/// Convenient, [`vec!`](vec!)-like macro to initialize bit vectors.
97
///
98
/// # Examples
99
///
100
/// ```rust
101
/// use sux::bit_vec;
102
/// use sux::traits::BitLength;
103
///
104
/// // Empty bit vector
105
/// let b = bit_vec![];
106
/// assert_eq!(b.len(), 0);
107
///
108
/// // 10 bits set to true
109
/// let b = bit_vec![true; 10];
110
/// assert_eq!(b.len(), 10);
111
/// assert_eq!(b.iter().all(|x| x), true);
112
/// let b = bit_vec![1; 10];
113
/// assert_eq!(b.len(), 10);
114
/// assert_eq!(b.iter().all(|x| x), true);
115
///
116
/// // 10 bits set to false
117
/// let b = bit_vec![false; 10];
118
/// assert_eq!(b.len(), 10);
119
/// assert_eq!(b.iter().any(|x| x), false);
120
/// let b = bit_vec![0; 10];
121
/// assert_eq!(b.len(), 10);
122
/// assert_eq!(b.iter().any(|x| x), false);
123
///
124
/// // Bit list
125
/// let b = bit_vec![0, 1, 0, 1, 0, 0];
126
/// assert_eq!(b.len(), 6);
127
/// assert_eq!(b[0], false);
128
/// assert_eq!(b[1], true);
129
/// assert_eq!(b[2], false);
130
/// assert_eq!(b[3], true);
131
/// assert_eq!(b[4], false);
132
/// assert_eq!(b[5], false);
133
/// ```
134
#[macro_export]
135
macro_rules! bit_vec {
136
    () => {
137
        $crate::bits::BitVec::new(0)
138
    };
139
    (false; $n:expr) => {
140
        $crate::bits::BitVec::new($n)
141
    };
142
    (0; $n:expr) => {
143
        $crate::bits::BitVec::new($n)
144
    };
145
    (true; $n:expr) => {
146
        {
147
            $crate::bits::BitVec::with_value($n, true)
148
        }
149
    };
150
    (1; $n:expr) => {
151
        {
152
            $crate::bits::BitVec::with_value($n, true)
153
        }
154
    };
155
    ($($x:expr),+ $(,)?) => {
156
        {
157
            let mut b = $crate::bits::BitVec::with_capacity([$($x),+].len());
158
            $( b.push($x != 0); )*
159
            b
160
        }
161
    };
162
}
163

164
macro_rules! panic_if_out_of_bounds {
165
    ($index: expr, $len: expr) => {
166
        if $index >= $len {
167
            panic!("Bit index out of bounds: {} >= {}", $index, $len)
168
        }
169
    };
170
}
171

172
#[derive(Debug, Clone, Copy, MemDbg, MemSize)]
173
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
174
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175
/// A bit vector.
176
pub struct BitVec<B = Vec<usize>> {
177
    bits: B,
178
    len: usize,
179
}
180

181
impl<B> BitVec<B> {
182
    /// Returns the number of bits in the bit vector.
183
    ///
184
    /// This method is equivalent to [`BitLength::len`], but it is provided to
185
    /// reduce ambiguity in method resolution.
186
    #[inline(always)]
187
    pub fn len(&self) -> usize {
222,203✔
188
        BitLength::len(self)
444,406✔
189
    }
190

191
    /// # Safety
192
    /// `len` must be between 0 (included) the number of
193
    /// bits in `bits` (included).
194
    #[inline(always)]
195
    pub unsafe fn from_raw_parts(bits: B, len: usize) -> Self {
24✔
196
        Self { bits, len }
197
    }
198

199
    #[inline(always)]
200
    pub fn into_raw_parts(self) -> (B, usize) {
2✔
201
        (self.bits, self.len)
2✔
202
    }
203

204
    #[inline(always)]
205
    /// Modify the bit vector in place.
206
    /// # Safety
207
    /// This is unsafe because it's the caller's responsibility to ensure that
208
    /// that the length is compatible with the modified bits.
209
    pub unsafe fn map<B2>(self, f: impl FnOnce(B) -> B2) -> BitVec<B2> {
×
210
        BitVec {
211
            bits: f(self.bits),
×
212
            len: self.len,
×
213
        }
214
    }
215
}
216

217
impl<T: ?Sized + AsRef<[usize]> + BitLength> BitVecOps for T {}
218

219
pub trait BitVecOps: AsRef<[usize]> + BitLength {
220
    /// Returns true if the bit of given index is set.
221
    #[inline]
222
    fn get(&self, index: usize) -> bool {
481,610,659✔
223
        panic_if_out_of_bounds!(index, self.len());
963,221,320✔
224
        unsafe { self.get_unchecked(index) }
481,610,658✔
225
    }
226

227
    /// Returns true if the bit of given index is set, without
228
    /// bound checks.
229
    ///
230
    /// # Safety
231
    ///
232
    /// `index` must be between 0 (included) and [`BitVec::len`] (excluded).
233
    #[inline(always)]
234
    unsafe fn get_unchecked(&self, index: usize) -> bool {
481,610,658✔
235
        let word_index = index / BITS;
963,221,316✔
236
        let word = unsafe { self.as_ref().get_unchecked(word_index) };
1,926,442,632✔
237
        (word >> (index % BITS)) & 1 != 0
481,610,658✔
238
    }
239

240
    // Returns an iterator over the bits of the bit vector.
241
    #[inline(always)]
242
    fn iter(&self) -> BitIterator<'_, [usize]> {
5✔
243
        BitIterator {
244
            bits: self.as_ref(),
10✔
245
            len: self.len(),
5✔
246
            next_bit_pos: 0,
247
        }
248
    }
249

250
    // Returns an iterator over the positions of the ones in this bit vector.
251
    fn iter_ones(&self) -> OnesIterator<'_, [usize]> {
5✔
252
        OnesIterator::new(self.as_ref(), self.len())
20✔
253
    }
254

255
    // Returns an iterator over the positions of the zeros in this bit vector.
256
    fn iter_zeros(&self) -> ZerosIterator<'_, [usize]> {
5✔
257
        ZerosIterator::new(self.as_ref(), self.len())
20✔
258
    }
259
}
260

261
impl<B: AsRef<[usize]>> BitVec<B> {
262
    /// Returns an owned copy of the bit vector.
NEW
263
    pub fn to_owned(&self) -> BitVec {
×
264
        BitVec {
NEW
265
            bits: self.bits.as_ref().to_owned(),
×
NEW
266
            len: self.len,
×
267
        }
268
    }
269
}
270

271
impl<T: AsRef<[usize]> + AsMut<[usize]> + BitLength> BitVecOpsMut for T {}
272

273
pub trait BitVecOpsMut: AsRef<[usize]> + AsMut<[usize]> + BitLength {
274
    #[inline]
275
    fn set(&mut self, index: usize, value: bool) {
2,147,483,647✔
276
        panic_if_out_of_bounds!(index, self.len());
2,147,483,647✔
277
        unsafe { self.set_unchecked(index, value) }
2,147,483,647✔
278
    }
279

280
    /// # Safety
281
    ///
282
    /// `index` must be between 0 (included) and [`BitVec::len`] (excluded).
283
    #[inline(always)]
284
    unsafe fn set_unchecked(&mut self, index: usize, value: bool) {
2,147,483,647✔
285
        let word_index = index / BITS;
2,147,483,647✔
286
        let bit_index = index % BITS;
2,147,483,647✔
287
        let bits = self.as_mut();
2,147,483,647✔
288
        // TODO: no test?
289
        // For constant values, this should be inlined with no test.
290
        unsafe {
291
            if value {
2,147,483,647✔
292
                *bits.get_unchecked_mut(word_index) |= 1 << bit_index;
2,147,483,647✔
293
            } else {
294
                *bits.get_unchecked_mut(word_index) &= !(1 << bit_index);
168,149✔
295
            }
296
        }
297
    }
298

299
    /// Sets all bits to the given value.
300
    fn fill(&mut self, value: bool) {
24✔
301
        let full_words = self.len() / BITS;
48✔
302
        let residual = self.len() % BITS;
48✔
303
        let bits = self.as_mut();
72✔
304
        let word_value = if value { !0 } else { 0 };
72✔
305
        bits[..full_words].iter_mut().for_each(|x| *x = word_value);
135✔
306
        if residual != 0 {
39✔
307
            let mask = (1 << residual) - 1;
45✔
308
            bits[full_words] = (bits[full_words] & !mask) | (word_value & mask);
45✔
309
        }
310
    }
311

312
    /// Sets all bits to the given value using a parallel implementation.
313
    #[cfg(feature = "rayon")]
314
    fn par_fill(&mut self, value: bool) {
16✔
315
        let full_words = self.len() / BITS;
32✔
316
        let residual = self.len() % BITS;
32✔
317
        let bits = self.as_mut();
48✔
318
        let word_value = if value { !0 } else { 0 };
48✔
319
        bits[..full_words]
16✔
320
            .par_iter_mut()
321
            .with_min_len(RAYON_MIN_LEN)
16✔
322
            .for_each(|x| *x = word_value);
58✔
323
        if residual != 0 {
26✔
324
            let mask = (1 << residual) - 1;
30✔
325
            bits[full_words] = (bits[full_words] & !mask) | (word_value & mask);
30✔
326
        }
327
    }
328

329
    /// Sets all bits to zero.
NEW
330
    fn reset(&mut self) {
×
331
        self.fill(false);
×
332
    }
333

334
    /// Sets all bits to zero using a parallel implementation.
335
    #[cfg(feature = "rayon")]
NEW
336
    fn par_reset(&mut self) {
×
337
        self.par_fill(false);
×
338
    }
339

340
    /// Flip all bits.
341
    fn flip(&mut self) {
22✔
342
        let full_words = self.len() / BITS;
44✔
343
        let residual = self.len() % BITS;
44✔
344
        let bits = self.as_mut();
66✔
345
        bits[..full_words].iter_mut().for_each(|x| *x = !*x);
156,281,364✔
346
        if residual != 0 {
34✔
347
            let mask = (1 << residual) - 1;
36✔
348
            bits[full_words] = (bits[full_words] & !mask) | (!bits[full_words] & mask);
36✔
349
        }
350
    }
351

352
    /// Flip all bits using a parallel implementation.
353
    #[cfg(feature = "rayon")]
354
    fn par_flip(&mut self) {
16✔
355
        let full_words = self.len() / BITS;
32✔
356
        let residual = self.len() % BITS;
32✔
357
        let bits = self.as_mut();
48✔
358
        bits[..full_words]
16✔
359
            .par_iter_mut()
360
            .with_min_len(RAYON_MIN_LEN)
16✔
361
            .for_each(|x| *x = !*x);
58✔
362
        if residual != 0 {
26✔
363
            let mask = (1 << residual) - 1;
30✔
364
            bits[full_words] = (bits[full_words] & !mask) | (!bits[full_words] & mask);
30✔
365
        }
366
    }
367

368
    /// A parallel version of [`BitVec::count_ones`].
369
    #[cfg(feature = "rayon")]
NEW
370
    fn par_count_ones(&self) -> usize {
×
371
        let full_words = self.len() / BITS;
×
372
        let residual = self.len() % BITS;
×
NEW
373
        let bits = self.as_ref();
×
374
        let mut num_ones;
×
375
        num_ones = bits[..full_words]
×
376
            .par_iter()
×
377
            .with_min_len(RAYON_MIN_LEN)
×
378
            .map(|x| x.count_ones() as usize)
×
379
            .sum();
×
380
        if residual != 0 {
×
381
            num_ones += (self.as_ref()[full_words] << (BITS - residual)).count_ones() as usize
×
382
        }
383

384
        num_ones
×
385
    }
386
}
387

388
impl BitVec<Vec<usize>> {
389
    /// Creates a new bit vector of length `len` initialized to `false`.
390
    pub fn new(len: usize) -> Self {
104,572✔
391
        Self::with_value(len, false)
209,144✔
392
    }
393

394
    /// Creates a new bit vector of length `len` initialized to `value`.
395
    pub fn with_value(len: usize, value: bool) -> Self {
105,242✔
396
        let n_of_words = len.div_ceil(BITS);
315,726✔
397
        let extra_bits = (n_of_words * BITS) - len;
210,484✔
398
        let word_value = if value { !0 } else { 0 };
315,726✔
399
        let mut bits = vec![word_value; n_of_words];
420,968✔
400
        if extra_bits > 0 {
106,662✔
401
            let last_word_value = word_value >> extra_bits;
4,260✔
402
            bits[n_of_words - 1] = last_word_value;
1,420✔
403
        }
404
        Self { bits, len }
405
    }
406

407
    /// Creates a new zero-length bit vector of given capacity.
408
    ///
409
    /// Note that the capacity will be rounded up to a multiple of the word
410
    /// size.
411
    pub fn with_capacity(capacity: usize) -> Self {
50✔
412
        let n_of_words = capacity.div_ceil(BITS);
150✔
413
        Self {
414
            bits: Vec::with_capacity(n_of_words),
50✔
415
            len: 0,
416
        }
417
    }
418

419
    pub fn capacity(&self) -> usize {
80✔
420
        self.bits.capacity() * BITS
80✔
421
    }
422

423
    pub fn push(&mut self, b: bool) {
2,147,483,647✔
424
        if self.bits.len() * BITS == self.len {
2,147,483,647✔
425
            self.bits.push(0);
40,495,570✔
426
        }
427
        let word_index = self.len / BITS;
2,147,483,647✔
428
        let bit_index = self.len % BITS;
2,147,483,647✔
429
        // Clear bit
430
        self.bits[word_index] &= !(1 << bit_index);
2,147,483,647✔
431
        // Set bit
432
        self.bits[word_index] |= (b as usize) << bit_index;
2,147,483,647✔
433
        self.len += 1;
2,147,483,647✔
434
    }
435

436
    pub fn pop(&mut self) -> Option<bool> {
1,005✔
437
        if self.len == 0 {
1,005✔
438
            return None;
5✔
439
        }
440
        self.len -= 1;
×
441
        let word_index = self.len / BITS;
×
442
        let bit_index = self.len % BITS;
×
443
        Some((self.bits[word_index] >> bit_index) & 1 != 0)
×
444
    }
445

446
    pub fn resize(&mut self, new_len: usize, value: bool) {
10✔
447
        // TODO: rewrite by word
448
        if new_len > self.len {
10✔
449
            if new_len > self.bits.len() * BITS {
15✔
450
                self.bits.resize(new_len.div_ceil(BITS), 0);
15✔
451
            }
452
            for i in self.len..new_len {
510✔
453
                unsafe {
454
                    self.set_unchecked(i, value);
×
455
                }
456
            }
457
        }
458
        self.len = new_len;
10✔
459
    }
460
}
461

462
impl<B> BitLength for BitVec<B> {
463
    #[inline(always)]
464
    fn len(&self) -> usize {
2,147,483,647✔
465
        self.len
2,147,483,647✔
466
    }
467
}
468

469
impl<B: AsRef<[usize]>> BitCount for BitVec<B> {
470
    fn count_ones(&self) -> usize {
102,250✔
471
        let full_words = self.len() / BITS;
204,500✔
472
        let residual = self.len() % BITS;
204,500✔
473
        let bits = self.as_ref();
306,750✔
474
        let mut num_ones = bits[..full_words]
204,500✔
475
            .iter()
476
            .map(|x| x.count_ones() as usize)
706,962,990✔
477
            .sum();
478
        if residual != 0 {
102,250✔
479
            num_ones += (self.as_ref()[full_words] << (BITS - residual)).count_ones() as usize
183,176✔
480
        }
481
        num_ones
102,250✔
482
    }
483
}
484

485
impl<B: AsRef<[usize]>> Index<usize> for BitVec<B> {
486
    type Output = bool;
487

488
    fn index(&self, index: usize) -> &Self::Output {
325,879,792✔
489
        match self.get(index) {
651,759,584✔
490
            false => &false,
172,742,035✔
491
            true => &true,
153,137,757✔
492
        }
493
    }
494
}
495

496
impl Extend<bool> for BitVec<Vec<usize>> {
497
    fn extend<T>(&mut self, i: T)
20,582✔
498
    where
499
        T: IntoIterator<Item = bool>,
500
    {
501
        for b in i {
1,035,509,862✔
502
            self.push(b);
×
503
        }
504
    }
505
}
506

507
impl FromIterator<bool> for BitVec<Vec<usize>> {
508
    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
20,582✔
509
        let mut res = Self::new(0);
41,164✔
510
        res.extend(iter);
61,746✔
511
        res
20,582✔
512
    }
513
}
514

515
impl<B: AsRef<[usize]>> RankHinted<64> for BitVec<B> {
516
    #[inline(always)]
517
    unsafe fn rank_hinted(&self, pos: usize, hint_pos: usize, hint_rank: usize) -> usize {
9✔
518
        let bits = self.as_ref();
27✔
519
        let mut rank = hint_rank;
18✔
520
        let mut hint_pos = hint_pos;
18✔
521

522
        debug_assert!(
9✔
523
            hint_pos < bits.len(),
18✔
524
            "hint_pos: {}, len: {}",
×
525
            hint_pos,
×
526
            bits.len()
×
527
        );
528

529
        while (hint_pos + 1) * 64 <= pos {
9✔
530
            rank += unsafe { bits.get_unchecked(hint_pos).count_ones() } as usize;
×
531
            hint_pos += 1;
×
532
        }
533

534
        rank + (unsafe { bits.get_unchecked(hint_pos) } & ((1 << (pos % 64)) - 1)).count_ones()
36✔
535
            as usize
9✔
536
    }
537
}
538

539
impl<B: AsRef<[usize]>> SelectHinted for BitVec<B> {
540
    unsafe fn select_hinted(&self, rank: usize, hint_pos: usize, hint_rank: usize) -> usize {
2,147,483,647✔
541
        let mut word_index = hint_pos / BITS;
2,147,483,647✔
542
        let bit_index = hint_pos % BITS;
2,147,483,647✔
543
        let mut residual = rank - hint_rank;
2,147,483,647✔
544
        let mut word =
2,147,483,647✔
545
            (unsafe { self.as_ref().get_unchecked(word_index) } >> bit_index) << bit_index;
2,147,483,647✔
546
        loop {
×
547
            let bit_count = word.count_ones() as usize;
2,147,483,647✔
548
            if residual < bit_count {
2,147,483,647✔
549
                return word_index * BITS + word.select_in_word(residual);
2,147,483,647✔
550
            }
551
            word_index += 1;
×
552
            word = *unsafe { self.as_ref().get_unchecked(word_index) };
×
553
            residual -= bit_count;
×
554
        }
555
    }
556
}
557

558
impl<B: AsRef<[usize]>> SelectZeroHinted for BitVec<B> {
559
    unsafe fn select_zero_hinted(&self, rank: usize, hint_pos: usize, hint_rank: usize) -> usize {
2,147,483,647✔
560
        let mut word_index = hint_pos / BITS;
2,147,483,647✔
561
        let bit_index = hint_pos % BITS;
2,147,483,647✔
562
        let mut residual = rank - hint_rank;
2,147,483,647✔
563
        let mut word =
2,147,483,647✔
564
            (!*unsafe { self.as_ref().get_unchecked(word_index) } >> bit_index) << bit_index;
2,147,483,647✔
565
        loop {
×
566
            let bit_count = word.count_ones() as usize;
2,147,483,647✔
567
            if residual < bit_count {
2,147,483,647✔
568
                return word_index * BITS + word.select_in_word(residual);
2,147,483,647✔
569
            }
570
            word_index += 1;
×
571
            word = unsafe { !self.as_ref().get_unchecked(word_index) };
×
572
            residual -= bit_count;
×
573
        }
574
    }
575
}
576

577
impl<B: AsRef<[usize]>, C: AsRef<[usize]>> PartialEq<BitVec<C>> for BitVec<B> {
578
    fn eq(&self, other: &BitVec<C>) -> bool {
70✔
579
        let len = self.len();
210✔
580
        if len != other.len() {
140✔
581
            return false;
1✔
582
        }
583

584
        let full_words = len / BITS;
×
585
        if self.as_ref()[..full_words] != other.as_ref()[..full_words] {
×
586
            return false;
×
587
        }
588

589
        let residual = len % BITS;
×
590

591
        residual == 0
×
592
            || (self.as_ref()[full_words] ^ other.as_ref()[full_words]) << (BITS - residual) == 0
67✔
593
    }
594
}
595

596
impl Eq for BitVec<Vec<usize>> {}
597

598
impl<B: AsRef<[usize]>> fmt::Display for BitVec<B> {
599
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
×
600
        write!(f, "[")?;
×
601
        for b in self {
×
602
            write!(f, "{:b}", b as usize)?;
×
603
        }
604
        write!(f, "]")?;
×
605
        Ok(())
×
606
    }
607
}
608

609
// An iterator over the bits of the bit vector as booleans.
610
#[derive(Debug, Clone, MemDbg, MemSize)]
611
pub struct BitIterator<'a, B: ?Sized> {
612
    bits: &'a B,
613
    len: usize,
614
    next_bit_pos: usize,
615
}
616

617
impl<'a, B: AsRef<[usize]>> IntoIterator for &'a BitVec<B> {
618
    type IntoIter = BitIterator<'a, B>;
619
    type Item = bool;
620

621
    fn into_iter(self) -> Self::IntoIter {
6,794✔
622
        BitIterator {
623
            bits: &self.bits,
6,794✔
624
            len: self.len,
6,794✔
625
            next_bit_pos: 0,
626
        }
627
    }
628
}
629

630
impl<B: ?Sized + AsRef<[usize]>> Iterator for BitIterator<'_, B> {
631
    type Item = bool;
632
    fn next(&mut self) -> Option<bool> {
110,751,792✔
633
        if self.next_bit_pos == self.len {
110,751,792✔
634
            return None;
6,799✔
635
        }
636
        let word_idx = self.next_bit_pos / BITS;
×
637
        let bit_idx = self.next_bit_pos % BITS;
×
638
        let word = unsafe { *self.bits.as_ref().get_unchecked(word_idx) };
×
639
        let bit = (word >> bit_idx) & 1;
×
640
        self.next_bit_pos += 1;
×
641
        Some(bit != 0)
×
642
    }
643
}
644

645
/// An iterator over the positions of the ones in a bit vector.
646
#[derive(Debug, Clone, MemDbg, MemSize)]
647
pub struct OnesIterator<'a, B: ?Sized> {
648
    bits: &'a B,
649
    len: usize,
650
    word_idx: usize,
651
    /// This is a usize because BitVec is currently implemented only for `Vec<usize>` and `&[usize]`.
652
    word: usize,
653
}
654

655
impl<'a, B: ?Sized + AsRef<[usize]>> OnesIterator<'a, B> {
656
    pub fn new(bits: &'a B, len: usize) -> Self {
5✔
657
        let word = if bits.as_ref().is_empty() {
15✔
658
            0
×
659
        } else {
660
            unsafe { *bits.as_ref().get_unchecked(0) }
5✔
661
        };
662
        Self {
663
            bits,
664
            len,
665
            word_idx: 0,
666
            word,
667
        }
668
    }
669
}
670

671
impl<B: ?Sized + AsRef<[usize]>> Iterator for OnesIterator<'_, B> {
672
    type Item = usize;
673

674
    fn next(&mut self) -> Option<Self::Item> {
106✔
675
        // find the next word with ones
676
        while self.word == 0 {
115✔
677
            self.word_idx += 1;
13✔
678
            if self.word_idx == self.bits.as_ref().len() {
26✔
679
                return None;
4✔
680
            }
681
            self.word = unsafe { *self.bits.as_ref().get_unchecked(self.word_idx) };
×
682
        }
683
        // find the lowest bit set index in the word
684
        let bit_idx = self.word.trailing_zeros() as usize;
102✔
685
        // compute the global bit index
686
        let res = (self.word_idx * BITS) + bit_idx;
×
687
        if res >= self.len {
×
688
            None
1✔
689
        } else {
690
            // clear the lowest bit set
691
            self.word &= self.word - 1;
101✔
692
            Some(res)
×
693
        }
694
    }
695
}
696

697
/// An iterator over the positions of the zeros in a bit vector.
698
#[derive(Debug, Clone, MemDbg, MemSize)]
699
pub struct ZerosIterator<'a, B: ?Sized> {
700
    bits: &'a B,
701
    len: usize,
702
    word_idx: usize,
703
    /// This is a usize because BitVec is currently implemented only for `Vec<usize>` and `&[usize]`.
704
    word: usize,
705
}
706

707
impl<'a, B: ?Sized + AsRef<[usize]>> ZerosIterator<'a, B> {
708
    pub fn new(bits: &'a B, len: usize) -> Self {
5✔
709
        let word = if bits.as_ref().is_empty() {
15✔
710
            0
×
711
        } else {
712
            unsafe { !*bits.as_ref().get_unchecked(0) }
5✔
713
        };
714
        Self {
715
            bits,
716
            len,
717
            word_idx: 0,
718
            word,
719
        }
720
    }
721
}
722

723
impl<B: ?Sized + AsRef<[usize]>> Iterator for ZerosIterator<'_, B> {
724
    type Item = usize;
725

726
    fn next(&mut self) -> Option<Self::Item> {
106✔
727
        // find the next flipped word with zeros
728
        while self.word == 0 {
115✔
729
            self.word_idx += 1;
10✔
730
            if self.word_idx == self.bits.as_ref().len() {
20✔
731
                return None;
1✔
732
            }
733
            self.word = unsafe { !*self.bits.as_ref().get_unchecked(self.word_idx) };
×
734
        }
735
        // find the lowest zero bit index in the word
736
        let bit_idx = self.word.trailing_zeros() as usize;
105✔
737
        // compute the global bit index
738
        let res = (self.word_idx * BITS) + bit_idx;
×
739
        if res >= self.len {
×
740
            None
4✔
741
        } else {
742
            // clear the lowest bit set
743
            self.word &= self.word - 1;
101✔
744
            Some(res)
×
745
        }
746
    }
747
}
748

749
#[derive(Debug, Clone, MemDbg, MemSize)]
750
/// A thread-safe bit vector.
751
pub struct AtomicBitVec<B = Vec<AtomicUsize>> {
752
    bits: B,
753
    len: usize,
754
}
755

756
impl<B> AtomicBitVec<B> {
757
    /// Returns the number of bits in the bit vector.
758
    ///
759
    /// This method is equivalent to [`BitLength::len`], but it is provided to
760
    /// reduce ambiguity in method resolution.
761
    #[inline(always)]
762
    pub fn len(&self) -> usize {
6✔
763
        BitLength::len(self)
12✔
764
    }
765

766
    /// # Safety
767
    /// `len` must be between 0 (included) the number of
768
    /// bits in `bits` (included).
769
    #[inline(always)]
770
    pub unsafe fn from_raw_parts(bits: B, len: usize) -> Self {
3✔
771
        Self { bits, len }
772
    }
773
    #[inline(always)]
774
    pub fn into_raw_parts(self) -> (B, usize) {
1✔
775
        (self.bits, self.len)
1✔
776
    }
777
}
778

779
impl<T: ?Sized + AsRef<[AtomicUsize]> + BitLength> AtomicBitVecOps for T {}
780

781
pub trait AtomicBitVecOps: AsRef<[AtomicUsize]> + BitLength {
782
    fn get(&self, index: usize, ordering: Ordering) -> bool {
64,368✔
783
        panic_if_out_of_bounds!(index, self.len());
128,736✔
784
        unsafe { self.get_unchecked(index, ordering) }
64,368✔
785
    }
786

787
    fn set(&self, index: usize, value: bool, ordering: Ordering) {
21,550✔
788
        panic_if_out_of_bounds!(index, self.len());
43,100✔
789
        unsafe { self.set_unchecked(index, value, ordering) }
21,550✔
790
    }
791

792
    fn swap(&self, index: usize, value: bool, ordering: Ordering) -> bool {
3✔
793
        panic_if_out_of_bounds!(index, self.len());
6✔
794
        unsafe { self.swap_unchecked(index, value, ordering) }
3✔
795
    }
796

797
    /// # Safety
798
    ///
799
    /// `index` must be between 0 (included) and [`BitVec::len`] (excluded).
800
    #[inline]
801
    unsafe fn get_unchecked(&self, index: usize, ordering: Ordering) -> bool {
64,368✔
802
        let word_index = index / BITS;
128,736✔
803
        let bits = self.as_ref();
193,104✔
804
        let word = unsafe { bits.get_unchecked(word_index).load(ordering) };
321,840✔
805
        (word >> (index % BITS)) & 1 != 0
64,368✔
806
    }
807

808
    /// # Safety
809
    ///
810
    /// `index` must be between 0 (included) and [`BitVec::len`] (excluded).
811
    #[inline]
812
    unsafe fn set_unchecked(&self, index: usize, value: bool, ordering: Ordering) {
21,550✔
813
        let word_index = index / BITS;
43,100✔
814
        let bit_index = index % BITS;
43,100✔
815
        let bits = self.as_ref();
64,650✔
816

817
        // For constant values, this should be inlined with no test.
818
        unsafe {
819
            if value {
37,850✔
820
                bits.get_unchecked(word_index)
48,900✔
821
                    .fetch_or(1 << bit_index, ordering);
32,600✔
822
            } else {
823
                bits.get_unchecked(word_index)
5,250✔
824
                    .fetch_and(!(1 << bit_index), ordering);
5,250✔
825
            }
826
        }
827
    }
828

829
    /// # Safety
830
    ///
831
    /// `index` must be between 0 (included) and [`BitVec::len`] (excluded).
832
    #[inline]
833
    unsafe fn swap_unchecked(&self, index: usize, value: bool, ordering: Ordering) -> bool {
3✔
834
        let word_index = index / BITS;
6✔
835
        let bit_index = index % BITS;
6✔
836
        let bits = self.as_ref();
9✔
837

838
        let old_word = unsafe {
839
            if value {
3✔
840
                bits.get_unchecked(word_index)
4✔
841
                    .fetch_or(1 << bit_index, ordering)
6✔
842
            } else {
843
                bits.get_unchecked(word_index)
1✔
844
                    .fetch_and(!(1 << bit_index), ordering)
×
845
            }
846
        };
847

848
        (old_word >> (bit_index)) & 1 != 0
3✔
849
    }
850

851
    /// Sets all bits to the given value.
852
    fn fill(&mut self, value: bool, ordering: Ordering) {
24✔
853
        let full_words = self.len() / BITS;
48✔
854
        let residual = self.len() % BITS;
48✔
855
        let bits = self.as_ref();
72✔
856
        let word_value = if value { !0 } else { 0 };
72✔
857
        // Just to be sure, add a fence to ensure that we will see all the final
858
        // values
859
        core::sync::atomic::fence(Ordering::SeqCst);
48✔
860
        bits[..full_words]
24✔
861
            .iter()
862
            .for_each(|x| x.store(word_value, ordering));
276✔
863
        if residual != 0 {
39✔
864
            let mask = (1 << residual) - 1;
45✔
865
            bits[full_words].store(
45✔
866
                (bits[full_words].load(ordering) & !mask) | (word_value & mask),
60✔
867
                ordering,
15✔
868
            );
869
        }
870
    }
871

872
    /// Sets all bits to the given value using a parallel implementation.
873
    #[cfg(feature = "rayon")]
874
    fn par_fill(&mut self, value: bool, ordering: Ordering) {
16✔
875
        let full_words = self.len() / BITS;
32✔
876
        let residual = self.len() % BITS;
32✔
877
        let bits = self.as_ref();
48✔
878
        let word_value = if value { !0 } else { 0 };
48✔
879

880
        // Just to be sure, add a fence to ensure that we will see all the final
881
        // values
882
        core::sync::atomic::fence(Ordering::SeqCst);
32✔
883
        bits[..full_words]
16✔
884
            .par_iter()
885
            .with_min_len(RAYON_MIN_LEN)
16✔
886
            .for_each(|x| x.store(word_value, ordering));
184✔
887
        if residual != 0 {
26✔
888
            let mask = (1 << residual) - 1;
30✔
889
            bits[full_words].store(
30✔
890
                (bits[full_words].load(ordering) & !mask) | (word_value & mask),
40✔
891
                ordering,
10✔
892
            );
893
        }
894
    }
895

896
    /// Sets all bits to zero.
NEW
897
    fn reset(&mut self, ordering: Ordering) {
×
898
        self.fill(false, ordering);
×
899
    }
900

901
    /// Sets all bits to zero using a parallel implementation.
902
    #[cfg(feature = "rayon")]
NEW
903
    fn par_reset(&mut self, ordering: Ordering) {
×
904
        self.par_fill(false, ordering);
×
905
    }
906

907
    /// Flip all bits.
908
    fn flip(&mut self, ordering: Ordering) {
16✔
909
        let full_words = self.len() / BITS;
32✔
910
        let residual = self.len() % BITS;
32✔
911
        let bits = self.as_ref();
48✔
912
        // Just to be sure, add a fence to ensure that we will see all the final
913
        // values
914
        core::sync::atomic::fence(Ordering::SeqCst);
32✔
915
        bits[..full_words]
16✔
916
            .iter()
917
            .for_each(|x| _ = x.fetch_xor(!0, ordering));
142✔
918
        if residual != 0 {
26✔
919
            let mask = (1 << residual) - 1;
30✔
920
            let last_word = bits[full_words].load(ordering);
50✔
921
            bits[full_words].store((last_word & !mask) | (!last_word & mask), ordering);
40✔
922
        }
923
    }
924

925
    /// Flip all bits using a parallel implementation.
926
    #[cfg(feature = "rayon")]
927
    fn par_flip(&mut self, ordering: Ordering) {
16✔
928
        let full_words = self.len() / BITS;
32✔
929
        let residual = self.len() % BITS;
32✔
930
        let bits = self.as_ref();
48✔
931
        // Just to be sure, add a fence to ensure that we will see all the final
932
        // values
933
        core::sync::atomic::fence(Ordering::SeqCst);
32✔
934
        bits[..full_words]
16✔
935
            .par_iter()
936
            .with_min_len(RAYON_MIN_LEN)
16✔
937
            .for_each(|x| _ = x.fetch_xor(!0, ordering));
142✔
938
        if residual != 0 {
26✔
939
            let mask = (1 << residual) - 1;
30✔
940
            let last_word = bits[full_words].load(ordering);
50✔
941
            bits[full_words].store((last_word & !mask) | (!last_word & mask), ordering);
40✔
942
        }
943
    }
944

945
    /// A parallel version of [`BitVec::count_ones`].
946
    #[cfg(feature = "rayon")]
NEW
947
    fn par_count_ones(&self) -> usize {
×
948
        let full_words = self.len() / BITS;
×
949
        let residual = self.len() % BITS;
×
NEW
950
        let bits = self.as_ref();
×
951
        let mut num_ones;
×
952
        // Just to be sure, add a fence to ensure that we will see all the final
953
        // values
954
        core::sync::atomic::fence(Ordering::SeqCst);
×
955
        num_ones = bits[..full_words]
×
956
            .par_iter()
×
957
            .with_min_len(RAYON_MIN_LEN)
×
958
            .map(|x| x.load(Ordering::Relaxed).count_ones() as usize)
×
959
            .sum();
×
960
        if residual != 0 {
×
961
            num_ones += (bits[full_words].load(Ordering::Relaxed) << (BITS - residual)).count_ones()
×
962
                as usize
×
963
        }
964
        num_ones
×
965
    }
966
}
967

968
impl AtomicBitVec<Vec<AtomicUsize>> {
969
    /// Creates a new atomic bit vector of length `len` initialized to `false`.
970
    pub fn new(len: usize) -> Self {
115✔
971
        Self::with_value(len, false)
230✔
972
    }
973

974
    /// Creates a new atomic bit vector of length `len` initialized to `value`.
975
    pub fn with_value(len: usize, value: bool) -> Self {
120✔
976
        let n_of_words = len.div_ceil(BITS);
360✔
977
        let extra_bits = (n_of_words * BITS) - len;
240✔
978
        let word_value = if value { !0 } else { 0 };
360✔
979
        let mut bits = (0..n_of_words)
240✔
980
            .map(|_| AtomicUsize::new(word_value))
1,260✔
981
            .collect::<Vec<_>>();
982
        if extra_bits > 0 {
210✔
983
            let last_word_value = word_value >> extra_bits;
270✔
984
            bits[n_of_words - 1] = AtomicUsize::new(last_word_value);
180✔
985
        }
986
        Self { bits, len }
987
    }
988
}
989

990
impl<B> BitLength for AtomicBitVec<B> {
991
    #[inline(always)]
992
    fn len(&self) -> usize {
86,071✔
993
        self.len
86,071✔
994
    }
995
}
996

997
impl<B: AsRef<[AtomicUsize]>> Index<usize> for AtomicBitVec<B> {
998
    type Output = bool;
999

1000
    /// Shorthand for [`Self::get`] using [`Ordering::Relaxed`].
1001
    fn index(&self, index: usize) -> &Self::Output {
10,000✔
1002
        match self.get(index, Ordering::Relaxed) {
30,000✔
1003
            false => &false,
9,500✔
1004
            true => &true,
500✔
1005
        }
1006
    }
1007
}
1008

1009
impl<B: AsRef<[AtomicUsize]>> BitCount for AtomicBitVec<B> {
1010
    fn count_ones(&self) -> usize {
3✔
1011
        let full_words = self.len() / BITS;
6✔
1012
        let residual = self.len() % BITS;
6✔
1013
        let bits = self.as_ref();
9✔
1014
        let mut num_ones;
×
1015
        // Just to be sure, add a fence to ensure that we will see all the final
1016
        // values
1017
        core::sync::atomic::fence(Ordering::SeqCst);
6✔
1018
        num_ones = bits[..full_words]
3✔
1019
            .iter()
3✔
1020
            .map(|x| x.load(Ordering::Relaxed).count_ones() as usize)
63✔
1021
            .sum();
3✔
1022
        if residual != 0 {
3✔
1023
            num_ones += (bits[full_words].load(Ordering::Relaxed) << (BITS - residual)).count_ones()
6✔
1024
                as usize
2✔
1025
        }
1026
        num_ones
3✔
1027
    }
1028
}
1029

1030
// Conversions
1031

1032
impl<W: IntoAtomic> From<BitVec<Vec<W>>> for AtomicBitVec<Vec<W::AtomicType>> {
1033
    fn from(value: BitVec<Vec<W>>) -> Self {
2✔
1034
        AtomicBitVec {
1035
            bits: transmute_vec_into_atomic(value.bits),
4✔
1036
            len: value.len,
2✔
1037
        }
1038
    }
1039
}
1040

1041
impl<'a, W: IntoAtomic> TryFrom<BitVec<&'a [W]>> for AtomicBitVec<&'a [W::AtomicType]> {
1042
    type Error = CannotCastToAtomicError<W>;
1043
    fn try_from(value: BitVec<&'a [W]>) -> Result<Self, Self::Error> {
1✔
1044
        if core::mem::align_of::<W>() != core::mem::align_of::<W::AtomicType>() {
1✔
1045
            return Err(CannotCastToAtomicError::default());
×
1046
        }
1047
        Ok(AtomicBitVec {
×
1048
            bits: unsafe { core::mem::transmute::<&'a [W], &'a [W::AtomicType]>(value.bits) },
×
1049
            len: value.len,
×
1050
        })
1051
    }
1052
}
1053

1054
impl<'a, W: IntoAtomic> TryFrom<BitVec<&'a mut [W]>> for AtomicBitVec<&'a mut [W::AtomicType]> {
1055
    type Error = CannotCastToAtomicError<W>;
1056
    fn try_from(value: BitVec<&'a mut [W]>) -> Result<Self, Self::Error> {
1✔
1057
        if core::mem::align_of::<W>() != core::mem::align_of::<W::AtomicType>() {
1✔
1058
            return Err(CannotCastToAtomicError::default());
×
1059
        }
1060
        Ok(AtomicBitVec {
×
1061
            bits: unsafe {
×
1062
                core::mem::transmute::<&'a mut [W], &'a mut [W::AtomicType]>(value.bits)
×
1063
            },
1064
            len: value.len,
×
1065
        })
1066
    }
1067
}
1068

1069
impl<W: IntoAtomic> From<AtomicBitVec<Vec<W::AtomicType>>> for BitVec<Vec<W>> {
1070
    fn from(value: AtomicBitVec<Vec<W::AtomicType>>) -> Self {
30✔
1071
        BitVec {
1072
            bits: transmute_vec_from_atomic::<W::AtomicType>(value.bits),
60✔
1073
            len: value.len,
30✔
1074
        }
1075
    }
1076
}
1077

1078
impl<W: IntoAtomic> From<AtomicBitVec<Box<[W::AtomicType]>>> for BitVec<Box<[W]>> {
1079
    fn from(value: AtomicBitVec<Box<[W::AtomicType]>>) -> Self {
1✔
1080
        BitVec {
1081
            bits: transmute_boxed_slice_from_atomic::<W::AtomicType>(value.bits),
2✔
1082
            len: value.len,
1✔
1083
        }
1084
    }
1085
}
1086

1087
impl<W: IntoAtomic + Copy> From<BitVec<Box<[W]>>> for AtomicBitVec<Box<[W::AtomicType]>> {
1088
    fn from(value: BitVec<Box<[W]>>) -> Self {
1✔
1089
        AtomicBitVec {
1090
            bits: transmute_boxed_slice_into_atomic::<W>(value.bits),
2✔
1091
            len: value.len,
1✔
1092
        }
1093
    }
1094
}
1095

1096
impl<'a, W: IntoAtomic> From<AtomicBitVec<&'a [W::AtomicType]>> for BitVec<&'a [W]> {
1097
    fn from(value: AtomicBitVec<&'a [W::AtomicType]>) -> Self {
1✔
1098
        BitVec {
1099
            bits: unsafe { core::mem::transmute::<&'a [W::AtomicType], &'a [W]>(value.bits) },
1✔
1100
            len: value.len,
1✔
1101
        }
1102
    }
1103
}
1104

1105
impl<'a, W: IntoAtomic> From<AtomicBitVec<&'a mut [W::AtomicType]>> for BitVec<&'a mut [W]> {
1106
    fn from(value: AtomicBitVec<&'a mut [W::AtomicType]>) -> Self {
1✔
1107
        BitVec {
1108
            bits: unsafe {
1✔
1109
                core::mem::transmute::<&'a mut [W::AtomicType], &'a mut [W]>(value.bits)
1110
            },
1111
            len: value.len,
1✔
1112
        }
1113
    }
1114
}
1115

1116
impl<W> From<BitVec<Vec<W>>> for BitVec<Box<[W]>> {
1117
    fn from(value: BitVec<Vec<W>>) -> Self {
146✔
1118
        BitVec {
1119
            bits: value.bits.into_boxed_slice(),
292✔
1120
            len: value.len,
146✔
1121
        }
1122
    }
1123
}
1124

1125
impl<W> From<BitVec<Box<[W]>>> for BitVec<Vec<W>> {
1126
    fn from(value: BitVec<Box<[W]>>) -> Self {
1✔
1127
        BitVec {
1128
            bits: value.bits.into_vec(),
2✔
1129
            len: value.len,
1✔
1130
        }
1131
    }
1132
}
1133

1134
impl<W, B: AsRef<[W]>> AsRef<[W]> for BitVec<B> {
1135
    #[inline(always)]
1136
    fn as_ref(&self) -> &[W] {
2,147,483,647✔
1137
        self.bits.as_ref()
2,147,483,647✔
1138
    }
1139
}
1140

1141
impl<W, B: AsMut<[W]>> AsMut<[W]> for BitVec<B> {
1142
    #[inline(always)]
1143
    fn as_mut(&mut self) -> &mut [W] {
2,147,483,647✔
1144
        self.bits.as_mut()
2,147,483,647✔
1145
    }
1146
}
1147

1148
impl<W, B: AsRef<[W]>> AsRef<[W]> for AtomicBitVec<B> {
1149
    #[inline(always)]
1150
    fn as_ref(&self) -> &[W] {
85,996✔
1151
        self.bits.as_ref()
85,996✔
1152
    }
1153
}
1154
// An iterator over the bits of this atomic bit vector as booleans.
1155
#[derive(Debug, MemDbg, MemSize)]
1156
pub struct AtomicBitIterator<'a, B> {
1157
    bits: &'a mut B,
1158
    len: usize,
1159
    next_bit_pos: usize,
1160
}
1161

1162
// We implement [`IntoIterator`] for a mutable reference so no
1163
// outstanding references are allowed while iterating.
1164
impl<'a, B: AsRef<[AtomicUsize]>> IntoIterator for &'a mut AtomicBitVec<B> {
1165
    type IntoIter = AtomicBitIterator<'a, B>;
1166
    type Item = bool;
1167

1168
    fn into_iter(self) -> Self::IntoIter {
1✔
1169
        AtomicBitIterator {
1170
            bits: &mut self.bits,
1✔
1171
            len: self.len,
1✔
1172
            next_bit_pos: 0,
1173
        }
1174
    }
1175
}
1176

1177
impl<B: AsRef<[AtomicUsize]>> Iterator for AtomicBitIterator<'_, B> {
1178
    type Item = bool;
1179
    fn next(&mut self) -> Option<bool> {
101✔
1180
        if self.next_bit_pos == self.len {
101✔
1181
            return None;
1✔
1182
        }
1183
        let word_idx = self.next_bit_pos / BITS;
×
1184
        let bit_idx = self.next_bit_pos % BITS;
×
1185
        let word = unsafe {
1186
            self.bits
×
1187
                .as_ref()
1188
                .get_unchecked(word_idx)
×
1189
                .load(Ordering::Relaxed)
×
1190
        };
1191
        let bit = (word >> bit_idx) & 1;
×
1192
        self.next_bit_pos += 1;
×
1193
        Some(bit != 0)
×
1194
    }
1195
}
1196

1197
impl<B: AsRef<[AtomicUsize]>> AtomicBitVec<B> {
1198
    // Returns an iterator over the bits of the bit vector.
1199
    //
1200
    // Note that this method takes a mutable reference to the bit vector,
1201
    // so no outstanding references are allowed while iterating.
1202
    #[inline(always)]
1203
    pub fn iter(&mut self) -> AtomicBitIterator<'_, B> {
1✔
1204
        self.into_iter()
2✔
1205
    }
1206
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc