]> git.lizzy.rs Git - rust.git/blob - crates/core_simd/src/reduction.rs
Remove wrapping from sum/product fns
[rust.git] / crates / core_simd / src / reduction.rs
1 macro_rules! impl_integer_reductions {
2     { $name:ident, $scalar:ty } => {
3         impl<const LANES: usize> crate::$name<LANES>
4         where
5             Self: crate::LanesAtMost32
6         {
7             /// Horizontal wrapping add.  Returns the sum of the lanes of the vector, with wrapping addition.
8             #[inline]
9             pub fn horizontal_sum(self) -> $scalar {
10                 unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0) }
11             }
12
13             /// Horizontal wrapping multiply.  Returns the product of the lanes of the vector, with wrapping multiplication.
14             #[inline]
15             pub fn horizontal_product(self) -> $scalar {
16                 unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1) }
17             }
18
19             /// Horizontal bitwise "and".  Returns the cumulative bitwise "and" across the lanes of
20             /// the vector.
21             #[inline]
22             pub fn horizontal_and(self) -> $scalar {
23                 unsafe { crate::intrinsics::simd_reduce_and(self) }
24             }
25
26             /// Horizontal bitwise "or".  Returns the cumulative bitwise "or" across the lanes of
27             /// the vector.
28             #[inline]
29             pub fn horizontal_or(self) -> $scalar {
30                 unsafe { crate::intrinsics::simd_reduce_or(self) }
31             }
32
33             /// Horizontal bitwise "xor".  Returns the cumulative bitwise "xor" across the lanes of
34             /// the vector.
35             #[inline]
36             pub fn horizontal_xor(self) -> $scalar {
37                 unsafe { crate::intrinsics::simd_reduce_xor(self) }
38             }
39
40             /// Horizontal maximum.  Returns the maximum lane in the vector.
41             #[inline]
42             pub fn horizontal_max(self) -> $scalar {
43                 unsafe { crate::intrinsics::simd_reduce_max(self) }
44             }
45
46             /// Horizontal minimum.  Returns the minimum lane in the vector.
47             #[inline]
48             pub fn horizontal_min(self) -> $scalar {
49                 unsafe { crate::intrinsics::simd_reduce_min(self) }
50             }
51         }
52     }
53 }
54
55 macro_rules! impl_float_reductions {
56     { $name:ident, $scalar:ty } => {
57         impl<const LANES: usize> crate::$name<LANES>
58         where
59             Self: crate::LanesAtMost32
60         {
61
62             /// Horizontal add.  Returns the sum of the lanes of the vector.
63             #[inline]
64             pub fn horizontal_sum(self) -> $scalar {
65                 // LLVM sum is inaccurate on i586
66                 if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
67                     self.as_slice().iter().sum()
68                 } else {
69                     unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
70                 }
71             }
72
73             /// Horizontal multiply.  Returns the product of the lanes of the vector.
74             #[inline]
75             pub fn horizontal_product(self) -> $scalar {
76                 // LLVM product is inaccurate on i586
77                 if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
78                     self.as_slice().iter().product()
79                 } else {
80                     unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
81                 }
82             }
83
84             /// Horizontal maximum.  Returns the maximum lane in the vector.
85             ///
86             /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
87             /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
88             #[inline]
89             pub fn horizontal_max(self) -> $scalar {
90                 unsafe { crate::intrinsics::simd_reduce_max(self) }
91             }
92
93             /// Horizontal minimum.  Returns the minimum lane in the vector.
94             ///
95             /// Returns values based on equality, so a vector containing both `0.` and `-0.` may
96             /// return either.  This function will not return `NaN` unless all lanes are `NaN`.
97             #[inline]
98             pub fn horizontal_min(self) -> $scalar {
99                 unsafe { crate::intrinsics::simd_reduce_min(self) }
100             }
101         }
102     }
103 }
104
105 macro_rules! impl_full_mask_reductions {
106     { $name:ident, $inner:ident } => {
107         impl<const LANES: usize> crate::$name<LANES>
108         where
109             crate::$inner<LANES>: crate::LanesAtMost32
110         {
111             /// Returns true if any lane is set, or false otherwise.
112             #[inline]
113             pub fn any(self) -> bool {
114                 unsafe { crate::intrinsics::simd_reduce_any(self.to_int()) }
115             }
116
117             /// Returns true if all lanes are set, or false otherwise.
118             #[inline]
119             pub fn all(self) -> bool {
120                 unsafe { crate::intrinsics::simd_reduce_all(self.to_int()) }
121             }
122         }
123     }
124 }
125
126 macro_rules! impl_opaque_mask_reductions {
127     { $name:ident, $inner:ident, $bits_ty:ident } => {
128         impl<const LANES: usize> $name<LANES>
129         where
130             $bits_ty<LANES>: crate::LanesAtMost32
131         {
132             /// Returns true if any lane is set, or false otherwise.
133             #[inline]
134             pub fn any(self) -> bool {
135                 self.0.any()
136             }
137
138             /// Returns true if all lanes are set, or false otherwise.
139             #[inline]
140             pub fn all(self) -> bool {
141                 self.0.all()
142             }
143         }
144     }
145 }
146
147 impl<const LANES: usize> crate::BitMask<LANES>
148 where
149     crate::BitMask<LANES>: crate::LanesAtMost32,
150 {
151     /// Returns true if any lane is set, or false otherwise.
152     #[inline]
153     pub fn any(self) -> bool {
154         self != Self::splat(false)
155     }
156
157     /// Returns true if all lanes are set, or false otherwise.
158     #[inline]
159     pub fn all(self) -> bool {
160         self == Self::splat(true)
161     }
162 }