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

vigna / sux-rs / 24281101826

11 Apr 2026 11:03AM UTC coverage: 71.146% (+0.1%) from 71.047%
24281101826

push

github

vigna
Completed inline link removal

7200 of 10120 relevant lines covered (71.15%)

17328249.11 hits per line

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

83.96
/src/traits/bit_vec_ops.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
//! Operations on bit vectors.
9
//!
10
//! `sux` does not provide a dedicated trait for bit vectors (whereas it
11
//! provides a trait for [bit-field slices]).
12
//! Rather, it considers anything that is `AsRef<[W]>` (where `W` implements
13
//! [`Word`]) and implements [`BitLength`] as a bit vector.
14
//!
15
//! This approach was chosen for efficiency reasons—all methods are implemented
16
//! as efficiently as possible for a concrete representation. Other crates opt
17
//! for a general trait representing a bit vector, but in our experiments the
18
//! resulting code was not as efficient as the code we obtain.
19
//!
20
//! The Rust type system makes the approach quite flexible. We cannot, however,
21
//! accommodate implicit representation of bit vectors (e.g., compressed or
22
//! algorithmic). This is in fact in line with Rust's philosophy—the
23
//! [`Index`] trait returns a reference, which forces an
24
//! explicit representation of sequences (an alternative approach is provided by
25
//! the [`value-traits`] crate, which is used by bit-field slices).
26
//!
27
//! All traits provided in this module are extension traits. They have no
28
//! unimplemented methods: just pulling them into scope will provide anything
29
//! that is `AsRef<[W]>` and implements [`BitLength`] with the operations of
30
//! a bit vector.
31
//!
32
//! Iteration on the bits of the vector, or on the positions of the ones or of the
33
//! zeros, is provided by means of structures that can be reused.
34
//!
35
//! The reference implementations using these traits are
36
//! [`BitVec`] and [`AtomicBitVec`].
37
//!
38
//! [`value-traits`]: https://crates.io/crates/value-traits
39
//! [bit-field slices]: crate::traits::bit_field_slice
40
//! [`BitVec`]: crate::bits::BitVec
41
//! [`AtomicBitVec`]: crate::bits::AtomicBitVec
42
//! [`Index`]: std::ops::Index
43

44
use crate::traits::Word;
45
use ambassador::delegatable_trait;
46
use atomic_primitive::PrimitiveAtomicUnsigned;
47
use impl_tools::autoimpl;
48
use mem_dbg::{MemDbg, MemSize};
49
use num_primitive::PrimitiveInteger;
50
#[cfg(feature = "rayon")]
51
use rayon::prelude::*;
52
use std::{iter::FusedIterator, marker::PhantomData, sync::atomic::Ordering};
53

54
macro_rules! panic_if_out_of_bounds {
55
    ($index: expr, $len: expr) => {
56
        if $index >= $len {
57
            panic!("Bit index out of bounds: {} >= {}", $index, $len)
58
        }
59
    };
60
}
61

62
/// A trait expressing a length in bits.
63
///
64
/// This trait is typically used in conjunction with
65
/// [`AsRef<[W]>`](core::convert::AsRef) to provide word-based access to a bit
66
/// vector on words of type `W`.
67
#[autoimpl(for<T: trait + ?Sized> &T, &mut T, Box<T>)]
68
#[delegatable_trait]
69
pub trait BitLength {
70
    /// Returns a length in bits.
71
    fn len(&self) -> usize;
72
}
73

74
impl<W: Word, T: ?Sized + AsRef<[W]> + BitLength> BitVecOps<W> for T {}
75

