polars_core/chunked_array/ops/
bits.rs1use super::BooleanChunked;
2
3fn first_true_idx_impl(ca: &BooleanChunked, invert: bool) -> Option<usize> {
4 let null_count = ca.null_count();
5 if null_count == ca.len() {
6 return None;
7 }
8
9 if (ca.is_sorted_ascending_flag() && invert) || (ca.is_sorted_descending_flag() && !invert) {
10 let idx = ca.first_non_null()?;
11 let value = unsafe { ca.value_unchecked(idx) };
12 return (value != invert).then_some(idx);
13 }
14
15 let invert_mask = if invert { u64::MAX } else { 0 };
16 let mut offset = 0;
17 for arr in ca.downcast_iter() {
18 let values = arr.values();
19 if let Some(validity) = arr.validity() {
20 let mut x_it = values.fast_iter_u56();
21 let mut v_it = validity.fast_iter_u56();
22 for (x, v) in x_it.by_ref().zip(v_it.by_ref()) {
23 let n = ((x ^ invert_mask) & v).trailing_zeros() as usize;
24 if n < 56 {
25 return Some(offset + n);
26 }
27 offset += 56;
28 }
29
30 let (x, rest_len) = x_it.remainder();
31 let (v, _rest_len) = v_it.remainder();
32 let n = ((x ^ invert_mask) & v).trailing_zeros() as usize;
33 if n < rest_len {
34 return Some(offset + n);
35 }
36 offset += rest_len;
37 } else {
38 let n = if invert {
39 values.leading_ones()
40 } else {
41 values.leading_zeros()
42 };
43 if n < values.len() {
44 return Some(offset + n);
45 }
46 offset += values.len();
47 }
48 }
49
50 None
51}
52
53impl BooleanChunked {
54 pub fn num_trues(&self) -> usize {
55 self.downcast_iter()
56 .map(|arr| match arr.validity() {
57 None => arr.values().set_bits(),
58 Some(validity) => arr.values().num_intersections_with(validity),
59 })
60 .sum()
61 }
62
63 pub fn num_falses(&self) -> usize {
64 self.downcast_iter()
65 .map(|arr| match arr.validity() {
66 None => arr.values().unset_bits(),
67 Some(validity) => (!arr.values()).num_intersections_with(validity),
68 })
69 .sum()
70 }
71
72 pub fn first_true_idx(&self) -> Option<usize> {
73 first_true_idx_impl(self, false)
74 }
75
76 pub fn first_false_idx(&self) -> Option<usize> {
77 first_true_idx_impl(self, true)
78 }
79}