Skip to content

Commit 0a6992f

Browse files
impl deref.rs<&Self> for Simd<T, _>
Instead of implementing each "deref" pattern for every single scalar, we can use type parameters for Simd operating on &Self. We can use a macro, but keep it cleaner and more explicit.
1 parent b8d6b68 commit 0a6992f

File tree

2 files changed

+76
-56
lines changed

2 files changed

+76
-56
lines changed

crates/core_simd/src/ops.rs

+6-56
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
use crate::simd::intrinsics;
22
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
3+
use core::ops::{Add, Mul};
4+
use core::ops::{BitAnd, BitOr, BitXor};
5+
use core::ops::{Div, Rem, Sub};
6+
use core::ops::{Shl, Shr};
7+
8+
mod deref;
39

410
impl<I, T, const LANES: usize> core::ops::Index<I> for Simd<T, LANES>
511
where
@@ -57,42 +63,6 @@ macro_rules! impl_ref_ops {
5763
$(#[$attrs])*
5864
fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body
5965
}
60-
61-
impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for $type
62-
where
63-
LaneCount<$lanes2>: SupportedLaneCount,
64-
{
65-
type Output = <$type as core::ops::$trait<$rhs>>::Output;
66-
67-
$(#[$attrs])*
68-
fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output {
69-
core::ops::$trait::$fn($self_tok, *$rhs_arg)
70-
}
71-
}
72-
73-
impl<const $lanes: usize> core::ops::$trait<$rhs> for &'_ $type
74-
where
75-
LaneCount<$lanes2>: SupportedLaneCount,
76-
{
77-
type Output = <$type as core::ops::$trait<$rhs>>::Output;
78-
79-
$(#[$attrs])*
80-
fn $fn($self_tok, $rhs_arg: $rhs) -> Self::Output {
81-
core::ops::$trait::$fn(*$self_tok, $rhs_arg)
82-
}
83-
}
84-
85-
impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for &'_ $type
86-
where
87-
LaneCount<$lanes2>: SupportedLaneCount,
88-
{
89-
type Output = <$type as core::ops::$trait<$rhs>>::Output;
90-
91-
$(#[$attrs])*
92-
fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output {
93-
core::ops::$trait::$fn(*$self_tok, *$rhs_arg)
94-
}
95-
}
9666
};
9767

9868
// binary assignment op
@@ -112,16 +82,6 @@ macro_rules! impl_ref_ops {
11282
$(#[$attrs])*
11383
fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body
11484
}
115-
116-
impl<const $lanes: usize> core::ops::$trait<&'_ $rhs> for $type
117-
where
118-
LaneCount<$lanes2>: SupportedLaneCount,
119-
{
120-
$(#[$attrs])*
121-
fn $fn(&mut $self_tok, $rhs_arg: &$rhs_arg_ty) {
122-
core::ops::$trait::$fn($self_tok, *$rhs_arg)
123-
}
124-
}
12585
};
12686

12787
// unary op
@@ -141,16 +101,6 @@ macro_rules! impl_ref_ops {
141101
type Output = $output;
142102
fn $fn($self_tok) -> Self::Output $body
143103
}
144-
145-
impl<const $lanes: usize> core::ops::$trait for &'_ $type
146-
where
147-
LaneCount<$lanes2>: SupportedLaneCount,
148-
{
149-
type Output = <$type as core::ops::$trait>::Output;
150-
fn $fn($self_tok) -> Self::Output {
151-
core::ops::$trait::$fn(*$self_tok)
152-
}
153-
}
154104
}
155105
}
156106

crates/core_simd/src/ops/deref.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
//! So, we'll manually deref the RHS.
5+
use super::*;
6+
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>
12+
where
13+
Self: $trait<Self, Output = Self>,
14+
T: SimdElement,
15+
LaneCount<LANES>: SupportedLaneCount,
16+
{
17+
type Output = Self;
18+
19+
#[inline]
20+
#[must_use = "operator returns a new vector without mutating the inputs"]
21+
fn $call(self, rhs: &Self) -> Self::Output {
22+
self.$call(*rhs)
23+
}
24+
})*
25+
}
26+
}
27+
28+
deref_ops! {
29+
// Arithmetic
30+
impl<T, const LANES: usize> Add<&Self> for Simd<T, LANES> {
31+
fn add(rhs: &Self)
32+
}
33+
34+
impl<T, const LANES: usize> Mul<&Self> for Simd<T, LANES> {
35+
fn mul(rhs: &Self)
36+
}
37+
38+
impl<T, const LANES: usize> Sub<&Self> for Simd<T, LANES> {
39+
fn sub(rhs: &Self)
40+
}
41+
42+
impl<T, const LANES: usize> Div<&Self> for Simd<T, LANES> {
43+
fn div(rhs: &Self)
44+
}
45+
46+
impl<T, const LANES: usize> Rem<&Self> for Simd<T, LANES> {
47+
fn rem(rhs: &Self)
48+
}
49+
50+
// Bitops
51+
impl<T, const LANES: usize> BitAnd<&Self> for Simd<T, LANES> {
52+
fn bitand(rhs: &Self)
53+
}
54+
55+
impl<T, const LANES: usize> BitOr<&Self> for Simd<T, LANES> {
56+
fn bitor(rhs: &Self)
57+
}
58+
59+
impl<T, const LANES: usize> BitXor<&Self> for Simd<T, LANES> {
60+
fn bitxor(rhs: &Self)
61+
}
62+
63+
impl<T, const LANES: usize> Shl<&Self> for Simd<T, LANES> {
64+
fn shl(rhs: &Self)
65+
}
66+
67+
impl<T, const LANES: usize> Shr<&Self> for Simd<T, LANES> {
68+
fn shr(rhs: &Self)
69+
}
70+
}

0 commit comments

Comments
 (0)