76
/// Read-only operations on bit vectors.
77
pub trait BitVecOps<W: Word>: AsRef<[W]> + BitLength {
78
    /// Returns true if the bit of given index is set.
79
    #[inline]
80
    fn get(&self, index: usize) -> bool {
486,950,385✔
81
        panic_if_out_of_bounds!(index, self.len());
973,900,770✔
82
        unsafe { self.get_unchecked(index) }
1,460,851,155✔
83
    }
84

85
    /// Returns true if the bit of given index is set, without
86
    /// bound checks.
87
    ///
88
    /// # Safety
89
    ///
90
    /// `index` must be between 0 (included) and [`BitLength::len`] (excluded).
91
    #[inline(always)]
92
    unsafe fn get_unchecked(&self, index: usize) -> bool {
486,952,625✔
93
        let bits_per_word = W::BITS as usize;
973,905,250✔
94
        let word_index = index / bits_per_word;
973,905,250✔
95
        let word = unsafe { *self.as_ref().get_unchecked(word_index) };
1,460,857,875✔
96
        (word >> (index % bits_per_word)) & W::ONE != W::ZERO
973,905,250✔
97
    }
98

99
    /// Returns an iterator over the bits of this bit vector as booleans.
100
    #[inline(always)]
101
    fn iter(&self) -> BitIter<'_, W, [W]> {
14,467✔
102
        BitIter::new(self.as_ref(), self.len())
57,868✔
103
    }
104

105
    /// Returns an iterator over the positions of the ones in this bit vector.
106
    fn iter_ones(&self) -> OnesIter<'_, W, [W]> {
30✔
107
        OnesIter::new(self.as_ref(), self.len())
120✔
108
    }
109

110
    /// Returns an iterator over the positions of the zeros in this bit vector.
111
    fn iter_zeros(&self) -> ZerosIter<'_, W, [W]> {
30✔
112
        ZerosIter::new(self.as_ref(), self.len())
120✔
113
    }
114

115
    /// A parallel version of [`BitCount::count_ones`].
116
    ///
117
    /// [`BitCount::count_ones`]: crate::traits::BitCount::count_ones
118
    #[cfg(feature = "rayon")]
119
    fn par_count_ones(&self) -> usize {
×
120
        let bits_per_word = W::BITS as usize;
×
121
        let full_words = self.len() / bits_per_word;
×
122
        let residual = self.len() % bits_per_word;
×
123
        let bits = self.as_ref();
×
124
        let mut num_ones;
×
125
        num_ones = bits[..full_words]
×
126
            .par_iter()
×
127
            .with_min_len(crate::RAYON_MIN_LEN)
×
128
            .map(|x| x.count_ones() as usize)
×
129
            .sum();
×
130
        if residual != 0 {
×
131
            num_ones +=
×
132
                (self.as_ref()[full_words] << (bits_per_word - residual)).count_ones() as usize
×
133
        }
134

135
        num_ones
×
136
    }
137
}
138

139
impl<W: Word, T: AsRef<[W]> + AsMut<[W]> + BitLength> BitVecOpsMut<W> for T {}
140

