diff options
| author | Caleb Zulawski <caleb.zulawski@gmail.com> | 2021-03-11 00:27:47 -0500 |
|---|---|---|
| committer | Caleb Zulawski <caleb.zulawski@gmail.com> | 2021-04-09 16:31:03 -0400 |
| commit | 64f564866bf09f98ae7a044fa8ca98a53bbbff1f (patch) | |
| tree | 36df55b585d05db71b7ca12f12594c0e73cfcbb7 | |
| parent | 02608d44f7542981202792234540915484e0560d (diff) | |
| download | rust-64f564866bf09f98ae7a044fa8ca98a53bbbff1f.tar.gz rust-64f564866bf09f98ae7a044fa8ca98a53bbbff1f.zip | |
Update documentation and fix i586 inaccuracy
| -rw-r--r-- | crates/core_simd/src/reduction.rs | 20 |
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) } |
