mirror of
https://github.com/opencv/opencv.git
synced 2025-08-01 02:18:01 +08:00
Merge pull request #23307 from alalek:simd_comparison_fix_misused_64f_guard
core(simd): 64-bit integer EQ/NE without misused 64F guard
This commit is contained in:
commit
36a03dbdbf
@ -879,14 +879,10 @@ OPENCV_HAL_IMPL_CMP_OP(<=)
|
|||||||
For all types except 64-bit integer values. */
|
For all types except 64-bit integer values. */
|
||||||
OPENCV_HAL_IMPL_CMP_OP(>=)
|
OPENCV_HAL_IMPL_CMP_OP(>=)
|
||||||
|
|
||||||
/** @brief Equal comparison
|
/** @brief Equal comparison */
|
||||||
|
|
||||||
For all types except 64-bit integer values. */
|
|
||||||
OPENCV_HAL_IMPL_CMP_OP(==)
|
OPENCV_HAL_IMPL_CMP_OP(==)
|
||||||
|
|
||||||
/** @brief Not equal comparison
|
/** @brief Not equal comparison */
|
||||||
|
|
||||||
For all types except 64-bit integer values. */
|
|
||||||
OPENCV_HAL_IMPL_CMP_OP(!=)
|
OPENCV_HAL_IMPL_CMP_OP(!=)
|
||||||
|
|
||||||
template<int n>
|
template<int n>
|
||||||
|
@ -1038,18 +1038,6 @@ OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float64x2, v_min, vminq_f64)
|
|||||||
OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float64x2, v_max, vmaxq_f64)
|
OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float64x2, v_max, vmaxq_f64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CV_SIMD128_64F
|
|
||||||
inline int64x2_t vmvnq_s64(int64x2_t a)
|
|
||||||
{
|
|
||||||
int64x2_t vx = vreinterpretq_s64_u32(vdupq_n_u32(0xFFFFFFFF));
|
|
||||||
return veorq_s64(a, vx);
|
|
||||||
}
|
|
||||||
inline uint64x2_t vmvnq_u64(uint64x2_t a)
|
|
||||||
{
|
|
||||||
uint64x2_t vx = vreinterpretq_u64_u32(vdupq_n_u32(0xFFFFFFFF));
|
|
||||||
return veorq_u64(a, vx);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#define OPENCV_HAL_IMPL_NEON_INT_CMP_OP(_Tpvec, cast, suffix, not_suffix) \
|
#define OPENCV_HAL_IMPL_NEON_INT_CMP_OP(_Tpvec, cast, suffix, not_suffix) \
|
||||||
inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \
|
inline _Tpvec operator == (const _Tpvec& a, const _Tpvec& b) \
|
||||||
{ return _Tpvec(cast(vceqq_##suffix(a.val, b.val))); } \
|
{ return _Tpvec(cast(vceqq_##suffix(a.val, b.val))); } \
|
||||||
@ -1071,9 +1059,47 @@ OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int16x8, vreinterpretq_s16_u16, s16, u16)
|
|||||||
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint32x4, OPENCV_HAL_NOP, u32, u32)
|
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint32x4, OPENCV_HAL_NOP, u32, u32)
|
||||||
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int32x4, vreinterpretq_s32_u32, s32, u32)
|
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int32x4, vreinterpretq_s32_u32, s32, u32)
|
||||||
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float32x4, vreinterpretq_f32_u32, f32, u32)
|
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float32x4, vreinterpretq_f32_u32, f32, u32)
|
||||||
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
static inline uint64x2_t vmvnq_u64(uint64x2_t a)
|
||||||
|
{
|
||||||
|
uint64x2_t vx = vreinterpretq_u64_u32(vdupq_n_u32(0xFFFFFFFF));
|
||||||
|
return veorq_u64(a, vx);
|
||||||
|
}
|
||||||
|
//OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint64x2, OPENCV_HAL_NOP, u64, u64)
|
||||||
|
//OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int64x2, vreinterpretq_s64_u64, s64, u64)
|
||||||
|
static inline v_uint64x2 operator == (const v_uint64x2& a, const v_uint64x2& b)
|
||||||
|
{ return v_uint64x2(vceqq_u64(a.val, b.val)); }
|
||||||
|
static inline v_uint64x2 operator != (const v_uint64x2& a, const v_uint64x2& b)
|
||||||
|
{ return v_uint64x2(vmvnq_u64(vceqq_u64(a.val, b.val))); }
|
||||||
|
static inline v_int64x2 operator == (const v_int64x2& a, const v_int64x2& b)
|
||||||
|
{ return v_int64x2(vreinterpretq_s64_u64(vceqq_s64(a.val, b.val))); }
|
||||||
|
static inline v_int64x2 operator != (const v_int64x2& a, const v_int64x2& b)
|
||||||
|
{ return v_int64x2(vreinterpretq_s64_u64(vmvnq_u64(vceqq_s64(a.val, b.val)))); }
|
||||||
|
#else
|
||||||
|
static inline v_uint64x2 operator == (const v_uint64x2& a, const v_uint64x2& b)
|
||||||
|
{
|
||||||
|
uint32x4_t cmp = vceqq_u32(vreinterpretq_u32_u64(a.val), vreinterpretq_u32_u64(b.val));
|
||||||
|
uint32x4_t swapped = vrev64q_u32(cmp);
|
||||||
|
return v_uint64x2(vreinterpretq_u64_u32(vandq_u32(cmp, swapped)));
|
||||||
|
}
|
||||||
|
static inline v_uint64x2 operator != (const v_uint64x2& a, const v_uint64x2& b)
|
||||||
|
{
|
||||||
|
uint32x4_t cmp = vceqq_u32(vreinterpretq_u32_u64(a.val), vreinterpretq_u32_u64(b.val));
|
||||||
|
uint32x4_t swapped = vrev64q_u32(cmp);
|
||||||
|
uint64x2_t v_eq = vreinterpretq_u64_u32(vandq_u32(cmp, swapped));
|
||||||
|
uint64x2_t vx = vreinterpretq_u64_u32(vdupq_n_u32(0xFFFFFFFF));
|
||||||
|
return v_uint64x2(veorq_u64(v_eq, vx));
|
||||||
|
}
|
||||||
|
static inline v_int64x2 operator == (const v_int64x2& a, const v_int64x2& b)
|
||||||
|
{
|
||||||
|
return v_reinterpret_as_s64(v_reinterpret_as_u64(a) == v_reinterpret_as_u64(b));
|
||||||
|
}
|
||||||
|
static inline v_int64x2 operator != (const v_int64x2& a, const v_int64x2& b)
|
||||||
|
{
|
||||||
|
return v_reinterpret_as_s64(v_reinterpret_as_u64(a) != v_reinterpret_as_u64(b));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if CV_SIMD128_64F
|
#if CV_SIMD128_64F
|
||||||
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_uint64x2, OPENCV_HAL_NOP, u64, u64)
|
|
||||||
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_int64x2, vreinterpretq_s64_u64, s64, u64)
|
|
||||||
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float64x2, vreinterpretq_f64_u64, f64, u64)
|
OPENCV_HAL_IMPL_NEON_INT_CMP_OP(v_float64x2, vreinterpretq_f64_u64, f64, u64)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ template <typename R> struct Data
|
|||||||
{
|
{
|
||||||
*this = r;
|
*this = r;
|
||||||
}
|
}
|
||||||
operator R ()
|
operator R () const
|
||||||
{
|
{
|
||||||
return initializer<R::nlanes>().init(*this);
|
return initializer<R::nlanes>().init(*this);
|
||||||
}
|
}
|
||||||
@ -1559,11 +1559,34 @@ template<typename R> struct TheTest
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CV_SIMD_64F
|
void do_check_cmp64(const Data<R>& dataA, const Data<R>& dataB)
|
||||||
|
{
|
||||||
|
R a = dataA;
|
||||||
|
R b = dataB;
|
||||||
|
|
||||||
|
Data<R> dataEQ = (a == b);
|
||||||
|
Data<R> dataNE = (a != b);
|
||||||
|
|
||||||
|
for (int i = 0; i < R::nlanes; ++i)
|
||||||
|
{
|
||||||
|
SCOPED_TRACE(cv::format("i=%d", i));
|
||||||
|
if (cvtest::debugLevel > 0) cout << "i=" << i << " ( " << dataA[i] << " vs " << dataB[i] << " ): eq=" << dataEQ[i] << " ne=" << dataNE[i] << endl;
|
||||||
|
EXPECT_NE((LaneType)dataEQ[i], (LaneType)dataNE[i]);
|
||||||
|
if (dataA[i] == dataB[i])
|
||||||
|
EXPECT_EQ((LaneType)-1, (LaneType)dataEQ[i]);
|
||||||
|
else
|
||||||
|
EXPECT_EQ((LaneType)0, (LaneType)dataEQ[i]);
|
||||||
|
if (dataA[i] != dataB[i])
|
||||||
|
EXPECT_EQ((LaneType)-1, (LaneType)dataNE[i]);
|
||||||
|
else
|
||||||
|
EXPECT_EQ((LaneType)0, (LaneType)dataNE[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TheTest & test_cmp64()
|
TheTest & test_cmp64()
|
||||||
{
|
{
|
||||||
Data<R> dataA, dataB;
|
Data<R> dataA;
|
||||||
R a = dataA, b = dataB;
|
Data<R> dataB;
|
||||||
|
|
||||||
for (int i = 0; i < R::nlanes; ++i)
|
for (int i = 0; i < R::nlanes; ++i)
|
||||||
{
|
{
|
||||||
@ -1571,37 +1594,25 @@ template<typename R> struct TheTest
|
|||||||
}
|
}
|
||||||
dataA[0]++;
|
dataA[0]++;
|
||||||
|
|
||||||
a = dataA, b = dataB;
|
do_check_cmp64(dataA, dataB);
|
||||||
|
do_check_cmp64(dataB, dataA);
|
||||||
|
|
||||||
Data<R> resC = (a == b);
|
dataA[0] = dataB[0];
|
||||||
Data<R> resD = (a != b);
|
dataA[1] += (((LaneType)1) << 32);
|
||||||
|
do_check_cmp64(dataA, dataB);
|
||||||
|
do_check_cmp64(dataB, dataA);
|
||||||
|
|
||||||
for (int i = 0; i < R::nlanes; ++i)
|
dataA[0] = (LaneType)-1;
|
||||||
{
|
dataB[0] = (LaneType)-1;
|
||||||
SCOPED_TRACE(cv::format("i=%d", i));
|
dataA[1] = (LaneType)-1;
|
||||||
EXPECT_EQ(dataA[i] == dataB[i], resC[i] != 0);
|
dataB[1] = (LaneType)2;
|
||||||
EXPECT_EQ(dataA[i] != dataB[i], resD[i] != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < R::nlanes; ++i)
|
do_check_cmp64(dataA, dataB);
|
||||||
{
|
do_check_cmp64(dataB, dataA);
|
||||||
dataA[i] = dataB[i] = (LaneType)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = dataA, b = dataB;
|
|
||||||
|
|
||||||
resC = (a == b);
|
|
||||||
resD = (a != b);
|
|
||||||
|
|
||||||
for (int i = 0; i < R::nlanes; ++i)
|
|
||||||
{
|
|
||||||
SCOPED_TRACE(cv::format("i=%d", i));
|
|
||||||
EXPECT_EQ(dataA[i] == dataB[i], resC[i] != 0);
|
|
||||||
EXPECT_EQ(dataA[i] != dataB[i], resD[i] != 0);
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1837,9 +1848,8 @@ void test_hal_intrin_uint64()
|
|||||||
TheTest<v_uint64>()
|
TheTest<v_uint64>()
|
||||||
.test_loadstore()
|
.test_loadstore()
|
||||||
.test_addsub()
|
.test_addsub()
|
||||||
#if CV_SIMD_64F
|
|
||||||
.test_cmp64()
|
.test_cmp64()
|
||||||
#endif
|
//.test_cmp() - not declared as supported
|
||||||
.test_shift<1>().test_shift<8>()
|
.test_shift<1>().test_shift<8>()
|
||||||
.test_logic()
|
.test_logic()
|
||||||
.test_reverse()
|
.test_reverse()
|
||||||
@ -1857,9 +1867,8 @@ void test_hal_intrin_int64()
|
|||||||
TheTest<v_int64>()
|
TheTest<v_int64>()
|
||||||
.test_loadstore()
|
.test_loadstore()
|
||||||
.test_addsub()
|
.test_addsub()
|
||||||
#if CV_SIMD_64F
|
|
||||||
.test_cmp64()
|
.test_cmp64()
|
||||||
#endif
|
//.test_cmp() - not declared as supported
|
||||||
.test_shift<1>().test_shift<8>()
|
.test_shift<1>().test_shift<8>()
|
||||||
.test_logic()
|
.test_logic()
|
||||||
.test_reverse()
|
.test_reverse()
|
||||||
@ -1936,7 +1945,8 @@ void test_hal_intrin_float64()
|
|||||||
.test_rotate<2>().test_rotate<3>()
|
.test_rotate<2>().test_rotate<3>()
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
#else
|
||||||
|
std::cout << "SKIP: CV_SIMD_64F is not available" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user