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