1 //! Bitmask API
2 
3 macro_rules! impl_bitmask {
4     ($id:ident | $ibitmask_ty:ident | ($set:expr, $clear:expr)
5      | $test_tt:tt) => {
6         impl $id {
7             /// Creates a bitmask with the MSB of each vector lane.
8             ///
9             /// If the vector has less than 8 lanes, the bits that do not
10             /// correspond to any vector lanes are cleared.
11             #[inline]
12             pub fn bitmask(self) -> $ibitmask_ty {
13                 unsafe { codegen::llvm::simd_bitmask(self.0) }
14             }
15         }
16 
17         test_if! {
18             $test_tt:
19             paste::item! {
20                 #[cfg(not(any(
21                     // FIXME: https://github.com/rust-lang-nursery/packed_simd/issues/210
22                     all(target_arch = "mips", target_endian = "big"),
23                     all(target_arch = "mips64", target_endian = "big"),
24                     target_arch = "sparc64",
25                     target_arch = "s390x",
26                 )))]
27                 pub mod [<$id _bitmask>] {
28                     use super::*;
29                     #[cfg_attr(not(target_arch = "wasm32"), test)]
30                     #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
31                     fn bitmask() {
32                         // clear all lanes
33                         let vec = $id::splat($clear as _);
34                         let bitmask: $ibitmask_ty = 0;
35                         assert_eq!(vec.bitmask(), bitmask);
36 
37                         // set even lanes
38                         let mut vec = $id::splat($clear as _);
39                         for i in 0..$id::lanes() {
40                             if i % 2 == 0 {
41                                 vec = vec.replace(i, $set as _);
42                             }
43                         }
44                         // create bitmask with even lanes set:
45                         let mut bitmask: $ibitmask_ty = 0;
46                         for i in 0..$id::lanes() {
47                             if i % 2 == 0 {
48                                 bitmask |= 1 << i;
49                             }
50                         }
51                         assert_eq!(vec.bitmask(), bitmask);
52 
53 
54                         // set odd lanes
55                         let mut vec = $id::splat($clear as _);
56                         for i in 0..$id::lanes() {
57                             if i % 2 != 0 {
58                                 vec = vec.replace(i, $set as _);
59                             }
60                         }
61                         // create bitmask with odd lanes set:
62                         let mut bitmask: $ibitmask_ty = 0;
63                         for i in 0..$id::lanes() {
64                             if i % 2 != 0 {
65                                 bitmask |= 1 << i;
66                             }
67                         }
68                         assert_eq!(vec.bitmask(), bitmask);
69 
70                         // set all lanes
71                         let vec = $id::splat($set as _);
72                         let mut bitmask: $ibitmask_ty = 0;
73                         for i in 0..$id::lanes() {
74                             bitmask |= 1 << i;
75                         }
76                         assert_eq!(vec.bitmask(), bitmask);
77                     }
78                 }
79             }
80         }
81     };
82 }
83