141
/// Mutation operations on bit vectors.
142
pub trait BitVecOpsMut<W: Word>: AsRef<[W]> + AsMut<[W]> + BitLength {
143
    /// Sets the bit of given index to the given value.
144
    #[inline]
145
    fn set(&mut self, index: usize, value: bool) {
50,249,476✔
146
        panic_if_out_of_bounds!(index, self.len());
100,498,952✔
147
        unsafe { self.set_unchecked(index, value) }
200,997,904✔
148
    }
149

150
    /// Sets the bit of given index to the given value without bound checks.
151
    ///
152
    /// # Safety
153
    ///
154
    /// `index` must be between 0 (included) and [`BitLength::len`] (excluded).
155
    #[inline(always)]
156
    unsafe fn set_unchecked(&mut self, index: usize, value: bool) {
50,249,487✔
157
        let bits_per_word = W::BITS as usize;
100,498,974✔
158
        let word_index = index / bits_per_word;
100,498,974✔
159
        let bit_index = index % bits_per_word;
100,498,974✔
160
        let bits = self.as_mut();
150,748,461✔
161
        // For constant values, this should be inlined with no test.
162
        unsafe {
163
            if value {
99,542,425✔
164
                *bits.get_unchecked_mut(word_index) |= W::ONE << bit_index;
98,585,876✔
165
            } else {
166
                *bits.get_unchecked_mut(word_index) &= !(W::ONE << bit_index);
1,913,098✔
167
            }
168
        }
169
    }
170

171
    /// Sets all bits to the given value.
172
    fn fill(&mut self, value: bool) {
114✔
173
        let bits_per_word = W::BITS as usize;
228✔
174
        let full_words = self.len() / bits_per_word;
342✔
175
        let residual = self.len() % bits_per_word;
342✔
176
        let bits = self.as_mut();
342✔
177
        let word_value: W = if value { !W::ZERO } else { W::ZERO };
456✔
178
        bits[..full_words].iter_mut().for_each(|x| *x = word_value);
1,117✔
179
        if residual != 0 {
189✔
180
            let mask = (W::ONE << residual) - W::ONE;
225✔
181
            bits[full_words] = (bits[full_words] & !mask) | (word_value & mask);
225✔
182
        }
183
    }
184

185
    /// Sets all bits to the given value using a parallel implementation.
186
    #[cfg(feature = "rayon")]
187
    fn par_fill(&mut self, value: bool) {
16✔
188
        let bits_per_word = W::BITS as usize;
32✔
189
        let full_words = self.len() / bits_per_word;
48✔
190
        let residual = self.len() % bits_per_word;
48✔
191
        let bits = self.as_mut();
48✔
192
        let word_value: W = if value { !W::ZERO } else { W::ZERO };
64✔
193
        bits[..full_words]
16✔
194
            .par_iter_mut()
195
            .with_min_len(crate::RAYON_MIN_LEN)
16✔
196
            .for_each(|x| *x = word_value);
58✔
197
        if residual != 0 {
26✔
198
            let mask = (W::ONE << residual) - W::ONE;
30✔
199
            bits[full_words] = (bits[full_words] & !mask) | (word_value & mask);
30✔
200
        }
201
    }
202

203
    /// Sets all bits to zero.
204
    fn reset(&mut self) {
×
205
        self.fill(false);
×
206
    }
207

208
    /// Sets all bits to zero using a parallel implementation.
209
    #[cfg(feature = "rayon")]
210
    fn par_reset(&mut self) {
×
211
        self.par_fill(false);
×
212
    }
213

214
    /// Flip all bits.
215
    fn flip(&mut self) {
112✔
216
        let bits_per_word = W::BITS as usize;
224✔
217
        let full_words = self.len() / bits_per_word;
336✔
218
        let residual = self.len() % bits_per_word;
336✔
219
        let bits = self.as_mut();
336✔
220
        bits[..full_words].iter_mut().for_each(|x| *x = !*x);
156,282,346✔
221
        if residual != 0 {
184✔
222
            let mask = (W::ONE << residual) - W::ONE;
216✔
223
            bits[full_words] = (bits[full_words] & !mask) | (!bits[full_words] & mask);
216✔
224
        }
225
    }
226

227
    /// Flips all bits using a parallel implementation.
228
    #[cfg(feature = "rayon")]
229
    fn par_flip(&mut self) {
16✔
230
        let bits_per_word = W::BITS as usize;
32✔
231
        let full_words = self.len() / bits_per_word;
48✔
232
        let residual = self.len() % bits_per_word;
48✔
233
        let bits = self.as_mut();
48✔
234
        bits[..full_words]
16✔
235
            .par_iter_mut()
236
            .with_min_len(crate::RAYON_MIN_LEN)
16✔
237
            .for_each(|x| *x = !*x);
58✔
238
        if residual != 0 {
26✔
239
            let mask = (W::ONE << residual) - W::ONE;
30✔
240
            bits[full_words] = (bits[full_words] & !mask) | (!bits[full_words] & mask);
30✔
241
        }
242
    }
243
}
244

245
/// Operations for reading multi-bit values from a bit vector at arbitrary
246
/// bit positions.
247
///
248
/// Unlike [`BitVecOps`] and [`BitVecOpsMut`], this trait does not have a
249
/// blanket implementation, allowing different types to provide specialized
250
/// implementations (e.g., using unaligned reads).
251
pub trait BitVecValueOps<W: Word> {
252
    /// Reads `width` bits starting at bit position `pos`.
253
    ///
254
    /// # Panics
255
    ///
256
    /// Panics if `pos + width` exceeds the bit length or if `width` >
257
    /// `W::BITS`.
258
    fn get_value(&self, pos: usize, width: usize) -> W;
259

260
    /// Reads `width` bits starting at bit position `pos`, without bounds
261
    /// checks.
262
    ///
263
    /// # Safety
264
    ///
265
    /// - `pos + width` must not exceed the bit length of the underlying
266
    ///   storage.
267
    /// - `width` must be at most `W::BITS`.
268
    unsafe fn get_value_unchecked(&self, pos: usize, width: usize) -> W;
269
}
270

