mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 07:43:03 +04:00
Change behaviour of 16-bit multiply operator
- redefine 16-bit multiply operator to perform saturating multiply
instead of non-saturating multiply
- implement 8-bit multiply operator to perform saturating multiply
- implement v_mul_wrap() for 8-bit, 16-bit non-saturating multiply
- improve performance of v_mul_hi() for VSX
- update intrin tests with new changes
- replace unv 16-bit multiplication operator with v_mul_wrap due behavior changes
- Several improvements depend on vpisarev review
* initial forward declarations for universal intrinsics
* move emulating SSE intrinsics into separate file
* implement v_mul_expand for 8-bit
* reimplement saturating multiply using v_mul_expand + v_pack
* map v_expand, v_load_expand, v_load_expand_q to sse4.1
* fix overflow avx2::v_pack(uint32)
* implement two universal intrinsics v_expand_low and v_expand_high
This commit is contained in:
@@ -1014,8 +1014,8 @@ void accSqr_simd_(const uchar* src, float* dst, const uchar* mask, int len, int
|
||||
v_uint8x16 v_src = v_load(src + x);
|
||||
v_uint16x8 v_src0, v_src1;
|
||||
v_expand(v_src, v_src0, v_src1);
|
||||
v_src0 = v_src0 * v_src0;
|
||||
v_src1 = v_src1 * v_src1;
|
||||
v_src0 = v_mul_wrap(v_src0, v_src0);
|
||||
v_src1 = v_mul_wrap(v_src1, v_src1);
|
||||
|
||||
v_uint32x4 v_src00, v_src01, v_src10, v_src11;
|
||||
v_expand(v_src0, v_src00, v_src01);
|
||||
@@ -1040,8 +1040,8 @@ void accSqr_simd_(const uchar* src, float* dst, const uchar* mask, int len, int
|
||||
v_src = v_src & v_mask;
|
||||
v_uint16x8 v_src0, v_src1;
|
||||
v_expand(v_src, v_src0, v_src1);
|
||||
v_src0 = v_src0 * v_src0;
|
||||
v_src1 = v_src1 * v_src1;
|
||||
v_src0 = v_mul_wrap(v_src0, v_src0);
|
||||
v_src1 = v_mul_wrap(v_src1, v_src1);
|
||||
|
||||
v_uint32x4 v_src00, v_src01, v_src10, v_src11;
|
||||
v_expand(v_src0, v_src00, v_src01);
|
||||
@@ -1070,12 +1070,12 @@ void accSqr_simd_(const uchar* src, float* dst, const uchar* mask, int len, int
|
||||
v_expand(v_src0, v_src00, v_src01);
|
||||
v_expand(v_src1, v_src10, v_src11);
|
||||
v_expand(v_src2, v_src20, v_src21);
|
||||
v_src00 = v_src00 * v_src00;
|
||||
v_src01 = v_src01 * v_src01;
|
||||
v_src10 = v_src10 * v_src10;
|
||||
v_src11 = v_src11 * v_src11;
|
||||
v_src20 = v_src20 * v_src20;
|
||||
v_src21 = v_src21 * v_src21;
|
||||
v_src00 = v_mul_wrap(v_src00, v_src00);
|
||||
v_src01 = v_mul_wrap(v_src01, v_src01);
|
||||
v_src10 = v_mul_wrap(v_src10, v_src10);
|
||||
v_src11 = v_mul_wrap(v_src11, v_src11);
|
||||
v_src20 = v_mul_wrap(v_src20, v_src20);
|
||||
v_src21 = v_mul_wrap(v_src21, v_src21);
|
||||
|
||||
v_uint32x4 v_src000, v_src001, v_src010, v_src011;
|
||||
v_uint32x4 v_src100, v_src101, v_src110, v_src111;
|
||||
@@ -1776,8 +1776,8 @@ void accProd_simd_(const uchar* src1, const uchar* src2, float* dst, const uchar
|
||||
v_expand(v_2src, v_2src0, v_2src1);
|
||||
|
||||
v_uint16x8 v_src0, v_src1;
|
||||
v_src0 = v_1src0 * v_2src0;
|
||||
v_src1 = v_1src1 * v_2src1;
|
||||
v_src0 = v_mul_wrap(v_1src0, v_2src0);
|
||||
v_src1 = v_mul_wrap(v_1src1, v_2src1);
|
||||
|
||||
v_uint32x4 v_src00, v_src01, v_src10, v_src11;
|
||||
v_expand(v_src0, v_src00, v_src01);
|
||||
@@ -1808,8 +1808,8 @@ void accProd_simd_(const uchar* src1, const uchar* src2, float* dst, const uchar
|
||||
v_expand(v_2src, v_2src0, v_2src1);
|
||||
|
||||
v_uint16x8 v_src0, v_src1;
|
||||
v_src0 = v_1src0 * v_2src0;
|
||||
v_src1 = v_1src1 * v_2src1;
|
||||
v_src0 = v_mul_wrap(v_1src0, v_2src0);
|
||||
v_src1 = v_mul_wrap(v_1src1, v_2src1);
|
||||
|
||||
v_uint32x4 v_src00, v_src01, v_src10, v_src11;
|
||||
v_expand(v_src0, v_src00, v_src01);
|
||||
@@ -1846,12 +1846,12 @@ void accProd_simd_(const uchar* src1, const uchar* src2, float* dst, const uchar
|
||||
v_expand(v_2src2, v_2src20, v_2src21);
|
||||
|
||||
v_uint16x8 v_src00, v_src01, v_src10, v_src11, v_src20, v_src21;
|
||||
v_src00 = v_1src00 * v_2src00;
|
||||
v_src01 = v_1src01 * v_2src01;
|
||||
v_src10 = v_1src10 * v_2src10;
|
||||
v_src11 = v_1src11 * v_2src11;
|
||||
v_src20 = v_1src20 * v_2src20;
|
||||
v_src21 = v_1src21 * v_2src21;
|
||||
v_src00 = v_mul_wrap(v_1src00, v_2src00);
|
||||
v_src01 = v_mul_wrap(v_1src01, v_2src01);
|
||||
v_src10 = v_mul_wrap(v_1src10, v_2src10);
|
||||
v_src11 = v_mul_wrap(v_1src11, v_2src11);
|
||||
v_src20 = v_mul_wrap(v_1src20, v_2src20);
|
||||
v_src21 = v_mul_wrap(v_1src21, v_2src21);
|
||||
|
||||
v_uint32x4 v_src000, v_src001, v_src002, v_src003, v_src100, v_src101, v_src102, v_src103, v_src200, v_src201, v_src202, v_src203;
|
||||
v_expand(v_src00, v_src000, v_src001);
|
||||
|
||||
@@ -1825,7 +1825,7 @@ void hlineSmooth1N<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, const ufi
|
||||
const int VECSZ = v_uint16::nlanes;
|
||||
v_uint16 v_mul = vx_setall_u16(*((uint16_t*)m));
|
||||
for (; i <= lencn - VECSZ; i += VECSZ)
|
||||
v_store((uint16_t*)dst + i, v_mul*vx_load_expand(src + i));
|
||||
v_store((uint16_t*)dst + i, v_mul_wrap(v_mul, vx_load_expand(src + i)));
|
||||
#endif
|
||||
for (; i < lencn; i++)
|
||||
dst[i] = m[0] * src[i];
|
||||
@@ -1915,7 +1915,9 @@ void hlineSmooth3N<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, const ufi
|
||||
v_uint16 v_mul1 = vx_setall_u16(_m[1]);
|
||||
v_uint16 v_mul2 = vx_setall_u16(_m[2]);
|
||||
for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
|
||||
v_store((uint16_t*)dst, vx_load_expand(src - cn) * v_mul0 + vx_load_expand(src) * v_mul1 + vx_load_expand(src + cn) * v_mul2);
|
||||
v_store((uint16_t*)dst, v_mul_wrap(vx_load_expand(src - cn), v_mul0) +
|
||||
v_mul_wrap(vx_load_expand(src), v_mul1) +
|
||||
v_mul_wrap(vx_load_expand(src + cn), v_mul2));
|
||||
#endif
|
||||
for (; i < lencn; i++, src++, dst++)
|
||||
*dst = m[0] * src[-cn] + m[1] * src[0] + m[2] * src[cn];
|
||||
@@ -2089,7 +2091,8 @@ void hlineSmooth3Naba<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, const
|
||||
v_uint16 v_mul0 = vx_setall_u16(_m[0]);
|
||||
v_uint16 v_mul1 = vx_setall_u16(_m[1]);
|
||||
for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
|
||||
v_store((uint16_t*)dst, (vx_load_expand(src - cn) + vx_load_expand(src + cn)) * v_mul0 + vx_load_expand(src) * v_mul1);
|
||||
v_store((uint16_t*)dst, v_mul_wrap(vx_load_expand(src - cn) + vx_load_expand(src + cn), v_mul0) +
|
||||
v_mul_wrap(vx_load_expand(src), v_mul1));
|
||||
#endif
|
||||
for (; i < lencn; i++, src++, dst++)
|
||||
*((uint16_t*)dst) = ((uint16_t*)m)[1] * src[0] + ((uint16_t*)m)[0] * ((uint16_t)(src[-cn]) + (uint16_t)(src[cn]));
|
||||
@@ -2285,7 +2288,11 @@ void hlineSmooth5N<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, const ufi
|
||||
v_uint16 v_mul3 = vx_setall_u16(_m[3]);
|
||||
v_uint16 v_mul4 = vx_setall_u16(_m[4]);
|
||||
for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
|
||||
v_store((uint16_t*)dst, vx_load_expand(src - 2 * cn) * v_mul0 + vx_load_expand(src - cn) * v_mul1 + vx_load_expand(src) * v_mul2 + vx_load_expand(src + cn) * v_mul3 + vx_load_expand(src + 2 * cn) * v_mul4);
|
||||
v_store((uint16_t*)dst, v_mul_wrap(vx_load_expand(src - 2 * cn), v_mul0) +
|
||||
v_mul_wrap(vx_load_expand(src - cn), v_mul1) +
|
||||
v_mul_wrap(vx_load_expand(src), v_mul2) +
|
||||
v_mul_wrap(vx_load_expand(src + cn), v_mul3) +
|
||||
v_mul_wrap(vx_load_expand(src + 2 * cn), v_mul4));
|
||||
#endif
|
||||
for (; i < lencn; i++, src++, dst++)
|
||||
*dst = m[0] * src[-2*cn] + m[1] * src[-cn] + m[2] * src[0] + m[3] * src[cn] + m[4] * src[2*cn];
|
||||
@@ -2488,7 +2495,7 @@ void hlineSmooth5N14641<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, cons
|
||||
const int VECSZ = v_uint16::nlanes;
|
||||
v_uint16 v_6 = vx_setall_u16(6);
|
||||
for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
|
||||
v_store((uint16_t*)dst, (vx_load_expand(src) * v_6 + ((vx_load_expand(src - cn) + vx_load_expand(src + cn)) << 2) + vx_load_expand(src - 2 * cn) + vx_load_expand(src + 2 * cn)) << 4);
|
||||
v_store((uint16_t*)dst, (v_mul_wrap(vx_load_expand(src), v_6) + ((vx_load_expand(src - cn) + vx_load_expand(src + cn)) << 2) + vx_load_expand(src - 2 * cn) + vx_load_expand(src + 2 * cn)) << 4);
|
||||
#endif
|
||||
for (; i < lencn; i++, src++, dst++)
|
||||
*((uint16_t*)dst) = (uint16_t(src[0]) * 6 + ((uint16_t(src[-cn]) + uint16_t(src[cn])) << 2) + uint16_t(src[-2 * cn]) + uint16_t(src[2 * cn])) << 4;
|
||||
@@ -2689,7 +2696,9 @@ void hlineSmooth5Nabcba<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, cons
|
||||
v_uint16 v_mul1 = vx_setall_u16(_m[1]);
|
||||
v_uint16 v_mul2 = vx_setall_u16(_m[2]);
|
||||
for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
|
||||
v_store((uint16_t*)dst, (vx_load_expand(src - 2 * cn) + vx_load_expand(src + 2 * cn)) * v_mul0 + (vx_load_expand(src - cn) + vx_load_expand(src + cn))* v_mul1 + vx_load_expand(src) * v_mul2);
|
||||
v_store((uint16_t*)dst, v_mul_wrap(vx_load_expand(src - 2 * cn) + vx_load_expand(src + 2 * cn), v_mul0) +
|
||||
v_mul_wrap(vx_load_expand(src - cn) + vx_load_expand(src + cn), v_mul1) +
|
||||
v_mul_wrap(vx_load_expand(src), v_mul2));
|
||||
#endif
|
||||
for (; i < lencn; i++, src++, dst++)
|
||||
*((uint16_t*)dst) = ((uint16_t*)m)[0] * ((uint16_t)(src[-2 * cn]) + (uint16_t)(src[2 * cn])) + ((uint16_t*)m)[1] * ((uint16_t)(src[-cn]) + (uint16_t)(src[cn])) + ((uint16_t*)m)[2] * src[0];
|
||||
@@ -2804,9 +2813,9 @@ void hlineSmooth<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, const ufixe
|
||||
const int VECSZ = v_uint16::nlanes;
|
||||
for (; i <= lencn - VECSZ; i+=VECSZ, src+=VECSZ, dst+=VECSZ)
|
||||
{
|
||||
v_uint16 v_res0 = vx_load_expand(src) * vx_setall_u16(*((uint16_t*)m));
|
||||
v_uint16 v_res0 = v_mul_wrap(vx_load_expand(src), vx_setall_u16(*((uint16_t*)m)));
|
||||
for (int j = 1; j < n; j++)
|
||||
v_res0 += vx_load_expand(src + j * cn) * vx_setall_u16(*((uint16_t*)(m + j)));
|
||||
v_res0 += v_mul_wrap(vx_load_expand(src + j * cn), vx_setall_u16(*((uint16_t*)(m + j))));
|
||||
v_store((uint16_t*)dst, v_res0);
|
||||
}
|
||||
#endif
|
||||
@@ -2923,9 +2932,9 @@ void hlineSmoothONa_yzy_a<uint8_t, ufixedpoint16>(const uint8_t* src, int cn, co
|
||||
const int VECSZ = v_uint16::nlanes;
|
||||
for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
|
||||
{
|
||||
v_uint16 v_res0 = vx_load_expand(src + pre_shift * cn) * vx_setall_u16(*((uint16_t*)(m + pre_shift)));
|
||||
v_uint16 v_res0 = v_mul_wrap(vx_load_expand(src + pre_shift * cn), vx_setall_u16(*((uint16_t*)(m + pre_shift))));
|
||||
for (int j = 0; j < pre_shift; j ++)
|
||||
v_res0 += (vx_load_expand(src + j * cn) + vx_load_expand(src + (n - 1 - j)*cn)) * vx_setall_u16(*((uint16_t*)(m + j)));
|
||||
v_res0 += v_mul_wrap(vx_load_expand(src + j * cn) + vx_load_expand(src + (n - 1 - j)*cn), vx_setall_u16(*((uint16_t*)(m + j))));
|
||||
v_store((uint16_t*)dst, v_res0);
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user