Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-arrow/src/bitmap/immutable.rs
8406 views
1
#![allow(unsafe_op_in_unsafe_fn)]
2
use std::ops::Deref;
3
4
use either::Either;
5
use polars_buffer::{Buffer, SharedStorage};
6
use polars_error::{PolarsResult, polars_bail};
7
use polars_utils::relaxed_cell::RelaxedCell;
8
9
use super::utils::{self, BitChunk, BitChunks, BitmapIter, count_zeros, fmt, get_bit_unchecked};
10
use super::{IntoIter, MutableBitmap, chunk_iter_to_vec, num_intersections_with};
11
use crate::array::Splitable;
12
use crate::bitmap::aligned::AlignedBitmapSlice;
13
use crate::bitmap::iterator::{
14
FastU32BitmapIter, FastU56BitmapIter, FastU64BitmapIter, TrueIdxIter,
15
};
16
use crate::bitmap::utils::bytes_for;
17
use crate::legacy::utils::FromTrustedLenIterator;
18
use crate::trusted_len::TrustedLen;
19
20
const 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)]
55
pub 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)]
70
fn has_cached_unset_bit_count(ubcc: u64) -> bool {
71
ubcc >> 63 == 0
72
}
73
74
impl 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
81
pub(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
92
impl 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
611
impl<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
617
impl 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
626
impl 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
635
impl 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
674
impl<'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
683
impl 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
692
impl 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
}
760
761