Skip to content

Commit 853e41d

Browse files
impl Op<&'_ RHS> for &'_ LHS
1 parent 257fa7a commit 853e41d

File tree

2 files changed

+107
-30
lines changed

2 files changed

+107
-30
lines changed

crates/core_simd/src/ops/deref.rs

Lines changed: 85 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,125 @@
11
//! This module hacks in "implicit deref" for Simd's operators.
22
//! Ideally, Rust would take care of this itself,
33
//! and method calls usually handle the LHS implicitly.
4-
//! So, we'll manually deref the RHS.
4+
//! But this is not the case with arithmetic ops.
55
use super::*;
66

7-
macro_rules! deref_ops {
8-
($(impl<T, const LANES: usize> $trait:ident<&Self> for Simd<T, LANES> {
9-
fn $call:ident(rhs: &Self)
10-
})*) => {
11-
$(impl<T, const LANES: usize> $trait<&Self> for Simd<T, LANES>
7+
8+
macro_rules! deref_lhs {
9+
(impl<T, const LANES: usize> $trait:ident for $simd:ty {
10+
fn $call:ident
11+
}) => {
12+
impl<T, const LANES: usize> $trait<$simd> for &$simd
1213
where
13-
Self: $trait<Self, Output = Self>,
1414
T: SimdElement,
15+
$simd: $trait<$simd, Output = $simd>,
1516
LaneCount<LANES>: SupportedLaneCount,
1617
{
17-
type Output = Self;
18+
type Output = Simd<T, LANES>;
1819

1920
#[inline]
2021
#[must_use = "operator returns a new vector without mutating the inputs"]
21-
fn $call(self, rhs: &Self) -> Self::Output {
22+
fn $call(self, rhs: $simd) -> Self::Output {
23+
(*self).$call(rhs)
24+
}
25+
}
26+
}
27+
}
28+
29+
macro_rules! deref_rhs {
30+
(impl<T, const LANES: usize> $trait:ident for $simd:ty {
31+
fn $call:ident
32+
}) => {
33+
impl<T, const LANES: usize> $trait<&$simd> for $simd
34+
where
35+
T: SimdElement,
36+
$simd: $trait<$simd, Output = $simd>,
37+
LaneCount<LANES>: SupportedLaneCount,
38+
{
39+
type Output = Simd<T, LANES>;
40+
41+
#[inline]
42+
#[must_use = "operator returns a new vector without mutating the inputs"]
43+
fn $call(self, rhs: &$simd) -> Self::Output {
2244
self.$call(*rhs)
2345
}
24-
})*
46+
}
47+
}
48+
}
49+
50+
macro_rules! deref_ops {
51+
($(impl<T, const LANES: usize> $trait:ident for $simd:ty {
52+
fn $call:ident
53+
})*) => {
54+
$(
55+
deref_rhs! {
56+
impl<T, const LANES: usize> $trait for $simd {
57+
fn $call
58+
}
59+
}
60+
deref_lhs! {
61+
impl<T, const LANES: usize> $trait for $simd {
62+
fn $call
63+
}
64+
}
65+
impl<'lhs, 'rhs, T, const LANES: usize> $trait<&'rhs $simd> for &'lhs $simd
66+
where
67+
T: SimdElement,
68+
$simd: $trait<$simd, Output = $simd>,
69+
LaneCount<LANES>: SupportedLaneCount,
70+
{
71+
type Output = $simd;
72+
73+
#[inline]
74+
#[must_use = "operator returns a new vector without mutating the inputs"]
75+
fn $call(self, rhs: &$simd) -> Self::Output {
76+
(*self).$call(*rhs)
77+
}
78+
}
79+
)*
2580
}
2681
}
2782

2883
deref_ops! {
2984
// Arithmetic
30-
impl<T, const LANES: usize> Add<&Self> for Simd<T, LANES> {
31-
fn add(rhs: &Self)
85+
impl<T, const LANES: usize> Add for Simd<T, LANES> {
86+
fn add
3287
}
3388

34-
impl<T, const LANES: usize> Mul<&Self> for Simd<T, LANES> {
35-
fn mul(rhs: &Self)
89+
impl<T, const LANES: usize> Mul for Simd<T, LANES> {
90+
fn mul
3691
}
3792

38-
impl<T, const LANES: usize> Sub<&Self> for Simd<T, LANES> {
39-
fn sub(rhs: &Self)
93+
impl<T, const LANES: usize> Sub for Simd<T, LANES> {
94+
fn sub
4095
}
4196

42-
impl<T, const LANES: usize> Div<&Self> for Simd<T, LANES> {
43-
fn div(rhs: &Self)
97+
impl<T, const LANES: usize> Div for Simd<T, LANES> {
98+
fn div
4499
}
45100

46-
impl<T, const LANES: usize> Rem<&Self> for Simd<T, LANES> {
47-
fn rem(rhs: &Self)
101+
impl<T, const LANES: usize> Rem for Simd<T, LANES> {
102+
fn rem
48103
}
49104

50105
// Bitops
51-
impl<T, const LANES: usize> BitAnd<&Self> for Simd<T, LANES> {
52-
fn bitand(rhs: &Self)
106+
impl<T, const LANES: usize> BitAnd for Simd<T, LANES> {
107+
fn bitand
53108
}
54109

55-
impl<T, const LANES: usize> BitOr<&Self> for Simd<T, LANES> {
56-
fn bitor(rhs: &Self)
110+
impl<T, const LANES: usize> BitOr for Simd<T, LANES> {
111+
fn bitor
57112
}
58113

59-
impl<T, const LANES: usize> BitXor<&Self> for Simd<T, LANES> {
60-
fn bitxor(rhs: &Self)
114+
impl<T, const LANES: usize> BitXor for Simd<T, LANES> {
115+
fn bitxor
61116
}
62117

63-
impl<T, const LANES: usize> Shl<&Self> for Simd<T, LANES> {
64-
fn shl(rhs: &Self)
118+
impl<T, const LANES: usize> Shl for Simd<T, LANES> {
119+
fn shl
65120
}
66121

67-
impl<T, const LANES: usize> Shr<&Self> for Simd<T, LANES> {
68-
fn shr(rhs: &Self)
122+
impl<T, const LANES: usize> Shr for Simd<T, LANES> {
123+
fn shr
69124
}
70125
}

crates/core_simd/tests/autoderef.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Test that we handle all our "auto-deref" cases correctly.
2+
#![feature(portable_simd)]
3+
use core_simd::f32x4;
4+
5+
#[cfg(target_arch = "wasm32")]
6+
use wasm_bindgen_test::*;
7+
8+
#[cfg(target_arch = "wasm32")]
9+
wasm_bindgen_test_configure!(run_in_browser);
10+
11+
#[test]
12+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
13+
fn deref() {
14+
let x = f32x4::splat(1.0);
15+
let y = f32x4::splat(2.0);
16+
let a = &x;
17+
let b = &y;
18+
assert_eq!(f32x4::splat(3.0), x + y);
19+
assert_eq!(f32x4::splat(3.0), x + b);
20+
assert_eq!(f32x4::splat(3.0), a + y);
21+
assert_eq!(f32x4::splat(3.0), a + b);
22+
}

0 commit comments

Comments
 (0)