mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
use universal intrinsic and SSE4 popcount instruction in normHamming
- add v_popcount in universal intrinsic - add test for v_popcount - add wrapper of popcount for both MSVC and GCC
This commit is contained in:
@@ -188,8 +188,16 @@ enum CpuFeatures {
|
||||
# if defined __POPCNT__ || (defined _MSC_VER && _MSC_VER >= 1500)
|
||||
# ifdef _MSC_VER
|
||||
# include <nmmintrin.h>
|
||||
# if defined(_M_X64)
|
||||
# define CV_POPCNT_U64 _mm_popcnt_u64
|
||||
# endif
|
||||
# define CV_POPCNT_U32 _mm_popcnt_u32
|
||||
# else
|
||||
# include <popcntintrin.h>
|
||||
# if defined(__x86_64__)
|
||||
# define CV_POPCNT_U64 __builtin_popcountll
|
||||
# endif
|
||||
# define CV_POPCNT_U32 __builtin_popcount
|
||||
# endif
|
||||
# define CV_POPCNT 1
|
||||
# endif
|
||||
|
||||
@@ -149,7 +149,7 @@ Element-wise binary and unary operations.
|
||||
|
||||
Most of these operations return only one value.
|
||||
|
||||
- Reduce: @ref v_reduce_min, @ref v_reduce_max, @ref v_reduce_sum
|
||||
- Reduce: @ref v_reduce_min, @ref v_reduce_max, @ref v_reduce_sum, @ref v_popcount
|
||||
- Mask: @ref v_signmask, @ref v_check_all, @ref v_check_any, @ref v_select
|
||||
|
||||
### Other math
|
||||
@@ -574,6 +574,49 @@ Scheme:
|
||||
For 32-bit integer and 32-bit floating point types. */
|
||||
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_max, std::max)
|
||||
|
||||
static const unsigned char popCountTable[] =
|
||||
{
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
|
||||
};
|
||||
/** @brief Count the 1 bits in the vector and return 4 values
|
||||
|
||||
Scheme:
|
||||
@code
|
||||
{A1 A2 A3 ...} => popcount(A1)
|
||||
@endcode
|
||||
Any types but result will be in v_uint32x4*/
|
||||
template<typename _Tp, int n> inline v_uint32x4 v_popcount(const v_reg<_Tp, n>& a)
|
||||
{
|
||||
v_uint8x16 b;
|
||||
b = v_reinterpret_as_u8(a);
|
||||
for( int i = 0; i < v_uint8x16::nlanes; i++ )
|
||||
{
|
||||
b.s[i] = popCountTable[b.s[i]];
|
||||
}
|
||||
v_uint32x4 c;
|
||||
for( int i = 0; i < v_uint32x4::nlanes; i++ )
|
||||
{
|
||||
c.s[i] = b.s[i*4] + b.s[i*4+1] + b.s[i*4+2] + b.s[i*4+3];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
//! @cond IGNORED
|
||||
template<typename _Tp, int n>
|
||||
inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
|
||||
|
||||
@@ -813,6 +813,22 @@ OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, sum, add, f32)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, max, max, f32)
|
||||
OPENCV_HAL_IMPL_NEON_REDUCE_OP_4(v_float32x4, float32x2, float, min, min, f32)
|
||||
|
||||
#define OPENCV_HAL_IMPL_NEON_POPCOUNT(_Tpvec, cast) \
|
||||
inline v_uint32x4 v_popcount(const _Tpvec& a) \
|
||||
{ \
|
||||
uint8x16_t t = vcntq_u8(cast(a.val)); \
|
||||
uint16x8_t t0 = vpaddlq_u8(t); /* 16 -> 8 */ \
|
||||
uint32x4_t t1 = vpaddlq_u16(t0); /* 8 -> 4 */ \
|
||||
return v_uint32x4(t1); \
|
||||
}
|
||||
|
||||
OPENCV_HAL_IMPL_NEON_POPCOUNT(v_uint8x16, OPENCV_HAL_NOP)
|
||||
OPENCV_HAL_IMPL_NEON_POPCOUNT(v_uint16x8, vreinterpretq_u8_u16)
|
||||
OPENCV_HAL_IMPL_NEON_POPCOUNT(v_uint32x4, vreinterpretq_u8_u32)
|
||||
OPENCV_HAL_IMPL_NEON_POPCOUNT(v_int8x16, vreinterpretq_u8_s8)
|
||||
OPENCV_HAL_IMPL_NEON_POPCOUNT(v_int16x8, vreinterpretq_u8_s16)
|
||||
OPENCV_HAL_IMPL_NEON_POPCOUNT(v_int32x4, vreinterpretq_u8_s32)
|
||||
|
||||
inline int v_signmask(const v_uint8x16& a)
|
||||
{
|
||||
int8x8_t m0 = vcreate_s8(CV_BIG_UINT(0x0706050403020100));
|
||||
|
||||
@@ -1121,6 +1121,28 @@ OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_float32x4, float, sum, OPENCV_HAL_ADD)
|
||||
OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_float32x4, float, max, std::max)
|
||||
OPENCV_HAL_IMPL_SSE_REDUCE_OP_4(v_float32x4, float, min, std::min)
|
||||
|
||||
#define OPENCV_HAL_IMPL_SSE_POPCOUNT(_Tpvec) \
|
||||
inline v_uint32x4 v_popcount(const _Tpvec& a) \
|
||||
{ \
|
||||
__m128i m1 = _mm_set1_epi32(0x55555555); \
|
||||
__m128i m2 = _mm_set1_epi32(0x33333333); \
|
||||
__m128i m4 = _mm_set1_epi32(0x0f0f0f0f); \
|
||||
__m128i p = a.val; \
|
||||
p = _mm_add_epi32(_mm_and_si128(_mm_srli_epi32(p, 1), m1), _mm_and_si128(p, m1)); \
|
||||
p = _mm_add_epi32(_mm_and_si128(_mm_srli_epi32(p, 2), m2), _mm_and_si128(p, m2)); \
|
||||
p = _mm_add_epi32(_mm_and_si128(_mm_srli_epi32(p, 4), m4), _mm_and_si128(p, m4)); \
|
||||
p = _mm_adds_epi8(p, _mm_srli_si128(p, 1)); \
|
||||
p = _mm_adds_epi8(p, _mm_srli_si128(p, 2)); \
|
||||
return v_uint32x4(_mm_and_si128(p, _mm_set1_epi32(0x000000ff))); \
|
||||
}
|
||||
|
||||
OPENCV_HAL_IMPL_SSE_POPCOUNT(v_uint8x16)
|
||||
OPENCV_HAL_IMPL_SSE_POPCOUNT(v_uint16x8)
|
||||
OPENCV_HAL_IMPL_SSE_POPCOUNT(v_uint32x4)
|
||||
OPENCV_HAL_IMPL_SSE_POPCOUNT(v_int8x16)
|
||||
OPENCV_HAL_IMPL_SSE_POPCOUNT(v_int16x8)
|
||||
OPENCV_HAL_IMPL_SSE_POPCOUNT(v_int32x4)
|
||||
|
||||
#define OPENCV_HAL_IMPL_SSE_CHECK_SIGNS(_Tpvec, suffix, pack_op, and_op, signmask, allmask) \
|
||||
inline int v_signmask(const _Tpvec& a) \
|
||||
{ \
|
||||
|
||||
Reference in New Issue
Block a user