1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #28267 from akretz:absdiff-int

Fix absdiff with int arguments #28267

I believe the fix to the undefined behavior described in #27080 is simply casting to unsigned before subtraction, because

1. casting int to unsigned is well-defined; negative values get represented modulo $2^{32}$
2. overflow in unsigned subtraction is well-defined and the results are modulo $2^{32}$

Since we are computing everything modulo $2^{32}$ and the result must always be a non-negative number below $2^{32}$, this computation should be well-defined and correct.

I have verified this on ARM Apple Clang and on x64 Linux gcc with `-O3` and both produce the correct values in the reproducer of #27080. The test I have added fails with the integer overflow on both platforms I have tested. Perhaps @fengyuentau could verify if this also fixes the issue on the platforms he has tested?

I have added a fix and removed the workarounds. I recommended this approach in #28229, but he decided to revert it.


### 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
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Adrian Kretz
2026-02-15 08:29:29 +01:00
committed by GitHub
parent 82ff8e45e9
commit 196a8afe76
3 changed files with 17 additions and 48 deletions
+1 -1
View File
@@ -316,7 +316,7 @@ inline int cv_absdiff(uchar x, uchar y) { return (int)std::abs((int)x - (int)y);
inline int cv_absdiff(schar x, schar y) { return (int)std::abs((int)x - (int)y); }
inline int cv_absdiff(ushort x, ushort y) { return (int)std::abs((int)x - (int)y); }
inline int cv_absdiff(short x, short y) { return (int)std::abs((int)x - (int)y); }
inline unsigned cv_absdiff(int x, int y) { return (unsigned)(std::max(x, y) - std::min(x, y)); }
inline unsigned cv_absdiff(int x, int y) { return (unsigned)std::max(x, y) - (unsigned)std::min(x, y); }
inline unsigned cv_absdiff(unsigned x, unsigned y) { return std::max(x, y) - std::min(x, y); }
inline uint64 cv_absdiff(uint64 x, uint64 y) { return std::max(x, y) - std::min(x, y); }
inline float cv_absdiff(hfloat x, hfloat y) { return std::abs((float)x - (float)y); }