Skip to content

Commit 51ff925

Browse files
impl assign.rs<U> for Simd<T, _>
Instead of implementing {Op}Assign traits for individual scalar type args to Simd<_, _>, use parametric impls that reassert the bounds of the binary op.
1 parent 0a6992f commit 51ff925

File tree

2 files changed

+136
-154
lines changed

2 files changed

+136
-154
lines changed

crates/core_simd/src/ops.rs

+12-154
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use core::ops::{BitAnd, BitOr, BitXor};
55
use core::ops::{Div, Rem, Sub};
66
use core::ops::{Shl, Shr};
77

8+
mod assign;
89
mod deref;
910

1011
impl<I, T, const LANES: usize> core::ops::Index<I> for Simd<T, LANES>
@@ -65,25 +66,6 @@ macro_rules! impl_ref_ops {
6566
}
6667
};
6768

68-
// binary assignment op
69-
{
70-
impl<const $lanes:ident: usize> core::ops::$trait:ident<$rhs:ty> for $type:ty
71-
where
72-
LaneCount<$lanes2:ident>: SupportedLaneCount,
73-
{
74-
$(#[$attrs:meta])*
75-
fn $fn:ident(&mut $self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) $body:tt
76-
}
77-
} => {
78-
impl<const $lanes: usize> core::ops::$trait<$rhs> for $type
79-
where
80-
LaneCount<$lanes2>: SupportedLaneCount,
81-
{
82-
$(#[$attrs])*
83-
fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body
84-
}
85-
};
86-
8769
// unary op
8870
{
8971
impl<const $lanes:ident: usize> core::ops::$trait:ident for $type:ty
@@ -107,34 +89,34 @@ macro_rules! impl_ref_ops {
10789
/// Automatically implements operators over vectors and scalars for a particular vector.
10890
macro_rules! impl_op {
10991
{ impl Add for $scalar:ty } => {
110-
impl_op! { @binary $scalar, Add::add, AddAssign::add_assign, simd_add }
92+
impl_op! { @binary $scalar, Add::add, simd_add }
11193
};
11294
{ impl Sub for $scalar:ty } => {
113-
impl_op! { @binary $scalar, Sub::sub, SubAssign::sub_assign, simd_sub }
95+
impl_op! { @binary $scalar, Sub::sub, simd_sub }
11496
};
11597
{ impl Mul for $scalar:ty } => {
116-
impl_op! { @binary $scalar, Mul::mul, MulAssign::mul_assign, simd_mul }
98+
impl_op! { @binary $scalar, Mul::mul, simd_mul }
11799
};
118100
{ impl Div for $scalar:ty } => {
119-
impl_op! { @binary $scalar, Div::div, DivAssign::div_assign, simd_div }
101+
impl_op! { @binary $scalar, Div::div, simd_div }
120102
};
121103
{ impl Rem for $scalar:ty } => {
122-
impl_op! { @binary $scalar, Rem::rem, RemAssign::rem_assign, simd_rem }
104+
impl_op! { @binary $scalar, Rem::rem, simd_rem }
123105
};
124106
{ impl Shl for $scalar:ty } => {
125-
impl_op! { @binary $scalar, Shl::shl, ShlAssign::shl_assign, simd_shl }
107+
impl_op! { @binary $scalar, Shl::shl, simd_shl }
126108
};
127109
{ impl Shr for $scalar:ty } => {
128-
impl_op! { @binary $scalar, Shr::shr, ShrAssign::shr_assign, simd_shr }
110+
impl_op! { @binary $scalar, Shr::shr, simd_shr }
129111
};
130112
{ impl BitAnd for $scalar:ty } => {
131-
impl_op! { @binary $scalar, BitAnd::bitand, BitAndAssign::bitand_assign, simd_and }
113+
impl_op! { @binary $scalar, BitAnd::bitand, simd_and }
132114
};
133115
{ impl BitOr for $scalar:ty } => {
134-
impl_op! { @binary $scalar, BitOr::bitor, BitOrAssign::bitor_assign, simd_or }
116+
impl_op! { @binary $scalar, BitOr::bitor, simd_or }
135117
};
136118
{ impl BitXor for $scalar:ty } => {
137-
impl_op! { @binary $scalar, BitXor::bitxor, BitXorAssign::bitxor_assign, simd_xor }
119+
impl_op! { @binary $scalar, BitXor::bitxor, simd_xor }
138120
};
139121

140122
{ impl Not for $scalar:ty } => {
@@ -166,7 +148,7 @@ macro_rules! impl_op {
166148
};
167149

168150
// generic binary op with assignment when output is `Self`
169-
{ @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $assign_trait:ident :: $assign_trait_fn:ident, $intrinsic:ident } => {
151+
{ @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $intrinsic:ident } => {
170152
impl_ref_ops! {
171153
impl<const LANES: usize> core::ops::$trait<Self> for Simd<$scalar, LANES>
172154
where
@@ -210,32 +192,6 @@ macro_rules! impl_op {
210192
}
211193
}
212194
}
213-
214-
impl_ref_ops! {
215-
impl<const LANES: usize> core::ops::$assign_trait<Self> for Simd<$scalar, LANES>
216-
where
217-
LaneCount<LANES>: SupportedLaneCount,
218-
{
219-
#[inline]
220-
fn $assign_trait_fn(&mut self, rhs: Self) {
221-
unsafe {
222-
*self = intrinsics::$intrinsic(*self, rhs);
223-
}
224-
}
225-
}
226-
}
227-
228-
impl_ref_ops! {
229-
impl<const LANES: usize> core::ops::$assign_trait<$scalar> for Simd<$scalar, LANES>
230-
where
231-
LaneCount<LANES>: SupportedLaneCount,
232-
{
233-
#[inline]
234-
fn $assign_trait_fn(&mut self, rhs: $scalar) {
235-
core::ops::$assign_trait::$assign_trait_fn(self, Self::splat(rhs));
236-
}
237-
}
238-
}
239195
};
240196
}
241197

@@ -331,30 +287,6 @@ macro_rules! impl_unsigned_int_ops {
331287
}
332288
}
333289

334-
impl_ref_ops! {
335-
impl<const LANES: usize> core::ops::DivAssign<Self> for Simd<$scalar, LANES>
336-
where
337-
LaneCount<LANES>: SupportedLaneCount,
338-
{
339-
#[inline]
340-
fn div_assign(&mut self, rhs: Self) {
341-
*self = *self / rhs;
342-
}
343-
}
344-
}
345-
346-
impl_ref_ops! {
347-
impl<const LANES: usize> core::ops::DivAssign<$scalar> for Simd<$scalar, LANES>
348-
where
349-
LaneCount<LANES>: SupportedLaneCount,
350-
{
351-
#[inline]
352-
fn div_assign(&mut self, rhs: $scalar) {
353-
*self = *self / rhs;
354-
}
355-
}
356-
}
357-
358290
// remainder panics on zero divisor
359291
impl_ref_ops! {
360292
impl<const LANES: usize> core::ops::Rem<Self> for Simd<$scalar, LANES>
@@ -421,30 +353,6 @@ macro_rules! impl_unsigned_int_ops {
421353
}
422354
}
423355

424-
impl_ref_ops! {
425-
impl<const LANES: usize> core::ops::RemAssign<Self> for Simd<$scalar, LANES>
426-
where
427-
LaneCount<LANES>: SupportedLaneCount,
428-
{
429-
#[inline]
430-
fn rem_assign(&mut self, rhs: Self) {
431-
*self = *self % rhs;
432-
}
433-
}
434-
}
435-
436-
impl_ref_ops! {
437-
impl<const LANES: usize> core::ops::RemAssign<$scalar> for Simd<$scalar, LANES>
438-
where
439-
LaneCount<LANES>: SupportedLaneCount,
440-
{
441-
#[inline]
442-
fn rem_assign(&mut self, rhs: $scalar) {
443-
*self = *self % rhs;
444-
}
445-
}
446-
}
447-
448356
// shifts panic on overflow
449357
impl_ref_ops! {
450358
impl<const LANES: usize> core::ops::Shl<Self> for Simd<$scalar, LANES>
@@ -486,31 +394,6 @@ macro_rules! impl_unsigned_int_ops {
486394
}
487395
}
488396

489-
490-
impl_ref_ops! {
491-
impl<const LANES: usize> core::ops::ShlAssign<Self> for Simd<$scalar, LANES>
492-
where
493-
LaneCount<LANES>: SupportedLaneCount,
494-
{
495-
#[inline]
496-
fn shl_assign(&mut self, rhs: Self) {
497-
*self = *self << rhs;
498-
}
499-
}
500-
}
501-
502-
impl_ref_ops! {
503-
impl<const LANES: usize> core::ops::ShlAssign<$scalar> for Simd<$scalar, LANES>
504-
where
505-
LaneCount<LANES>: SupportedLaneCount,
506-
{
507-
#[inline]
508-
fn shl_assign(&mut self, rhs: $scalar) {
509-
*self = *self << rhs;
510-
}
511-
}
512-
}
513-
514397
impl_ref_ops! {
515398
impl<const LANES: usize> core::ops::Shr<Self> for Simd<$scalar, LANES>
516399
where
@@ -550,31 +433,6 @@ macro_rules! impl_unsigned_int_ops {
550433
}
551434
}
552435
}
553-
554-
555-
impl_ref_ops! {
556-
impl<const LANES: usize> core::ops::ShrAssign<Self> for Simd<$scalar, LANES>
557-
where
558-
LaneCount<LANES>: SupportedLaneCount,
559-
{
560-
#[inline]
561-
fn shr_assign(&mut self, rhs: Self) {
562-
*self = *self >> rhs;
563-
}
564-
}
565-
}
566-
567-
impl_ref_ops! {
568-
impl<const LANES: usize> core::ops::ShrAssign<$scalar> for Simd<$scalar, LANES>
569-
where
570-
LaneCount<LANES>: SupportedLaneCount,
571-
{
572-
#[inline]
573-
fn shr_assign(&mut self, rhs: $scalar) {
574-
*self = *self >> rhs;
575-
}
576-
}
577-
}
578436
)*
579437
};
580438
}

