]> git.lizzy.rs Git - rust.git/commitdiff
impl unary.rs for Simd<{i,u}{8,16,32,64,size}, _>
authorJubilee Young <workingjubilee@gmail.com>
Wed, 24 Nov 2021 01:36:54 +0000 (17:36 -0800)
committerJubilee Young <workingjubilee@gmail.com>
Wed, 1 Dec 2021 23:40:46 +0000 (15:40 -0800)
In order to assure type soundness, these "base" impls
need to go directly on Simd<T, _> for every scalar type argument.
A bit of cleanup of ops.rs is still warranted.

crates/core_simd/src/ops.rs
crates/core_simd/src/ops/unary.rs [new file with mode: 0644]

index aee5a111a82f26ed0ca792714aaf8fd4c1a7b4ec..b7da4f341d171716125678cc03a560703ad275b3 100644 (file)
@@ -7,6 +7,7 @@
 
 mod assign;
 mod deref;
+mod unary;
 
 impl<I, T, const LANES: usize> core::ops::Index<I> for Simd<T, LANES>
 where
@@ -65,25 +66,6 @@ impl<const $lanes: usize> core::ops::$trait<$rhs> for $type
             fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body
         }
     };
-
-    // unary op
-    {
-        impl<const $lanes:ident: usize> core::ops::$trait:ident for $type:ty
-        where
-            LaneCount<$lanes2:ident>: SupportedLaneCount,
-        {
-            type Output = $output:ty;
-            fn $fn:ident($self_tok:ident) -> Self::Output $body:tt
-        }
-    } => {
-        impl<const $lanes: usize> core::ops::$trait for $type
-        where
-            LaneCount<$lanes2>: SupportedLaneCount,
-        {
-            type Output = $output;
-            fn $fn($self_tok) -> Self::Output $body
-        }
-    }
 }
 
 /// Automatically implements operators over vectors and scalars for a particular vector.
@@ -119,34 +101,6 @@ macro_rules! impl_op {
         impl_op! { @binary $scalar, BitXor::bitxor, simd_xor }
     };
 
-    { impl Not for $scalar:ty } => {
-        impl_ref_ops! {
-            impl<const LANES: usize> core::ops::Not for Simd<$scalar, LANES>
-            where
-                LaneCount<LANES>: SupportedLaneCount,
-            {
-                type Output = Self;
-                fn not(self) -> Self::Output {
-                    self ^ Self::splat(!<$scalar>::default())
-                }
-            }
-        }
-    };
-
-    { impl Neg for $scalar:ty } => {
-        impl_ref_ops! {
-            impl<const LANES: usize> core::ops::Neg for Simd<$scalar, LANES>
-            where
-                LaneCount<LANES>: SupportedLaneCount,
-            {
-                type Output = Self;
-                fn neg(self) -> Self::Output {
-                    unsafe { intrinsics::simd_neg(self) }
-                }
-            }
-        }
-    };
-
     // generic binary op with assignment when output is `Self`
     { @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $intrinsic:ident } => {
         impl_ref_ops! {
@@ -204,7 +158,6 @@ macro_rules! impl_float_ops {
             impl_op! { impl Mul for $scalar }
             impl_op! { impl Div for $scalar }
             impl_op! { impl Rem for $scalar }
-            impl_op! { impl Neg for $scalar }
         )*
     };
 }
@@ -219,7 +172,6 @@ macro_rules! impl_unsigned_int_ops {
             impl_op! { impl BitAnd for $scalar }
             impl_op! { impl BitOr  for $scalar }
             impl_op! { impl BitXor for $scalar }
-            impl_op! { impl Not for $scalar }
 
             // Integers panic on divide by 0
             impl_ref_ops! {
@@ -441,9 +393,6 @@ fn shr(self, rhs: $scalar) -> Self::Output {
 macro_rules! impl_signed_int_ops {
     { $($scalar:ty),* } => {
         impl_unsigned_int_ops! { $($scalar),* }
-        $( // scalar
-            impl_op! { impl Neg for $scalar }
-        )*
     };
 }
 
diff --git a/crates/core_simd/src/ops/unary.rs b/crates/core_simd/src/ops/unary.rs
new file mode 100644 (file)
index 0000000..4ebea56
--- /dev/null
@@ -0,0 +1,77 @@
+use crate::simd::intrinsics;
+use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
+use core::ops::{Neg, Not}; // unary ops
+
+macro_rules! neg {
+    ($(impl<const LANES: usize> Neg for Simd<$scalar:ty, LANES>)*) => {
+        $(impl<const LANES: usize> Neg for Simd<$scalar, LANES>
+        where
+            $scalar: SimdElement,
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            type Output = Self;
+
+            #[inline]
+            #[must_use = "operator returns a new vector without mutating the input"]
+            fn neg(self) -> Self::Output {
+                unsafe { intrinsics::simd_neg(self) }
+            }
+        })*
+    }
+}
+
+neg! {
+    impl<const LANES: usize> Neg for Simd<f32, LANES>
+
+    impl<const LANES: usize> Neg for Simd<f64, LANES>
+
+    impl<const LANES: usize> Neg for Simd<i8, LANES>
+
+    impl<const LANES: usize> Neg for Simd<i16, LANES>
+
+    impl<const LANES: usize> Neg for Simd<i32, LANES>
+
+    impl<const LANES: usize> Neg for Simd<i64, LANES>
+
+    impl<const LANES: usize> Neg for Simd<isize, LANES>
+}
+
+macro_rules! not {
+    ($(impl<const LANES: usize> Not for Simd<$scalar:ty, LANES>)*) => {
+        $(impl<const LANES: usize> Not for Simd<$scalar, LANES>
+        where
+            $scalar: SimdElement,
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            type Output = Self;
+
+            #[inline]
+            #[must_use = "operator returns a new vector without mutating the input"]
+            fn not(self) -> Self::Output {
+                self ^ (Simd::splat(!(0 as $scalar)))
+            }
+        })*
+    }
+}
+
+not! {
+    impl<const LANES: usize> Not for Simd<i8, LANES>
+
+    impl<const LANES: usize> Not for Simd<i16, LANES>
+
+    impl<const LANES: usize> Not for Simd<i32, LANES>
+
+    impl<const LANES: usize> Not for Simd<i64, LANES>
+
+    impl<const LANES: usize> Not for Simd<isize, LANES>
+
+    impl<const LANES: usize> Not for Simd<u8, LANES>
+
+    impl<const LANES: usize> Not for Simd<u16, LANES>
+
+    impl<const LANES: usize> Not for Simd<u32, LANES>
+
+    impl<const LANES: usize> Not for Simd<u64, LANES>
+
+    impl<const LANES: usize> Not for Simd<usize, LANES>
+}