2021-03-07 20:15:56 -06:00
|
|
|
macro_rules! impl_integer_reductions {
|
|
|
|
{ $name:ident, $scalar:ty } => {
|
|
|
|
impl<const LANES: usize> crate::$name<LANES>
|
|
|
|
where
|
|
|
|
Self: crate::LanesAtMost32
|
|
|
|
{
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal wrapping add. Returns the sum of the lanes of the vector, with wrapping addition.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-19 18:41:11 -05:00
|
|
|
pub fn horizontal_wrapping_sum(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal wrapping multiply. Returns the product of the lanes of the vector, with wrapping multiplication.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-19 18:41:11 -05:00
|
|
|
pub fn horizontal_wrapping_product(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal bitwise "and". Returns the cumulative bitwise "and" across the lanes of
|
2021-04-11 09:59:05 -05:00
|
|
|
/// the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_and(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_and(self) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal bitwise "or". Returns the cumulative bitwise "or" across the lanes of
|
2021-04-11 09:59:05 -05:00
|
|
|
/// the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_or(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_or(self) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of
|
2021-04-11 09:59:05 -05:00
|
|
|
/// the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_xor(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_xor(self) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal maximum. Returns the maximum lane in the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_max(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_max(self) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal minimum. Returns the minimum lane in the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_min(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_min(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_float_reductions {
|
|
|
|
{ $name:ident, $scalar:ty } => {
|
|
|
|
impl<const LANES: usize> crate::$name<LANES>
|
|
|
|
where
|
|
|
|
Self: crate::LanesAtMost32
|
|
|
|
{
|
2021-03-11 00:02:47 -06:00
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal add. Returns the sum of the lanes of the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-19 18:41:11 -05:00
|
|
|
pub fn horizontal_sum(self) -> $scalar {
|
2021-03-12 19:31:30 -06:00
|
|
|
// LLVM sum is inaccurate on i586
|
|
|
|
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
|
2021-03-12 19:09:31 -06:00
|
|
|
self.as_slice().iter().sum()
|
|
|
|
} else {
|
|
|
|
unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
|
|
|
|
}
|
2021-03-07 20:15:56 -06:00
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal multiply. Returns the product of the lanes of the vector.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-19 18:41:11 -05:00
|
|
|
pub fn horizontal_product(self) -> $scalar {
|
2021-03-12 19:31:30 -06:00
|
|
|
// LLVM product is inaccurate on i586
|
|
|
|
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
|
2021-03-12 19:09:31 -06:00
|
|
|
self.as_slice().iter().product()
|
|
|
|
} else {
|
|
|
|
unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
|
|
|
|
}
|
2021-03-07 20:15:56 -06:00
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal maximum. Returns the maximum lane in the vector.
|
2021-03-10 23:27:47 -06:00
|
|
|
///
|
|
|
|
/// Returns values based on equality, so a vector containing both `0.` and `-0.` may
|
|
|
|
/// return either. This function will not return `NaN` unless all lanes are `NaN`.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_max(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_max(self) }
|
|
|
|
}
|
|
|
|
|
2021-04-16 20:32:45 -05:00
|
|
|
/// Horizontal minimum. Returns the minimum lane in the vector.
|
2021-03-10 23:27:47 -06:00
|
|
|
///
|
|
|
|
/// Returns values based on equality, so a vector containing both `0.` and `-0.` may
|
|
|
|
/// return either. This function will not return `NaN` unless all lanes are `NaN`.
|
2021-03-07 20:15:56 -06:00
|
|
|
#[inline]
|
2021-04-11 09:59:05 -05:00
|
|
|
pub fn horizontal_min(self) -> $scalar {
|
2021-03-07 20:15:56 -06:00
|
|
|
unsafe { crate::intrinsics::simd_reduce_min(self) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_full_mask_reductions {
|
|
|
|
{ $name:ident, $inner:ident } => {
|
|
|
|
impl<const LANES: usize> crate::$name<LANES>
|
|
|
|
where
|
|
|
|
crate::$inner<LANES>: crate::LanesAtMost32
|
|
|
|
{
|
|
|
|
/// Returns true if any lane is set, or false otherwise.
|
|
|
|
#[inline]
|
|
|
|
pub fn any(self) -> bool {
|
|
|
|
unsafe { crate::intrinsics::simd_reduce_any(self.to_int()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if all lanes are set, or false otherwise.
|
|
|
|
#[inline]
|
|
|
|
pub fn all(self) -> bool {
|
|
|
|
unsafe { crate::intrinsics::simd_reduce_all(self.to_int()) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_opaque_mask_reductions {
|
|
|
|
{ $name:ident, $inner:ident, $bits_ty:ident } => {
|
|
|
|
impl<const LANES: usize> $name<LANES>
|
|
|
|
where
|
|
|
|
$bits_ty<LANES>: crate::LanesAtMost32
|
|
|
|
{
|
|
|
|
/// Returns true if any lane is set, or false otherwise.
|
|
|
|
#[inline]
|
|
|
|
pub fn any(self) -> bool {
|
|
|
|
self.0.any()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if all lanes are set, or false otherwise.
|
|
|
|
#[inline]
|
|
|
|
pub fn all(self) -> bool {
|
|
|
|
self.0.all()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<const LANES: usize> crate::BitMask<LANES>
|
|
|
|
where
|
|
|
|
crate::BitMask<LANES>: crate::LanesAtMost32,
|
|
|
|
{
|
|
|
|
/// Returns true if any lane is set, or false otherwise.
|
|
|
|
#[inline]
|
|
|
|
pub fn any(self) -> bool {
|
2021-03-10 23:05:20 -06:00
|
|
|
self != Self::splat(false)
|
2021-03-07 20:15:56 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns true if all lanes are set, or false otherwise.
|
|
|
|
#[inline]
|
|
|
|
pub fn all(self) -> bool {
|
2021-03-10 23:05:20 -06:00
|
|
|
self == Self::splat(true)
|
2021-03-07 20:15:56 -06:00
|
|
|
}
|
|
|
|
}
|