use super::sealed::Sealed; use crate::simd::{intrinsics, LaneCount, Simd, SupportedLaneCount}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { /// Scalar type contained by this SIMD vector type. type Scalar; /// Lanewise saturating add. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; /// # use simd::{Simd, SimdUint}; /// use core::u32::MAX; /// let x = Simd::from_array([2, 1, 0, MAX]); /// let max = Simd::splat(MAX); /// let unsat = x + max; /// let sat = x.saturating_add(max); /// assert_eq!(unsat, Simd::from_array([1, 0, MAX, MAX - 1])); /// assert_eq!(sat, max); /// ``` fn saturating_add(self, second: Self) -> Self; /// Lanewise saturating subtract. /// /// # Examples /// ``` /// # #![feature(portable_simd)] /// # #[cfg(feature = "as_crate")] use core_simd::simd; /// # #[cfg(not(feature = "as_crate"))] use core::simd; /// # use simd::{Simd, SimdUint}; /// use core::u32::MAX; /// let x = Simd::from_array([2, 1, 0, MAX]); /// let max = Simd::splat(MAX); /// let unsat = x - max; /// let sat = x.saturating_sub(max); /// assert_eq!(unsat, Simd::from_array([3, 2, 1, 0])); /// assert_eq!(sat, Simd::splat(0)); fn saturating_sub(self, second: Self) -> Self; /// Returns the sum of the lanes of the vector, with wrapping addition. fn reduce_sum(self) -> Self::Scalar; /// Returns the product of the lanes of the vector, with wrapping multiplication. fn reduce_product(self) -> Self::Scalar; /// Returns the maximum lane in the vector. fn reduce_max(self) -> Self::Scalar; /// Returns the minimum lane in the vector. fn reduce_min(self) -> Self::Scalar; /// Returns the cumulative bitwise "and" across the lanes of the vector. fn reduce_and(self) -> Self::Scalar; /// Returns the cumulative bitwise "or" across the lanes of the vector. fn reduce_or(self) -> Self::Scalar; /// Returns the cumulative bitwise "xor" across the lanes of the vector. fn reduce_xor(self) -> Self::Scalar; } macro_rules! impl_trait { { $($ty:ty),* } => { $( impl Sealed for Simd<$ty, LANES> where LaneCount: SupportedLaneCount, { } impl SimdUint for Simd<$ty, LANES> where LaneCount: SupportedLaneCount, { type Scalar = $ty; #[inline] fn saturating_add(self, second: Self) -> Self { // Safety: `self` is a vector unsafe { intrinsics::simd_saturating_add(self, second) } } #[inline] fn saturating_sub(self, second: Self) -> Self { // Safety: `self` is a vector unsafe { intrinsics::simd_saturating_sub(self, second) } } #[inline] fn reduce_sum(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_add_ordered(self, 0) } } #[inline] fn reduce_product(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_mul_ordered(self, 1) } } #[inline] fn reduce_max(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_max(self) } } #[inline] fn reduce_min(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_min(self) } } #[inline] fn reduce_and(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_and(self) } } #[inline] fn reduce_or(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_or(self) } } #[inline] fn reduce_xor(self) -> Self::Scalar { // Safety: `self` is an integer vector unsafe { intrinsics::simd_reduce_xor(self) } } } )* } } impl_trait! { u8, u16, u32, u64, usize }