about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2021-03-11 00:27:47 -0500
committerCaleb Zulawski <caleb.zulawski@gmail.com>2021-04-09 16:31:03 -0400
commit64f564866bf09f98ae7a044fa8ca98a53bbbff1f (patch)
tree36df55b585d05db71b7ca12f12594c0e73cfcbb7
parent02608d44f7542981202792234540915484e0560d (diff)
downloadrust-64f564866bf09f98ae7a044fa8ca98a53bbbff1f.tar.gz
rust-64f564866bf09f98ae7a044fa8ca98a53bbbff1f.zip
Update documentation and fix i586 inaccuracy
-rw-r--r--crates/core_simd/src/reduction.rs20
1 files changed, 18 insertions, 2 deletions
diff --git a/crates/core_simd/src/reduction.rs b/crates/core_simd/src/reduction.rs
index d314cc737ed..684879021b4 100644
--- a/crates/core_simd/src/reduction.rs
+++ b/crates/core_simd/src/reduction.rs
@@ -58,22 +58,38 @@ macro_rules! impl_float_reductions {
             /// Produces the sum of the lanes of the vector.
             #[inline]
             pub fn sum(self) -> $scalar {
-                unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
+                // f32 SIMD sum is inaccurate on i586
+                if cfg!(target_arch = "i586") && core::mem::size_of::<$scalar>() == 4 {
+                    self.as_slice().iter().sum()
+                } else {
+                    unsafe { crate::intrinsics::simd_reduce_add_ordered(self, 0.) }
+                }
             }
 
             /// Produces the sum of the lanes of the vector.
             #[inline]
             pub fn product(self) -> $scalar {
-                unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
+                // f32 SIMD product is inaccurate on i586
+                if cfg!(target_arch = "i586") && core::mem::size_of::<$scalar>() == 4 {
+                    self.as_slice().iter().product()
+                } else {
+                    unsafe { crate::intrinsics::simd_reduce_mul_ordered(self, 1.) }
+                }
             }
 
             /// Returns the maximum lane in the vector.
+            ///
+            /// 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`.
             #[inline]
             pub fn max_lane(self) -> $scalar {
                 unsafe { crate::intrinsics::simd_reduce_max(self) }
             }
 
             /// Returns the minimum lane in the vector.
+            ///
+            /// 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`.
             #[inline]
             pub fn min_lane(self) -> $scalar {
                 unsafe { crate::intrinsics::simd_reduce_min(self) }