simba/simd/simd_bool.rs
1use crate::simd::SimdValue;
2use std::ops::{BitAnd, BitOr, BitXor, Not};
3
4/// Lane-wise generalization of `bool` for SIMD booleans.
5///
6/// This trait implemented by `bool` as well as SIMD boolean types like `portable_simd::mask32x4`.
7/// It is designed to abstract the behavior of booleans so it can work with multi-lane boolean
8/// values in an AoSoA setting.
9pub trait SimdBool:
10 Copy
11 + BitAnd<Self, Output = Self>
12 + BitOr<Self, Output = Self>
13 + BitXor<Self, Output = Self>
14 + Not<Output = Self>
15{
16 /// A bit mask representing the boolean state of each lanes of `self`.
17 ///
18 /// The `i-th` bit of the result is `1` iff. the `i-th` lane of `self` is `true`.
19 fn bitmask(self) -> u64;
20 /// Lane-wise bitwise and of the vector elements.
21 fn and(self) -> bool;
22 /// Lane-wise bitwise or of the vector elements.
23 fn or(self) -> bool;
24 /// Lane-wise bitwise xor of the vector elements.
25 fn xor(self) -> bool;
26 /// Are all vector lanes true?
27 fn all(self) -> bool;
28 /// Is any vector lane true?
29 fn any(self) -> bool;
30 /// Are all vector lanes false?
31 fn none(self) -> bool;
32 /// Merges the value of `if_value()` and `else_value()` depending on the lanes of `self`.
33 ///
34 /// - For each lane of `self` containing `1`, the result will contain the corresponding lane of `if_value()`.
35 /// - For each lane of `self` containing `0`, the result will contain the corresponding lane of `else_value()`.
36 ///
37 /// The implementor of this trait is free to choose on what cases `if_value` and `else_value` are actually
38 /// called.
39 fn if_else<Res: SimdValue<SimdBool = Self>>(
40 self,
41 if_value: impl FnOnce() -> Res,
42 else_value: impl FnOnce() -> Res,
43 ) -> Res;
44
45 /// Merges the value of `if_value()` and `else_if.1()` and `else_value()` depending on the lanes of `self` and `else_if.0()`.
46 ///
47 /// - For each lane of `self` containing `1`, the result will contain the corresponding lane of `if_value()`.
48 /// - For each lane of `self` containing `0` but with a corresponding lane of `else_if.0()` containing `1`, the result will contain the corresponding lane of `else_if.1()`.
49 /// - For each lane of `self` containing `0` but with a corresponding lane of `else_if.0()` containing `0`, the result will contain the corresponding lane of `else_value()`.
50 ///
51 /// The implementor of this trait is free to choose on what cases any of those closures are implemented.
52 fn if_else2<Res: SimdValue<SimdBool = Self>>(
53 self,
54 if_value: impl FnOnce() -> Res,
55 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
56 else_value: impl FnOnce() -> Res,
57 ) -> Res;
58
59 /// Merges the value of `if_value()` and `else_if.1()` and `else_else_if.1()` and `else_value()` depending on the lanes of `self` and `else_if.0()` and `else_else_if.0()`.
60 ///
61 /// - For each lane of `self` containing `1`, the result will contain the corresponding lane of `if_value()`.
62 /// - For each lane of `self` containing `0` but with a corresponding lane of `else_if.0()` containing `1`, the result will contain the corresponding lane of `else_if.1()`.
63 /// - For each lane of `self` containing `0` and `else_if.0()` containing `0` and `else_else_if.0()` containing `1`, the result will contain the corresponding lane of `else_else_if.1()`.
64 /// - Other lanes will contain the corresponding lane of `else_value()`.
65 ///
66 /// The implementor of this trait is free to choose on what cases any of those closures are implemented.
67 fn if_else3<Res: SimdValue<SimdBool = Self>>(
68 self,
69 if_value: impl FnOnce() -> Res,
70 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
71 else_else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
72 else_value: impl FnOnce() -> Res,
73 ) -> Res;
74}
75
76impl SimdBool for bool {
77 #[inline(always)]
78 fn bitmask(self) -> u64 {
79 self as u64
80 }
81
82 #[inline(always)]
83 fn and(self) -> bool {
84 self
85 }
86
87 #[inline(always)]
88 fn or(self) -> bool {
89 self
90 }
91
92 #[inline(always)]
93 fn xor(self) -> bool {
94 self
95 }
96
97 #[inline(always)]
98 fn all(self) -> bool {
99 self
100 }
101
102 #[inline(always)]
103 fn any(self) -> bool {
104 self
105 }
106
107 #[inline(always)]
108 fn none(self) -> bool {
109 !self
110 }
111
112 #[inline(always)]
113 fn if_else<Res: SimdValue<SimdBool = Self>>(
114 self,
115 if_value: impl FnOnce() -> Res,
116 else_value: impl FnOnce() -> Res,
117 ) -> Res {
118 if self {
119 if_value()
120 } else {
121 else_value()
122 }
123 }
124
125 #[inline(always)]
126 fn if_else2<Res: SimdValue<SimdBool = Self>>(
127 self,
128 if_value: impl FnOnce() -> Res,
129 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
130 else_value: impl FnOnce() -> Res,
131 ) -> Res {
132 if self {
133 if_value()
134 } else if else_if.0() {
135 else_if.1()
136 } else {
137 else_value()
138 }
139 }
140
141 #[inline(always)]
142 fn if_else3<Res: SimdValue<SimdBool = Self>>(
143 self,
144 if_value: impl FnOnce() -> Res,
145 else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
146 else_else_if: (impl FnOnce() -> Self, impl FnOnce() -> Res),
147 else_value: impl FnOnce() -> Res,
148 ) -> Res {
149 if self {
150 if_value()
151 } else if else_if.0() {
152 else_if.1()
153 } else if else_else_if.0() {
154 else_else_if.1()
155 } else {
156 else_value()
157 }
158 }
159}