From cd4e86a2d68f95445a4569927753c37b0d259017 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sat, 2 May 2026 17:43:12 +0100 Subject: [PATCH] Fix I32x4 min/max working incorrectly for large values --- simd/src/arm/mod.rs | 4 ++-- simd/src/test.rs | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/simd/src/arm/mod.rs b/simd/src/arm/mod.rs index 43d410ec..fc6b97b7 100644 --- a/simd/src/arm/mod.rs +++ b/simd/src/arm/mod.rs @@ -604,12 +604,12 @@ impl I32x4 { #[inline] pub fn max(self, other: I32x4) -> I32x4 { - unsafe { I32x4(simd_cast(simd_maximum_number_nsz(self.to_f32x4().0, other.to_f32x4().0))) } + unsafe { I32x4(aarch64::vmaxq_s32(self.0, other.0)) } } #[inline] pub fn min(self, other: I32x4) -> I32x4 { - unsafe { I32x4(simd_cast(simd_minimum_number_nsz(self.to_f32x4().0, other.to_f32x4().0))) } + unsafe { I32x4(aarch64::vminq_s32(self.0, other.0)) } } // Packed comparisons diff --git a/simd/src/test.rs b/simd/src/test.rs index 0f287525..16748c00 100644 --- a/simd/src/test.rs +++ b/simd/src/test.rs @@ -11,6 +11,29 @@ use crate::default::{F32x4, I32x4, U32x4}; use crate::scalar::F32x4 as F32x4S; +#[cfg(all(pf_rustc_nightly, target_arch = "aarch64"))] +mod test_arm_i32x4_min_max_precision { + use crate::arm::I32x4; + + #[test] + fn min_max_preserve_values_above_f32_integer_precision() { + // The ARM I32x4::{min,max} implementations must compare integer lanes directly. + // Converting through f32 loses precision above 2^24, so values such as 16_777_217 + // round to neighboring integers and can produce a numerically wrong vector. + let a = I32x4::new(16_777_217, -16_777_217, 16_777_219, -16_777_219); + let b = I32x4::new(0, 0, 16_777_218, -16_777_218); + + assert_eq!( + a.max(b), + I32x4::new(16_777_217, 0, 16_777_219, -16_777_218) + ); + assert_eq!( + a.min(b), + I32x4::new(0, -16_777_217, 16_777_218, -16_777_219) + ); + } +} + // F32x4 #[test]