rust-lang/portable-simd#260: Add .min and .max for integers

This commit is contained in:
Jorge Leitao 2022-03-11 00:12:40 +01:00 committed by GitHub
parent 89bc660d21
commit 86b9f69622
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 0 deletions

View File

@ -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 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);

View File

@ -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]));
}

View File

@ -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! {