mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -7,6 +7,9 @@ ocv_add_dispatched_file(convert SSE2 AVX2)
|
||||
ocv_add_dispatched_file(convert_scale SSE2 AVX2)
|
||||
ocv_add_dispatched_file(count_non_zero SSE2 AVX2)
|
||||
ocv_add_dispatched_file(matmul SSE2 AVX2)
|
||||
ocv_add_dispatched_file(mean SSE2 AVX2)
|
||||
ocv_add_dispatched_file(merge SSE2 AVX2)
|
||||
ocv_add_dispatched_file(split SSE2 AVX2)
|
||||
ocv_add_dispatched_file(sum SSE2 AVX2)
|
||||
|
||||
# dispatching for accuracy tests
|
||||
|
||||
@@ -234,7 +234,12 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
|
||||
inline vtyp vx_##loadsfx##_low(const typ* ptr) { return prefix##_##loadsfx##_low(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_halves(const typ* ptr0, const typ* ptr1) { return prefix##_##loadsfx##_halves(ptr0, ptr1); } \
|
||||
inline void vx_store(typ* ptr, const vtyp& v) { return v_store(ptr, v); } \
|
||||
inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); }
|
||||
inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); } \
|
||||
inline vtyp vx_lut(const typ* ptr, const int* idx) { return prefix##_lut(ptr, idx); } \
|
||||
inline vtyp vx_lut_pairs(const typ* ptr, const int* idx) { return prefix##_lut_pairs(ptr, idx); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
|
||||
inline vtyp vx_lut_quads(const typ* ptr, const int* idx) { return prefix##_lut_quads(ptr, idx); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
|
||||
inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
|
||||
@@ -244,6 +249,7 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(typ, vtyp, short_typ, wtyp, qtyp, prefix, loadsfx) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(typ, vtyp, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix)
|
||||
|
||||
@@ -251,14 +257,19 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(uchar, v_uint8, u8, v_uint16, v_uint32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(schar, v_int8, s8, v_int16, v_int32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(ushort, v_uint16, u16, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(ushort, v_uint16, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(ushort, v_uint32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(short, v_int16, s16, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(short, v_int16, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(short, v_int32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(int, v_int32, s32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(int, v_int32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(int, v_int64, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(unsigned, v_uint32, u32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(unsigned, v_uint32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(unsigned, v_uint64, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(float, v_float32, f32, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LUT_QUAD(float, v_float32, prefix) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(int64, v_int64, s64, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(uint64, v_uint64, u64, prefix, load) \
|
||||
CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(float16_t, v_float32, prefix)
|
||||
@@ -335,11 +346,11 @@ namespace CV__SIMD_NAMESPACE {
|
||||
typedef v_uint64x4 v_uint64;
|
||||
typedef v_int64x4 v_int64;
|
||||
typedef v_float32x8 v_float32;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
|
||||
#if CV_SIMD256_64F
|
||||
typedef v_float64x4 v_float64;
|
||||
#endif
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
|
||||
#endif
|
||||
inline void vx_cleanup() { v256_cleanup(); }
|
||||
} // namespace
|
||||
using namespace CV__SIMD_NAMESPACE;
|
||||
@@ -358,11 +369,9 @@ namespace CV__SIMD_NAMESPACE {
|
||||
typedef v_uint64x2 v_uint64;
|
||||
typedef v_int64x2 v_int64;
|
||||
typedef v_float32x4 v_float32;
|
||||
#if CV_SIMD128_64F
|
||||
typedef v_float64x2 v_float64;
|
||||
#endif
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v)
|
||||
#if CV_SIMD128_64F
|
||||
typedef v_float64x2 v_float64;
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v, load)
|
||||
#endif
|
||||
inline void vx_cleanup() { v_cleanup(); }
|
||||
|
||||
@@ -1417,6 +1417,97 @@ inline v_float64x4 v_cvt_f64_high(const v_float32x8& a)
|
||||
|
||||
////////////// Lookup table access ////////////////////
|
||||
|
||||
inline v_int8x32 v256_lut(const schar* tab, const int* idx)
|
||||
{
|
||||
return v_int8x32(_mm256_setr_epi8(tab[idx[ 0]], tab[idx[ 1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
|
||||
tab[idx[ 8]], tab[idx[ 9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]],
|
||||
tab[idx[16]], tab[idx[17]], tab[idx[18]], tab[idx[19]], tab[idx[20]], tab[idx[21]], tab[idx[22]], tab[idx[23]],
|
||||
tab[idx[24]], tab[idx[25]], tab[idx[26]], tab[idx[27]], tab[idx[28]], tab[idx[29]], tab[idx[30]], tab[idx[31]]));
|
||||
}
|
||||
inline v_int8x32 v256_lut_pairs(const schar* tab, const int* idx)
|
||||
{
|
||||
return v_int8x32(_mm256_setr_epi16(*(const short*)(tab + idx[ 0]), *(const short*)(tab + idx[ 1]), *(const short*)(tab + idx[ 2]), *(const short*)(tab + idx[ 3]),
|
||||
*(const short*)(tab + idx[ 4]), *(const short*)(tab + idx[ 5]), *(const short*)(tab + idx[ 6]), *(const short*)(tab + idx[ 7]),
|
||||
*(const short*)(tab + idx[ 8]), *(const short*)(tab + idx[ 9]), *(const short*)(tab + idx[10]), *(const short*)(tab + idx[11]),
|
||||
*(const short*)(tab + idx[12]), *(const short*)(tab + idx[13]), *(const short*)(tab + idx[14]), *(const short*)(tab + idx[15])));
|
||||
}
|
||||
inline v_int8x32 v256_lut_quads(const schar* tab, const int* idx)
|
||||
{
|
||||
return v_int8x32(_mm256_i32gather_epi32((const int*)tab, _mm256_loadu_si256((const __m256i*)idx), 1));
|
||||
}
|
||||
inline v_uint8x32 v256_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut((const schar *)tab, idx)); }
|
||||
inline v_uint8x32 v256_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x32 v256_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v256_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
inline v_int16x16 v256_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x16(_mm256_setr_epi16(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
|
||||
tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]]));
|
||||
}
|
||||
inline v_int16x16 v256_lut_pairs(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x16(_mm256_i32gather_epi32((const int*)tab, _mm256_loadu_si256((const __m256i*)idx), 2));
|
||||
}
|
||||
inline v_int16x16 v256_lut_quads(const short* tab, const int* idx)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return v_int16x16(_mm256_i32gather_epi64((const long long int*)tab, _mm_loadu_si128((const __m128i*)idx), 2));//Looks like intrinsic has wrong definition
|
||||
#else
|
||||
return v_int16x16(_mm256_i32gather_epi64((const int64*)tab, _mm_loadu_si128((const __m128i*)idx), 2));
|
||||
#endif
|
||||
}
|
||||
inline v_uint16x16 v256_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v256_lut((const short *)tab, idx)); }
|
||||
inline v_uint16x16 v256_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v256_lut_pairs((const short *)tab, idx)); }
|
||||
inline v_uint16x16 v256_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v256_lut_quads((const short *)tab, idx)); }
|
||||
|
||||
inline v_int32x8 v256_lut(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x8(_mm256_i32gather_epi32(tab, _mm256_loadu_si256((const __m256i*)idx), 4));
|
||||
}
|
||||
inline v_int32x8 v256_lut_pairs(const int* tab, const int* idx)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return v_int32x8(_mm256_i32gather_epi64((const long long int*)tab, _mm_loadu_si128((const __m128i*)idx), 4));
|
||||
#else
|
||||
return v_int32x8(_mm256_i32gather_epi64((const int64*)tab, _mm_loadu_si128((const __m128i*)idx), 4));
|
||||
#endif
|
||||
}
|
||||
inline v_int32x8 v256_lut_quads(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x8(_mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((const __m128i*)(tab + idx[0]))), _mm_loadu_si128((const __m128i*)(tab + idx[1])), 0x1));
|
||||
}
|
||||
inline v_uint32x8 v256_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v256_lut((const int *)tab, idx)); }
|
||||
inline v_uint32x8 v256_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v256_lut_pairs((const int *)tab, idx)); }
|
||||
inline v_uint32x8 v256_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v256_lut_quads((const int *)tab, idx)); }
|
||||
|
||||
inline v_int64x4 v256_lut(const int64* tab, const int* idx)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return v_int64x4(_mm256_i32gather_epi64((const long long int*)tab, _mm_loadu_si128((const __m128i*)idx), 8));
|
||||
#else
|
||||
return v_int64x4(_mm256_i32gather_epi64(tab, _mm_loadu_si128((const __m128i*)idx), 8));
|
||||
#endif
|
||||
}
|
||||
inline v_int64x4 v256_lut_pairs(const int64* tab, const int* idx)
|
||||
{
|
||||
return v_int64x4(_mm256_insertf128_si256(_mm256_castsi128_si256(_mm_loadu_si128((const __m128i*)(tab + idx[0]))), _mm_loadu_si128((const __m128i*)(tab + idx[1])), 0x1));
|
||||
}
|
||||
inline v_uint64x4 v256_lut(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v256_lut((const int64 *)tab, idx)); }
|
||||
inline v_uint64x4 v256_lut_pairs(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v256_lut_pairs((const int64 *)tab, idx)); }
|
||||
|
||||
inline v_float32x8 v256_lut(const float* tab, const int* idx)
|
||||
{
|
||||
return v_float32x8(_mm256_i32gather_ps(tab, _mm256_loadu_si256((const __m256i*)idx), 4));
|
||||
}
|
||||
inline v_float32x8 v256_lut_pairs(const float* tab, const int* idx) { return v_reinterpret_as_f32(v256_lut_pairs((const int *)tab, idx)); }
|
||||
inline v_float32x8 v256_lut_quads(const float* tab, const int* idx) { return v_reinterpret_as_f32(v256_lut_quads((const int *)tab, idx)); }
|
||||
|
||||
inline v_float64x4 v256_lut(const double* tab, const int* idx)
|
||||
{
|
||||
return v_float64x4(_mm256_i32gather_pd(tab, _mm_loadu_si128((const __m128i*)idx), 8));
|
||||
}
|
||||
inline v_float64x4 v256_lut_pairs(const double* tab, const int* idx) { return v_float64x4(_mm256_insertf128_pd(_mm256_castpd128_pd256(_mm_loadu_pd(tab + idx[0])), _mm_loadu_pd(tab + idx[1]), 0x1)); }
|
||||
|
||||
inline v_int32x8 v_lut(const int* tab, const v_int32x8& idxvec)
|
||||
{
|
||||
return v_int32x8(_mm256_i32gather_epi32(tab, idxvec.val, 4));
|
||||
@@ -1476,6 +1567,49 @@ inline void v_lut_deinterleave(const double* tab, const v_int32x8& idxvec, v_flo
|
||||
y = v_float64x4(_mm256_unpackhi_pd(xy02, xy13));
|
||||
}
|
||||
|
||||
inline v_int8x32 v_interleave_pairs(const v_int8x32& vec)
|
||||
{
|
||||
return v_int8x32(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0d0e0c0b090a08, 0x0705060403010200, 0x0f0d0e0c0b090a08, 0x0705060403010200)));
|
||||
}
|
||||
inline v_uint8x32 v_interleave_pairs(const v_uint8x32& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
|
||||
inline v_int8x32 v_interleave_quads(const v_int8x32& vec)
|
||||
{
|
||||
return v_int8x32(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0b0e0a0d090c08, 0x0703060205010400, 0x0f0b0e0a0d090c08, 0x0703060205010400)));
|
||||
}
|
||||
inline v_uint8x32 v_interleave_quads(const v_uint8x32& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x16 v_interleave_pairs(const v_int16x16& vec)
|
||||
{
|
||||
return v_int16x16(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0e0b0a0d0c0908, 0x0706030205040100, 0x0f0e0b0a0d0c0908, 0x0706030205040100)));
|
||||
}
|
||||
inline v_uint16x16 v_interleave_pairs(const v_uint16x16& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
|
||||
inline v_int16x16 v_interleave_quads(const v_int16x16& vec)
|
||||
{
|
||||
return v_int16x16(_mm256_shuffle_epi8(vec.val, _mm256_set_epi64x(0x0f0e07060d0c0504, 0x0b0a030209080100, 0x0f0e07060d0c0504, 0x0b0a030209080100)));
|
||||
}
|
||||
inline v_uint16x16 v_interleave_quads(const v_uint16x16& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int32x8 v_interleave_pairs(const v_int32x8& vec)
|
||||
{
|
||||
return v_int32x8(_mm256_shuffle_epi32(vec.val, _MM_SHUFFLE(3, 1, 2, 0)));
|
||||
}
|
||||
inline v_uint32x8 v_interleave_pairs(const v_uint32x8& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_float32x8 v_interleave_pairs(const v_float32x8& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
|
||||
inline v_int8x32 v_pack_triplets(const v_int8x32& vec)
|
||||
{
|
||||
return v_int8x32(_mm256_permutevar8x32_epi32(_mm256_shuffle_epi8(vec.val, _mm256_broadcastsi128_si256(_mm_set_epi64x(0xffffff0f0e0d0c0a, 0x0908060504020100))),
|
||||
_mm256_set_epi64x(0x0000000700000007, 0x0000000600000005, 0x0000000400000002, 0x0000000100000000)));
|
||||
}
|
||||
inline v_uint8x32 v_pack_triplets(const v_uint8x32& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x16 v_pack_triplets(const v_int16x16& vec)
|
||||
{
|
||||
return v_int16x16(_mm256_permutevar8x32_epi32(_mm256_shuffle_epi8(vec.val, _mm256_broadcastsi128_si256(_mm_set_epi64x(0xffff0f0e0d0c0b0a, 0x0908050403020100))),
|
||||
_mm256_set_epi64x(0x0000000700000007, 0x0000000600000005, 0x0000000400000002, 0x0000000100000000)));
|
||||
}
|
||||
inline v_uint16x16 v_pack_triplets(const v_uint16x16& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
////////// Matrix operations /////////
|
||||
|
||||
inline v_int32x8 v_dotprod(const v_int16x16& a, const v_int16x16& b)
|
||||
|
||||
@@ -1799,6 +1799,28 @@ template<int n> inline v_reg<double, n> v_cvt_f64(const v_reg<float, n*2>& a)
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut(const _Tp* tab, const int* idx)
|
||||
{
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for (int i = 0; i < V_TypeTraits<_Tp>::nlanes128; i++)
|
||||
c.s[i] = tab[idx[i]];
|
||||
return c;
|
||||
}
|
||||
template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut_pairs(const _Tp* tab, const int* idx)
|
||||
{
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for (int i = 0; i < V_TypeTraits<_Tp>::nlanes128; i++)
|
||||
c.s[i] = tab[idx[i / 2] + i % 2];
|
||||
return c;
|
||||
}
|
||||
template<typename _Tp> inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_lut_quads(const _Tp* tab, const int* idx)
|
||||
{
|
||||
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
|
||||
for (int i = 0; i < V_TypeTraits<_Tp>::nlanes128; i++)
|
||||
c.s[i] = tab[idx[i / 4] + i % 4];
|
||||
return c;
|
||||
}
|
||||
|
||||
template<int n> inline v_reg<int, n> v_lut(const int* tab, const v_reg<int, n>& idx)
|
||||
{
|
||||
v_reg<int, n> c;
|
||||
@@ -1807,6 +1829,14 @@ template<int n> inline v_reg<int, n> v_lut(const int* tab, const v_reg<int, n>&
|
||||
return c;
|
||||
}
|
||||
|
||||
template<int n> inline v_reg<unsigned, n> v_lut(const unsigned* tab, const v_reg<int, n>& idx)
|
||||
{
|
||||
v_reg<int, n> c;
|
||||
for (int i = 0; i < n; i++)
|
||||
c.s[i] = tab[idx.s[i]];
|
||||
return c;
|
||||
}
|
||||
|
||||
template<int n> inline v_reg<float, n> v_lut(const float* tab, const v_reg<int, n>& idx)
|
||||
{
|
||||
v_reg<float, n> c;
|
||||
@@ -1845,6 +1875,49 @@ template<int n> inline void v_lut_deinterleave(const double* tab, const v_reg<in
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, int n> inline v_reg<_Tp, n> v_interleave_pairs(const v_reg<_Tp, n>& vec)
|
||||
{
|
||||
v_reg<float, n> c;
|
||||
for (int i = 0; i < n/4; i++)
|
||||
{
|
||||
c.s[4*i ] = vec.s[4*i ];
|
||||
c.s[4*i+1] = vec.s[4*i+2];
|
||||
c.s[4*i+2] = vec.s[4*i+1];
|
||||
c.s[4*i+3] = vec.s[4*i+3];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename _Tp, int n> inline v_reg<_Tp, n> v_interleave_quads(const v_reg<_Tp, n>& vec)
|
||||
{
|
||||
v_reg<float, n> c;
|
||||
for (int i = 0; i < n/8; i++)
|
||||
{
|
||||
c.s[8*i ] = vec.s[8*i ];
|
||||
c.s[8*i+1] = vec.s[8*i+4];
|
||||
c.s[8*i+2] = vec.s[8*i+1];
|
||||
c.s[8*i+3] = vec.s[8*i+5];
|
||||
c.s[8*i+4] = vec.s[8*i+2];
|
||||
c.s[8*i+5] = vec.s[8*i+6];
|
||||
c.s[8*i+6] = vec.s[8*i+3];
|
||||
c.s[8*i+7] = vec.s[8*i+7];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template<typename _Tp, int n> inline v_reg<_Tp, n> v_pack_triplets(const v_reg<_Tp, n>& vec)
|
||||
{
|
||||
v_reg<float, n> c;
|
||||
int j = 0;
|
||||
for (int i = 0; i < n/4; i++)
|
||||
{
|
||||
c.s[3*i ] = vec.s[4*i ];
|
||||
c.s[3*i+1] = vec.s[4*i+1];
|
||||
c.s[3*i+2] = vec.s[4*i+2];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/** @brief Transpose 4x4 matrix
|
||||
|
||||
Scheme:
|
||||
|
||||
@@ -1572,6 +1572,162 @@ inline v_float64x2 v_cvt_f64_high(const v_float32x4& a)
|
||||
|
||||
////////////// Lookup table access ////////////////////
|
||||
|
||||
inline v_int8x16 v_lut(const schar* tab, const int* idx)
|
||||
{
|
||||
schar CV_DECL_ALIGNED(32) elems[16] =
|
||||
{
|
||||
tab[idx[ 0]],
|
||||
tab[idx[ 1]],
|
||||
tab[idx[ 2]],
|
||||
tab[idx[ 3]],
|
||||
tab[idx[ 4]],
|
||||
tab[idx[ 5]],
|
||||
tab[idx[ 6]],
|
||||
tab[idx[ 7]],
|
||||
tab[idx[ 8]],
|
||||
tab[idx[ 9]],
|
||||
tab[idx[10]],
|
||||
tab[idx[11]],
|
||||
tab[idx[12]],
|
||||
tab[idx[13]],
|
||||
tab[idx[14]],
|
||||
tab[idx[15]]
|
||||
};
|
||||
return v_int8x16(vld1q_s8(elems));
|
||||
}
|
||||
inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
|
||||
{
|
||||
short CV_DECL_ALIGNED(32) elems[8] =
|
||||
{
|
||||
*(short*)(tab+idx[0]),
|
||||
*(short*)(tab+idx[1]),
|
||||
*(short*)(tab+idx[2]),
|
||||
*(short*)(tab+idx[3]),
|
||||
*(short*)(tab+idx[4]),
|
||||
*(short*)(tab+idx[5]),
|
||||
*(short*)(tab+idx[6]),
|
||||
*(short*)(tab+idx[7])
|
||||
};
|
||||
return v_int8x16(vreinterpretq_s8_s16(vld1q_s16(elems)));
|
||||
}
|
||||
inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) elems[4] =
|
||||
{
|
||||
*(int*)(tab + idx[0]),
|
||||
*(int*)(tab + idx[1]),
|
||||
*(int*)(tab + idx[2]),
|
||||
*(int*)(tab + idx[3])
|
||||
};
|
||||
return v_int8x16(vreinterpretq_s8_s32(vld1q_s32(elems)));
|
||||
}
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((schar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
short CV_DECL_ALIGNED(32) elems[8] =
|
||||
{
|
||||
tab[idx[0]],
|
||||
tab[idx[1]],
|
||||
tab[idx[2]],
|
||||
tab[idx[3]],
|
||||
tab[idx[4]],
|
||||
tab[idx[5]],
|
||||
tab[idx[6]],
|
||||
tab[idx[7]]
|
||||
};
|
||||
return v_int16x8(vld1q_s16(elems));
|
||||
}
|
||||
inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) elems[4] =
|
||||
{
|
||||
*(int*)(tab + idx[0]),
|
||||
*(int*)(tab + idx[1]),
|
||||
*(int*)(tab + idx[2]),
|
||||
*(int*)(tab + idx[3])
|
||||
};
|
||||
return v_int16x8(vreinterpretq_s16_s32(vld1q_s32(elems)));
|
||||
}
|
||||
inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
|
||||
{
|
||||
int64 CV_DECL_ALIGNED(32) elems[2] =
|
||||
{
|
||||
*(int64*)(tab + idx[0]),
|
||||
*(int64*)(tab + idx[1])
|
||||
};
|
||||
return v_int16x8(vreinterpretq_s16_s64(vld1q_s64(elems)));
|
||||
}
|
||||
inline v_uint16x8 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((short*)tab, idx)); }
|
||||
inline v_uint16x8 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((short*)tab, idx)); }
|
||||
inline v_uint16x8 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((short*)tab, idx)); }
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const int* idx)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) elems[4] =
|
||||
{
|
||||
tab[idx[0]],
|
||||
tab[idx[1]],
|
||||
tab[idx[2]],
|
||||
tab[idx[3]]
|
||||
};
|
||||
return v_int32x4(vld1q_s32(elems));
|
||||
}
|
||||
inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
|
||||
{
|
||||
int64 CV_DECL_ALIGNED(32) elems[2] =
|
||||
{
|
||||
*(int64*)(tab + idx[0]),
|
||||
*(int64*)(tab + idx[1])
|
||||
};
|
||||
return v_int32x4(vreinterpretq_s32_s64(vld1q_s64(elems)));
|
||||
}
|
||||
inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x4(vld1q_s32(tab + idx[0]));
|
||||
}
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut((int*)tab, idx)); }
|
||||
inline v_uint32x4 v_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_pairs((int*)tab, idx)); }
|
||||
inline v_uint32x4 v_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_quads((int*)tab, idx)); }
|
||||
|
||||
inline v_int64x2 v_lut(const int64_t* tab, const int* idx)
|
||||
{
|
||||
return v_int64x2(vcombine_s64(vcreate_s64(tab[idx[0]]), vcreate_s64(tab[idx[1]])));
|
||||
}
|
||||
inline v_int64x2 v_lut_pairs(const int64_t* tab, const int* idx)
|
||||
{
|
||||
return v_int64x2(vld1q_s64(tab + idx[0]));
|
||||
}
|
||||
inline v_uint64x2 v_lut(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
|
||||
inline v_uint64x2 v_lut_pairs(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); }
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const int* idx)
|
||||
{
|
||||
float CV_DECL_ALIGNED(32) elems[4] =
|
||||
{
|
||||
tab[idx[0]],
|
||||
tab[idx[1]],
|
||||
tab[idx[2]],
|
||||
tab[idx[3]]
|
||||
};
|
||||
return v_float32x4(vld1q_f32(elems));
|
||||
}
|
||||
inline v_float32x4 v_lut_pairs(const float* tab, const int* idx)
|
||||
{
|
||||
uint64 CV_DECL_ALIGNED(32) elems[2] =
|
||||
{
|
||||
*(uint64*)(tab + idx[0]),
|
||||
*(uint64*)(tab + idx[1])
|
||||
};
|
||||
return v_float32x4(vreinterpretq_f32_u64(vld1q_u64(elems)));
|
||||
}
|
||||
inline v_float32x4 v_lut_quads(const float* tab, const int* idx)
|
||||
{
|
||||
return v_float32x4(vld1q_f32(tab + idx[0]));
|
||||
}
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) elems[4] =
|
||||
@@ -1584,6 +1740,18 @@ inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
return v_int32x4(vld1q_s32(elems));
|
||||
}
|
||||
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
unsigned CV_DECL_ALIGNED(32) elems[4] =
|
||||
{
|
||||
tab[vgetq_lane_s32(idxvec.val, 0)],
|
||||
tab[vgetq_lane_s32(idxvec.val, 1)],
|
||||
tab[vgetq_lane_s32(idxvec.val, 2)],
|
||||
tab[vgetq_lane_s32(idxvec.val, 3)]
|
||||
};
|
||||
return v_uint32x4(vld1q_u32(elems));
|
||||
}
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
float CV_DECL_ALIGNED(32) elems[4] =
|
||||
@@ -1614,7 +1782,64 @@ inline void v_lut_deinterleave(const float* tab, const v_int32x4& idxvec, v_floa
|
||||
y = v_float32x4(tab[idx[0]+1], tab[idx[1]+1], tab[idx[2]+1], tab[idx[3]+1]);
|
||||
}
|
||||
|
||||
inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
|
||||
{
|
||||
return v_int8x16(vcombine_s8(vtbl1_s8(vget_low_s8(vec.val), vcreate_s8(0x0705060403010200)), vtbl1_s8(vget_high_s8(vec.val), vcreate_s8(0x0705060403010200))));
|
||||
}
|
||||
inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
|
||||
inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
|
||||
{
|
||||
return v_int8x16(vcombine_s8(vtbl1_s8(vget_low_s8(vec.val), vcreate_s8(0x0703060205010400)), vtbl1_s8(vget_high_s8(vec.val), vcreate_s8(0x0703060205010400))));
|
||||
}
|
||||
inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
|
||||
{
|
||||
return v_int16x8(vreinterpretq_s16_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0706030205040100)), vtbl1_s8(vget_high_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0706030205040100)))));
|
||||
}
|
||||
inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
|
||||
inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
|
||||
{
|
||||
return v_int16x8(vreinterpretq_s16_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0b0a030209080100)), vtbl1_s8(vget_high_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0b0a030209080100)))));
|
||||
}
|
||||
inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
|
||||
{
|
||||
int32x2x2_t res = vzip_s32(vget_low_s32(vec.val), vget_high_s32(vec.val));
|
||||
return v_int32x4(vcombine_s32(res.val[0], res.val[1]));
|
||||
}
|
||||
inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_float32x4 v_interleave_pairs(const v_float32x4& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
|
||||
inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
|
||||
{
|
||||
return v_int8x16(vextq_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vec.val), vcreate_s8(0x0605040201000000)), vtbl1_s8(vget_high_s8(vec.val), vcreate_s8(0x0807060504020100))), vdupq_n_s8(0), 2));
|
||||
}
|
||||
inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
|
||||
{
|
||||
return v_int16x8(vreinterpretq_s16_s8(vextq_s8(vcombine_s8(vtbl1_s8(vget_low_s8(vreinterpretq_s8_s16(vec.val)), vcreate_s8(0x0504030201000000)), vget_high_s8(vreinterpretq_s8_s16(vec.val))), vdupq_n_s8(0), 2)));
|
||||
}
|
||||
inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
#if CV_SIMD128_64F
|
||||
inline v_float64x2 v_lut(const double* tab, const int* idx)
|
||||
{
|
||||
double CV_DECL_ALIGNED(32) elems[2] =
|
||||
{
|
||||
tab[idx[0]],
|
||||
tab[idx[1]]
|
||||
};
|
||||
return v_float64x2(vld1q_f64(elems));
|
||||
}
|
||||
|
||||
inline v_float64x2 v_lut_pairs(const double* tab, const int* idx)
|
||||
{
|
||||
return v_float64x2(vld1q_f64(tab + idx[0]));
|
||||
}
|
||||
|
||||
inline v_float64x2 v_lut(const double* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
double CV_DECL_ALIGNED(32) elems[2] =
|
||||
|
||||
@@ -2699,6 +2699,126 @@ inline void v_store_fp16(short* ptr, const v_float32x4& a)
|
||||
|
||||
////////////// Lookup table access ////////////////////
|
||||
|
||||
inline v_int8x16 v_lut(const schar* tab, const int* idx)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return v_int8x16(_mm_setr_epi8(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]],
|
||||
tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]]));
|
||||
#else
|
||||
return v_int8x16(_mm_setr_epi64(
|
||||
_mm_setr_pi8(tab[idx[0]], tab[idx[1]], tab[idx[ 2]], tab[idx[ 3]], tab[idx[ 4]], tab[idx[ 5]], tab[idx[ 6]], tab[idx[ 7]]),
|
||||
_mm_setr_pi8(tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]])
|
||||
));
|
||||
#endif
|
||||
}
|
||||
inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return v_int8x16(_mm_setr_epi16(*(const short*)(tab + idx[0]), *(const short*)(tab + idx[1]), *(const short*)(tab + idx[2]), *(const short*)(tab + idx[3]),
|
||||
*(const short*)(tab + idx[4]), *(const short*)(tab + idx[5]), *(const short*)(tab + idx[6]), *(const short*)(tab + idx[7])));
|
||||
#else
|
||||
return v_int8x16(_mm_setr_epi64(
|
||||
_mm_setr_pi16(*(const short*)(tab + idx[0]), *(const short*)(tab + idx[1]), *(const short*)(tab + idx[2]), *(const short*)(tab + idx[3])),
|
||||
_mm_setr_pi16(*(const short*)(tab + idx[4]), *(const short*)(tab + idx[5]), *(const short*)(tab + idx[6]), *(const short*)(tab + idx[7]))
|
||||
));
|
||||
#endif
|
||||
}
|
||||
inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return v_int8x16(_mm_setr_epi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1]),
|
||||
*(const int*)(tab + idx[2]), *(const int*)(tab + idx[3])));
|
||||
#else
|
||||
return v_int8x16(_mm_setr_epi64(
|
||||
_mm_setr_pi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1])),
|
||||
_mm_setr_pi32(*(const int*)(tab + idx[2]), *(const int*)(tab + idx[3]))
|
||||
));
|
||||
#endif
|
||||
}
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((const schar *)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar *)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar *)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return v_int16x8(_mm_setr_epi16(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]],
|
||||
tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]]));
|
||||
#else
|
||||
return v_int16x8(_mm_setr_epi64(
|
||||
_mm_setr_pi16(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]),
|
||||
_mm_setr_pi16(tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]])
|
||||
));
|
||||
#endif
|
||||
}
|
||||
inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return v_int16x8(_mm_setr_epi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1]),
|
||||
*(const int*)(tab + idx[2]), *(const int*)(tab + idx[3])));
|
||||
#else
|
||||
return v_int16x8(_mm_setr_epi64(
|
||||
_mm_setr_pi32(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1])),
|
||||
_mm_setr_pi32(*(const int*)(tab + idx[2]), *(const int*)(tab + idx[3]))
|
||||
));
|
||||
#endif
|
||||
}
|
||||
inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x8(_mm_set_epi64x(*(const int64_t*)(tab + idx[1]), *(const int64_t*)(tab + idx[0])));
|
||||
}
|
||||
inline v_uint16x8 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((const short *)tab, idx)); }
|
||||
inline v_uint16x8 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((const short *)tab, idx)); }
|
||||
inline v_uint16x8 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((const short *)tab, idx)); }
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const int* idx)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
return v_int32x4(_mm_setr_epi32(tab[idx[0]], tab[idx[1]],
|
||||
tab[idx[2]], tab[idx[3]]));
|
||||
#else
|
||||
return v_int32x4(_mm_setr_epi64(
|
||||
_mm_setr_pi32(tab[idx[0]], tab[idx[1]]),
|
||||
_mm_setr_pi32(tab[idx[2]], tab[idx[3]])
|
||||
));
|
||||
#endif
|
||||
}
|
||||
inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x4(_mm_set_epi64x(*(const int64_t*)(tab + idx[1]), *(const int64_t*)(tab + idx[0])));
|
||||
}
|
||||
inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x4(_mm_load_si128((const __m128i*)(tab + idx[0])));
|
||||
}
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut((const int *)tab, idx)); }
|
||||
inline v_uint32x4 v_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_pairs((const int *)tab, idx)); }
|
||||
inline v_uint32x4 v_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_quads((const int *)tab, idx)); }
|
||||
|
||||
inline v_int64x2 v_lut(const int64_t* tab, const int* idx)
|
||||
{
|
||||
return v_int64x2(_mm_set_epi64x(tab[idx[1]], tab[idx[0]]));
|
||||
}
|
||||
inline v_int64x2 v_lut_pairs(const int64_t* tab, const int* idx)
|
||||
{
|
||||
return v_int64x2(_mm_load_si128((const __m128i*)(tab + idx[0])));
|
||||
}
|
||||
inline v_uint64x2 v_lut(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
|
||||
inline v_uint64x2 v_lut_pairs(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); }
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const int* idx)
|
||||
{
|
||||
return v_float32x4(_mm_setr_ps(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]));
|
||||
}
|
||||
inline v_float32x4 v_lut_pairs(const float* tab, const int* idx) { return v_reinterpret_as_f32(v_lut_pairs((const int *)tab, idx)); }
|
||||
inline v_float32x4 v_lut_quads(const float* tab, const int* idx) { return v_reinterpret_as_f32(v_lut_quads((const int *)tab, idx)); }
|
||||
|
||||
inline v_float64x2 v_lut(const double* tab, const int* idx)
|
||||
{
|
||||
return v_float64x2(_mm_setr_pd(tab[idx[0]], tab[idx[1]]));
|
||||
}
|
||||
inline v_float64x2 v_lut_pairs(const double* tab, const int* idx) { return v_float64x2(_mm_castsi128_pd(_mm_load_si128((const __m128i*)(tab + idx[0])))); }
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
@@ -2706,6 +2826,11 @@ inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
return v_int32x4(_mm_setr_epi32(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]));
|
||||
}
|
||||
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
return v_reinterpret_as_u32(v_lut((const int *)tab, idxvec));
|
||||
}
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
@@ -2751,6 +2876,77 @@ inline void v_lut_deinterleave(const double* tab, const v_int32x4& idxvec, v_flo
|
||||
y = v_float64x2(_mm_unpackhi_pd(xy0, xy1));
|
||||
}
|
||||
|
||||
inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
|
||||
{
|
||||
#if CV_SSSE3
|
||||
return v_int8x16(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0d0e0c0b090a08, 0x0705060403010200)));
|
||||
#else
|
||||
__m128i a = _mm_shufflelo_epi16(vec.val, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
a = _mm_shufflehi_epi16(a, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
a = _mm_shuffle_epi32(a, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
return v_int8x16(_mm_unpacklo_epi8(a, _mm_unpackhi_epi64(a, a)));
|
||||
#endif
|
||||
}
|
||||
inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
|
||||
inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
|
||||
{
|
||||
#if CV_SSSE3
|
||||
return v_int8x16(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0b0e0a0d090c08, 0x0703060205010400)));
|
||||
#else
|
||||
__m128i a = _mm_shuffle_epi32(vec.val, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
return v_int8x16(_mm_unpacklo_epi8(a, _mm_unpackhi_epi64(a, a)));
|
||||
#endif
|
||||
}
|
||||
inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
|
||||
{
|
||||
#if CV_SSSE3
|
||||
return v_int16x8(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0e0b0a0d0c0908, 0x0706030205040100)));
|
||||
#else
|
||||
__m128i a = _mm_shufflelo_epi16(vec.val, _MM_SHUFFLE(3, 1, 2, 0));
|
||||
return v_int16x8(_mm_shufflehi_epi16(a, _MM_SHUFFLE(3, 1, 2, 0)));
|
||||
#endif
|
||||
}
|
||||
inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
|
||||
inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
|
||||
{
|
||||
#if CV_SSSE3
|
||||
return v_int16x8(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0x0f0e07060d0c0504, 0x0b0a030209080100)));
|
||||
#else
|
||||
return v_int16x8(_mm_unpacklo_epi16(vec.val, _mm_unpackhi_epi64(vec.val, vec.val)));
|
||||
#endif
|
||||
}
|
||||
inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
|
||||
{
|
||||
return v_int32x4(_mm_shuffle_epi32(vec.val, _MM_SHUFFLE(3, 1, 2, 0)));
|
||||
}
|
||||
inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_float32x4 v_interleave_pairs(const v_float32x4& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
|
||||
inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
|
||||
{
|
||||
#if CV_SSSE3
|
||||
return v_int8x16(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0xffffff0f0e0d0c0a, 0x0908060504020100)));
|
||||
#else
|
||||
__m128i mask = _mm_set1_epi64x(0x00000000FFFFFFFF);
|
||||
__m128i a = _mm_or_si128(_mm_andnot_si128(mask, vec.val), _mm_and_si128(mask, _mm_sll_epi32(vec.val, _mm_set_epi64x(0, 8))));
|
||||
return v_int8x16(_mm_srli_si128(_mm_shufflelo_epi16(a, _MM_SHUFFLE(2, 1, 0, 3)), 2));
|
||||
#endif
|
||||
}
|
||||
inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
|
||||
{
|
||||
#if CV_SSSE3
|
||||
return v_int16x8(_mm_shuffle_epi8(vec.val, _mm_set_epi64x(0xffff0f0e0d0c0b0a, 0x0908050403020100)));
|
||||
#else
|
||||
return v_int16x8(_mm_srli_si128(_mm_shufflelo_epi16(vec.val, _MM_SHUFFLE(2, 1, 0, 3)), 2));
|
||||
#endif
|
||||
}
|
||||
inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
////////////// FP16 support ///////////////////////////
|
||||
|
||||
|
||||
@@ -993,6 +993,80 @@ inline v_float64x2 v_cvt_f64_high(const v_float32x4& a)
|
||||
|
||||
////////////// Lookup table access ////////////////////
|
||||
|
||||
inline v_int8x16 v_lut(const schar* tab, const int* idx)
|
||||
{
|
||||
return v_int8x16(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]], tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]],
|
||||
tab[idx[8]], tab[idx[9]], tab[idx[10]], tab[idx[11]], tab[idx[12]], tab[idx[13]], tab[idx[14]], tab[idx[15]]);
|
||||
}
|
||||
inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
|
||||
{
|
||||
return v_reinterpret_as_s8(v_int16x8(*(const short*)(tab+idx[0]), *(const short*)(tab+idx[1]), *(const short*)(tab+idx[2]), *(const short*)(tab+idx[3]),
|
||||
*(const short*)(tab+idx[4]), *(const short*)(tab+idx[5]), *(const short*)(tab+idx[6]), *(const short*)(tab+idx[7])));
|
||||
}
|
||||
inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
|
||||
{
|
||||
return v_reinterpret_as_s8(v_int32x4(*(const int*)(tab+idx[0]), *(const int*)(tab+idx[1]), *(const int*)(tab+idx[2]), *(const int*)(tab+idx[3])));
|
||||
}
|
||||
inline v_uint8x16 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((const schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((const schar*)tab, idx)); }
|
||||
inline v_uint8x16 v_lut_quads(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_quads((const schar*)tab, idx)); }
|
||||
|
||||
inline v_int16x8 v_lut(const short* tab, const int* idx)
|
||||
{
|
||||
return v_int16x8(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]], tab[idx[4]], tab[idx[5]], tab[idx[6]], tab[idx[7]]);
|
||||
}
|
||||
inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
|
||||
{
|
||||
return v_reinterpret_as_s16(v_int32x4(*(const int*)(tab + idx[0]), *(const int*)(tab + idx[1]), *(const int*)(tab + idx[2]), *(const int*)(tab + idx[3])));
|
||||
}
|
||||
inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
|
||||
{
|
||||
return v_reinterpret_as_s16(v_int64x2(*(const int64*)(tab + idx[0]), *(const int64*)(tab + idx[1])));
|
||||
}
|
||||
inline v_uint16x8 v_lut(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut((const short*)tab, idx)); }
|
||||
inline v_uint16x8 v_lut_pairs(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_pairs((const short*)tab, idx)); }
|
||||
inline v_uint16x8 v_lut_quads(const ushort* tab, const int* idx) { return v_reinterpret_as_u16(v_lut_quads((const short*)tab, idx)); }
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
|
||||
{
|
||||
return v_reinterpret_as_s32(v_int64x2(*(const int64*)(tab + idx[0]), *(const int64*)(tab + idx[1])));
|
||||
}
|
||||
inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
|
||||
{
|
||||
return v_int32x4(vsx_ld(0, tab + idx[0]));
|
||||
}
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut((const int*)tab, idx)); }
|
||||
inline v_uint32x4 v_lut_pairs(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_pairs((const int*)tab, idx)); }
|
||||
inline v_uint32x4 v_lut_quads(const unsigned* tab, const int* idx) { return v_reinterpret_as_u32(v_lut_quads((const int*)tab, idx)); }
|
||||
|
||||
inline v_int64x2 v_lut(const int64_t* tab, const int* idx)
|
||||
{
|
||||
return v_int64x2(tab[idx[0]], tab[idx[1]]);
|
||||
}
|
||||
inline v_int64x2 v_lut_pairs(const int64_t* tab, const int* idx)
|
||||
{
|
||||
return v_int64x2(vsx_ld2(0, tab + idx[0]));
|
||||
}
|
||||
inline v_uint64x2 v_lut(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
|
||||
inline v_uint64x2 v_lut_pairs(const uint64_t* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); }
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const int* idx)
|
||||
{
|
||||
return v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
inline v_float32x4 v_lut_pairs(const float* tab, const int* idx) { return v_reinterpret_as_f32(v_lut_pairs((const int*)tab, idx)); }
|
||||
inline v_float32x4 v_lut_quads(const float* tab, const int* idx) { return v_load(tab + *idx); }
|
||||
|
||||
inline v_float64x2 v_lut(const double* tab, const int* idx)
|
||||
{
|
||||
return v_float64x2(tab[idx[0]], tab[idx[1]]);
|
||||
}
|
||||
inline v_float64x2 v_lut_pairs(const double* tab, const int* idx) { return v_load(tab + *idx); }
|
||||
|
||||
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
@@ -1000,6 +1074,13 @@ inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
|
||||
return v_int32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
|
||||
inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
v_store_aligned(idx, idxvec);
|
||||
return v_uint32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
|
||||
}
|
||||
|
||||
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
|
||||
{
|
||||
int CV_DECL_ALIGNED(32) idx[4];
|
||||
@@ -1030,6 +1111,55 @@ inline void v_lut_deinterleave(const double* tab, const v_int32x4& idxvec, v_flo
|
||||
y = v_float64x2(tab[idx[0]+1], tab[idx[1]+1]);
|
||||
}
|
||||
|
||||
inline v_int8x16 v_interleave_pairs(const v_int8x16& vec)
|
||||
{
|
||||
vec_short8 vec0 = vec_mergeh((vec_short8)vec.val, (vec_short8)vec_mergesql(vec.val, vec.val));
|
||||
vec0 = vec_mergeh(vec0, vec_mergesql(vec0, vec0));
|
||||
return v_int8x16(vec_mergeh((vec_char16)vec0, (vec_char16)vec_mergesql(vec0, vec0)));
|
||||
}
|
||||
inline v_uint8x16 v_interleave_pairs(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_pairs(v_reinterpret_as_s8(vec))); }
|
||||
inline v_int8x16 v_interleave_quads(const v_int8x16& vec)
|
||||
{
|
||||
vec_char16 vec0 = (vec_char16)vec_mergeh((vec_int4)vec.val, (vec_int4)vec_mergesql(vec.val, vec.val));
|
||||
return v_int8x16(vec_mergeh(vec0, vec_mergesql(vec0, vec0)));
|
||||
}
|
||||
inline v_uint8x16 v_interleave_quads(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_interleave_quads(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_interleave_pairs(const v_int16x8& vec)
|
||||
{
|
||||
vec_short8 vec0 = (vec_short8)vec_mergeh((vec_int4)vec.val, (vec_int4)vec_mergesql(vec.val, vec.val));
|
||||
return v_int16x8(vec_mergeh(vec0, vec_mergesql(vec0, vec0)));
|
||||
}
|
||||
inline v_uint16x8 v_interleave_pairs(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_pairs(v_reinterpret_as_s16(vec))); }
|
||||
inline v_int16x8 v_interleave_quads(const v_int16x8& vec)
|
||||
{
|
||||
return v_int16x8(vec_mergeh(vec.val, vec_mergesql(vec.val, vec.val)));
|
||||
}
|
||||
inline v_uint16x8 v_interleave_quads(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_interleave_quads(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
inline v_int32x4 v_interleave_pairs(const v_int32x4& vec)
|
||||
{
|
||||
return v_int32x4(vec_mergeh(vec.val, vec_mergesql(vec.val, vec.val)));
|
||||
}
|
||||
inline v_uint32x4 v_interleave_pairs(const v_uint32x4& vec) { return v_reinterpret_as_u32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
inline v_float32x4 v_interleave_pairs(const v_float32x4& vec) { return v_reinterpret_as_f32(v_interleave_pairs(v_reinterpret_as_s32(vec))); }
|
||||
|
||||
inline v_int8x16 v_pack_triplets(const v_int8x16& vec)
|
||||
{
|
||||
schar CV_DECL_ALIGNED(32) val[16];
|
||||
v_store_aligned(val, vec);
|
||||
return v_int8x16(val[0], val[1], val[2], val[4], val[5], val[6], val[8], val[9], val[10], val[12], val[13], val[14], val[15], val[15], val[15], val[15]);
|
||||
}
|
||||
inline v_uint8x16 v_pack_triplets(const v_uint8x16& vec) { return v_reinterpret_as_u8(v_pack_triplets(v_reinterpret_as_s8(vec))); }
|
||||
|
||||
inline v_int16x8 v_pack_triplets(const v_int16x8& vec)
|
||||
{
|
||||
short CV_DECL_ALIGNED(32) val[8];
|
||||
v_store_aligned(val, vec);
|
||||
return v_int16x8(val[0], val[1], val[2], val[4], val[5], val[6], val[7], val[7]);
|
||||
}
|
||||
inline v_uint16x8 v_pack_triplets(const v_uint16x8& vec) { return v_reinterpret_as_u16(v_pack_triplets(v_reinterpret_as_s16(vec))); }
|
||||
|
||||
/////// FP16 support ////////
|
||||
|
||||
// [TODO] implement these 2 using VSX or universal intrinsics (copy from intrin_sse.cpp and adopt)
|
||||
|
||||
@@ -206,7 +206,7 @@ void cv::cuda::HostMem::create(int rows_, int cols_, int type_)
|
||||
cols = cols_;
|
||||
step = elemSize() * cols;
|
||||
int sz[] = { rows, cols };
|
||||
size_t steps[] = { step, CV_ELEM_SIZE(type_) };
|
||||
size_t steps[] = { step, (size_t)CV_ELEM_SIZE(type_) };
|
||||
flags = updateContinuityFlag(flags, 2, sz, steps);
|
||||
|
||||
if (alloc_type == SHARED)
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
#undef CV_IPP_RUN
|
||||
#define CV_IPP_RUN(c, f, ...)
|
||||
|
||||
#include "mean.simd.hpp"
|
||||
#include "mean.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
|
||||
|
||||
namespace cv {
|
||||
|
||||
#if defined HAVE_IPP
|
||||
namespace cv
|
||||
{
|
||||
static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret )
|
||||
{
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
@@ -107,10 +110,9 @@ static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret )
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cv::Scalar cv::mean( InputArray _src, InputArray _mask )
|
||||
Scalar mean(InputArray _src, InputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -173,314 +175,11 @@ cv::Scalar cv::mean( InputArray _src, InputArray _mask )
|
||||
return s*(nz0 ? 1./nz0 : 0);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
|
||||
namespace cv {
|
||||
|
||||
template <typename T, typename ST, typename SQT>
|
||||
struct SumSqr_SIMD
|
||||
static SumSqrFunc getSumSqrFunc(int depth)
|
||||
{
|
||||
int operator () (const T *, const uchar *, ST *, SQT *, int, int) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#if CV_SIMD
|
||||
|
||||
template <>
|
||||
struct SumSqr_SIMD<uchar, int, int>
|
||||
{
|
||||
int operator () (const uchar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
|
||||
{
|
||||
if (mask || (cn != 1 && cn != 2 && cn != 4))
|
||||
return 0;
|
||||
len *= cn;
|
||||
|
||||
int x = 0;
|
||||
v_int32 v_sum = vx_setzero_s32();
|
||||
v_int32 v_sqsum = vx_setzero_s32();
|
||||
|
||||
const int len0 = len & -v_uint8::nlanes;
|
||||
while(x < len0)
|
||||
{
|
||||
const int len_tmp = min(x + 256*v_uint16::nlanes, len0);
|
||||
v_uint16 v_sum16 = vx_setzero_u16();
|
||||
for ( ; x < len_tmp; x += v_uint8::nlanes)
|
||||
{
|
||||
v_uint16 v_src0 = vx_load_expand(src0 + x);
|
||||
v_uint16 v_src1 = vx_load_expand(src0 + x + v_uint16::nlanes);
|
||||
v_sum16 += v_src0 + v_src1;
|
||||
v_int16 v_tmp0, v_tmp1;
|
||||
v_zip(v_reinterpret_as_s16(v_src0), v_reinterpret_as_s16(v_src1), v_tmp0, v_tmp1);
|
||||
v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
|
||||
}
|
||||
v_uint32 v_half0, v_half1;
|
||||
v_expand(v_sum16, v_half0, v_half1);
|
||||
v_sum += v_reinterpret_as_s32(v_half0 + v_half1);
|
||||
}
|
||||
if (x <= len - v_uint16::nlanes)
|
||||
{
|
||||
v_uint16 v_src = vx_load_expand(src0 + x);
|
||||
v_uint16 v_half = v_combine_high(v_src, v_src);
|
||||
|
||||
v_uint32 v_tmp0, v_tmp1;
|
||||
v_expand(v_src + v_half, v_tmp0, v_tmp1);
|
||||
v_sum += v_reinterpret_as_s32(v_tmp0);
|
||||
|
||||
v_int16 v_tmp2, v_tmp3;
|
||||
v_zip(v_reinterpret_as_s16(v_src), v_reinterpret_as_s16(v_half), v_tmp2, v_tmp3);
|
||||
v_sqsum += v_dotprod(v_tmp2, v_tmp2);
|
||||
x += v_uint16::nlanes;
|
||||
}
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
*sum += v_reduce_sum(v_sum);
|
||||
*sqsum += v_reduce_sum(v_sqsum);
|
||||
}
|
||||
else
|
||||
{
|
||||
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
|
||||
v_store(ar, v_sum);
|
||||
v_store(ar + v_int32::nlanes, v_sqsum);
|
||||
for (int i = 0; i < v_int32::nlanes; ++i)
|
||||
{
|
||||
sum[i % cn] += ar[i];
|
||||
sqsum[i % cn] += ar[v_int32::nlanes + i];
|
||||
}
|
||||
}
|
||||
v_cleanup();
|
||||
return x / cn;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SumSqr_SIMD<schar, int, int>
|
||||
{
|
||||
int operator () (const schar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
|
||||
{
|
||||
if (mask || (cn != 1 && cn != 2 && cn != 4))
|
||||
return 0;
|
||||
len *= cn;
|
||||
|
||||
int x = 0;
|
||||
v_int32 v_sum = vx_setzero_s32();
|
||||
v_int32 v_sqsum = vx_setzero_s32();
|
||||
|
||||
const int len0 = len & -v_int8::nlanes;
|
||||
while (x < len0)
|
||||
{
|
||||
const int len_tmp = min(x + 256 * v_int16::nlanes, len0);
|
||||
v_int16 v_sum16 = vx_setzero_s16();
|
||||
for (; x < len_tmp; x += v_int8::nlanes)
|
||||
{
|
||||
v_int16 v_src0 = vx_load_expand(src0 + x);
|
||||
v_int16 v_src1 = vx_load_expand(src0 + x + v_int16::nlanes);
|
||||
v_sum16 += v_src0 + v_src1;
|
||||
v_int16 v_tmp0, v_tmp1;
|
||||
v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
|
||||
v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
|
||||
}
|
||||
v_int32 v_half0, v_half1;
|
||||
v_expand(v_sum16, v_half0, v_half1);
|
||||
v_sum += v_half0 + v_half1;
|
||||
}
|
||||
if (x <= len - v_int16::nlanes)
|
||||
{
|
||||
v_int16 v_src = vx_load_expand(src0 + x);
|
||||
v_int16 v_half = v_combine_high(v_src, v_src);
|
||||
|
||||
v_int32 v_tmp0, v_tmp1;
|
||||
v_expand(v_src + v_half, v_tmp0, v_tmp1);
|
||||
v_sum += v_tmp0;
|
||||
|
||||
v_int16 v_tmp2, v_tmp3;
|
||||
v_zip(v_src, v_half, v_tmp2, v_tmp3);
|
||||
v_sqsum += v_dotprod(v_tmp2, v_tmp2);
|
||||
x += v_int16::nlanes;
|
||||
}
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
*sum += v_reduce_sum(v_sum);
|
||||
*sqsum += v_reduce_sum(v_sqsum);
|
||||
}
|
||||
else
|
||||
{
|
||||
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
|
||||
v_store(ar, v_sum);
|
||||
v_store(ar + v_int32::nlanes, v_sqsum);
|
||||
for (int i = 0; i < v_int32::nlanes; ++i)
|
||||
{
|
||||
sum[i % cn] += ar[i];
|
||||
sqsum[i % cn] += ar[v_int32::nlanes + i];
|
||||
}
|
||||
}
|
||||
v_cleanup();
|
||||
return x / cn;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T, typename ST, typename SQT>
|
||||
static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
|
||||
{
|
||||
const T* src = src0;
|
||||
|
||||
if( !mask )
|
||||
{
|
||||
SumSqr_SIMD<T, ST, SQT> vop;
|
||||
int x = vop(src0, mask, sum, sqsum, len, cn), k = cn % 4;
|
||||
src = src0 + x * cn;
|
||||
|
||||
if( k == 1 )
|
||||
{
|
||||
ST s0 = sum[0];
|
||||
SQT sq0 = sqsum[0];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v = src[0];
|
||||
s0 += v; sq0 += (SQT)v*v;
|
||||
}
|
||||
sum[0] = s0;
|
||||
sqsum[0] = sq0;
|
||||
}
|
||||
else if( k == 2 )
|
||||
{
|
||||
ST s0 = sum[0], s1 = sum[1];
|
||||
SQT sq0 = sqsum[0], sq1 = sqsum[1];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v0 = src[0], v1 = src[1];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
}
|
||||
sum[0] = s0; sum[1] = s1;
|
||||
sqsum[0] = sq0; sqsum[1] = sq1;
|
||||
}
|
||||
else if( k == 3 )
|
||||
{
|
||||
ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
|
||||
SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v0 = src[0], v1 = src[1], v2 = src[2];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
s2 += v2; sq2 += (SQT)v2*v2;
|
||||
}
|
||||
sum[0] = s0; sum[1] = s1; sum[2] = s2;
|
||||
sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
|
||||
}
|
||||
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
src = src0 + x * cn + k;
|
||||
ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3];
|
||||
SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v0, v1;
|
||||
v0 = src[0], v1 = src[1];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
v0 = src[2], v1 = src[3];
|
||||
s2 += v0; sq2 += (SQT)v0*v0;
|
||||
s3 += v1; sq3 += (SQT)v1*v1;
|
||||
}
|
||||
sum[k] = s0; sum[k+1] = s1;
|
||||
sum[k+2] = s2; sum[k+3] = s3;
|
||||
sqsum[k] = sq0; sqsum[k+1] = sq1;
|
||||
sqsum[k+2] = sq2; sqsum[k+3] = sq3;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int i, nzm = 0;
|
||||
|
||||
if( cn == 1 )
|
||||
{
|
||||
ST s0 = sum[0];
|
||||
SQT sq0 = sqsum[0];
|
||||
for( i = 0; i < len; i++ )
|
||||
if( mask[i] )
|
||||
{
|
||||
T v = src[i];
|
||||
s0 += v; sq0 += (SQT)v*v;
|
||||
nzm++;
|
||||
}
|
||||
sum[0] = s0;
|
||||
sqsum[0] = sq0;
|
||||
}
|
||||
else if( cn == 3 )
|
||||
{
|
||||
ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
|
||||
SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
|
||||
for( i = 0; i < len; i++, src += 3 )
|
||||
if( mask[i] )
|
||||
{
|
||||
T v0 = src[0], v1 = src[1], v2 = src[2];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
s2 += v2; sq2 += (SQT)v2*v2;
|
||||
nzm++;
|
||||
}
|
||||
sum[0] = s0; sum[1] = s1; sum[2] = s2;
|
||||
sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < len; i++, src += cn )
|
||||
if( mask[i] )
|
||||
{
|
||||
for( int k = 0; k < cn; k++ )
|
||||
{
|
||||
T v = src[k];
|
||||
ST s = sum[k] + v;
|
||||
SQT sq = sqsum[k] + (SQT)v*v;
|
||||
sum[k] = s; sqsum[k] = sq;
|
||||
}
|
||||
nzm++;
|
||||
}
|
||||
}
|
||||
return nzm;
|
||||
}
|
||||
|
||||
|
||||
static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
||||
{ return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int);
|
||||
|
||||
static SumSqrFunc getSumSqrTab(int depth)
|
||||
{
|
||||
static SumSqrFunc sumSqrTab[] =
|
||||
{
|
||||
(SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s,
|
||||
(SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0
|
||||
};
|
||||
|
||||
return sumSqrTab[depth];
|
||||
CV_INSTRUMENT_REGION();
|
||||
CV_CPU_DISPATCH(getSumSqrFunc, (depth),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
@@ -804,9 +503,7 @@ static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& m
|
||||
}
|
||||
#endif
|
||||
|
||||
} // cv::
|
||||
|
||||
void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask )
|
||||
void meanStdDev(InputArray _src, OutputArray _mean, OutputArray _sdv, InputArray _mask)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -825,7 +522,7 @@ void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, Input
|
||||
|
||||
int k, cn = src.channels(), depth = src.depth();
|
||||
|
||||
SumSqrFunc func = getSumSqrTab(depth);
|
||||
SumSqrFunc func = getSumSqrFunc(depth);
|
||||
|
||||
CV_Assert( func != 0 );
|
||||
|
||||
@@ -913,3 +610,5 @@ void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, Input
|
||||
dptr[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,325 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "stat.hpp"
|
||||
|
||||
namespace cv {
|
||||
typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int);
|
||||
|
||||
CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
|
||||
|
||||
SumSqrFunc getSumSqrFunc(int depth);
|
||||
|
||||
#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
|
||||
|
||||
template <typename T, typename ST, typename SQT>
|
||||
struct SumSqr_SIMD
|
||||
{
|
||||
inline int operator () (const T *, const uchar *, ST *, SQT *, int, int) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#if CV_SIMD
|
||||
|
||||
template <>
|
||||
struct SumSqr_SIMD<uchar, int, int>
|
||||
{
|
||||
int operator () (const uchar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
|
||||
{
|
||||
if (mask || (cn != 1 && cn != 2 && cn != 4))
|
||||
return 0;
|
||||
len *= cn;
|
||||
|
||||
int x = 0;
|
||||
v_int32 v_sum = vx_setzero_s32();
|
||||
v_int32 v_sqsum = vx_setzero_s32();
|
||||
|
||||
const int len0 = len & -v_uint8::nlanes;
|
||||
while(x < len0)
|
||||
{
|
||||
const int len_tmp = min(x + 256*v_uint16::nlanes, len0);
|
||||
v_uint16 v_sum16 = vx_setzero_u16();
|
||||
for ( ; x < len_tmp; x += v_uint8::nlanes)
|
||||
{
|
||||
v_uint16 v_src0 = vx_load_expand(src0 + x);
|
||||
v_uint16 v_src1 = vx_load_expand(src0 + x + v_uint16::nlanes);
|
||||
v_sum16 += v_src0 + v_src1;
|
||||
v_int16 v_tmp0, v_tmp1;
|
||||
v_zip(v_reinterpret_as_s16(v_src0), v_reinterpret_as_s16(v_src1), v_tmp0, v_tmp1);
|
||||
v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
|
||||
}
|
||||
v_uint32 v_half0, v_half1;
|
||||
v_expand(v_sum16, v_half0, v_half1);
|
||||
v_sum += v_reinterpret_as_s32(v_half0 + v_half1);
|
||||
}
|
||||
if (x <= len - v_uint16::nlanes)
|
||||
{
|
||||
v_uint16 v_src = vx_load_expand(src0 + x);
|
||||
v_uint16 v_half = v_combine_high(v_src, v_src);
|
||||
|
||||
v_uint32 v_tmp0, v_tmp1;
|
||||
v_expand(v_src + v_half, v_tmp0, v_tmp1);
|
||||
v_sum += v_reinterpret_as_s32(v_tmp0);
|
||||
|
||||
v_int16 v_tmp2, v_tmp3;
|
||||
v_zip(v_reinterpret_as_s16(v_src), v_reinterpret_as_s16(v_half), v_tmp2, v_tmp3);
|
||||
v_sqsum += v_dotprod(v_tmp2, v_tmp2);
|
||||
x += v_uint16::nlanes;
|
||||
}
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
*sum += v_reduce_sum(v_sum);
|
||||
*sqsum += v_reduce_sum(v_sqsum);
|
||||
}
|
||||
else
|
||||
{
|
||||
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
|
||||
v_store(ar, v_sum);
|
||||
v_store(ar + v_int32::nlanes, v_sqsum);
|
||||
for (int i = 0; i < v_int32::nlanes; ++i)
|
||||
{
|
||||
sum[i % cn] += ar[i];
|
||||
sqsum[i % cn] += ar[v_int32::nlanes + i];
|
||||
}
|
||||
}
|
||||
v_cleanup();
|
||||
return x / cn;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SumSqr_SIMD<schar, int, int>
|
||||
{
|
||||
int operator () (const schar * src0, const uchar * mask, int * sum, int * sqsum, int len, int cn) const
|
||||
{
|
||||
if (mask || (cn != 1 && cn != 2 && cn != 4))
|
||||
return 0;
|
||||
len *= cn;
|
||||
|
||||
int x = 0;
|
||||
v_int32 v_sum = vx_setzero_s32();
|
||||
v_int32 v_sqsum = vx_setzero_s32();
|
||||
|
||||
const int len0 = len & -v_int8::nlanes;
|
||||
while (x < len0)
|
||||
{
|
||||
const int len_tmp = min(x + 256 * v_int16::nlanes, len0);
|
||||
v_int16 v_sum16 = vx_setzero_s16();
|
||||
for (; x < len_tmp; x += v_int8::nlanes)
|
||||
{
|
||||
v_int16 v_src0 = vx_load_expand(src0 + x);
|
||||
v_int16 v_src1 = vx_load_expand(src0 + x + v_int16::nlanes);
|
||||
v_sum16 += v_src0 + v_src1;
|
||||
v_int16 v_tmp0, v_tmp1;
|
||||
v_zip(v_src0, v_src1, v_tmp0, v_tmp1);
|
||||
v_sqsum += v_dotprod(v_tmp0, v_tmp0) + v_dotprod(v_tmp1, v_tmp1);
|
||||
}
|
||||
v_int32 v_half0, v_half1;
|
||||
v_expand(v_sum16, v_half0, v_half1);
|
||||
v_sum += v_half0 + v_half1;
|
||||
}
|
||||
if (x <= len - v_int16::nlanes)
|
||||
{
|
||||
v_int16 v_src = vx_load_expand(src0 + x);
|
||||
v_int16 v_half = v_combine_high(v_src, v_src);
|
||||
|
||||
v_int32 v_tmp0, v_tmp1;
|
||||
v_expand(v_src + v_half, v_tmp0, v_tmp1);
|
||||
v_sum += v_tmp0;
|
||||
|
||||
v_int16 v_tmp2, v_tmp3;
|
||||
v_zip(v_src, v_half, v_tmp2, v_tmp3);
|
||||
v_sqsum += v_dotprod(v_tmp2, v_tmp2);
|
||||
x += v_int16::nlanes;
|
||||
}
|
||||
|
||||
if (cn == 1)
|
||||
{
|
||||
*sum += v_reduce_sum(v_sum);
|
||||
*sqsum += v_reduce_sum(v_sqsum);
|
||||
}
|
||||
else
|
||||
{
|
||||
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) ar[2 * v_int32::nlanes];
|
||||
v_store(ar, v_sum);
|
||||
v_store(ar + v_int32::nlanes, v_sqsum);
|
||||
for (int i = 0; i < v_int32::nlanes; ++i)
|
||||
{
|
||||
sum[i % cn] += ar[i];
|
||||
sqsum[i % cn] += ar[v_int32::nlanes + i];
|
||||
}
|
||||
}
|
||||
v_cleanup();
|
||||
return x / cn;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template<typename T, typename ST, typename SQT>
|
||||
static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
|
||||
{
|
||||
const T* src = src0;
|
||||
|
||||
if( !mask )
|
||||
{
|
||||
SumSqr_SIMD<T, ST, SQT> vop;
|
||||
int x = vop(src0, mask, sum, sqsum, len, cn), k = cn % 4;
|
||||
src = src0 + x * cn;
|
||||
|
||||
if( k == 1 )
|
||||
{
|
||||
ST s0 = sum[0];
|
||||
SQT sq0 = sqsum[0];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v = src[0];
|
||||
s0 += v; sq0 += (SQT)v*v;
|
||||
}
|
||||
sum[0] = s0;
|
||||
sqsum[0] = sq0;
|
||||
}
|
||||
else if( k == 2 )
|
||||
{
|
||||
ST s0 = sum[0], s1 = sum[1];
|
||||
SQT sq0 = sqsum[0], sq1 = sqsum[1];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v0 = src[0], v1 = src[1];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
}
|
||||
sum[0] = s0; sum[1] = s1;
|
||||
sqsum[0] = sq0; sqsum[1] = sq1;
|
||||
}
|
||||
else if( k == 3 )
|
||||
{
|
||||
ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
|
||||
SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v0 = src[0], v1 = src[1], v2 = src[2];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
s2 += v2; sq2 += (SQT)v2*v2;
|
||||
}
|
||||
sum[0] = s0; sum[1] = s1; sum[2] = s2;
|
||||
sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
|
||||
}
|
||||
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
src = src0 + x * cn + k;
|
||||
ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3];
|
||||
SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3];
|
||||
for(int i = x; i < len; i++, src += cn )
|
||||
{
|
||||
T v0, v1;
|
||||
v0 = src[0], v1 = src[1];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
v0 = src[2], v1 = src[3];
|
||||
s2 += v0; sq2 += (SQT)v0*v0;
|
||||
s3 += v1; sq3 += (SQT)v1*v1;
|
||||
}
|
||||
sum[k] = s0; sum[k+1] = s1;
|
||||
sum[k+2] = s2; sum[k+3] = s3;
|
||||
sqsum[k] = sq0; sqsum[k+1] = sq1;
|
||||
sqsum[k+2] = sq2; sqsum[k+3] = sq3;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int i, nzm = 0;
|
||||
|
||||
if( cn == 1 )
|
||||
{
|
||||
ST s0 = sum[0];
|
||||
SQT sq0 = sqsum[0];
|
||||
for( i = 0; i < len; i++ )
|
||||
if( mask[i] )
|
||||
{
|
||||
T v = src[i];
|
||||
s0 += v; sq0 += (SQT)v*v;
|
||||
nzm++;
|
||||
}
|
||||
sum[0] = s0;
|
||||
sqsum[0] = sq0;
|
||||
}
|
||||
else if( cn == 3 )
|
||||
{
|
||||
ST s0 = sum[0], s1 = sum[1], s2 = sum[2];
|
||||
SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2];
|
||||
for( i = 0; i < len; i++, src += 3 )
|
||||
if( mask[i] )
|
||||
{
|
||||
T v0 = src[0], v1 = src[1], v2 = src[2];
|
||||
s0 += v0; sq0 += (SQT)v0*v0;
|
||||
s1 += v1; sq1 += (SQT)v1*v1;
|
||||
s2 += v2; sq2 += (SQT)v2*v2;
|
||||
nzm++;
|
||||
}
|
||||
sum[0] = s0; sum[1] = s1; sum[2] = s2;
|
||||
sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < len; i++, src += cn )
|
||||
if( mask[i] )
|
||||
{
|
||||
for( int k = 0; k < cn; k++ )
|
||||
{
|
||||
T v = src[k];
|
||||
ST s = sum[k] + v;
|
||||
SQT sq = sqsum[k] + (SQT)v*v;
|
||||
sum[k] = s; sqsum[k] = sq;
|
||||
}
|
||||
nzm++;
|
||||
}
|
||||
}
|
||||
return nzm;
|
||||
}
|
||||
|
||||
|
||||
static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn )
|
||||
{ CV_INSTRUMENT_REGION(); return sumsqr_(src, mask, sum, sqsum, len, cn); }
|
||||
|
||||
SumSqrFunc getSumSqrFunc(int depth)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
static SumSqrFunc sumSqrTab[] =
|
||||
{
|
||||
(SumSqrFunc)GET_OPTIMIZED(sqsum8u), (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s,
|
||||
(SumSqrFunc)sqsum32s, (SumSqrFunc)GET_OPTIMIZED(sqsum32f), (SumSqrFunc)sqsum64f, 0
|
||||
};
|
||||
|
||||
return sumSqrTab[depth];
|
||||
}
|
||||
|
||||
#endif
|
||||
CV_CPU_OPTIMIZATION_NAMESPACE_END
|
||||
} // namespace
|
||||
@@ -6,208 +6,44 @@
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_core.hpp"
|
||||
|
||||
#include "merge.simd.hpp"
|
||||
#include "merge.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
|
||||
|
||||
namespace cv { namespace hal {
|
||||
|
||||
#if CV_SIMD
|
||||
/*
|
||||
The trick with STORE_UNALIGNED/STORE_ALIGNED_NOCACHE is the following:
|
||||
on IA there are instructions movntps and such to which
|
||||
v_store_interleave(...., STORE_ALIGNED_NOCACHE) is mapped.
|
||||
Those instructions write directly into memory w/o touching cache
|
||||
that results in dramatic speed improvements, especially on
|
||||
large arrays (FullHD, 4K etc.).
|
||||
|
||||
Those intrinsics require the destination address to be aligned
|
||||
by 16/32 bits (with SSE2 and AVX2, respectively).
|
||||
So we potentially split the processing into 3 stages:
|
||||
1) the optional prefix part [0:i0), where we use simple unaligned stores.
|
||||
2) the optional main part [i0:len - VECSZ], where we use "nocache" mode.
|
||||
But in some cases we have to use unaligned stores in this part.
|
||||
3) the optional suffix part (the tail) (len - VECSZ:len) where we switch back to "unaligned" mode
|
||||
to process the remaining len - VECSZ elements.
|
||||
In principle there can be very poorly aligned data where there is no main part.
|
||||
For that we set i0=0 and use unaligned stores for the whole array.
|
||||
*/
|
||||
template<typename T, typename VecT> static void
|
||||
vecmerge_( const T** src, T* dst, int len, int cn )
|
||||
{
|
||||
const int VECSZ = VecT::nlanes;
|
||||
int i, i0 = 0;
|
||||
const T* src0 = src[0];
|
||||
const T* src1 = src[1];
|
||||
|
||||
const int dstElemSize = cn * sizeof(T);
|
||||
int r = (int)((size_t)(void*)dst % (VECSZ*sizeof(T)));
|
||||
hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
if( r != 0 )
|
||||
{
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
if (r % dstElemSize == 0 && len > VECSZ*2)
|
||||
i0 = VECSZ - (r / dstElemSize);
|
||||
}
|
||||
|
||||
if( cn == 2 )
|
||||
{
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
|
||||
v_store_interleave(dst + i*cn, a, b, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( cn == 3 )
|
||||
{
|
||||
const T* src2 = src[2];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a = vx_load(src0 + i), b = vx_load(src1 + i), c = vx_load(src2 + i);
|
||||
v_store_interleave(dst + i*cn, a, b, c, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( cn == 4 );
|
||||
const T* src2 = src[2];
|
||||
const T* src3 = src[3];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
|
||||
VecT c = vx_load(src2 + i), d = vx_load(src3 + i);
|
||||
v_store_interleave(dst + i*cn, a, b, c, d, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
vx_cleanup();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> static void
|
||||
merge_( const T** src, T* dst, int len, int cn )
|
||||
{
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i, j;
|
||||
if( k == 1 )
|
||||
{
|
||||
const T* src0 = src[0];
|
||||
for( i = j = 0; i < len; i++, j += cn )
|
||||
dst[j] = src0[i];
|
||||
}
|
||||
else if( k == 2 )
|
||||
{
|
||||
const T *src0 = src[0], *src1 = src[1];
|
||||
i = j = 0;
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i];
|
||||
dst[j+1] = src1[i];
|
||||
}
|
||||
}
|
||||
else if( k == 3 )
|
||||
{
|
||||
const T *src0 = src[0], *src1 = src[1], *src2 = src[2];
|
||||
i = j = 0;
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i];
|
||||
dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const T *src0 = src[0], *src1 = src[1], *src2 = src[2], *src3 = src[3];
|
||||
i = j = 0;
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i]; dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i]; dst[j+3] = src3[i];
|
||||
}
|
||||
}
|
||||
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
const T *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
|
||||
for( i = 0, j = k; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i]; dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i]; dst[j+3] = src3[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void merge8u(const uchar** src, uchar* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(merge8u, cv_hal_merge8u, src, dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<uchar, v_uint8>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(merge8u, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
void merge16u(const ushort** src, ushort* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(merge16u, cv_hal_merge16u, src, dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<ushort, v_uint16>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(merge16u, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
void merge32s(const int** src, int* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(merge32s, cv_hal_merge32s, src, dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_int32::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<int, v_int32>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(merge32s, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
void merge64s(const int64** src, int64* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(merge64s, cv_hal_merge64s, src, dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<int64, v_int64>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(merge64s, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
}} // cv::hal::
|
||||
} // namespace cv::hal::
|
||||
|
||||
|
||||
typedef void (*MergeFunc)(const uchar** src, uchar* dst, int len, int cn);
|
||||
@@ -227,7 +63,6 @@ static MergeFunc getMergeFunc(int depth)
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
|
||||
namespace cv {
|
||||
static bool ipp_merge(const Mat* mv, Mat& dst, int channels)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW_LL
|
||||
@@ -276,10 +111,9 @@ static bool ipp_merge(const Mat* mv, Mat& dst, int channels)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void cv::merge(const Mat* mv, size_t n, OutputArray _dst)
|
||||
void merge(const Mat* mv, size_t n, OutputArray _dst)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -363,8 +197,6 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst)
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst )
|
||||
{
|
||||
std::vector<UMat> src, ksrc;
|
||||
@@ -423,11 +255,9 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst )
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void cv::merge(InputArrayOfArrays _mv, OutputArray _dst)
|
||||
void merge(InputArrayOfArrays _mv, OutputArray _dst)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -438,3 +268,5 @@ void cv::merge(InputArrayOfArrays _mv, OutputArray _dst)
|
||||
_mv.getMatVector(mv);
|
||||
merge(!mv.empty() ? &mv[0] : 0, mv.size(), _dst);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,219 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv { namespace hal {
|
||||
CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
|
||||
|
||||
void merge8u(const uchar** src, uchar* dst, int len, int cn);
|
||||
void merge16u(const ushort** src, ushort* dst, int len, int cn);
|
||||
void merge32s(const int** src, int* dst, int len, int cn);
|
||||
void merge64s(const int64** src, int64* dst, int len, int cn);
|
||||
|
||||
#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
|
||||
|
||||
#if CV_SIMD
|
||||
/*
|
||||
The trick with STORE_UNALIGNED/STORE_ALIGNED_NOCACHE is the following:
|
||||
on IA there are instructions movntps and such to which
|
||||
v_store_interleave(...., STORE_ALIGNED_NOCACHE) is mapped.
|
||||
Those instructions write directly into memory w/o touching cache
|
||||
that results in dramatic speed improvements, especially on
|
||||
large arrays (FullHD, 4K etc.).
|
||||
|
||||
Those intrinsics require the destination address to be aligned
|
||||
by 16/32 bits (with SSE2 and AVX2, respectively).
|
||||
So we potentially split the processing into 3 stages:
|
||||
1) the optional prefix part [0:i0), where we use simple unaligned stores.
|
||||
2) the optional main part [i0:len - VECSZ], where we use "nocache" mode.
|
||||
But in some cases we have to use unaligned stores in this part.
|
||||
3) the optional suffix part (the tail) (len - VECSZ:len) where we switch back to "unaligned" mode
|
||||
to process the remaining len - VECSZ elements.
|
||||
In principle there can be very poorly aligned data where there is no main part.
|
||||
For that we set i0=0 and use unaligned stores for the whole array.
|
||||
*/
|
||||
template<typename T, typename VecT> static void
|
||||
vecmerge_( const T** src, T* dst, int len, int cn )
|
||||
{
|
||||
const int VECSZ = VecT::nlanes;
|
||||
int i, i0 = 0;
|
||||
const T* src0 = src[0];
|
||||
const T* src1 = src[1];
|
||||
|
||||
const int dstElemSize = cn * sizeof(T);
|
||||
int r = (int)((size_t)(void*)dst % (VECSZ*sizeof(T)));
|
||||
hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
if( r != 0 )
|
||||
{
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
if (r % dstElemSize == 0 && len > VECSZ*2)
|
||||
i0 = VECSZ - (r / dstElemSize);
|
||||
}
|
||||
|
||||
if( cn == 2 )
|
||||
{
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
|
||||
v_store_interleave(dst + i*cn, a, b, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( cn == 3 )
|
||||
{
|
||||
const T* src2 = src[2];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a = vx_load(src0 + i), b = vx_load(src1 + i), c = vx_load(src2 + i);
|
||||
v_store_interleave(dst + i*cn, a, b, c, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( cn == 4 );
|
||||
const T* src2 = src[2];
|
||||
const T* src3 = src[3];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a = vx_load(src0 + i), b = vx_load(src1 + i);
|
||||
VecT c = vx_load(src2 + i), d = vx_load(src3 + i);
|
||||
v_store_interleave(dst + i*cn, a, b, c, d, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
vx_cleanup();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> static void
|
||||
merge_( const T** src, T* dst, int len, int cn )
|
||||
{
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i, j;
|
||||
if( k == 1 )
|
||||
{
|
||||
const T* src0 = src[0];
|
||||
for( i = j = 0; i < len; i++, j += cn )
|
||||
dst[j] = src0[i];
|
||||
}
|
||||
else if( k == 2 )
|
||||
{
|
||||
const T *src0 = src[0], *src1 = src[1];
|
||||
i = j = 0;
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i];
|
||||
dst[j+1] = src1[i];
|
||||
}
|
||||
}
|
||||
else if( k == 3 )
|
||||
{
|
||||
const T *src0 = src[0], *src1 = src[1], *src2 = src[2];
|
||||
i = j = 0;
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i];
|
||||
dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const T *src0 = src[0], *src1 = src[1], *src2 = src[2], *src3 = src[3];
|
||||
i = j = 0;
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i]; dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i]; dst[j+3] = src3[i];
|
||||
}
|
||||
}
|
||||
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
const T *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3];
|
||||
for( i = 0, j = k; i < len; i++, j += cn )
|
||||
{
|
||||
dst[j] = src0[i]; dst[j+1] = src1[i];
|
||||
dst[j+2] = src2[i]; dst[j+3] = src3[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void merge8u(const uchar** src, uchar* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<uchar, v_uint8>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
void merge16u(const ushort** src, ushort* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<ushort, v_uint16>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
void merge32s(const int** src, int* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_int32::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<int, v_int32>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
void merge64s(const int64** src, int64* dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecmerge_<int64, v_int64>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
merge_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
#endif
|
||||
CV_CPU_OPTIMIZATION_NAMESPACE_END
|
||||
}} // namespace
|
||||
@@ -6,213 +6,44 @@
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels_core.hpp"
|
||||
|
||||
#include "split.simd.hpp"
|
||||
#include "split.simd_declarations.hpp" // defines CV_CPU_DISPATCH_MODES_ALL=AVX2,...,BASELINE based on CMakeLists.txt content
|
||||
|
||||
namespace cv { namespace hal {
|
||||
|
||||
#if CV_SIMD
|
||||
// see the comments for vecmerge_ in merge.cpp
|
||||
template<typename T, typename VecT> static void
|
||||
vecsplit_( const T* src, T** dst, int len, int cn )
|
||||
{
|
||||
const int VECSZ = VecT::nlanes;
|
||||
int i, i0 = 0;
|
||||
T* dst0 = dst[0];
|
||||
T* dst1 = dst[1];
|
||||
|
||||
int r0 = (int)((size_t)(void*)dst0 % (VECSZ*sizeof(T)));
|
||||
int r1 = (int)((size_t)(void*)dst1 % (VECSZ*sizeof(T)));
|
||||
int r2 = cn > 2 ? (int)((size_t)(void*)dst[2] % (VECSZ*sizeof(T))) : r0;
|
||||
int r3 = cn > 3 ? (int)((size_t)(void*)dst[3] % (VECSZ*sizeof(T))) : r0;
|
||||
|
||||
hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
if( (r0|r1|r2|r3) != 0 )
|
||||
{
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
if( r0 == r1 && r0 == r2 && r0 == r3 && r0 % sizeof(T) == 0 && len > VECSZ*2 )
|
||||
i0 = VECSZ - (r0 / sizeof(T));
|
||||
}
|
||||
|
||||
if( cn == 2 )
|
||||
{
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a, b;
|
||||
v_load_deinterleave(src + i*cn, a, b);
|
||||
v_store(dst0 + i, a, mode);
|
||||
v_store(dst1 + i, b, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( cn == 3 )
|
||||
{
|
||||
T* dst2 = dst[2];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a, b, c;
|
||||
v_load_deinterleave(src + i*cn, a, b, c);
|
||||
v_store(dst0 + i, a, mode);
|
||||
v_store(dst1 + i, b, mode);
|
||||
v_store(dst2 + i, c, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( cn == 4 );
|
||||
T* dst2 = dst[2];
|
||||
T* dst3 = dst[3];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a, b, c, d;
|
||||
v_load_deinterleave(src + i*cn, a, b, c, d);
|
||||
v_store(dst0 + i, a, mode);
|
||||
v_store(dst1 + i, b, mode);
|
||||
v_store(dst2 + i, c, mode);
|
||||
v_store(dst3 + i, d, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
vx_cleanup();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> static void
|
||||
split_( const T* src, T** dst, int len, int cn )
|
||||
{
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i, j;
|
||||
if( k == 1 )
|
||||
{
|
||||
T* dst0 = dst[0];
|
||||
|
||||
if(cn == 1)
|
||||
{
|
||||
memcpy(dst0, src, len * sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0, j = 0 ; i < len; i++, j += cn )
|
||||
dst0[i] = src[j];
|
||||
}
|
||||
}
|
||||
else if( k == 2 )
|
||||
{
|
||||
T *dst0 = dst[0], *dst1 = dst[1];
|
||||
i = j = 0;
|
||||
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j];
|
||||
dst1[i] = src[j+1];
|
||||
}
|
||||
}
|
||||
else if( k == 3 )
|
||||
{
|
||||
T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
|
||||
i = j = 0;
|
||||
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j];
|
||||
dst1[i] = src[j+1];
|
||||
dst2[i] = src[j+2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2], *dst3 = dst[3];
|
||||
i = j = 0;
|
||||
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j]; dst1[i] = src[j+1];
|
||||
dst2[i] = src[j+2]; dst3[i] = src[j+3];
|
||||
}
|
||||
}
|
||||
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
T *dst0 = dst[k], *dst1 = dst[k+1], *dst2 = dst[k+2], *dst3 = dst[k+3];
|
||||
for( i = 0, j = k; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j]; dst1[i] = src[j+1];
|
||||
dst2[i] = src[j+2]; dst3[i] = src[j+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void split8u(const uchar* src, uchar** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(split8u, cv_hal_split8u, src,dst, len, cn)
|
||||
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<uchar, v_uint8>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(split8u, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
void split16u(const ushort* src, ushort** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(split16u, cv_hal_split16u, src,dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<ushort, v_uint16>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(split16u, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
void split32s(const int* src, int** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(split32s, cv_hal_split32s, src,dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint32::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<int, v_int32>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(split32s, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
void split64s(const int64* src, int64** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
CALL_HAL(split64s, cv_hal_split64s, src,dst, len, cn)
|
||||
#if CV_SIMD
|
||||
if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<int64, v_int64>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
CV_CPU_DISPATCH(split64s, (src, dst, len, cn),
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
}} // cv::hal::
|
||||
} // namespace cv::hal::
|
||||
|
||||
/****************************************************************************************\
|
||||
* split & merge *
|
||||
@@ -235,7 +66,6 @@ static SplitFunc getSplitFunc(int depth)
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
|
||||
namespace cv {
|
||||
static bool ipp_split(const Mat& src, Mat* mv, int channels)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW_LL
|
||||
@@ -284,10 +114,9 @@ static bool ipp_split(const Mat& src, Mat* mv, int channels)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void cv::split(const Mat& src, Mat* mv)
|
||||
void split(const Mat& src, Mat* mv)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -343,8 +172,6 @@ void cv::split(const Mat& src, Mat* mv)
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv )
|
||||
{
|
||||
int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type),
|
||||
@@ -383,11 +210,9 @@ static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv )
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void cv::split(InputArray _m, OutputArrayOfArrays _mv)
|
||||
void split(InputArray _m, OutputArrayOfArrays _mv)
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
@@ -413,3 +238,5 @@ void cv::split(InputArray _m, OutputArrayOfArrays _mv)
|
||||
|
||||
split(m, &dst[0]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,223 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv { namespace hal {
|
||||
CV_CPU_OPTIMIZATION_NAMESPACE_BEGIN
|
||||
|
||||
void split8u(const uchar* src, uchar** dst, int len, int cn);
|
||||
void split16u(const ushort* src, ushort** dst, int len, int cn);
|
||||
void split32s(const int* src, int** dst, int len, int cn);
|
||||
void split64s(const int64* src, int64** dst, int len, int cn);
|
||||
|
||||
#ifndef CV_CPU_OPTIMIZATION_DECLARATIONS_ONLY
|
||||
|
||||
#if CV_SIMD
|
||||
// see the comments for vecmerge_ in merge.cpp
|
||||
template<typename T, typename VecT> static void
|
||||
vecsplit_( const T* src, T** dst, int len, int cn )
|
||||
{
|
||||
const int VECSZ = VecT::nlanes;
|
||||
int i, i0 = 0;
|
||||
T* dst0 = dst[0];
|
||||
T* dst1 = dst[1];
|
||||
|
||||
int r0 = (int)((size_t)(void*)dst0 % (VECSZ*sizeof(T)));
|
||||
int r1 = (int)((size_t)(void*)dst1 % (VECSZ*sizeof(T)));
|
||||
int r2 = cn > 2 ? (int)((size_t)(void*)dst[2] % (VECSZ*sizeof(T))) : r0;
|
||||
int r3 = cn > 3 ? (int)((size_t)(void*)dst[3] % (VECSZ*sizeof(T))) : r0;
|
||||
|
||||
hal::StoreMode mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
if( (r0|r1|r2|r3) != 0 )
|
||||
{
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
if( r0 == r1 && r0 == r2 && r0 == r3 && r0 % sizeof(T) == 0 && len > VECSZ*2 )
|
||||
i0 = VECSZ - (r0 / sizeof(T));
|
||||
}
|
||||
|
||||
if( cn == 2 )
|
||||
{
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a, b;
|
||||
v_load_deinterleave(src + i*cn, a, b);
|
||||
v_store(dst0 + i, a, mode);
|
||||
v_store(dst1 + i, b, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( cn == 3 )
|
||||
{
|
||||
T* dst2 = dst[2];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a, b, c;
|
||||
v_load_deinterleave(src + i*cn, a, b, c);
|
||||
v_store(dst0 + i, a, mode);
|
||||
v_store(dst1 + i, b, mode);
|
||||
v_store(dst2 + i, c, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( cn == 4 );
|
||||
T* dst2 = dst[2];
|
||||
T* dst3 = dst[3];
|
||||
for( i = 0; i < len; i += VECSZ )
|
||||
{
|
||||
if( i > len - VECSZ )
|
||||
{
|
||||
i = len - VECSZ;
|
||||
mode = hal::STORE_UNALIGNED;
|
||||
}
|
||||
VecT a, b, c, d;
|
||||
v_load_deinterleave(src + i*cn, a, b, c, d);
|
||||
v_store(dst0 + i, a, mode);
|
||||
v_store(dst1 + i, b, mode);
|
||||
v_store(dst2 + i, c, mode);
|
||||
v_store(dst3 + i, d, mode);
|
||||
if( i < i0 )
|
||||
{
|
||||
i = i0 - VECSZ;
|
||||
mode = hal::STORE_ALIGNED_NOCACHE;
|
||||
}
|
||||
}
|
||||
}
|
||||
vx_cleanup();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> static void
|
||||
split_( const T* src, T** dst, int len, int cn )
|
||||
{
|
||||
int k = cn % 4 ? cn % 4 : 4;
|
||||
int i, j;
|
||||
if( k == 1 )
|
||||
{
|
||||
T* dst0 = dst[0];
|
||||
|
||||
if(cn == 1)
|
||||
{
|
||||
memcpy(dst0, src, len * sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0, j = 0 ; i < len; i++, j += cn )
|
||||
dst0[i] = src[j];
|
||||
}
|
||||
}
|
||||
else if( k == 2 )
|
||||
{
|
||||
T *dst0 = dst[0], *dst1 = dst[1];
|
||||
i = j = 0;
|
||||
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j];
|
||||
dst1[i] = src[j+1];
|
||||
}
|
||||
}
|
||||
else if( k == 3 )
|
||||
{
|
||||
T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2];
|
||||
i = j = 0;
|
||||
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j];
|
||||
dst1[i] = src[j+1];
|
||||
dst2[i] = src[j+2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2], *dst3 = dst[3];
|
||||
i = j = 0;
|
||||
|
||||
for( ; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j]; dst1[i] = src[j+1];
|
||||
dst2[i] = src[j+2]; dst3[i] = src[j+3];
|
||||
}
|
||||
}
|
||||
|
||||
for( ; k < cn; k += 4 )
|
||||
{
|
||||
T *dst0 = dst[k], *dst1 = dst[k+1], *dst2 = dst[k+2], *dst3 = dst[k+3];
|
||||
for( i = 0, j = k; i < len; i++, j += cn )
|
||||
{
|
||||
dst0[i] = src[j]; dst1[i] = src[j+1];
|
||||
dst2[i] = src[j+2]; dst3[i] = src[j+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void split8u(const uchar* src, uchar** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint8::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<uchar, v_uint8>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
void split16u(const ushort* src, ushort** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint16::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<ushort, v_uint16>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
void split32s(const int* src, int** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_uint32::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<int, v_int32>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
void split64s(const int64* src, int64** dst, int len, int cn )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
#if CV_SIMD
|
||||
if( len >= v_int64::nlanes && 2 <= cn && cn <= 4 )
|
||||
vecsplit_<int64, v_int64>(src, dst, len, cn);
|
||||
else
|
||||
#endif
|
||||
split_(src, dst, len, cn);
|
||||
}
|
||||
|
||||
#endif
|
||||
CV_CPU_OPTIMIZATION_NAMESPACE_END
|
||||
}} // namespace
|
||||
Reference in New Issue
Block a user