crates/core_simd/src/ops/assign.rs

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
//! Assignment operators
2+
use super::*;
3+
use core::ops::{AddAssign, MulAssign}; // commutative binary op-assignment
4+
use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign}; // commutative bit binary op-assignment
5+
use core::ops::{DivAssign, RemAssign, SubAssign}; // non-commutative binary op-assignment
6+
use core::ops::{ShlAssign, ShrAssign}; // non-commutative bit binary op-assignment
7+
8+
// Arithmetic
9+
10+
macro_rules! assign_ops {
11+
($(impl<T, U, const LANES: usize> $assignTrait:ident<U> for Simd<T, LANES>
12+
where
13+
Self: $trait:ident,
14+
{
15+
fn $assign_call:ident(rhs: U) {
16+
$call:ident
17+
}
18+
})*) => {
19+
$(impl<T, U, const LANES: usize> $assignTrait<U> for Simd<T, LANES>
20+
where
21+
Self: $trait<U, Output = Self>,
22+
T: SimdElement,
23+
LaneCount<LANES>: SupportedLaneCount,
24+
{
25+
#[inline]
26+
fn $assign_call(&mut self, rhs: U) {
27+
*self = self.$call(rhs);
28+
}
29+
})*
30+
}
31+
}
32+
33+
assign_ops! {
34+
// Arithmetic
35+
impl<T, U, const LANES: usize> AddAssign<U> for Simd<T, LANES>
36+
where
37+
Self: Add,
38+
{
39+
fn add_assign(rhs: U) {
40+
add
41+
}
42+
}
43+
44+
impl<T, U, const LANES: usize> MulAssign<U> for Simd<T, LANES>
45+
where
46+
Self: Mul,
47+
{
48+
fn mul_assign(rhs: U) {
49+
mul
50+
}
51+
}
52+
53+
impl<T, U, const LANES: usize> SubAssign<U> for Simd<T, LANES>
54+
where
55+
Self: Sub,
56+
{
57+
fn sub_assign(rhs: U) {
58+
sub
59+
}
60+
}
61+
62+
impl<T, U, const LANES: usize> DivAssign<U> for Simd<T, LANES>
63+
where
64+
Self: Div,
65+
{
66+
fn div_assign(rhs: U) {
67+
div
68+
}
69+
}
70+
impl<T, U, const LANES: usize> RemAssign<U> for Simd<T, LANES>
71+
where
72+
Self: Rem,
73+
{
74+
fn rem_assign(rhs: U) {
75+
rem
76+
}
77+
}
78+
79+
// Bitops
80+
impl<T, U, const LANES: usize> BitAndAssign<U> for Simd<T, LANES>
81+
where
82+
Self: BitAnd,
83+
{
84+
fn bitand_assign(rhs: U) {
85+
bitand
86+
}
87+
}
88+
89+
impl<T, U, const LANES: usize> BitOrAssign<U> for Simd<T, LANES>
90+
where
91+
Self: BitOr,
92+
{
93+
fn bitor_assign(rhs: U) {
94+
bitor
95+
}
96+
}
97+
98+
impl<T, U, const LANES: usize> BitXorAssign<U> for Simd<T, LANES>
99+
where
100+
Self: BitXor,
101+
{
102+
fn bitxor_assign(rhs: U) {
103+
bitxor
104+
}
105+
}
106+
107+
impl<T, U, const LANES: usize> ShlAssign<U> for Simd<T, LANES>
108+
where
109+
Self: Shl,
110+
{
111+
fn shl_assign(rhs: U) {
112+
shl
113+
}
114+
}
115+
116+
impl<T, U, const LANES: usize> ShrAssign<U> for Simd<T, LANES>
117+
where
118+
Self: Shr,
119+
{
120+
fn shr_assign(rhs: U) {
121+
shr
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)