1//! This module hacks in "implicit deref" for Simd's operators.
2//! Ideally, Rust would take care of this itself,
3//! and method calls usually handle the LHS implicitly.
4//! But this is not the case with arithmetic ops.
5use super::*;
6
7macro_rules! deref_lhs {
8 (impl<T, const N: usize> $trait:ident for $simd:ty {
9 fn $call:ident
10 }) => {
11 impl<T, const N: usize> $trait<$simd> for &$simd
12 where
13 T: SimdElement,
14 $simd: $trait<$simd, Output = $simd>,
15 LaneCount<N>: SupportedLaneCount,
16 {
17 type Output = Simd<T, N>;
18
19 #[inline]
20 #[must_use = "operator returns a new vector without mutating the inputs"]
21 fn $call(self, rhs: $simd) -> Self::Output {
22 (*self).$call(rhs)
23 }
24 }
25 };
26}
27
28macro_rules! deref_rhs {
29 (impl<T, const N: usize> $trait:ident for $simd:ty {
30 fn $call:ident
31 }) => {
32 impl<T, const N: usize> $trait<&$simd> for $simd
33 where
34 T: SimdElement,
35 $simd: $trait<$simd, Output = $simd>,
36 LaneCount<N>: SupportedLaneCount,
37 {
38 type Output = Simd<T, N>;
39
40 #[inline]
41 #[must_use = "operator returns a new vector without mutating the inputs"]
42 fn $call(self, rhs: &$simd) -> Self::Output {
43 self.$call(*rhs)
44 }
45 }
46 };
47}
48
49macro_rules! deref_ops {
50 ($(impl<T, const N: usize> $trait:ident for $simd:ty {
51 fn $call:ident
52 })*) => {
53 $(
54 deref_rhs! {
55 impl<T, const N: usize> $trait for $simd {
56 fn $call
57 }
58 }
59 deref_lhs! {
60 impl<T, const N: usize> $trait for $simd {
61 fn $call
62 }
63 }
64 impl<'lhs, 'rhs, T, const N: usize> $trait<&'rhs $simd> for &'lhs $simd
65 where
66 T: SimdElement,
67 $simd: $trait<$simd, Output = $simd>,
68 LaneCount<N>: SupportedLaneCount,
69 {
70 type Output = $simd;
71
72 #[inline]
73 #[must_use = "operator returns a new vector without mutating the inputs"]
74 fn $call(self, rhs: &'rhs $simd) -> Self::Output {
75 (*self).$call(*rhs)
76 }
77 }
78 )*
79 }
80}
81
82deref_ops! {
83 // Arithmetic
84 impl<T, const N: usize> Add for Simd<T, N> {
85 fn add
86 }
87
88 impl<T, const N: usize> Mul for Simd<T, N> {
89 fn mul
90 }
91
92 impl<T, const N: usize> Sub for Simd<T, N> {
93 fn sub
94 }
95
96 impl<T, const N: usize> Div for Simd<T, N> {
97 fn div
98 }
99
100 impl<T, const N: usize> Rem for Simd<T, N> {
101 fn rem
102 }
103
104 // Bitops
105 impl<T, const N: usize> BitAnd for Simd<T, N> {
106 fn bitand
107 }
108
109 impl<T, const N: usize> BitOr for Simd<T, N> {
110 fn bitor
111 }
112
113 impl<T, const N: usize> BitXor for Simd<T, N> {
114 fn bitxor
115 }
116
117 impl<T, const N: usize> Shl for Simd<T, N> {
118 fn shl
119 }
120
121 impl<T, const N: usize> Shr for Simd<T, N> {
122 fn shr
123 }
124}
125