271
/// An iterator over the bits of a bit vector as booleans.
272
#[derive(Debug, Clone, MemSize, MemDbg)]
273
pub struct BitIter<'a, W: Word, B: ?Sized> {
274
    bits: &'a B,
275
    len: usize,
276
    next_bit_pos: usize,
277
    _phantom: PhantomData<W>,
278
}
279

280
impl<'a, W: Word, B: ?Sized + AsRef<[W]>> BitIter<'a, W, B> {
281
    pub fn new(bits: &'a B, len: usize) -> Self {
15,781✔
282
        debug_assert!(len <= bits.as_ref().len() * W::BITS as usize);
63,124✔
283
        BitIter {
284
            bits,
285
            len,
286
            next_bit_pos: 0,
287
            _phantom: PhantomData,
288
        }
289
    }
290
}
291

292
impl<W: Word, B: ?Sized + AsRef<[W]>> Iterator for BitIter<'_, W, B> {
293
    type Item = bool;
294
    fn next(&mut self) -> Option<bool> {
243,508,421✔
295
        if self.next_bit_pos == self.len {
243,508,421✔
296
            return None;
15,781✔
297
        }
298
        let bits_per_word = W::BITS as usize;
486,985,280✔
299
        let word_idx = self.next_bit_pos / bits_per_word;
486,985,280✔
300
        let bit_idx = self.next_bit_pos % bits_per_word;
486,985,280✔
301
        let word = unsafe { *self.bits.as_ref().get_unchecked(word_idx) };
730,477,920✔
302
        let bit = (word >> bit_idx) & W::ONE;
486,985,280✔
303
        self.next_bit_pos += 1;
243,492,640✔
304
        Some(bit != W::ZERO)
243,492,640✔
305
    }
306
}
307

308
impl<W: Word, B: ?Sized + AsRef<[W]>> ExactSizeIterator for BitIter<'_, W, B> {
309
    fn len(&self) -> usize {
×
310
        self.len - self.next_bit_pos
×
311
    }
312
}
313

314
impl<W: Word, B: ?Sized + AsRef<[W]>> FusedIterator for BitIter<'_, W, B> {}
315

316
/// An iterator over the positions of the ones in a bit vector.
317
#[derive(Debug, Clone, MemSize, MemDbg)]
318
pub struct OnesIter<'a, W: Word, B: ?Sized> {
319
    bits: &'a B,
320
    len: usize,
321
    word_idx: usize,
322
    word: W,
323
}
324

325
impl<'a, W: Word, B: ?Sized + AsRef<[W]>> OnesIter<'a, W, B> {
326
    pub fn new(bits: &'a B, len: usize) -> Self {
30✔
327
        debug_assert!(len <= bits.as_ref().len() * W::BITS as usize);
120✔
328
        let word = if bits.as_ref().is_empty() {
90✔
329
            W::ZERO
5✔
330
        } else {
331
            unsafe { *bits.as_ref().get_unchecked(0) }
25✔
332
        };
333
        Self {
334
            bits,
335
            len,
336
            word_idx: 0,
337
            word,
338
        }
339
    }
340
}
341

342
impl<W: Word, B: ?Sized + AsRef<[W]>> Iterator for OnesIter<'_, W, B> {
343
    type Item = usize;
344

345
    fn next(&mut self) -> Option<Self::Item> {
971✔
346
        let bits_per_word = W::BITS as usize;
1,942✔
347
        // find the next word with ones
348
        while self.word == W::ZERO {
1,055✔
349
            self.word_idx += 1;
113✔
350
            if self.word_idx >= self.bits.as_ref().len() {
226✔
351
                return None;
29✔
352
            }
353
            self.word = unsafe { *self.bits.as_ref().get_unchecked(self.word_idx) };
168✔
354
        }
355
        // find the lowest bit set index in the word
356
        let bit_idx = self.word.trailing_zeros() as usize;
1,884✔
357
        // compute the global bit index
358
        let res = (self.word_idx * bits_per_word) + bit_idx;
1,884✔
359
        if res >= self.len {
942✔
360
            None
1✔
361
        } else {
362
            // clear the lowest bit set
363
            self.word &= self.word - W::ONE;
941✔
364
            Some(res)
941✔
365
        }
366
    }
