diff options
| author | Caleb Zulawski <caleb.zulawski@gmail.com> | 2022-03-13 19:57:06 +0000 |
|---|---|---|
| committer | Caleb Zulawski <caleb.zulawski@gmail.com> | 2022-03-13 19:57:06 +0000 |
| commit | 2a02c4d9cbee120915535f6fc8379849e10e8373 (patch) | |
| tree | 766429528335276bf38dcb9a94b7f785f877ea80 | |
| parent | 80469c66d650735a0520ae471c5fe5ebaf8971b5 (diff) | |
| download | rust-2a02c4d9cbee120915535f6fc8379849e10e8373.tar.gz rust-2a02c4d9cbee120915535f6fc8379849e10e8373.zip | |
Create SimdFloat trait
| -rw-r--r-- | crates/core_simd/src/vector/float.rs | 106 | ||||
| -rw-r--r-- | crates/core_simd/tests/ops_macros.rs | 3 |
2 files changed, 73 insertions, 36 deletions
diff --git a/crates/core_simd/src/vector/float.rs b/crates/core_simd/src/vector/float.rs index ebe4fbcb6fa..f422d161178 100644 --- a/crates/core_simd/src/vector/float.rs +++ b/crates/core_simd/src/vector/float.rs @@ -134,42 +134,6 @@ macro_rules! impl_float_vector { let magnitude = self.to_bits() & !Self::splat(-0.).to_bits(); Self::from_bits(sign_bit | magnitude) } - - /// Returns the minimum of each lane. - /// - /// If one of the values is `NAN`, then the other value is returned. - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn simd_min(self, other: Self) -> Self { - unsafe { intrinsics::simd_fmin(self, other) } - } - - /// Returns the maximum of each lane. - /// - /// If one of the values is `NAN`, then the other value is returned. - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn simd_max(self, other: Self) -> Self { - unsafe { intrinsics::simd_fmax(self, other) } - } - - /// Restrict each lane to a certain interval unless it is NaN. - /// - /// For each lane in `self`, returns the corresponding lane in `max` if the lane is - /// greater than `max`, and the corresponding lane in `min` if the lane is less - /// than `min`. Otherwise returns the lane in `self`. - #[inline] - #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn simd_clamp(self, min: Self, max: Self) -> Self { - assert!( - min.simd_le(max).all(), - "each lane in `min` must be less than or equal to the corresponding lane in `max`", - ); - let mut x = self; - x = x.simd_lt(min).select(min, x); - x = x.simd_gt(max).select(max, x); - x - } } }; } @@ -197,3 +161,73 @@ pub type f64x4 = Simd<f64, 4>; /// Vector of eight `f64` values pub type f64x8 = Simd<f64, 8>; + +mod sealed { + pub trait Sealed {} +} +use sealed::Sealed; + +/// SIMD operations on vectors of floating point numbers. +pub trait SimdFloat: Sized + Sealed { + /// Returns the minimum of each lane. + /// + /// If one of the values is `NAN`, then the other value is returned. + #[must_use = "method returns a new vector and does not mutate the original value"] + fn simd_min(self, other: Self) -> Self; + + /// Returns the maximum of each lane. + /// + /// If one of the values is `NAN`, then the other value is returned. + #[must_use = "method returns a new vector and does not mutate the original value"] + fn simd_max(self, other: Self) -> Self; + + /// Restrict each lane to a certain interval unless it is NaN. + /// + /// For each lane in `self`, returns the corresponding lane in `max` if the lane is + /// greater than `max`, and the corresponding lane in `min` if the lane is less + /// than `min`. Otherwise returns the lane in `self`. + #[must_use = "method returns a new vector and does not mutate the original value"] + fn simd_clamp(self, min: Self, max: Self) -> Self; +} + +macro_rules! impl_simd_float { + { $($float:ty),* } => { + $( + impl <const LANES: usize> Sealed for Simd<$float, LANES> + where + LaneCount<LANES>: SupportedLaneCount, + { + } + + impl <const LANES: usize> SimdFloat for Simd<$float, LANES> + where + LaneCount<LANES>: SupportedLaneCount, + { + #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] + fn simd_min(self, other: Self) -> Self { + unsafe { intrinsics::simd_fmin(self, other) } + } + + #[inline] + fn simd_max(self, other: Self) -> Self { + unsafe { intrinsics::simd_fmax(self, other) } + } + + #[inline] + fn simd_clamp(self, min: Self, max: Self) -> Self { + assert!( + min.simd_le(max).all(), + "each lane in `min` must be less than or equal to the corresponding lane in `max`", + ); + let mut x = self; + x = x.simd_lt(min).select(min, x); + x = x.simd_gt(max).select(max, x); + x + } + } + )* + } +} + +impl_simd_float! { f32, f64 } diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs index f8389c910c6..47fe49b0982 100644 --- a/crates/core_simd/tests/ops_macros.rs +++ b/crates/core_simd/tests/ops_macros.rs @@ -462,6 +462,7 @@ macro_rules! impl_float_tests { } fn simd_min<const LANES: usize>() { + use core_simd::simd::SimdFloat; // Regular conditions (both values aren't zero) test_helpers::test_binary_elementwise( &Vector::<LANES>::simd_min, @@ -485,6 +486,7 @@ macro_rules! impl_float_tests { } fn simd_max<const LANES: usize>() { + use core_simd::simd::SimdFloat; // Regular conditions (both values aren't zero) test_helpers::test_binary_elementwise( &Vector::<LANES>::simd_max, @@ -508,6 +510,7 @@ macro_rules! impl_float_tests { } fn simd_clamp<const LANES: usize>() { + use core_simd::simd::SimdFloat; test_helpers::test_3(&|value: [Scalar; LANES], mut min: [Scalar; LANES], mut max: [Scalar; LANES]| { for (min, max) in min.iter_mut().zip(max.iter_mut()) { if max < min { |
