From 86b9f69622badf863df71993e8b1e3468cf92eeb Mon Sep 17 00:00:00 2001 From: Jorge Leitao Date: Fri, 11 Mar 2022 00:12:40 +0100 Subject: [PATCH] rust-lang/portable-simd#260: Add `.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..88270a9b7e9 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 Simd<$type, LANES> + where + LaneCount: SupportedLaneCount, + { + /// Returns the lane-wise minimum with other + #[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 vector 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::::splat(0)); } + fn min() { + let a = Vector::::splat(Scalar::MIN); + let b = Vector::::splat(0); + assert_eq!(a.min(b), a); + let a = Vector::::splat(Scalar::MAX); + let b = Vector::::splat(0); + assert_eq!(a.min(b), b); + } + + fn max() { + let a = Vector::::splat(Scalar::MIN); + let b = Vector::::splat(0); + assert_eq!(a.max(b), b); + let a = Vector::::splat(Scalar::MAX); + let b = Vector::::splat(0); + assert_eq!(a.max(b), a); + } } test_helpers::test_lanes_panic! {