367
}
368

369
impl<W: Word, B: ?Sized + AsRef<[W]>> FusedIterator for OnesIter<'_, W, B> {}
370

371
/// An iterator over the positions of the zeros in a bit vector.
372
#[derive(Debug, Clone, MemSize, MemDbg)]
373
pub struct ZerosIter<'a, W: Word, B: ?Sized> {
374
    bits: &'a B,
375
    len: usize,
376
    word_idx: usize,
377
    word: W,
378
}
379

380
impl<'a, W: Word, B: ?Sized + AsRef<[W]>> ZerosIter<'a, W, B> {
381
    pub fn new(bits: &'a B, len: usize) -> Self {
30✔
382
        debug_assert!(len <= bits.as_ref().len() * W::BITS as usize);
120✔
383
        let word = if bits.as_ref().is_empty() {
90✔
384
            W::ZERO
5✔
385
        } else {
386
            unsafe { !*bits.as_ref().get_unchecked(0) }
25✔
387
        };
388
        Self {
389
            bits,
390
            len,
391
            word_idx: 0,
392
            word,
393
        }
394
    }
395
}
396

397
impl<W: Word, B: ?Sized + AsRef<[W]>> Iterator for ZerosIter<'_, W, B> {
398
    type Item = usize;
399

400
    fn next(&mut self) -> Option<Self::Item> {
961✔
401
        let bits_per_word = W::BITS as usize;
1,922✔
402
        // find the next flipped word with zeros
403
        while self.word == W::ZERO {
1,045✔
404
            self.word_idx += 1;
91✔
405
            if self.word_idx >= self.bits.as_ref().len() {
182✔
406
                return None;
7✔
407
            }
408
            self.word = unsafe { !*self.bits.as_ref().get_unchecked(self.word_idx) };
168✔
409
        }
410
        // find the lowest zero bit index in the word
411
        let bit_idx = self.word.trailing_zeros() as usize;
1,908✔
412
        // compute the global bit index
413
        let res = (self.word_idx * bits_per_word) + bit_idx;
1,908✔
414
        if res >= self.len {
954✔
415
            None
23✔
416
        } else {
417
            // clear the lowest bit set
418
            self.word &= self.word - W::ONE;
931✔
419
            Some(res)
931✔
420
        }
421
    }
422
}
423

424
impl<W: Word, B: ?Sized + AsRef<[W]>> FusedIterator for ZerosIter<'_, W, B> {}
425

426
impl<A: PrimitiveAtomicUnsigned<Value: Word>, T: ?Sized + AsRef<[A]> + BitLength> AtomicBitVecOps<A>
427
    for T
428
{
429
}
430

