impl unary.rs for Simd<{i,u}{8,16,32,64,size}, _>
In order to assure type soundness, these "base" impls need to go directly on Simd<T, _> for every scalar type argument. A bit of cleanup of ops.rs is still warranted.
This commit is contained in:
parent
51ff925925
commit
6094f22ceb
2 changed files with 78 additions and 52 deletions
|
@ -7,6 +7,7 @@ use core::ops::{Shl, Shr};
|
|||
|
||||
mod assign;
|
||||
mod deref;
|
||||
mod unary;
|
||||
|
||||
impl<I, T, const LANES: usize> core::ops::Index<I> for Simd<T, LANES>
|
||||
where
|
||||
|
@ -65,25 +66,6 @@ macro_rules! impl_ref_ops {
|
|||
fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body
|
||||
}
|
||||
};
|
||||
|
||||
// unary op
|
||||
{
|
||||
impl<const $lanes:ident: usize> core::ops::$trait:ident for $type:ty
|
||||
where
|
||||
LaneCount<$lanes2:ident>: SupportedLaneCount,
|
||||
{
|
||||
type Output = $output:ty;
|
||||
fn $fn:ident($self_tok:ident) -> Self::Output $body:tt
|
||||
}
|
||||
} => {
|
||||
impl<const $lanes: usize> core::ops::$trait for $type
|
||||
where
|
||||
LaneCount<$lanes2>: SupportedLaneCount,
|
||||
{
|
||||
type Output = $output;
|
||||
fn $fn($self_tok) -> Self::Output $body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Automatically implements operators over vectors and scalars for a particular vector.
|
||||
|
@ -119,34 +101,6 @@ macro_rules! impl_op {
|
|||
impl_op! { @binary $scalar, BitXor::bitxor, simd_xor }
|
||||
};
|
||||
|
||||
{ impl Not for $scalar:ty } => {
|
||||
impl_ref_ops! {
|
||||
impl<const LANES: usize> core::ops::Not for Simd<$scalar, LANES>
|
||||
where
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
type Output = Self;
|
||||
fn not(self) -> Self::Output {
|
||||
self ^ Self::splat(!<$scalar>::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
{ impl Neg for $scalar:ty } => {
|
||||
impl_ref_ops! {
|
||||
impl<const LANES: usize> core::ops::Neg for Simd<$scalar, LANES>
|
||||
where
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self::Output {
|
||||
unsafe { intrinsics::simd_neg(self) }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// generic binary op with assignment when output is `Self`
|
||||
{ @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $intrinsic:ident } => {
|
||||
impl_ref_ops! {
|
||||
|
@ -204,7 +158,6 @@ macro_rules! impl_float_ops {
|
|||
impl_op! { impl Mul for $scalar }
|
||||
impl_op! { impl Div for $scalar }
|
||||
impl_op! { impl Rem for $scalar }
|
||||
impl_op! { impl Neg for $scalar }
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
@ -219,7 +172,6 @@ macro_rules! impl_unsigned_int_ops {
|
|||
impl_op! { impl BitAnd for $scalar }
|
||||
impl_op! { impl BitOr for $scalar }
|
||||
impl_op! { impl BitXor for $scalar }
|
||||
impl_op! { impl Not for $scalar }
|
||||
|
||||
// Integers panic on divide by 0
|
||||
impl_ref_ops! {
|
||||
|
@ -441,9 +393,6 @@ macro_rules! impl_unsigned_int_ops {
|
|||
macro_rules! impl_signed_int_ops {
|
||||
{ $($scalar:ty),* } => {
|
||||
impl_unsigned_int_ops! { $($scalar),* }
|
||||
$( // scalar
|
||||
impl_op! { impl Neg for $scalar }
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
|
|
77
crates/core_simd/src/ops/unary.rs
Normal file
77
crates/core_simd/src/ops/unary.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
use crate::simd::intrinsics;
|
||||
use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount};
|
||||
use core::ops::{Neg, Not}; // unary ops
|
||||
|
||||
macro_rules! neg {
|
||||
($(impl<const LANES: usize> Neg for Simd<$scalar:ty, LANES>)*) => {
|
||||
$(impl<const LANES: usize> Neg for Simd<$scalar, LANES>
|
||||
where
|
||||
$scalar: SimdElement,
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
#[must_use = "operator returns a new vector without mutating the input"]
|
||||
fn neg(self) -> Self::Output {
|
||||
unsafe { intrinsics::simd_neg(self) }
|
||||
}
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
neg! {
|
||||
impl<const LANES: usize> Neg for Simd<f32, LANES>
|
||||
|
||||
impl<const LANES: usize> Neg for Simd<f64, LANES>
|
||||
|
||||
impl<const LANES: usize> Neg for Simd<i8, LANES>
|
||||
|
||||
impl<const LANES: usize> Neg for Simd<i16, LANES>
|
||||
|
||||
impl<const LANES: usize> Neg for Simd<i32, LANES>
|
||||
|
||||
impl<const LANES: usize> Neg for Simd<i64, LANES>
|
||||
|
||||
impl<const LANES: usize> Neg for Simd<isize, LANES>
|
||||
}
|
||||
|
||||
macro_rules! not {
|
||||
($(impl<const LANES: usize> Not for Simd<$scalar:ty, LANES>)*) => {
|
||||
$(impl<const LANES: usize> Not for Simd<$scalar, LANES>
|
||||
where
|
||||
$scalar: SimdElement,
|
||||
LaneCount<LANES>: SupportedLaneCount,
|
||||
{
|
||||
type Output = Self;
|
||||
|
||||
#[inline]
|
||||
#[must_use = "operator returns a new vector without mutating the input"]
|
||||
fn not(self) -> Self::Output {
|
||||
self ^ (Simd::splat(!(0 as $scalar)))
|
||||
}
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
not! {
|
||||
impl<const LANES: usize> Not for Simd<i8, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<i16, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<i32, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<i64, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<isize, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<u8, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<u16, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<u32, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<u64, LANES>
|
||||
|
||||
impl<const LANES: usize> Not for Simd<usize, LANES>
|
||||
}
|
Loading…
Reference in a new issue