]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | //! Implements portable horizontal bitwise vector reductions. |
2 | #![allow(unused)] | |
3 | ||
4 | macro_rules! impl_reduction_bitwise { | |
5 | ( | |
6 | [$elem_ty:ident; $elem_count:expr]: | |
7 | $id:ident | $ielem_ty:ident | $test_tt:tt | | |
8 | ($convert:expr) | | |
9 | ($true:expr, $false:expr) | |
10 | ) => { | |
11 | impl $id { | |
12 | /// Lane-wise bitwise `and` of the vector elements. | |
13 | /// | |
14 | /// Note: if the vector has one lane, the first element of the | |
15 | /// vector is returned. | |
16 | #[inline] | |
17 | pub fn and(self) -> $elem_ty { | |
18 | #[cfg(not(target_arch = "aarch64"))] | |
19 | { | |
20 | use crate::llvm::simd_reduce_and; | |
21 | let r: $ielem_ty = unsafe { simd_reduce_and(self.0) }; | |
22 | $convert(r) | |
23 | } | |
24 | #[cfg(target_arch = "aarch64")] | |
25 | { | |
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; | |
31 | } | |
32 | x | |
33 | } | |
34 | } | |
35 | ||
36 | /// Lane-wise bitwise `or` of the vector elements. | |
37 | /// | |
38 | /// Note: if the vector has one lane, the first element of the | |
39 | /// vector is returned. | |
40 | #[inline] | |
41 | pub fn or(self) -> $elem_ty { | |
42 | #[cfg(not(target_arch = "aarch64"))] | |
43 | { | |
44 | use crate::llvm::simd_reduce_or; | |
45 | let r: $ielem_ty = unsafe { simd_reduce_or(self.0) }; | |
46 | $convert(r) | |
47 | } | |
48 | #[cfg(target_arch = "aarch64")] | |
49 | { | |
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; | |
55 | } | |
56 | x | |
57 | } | |
58 | } | |
59 | ||
60 | /// Lane-wise bitwise `xor` of the vector elements. | |
61 | /// | |
62 | /// Note: if the vector has one lane, the first element of the | |
63 | /// vector is returned. | |
64 | #[inline] | |
65 | pub fn xor(self) -> $elem_ty { | |
66 | #[cfg(not(target_arch = "aarch64"))] | |
67 | { | |
68 | use crate::llvm::simd_reduce_xor; | |
69 | let r: $ielem_ty = unsafe { simd_reduce_xor(self.0) }; | |
70 | $convert(r) | |
71 | } | |
72 | #[cfg(target_arch = "aarch64")] | |
73 | { | |
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; | |
79 | } | |
80 | x | |
81 | } | |
82 | } | |
83 | } | |
84 | ||
85 | test_if!{ | |
86 | $test_tt: | |
87 | paste::item! { | |
88 | pub mod [<$id _reduction_bitwise>] { | |
89 | use super::*; | |
90 | ||
91 | #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] | |
92 | fn and() { | |
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); | |
99 | if $id::lanes() > 1 { | |
100 | assert_eq!(v.and(), $false); | |
101 | } else { | |
102 | assert_eq!(v.and(), $true); | |
103 | } | |
104 | let v = $id::splat($true); | |
105 | let v = v.replace(0, $false); | |
106 | assert_eq!(v.and(), $false); | |
107 | ||
108 | } | |
109 | #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] | |
110 | fn or() { | |
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); | |
122 | } else { | |
123 | assert_eq!(v.or(), $false); | |
124 | } | |
125 | } | |
126 | #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] | |
127 | fn xor() { | |
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); | |
133 | } else { | |
134 | assert_eq!(v.xor(), $true); | |
135 | } | |
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); | |
143 | } else { | |
144 | assert_eq!(v.xor(), $false); | |
145 | } | |
146 | } | |
147 | } | |
148 | } | |
149 | } | |
150 | }; | |
151 | } |