提交 8003b043 编写于 作者: J Jubilee Young

impl Op<&'_ RHS> for &'_ LHS

上级 257fa7aa
//! 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
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_rhs {
(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_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
}
}
// 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);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册