1
0
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:
Sayed Adel
2018-09-12 21:32:34 +02:00
parent 1ff11c84ab
commit 5771fd693d
13 changed files with 744 additions and 193 deletions
+20 -20
View File
@@ -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);
+19 -10
View File
@@ -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