From 2405556989c2f4e05b63f1344ec6701dc1b5ed72 Mon Sep 17 00:00:00 2001 From: Zixi Wang Date: Tue, 26 May 2026 23:01:06 +0800 Subject: [PATCH] Merge pull request #29140 from Tiansuanyu:fix-gcc13-vblas-fma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit core: fix numerical instability and UB in VBLAS SIMD helpers #29140 ### Description **Fixes #28845** **Root cause identified by:** stubbing out `VBLAS::givens()` to return 0 immediately — both tests pass, confirming the divergence originates in the double-precision Givens SIMD rotation. **Main fix:** Use FMA form in `VBLAS::{float,double}::givens()` to keep JacobiSVD vector rotation numerically stable on SIMD/FMA builds. This fixes the fisheye homography initialization divergence (`RMS 36.2553` vs `1`) seen in `RegisterCamerasTest.hetero1/2` under GCC 13. **Additional fix:** Replace fixed-size temporary storage `sbuf[2]` in `VBLAS::dot()` with `v_reduce_sum()` to avoid out-of-bounds stores on wide SIMD backends (e.g., AVX2 `v_float64` requires 4 lanes, causing UB). **Verification:** Passed full `opencv_test_core` and `opencv_test_calib` locally under Ubuntu 24.04 (GCC 13) with AVX2. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch (`next`) - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable (Passed existing `opencv_test_core` and `opencv_test_calib` tests) - [ ] The feature is well documented and sample code can be built with the project CMake (N/A - Bug fix) --- modules/core/src/lapack.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index c3ee3c2a1b..75c40f8f6e 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -302,12 +302,13 @@ template<> inline int VBLAS::givens(float* a, float* b, int n, float c, f return 0; int k = 0; v_float32 c4 = vx_setall_f32(c), s4 = vx_setall_f32(s); + v_float32 ns4 = vx_setall_f32(-s); for( ; k <= n - VTraits::vlanes(); k += VTraits::vlanes() ) { v_float32 a0 = vx_load(a + k); v_float32 b0 = vx_load(b + k); - v_float32 t0 = v_add(v_mul(a0, c4), v_mul(b0, s4)); - v_float32 t1 = v_sub(v_mul(b0, c4), v_mul(a0, s4)); + v_float32 t0 = v_fma(a0, c4, v_mul(b0, s4)); + v_float32 t1 = v_fma(a0, ns4, v_mul(b0, c4)); v_store(a + k, t0); v_store(b + k, t1); } @@ -330,9 +331,7 @@ template<> inline int VBLAS::dot(const double* a, const double* b, int n s0 = v_add(s0, v_mul(a0, b0)); } - double sbuf[2]; - v_store(sbuf, s0); - *result = sbuf[0] + sbuf[1]; + *result = v_reduce_sum(s0); vx_cleanup(); return k; } @@ -342,12 +341,13 @@ template<> inline int VBLAS::givens(double* a, double* b, int n, double { int k = 0; v_float64 c2 = vx_setall_f64(c), s2 = vx_setall_f64(s); + v_float64 ns2 = vx_setall_f64(-s); for( ; k <= n - VTraits::vlanes(); k += VTraits::vlanes() ) { v_float64 a0 = vx_load(a + k); v_float64 b0 = vx_load(b + k); - v_float64 t0 = v_add(v_mul(a0, c2), v_mul(b0, s2)); - v_float64 t1 = v_sub(v_mul(b0, c2), v_mul(a0, s2)); + v_float64 t0 = v_fma(a0, c2, v_mul(b0, s2)); + v_float64 t1 = v_fma(a0, ns2, v_mul(b0, c2)); v_store(a + k, t0); v_store(b + k, t1); }