about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee Young <workingjubilee@gmail.com>2021-11-23 16:15:19 -0800
committerJubilee Young <workingjubilee@gmail.com>2021-11-23 18:11:48 -0800
commit0a6992f5bfb6a2e879d23ff015ae27e2534095aa (patch)
tree9ca4cca94234cffc5d5abf34a2f66ad3581d7c7b
parentb8d6b6844602f80af79cd96401339ec594d472d8 (diff)
downloadrust-0a6992f5bfb6a2e879d23ff015ae27e2534095aa.tar.gz
rust-0a6992f5bfb6a2e879d23ff015ae27e2534095aa.zip
impl deref.rs<&Self> for Simd<T, _>
Instead of implementing each "deref" pattern for every single scalar,
we can use type parameters for Simd operating on &Self.
We can use a macro, but keep it cleaner and more explicit.
-rw-r--r--crates/core_simd/src/ops.rs62
-rw-r--r--crates/core_simd/src/ops/deref.rs70
2 files changed, 76 insertions, 56 deletions
diff --git a/crates/core_simd/src/ops.rs b/crates/core_simd/src/ops.rs
index 5d7af474caf..f5683ebb2c0 100644
--- a/crates/core_simd/src/ops.rs
+++ b/crates/core_simd/src/ops.rs
@@ -1,5 +1,11 @@
 use crate::simd::intrinsics;
 use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
+use core::ops::{Add, Mul};
+use core::ops::{BitAnd, BitOr, BitXor};
+use core::ops::{Div, Rem, Sub};
+use core::ops::{Shl, Shr};
+
+mod deref;
 
 impl<I, T, const LANES: usize> core::ops::Index<I> for Simd<T, LANES>
 where
@@ -57,42 +63,6 @@ macro_rules! impl_ref_ops {
             $(#[$attrs])*
             fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body
         }
-
-        impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for $type
-        where
-            LaneCount<$lanes2>: SupportedLaneCount,
-        {
-            type Output = <$type as core::ops::$trait<$rhs>>::Output;
-
-            $(#[$attrs])*
-            fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output {
-                core::ops::$trait::$fn($self_tok, *$rhs_arg)
-            }
-        }
-
-        impl<const $lanes: usize> core::ops::$trait<$rhs> for &'_ $type
-        where
-            LaneCount<$lanes2>: SupportedLaneCount,
-        {
-            type Output = <$type as core::ops::$trait<$rhs>>::Output;
-
-            $(#[$attrs])*
-            fn $fn($self_tok, $rhs_arg: $rhs) -> Self::Output {
-                core::ops::$trait::$fn(*$self_tok, $rhs_arg)
-            }
-        }
-
-        impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for &'_ $type
-        where
-            LaneCount<$lanes2>: SupportedLaneCount,
-        {
-            type Output = <$type as core::ops::$trait<$rhs>>::Output;
-
-            $(#[$attrs])*
-            fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output {
-                core::ops::$trait::$fn(*$self_tok, *$rhs_arg)
-            }
-        }
     };
 
     // binary assignment op
@@ -112,16 +82,6 @@ macro_rules! impl_ref_ops {
             $(#[$attrs])*
             fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body
         }
-
-        impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for $type
-        where
-            LaneCount<$lanes2>: SupportedLaneCount,
-        {
-            $(#[$attrs])*
-            fn $fn(&mut $self_tok, $rhs_arg: &$rhs_arg_ty) {
-                core::ops::$trait::$fn($self_tok, *$rhs_arg)
-            }
-        }
     };
 
     // unary op
@@ -141,16 +101,6 @@ macro_rules! impl_ref_ops {
             type Output = $output;
             fn $fn($self_tok) -> Self::Output $body
         }
-
-        impl<const $lanes: usize> core::ops::$trait for &'_ $type
-        where
-            LaneCount<$lanes2>: SupportedLaneCount,
-        {
-            type Output = <$type as core::ops::$trait>::Output;
-            fn $fn($self_tok) -> Self::Output {
-                core::ops::$trait::$fn(*$self_tok)
-            }
-        }
     }
 }
 
diff --git a/crates/core_simd/src/ops/deref.rs b/crates/core_simd/src/ops/deref.rs
new file mode 100644
index 00000000000..1138b9494f6
--- /dev/null
+++ b/crates/core_simd/src/ops/deref.rs
@@ -0,0 +1,70 @@
+//! This module hacks in "implicit deref" for Simd's operators.
+//! Ideally, Rust would take care of this itself,
+//! and method calls usually handle the LHS implicitly.
+//! So, we'll manually deref the RHS.
+use super::*;
+
+macro_rules! deref_ops {
+    ($(impl<T, const LANES: usize> $trait:ident<&Self> for Simd<T, LANES> {
+            fn $call:ident(rhs: &Self)
+        })*) => {
+        $(impl<T, const LANES: usize> $trait<&Self> for Simd<T, LANES>
+        where
+            Self: $trait<Self, Output = Self>,
+            T: SimdElement,
+            LaneCount<LANES>: SupportedLaneCount,
+        {
+            type Output = Self;
+
+            #[inline]
+            #[must_use = "operator returns a new vector without mutating the inputs"]
+            fn $call(self, rhs: &Self) -> Self::Output {
+                self.$call(*rhs)
+            }
+        })*
+    }
+}
+
+deref_ops! {
+    // Arithmetic
+    impl<T, const LANES: usize> Add<&Self> for Simd<T, LANES> {
+        fn add(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> Mul<&Self> for Simd<T, LANES> {
+        fn mul(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> Sub<&Self> for Simd<T, LANES> {
+        fn sub(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> Div<&Self> for Simd<T, LANES> {
+        fn div(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> Rem<&Self> for Simd<T, LANES> {
+        fn rem(rhs: &Self)
+    }
+
+    // Bitops
+    impl<T, const LANES: usize> BitAnd<&Self> for Simd<T, LANES> {
+        fn bitand(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> BitOr<&Self> for Simd<T, LANES> {
+        fn bitor(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> BitXor<&Self> for Simd<T, LANES> {
+        fn bitxor(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> Shl<&Self> for Simd<T, LANES> {
+        fn shl(rhs: &Self)
+    }
+
+    impl<T, const LANES: usize> Shr<&Self> for Simd<T, LANES> {
+        fn shr(rhs: &Self)
+    }
+}