1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge pull request #29140 from Tiansuanyu:fix-gcc13-vblas-fma

core: fix numerical instability and UB in VBLAS SIMD helpers #29140

### Description

**Fixes #28845**

**Root cause identified by:** stubbing out `VBLAS<double>::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<double>::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)
This commit is contained in:
Zixi Wang
2026-05-26 23:01:06 +08:00
committed by GitHub
parent aed3df4ed9
commit 2405556989
+7 -7
View File
@@ -302,12 +302,13 @@ template<> inline int VBLAS<float>::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<v_float32>::vlanes(); k += VTraits<v_float32>::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<double>::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<double>::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<v_float64>::vlanes(); k += VTraits<v_float64>::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);
}