about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2021-04-22 04:09:56 +0000
committerCaleb Zulawski <caleb.zulawski@gmail.com>2021-05-01 15:21:41 +0000
commit563d2a2cfce14b5807bb6cacce336e0e87950289 (patch)
tree37fdf616b0f8b24ac6b315b446f41c81168c5ec2
parent9a063bc2ed892315c8317f08f263466af35e9279 (diff)
downloadrust-563d2a2cfce14b5807bb6cacce336e0e87950289.tar.gz
rust-563d2a2cfce14b5807bb6cacce336e0e87950289.zip
Add select function
-rw-r--r--crates/core_simd/src/intrinsics.rs1
-rw-r--r--crates/core_simd/src/lib.rs3
-rw-r--r--crates/core_simd/src/select.rs52
3 files changed, 56 insertions, 0 deletions
diff --git a/crates/core_simd/src/intrinsics.rs b/crates/core_simd/src/intrinsics.rs
index 8cbb0cbccf7..798c4461f79 100644
--- a/crates/core_simd/src/intrinsics.rs
+++ b/crates/core_simd/src/intrinsics.rs
@@ -81,6 +81,7 @@ extern "platform-intrinsic" {
     pub(crate) fn simd_bitmask<T, U>(x: T) -> U;
 
     // select
+    pub(crate) fn simd_select<T, U>(m: T, a: U, b: U) -> U;
     pub(crate) fn simd_select_bitmask<T, U>(m: T, a: U, b: U) -> U;
 }
 
diff --git a/crates/core_simd/src/lib.rs b/crates/core_simd/src/lib.rs
index 2d4176ce342..3489dfb5f3e 100644
--- a/crates/core_simd/src/lib.rs
+++ b/crates/core_simd/src/lib.rs
@@ -14,6 +14,9 @@ mod transmute;
 #[macro_use]
 mod reduction;
 
+mod select;
+pub use select::Select;
+
 mod comparisons;
 mod fmt;
 mod intrinsics;
diff --git a/crates/core_simd/src/select.rs b/crates/core_simd/src/select.rs
new file mode 100644
index 00000000000..66b0839cf24
--- /dev/null
+++ b/crates/core_simd/src/select.rs
@@ -0,0 +1,52 @@
+mod sealed {
+pub trait Sealed {}
+}
+use sealed::Sealed;
+
+/// Supporting trait for vector `select` function
+pub trait Select<Mask>: Sealed {}
+
+macro_rules! impl_select {
+    {
+        $mask:ident ($bits_ty:ident): $($type:ident),*
+    } => {
+        $(
+        impl<const LANES: usize> Sealed for crate::$type<LANES> where Self: crate::LanesAtMost32 {}
+        impl<const LANES: usize> Select<crate::$mask<LANES>> for crate::$type<LANES>
+        where
+            crate::$mask<LANES>: crate::Mask,
+            crate::$bits_ty<LANES>: crate::LanesAtMost32,
+            Self: crate::LanesAtMost32,
+        {}
+        )*
+
+        impl<const LANES: usize> crate::$mask<LANES>
+        where
+            Self: crate::Mask,
+            crate::$bits_ty<LANES>: crate::LanesAtMost32,
+        {
+            /// Choose lanes from two vectors.
+            ///
+            /// For each lane in the mask, choose the corresponding lane from `true_values` if
+            /// that lane mask is true, and `false_values` if that lane mask is false.
+            ///
+            /// ```
+            /// # use core_simd::{Mask32, SimdI32};
+            /// let a = SimdI32::from_array([0, 1, 2, 3]);
+            /// let b = SimdI32::from_array([4, 5, 6, 7]);
+            /// let mask = Mask32::from_array([true, false, false, true]);
+            /// let c = mask.select(a, b);
+            /// assert_eq!(c.to_array(), [0, 5, 6, 3]);
+            /// ```
+            pub fn select<S: Select<Self>>(self, true_values: S, false_values: S) -> S {
+                unsafe { crate::intrinsics::simd_select(self.to_int(), true_values, false_values) }
+            }
+        }
+    }
+}
+
+impl_select! { Mask8 (SimdI8): SimdU8, SimdI8 }
+impl_select! { Mask16 (SimdI16): SimdU16, SimdI16 }
+impl_select! { Mask32 (SimdI32): SimdU32, SimdI32, SimdF32}
+impl_select! { Mask64 (SimdI64): SimdU64, SimdI64, SimdF64}
+impl_select! { MaskSize (SimdIsize): SimdUsize, SimdIsize }