431
/// Operations on atomic bit vectors.
432
///
433
/// Parameterized by the atomic type `A` (e.g., `AtomicU64`), not the word type.
434
/// This avoids method-resolution ambiguity with [`BitVecOpsMut`], because
435
/// [`PrimitiveAtomicUnsigned`] is only implemented for atomic types, so the compiler can
436
/// definitively rule out non-atomic backends.
437
pub trait AtomicBitVecOps<A: PrimitiveAtomicUnsigned<Value: Word>>: AsRef<[A]> + BitLength {
438
    /// Returns true if the bit of given index is set.
439
    ///
440
    /// This method performs a single atomic operation with the given memory
441
    /// ordering.
442
    fn get(&self, index: usize, ordering: Ordering) -> bool {
64,368✔
443
        panic_if_out_of_bounds!(index, self.len());
128,736✔
444
        unsafe { self.get_unchecked(index, ordering) }
257,472✔
445
    }
446

447
    /// Sets the bit of given index to the given value.
448
    ///
449
    /// This method performs a single atomic operation with the given memory
450
    /// ordering.
451
    fn set(&self, index: usize, value: bool, ordering: Ordering) {
4,310✔
452
        panic_if_out_of_bounds!(index, self.len());
8,620✔
453
        unsafe { self.set_unchecked(index, value, ordering) }
21,550✔
454
    }
455

456
    /// Sets the bit of given index to the given value and returns the previous
457
    /// value.
458
    ///
459
    /// This method performs a single atomic operation with the given memory
460
    /// ordering.
461
    fn swap(&self, index: usize, value: bool, ordering: Ordering) -> bool {
3✔
462
        panic_if_out_of_bounds!(index, self.len());
6✔
463
        unsafe { self.swap_unchecked(index, value, ordering) }
15✔
464
    }
465

466
    /// Returns true if the bit of given index is set.
467
    ///
468
    /// This method performs a single atomic operation with the given memory
469
    /// ordering.
470
    ///
471
    /// # Safety
472
    ///
473
    /// `index` must be between 0 (included) and [`BitLength::len`] (excluded).
474
    #[inline]
475
    unsafe fn get_unchecked(&self, index: usize, ordering: Ordering) -> bool {
64,368✔
476
        let bits_per_word = A::Value::BITS as usize;
128,736✔
477
        let word_index = index / bits_per_word;
128,736✔
478
        let bits = self.as_ref();
193,104✔
479
        let word = unsafe { bits.get_unchecked(word_index).load(ordering) };
321,840✔
480
        (word >> (index % bits_per_word)) & A::Value::ONE != A::Value::ZERO
128,736✔
481
    }
482

483
    /// Sets the bit of given index to the given value.
484
    ///
485
    /// This method performs a single atomic operation with the given memory
486
    /// ordering.
487
    ///
488
    /// # Safety
489
    ///
490
    /// `index` must be between 0 (included) and [`BitLength::len`] (excluded).
491
    #[inline]
492
    unsafe fn set_unchecked(&self, index: usize, value: bool, ordering: Ordering) {
4,310✔
493
        let bits_per_word = A::Value::BITS as usize;
8,620✔
494
        let word_index = index / bits_per_word;
8,620✔
495
        let bit_index = index % bits_per_word;
8,620✔
496
        let bits = self.as_ref();
12,930✔
497

498
        // For constant values, this should be inlined with no test.
499
        unsafe {
500
            if value {
7,570✔
501
                bits.get_unchecked(word_index)
9,780✔
502
                    .fetch_or(A::Value::ONE << bit_index, ordering);
6,520✔
503
            } else {
504
                bits.get_unchecked(word_index)
3,150✔
505
                    .fetch_and(!(A::Value::ONE << bit_index), ordering);
2,100✔
506
            }
507
        }
508
    }
509

510
    /// Sets the bit of given index to the given value and returns the previous
511
    /// value, without bound checks.
512
    ///
513
    /// This method performs a single atomic operation with the given memory
514
    /// ordering.
515
    ///
516
    /// # Safety
517
    ///
518
    /// `index` must be between 0 (included) and [`BitLength::len`] (excluded).
519
    #[inline]
520
    unsafe fn swap_unchecked(&self, index: usize, value: bool, ordering: Ordering) -> bool {
3✔
521
        let bits_per_word = A::Value::BITS as usize;
6✔
522
        let word_index = index / bits_per_word;
6✔
523
        let bit_index = index % bits_per_word;
6✔
524
        let bits = self.as_ref();
9✔
525

526
        let old_word = unsafe {
527
            if value {
3✔
528
                bits.get_unchecked(word_index)
4✔
529
                    .fetch_or(A::Value::ONE << bit_index, ordering)
6✔
530
            } else {
531
                bits.get_unchecked(word_index)
2✔
532
                    .fetch_and(!(A::Value::ONE << bit_index), ordering)
3✔
533
            }
534
        };
535

536
        (old_word >> bit_index) & A::Value::ONE != A::Value::ZERO
3✔
537
    }
538

539
    /// Sets all bits to the given value.
540
    fn fill(&mut self, value: bool, ordering: Ordering) {
24✔
541
        let bits_per_word = A::Value::BITS as usize;
48✔
542
        let full_words = self.len() / bits_per_word;
72✔
543
        let residual = self.len() % bits_per_word;
72✔
544
        let bits = self.as_ref();
72✔
545
        let word_value: A::Value = if value {
72✔
546
            !A::Value::ZERO
8✔
547
        } else {
548
            A::Value::ZERO
16✔
549
        };
550
        // Just to be sure, add a fence to ensure that we will see all the final
551
        // values
552
        core::sync::atomic::fence(Ordering::SeqCst);
48✔
553
        bits[..full_words]
24✔
554
            .iter()
555
            .for_each(|x| x.store(word_value, ordering));
276✔
556
        if residual != 0 {
39✔
557
            let mask = (A::Value::ONE << residual) - A::Value::ONE;
45✔
558
            bits[full_words].store(
45✔
559
                (bits[full_words].load(ordering) & !mask) | (word_value & mask),
60✔
560
                ordering,
15✔
561
            );
562
        }
563
    }
564

565
    /// Sets all bits to the given value using a parallel implementation.
566
    #[cfg(feature = "rayon")]
567
    fn par_fill(&mut self, value: bool, ordering: Ordering) {
16✔
568
        let bits_per_word = A::Value::BITS as usize;
32✔
569
        let full_words = self.len() / bits_per_word;
48✔
570
        let residual = self.len() % bits_per_word;
48✔
571
        let bits = self.as_ref();
48✔
572
        let word_value: A::Value = if value {
48✔
573
            !A::Value::ZERO
8✔
574
        } else {
575
            A::Value::ZERO
8✔
576
        };
577

578
        // Just to be sure, add a fence to ensure that we will see all the final
579
        // values
580
        core::sync::atomic::fence(Ordering::SeqCst);
32✔
581
        bits[..full_words]
16✔
582
            .par_iter()
583
            .with_min_len(crate::RAYON_MIN_LEN)
16✔
584
            .for_each(|x| x.store(word_value, ordering));
184✔
585
        if residual != 0 {
26✔
586
            let mask = (A::Value::ONE << residual) - A::Value::ONE;
30✔
587
            bits[full_words].store(
30✔
588
                (bits[full_words].load(ordering) & !mask) | (word_value & mask),
40✔
589
                ordering,
10✔
590
            );
591
        }
592
    }
593

594
    /// Sets all bits to zero.
595
    fn reset(&mut self, ordering: Ordering) {
×
596
        self.fill(false, ordering);
×
597
    }
598

599
    /// Sets all bits to zero using a parallel implementation.
600
    #[cfg(feature = "rayon")]
601
    fn par_reset(&mut self, ordering: Ordering) {
×
602
        self.par_fill(false, ordering);
×
603
    }
604

605
    /// Flips all bits.
606
    fn flip(&mut self, ordering: Ordering) {
16✔
607
        let bits_per_word = A::Value::BITS as usize;
32✔
608
        let full_words = self.len() / bits_per_word;
48✔
609
        let residual = self.len() % bits_per_word;
48✔
610
        let bits = self.as_ref();
48✔
611
        // Just to be sure, add a fence to ensure that we will see all the final
612
        // values
613
        core::sync::atomic::fence(Ordering::SeqCst);
32✔
614
        bits[..full_words]
16✔
615
            .iter()
616
            .for_each(|x| _ = x.fetch_xor(!A::Value::ZERO, ordering));
142✔
617
        if residual != 0 {
26✔
618
            let mask = (A::Value::ONE << residual) - A::Value::ONE;
30✔
619
            let last_word = bits[full_words].load(ordering);
50✔
620
            bits[full_words].store((last_word & !mask) | (!last_word & mask), ordering);
40✔
621
        }
622
    }
623

624
    /// Flips all bits using a parallel implementation.
625
    #[cfg(feature = "rayon")]
626
    fn par_flip(&mut self, ordering: Ordering) {
16✔
627
        let bits_per_word = A::Value::BITS as usize;
32✔
628
        let full_words = self.len() / bits_per_word;
48✔
629
        let residual = self.len() % bits_per_word;
48✔
630
        let bits = self.as_ref();
48✔
631
        // Just to be sure, add a fence to ensure that we will see all the final
632
        // values
633
        core::sync::atomic::fence(Ordering::SeqCst);
32✔
634
        bits[..full_words]
16✔
635
            .par_iter()
636
            .with_min_len(crate::RAYON_MIN_LEN)
16✔
637
            .for_each(|x| _ = x.fetch_xor(!A::Value::ZERO, ordering));
142✔
638
        if residual != 0 {
26✔
639
            let mask = (A::Value::ONE << residual) - A::Value::ONE;
30✔
640
            let last_word = bits[full_words].load(ordering);
50✔
641
            bits[full_words].store((last_word & !mask) | (!last_word & mask), ordering);
40✔
642
        }
643
    }
644

645
    /// A parallel version of [`BitCount::count_ones`].
646
    ///
647
    /// [`BitCount::count_ones`]: `crate::traits::BitCount::count_ones`
648
    #[cfg(feature = "rayon")]
649
    fn par_count_ones(&self) -> usize {
×
650
        let bits_per_word = A::Value::BITS as usize;
×
651
        let full_words = self.len() / bits_per_word;
×
652
        let residual = self.len() % bits_per_word;
×
653
        let bits = self.as_ref();
×
654
        let mut num_ones;
×
655
        // Just to be sure, add a fence to ensure that we will see all the final
656
        // values
657
        core::sync::atomic::fence(Ordering::SeqCst);
×
658
        num_ones = bits[..full_words]
×
659
            .par_iter()
×
660
            .with_min_len(crate::RAYON_MIN_LEN)
×
661
            .map(|x| x.load(Ordering::Relaxed).count_ones() as usize)
×
662
            .sum();
×
663
        if residual != 0 {
×
664
            num_ones += (bits[full_words].load(Ordering::Relaxed) << (bits_per_word - residual))
×
665
                .count_ones() as usize
×
666
        }
667
        num_ones
×
668
    }
669

670
    /// Returns an iterator over the bits of this atomic bit vector.
671
    ///
672
    /// Note that modifying the bit vector while iterating over it will lead to
673
    /// behavior depending on processor scheduling and memory model.
674
    /// Nonetheless, all returned values have been valid at some point during
675
    /// the iteration.
676
    #[inline(always)]
677
    fn iter(&self) -> AtomicBitIter<'_, A, [A]> {
1✔
678
        AtomicBitIter::new(self.as_ref(), self.len())
4✔
679
    }
