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

Merge pull request #25671 from savuor:rv/arithm_extend_tests

Tests added for mixed type arithmetic operations #25671

### Changes
* added accuracy tests for mixed type arithmetic operations
    _Note: div-by-zero values are removed from checking since the result is implementation-defined in common case_
* added perf tests for the same cases
* fixed a typo in `getMulExtTab()` function that lead to dead code

### 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:
Rostislav Vasilikhin
2024-06-02 13:28:06 +02:00
committed by GitHub
parent 1bd5ca1ebe
commit a7e53aa184
5 changed files with 494 additions and 87 deletions
+69 -42
View File
@@ -2551,30 +2551,31 @@ void max(const Mat& src1, double val, Mat& dst)
}
template<typename _Tp> static void
muldiv_(const _Tp* src1, const _Tp* src2, _Tp* dst, size_t total, double scale, char op)
template<typename SrcType, typename DstType> static void
muldiv_(const SrcType* src1, const SrcType* src2, DstType* dst, size_t total, double scale, char op)
{
if( op == '*' )
for( size_t i = 0; i < total; i++ )
dst[i] = saturate_cast<_Tp>((scale*src1[i])*src2[i]);
else if( src1 )
for( size_t i = 0; i < total; i++ )
dst[i] = src2[i] ? saturate_cast<_Tp>((scale*src1[i])/src2[i]) : 0;
else
for( size_t i = 0; i < total; i++ )
dst[i] = src2[i] ? saturate_cast<_Tp>(scale/src2[i]) : 0;
for( size_t i = 0; i < total; i++ )
{
double m1 = src1 ? (double)src1[i] : 1.0;
double m2 = src2 ? (double)src2[i] : 1.0;
if (op == '/')
{
m2 = abs(m2) > FLT_EPSILON ? (1.0 / m2) : 0;
}
dst[i] = saturate_cast<DstType>(scale * m1 * m2);
}
}
static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, double scale, char op)
static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, int ctype, double scale, char op)
{
dst.create(src2.dims, src2.size, src2.type());
dst.create(src2.dims, src2.size, (ctype >= 0 ? ctype : src2.type()));
CV_Assert( src1.empty() || (src1.type() == src2.type() && src1.size == src2.size) );
const Mat *arrays[]={&src1, &src2, &dst, 0};
Mat planes[3];
NAryMatIterator it(arrays, planes);
size_t total = planes[1].total()*planes[1].channels();
size_t i, nplanes = it.nplanes, depth = src2.depth();
size_t i, nplanes = it.nplanes, srcDepth = src2.depth(), dstDepth = dst.depth();
for( i = 0; i < nplanes; i++, ++it )
{
@@ -2582,44 +2583,70 @@ static void muldiv(const Mat& src1, const Mat& src2, Mat& dst, double scale, cha
const uchar* sptr2 = planes[1].ptr();
uchar* dptr = planes[2].ptr();
switch( depth )
if (srcDepth == dstDepth)
{
case CV_8U:
muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (uchar*)dptr, total, scale, op);
break;
case CV_8S:
muldiv_((const schar*)sptr1, (const schar*)sptr2, (schar*)dptr, total, scale, op);
break;
case CV_16U:
muldiv_((const ushort*)sptr1, (const ushort*)sptr2, (ushort*)dptr, total, scale, op);
break;
case CV_16S:
muldiv_((const short*)sptr1, (const short*)sptr2, (short*)dptr, total, scale, op);
break;
case CV_32S:
muldiv_((const int*)sptr1, (const int*)sptr2, (int*)dptr, total, scale, op);
break;
case CV_32F:
muldiv_((const float*)sptr1, (const float*)sptr2, (float*)dptr, total, scale, op);
break;
case CV_64F:
muldiv_((const double*)sptr1, (const double*)sptr2, (double*)dptr, total, scale, op);
break;
default:
CV_Error(Error::StsUnsupportedFormat, "");
switch( srcDepth )
{
case CV_8U:
muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (uchar*)dptr, total, scale, op);
break;
case CV_8S:
muldiv_((const schar*)sptr1, (const schar*)sptr2, (schar*)dptr, total, scale, op);
break;
case CV_16U:
muldiv_((const ushort*)sptr1, (const ushort*)sptr2, (ushort*)dptr, total, scale, op);
break;
case CV_16S:
muldiv_((const short*)sptr1, (const short*)sptr2, (short*)dptr, total, scale, op);
break;
case CV_32S:
muldiv_((const int*)sptr1, (const int*)sptr2, (int*)dptr, total, scale, op);
break;
case CV_32F:
muldiv_((const float*)sptr1, (const float*)sptr2, (float*)dptr, total, scale, op);
break;
case CV_64F:
muldiv_((const double*)sptr1, (const double*)sptr2, (double*)dptr, total, scale, op);
break;
default:
CV_Error(Error::StsUnsupportedFormat, "");
}
}
else
{
if (srcDepth == CV_8U && dstDepth == CV_16U)
{
muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (ushort*)dptr, total, scale, op);
}
else if (srcDepth == CV_8S && dstDepth == CV_16S)
{
muldiv_((const schar*)sptr1, (const schar*)sptr2, (short*)dptr, total, scale, op);
}
else if (srcDepth == CV_8U && dstDepth == CV_32F)
{
muldiv_((const uchar*)sptr1, (const uchar*)sptr2, (float*)dptr, total, scale, op);
}
else if (srcDepth == CV_8S && dstDepth == CV_32F)
{
muldiv_((const schar*)sptr1, (const schar*)sptr2, (float*)dptr, total, scale, op);
}
else
{
CV_Error(Error::StsUnsupportedFormat, "This format combination is not supported yet");
}
}
}
}
void multiply(const Mat& src1, const Mat& src2, Mat& dst, double scale)
void multiply(const Mat& src1, const Mat& src2, Mat& dst, double scale, int ctype)
{
muldiv( src1, src2, dst, scale, '*' );
muldiv( src1, src2, dst, ctype, scale, '*' );
}
void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale)
void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale, int ctype)
{
muldiv( src1, src2, dst, scale, '/' );
muldiv( src1, src2, dst, ctype, scale, '/' );
}