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