//! 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. //! But this is not the case with arithmetic ops. use super::*; macro_rules! deref_lhs { (impl $trait:ident for $simd:ty { fn $call:ident }) => { impl $trait<$simd> for &$simd where T: SimdElement, $simd: $trait<$simd, Output = $simd>, LaneCount: SupportedLaneCount, { type Output = Simd; #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] fn $call(self, rhs: $simd) -> Self::Output { (*self).$call(rhs) } } }; } macro_rules! deref_rhs { (impl $trait:ident for $simd:ty { fn $call:ident }) => { impl $trait<&$simd> for $simd where T: SimdElement, $simd: $trait<$simd, Output = $simd>, LaneCount: SupportedLaneCount, { type Output = Simd; #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] fn $call(self, rhs: &$simd) -> Self::Output { self.$call(*rhs) } } }; } macro_rules! deref_ops { ($(impl $trait:ident for $simd:ty { fn $call:ident })*) => { $( deref_rhs! { impl $trait for $simd { fn $call } } deref_lhs! { impl $trait for $simd { fn $call } } impl<'lhs, 'rhs, T, const LANES: usize> $trait<&'rhs $simd> for &'lhs $simd where T: SimdElement, $simd: $trait<$simd, Output = $simd>, LaneCount: SupportedLaneCount, { type Output = $simd; #[inline] #[must_use = "operator returns a new vector without mutating the inputs"] fn $call(self, rhs: &$simd) -> Self::Output { (*self).$call(*rhs) } } )* } } deref_ops! { // Arithmetic impl Add for Simd { fn add } impl Mul for Simd { fn mul } impl Sub for Simd { fn sub } impl Div for Simd { fn div } impl Rem for Simd { fn rem } // Bitops impl BitAnd for Simd { fn bitand } impl BitOr for Simd { fn bitor } impl BitXor for Simd { fn bitxor } impl Shl for Simd { fn shl } impl Shr for Simd { fn shr } }