680
}
681

682
/// An iterator over the bits of an atomic bit vector as booleans.
683
///
684
/// Note that modifying the bit vector while iterating over it will lead to
685
/// behavior depending on processor scheduling and memory model.
686
#[derive(Debug, MemSize, MemDbg)]
687
pub struct AtomicBitIter<'a, A, B: ?Sized> {
688
    bits: &'a B,
689
    len: usize,
690
    next_bit_pos: usize,
691
    _phantom: PhantomData<A>,
692
}
693

694
impl<'a, A: PrimitiveAtomicUnsigned<Value: Word>, B: ?Sized + AsRef<[A]>> AtomicBitIter<'a, A, B> {
695
    pub fn new(bits: &'a B, len: usize) -> Self {
1✔
696
        debug_assert!(len <= bits.as_ref().len() * A::Value::BITS as usize);
4✔
697
        AtomicBitIter {
698
            bits,
699
            len,
700
            next_bit_pos: 0,
701
            _phantom: PhantomData,
702
        }
703
    }
704
}
705

706
impl<A: PrimitiveAtomicUnsigned<Value: Word>, B: ?Sized + AsRef<[A]>> Iterator
707
    for AtomicBitIter<'_, A, B>
708
{
709
    type Item = bool;
710
    fn next(&mut self) -> Option<bool> {
101✔
711
        if self.next_bit_pos == self.len {
101✔
712
            return None;
1✔
713
        }
714
        let bits_per_word = A::Value::BITS as usize;
200✔
715
        let word_idx = self.next_bit_pos / bits_per_word;
200✔
716
        let bit_idx = self.next_bit_pos % bits_per_word;
200✔
717
        let word = unsafe {
718
            self.bits
200✔
719
                .as_ref()
720
                .get_unchecked(word_idx)
100✔
721
                .load(Ordering::Relaxed)
200✔
722
        };
723
        let bit = (word >> bit_idx) & A::Value::ONE;
200✔
724
        self.next_bit_pos += 1;
100✔
725
        Some(bit != A::Value::ZERO)
100✔
726
    }
727
}
728

729
impl<A: PrimitiveAtomicUnsigned<Value: Word>, B: ?Sized + AsRef<[A]>> ExactSizeIterator
730
    for AtomicBitIter<'_, A, B>
731
{
732
    fn len(&self) -> usize {
×
733
        self.len - self.next_bit_pos
×
734
    }
735
}
736

737
impl<A: PrimitiveAtomicUnsigned<Value: Word>, B: ?Sized + AsRef<[A]>> FusedIterator
738
    for AtomicBitIter<'_, A, B>
739
{
740
}
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