impl Op<&'_ RHS> for &'_ LHS
This commit is contained in:
parent
257fa7aa6d
commit
8003b04323
2 changed files with 106 additions and 30 deletions
|
@ -1,70 +1,124 @@
|
|||
//! 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.
|
||||
//! But this is not the case with arithmetic ops.
|
||||
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>
|
||||
macro_rules! deref_lhs {
|
||||
(impl<T, const LANES: usize> $trait:ident for $simd:ty {
|
||||
fn $call:ident
|
||||
}) => {
|
||||
impl<T, const LANES: usize> $trait<$simd> for &$simd
|
||||
where
|
||||
Self: $trait<Self, Output = Self>,
|
||||
T: SimdElement,
|
||||
$simd: $trait<$simd, Output = $simd>,
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
type Output = Self;
|
||||
type Output = Simd<T, LANES>;
|
||||
|
||||
#[inline]
|
||||
#[must_use = "operator returns a new vector without mutating the inputs"]
|
||||
fn $call(self, rhs: &Self) -> Self::Output {
|
||||
fn $call(self, rhs: $simd) -> Self::Output {
|
||||
(*self).$call(rhs)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! deref_rhs {
|
||||
(impl<T, const LANES: usize> $trait:ident for $simd:ty {
|
||||
fn $call:ident
|
||||
}) => {
|
||||
impl<T, const LANES: usize> $trait<&$simd> for $simd
|
||||
where
|
||||
T: SimdElement,
|
||||
$simd: $trait<$simd, Output = $simd>,
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
type Output = Simd<T, LANES>;
|
||||
|
||||
#[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<T, const LANES: usize> $trait:ident for $simd:ty {
|
||||
fn $call:ident
|
||||
})*) => {
|
||||
$(
|
||||
deref_rhs! {
|
||||
impl<T, const LANES: usize> $trait for $simd {
|
||||
fn $call
|
||||
}
|
||||
}
|
||||
deref_lhs! {
|
||||
impl<T, const LANES: usize> $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<LANES>: 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<T, const LANES: usize> Add<&Self> for Simd<T, LANES> {
|
||||
fn add(rhs: &Self)
|
||||
impl<T, const LANES: usize> Add for Simd<T, LANES> {
|
||||
fn add
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> Mul<&Self> for Simd<T, LANES> {
|
||||
fn mul(rhs: &Self)
|
||||
impl<T, const LANES: usize> Mul for Simd<T, LANES> {
|
||||
fn mul
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> Sub<&Self> for Simd<T, LANES> {
|
||||
fn sub(rhs: &Self)
|
||||
impl<T, const LANES: usize> Sub for Simd<T, LANES> {
|
||||
fn sub
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> Div<&Self> for Simd<T, LANES> {
|
||||
fn div(rhs: &Self)
|
||||
impl<T, const LANES: usize> Div for Simd<T, LANES> {
|
||||
fn div
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> Rem<&Self> for Simd<T, LANES> {
|
||||
fn rem(rhs: &Self)
|
||||
impl<T, const LANES: usize> Rem for Simd<T, LANES> {
|
||||
fn rem
|
||||
}
|
||||
|
||||
// Bitops
|
||||
impl<T, const LANES: usize> BitAnd<&Self> for Simd<T, LANES> {
|
||||
fn bitand(rhs: &Self)
|
||||
impl<T, const LANES: usize> BitAnd for Simd<T, LANES> {
|
||||
fn bitand
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> BitOr<&Self> for Simd<T, LANES> {
|
||||
fn bitor(rhs: &Self)
|
||||
impl<T, const LANES: usize> BitOr for Simd<T, LANES> {
|
||||
fn bitor
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> BitXor<&Self> for Simd<T, LANES> {
|
||||
fn bitxor(rhs: &Self)
|
||||
impl<T, const LANES: usize> BitXor for Simd<T, LANES> {
|
||||
fn bitxor
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> Shl<&Self> for Simd<T, LANES> {
|
||||
fn shl(rhs: &Self)
|
||||
impl<T, const LANES: usize> Shl for Simd<T, LANES> {
|
||||
fn shl
|
||||
}
|
||||
|
||||
impl<T, const LANES: usize> Shr<&Self> for Simd<T, LANES> {
|
||||
fn shr(rhs: &Self)
|
||||
impl<T, const LANES: usize> Shr for Simd<T, LANES> {
|
||||
fn shr
|
||||
}
|
||||
}
|
||||
|
|
22
crates/core_simd/tests/autoderef.rs
Normal file
22
crates/core_simd/tests/autoderef.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Test that we handle all our "auto-deref" cases correctly.
|
||||
#![feature(portable_simd)]
|
||||
use core_simd::f32x4;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
|
||||
fn deref() {
|
||||
let x = f32x4::splat(1.0);
|
||||
let y = f32x4::splat(2.0);
|
||||
let a = &x;
|
||||
let b = &y;
|
||||
assert_eq!(f32x4::splat(3.0), x + y);
|
||||
assert_eq!(f32x4::splat(3.0), x + b);
|
||||
assert_eq!(f32x4::splat(3.0), a + y);
|
||||
assert_eq!(f32x4::splat(3.0), a + b);
|
||||
}
|
Loading…
Reference in a new issue