-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
257fa7a
commit 853e41d
Showing
2 changed files
with
107 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,125 @@ | ||
//! 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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |