polars_arrow/bitmap/
immutable.rs

1use std::ops::Deref;
2use std::sync::atomic::{AtomicU64, Ordering};
3use std::sync::LazyLock;
4
5use either::Either;
6use polars_error::{polars_bail, PolarsResult};
7
8use super::utils::{self, count_zeros, fmt, get_bit_unchecked, BitChunk, BitChunks, BitmapIter};
9use super::{chunk_iter_to_vec, intersects_with, num_intersections_with, IntoIter, MutableBitmap};
10use crate::array::Splitable;
11use crate::bitmap::aligned::AlignedBitmapSlice;
12use crate::bitmap::iterator::{
13    FastU32BitmapIter, FastU56BitmapIter, FastU64BitmapIter, TrueIdxIter,
14};
15use crate::legacy::utils::FromTrustedLenIterator;
16use crate::storage::SharedStorage;
17use crate::trusted_len::TrustedLen;
18
19const UNKNOWN_BIT_COUNT: u64 = u64::MAX;
20
21/// An immutable container semantically equivalent to `Arc<Vec<bool>>` but represented as `Arc<Vec<u8>>` where
22/// each boolean is represented as a single bit.
23///
24/// # Examples
25/// ```
26/// use polars_arrow::bitmap::{Bitmap, MutableBitmap};
27///
28/// let bitmap = Bitmap::from([true, false, true]);
29/// assert_eq!(bitmap.iter().collect::<Vec<_>>(), vec![true, false, true]);
30///
31/// // creation directly from bytes
32/// let bitmap = Bitmap::try_new(vec![0b00001101], 5).unwrap();
33/// // note: the first bit is the left-most of the first byte
34/// assert_eq!(bitmap.iter().collect::<Vec<_>>(), vec![true, false, true, true, false]);
35/// // we can also get the slice:
36/// assert_eq!(bitmap.as_slice(), ([0b00001101u8].as_ref(), 0, 5));
37/// // debug helps :)
38/// assert_eq!(format!("{:?}", bitmap), "Bitmap { len: 5, offset: 0, bytes: [0b___01101] }");
39///
40/// // it supports copy-on-write semantics (to a `MutableBitmap`)
41/// let bitmap: MutableBitmap = bitmap.into_mut().right().unwrap();
42/// assert_eq!(bitmap, MutableBitmap::from([true, false, true, true, false]));
43///
44/// // slicing is 'O(1)' (data is shared)
45/// let bitmap = Bitmap::try_new(vec![0b00001101], 5).unwrap();
46/// let mut sliced = bitmap.clone();
47/// sliced.slice(1, 4);
48/// assert_eq!(sliced.as_slice(), ([0b00001101u8].as_ref(), 1, 4)); // 1 here is the offset:
49/// assert_eq!(format!("{:?}", sliced), "Bitmap { len: 4, offset: 1, bytes: [0b___0110_] }");
50/// // when sliced (or cloned), it is no longer possible to `into_mut`.
51/// let same: Bitmap = sliced.into_mut().left().unwrap();
52/// ```
53pub struct Bitmap {
54    storage: SharedStorage<u8>,
55    // Both offset and length are measured in bits. They are used to bound the
56    // bitmap to a region of Bytes.
57    offset: usize,
58    length: usize,
59
60    // A bit field that contains our cache for the number of unset bits.
61    // If it is u64::MAX, we have no known value at all.
62    // Other bit patterns where the top bit is set is reserved for future use.
63    // If the top bit is not set we have an exact count.
64    unset_bit_count_cache: AtomicU64,
65}
66
67#[inline(always)]
68fn has_cached_unset_bit_count(ubcc: u64) -> bool {
69    ubcc >> 63 == 0
70}
71
72impl Clone for Bitmap {
73    fn clone(&self) -> Self {
74        Self {
75            storage: self.storage.clone(),
76            offset: self.offset,
77            length: self.length,
78            unset_bit_count_cache: AtomicU64::new(
79                self.unset_bit_count_cache.load(Ordering::Relaxed),
80            ),
81        }
82    }
83}
84
85impl std::fmt::Debug for Bitmap {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        let (bytes, offset, len) = self.as_slice();
88        fmt(bytes, offset, len, f)
89    }
90}
91
92impl Default for Bitmap {
93    fn default() -> Self {
94        MutableBitmap::new().into()
95    }
96}
97
98pub(super) fn check(bytes: &[u8], offset: usize, length: usize) -> PolarsResult<()> {
99    if offset + length > bytes.len().saturating_mul(8) {
100        polars_bail!(InvalidOperation:
101            "The offset + length of the bitmap ({}) must be `<=` to the number of bytes times 8 ({})",
102            offset + length,
103            bytes.len().saturating_mul(8)
104        );
105    }
106    Ok(())
107}
108
109impl Bitmap {
110    /// Initializes an empty [`Bitmap`].
111    #[inline]
112    pub fn new() -> Self {
113        Self::default()
114    }
115
116    /// Initializes a new [`Bitmap`] from vector of bytes and a length.
117    /// # Errors
118    /// This function errors iff `length > bytes.len() * 8`
119    #[inline]
120    pub fn try_new(bytes: Vec<u8>, length: usize) -> PolarsResult<Self> {
121        check(&bytes, 0, length)?;
122        Ok(Self {
123            storage: SharedStorage::from_vec(bytes),
124            length,
125            offset: 0,
126            unset_bit_count_cache: AtomicU64::new(if length == 0 { 0 } else { UNKNOWN_BIT_COUNT }),
127        })
128    }
129
130    /// Returns the length of the [`Bitmap`].
131    #[inline]
132    pub fn len(&self) -> usize {
133        self.length
134    }
135
136    /// Returns whether [`Bitmap`] is empty
137    #[inline]
138    pub fn is_empty(&self) -> bool {
139        self.len() == 0
140    }
141
142    /// Returns a new iterator of `bool` over this bitmap
143    pub fn iter(&self) -> BitmapIter {
144        BitmapIter::new(&self.storage, self.offset, self.length)
145    }
146
147    /// Returns an iterator over bits in bit chunks [`BitChunk`].
148    ///
149    /// This iterator is useful to operate over multiple bits via e.g. bitwise.
150    pub fn chunks<T: BitChunk>(&self) -> BitChunks<T> {
151        BitChunks::new(&self.storage, self.offset, self.length)
152    }
153
154    /// Returns a fast iterator that gives 32 bits at a time.
155    /// Has a remainder that must be handled separately.
156    pub fn fast_iter_u32(&self) -> FastU32BitmapIter<'_> {
157        FastU32BitmapIter::new(&self.storage, self.offset, self.length)
158    }
159
160    /// Returns a fast iterator that gives 56 bits at a time.
161    /// Has a remainder that must be handled separately.
162    pub fn fast_iter_u56(&self) -> FastU56BitmapIter<'_> {
163        FastU56BitmapIter::new(&self.storage, self.offset, self.length)
164    }
165
166    /// Returns a fast iterator that gives 64 bits at a time.
167    /// Has a remainder that must be handled separately.
168    pub fn fast_iter_u64(&self) -> FastU64BitmapIter<'_> {
169        FastU64BitmapIter::new(&self.storage, self.offset, self.length)
170    }
171
172    /// Returns an iterator that only iterates over the set bits.
173    pub fn true_idx_iter(&self) -> TrueIdxIter<'_> {
174        TrueIdxIter::new(self.len(), Some(self))
175    }
176
177    /// Returns the bits of this [`Bitmap`] as a [`AlignedBitmapSlice`].
178    pub fn aligned<T: BitChunk>(&self) -> AlignedBitmapSlice<'_, T> {
179        AlignedBitmapSlice::new(&self.storage, self.offset, self.length)
180    }
181
182    /// Returns the byte slice of this [`Bitmap`].
183    ///
184    /// The returned tuple contains:
185    /// * `.1`: The byte slice, truncated to the start of the first bit. So the start of the slice
186    ///       is within the first 8 bits.
187    /// * `.2`: The start offset in bits on a range `0 <= offsets < 8`.
188    /// * `.3`: The length in number of bits.
189    #[inline]
190    pub fn as_slice(&self) -> (&[u8], usize, usize) {
191        let start = self.offset / 8;
192        let len = (self.offset % 8 + self.length).saturating_add(7) / 8;
193        (
194            &self.storage[start..start + len],
195            self.offset % 8,
196            self.length,
197        )
198    }
199
200    /// Returns the number of set bits on this [`Bitmap`].
201    ///
202    /// See `unset_bits` for details.
203    #[inline]
204    pub fn set_bits(&self) -> usize {
205        self.length - self.unset_bits()
206    }
207
208    /// Returns the number of set bits on this [`Bitmap`] if it is known.
209    ///
210    /// See `lazy_unset_bits` for details.
211    #[inline]
212    pub fn lazy_set_bits(&self) -> Option<usize> {
213        Some(self.length - self.lazy_unset_bits()?)
214    }
215
216    /// Returns the number of unset bits on this [`Bitmap`].
217    ///
218    /// Guaranteed to be `<= self.len()`.
219    ///
220    /// # Implementation
221    ///
222    /// This function counts the number of unset bits if it is not already
223    /// computed. Repeated calls use the cached bitcount.
224    pub fn unset_bits(&self) -> usize {
225        self.lazy_unset_bits().unwrap_or_else(|| {
226            let zeros = count_zeros(&self.storage, self.offset, self.length);
227            self.unset_bit_count_cache
228                .store(zeros as u64, Ordering::Relaxed);
229            zeros
230        })
231    }
232
233    /// Returns the number of unset bits on this [`Bitmap`] if it is known.
234    ///
235    /// Guaranteed to be `<= self.len()`.
236    pub fn lazy_unset_bits(&self) -> Option<usize> {
237        let cache = self.unset_bit_count_cache.load(Ordering::Relaxed);
238        has_cached_unset_bit_count(cache).then_some(cache as usize)
239    }
240
241    /// Updates the count of the number of set bits on this [`Bitmap`].
242    ///
243    /// # Safety
244    ///
245    /// The number of set bits must be correct.
246    pub unsafe fn update_bit_count(&mut self, bits_set: usize) {
247        assert!(bits_set <= self.length);
248        let zeros = self.length - bits_set;
249        self.unset_bit_count_cache
250            .store(zeros as u64, Ordering::Relaxed);
251    }
252
253    /// Slices `self`, offsetting by `offset` and truncating up to `length` bits.
254    /// # Panic
255    /// Panics iff `offset + length > self.length`, i.e. if the offset and `length`
256    /// exceeds the allocated capacity of `self`.
257    #[inline]
258    pub fn slice(&mut self, offset: usize, length: usize) {
259        assert!(offset + length <= self.length);
260        unsafe { self.slice_unchecked(offset, length) }
261    }
262
263    /// Slices `self`, offsetting by `offset` and truncating up to `length` bits.
264    ///
265    /// # Safety
266    /// The caller must ensure that `self.offset + offset + length <= self.len()`
267    #[inline]
268    pub unsafe fn slice_unchecked(&mut self, offset: usize, length: usize) {
269        // Fast path: no-op slice.
270        if offset == 0 && length == self.length {
271            return;
272        }
273
274        // Fast path: we have no nulls or are full-null.
275        let unset_bit_count_cache = self.unset_bit_count_cache.get_mut();
276        if *unset_bit_count_cache == 0 || *unset_bit_count_cache == self.length as u64 {
277            let new_count = if *unset_bit_count_cache > 0 {
278                length as u64
279            } else {
280                0
281            };
282            *unset_bit_count_cache = new_count;
283            self.offset += offset;
284            self.length = length;
285            return;
286        }
287
288        if has_cached_unset_bit_count(*unset_bit_count_cache) {
289            // If we keep all but a small portion of the array it is worth
290            // doing an eager re-count since we can reuse the old count via the
291            // inclusion-exclusion principle.
292            let small_portion = (self.length / 5).max(32);
293            if length + small_portion >= self.length {
294                // Subtract the null count of the chunks we slice off.
295                let slice_end = self.offset + offset + length;
296                let head_count = count_zeros(&self.storage, self.offset, offset);
297                let tail_count =
298                    count_zeros(&self.storage, slice_end, self.length - length - offset);
299                let new_count = *unset_bit_count_cache - head_count as u64 - tail_count as u64;
300                *unset_bit_count_cache = new_count;
301            } else {
302                *unset_bit_count_cache = UNKNOWN_BIT_COUNT;
303            }
304        }
305
306        self.offset += offset;
307        self.length = length;
308    }
309
310    /// Slices `self`, offsetting by `offset` and truncating up to `length` bits.
311    /// # Panic
312    /// Panics iff `offset + length > self.length`, i.e. if the offset and `length`
313    /// exceeds the allocated capacity of `self`.
314    #[inline]
315    #[must_use]
316    pub fn sliced(self, offset: usize, length: usize) -> Self {
317        assert!(offset + length <= self.length);
318        unsafe { self.sliced_unchecked(offset, length) }
319    }
320
321    /// Slices `self`, offsetting by `offset` and truncating up to `length` bits.
322    ///
323    /// # Safety
324    /// The caller must ensure that `self.offset + offset + length <= self.len()`
325    #[inline]
326    #[must_use]
327    pub unsafe fn sliced_unchecked(mut self, offset: usize, length: usize) -> Self {
328        self.slice_unchecked(offset, length);
329        self
330    }
331
332    /// Returns whether the bit at position `i` is set.
333    /// # Panics
334    /// Panics iff `i >= self.len()`.
335    #[inline]
336    pub fn get_bit(&self, i: usize) -> bool {
337        assert!(i < self.len());
338        unsafe { self.get_bit_unchecked(i) }
339    }
340
341    /// Unsafely returns whether the bit at position `i` is set.
342    ///
343    /// # Safety
344    /// Unsound iff `i >= self.len()`.
345    #[inline]
346    pub unsafe fn get_bit_unchecked(&self, i: usize) -> bool {
347        debug_assert!(i < self.len());
348        get_bit_unchecked(&self.storage, self.offset + i)
349    }
350
351    /// Returns a pointer to the start of this [`Bitmap`] (ignores `offsets`)
352    /// This pointer is allocated iff `self.len() > 0`.
353    pub(crate) fn as_ptr(&self) -> *const u8 {
354        self.storage.deref().as_ptr()
355    }
356
357    /// Returns a pointer to the start of this [`Bitmap`] (ignores `offsets`)
358    /// This pointer is allocated iff `self.len() > 0`.
359    pub(crate) fn offset(&self) -> usize {
360        self.offset
361    }
362
363    /// Converts this [`Bitmap`] to [`MutableBitmap`], returning itself if the conversion
364    /// is not possible
365    ///
366    /// This operation returns a [`MutableBitmap`] iff:
367    /// * this [`Bitmap`] is not an offsetted slice of another [`Bitmap`]
368    /// * this [`Bitmap`] has not been cloned (i.e. [`Arc`]`::get_mut` yields [`Some`])
369    /// * this [`Bitmap`] was not imported from the c data interface (FFI)
370    pub fn into_mut(mut self) -> Either<Self, MutableBitmap> {
371        match self.storage.try_into_vec() {
372            Ok(v) => Either::Right(MutableBitmap::from_vec(v, self.length)),
373            Err(storage) => {
374                self.storage = storage;
375                Either::Left(self)
376            },
377        }
378    }
379
380    /// Converts this [`Bitmap`] into a [`MutableBitmap`], cloning its internal
381    /// buffer if required (clone-on-write).
382    pub fn make_mut(self) -> MutableBitmap {
383        match self.into_mut() {
384            Either::Left(data) => {
385                if data.offset > 0 {
386                    // re-align the bits (remove the offset)
387                    let chunks = data.chunks::<u64>();
388                    let remainder = chunks.remainder();
389                    let vec = chunk_iter_to_vec(chunks.chain(std::iter::once(remainder)));
390                    MutableBitmap::from_vec(vec, data.length)
391                } else {
392                    MutableBitmap::from_vec(data.storage.as_ref().to_vec(), data.length)
393                }
394            },
395            Either::Right(data) => data,
396        }
397    }
398
399    /// Initializes an new [`Bitmap`] filled with unset values.
400    #[inline]
401    pub fn new_zeroed(length: usize) -> Self {
402        // We intentionally leak 1MiB of zeroed memory once so we don't have to
403        // refcount it.
404        const GLOBAL_ZERO_SIZE: usize = 1024 * 1024;
405        static GLOBAL_ZEROES: LazyLock<SharedStorage<u8>> =
406            LazyLock::new(|| SharedStorage::from_static(vec![0; GLOBAL_ZERO_SIZE].leak()));
407
408        let bytes_needed = length.div_ceil(8);
409        let storage = if bytes_needed <= GLOBAL_ZERO_SIZE {
410            GLOBAL_ZEROES.clone()
411        } else {
412            SharedStorage::from_vec(vec![0; bytes_needed])
413        };
414        Self {
415            storage,
416            offset: 0,
417            length,
418            unset_bit_count_cache: AtomicU64::new(length as u64),
419        }
420    }
421
422    /// Initializes an new [`Bitmap`] filled with the given value.
423    #[inline]
424    pub fn new_with_value(value: bool, length: usize) -> Self {
425        if !value {
426            return Self::new_zeroed(length);
427        }
428
429        unsafe {
430            Bitmap::from_inner_unchecked(
431                SharedStorage::from_vec(vec![u8::MAX; length.saturating_add(7) / 8]),
432                0,
433                length,
434                Some(0),
435            )
436        }
437    }
438
439    /// Counts the nulls (unset bits) starting from `offset` bits and for `length` bits.
440    #[inline]
441    pub fn null_count_range(&self, offset: usize, length: usize) -> usize {
442        count_zeros(&self.storage, self.offset + offset, length)
443    }
444
445    /// Creates a new [`Bitmap`] from a slice and length.
446    /// # Panic
447    /// Panics iff `length <= bytes.len() * 8`
448    #[inline]
449    pub fn from_u8_slice<T: AsRef<[u8]>>(slice: T, length: usize) -> Self {
450        Bitmap::try_new(slice.as_ref().to_vec(), length).unwrap()
451    }
452
453    /// Alias for `Bitmap::try_new().unwrap()`
454    /// This function is `O(1)`
455    /// # Panic
456    /// This function panics iff `length > bytes.len() * 8`
457    #[inline]
458    pub fn from_u8_vec(vec: Vec<u8>, length: usize) -> Self {
459        Bitmap::try_new(vec, length).unwrap()
460    }
461
462    /// Returns whether the bit at position `i` is set.
463    #[inline]
464    pub fn get(&self, i: usize) -> Option<bool> {
465        if i < self.len() {
466            Some(unsafe { self.get_bit_unchecked(i) })
467        } else {
468            None
469        }
470    }
471
472    /// Creates a [`Bitmap`] from its internal representation.
473    /// This is the inverted from [`Bitmap::into_inner`]
474    ///
475    /// # Safety
476    /// Callers must ensure all invariants of this struct are upheld.
477    pub unsafe fn from_inner_unchecked(
478        storage: SharedStorage<u8>,
479        offset: usize,
480        length: usize,
481        unset_bits: Option<usize>,
482    ) -> Self {
483        debug_assert!(check(&storage[..], offset, length).is_ok());
484
485        let unset_bit_count_cache = if let Some(n) = unset_bits {
486            AtomicU64::new(n as u64)
487        } else {
488            AtomicU64::new(UNKNOWN_BIT_COUNT)
489        };
490        Self {
491            storage,
492            offset,
493            length,
494            unset_bit_count_cache,
495        }
496    }
497
498    /// Checks whether two [`Bitmap`]s have shared set bits.
499    ///
500    /// This is an optimized version of `(self & other) != 0000..`.
501    pub fn intersects_with(&self, other: &Self) -> bool {
502        intersects_with(self, other)
503    }
504
505    /// Calculates the number of shared set bits between two [`Bitmap`]s.
506    pub fn num_intersections_with(&self, other: &Self) -> usize {
507        num_intersections_with(self, other)
508    }
509
510    /// Select between `truthy` and `falsy` based on `self`.
511    ///
512    /// This essentially performs:
513    ///
514    /// `out[i] = if self[i] { truthy[i] } else { falsy[i] }`
515    pub fn select(&self, truthy: &Self, falsy: &Self) -> Self {
516        super::bitmap_ops::select(self, truthy, falsy)
517    }
518
519    /// Select between `truthy` and constant `falsy` based on `self`.
520    ///
521    /// This essentially performs:
522    ///
523    /// `out[i] = if self[i] { truthy[i] } else { falsy }`
524    pub fn select_constant(&self, truthy: &Self, falsy: bool) -> Self {
525        super::bitmap_ops::select_constant(self, truthy, falsy)
526    }
527
528    /// Calculates the number of edges from `0 -> 1` and `1 -> 0`.
529    pub fn num_edges(&self) -> usize {
530        super::bitmap_ops::num_edges(self)
531    }
532
533    /// Returns the number of zero bits from the start before a one bit is seen
534    pub fn leading_zeros(&self) -> usize {
535        utils::leading_zeros(&self.storage, self.offset, self.length)
536    }
537    /// Returns the number of one bits from the start before a zero bit is seen
538    pub fn leading_ones(&self) -> usize {
539        utils::leading_ones(&self.storage, self.offset, self.length)
540    }
541    /// Returns the number of zero bits from the back before a one bit is seen
542    pub fn trailing_zeros(&self) -> usize {
543        utils::trailing_zeros(&self.storage, self.offset, self.length)
544    }
545    /// Returns the number of one bits from the back before a zero bit is seen
546    pub fn trailing_ones(&mut self) -> usize {
547        utils::trailing_ones(&self.storage, self.offset, self.length)
548    }
549
550    /// Take all `0` bits at the start of the [`Bitmap`] before a `1` is seen, returning how many
551    /// bits were taken
552    pub fn take_leading_zeros(&mut self) -> usize {
553        if self
554            .lazy_unset_bits()
555            .is_some_and(|unset_bits| unset_bits == self.length)
556        {
557            let leading_zeros = self.length;
558            self.offset += self.length;
559            self.length = 0;
560            *self.unset_bit_count_cache.get_mut() = 0;
561            return leading_zeros;
562        }
563
564        let leading_zeros = self.leading_zeros();
565        self.offset += leading_zeros;
566        self.length -= leading_zeros;
567        if has_cached_unset_bit_count(*self.unset_bit_count_cache.get_mut()) {
568            *self.unset_bit_count_cache.get_mut() -= leading_zeros as u64;
569        }
570        leading_zeros
571    }
572    /// Take all `1` bits at the start of the [`Bitmap`] before a `0` is seen, returning how many
573    /// bits were taken
574    pub fn take_leading_ones(&mut self) -> usize {
575        if self
576            .lazy_unset_bits()
577            .is_some_and(|unset_bits| unset_bits == 0)
578        {
579            let leading_ones = self.length;
580            self.offset += self.length;
581            self.length = 0;
582            *self.unset_bit_count_cache.get_mut() = 0;
583            return leading_ones;
584        }
585
586        let leading_ones = self.leading_ones();
587        self.offset += leading_ones;
588        self.length -= leading_ones;
589        // @NOTE: the unset_bit_count_cache remains unchanged
590        leading_ones
591    }
592    /// Take all `0` bits at the back of the [`Bitmap`] before a `1` is seen, returning how many
593    /// bits were taken
594    pub fn take_trailing_zeros(&mut self) -> usize {
595        if self
596            .lazy_unset_bits()
597            .is_some_and(|unset_bits| unset_bits == self.length)
598        {
599            let trailing_zeros = self.length;
600            self.length = 0;
601            *self.unset_bit_count_cache.get_mut() = 0;
602            return trailing_zeros;
603        }
604
605        let trailing_zeros = self.trailing_zeros();
606        self.length -= trailing_zeros;
607        if has_cached_unset_bit_count(*self.unset_bit_count_cache.get_mut()) {
608            *self.unset_bit_count_cache.get_mut() -= trailing_zeros as u64;
609        }
610        trailing_zeros
611    }
612    /// Take all `1` bits at the back of the [`Bitmap`] before a `0` is seen, returning how many
613    /// bits were taken
614    pub fn take_trailing_ones(&mut self) -> usize {
615        if self
616            .lazy_unset_bits()
617            .is_some_and(|unset_bits| unset_bits == 0)
618        {
619            let trailing_ones = self.length;
620            self.length = 0;
621            *self.unset_bit_count_cache.get_mut() = 0;
622            return trailing_ones;
623        }
624
625        let trailing_ones = self.trailing_ones();
626        self.length -= trailing_ones;
627        // @NOTE: the unset_bit_count_cache remains unchanged
628        trailing_ones
629    }
630}
631
632impl<P: AsRef<[bool]>> From<P> for Bitmap {
633    fn from(slice: P) -> Self {
634        Self::from_trusted_len_iter(slice.as_ref().iter().copied())
635    }
636}
637
638impl FromIterator<bool> for Bitmap {
639    fn from_iter<I>(iter: I) -> Self
640    where
641        I: IntoIterator<Item = bool>,
642    {
643        MutableBitmap::from_iter(iter).into()
644    }
645}
646
647impl FromTrustedLenIterator<bool> for Bitmap {
648    fn from_iter_trusted_length<T: IntoIterator<Item = bool>>(iter: T) -> Self
649    where
650        T::IntoIter: TrustedLen,
651    {
652        MutableBitmap::from_trusted_len_iter(iter.into_iter()).into()
653    }
654}
655
656impl Bitmap {
657    /// Creates a new [`Bitmap`] from an iterator of booleans.
658    ///
659    /// # Safety
660    /// The iterator must report an accurate length.
661    #[inline]
662    pub unsafe fn from_trusted_len_iter_unchecked<I: Iterator<Item = bool>>(iterator: I) -> Self {
663        MutableBitmap::from_trusted_len_iter_unchecked(iterator).into()
664    }
665
666    /// Creates a new [`Bitmap`] from an iterator of booleans.
667    #[inline]
668    pub fn from_trusted_len_iter<I: TrustedLen<Item = bool>>(iterator: I) -> Self {
669        MutableBitmap::from_trusted_len_iter(iterator).into()
670    }
671
672    /// Creates a new [`Bitmap`] from a fallible iterator of booleans.
673    #[inline]
674    pub fn try_from_trusted_len_iter<E, I: TrustedLen<Item = std::result::Result<bool, E>>>(
675        iterator: I,
676    ) -> std::result::Result<Self, E> {
677        Ok(MutableBitmap::try_from_trusted_len_iter(iterator)?.into())
678    }
679
680    /// Creates a new [`Bitmap`] from a fallible iterator of booleans.
681    ///
682    /// # Safety
683    /// The iterator must report an accurate length.
684    #[inline]
685    pub unsafe fn try_from_trusted_len_iter_unchecked<
686        E,
687        I: Iterator<Item = std::result::Result<bool, E>>,
688    >(
689        iterator: I,
690    ) -> std::result::Result<Self, E> {
691        Ok(MutableBitmap::try_from_trusted_len_iter_unchecked(iterator)?.into())
692    }
693}
694
695impl<'a> IntoIterator for &'a Bitmap {
696    type Item = bool;
697    type IntoIter = BitmapIter<'a>;
698
699    fn into_iter(self) -> Self::IntoIter {
700        BitmapIter::<'a>::new(&self.storage, self.offset, self.length)
701    }
702}
703
704impl IntoIterator for Bitmap {
705    type Item = bool;
706    type IntoIter = IntoIter;
707
708    fn into_iter(self) -> Self::IntoIter {
709        IntoIter::new(self)
710    }
711}
712
713impl Splitable for Bitmap {
714    #[inline(always)]
715    fn check_bound(&self, offset: usize) -> bool {
716        offset <= self.len()
717    }
718
719    unsafe fn _split_at_unchecked(&self, offset: usize) -> (Self, Self) {
720        if offset == 0 {
721            return (Self::new(), self.clone());
722        }
723        if offset == self.len() {
724            return (self.clone(), Self::new());
725        }
726
727        let ubcc = self.unset_bit_count_cache.load(Ordering::Relaxed);
728
729        let lhs_length = offset;
730        let rhs_length = self.length - offset;
731
732        let mut lhs_ubcc = UNKNOWN_BIT_COUNT;
733        let mut rhs_ubcc = UNKNOWN_BIT_COUNT;
734
735        if has_cached_unset_bit_count(ubcc) {
736            if ubcc == 0 {
737                lhs_ubcc = 0;
738                rhs_ubcc = 0;
739            } else if ubcc == self.length as u64 {
740                lhs_ubcc = offset as u64;
741                rhs_ubcc = (self.length - offset) as u64;
742            } else {
743                // If we keep all but a small portion of the array it is worth
744                // doing an eager re-count since we can reuse the old count via the
745                // inclusion-exclusion principle.
746                let small_portion = (self.length / 4).max(32);
747
748                if lhs_length <= rhs_length {
749                    if rhs_length + small_portion >= self.length {
750                        let count = count_zeros(&self.storage, self.offset, lhs_length) as u64;
751                        lhs_ubcc = count;
752                        rhs_ubcc = ubcc - count;
753                    }
754                } else if lhs_length + small_portion >= self.length {
755                    let count = count_zeros(&self.storage, self.offset + offset, rhs_length) as u64;
756                    lhs_ubcc = ubcc - count;
757                    rhs_ubcc = count;
758                }
759            }
760        }
761
762        debug_assert!(lhs_ubcc == UNKNOWN_BIT_COUNT || lhs_ubcc <= ubcc);
763        debug_assert!(rhs_ubcc == UNKNOWN_BIT_COUNT || rhs_ubcc <= ubcc);
764
765        (
766            Self {
767                storage: self.storage.clone(),
768                offset: self.offset,
769                length: lhs_length,
770                unset_bit_count_cache: AtomicU64::new(lhs_ubcc),
771            },
772            Self {
773                storage: self.storage.clone(),
774                offset: self.offset + offset,
775                length: rhs_length,
776                unset_bit_count_cache: AtomicU64::new(rhs_ubcc),
777            },
778        )
779    }
780}