Skip to main content

polars_arrow/bitmap/
immutable.rs

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