1 use crate::simd::intrinsics::{
2 simd_reduce_add_ordered, simd_reduce_and, simd_reduce_max, simd_reduce_min,
3 simd_reduce_mul_ordered, simd_reduce_or, simd_reduce_xor,
5 use crate::simd::{LaneCount, Simd, SupportedLaneCount};
7 macro_rules! impl_integer_reductions {
9 impl<const LANES: usize> Simd<$scalar, LANES>
11 LaneCount<LANES>: SupportedLaneCount,
13 /// Horizontal wrapping add. Returns the sum of the lanes of the vector, with wrapping addition.
15 pub fn horizontal_sum(self) -> $scalar {
16 unsafe { simd_reduce_add_ordered(self, 0) }
19 /// Horizontal wrapping multiply. Returns the product of the lanes of the vector, with wrapping multiplication.
21 pub fn horizontal_product(self) -> $scalar {
22 unsafe { simd_reduce_mul_ordered(self, 1) }
25 /// Horizontal bitwise "and". Returns the cumulative bitwise "and" across the lanes of
28 pub fn horizontal_and(self) -> $scalar {
29 unsafe { simd_reduce_and(self) }
32 /// Horizontal bitwise "or". Returns the cumulative bitwise "or" across the lanes of
35 pub fn horizontal_or(self) -> $scalar {
36 unsafe { simd_reduce_or(self) }
39 /// Horizontal bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of
42 pub fn horizontal_xor(self) -> $scalar {
43 unsafe { simd_reduce_xor(self) }
46 /// Horizontal maximum. Returns the maximum lane in the vector.
48 pub fn horizontal_max(self) -> $scalar {
49 unsafe { simd_reduce_max(self) }
52 /// Horizontal minimum. Returns the minimum lane in the vector.
54 pub fn horizontal_min(self) -> $scalar {
55 unsafe { simd_reduce_min(self) }
61 impl_integer_reductions! { i8 }
62 impl_integer_reductions! { i16 }
63 impl_integer_reductions! { i32 }
64 impl_integer_reductions! { i64 }
65 impl_integer_reductions! { isize }
66 impl_integer_reductions! { u8 }
67 impl_integer_reductions! { u16 }
68 impl_integer_reductions! { u32 }
69 impl_integer_reductions! { u64 }
70 impl_integer_reductions! { usize }
72 macro_rules! impl_float_reductions {
74 impl<const LANES: usize> Simd<$scalar, LANES>
76 LaneCount<LANES>: SupportedLaneCount,
79 /// Horizontal add. Returns the sum of the lanes of the vector.
81 pub fn horizontal_sum(self) -> $scalar {
82 // LLVM sum is inaccurate on i586
83 if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
84 self.as_array().iter().sum()
86 unsafe { simd_reduce_add_ordered(self, 0.) }
90 /// Horizontal multiply. Returns the product of the lanes of the vector.
92 pub fn horizontal_product(self) -> $scalar {
93 // LLVM product is inaccurate on i586
94 if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
95 self.as_array().iter().product()
97 unsafe { simd_reduce_mul_ordered(self, 1.) }
101 /// Horizontal maximum. Returns the maximum lane in the vector.
103 /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
104 /// return either. This function will not return `NaN` unless all lanes are `NaN`.
106 pub fn horizontal_max(self) -> $scalar {
107 unsafe { simd_reduce_max(self) }
110 /// Horizontal minimum. Returns the minimum lane in the vector.
112 /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
113 /// return either. This function will not return `NaN` unless all lanes are `NaN`.
115 pub fn horizontal_min(self) -> $scalar {
116 unsafe { simd_reduce_min(self) }
122 impl_float_reductions! { f32 }
123 impl_float_reductions! { f64 }