polars_compute/if_then_else/
scalar.rs

1use std::mem::MaybeUninit;
2
3pub fn if_then_else_scalar_rest<T: Copy>(
4    mask: u64,
5    if_true: &[T],
6    if_false: &[T],
7    out: &mut [MaybeUninit<T>],
8) {
9    assert!(if_true.len() == out.len()); // Removes bounds checks in inner loop.
10    let true_it = if_true.iter().copied();
11    let false_it = if_false.iter().copied();
12    for (i, (t, f)) in true_it.zip(false_it).enumerate() {
13        let src = if (mask >> i) & 1 != 0 { t } else { f };
14        out[i] = MaybeUninit::new(src);
15    }
16}
17
18pub fn if_then_else_broadcast_false_scalar_rest<T: Copy>(
19    mask: u64,
20    if_true: &[T],
21    if_false: T,
22    out: &mut [MaybeUninit<T>],
23) {
24    assert!(if_true.len() == out.len()); // Removes bounds checks in inner loop.
25    let true_it = if_true.iter().copied();
26    for (i, t) in true_it.enumerate() {
27        let src = if (mask >> i) & 1 != 0 { t } else { if_false };
28        out[i] = MaybeUninit::new(src);
29    }
30}
31
32pub fn if_then_else_broadcast_both_scalar_rest<T: Copy>(
33    mask: u64,
34    if_true: T,
35    if_false: T,
36    out: &mut [MaybeUninit<T>],
37) {
38    for (i, dst) in out.iter_mut().enumerate() {
39        let src = if (mask >> i) & 1 != 0 {
40            if_true
41        } else {
42            if_false
43        };
44        *dst = MaybeUninit::new(src);
45    }
46}
47
48pub fn if_then_else_scalar_64<T: Copy>(
49    mask: u64,
50    if_true: &[T; 64],
51    if_false: &[T; 64],
52    out: &mut [MaybeUninit<T>; 64],
53) {
54    // This generated the best autovectorized code on ARM, and branchless everywhere.
55    if_then_else_scalar_rest(mask, if_true, if_false, out)
56}
57
58pub fn if_then_else_broadcast_false_scalar_64<T: Copy>(
59    mask: u64,
60    if_true: &[T; 64],
61    if_false: T,
62    out: &mut [MaybeUninit<T>; 64],
63) {
64    // This generated the best autovectorized code on ARM, and branchless everywhere.
65    if_then_else_broadcast_false_scalar_rest(mask, if_true, if_false, out)
66}
67
68pub fn if_then_else_broadcast_both_scalar_64<T: Copy>(
69    mask: u64,
70    if_true: T,
71    if_false: T,
72    out: &mut [MaybeUninit<T>; 64],
73) {
74    // This generated the best autovectorized code on ARM, and branchless everywhere.
75    if_then_else_broadcast_both_scalar_rest(mask, if_true, if_false, out)
76}