1 //! Implements portable horizontal bitwise vector reductions.
4 macro_rules
! impl_reduction_bitwise
{
6 [$elem_ty
:ident
; $elem_count
:expr
]:
7 $id
:ident
| $ielem_ty
:ident
| $test_tt
:tt
|
9 ($
true:expr
, $
false:expr
)
12 /// Lane-wise bitwise `and` of the vector elements.
14 /// Note: if the vector has one lane, the first element of the
15 /// vector is returned.
17 pub fn and(self) -> $elem_ty
{
18 #[cfg(not(target_arch = "aarch64"))]
20 use crate::llvm
::simd_reduce_and
;
21 let r
: $ielem_ty
= unsafe { simd_reduce_and(self.0) }
;
24 #[cfg(target_arch = "aarch64")]
26 // FIXME: broken on aarch64
27 // https://github.com/rust-lang-nursery/packed_simd/issues/15
28 let mut x
= self.extract(0) as $elem_ty
;
29 for i
in 1..$id
::lanes() {
30 x
&= self.extract(i
) as $elem_ty
;
36 /// Lane-wise bitwise `or` of the vector elements.
38 /// Note: if the vector has one lane, the first element of the
39 /// vector is returned.
41 pub fn or(self) -> $elem_ty
{
42 #[cfg(not(target_arch = "aarch64"))]
44 use crate::llvm
::simd_reduce_or
;
45 let r
: $ielem_ty
= unsafe { simd_reduce_or(self.0) }
;
48 #[cfg(target_arch = "aarch64")]
50 // FIXME: broken on aarch64
51 // https://github.com/rust-lang-nursery/packed_simd/issues/15
52 let mut x
= self.extract(0) as $elem_ty
;
53 for i
in 1..$id
::lanes() {
54 x
|= self.extract(i
) as $elem_ty
;
60 /// Lane-wise bitwise `xor` of the vector elements.
62 /// Note: if the vector has one lane, the first element of the
63 /// vector is returned.
65 pub fn xor(self) -> $elem_ty
{
66 #[cfg(not(target_arch = "aarch64"))]
68 use crate::llvm
::simd_reduce_xor
;
69 let r
: $ielem_ty
= unsafe { simd_reduce_xor(self.0) }
;
72 #[cfg(target_arch = "aarch64")]
74 // FIXME: broken on aarch64
75 // https://github.com/rust-lang-nursery/packed_simd/issues/15
76 let mut x
= self.extract(0) as $elem_ty
;
77 for i
in 1..$id
::lanes() {
78 x ^
= self.extract(i
) as $elem_ty
;
88 pub mod [<$id _reduction_bitwise
>] {
91 #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
93 let v
= $id
::splat($
false);
94 assert_eq
!(v
.and(), $
false);
95 let v
= $id
::splat($
true);
96 assert_eq
!(v
.and(), $
true);
97 let v
= $id
::splat($
false);
98 let v
= v
.replace(0, $
true);
100 assert_eq
!(v
.and(), $
false);
102 assert_eq
!(v
.and(), $
true);
104 let v
= $id
::splat($
true);
105 let v
= v
.replace(0, $
false);
106 assert_eq
!(v
.and(), $
false);
109 #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
111 let v
= $id
::splat($
false);
112 assert_eq
!(v
.or(), $
false);
113 let v
= $id
::splat($
true);
114 assert_eq
!(v
.or(), $
true);
115 let v
= $id
::splat($
false);
116 let v
= v
.replace(0, $
true);
117 assert_eq
!(v
.or(), $
true);
118 let v
= $id
::splat($
true);
119 let v
= v
.replace(0, $
false);
120 if $id
::lanes() > 1 {
121 assert_eq
!(v
.or(), $
true);
123 assert_eq
!(v
.or(), $
false);
126 #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
128 let v
= $id
::splat($
false);
129 assert_eq
!(v
.xor(), $
false);
130 let v
= $id
::splat($
true);
131 if $id
::lanes() > 1 {
132 assert_eq
!(v
.xor(), $
false);
134 assert_eq
!(v
.xor(), $
true);
136 let v
= $id
::splat($
false);
137 let v
= v
.replace(0, $
true);
138 assert_eq
!(v
.xor(), $
true);
139 let v
= $id
::splat($
true);
140 let v
= v
.replace(0, $
false);
141 if $id
::lanes() > 1 {
142 assert_eq
!(v
.xor(), $
true);
144 assert_eq
!(v
.xor(), $
false);