about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2022-03-13 19:57:06 +0000
committerCaleb Zulawski <caleb.zulawski@gmail.com>2022-03-13 19:57:06 +0000
commit2a02c4d9cbee120915535f6fc8379849e10e8373 (patch)
tree766429528335276bf38dcb9a94b7f785f877ea80
parent80469c66d650735a0520ae471c5fe5ebaf8971b5 (diff)
downloadrust-2a02c4d9cbee120915535f6fc8379849e10e8373.tar.gz
rust-2a02c4d9cbee120915535f6fc8379849e10e8373.zip
Create SimdFloat trait
-rw-r--r--crates/core_simd/src/vector/float.rs106
-rw-r--r--crates/core_simd/tests/ops_macros.rs3
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 {