From 14439f890d4958e2d9650339369f137b47ce6e13 Mon Sep 17 00:00:00 2001 From: "Jorge C. Leitao" <jorgecarleitao@gmail.com> Date: Thu, 10 Mar 2022 21:22:20 +0000 Subject: [PATCH 1/2] Added .min and .max for integers --- crates/core_simd/src/comparisons.rs | 34 ++++++++++++++++++++++++++++ crates/core_simd/tests/i16_ops.rs | 15 ++++++++++++ crates/core_simd/tests/ops_macros.rs | 17 ++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/crates/core_simd/src/comparisons.rs b/crates/core_simd/src/comparisons.rs index d024cf4ddbe..0b7bdcd0e48 100644 --- a/crates/core_simd/src/comparisons.rs +++ b/crates/core_simd/src/comparisons.rs @@ -66,3 +66,37 @@ where unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) } } } + +macro_rules! impl_min_max_vector { + { $type:ty } => { + impl<const LANES: usize> Simd<$type, LANES> + where + LaneCount<LANES>: SupportedLaneCount, + { + /// Returns the lane-wise minimum with other + #[must_use = "method returns a new mask and does not mutate the original value"] + #[inline] + pub fn min(self, other: Self) -> Self { + self.lanes_gt(other).select(other, self) + } + + /// Returns the lane-wise maximum with other + #[must_use = "method returns a new mask and does not mutate the original value"] + #[inline] + pub fn max(self, other: Self) -> Self { + self.lanes_lt(other).select(other, self) + } + } + } +} + +impl_min_max_vector!(i8); +impl_min_max_vector!(i16); +impl_min_max_vector!(i32); +impl_min_max_vector!(i64); +impl_min_max_vector!(isize); +impl_min_max_vector!(u8); +impl_min_max_vector!(u16); +impl_min_max_vector!(u32); +impl_min_max_vector!(u64); +impl_min_max_vector!(usize); diff --git a/crates/core_simd/tests/i16_ops.rs b/crates/core_simd/tests/i16_ops.rs index f6c5d74fbbc..cd6cadc2d5e 100644 --- a/crates/core_simd/tests/i16_ops.rs +++ b/crates/core_simd/tests/i16_ops.rs @@ -1,5 +1,20 @@ #![feature(portable_simd)] +use core_simd::i16x2; #[macro_use] mod ops_macros; impl_signed_tests! { i16 } + +#[test] +fn max_is_not_lexicographic() { + let a = i16x2::splat(10); + let b = i16x2::from_array([-4, 12]); + assert_eq!(a.max(b), i16x2::from_array([10, 12])); +} + +#[test] +fn min_is_not_lexicographic() { + let a = i16x2::splat(10); + let b = i16x2::from_array([12, -4]); + assert_eq!(a.min(b), i16x2::from_array([10, -4])); +} diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs index 50f7a4ca170..96da8c1b8dc 100644 --- a/crates/core_simd/tests/ops_macros.rs +++ b/crates/core_simd/tests/ops_macros.rs @@ -222,6 +222,23 @@ macro_rules! impl_signed_tests { assert_eq!(a % b, Vector::<LANES>::splat(0)); } + fn min<const LANES: usize>() { + let a = Vector::<LANES>::splat(Scalar::MIN); + let b = Vector::<LANES>::splat(0); + assert_eq!(a.min(b), a); + let a = Vector::<LANES>::splat(Scalar::MAX); + let b = Vector::<LANES>::splat(0); + assert_eq!(a.min(b), b); + } + + fn max<const LANES: usize>() { + let a = Vector::<LANES>::splat(Scalar::MIN); + let b = Vector::<LANES>::splat(0); + assert_eq!(a.max(b), b); + let a = Vector::<LANES>::splat(Scalar::MAX); + let b = Vector::<LANES>::splat(0); + assert_eq!(a.max(b), a); + } } test_helpers::test_lanes_panic! { From 5b253df9be3511603daf9e087f43be4a63f5ff5a Mon Sep 17 00:00:00 2001 From: "Jorge C. Leitao" <jorgecarleitao@gmail.com> Date: Thu, 10 Mar 2022 21:44:51 +0000 Subject: [PATCH 2/2] Fixed comment --- crates/core_simd/src/comparisons.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core_simd/src/comparisons.rs b/crates/core_simd/src/comparisons.rs index 0b7bdcd0e48..88270a9b7e9 100644 --- a/crates/core_simd/src/comparisons.rs +++ b/crates/core_simd/src/comparisons.rs @@ -74,14 +74,14 @@ macro_rules! impl_min_max_vector { LaneCount<LANES>: SupportedLaneCount, { /// Returns the lane-wise minimum with other - #[must_use = "method returns a new mask and does not mutate the original value"] + #[must_use = "method returns a new vector and does not mutate the original value"] #[inline] pub fn min(self, other: Self) -> Self { self.lanes_gt(other).select(other, self) } /// Returns the lane-wise maximum with other - #[must_use = "method returns a new mask and does not mutate the original value"] + #[must_use = "method returns a new vector and does not mutate the original value"] #[inline] pub fn max(self, other: Self) -> Self { self.lanes_lt(other).select(other, self)