]> git.proxmox.com Git - rustc.git/blobdiff - vendor/packed_simd/src/api/reductions/bitwise.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / vendor / packed_simd / src / api / reductions / bitwise.rs
diff --git a/vendor/packed_simd/src/api/reductions/bitwise.rs b/vendor/packed_simd/src/api/reductions/bitwise.rs
new file mode 100644 (file)
index 0000000..5bad4f4
--- /dev/null
@@ -0,0 +1,151 @@
+//! Implements portable horizontal bitwise vector reductions.
+#![allow(unused)]
+
+macro_rules! impl_reduction_bitwise {
+    (
+        [$elem_ty:ident; $elem_count:expr]:
+        $id:ident | $ielem_ty:ident | $test_tt:tt |
+        ($convert:expr) |
+        ($true:expr, $false:expr)
+    ) => {
+        impl $id {
+            /// Lane-wise bitwise `and` of the vector elements.
+            ///
+            /// Note: if the vector has one lane, the first element of the
+            /// vector is returned.
+            #[inline]
+            pub fn and(self) -> $elem_ty {
+                #[cfg(not(target_arch = "aarch64"))]
+                {
+                    use crate::llvm::simd_reduce_and;
+                    let r: $ielem_ty = unsafe { simd_reduce_and(self.0) };
+                    $convert(r)
+                }
+                #[cfg(target_arch = "aarch64")]
+                {
+                    // FIXME: broken on aarch64
+                    // https://github.com/rust-lang-nursery/packed_simd/issues/15
+                    let mut x = self.extract(0) as $elem_ty;
+                    for i in 1..$id::lanes() {
+                        x &= self.extract(i) as $elem_ty;
+                    }
+                    x
+                }
+            }
+
+            /// Lane-wise bitwise `or` of the vector elements.
+            ///
+            /// Note: if the vector has one lane, the first element of the
+            /// vector is returned.
+            #[inline]
+            pub fn or(self) -> $elem_ty {
+                #[cfg(not(target_arch = "aarch64"))]
+                {
+                    use crate::llvm::simd_reduce_or;
+                    let r: $ielem_ty = unsafe { simd_reduce_or(self.0) };
+                    $convert(r)
+                }
+                #[cfg(target_arch = "aarch64")]
+                {
+                    // FIXME: broken on aarch64
+                    // https://github.com/rust-lang-nursery/packed_simd/issues/15
+                    let mut x = self.extract(0) as $elem_ty;
+                    for i in 1..$id::lanes() {
+                        x |= self.extract(i) as $elem_ty;
+                    }
+                    x
+                }
+            }
+
+            /// Lane-wise bitwise `xor` of the vector elements.
+            ///
+            /// Note: if the vector has one lane, the first element of the
+            /// vector is returned.
+            #[inline]
+            pub fn xor(self) -> $elem_ty {
+                #[cfg(not(target_arch = "aarch64"))]
+                {
+                    use crate::llvm::simd_reduce_xor;
+                    let r: $ielem_ty = unsafe { simd_reduce_xor(self.0) };
+                    $convert(r)
+                }
+                #[cfg(target_arch = "aarch64")]
+                {
+                    // FIXME: broken on aarch64
+                    // https://github.com/rust-lang-nursery/packed_simd/issues/15
+                    let mut x = self.extract(0) as $elem_ty;
+                    for i in 1..$id::lanes() {
+                        x ^= self.extract(i) as $elem_ty;
+                    }
+                    x
+                }
+            }
+        }
+
+        test_if!{
+            $test_tt:
+            paste::item! {
+                pub mod [<$id _reduction_bitwise>] {
+                    use super::*;
+
+                    #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+                    fn and() {
+                        let v = $id::splat($false);
+                        assert_eq!(v.and(), $false);
+                        let v = $id::splat($true);
+                        assert_eq!(v.and(), $true);
+                        let v = $id::splat($false);
+                        let v = v.replace(0, $true);
+                        if $id::lanes() > 1 {
+                            assert_eq!(v.and(), $false);
+                        } else {
+                            assert_eq!(v.and(), $true);
+                        }
+                        let v = $id::splat($true);
+                        let v = v.replace(0, $false);
+                        assert_eq!(v.and(), $false);
+
+                    }
+                    #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+                    fn or() {
+                        let v = $id::splat($false);
+                        assert_eq!(v.or(), $false);
+                        let v = $id::splat($true);
+                        assert_eq!(v.or(), $true);
+                        let v = $id::splat($false);
+                        let v = v.replace(0, $true);
+                        assert_eq!(v.or(), $true);
+                        let v = $id::splat($true);
+                        let v = v.replace(0, $false);
+                        if $id::lanes() > 1 {
+                            assert_eq!(v.or(), $true);
+                        } else {
+                            assert_eq!(v.or(), $false);
+                        }
+                    }
+                    #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+                    fn xor() {
+                        let v = $id::splat($false);
+                        assert_eq!(v.xor(), $false);
+                        let v = $id::splat($true);
+                        if $id::lanes() > 1 {
+                            assert_eq!(v.xor(), $false);
+                        } else {
+                            assert_eq!(v.xor(), $true);
+                        }
+                        let v = $id::splat($false);
+                        let v = v.replace(0, $true);
+                        assert_eq!(v.xor(), $true);
+                        let v = $id::splat($true);
+                        let v = v.replace(0, $false);
+                        if $id::lanes() > 1 {
+                            assert_eq!(v.xor(), $true);
+                        } else {
+                            assert_eq!(v.xor(), $false);
+                        }
+                    }
+                }
+            }
+        }
+    };
+}