diff --git a/modules/core/include/opencv2/core/hal/intrin.hpp b/modules/core/include/opencv2/core/hal/intrin.hpp index a04de3a12d..c12140bbf8 100644 --- a/modules/core/include/opencv2/core/hal/intrin.hpp +++ b/modules/core/include/opencv2/core/hal/intrin.hpp @@ -537,7 +537,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_setall_f32(float v) { return VXPREFIX(_setall_f32)(v); } inline v_int64 vx_setall_s64(int64 v) { return VXPREFIX(_setall_s64)(v); } inline v_uint64 vx_setall_u64(uint64 v) { return VXPREFIX(_setall_u64)(v); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_setall_f64(double v) { return VXPREFIX(_setall_f64)(v); } #endif //! @} @@ -554,7 +554,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_setzero_f32() { return VXPREFIX(_setzero_f32)(); } inline v_int64 vx_setzero_s64() { return VXPREFIX(_setzero_s64)(); } inline v_uint64 vx_setzero_u64() { return VXPREFIX(_setzero_u64)(); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_setzero_f64() { return VXPREFIX(_setzero_f64)(); } #endif //! @} @@ -571,7 +571,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_load(const float * ptr) { return VXPREFIX(_load)(ptr); } inline v_int64 vx_load(const int64 * ptr) { return VXPREFIX(_load)(ptr); } inline v_uint64 vx_load(const uint64 * ptr) { return VXPREFIX(_load)(ptr); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_load(const double * ptr) { return VXPREFIX(_load)(ptr); } #endif //! @} @@ -588,7 +588,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_load_aligned(const float * ptr) { return VXPREFIX(_load_aligned)(ptr); } inline v_int64 vx_load_aligned(const int64 * ptr) { return VXPREFIX(_load_aligned)(ptr); } inline v_uint64 vx_load_aligned(const uint64 * ptr) { return VXPREFIX(_load_aligned)(ptr); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_load_aligned(const double * ptr) { return VXPREFIX(_load_aligned)(ptr); } #endif //! @} @@ -605,7 +605,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_load_low(const float * ptr) { return VXPREFIX(_load_low)(ptr); } inline v_int64 vx_load_low(const int64 * ptr) { return VXPREFIX(_load_low)(ptr); } inline v_uint64 vx_load_low(const uint64 * ptr) { return VXPREFIX(_load_low)(ptr); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_load_low(const double * ptr) { return VXPREFIX(_load_low)(ptr); } #endif //! @} @@ -622,7 +622,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_load_halves(const float * ptr0, const float * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); } inline v_int64 vx_load_halves(const int64 * ptr0, const int64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); } inline v_uint64 vx_load_halves(const uint64 * ptr0, const uint64 * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_load_halves(const double * ptr0, const double * ptr1) { return VXPREFIX(_load_halves)(ptr0, ptr1); } #endif //! @} @@ -639,7 +639,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_lut(const float* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); } inline v_int64 vx_lut(const int64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); } inline v_uint64 vx_lut(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_lut(const double* ptr, const int* idx) { return VXPREFIX(_lut)(ptr, idx); } #endif //! @} @@ -656,7 +656,7 @@ namespace CV__SIMD_NAMESPACE { inline v_float32 vx_lut_pairs(const float* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); } inline v_int64 vx_lut_pairs(const int64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); } inline v_uint64 vx_lut_pairs(const uint64 * ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); } -#if CV_SIMD_64F +#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F inline v_float64 vx_lut_pairs(const double* ptr, const int* idx) { return VXPREFIX(_lut_pairs)(ptr, idx); } #endif //! @} diff --git a/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp b/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp index 30c7524699..7452ad91ad 100644 --- a/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp +++ b/modules/core/include/opencv2/core/hal/intrin_rvv_scalable.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #ifndef CV_RVV_MAX_VLEN #define CV_RVV_MAX_VLEN 1024 @@ -284,6 +285,64 @@ inline v_float64 v_reinterpret_as_f64(const v_float32& v) \ } #endif +//////////// Extract ////////////// + +#define OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(_Tpvec, _Tp, suffix, vl) \ +template \ +inline _Tpvec v_extract(const _Tpvec& a, const _Tpvec& b, int i = s) \ +{ \ + return vslideup(vslidedown(v_setzero_##suffix(), a, i, vl), b, VTraits<_Tpvec>::vlanes() - i, vl); \ +} \ +template inline _Tp v_extract_n(_Tpvec v, int i = s) \ +{ \ + return vmv_x(vslidedown(v_setzero_##suffix(), v, i, vl)); \ +} + + +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_uint8, uchar, u8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_int8, schar, s8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_uint16, ushort, u16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_int16, short, s16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_uint32, unsigned int, u32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_int32, int, s32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_uint64, uint64, u64, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT_INTEGER(v_int64, int64, s64, VTraits::vlanes()) + +#define OPENCV_HAL_IMPL_RVV_EXTRACT_FP(_Tpvec, _Tp, suffix, vl) \ +template \ +inline _Tpvec v_extract(const _Tpvec& a, const _Tpvec& b, int i = s) \ +{ \ + return vslideup(vslidedown(v_setzero_##suffix(), a, i, vl), b, VTraits<_Tpvec>::vlanes() - i, vl); \ +} \ +template inline _Tp v_extract_n(_Tpvec v, int i = s) \ +{ \ + return vfmv_f(vslidedown(v_setzero_##suffix(), v, i, vl)); \ +} + +OPENCV_HAL_IMPL_RVV_EXTRACT_FP(v_float32, float, f32, VTraits::vlanes()) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_EXTRACT_FP(v_float64, double, f64, VTraits::vlanes()) +#endif + +#define OPENCV_HAL_IMPL_RVV_EXTRACT(_Tpvec, _Tp, vl) \ +inline _Tp v_extract_highest(_Tpvec v) \ +{ \ + return v_extract_n(v, vl-1); \ +} + +OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint8, uchar, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_int8, schar, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint16, ushort, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_int16, short, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint32, unsigned int, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_int32, int, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint64, uint64, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_int64, int64, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_EXTRACT(v_float32, float, VTraits::vlanes()) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_EXTRACT(v_float64, double, VTraits::vlanes()) +#endif + ////////////// Load/Store ////////////// #define OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(_Tpvec, _nTpvec, _Tp, hvl, vl, width, suffix, vmv) \ @@ -387,6 +446,9 @@ OPENCV_HAL_IMPL_RVV_LUT(v_int16, short, m2) OPENCV_HAL_IMPL_RVV_LUT(v_int32, int, m1) OPENCV_HAL_IMPL_RVV_LUT(v_int64, int64_t, mf2) OPENCV_HAL_IMPL_RVV_LUT(v_float32, float, m1) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_LUT(v_float64, double, mf2) +#endif inline v_uint8 v_lut(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut((schar*)tab, idx)); } inline v_uint8 v_lut_pairs(const uchar* tab, const int* idx) { return v_reinterpret_as_u8(v_lut_pairs((schar*)tab, idx)); } @@ -401,6 +463,189 @@ inline v_uint64 v_lut(const uint64* tab, const int* idx) { return v_reinterpret_ inline v_uint64 v_lut_pairs(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_pairs((const int64_t *)tab, idx)); } inline v_uint64 v_lut_quads(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v_lut_quads((const int64_t*)tab, idx)); } +////////////// Pack boolean //////////////////// +/* TODO */ + +////////////// Arithmetics ////////////// +#define OPENCV_HAL_IMPL_RVV_BIN_OP(_Tpvec, ocv_intrin, rvv_intrin) \ +inline _Tpvec v_##ocv_intrin(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return rvv_intrin(a, b, VTraits<_Tpvec>::vlanes()); \ +} + +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint8, add, vsaddu) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint8, sub, vssubu) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int8, add, vsadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int8, sub, vssub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint16, add, vsaddu) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint16, sub, vssubu) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int16, add, vsadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int16, sub, vssub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint32, add, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint32, sub, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint32, mul, vmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int32, add, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int32, sub, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int32, mul, vmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float32, add, vfadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float32, sub, vfsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float32, mul, vfmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float32, div, vfdiv) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint64, add, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint64, sub, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int64, add, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int64, sub, vsub) + +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float64, add, vfadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float64, sub, vfsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float64, mul, vfmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_float64, div, vfdiv) +#endif + +#define OPENCV_HAL_IMPL_RVV_BIN_MADD(_Tpvec, rvv_add) \ +template \ +inline _Tpvec v_add(const _Tpvec& f1, const _Tpvec& f2, const Args&... vf) { \ + return v_add(rvv_add(f1, f2, VTraits<_Tpvec>::vlanes()), vf...); \ +} +#define OPENCV_HAL_IMPL_RVV_BIN_MMUL(_Tpvec, rvv_mul) \ +template \ +inline _Tpvec v_mul(const _Tpvec& f1, const _Tpvec& f2, const Args&... vf) { \ + return v_mul(rvv_mul(f1, f2, VTraits<_Tpvec>::vlanes()), vf...); \ +} +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_uint8, vsaddu) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_int8, vsadd) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_uint16, vsaddu) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_int16, vsadd) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_uint32, vadd) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_int32, vadd) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_float32, vfadd) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_uint64, vadd) +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_int64, vadd) + +OPENCV_HAL_IMPL_RVV_BIN_MMUL(v_uint32, vmul) +OPENCV_HAL_IMPL_RVV_BIN_MMUL(v_int32, vmul) +OPENCV_HAL_IMPL_RVV_BIN_MMUL(v_float32, vfmul) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_BIN_MADD(v_float64, vfadd) +OPENCV_HAL_IMPL_RVV_BIN_MMUL(v_float64, vfmul) +#endif + +#define OPENCV_HAL_IMPL_RVV_MUL_EXPAND(_Tpvec, _Tpwvec, _TpwvecM2, suffix, wmul) \ +inline void v_mul_expand(const _Tpvec& a, const _Tpvec& b, _Tpwvec& c, _Tpwvec& d) \ +{ \ + _TpwvecM2 temp = wmul(a, b, VTraits<_Tpvec>::vlanes()); \ + c = vget_##suffix##m1(temp, 0); \ + d = vget_##suffix##m1(temp, 1); \ +} + +OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_uint8, v_uint16, vuint16m2_t, u16, vwmulu) +OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_int8, v_int16, vint16m2_t, i16, vwmul) +OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_uint16, v_uint32, vuint32m2_t, u32, vwmulu) +OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_int16, v_int32, vint32m2_t, i32, vwmul) +OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_uint32, v_uint64, vuint64m2_t, u64, vwmulu) + +inline v_int16 v_mul_hi(const v_int16& a, const v_int16& b) +{ + return vmulh(a, b, VTraits::vlanes()); +} +inline v_uint16 v_mul_hi(const v_uint16& a, const v_uint16& b) +{ + return vmulhu(a, b, VTraits::vlanes()); +} + +////////////// Arithmetics (wrap)////////////// +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint8, add_wrap, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int8, add_wrap, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint16, add_wrap, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int16, add_wrap, vadd) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint8, sub_wrap, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int8, sub_wrap, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint16, sub_wrap, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int16, sub_wrap, vsub) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint8, mul_wrap, vmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int8, mul_wrap, vmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_uint16, mul_wrap, vmul) +OPENCV_HAL_IMPL_RVV_BIN_OP(v_int16, mul_wrap, vmul) + +//////// Saturating Multiply //////// +#define OPENCV_HAL_IMPL_RVV_MUL_SAT(_Tpvec, _clip, _wmul) \ +inline _Tpvec v_mul(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _clip(_wmul(a, b, VTraits<_Tpvec>::vlanes()), 0, VTraits<_Tpvec>::vlanes()); \ +} \ +template \ +inline _Tpvec v_mul(const _Tpvec& a1, const _Tpvec& a2, const Args&... va) { \ + return v_mul(_clip(_wmul(a1, a2, VTraits<_Tpvec>::vlanes()), 0, VTraits<_Tpvec>::vlanes()), va...); \ +} + +OPENCV_HAL_IMPL_RVV_MUL_SAT(v_uint8, vnclipu, vwmulu) +OPENCV_HAL_IMPL_RVV_MUL_SAT(v_int8, vnclip, vwmul) +OPENCV_HAL_IMPL_RVV_MUL_SAT(v_uint16, vnclipu, vwmulu) +OPENCV_HAL_IMPL_RVV_MUL_SAT(v_int16, vnclip, vwmul) + +////////////// Bitwise logic ////////////// + +#define OPENCV_HAL_IMPL_RVV_LOGIC_OP(_Tpvec, vl) \ +inline _Tpvec v_and(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vand(a, b, vl); \ +} \ +inline _Tpvec v_or(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vor(a, b, vl); \ +} \ +inline _Tpvec v_xor(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vxor(a, b, vl); \ +} \ +inline _Tpvec v_not (const _Tpvec& a) \ +{ \ + return vnot(a, vl); \ +} + +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint64, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int64, VTraits::vlanes()) + + + +////////////// Bitwise shifts ////////////// + +#define OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(_Tpvec, vl) \ +template inline _Tpvec v_shl(const _Tpvec& a) \ +{ \ + return _Tpvec(vsll(a, uint8_t(n), vl)); \ +} \ +template inline _Tpvec v_shr(const _Tpvec& a) \ +{ \ + return _Tpvec(vsrl(a, uint8_t(n), vl)); \ +} + +#define OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(_Tpvec, vl) \ +template inline _Tpvec v_shl(const _Tpvec& a) \ +{ \ + return _Tpvec(vsll(a, uint8_t(n), vl)); \ +} \ +template inline _Tpvec v_shr(const _Tpvec& a) \ +{ \ + return _Tpvec(vsra(a, uint8_t(n), vl)); \ +} + +OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint64, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int64, VTraits::vlanes()) + +////////////// Comparison ////////////// +// TODO ////////////// Min/Max ////////////// @@ -424,15 +669,378 @@ OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int32, v_min, vmin, VTraits::vlanes()) OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int32, v_max, vmax, VTraits::vlanes()) OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float32, v_min, vfmin, VTraits::vlanes()) OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float32, v_max, vfmax, VTraits::vlanes()) -OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint64, v_min, vminu, VTraits::vlanes()) -OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint64, v_max, vmaxu, VTraits::vlanes()) -OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int64, v_min, vmin, VTraits::vlanes()) -OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int64, v_max, vmax, VTraits::vlanes()) #if CV_SIMD_SCALABLE_64F OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float64, v_min, vfmin, VTraits::vlanes()) OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float64, v_max, vfmax, VTraits::vlanes()) #endif +////////////// Reduce ////////////// + +#define OPENCV_HAL_IMPL_RVV_REDUCE_SUM(_Tpvec, _wTpvec, _nwTpvec, scalartype, wsuffix, vl, red) \ +inline scalartype v_reduce_sum(const _Tpvec& a) \ +{ \ + _nwTpvec zero = vmv_v_x_##wsuffix##m1(0, vl); \ + _nwTpvec res = vmv_v_x_##wsuffix##m1(0, vl); \ + res = v##red(res, a, zero, vl); \ + return (scalartype)v_get0(res); \ +} +OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint8, v_uint16, vuint16m1_t, unsigned, u16, VTraits::vlanes(), wredsumu) +OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int8, v_int16, vint16m1_t, int, i16, VTraits::vlanes(), wredsum) +OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint16, v_uint32, vuint32m1_t, unsigned, u32, VTraits::vlanes(), wredsumu) +OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int16, v_int32, vint32m1_t, int, i32, VTraits::vlanes(), wredsum) +OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint32, v_uint64, vuint64m1_t, unsigned, u64, VTraits::vlanes(), wredsumu) +OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int32, v_int64, vint64m1_t, int, i64, VTraits::vlanes(), wredsum) + +#define OPENCV_HAL_IMPL_RVV_REDUCE_SUM_FP(_Tpvec, _wTpvec, _nwTpvec, scalartype, wsuffix, vl) \ +inline scalartype v_reduce_sum(const _Tpvec& a) \ +{ \ + _nwTpvec zero = vfmv_v_f_##wsuffix##m1(0, vl); \ + _nwTpvec res = vfmv_v_f_##wsuffix##m1(0, vl); \ + res = vfredosum(res, a, zero, vl); \ + return (scalartype)v_get0(res); \ +} +OPENCV_HAL_IMPL_RVV_REDUCE_SUM_FP(v_float32, v_float32, vfloat32m1_t, float, f32, VTraits::vlanes()) + +#define OPENCV_HAL_IMPL_RVV_REDUCE(_Tpvec, func, scalartype, suffix, vl, red) \ +inline scalartype v_reduce_##func(const _Tpvec& a) \ +{ \ + _Tpvec res = _Tpvec(v##red(a, a, a, vl)); \ + return (scalartype)v_get0(res); \ +} + +OPENCV_HAL_IMPL_RVV_REDUCE(v_uint8, min, uchar, u8, VTraits::vlanes(), redminu) +OPENCV_HAL_IMPL_RVV_REDUCE(v_int8, min, schar, i8, VTraits::vlanes(), redmin) +OPENCV_HAL_IMPL_RVV_REDUCE(v_uint16, min, ushort, u16, VTraits::vlanes(), redminu) +OPENCV_HAL_IMPL_RVV_REDUCE(v_int16, min, short, i16, VTraits::vlanes(), redmin) +OPENCV_HAL_IMPL_RVV_REDUCE(v_uint32, min, unsigned, u32, VTraits::vlanes(), redminu) +OPENCV_HAL_IMPL_RVV_REDUCE(v_int32, min, int, i32, VTraits::vlanes(), redmin) +OPENCV_HAL_IMPL_RVV_REDUCE(v_float32, min, float, f32, VTraits::vlanes(), fredmin) +OPENCV_HAL_IMPL_RVV_REDUCE(v_uint8, max, uchar, u8, VTraits::vlanes(), redmaxu) +OPENCV_HAL_IMPL_RVV_REDUCE(v_int8, max, schar, i8, VTraits::vlanes(), redmax) +OPENCV_HAL_IMPL_RVV_REDUCE(v_uint16, max, ushort, u16, VTraits::vlanes(), redmaxu) +OPENCV_HAL_IMPL_RVV_REDUCE(v_int16, max, short, i16, VTraits::vlanes(), redmax) +OPENCV_HAL_IMPL_RVV_REDUCE(v_uint32, max, unsigned, u32, VTraits::vlanes(), redmaxu) +OPENCV_HAL_IMPL_RVV_REDUCE(v_int32, max, int, i32, VTraits::vlanes(), redmax) +OPENCV_HAL_IMPL_RVV_REDUCE(v_float32, max, float, f32, VTraits::vlanes(), fredmax) + +//TODO: v_reduce_sum4 + +////////////// Square-Root ////////////// + +inline v_float32 v_sqrt(const v_float32& x) +{ + return vfsqrt(x, VTraits::vlanes()); +} + +inline v_float32 v_invsqrt(const v_float32& x) +{ + v_float32 one = v_setall_f32(1.0f); + return v_div(one, v_sqrt(x)); +} + +#if CV_SIMD_SCALABLE_64F +inline v_float64 v_sqrt(const v_float64& x) +{ + return vfsqrt(x, VTraits::vlanes()); +} + +inline v_float64 v_invsqrt(const v_float64& x) +{ + v_float64 one = v_setall_f64(1.0f); + return v_div(one, v_sqrt(x)); +} +#endif + +inline v_float32 v_magnitude(const v_float32& a, const v_float32& b) +{ + v_float32 x = vfmacc(vfmul(a, a, VTraits::vlanes()), b, b, VTraits::vlanes()); + return v_sqrt(x); +} + +inline v_float32 v_sqr_magnitude(const v_float32& a, const v_float32& b) +{ + return v_float32(vfmacc(vfmul(a, a, VTraits::vlanes()), b, b, VTraits::vlanes())); +} + +#if CV_SIMD_SCALABLE_64F +inline v_float64 v_magnitude(const v_float64& a, const v_float64& b) +{ + v_float64 x = vfmacc(vfmul(a, a, VTraits::vlanes()), b, b, VTraits::vlanes()); + return v_sqrt(x); +} + +inline v_float64 v_sqr_magnitude(const v_float64& a, const v_float64& b) +{ + return vfmacc(vfmul(a, a, VTraits::vlanes()), b, b, VTraits::vlanes()); +} +#endif + +////////////// Multiply-Add ////////////// + +inline v_float32 v_fma(const v_float32& a, const v_float32& b, const v_float32& c) +{ + return vfmacc(c, a, b, VTraits::vlanes()); +} +inline v_int32 v_fma(const v_int32& a, const v_int32& b, const v_int32& c) +{ + return vmacc(c, a, b, VTraits::vlanes()); +} + +inline v_float32 v_muladd(const v_float32& a, const v_float32& b, const v_float32& c) +{ + return v_fma(a, b, c); +} + +inline v_int32 v_muladd(const v_int32& a, const v_int32& b, const v_int32& c) +{ + return v_fma(a, b, c); +} + +#if CV_SIMD_SCALABLE_64F +inline v_float64 v_fma(const v_float64& a, const v_float64& b, const v_float64& c) +{ + return vfmacc_vv_f64m1(c, a, b, VTraits::vlanes()); +} + +inline v_float64 v_muladd(const v_float64& a, const v_float64& b, const v_float64& c) +{ + return v_fma(a, b, c); +} +#endif + +////////////// Check all/any ////////////// + +#define OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(_Tpvec, vl) \ +inline bool v_check_all(const _Tpvec& a) \ +{ \ + return vcpop(vmslt(a, 0, vl), vl) == vl; \ +} \ +inline bool v_check_any(const _Tpvec& a) \ +{ \ + return vcpop(vmslt(a, 0, vl), vl) != 0; \ +} + +OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_int8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_int16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_int32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_int64, VTraits::vlanes()) + + +inline bool v_check_all(const v_uint8& a) +{ return v_check_all(v_reinterpret_as_s8(a)); } +inline bool v_check_any(const v_uint8& a) +{ return v_check_any(v_reinterpret_as_s8(a)); } + +inline bool v_check_all(const v_uint16& a) +{ return v_check_all(v_reinterpret_as_s16(a)); } +inline bool v_check_any(const v_uint16& a) +{ return v_check_any(v_reinterpret_as_s16(a)); } + +inline bool v_check_all(const v_uint32& a) +{ return v_check_all(v_reinterpret_as_s32(a)); } +inline bool v_check_any(const v_uint32& a) +{ return v_check_any(v_reinterpret_as_s32(a)); } + +inline bool v_check_all(const v_float32& a) +{ return v_check_all(v_reinterpret_as_s32(a)); } +inline bool v_check_any(const v_float32& a) +{ return v_check_any(v_reinterpret_as_s32(a)); } + +inline bool v_check_all(const v_uint64& a) +{ return v_check_all(v_reinterpret_as_s64(a)); } +inline bool v_check_any(const v_uint64& a) +{ return v_check_any(v_reinterpret_as_s64(a)); } + +#if CV_SIMD_SCALABLE_64F +inline bool v_check_all(const v_float64& a) +{ return v_check_all(v_reinterpret_as_s64(a)); } +inline bool v_check_any(const v_float64& a) +{ return v_check_any(v_reinterpret_as_s64(a)); } +#endif + +////////////// abs ////////////// + +#define OPENCV_HAL_IMPL_RVV_ABSDIFF(_Tpvec, abs) \ +inline _Tpvec v_##abs(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return v_sub(v_max(a, b), v_min(a, b)); \ +} + +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_uint8, absdiff) +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_uint16, absdiff) +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_uint32, absdiff) +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_float32, absdiff) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_float64, absdiff) +#endif +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_int8, absdiffs) +OPENCV_HAL_IMPL_RVV_ABSDIFF(v_int16, absdiffs) + +#define OPENCV_HAL_IMPL_RVV_ABSDIFF_S(_Tpvec, _rTpvec, width) \ +inline _rTpvec v_absdiff(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vnclipu(vreinterpret_u##width##m2(vwsub_vv(v_max(a, b), v_min(a, b), VTraits<_Tpvec>::vlanes())), 0, VTraits<_Tpvec>::vlanes()); \ +} + +OPENCV_HAL_IMPL_RVV_ABSDIFF_S(v_int8, v_uint8, 16) +OPENCV_HAL_IMPL_RVV_ABSDIFF_S(v_int16, v_uint16, 32) +OPENCV_HAL_IMPL_RVV_ABSDIFF_S(v_int32, v_uint32, 64) + +#define OPENCV_HAL_IMPL_RVV_ABS(_Tprvec, _Tpvec, suffix) \ +inline _Tprvec v_abs(const _Tpvec& a) \ +{ \ + return v_absdiff(a, v_setzero_##suffix()); \ +} + +OPENCV_HAL_IMPL_RVV_ABS(v_uint8, v_int8, s8) +OPENCV_HAL_IMPL_RVV_ABS(v_uint16, v_int16, s16) +OPENCV_HAL_IMPL_RVV_ABS(v_uint32, v_int32, s32) +OPENCV_HAL_IMPL_RVV_ABS(v_float32, v_float32, f32) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_ABS(v_float64, v_float64, f64) +#endif + + +#define OPENCV_HAL_IMPL_RVV_REDUCE_SAD(_Tpvec, scalartype) \ +inline scalartype v_reduce_sad(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return v_reduce_sum(v_absdiff(a, b)); \ +} + +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_uint8, unsigned) +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_int8, unsigned) +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_uint16, unsigned) +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_int16, unsigned) +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_uint32, unsigned) +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_int32, unsigned) +OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_float32, float) + +////////////// Select ////////////// + +#define OPENCV_HAL_IMPL_RVV_SELECT(_Tpvec, vl) \ +inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vmerge(vmsne(mask, 0, vl), b, a, vl); \ +} + +OPENCV_HAL_IMPL_RVV_SELECT(v_uint8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SELECT(v_uint16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SELECT(v_uint32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SELECT(v_int8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SELECT(v_int16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_SELECT(v_int32, VTraits::vlanes()) + +inline v_float32 v_select(const v_float32& mask, const v_float32& a, const v_float32& b) \ +{ \ + return vmerge(vmfne(mask, 0, VTraits::vlanes()), b, a, VTraits::vlanes()); \ +} + +#if CV_SIMD_SCALABLE_64F +inline v_float64 v_select(const v_float64& mask, const v_float64& a, const v_float64& b) \ +{ \ + return vmerge(vmfne(mask, 0, VTraits::vlanes()), b, a, VTraits::vlanes()); \ +} +#endif + +////////////// Rotate shift ////////////// + +#define OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(_Tpvec, suffix, vl) \ +template inline _Tpvec v_rotate_right(const _Tpvec& a) \ +{ \ + return vslidedown(vmv_v_x_##suffix##m1(0, vl), a, n, vl); \ +} \ +template inline _Tpvec v_rotate_left(const _Tpvec& a) \ +{ \ + return vslideup(vmv_v_x_##suffix##m1(0, vl), a, n, vl); \ +} \ +template<> inline _Tpvec v_rotate_left<0>(const _Tpvec& a) \ +{ return a; } \ +template inline _Tpvec v_rotate_right(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vslideup(vslidedown(vmv_v_x_##suffix##m1(0, vl), a, n, vl), b, VTraits<_Tpvec>::vlanes() - n, vl); \ +} \ +template inline _Tpvec v_rotate_left(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vslideup(vslidedown(vmv_v_x_##suffix##m1(0, vl), b, VTraits<_Tpvec>::vlanes() - n, vl), a, n, vl); \ +} \ +template<> inline _Tpvec v_rotate_left<0>(const _Tpvec& a, const _Tpvec& b) \ +{ CV_UNUSED(b); return a; } + +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_uint8, u8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_int8, i8, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_uint16, u16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_int16, i16, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_uint32, u32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_int32, i32, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_uint64, u64, VTraits::vlanes()) +OPENCV_HAL_IMPL_RVV_ROTATE_INTEGER(v_int64, i64, VTraits::vlanes()) + +#define OPENCV_HAL_IMPL_RVV_ROTATE_FP(_Tpvec, suffix, vl) \ +template inline _Tpvec v_rotate_right(const _Tpvec& a) \ +{ \ + return vslidedown(vfmv_v_f_##suffix##m1(0, vl), a, n, vl); \ +} \ +template inline _Tpvec v_rotate_left(const _Tpvec& a) \ +{ \ + return vslideup(vfmv_v_f_##suffix##m1(0, vl), a, n, vl); \ +} \ +template<> inline _Tpvec v_rotate_left<0>(const _Tpvec& a) \ +{ return a; } \ +template inline _Tpvec v_rotate_right(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vslideup(vslidedown(vfmv_v_f_##suffix##m1(0, vl), a, n, vl), b, VTraits<_Tpvec>::vlanes() - n, vl); \ +} \ +template inline _Tpvec v_rotate_left(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vslideup(vslidedown(vfmv_v_f_##suffix##m1(0, vl), b, VTraits<_Tpvec>::vlanes() - n, vl), a, n, vl); \ +} \ +template<> inline _Tpvec v_rotate_left<0>(const _Tpvec& a, const _Tpvec& b) \ +{ CV_UNUSED(b); return a; } + +OPENCV_HAL_IMPL_RVV_ROTATE_FP(v_float32, f32, VTraits::vlanes()) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_ROTATE_FP(v_float64, f64, VTraits::vlanes()) +#endif + +////////////// Convert to float ////////////// +// TODO + +//////////// Broadcast ////////////// + +#define OPENCV_HAL_IMPL_RVV_BROADCAST(_Tpvec, suffix) \ +template inline _Tpvec v_broadcast_element(_Tpvec v, int i = s) \ +{ \ + return v_setall_##suffix(v_extract_n(v, i)); \ +} \ +inline _Tpvec v_broadcast_highest(_Tpvec v) \ +{ \ + return v_setall_##suffix(v_extract_n(v, VTraits<_Tpvec>::vlanes()-1)); \ +} + +OPENCV_HAL_IMPL_RVV_BROADCAST(v_uint32, u32) +OPENCV_HAL_IMPL_RVV_BROADCAST(v_int32, s32) +OPENCV_HAL_IMPL_RVV_BROADCAST(v_float32, f32) + + +////////////// Reverse ////////////// +#define OPENCV_HAL_IMPL_RVV_REVERSE(_Tpvec, width) \ +inline _Tpvec v_reverse(const _Tpvec& a) \ +{ \ + vuint##width##m1_t vidx = vrsub(vid_v_u##width##m1(VTraits<_Tpvec>::vlanes()), VTraits<_Tpvec>::vlanes()-1, VTraits<_Tpvec>::vlanes()); \ + return vrgather(a, vidx, VTraits<_Tpvec>::vlanes()); \ +} +OPENCV_HAL_IMPL_RVV_REVERSE(v_uint8, 8) +OPENCV_HAL_IMPL_RVV_REVERSE(v_int8, 8) +OPENCV_HAL_IMPL_RVV_REVERSE(v_uint16, 16) +OPENCV_HAL_IMPL_RVV_REVERSE(v_int16, 16) +OPENCV_HAL_IMPL_RVV_REVERSE(v_uint32, 32) +OPENCV_HAL_IMPL_RVV_REVERSE(v_int32, 32) +OPENCV_HAL_IMPL_RVV_REVERSE(v_float32, 32) +OPENCV_HAL_IMPL_RVV_REVERSE(v_uint64, 64) +OPENCV_HAL_IMPL_RVV_REVERSE(v_int64, 64) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_REVERSE(v_float64, 64) +#endif //////////// Value reordering //////////// @@ -476,6 +1084,189 @@ inline v_int32 v_load_expand_q(const schar* ptr) } +/* void v_zip(const _Tpvec& a0, const _Tpvec& a1, _Tpvec& b0, _Tpvec& b1) + a0 = {A1 A2 A3 A4} + a1 = {B1 B2 B3 B4} +--------------- + {A1 B1 A2 B2} and {A3 B3 A4 B4} +*/ + +#define OPENCV_HAL_IMPL_RVV_ZIP(_Tpvec, _wTpvec, suffix, width, width2, convert2um2, convert2um1) \ +inline void v_zip(const _Tpvec& a0, const _Tpvec& a1, _Tpvec& b0, _Tpvec& b1) { \ + _wTpvec temp = vreinterpret_##suffix##m2(convert2um2( \ + vor(vzext_vf2(convert2um1(a0), VTraits<_Tpvec>::vlanes()*2), \ + vreinterpret_u##width2##m2(vslide1up(vreinterpret_u##width##m2(vzext_vf2(convert2um1(a1), VTraits<_Tpvec>::vlanes()*2)), 0, VTraits<_Tpvec>::vlanes()*2)), \ + VTraits<_Tpvec>::vlanes()))); \ + b0 = vget_##suffix##m1(temp, 0); \ + b1 = vget_##suffix##m1(temp, 1); \ +} +OPENCV_HAL_IMPL_RVV_ZIP(v_uint8, vuint8m2_t, u8, 8, 16, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_RVV_ZIP(v_int8, vint8m2_t, i8, 8, 16, vreinterpret_u8m2, vreinterpret_u8m1) +OPENCV_HAL_IMPL_RVV_ZIP(v_uint16, vuint16m2_t, u16, 16, 32, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_RVV_ZIP(v_int16, vint16m2_t, i16, 16, 32, vreinterpret_u16m2, vreinterpret_u16m1) +OPENCV_HAL_IMPL_RVV_ZIP(v_uint32, vuint32m2_t, u32, 32, 64, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_RVV_ZIP(v_int32, vint32m2_t, i32, 32, 64, vreinterpret_u32m2, vreinterpret_u32m1) +OPENCV_HAL_IMPL_RVV_ZIP(v_float32, vfloat32m2_t, f32, 32, 64, vreinterpret_u32m2, vreinterpret_u32m1) + +#define OPENCV_HAL_IMPL_RVV_UNPACKS(_Tpvec, width) \ +inline _Tpvec v_combine_low(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vslideup(a, b, VTraits<_Tpvec>::vlanes()/2, VTraits<_Tpvec>::vlanes());\ +} \ +inline _Tpvec v_combine_high(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return vslideup( \ + vslidedown(a, a, VTraits<_Tpvec>::vlanes()/2, VTraits<_Tpvec>::vlanes()), \ + vslidedown(b, b, VTraits<_Tpvec>::vlanes()/2, VTraits<_Tpvec>::vlanes()), \ + VTraits<_Tpvec>::vlanes()/2, \ + VTraits<_Tpvec>::vlanes()); \ +} \ +inline void v_recombine(const _Tpvec& a, const _Tpvec& b, _Tpvec& c, _Tpvec& d) \ +{ \ + c = v_combine_low(a, b); \ + d = v_combine_high(a, b); \ +} + +OPENCV_HAL_IMPL_RVV_UNPACKS(v_uint8, 8) +OPENCV_HAL_IMPL_RVV_UNPACKS(v_int8, 8) +OPENCV_HAL_IMPL_RVV_UNPACKS(v_uint16, 16) +OPENCV_HAL_IMPL_RVV_UNPACKS(v_int16, 16) +OPENCV_HAL_IMPL_RVV_UNPACKS(v_uint32, 32) +OPENCV_HAL_IMPL_RVV_UNPACKS(v_int32, 32) +OPENCV_HAL_IMPL_RVV_UNPACKS(v_float32, 32) +#if CV_SIMD_SCALABLE_64F +OPENCV_HAL_IMPL_RVV_UNPACKS(v_float64, 64) +#endif + +static uint64_t idx_interleave_pairs[] = { \ + 0x0705060403010200, 0x0f0d0e0c0b090a08, 0x1715161413111210, 0x1f1d1e1c1b191a18, \ + 0x2725262423212220, 0x2f2d2e2c2b292a28, 0x3735363433313230, 0x3f3d3e3c3b393a38, \ + 0x4745464443414240, 0x4f4d4e4c4b494a48, 0x5755565453515250, 0x5f5d5e5c5b595a58, \ + 0x6765666463616260, 0x6f6d6e6c6b696a68, 0x7775767473717270, 0x7f7d7e7c7b797a78}; + +static uint64_t idx_interleave_quads[] = { \ + 0x0703060205010400, 0x0f0b0e0a0d090c08, 0x1713161215111410, 0x1f1b1e1a1d191c18, \ + 0x2723262225212420, 0x2f2b2e2a2d292c28, 0x3733363235313430, 0x3f3b3e3a3d393c38, \ + 0x4743464245414440, 0x4f4b4e4a4d494c48, 0x5753565255515450, 0x5f5b5e5a5d595c58, \ + 0x6763666265616460, 0x6f6b6e6a6d696c68, 0x7773767275717470, 0x7f7b7e7a7d797c78}; + +#define OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(_Tpvec, func) \ +inline _Tpvec v_interleave_##func(const _Tpvec& vec) { \ + CV_CheckLE(VTraits<_Tpvec>::vlanes(), VTraits<_Tpvec>::max_nlanes, "RVV implementation only supports VLEN in the range [128, 1024]"); \ + vuint8m1_t vidx = vundefined_u8m1();\ + vidx = vreinterpret_u8m1(vle64_v_u64m1(idx_interleave_##func, 16)); \ + return vrgather(vec, vidx, VTraits::vlanes()); \ +} +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_uint8, pairs) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_int8, pairs) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_uint8, quads) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ_NOEXPEND(v_int8, quads) + +#define OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(_Tpvec, width, vzext_vfx, func) \ +inline _Tpvec v_interleave_##func(const _Tpvec& vec) { \ + CV_CheckLE(VTraits<_Tpvec>::vlanes(), VTraits<_Tpvec>::max_nlanes, "RVV implementation only supports VLEN in the range [128, 1024]"); \ + vuint##width##m1_t vidx = vundefined_u##width##m1();\ + vidx = vget_u##width##m1(vzext_vfx(vreinterpret_u8m1(vle64_v_u64m1(idx_interleave_##func, 16)), VTraits::vlanes()), 0); \ + return vrgather(vec, vidx, VTraits<_Tpvec>::vlanes()); \ +} + +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_uint16, 16, vzext_vf2, pairs) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_int16, 16, vzext_vf2, pairs) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_uint32, 32, vzext_vf4, pairs) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_int32, 32, vzext_vf4, pairs) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_float32, 32, vzext_vf4, pairs) + +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_uint16, 16, vzext_vf2, quads) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_int16, 16, vzext_vf2, quads) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_uint32, 32, vzext_vf4, quads) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_int32, 32, vzext_vf4, quads) +OPENCV_HAL_IMPL_RVV_INTERLEAVED_PQ(v_float32, 32, vzext_vf4, quads) + +////////////// Transpose4x4 ////////////// +#define OPENCV_HAL_IMPL_RVV_ZIP4(_Tpvec, _wTpvec, suffix, convert2u, convert) \ +static inline void v_zip4(const _Tpvec& a0, const _Tpvec& a1, _Tpvec& b0, _Tpvec& b1) { \ + int vl = 4; \ + _wTpvec temp = vreinterpret_##suffix##m2(convert2u( \ + vor(vzext_vf2(convert(a0), vl), \ + vreinterpret_u64m2(vslide1up(vreinterpret_u32m2(vzext_vf2(convert(a1), vl)), 0, vl*2)), \ + vl))); \ + b0 = vget_##suffix##m1(temp, 0); \ + b1 = vget_##suffix##m1(vrgather(temp, vadd(vid_v_u32m2(vl), 4, vl)/*{4,5,6,7} */, vl) ,0); \ +} + +OPENCV_HAL_IMPL_RVV_ZIP4(v_uint32, vuint32m2_t, u32, OPENCV_HAL_NOP, OPENCV_HAL_NOP) +OPENCV_HAL_IMPL_RVV_ZIP4(v_int32, vint32m2_t, i32, vreinterpret_u32m2, vreinterpret_u32m1) +OPENCV_HAL_IMPL_RVV_ZIP4(v_float32, vfloat32m2_t, f32, vreinterpret_u32m2, vreinterpret_u32m1) + +#define OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(_Tpvec, suffix) \ +inline void v_transpose4x4(const _Tpvec& a0, const _Tpvec& a1, const _Tpvec& a2, const _Tpvec& a3, _Tpvec& b0, _Tpvec& b1, _Tpvec& b2, _Tpvec& b3) { \ + _Tpvec t0,t1,t2,t3= vundefined_##suffix##m1(); \ + v_zip4(a0, a2, t0, t2); \ + v_zip4(a1, a3, t1, t3); \ + v_zip4(t0, t1, b0, b1); \ + v_zip4(t2, t3, b2, b3); \ +} + +OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(v_uint32, u32) +OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(v_int32, i32) +OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(v_float32, f32) + +//////////// PopCount ////////// +// TODO + +//////////// SignMask //////////// +#define OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(_Tpvec) \ +inline int v_signmask(const _Tpvec& a) \ +{ \ + uint8_t ans[4] = {0}; \ + vsm(ans, vmslt(a, 0, VTraits<_Tpvec>::vlanes()), VTraits<_Tpvec>::vlanes()); \ + return *(reinterpret_cast(ans)); \ +} \ +inline int v_scan_forward(const _Tpvec& a) \ +{ \ + return (int)vfirst(vmslt(a, 0, VTraits<_Tpvec>::vlanes()), VTraits<_Tpvec>::vlanes()); \ +} + +OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int8) +OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int16) +OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int32) +OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int64) + +inline int64 v_signmask(const v_uint8& a) +{ return v_signmask(v_reinterpret_as_s8(a)); } +inline int64 v_signmask(const v_uint16& a) +{ return v_signmask(v_reinterpret_as_s16(a)); } +inline int v_signmask(const v_uint32& a) +{ return v_signmask(v_reinterpret_as_s32(a)); } +inline int v_signmask(const v_float32& a) +{ return v_signmask(v_reinterpret_as_s32(a)); } +inline int v_signmask(const v_uint64& a) +{ return v_signmask(v_reinterpret_as_s64(a)); } +#if CV_SIMD_SCALABLE_64F +inline int v_signmask(const v_float64& a) +{ return v_signmask(v_reinterpret_as_s64(a)); } +#endif + +//////////// Scan forward //////////// +inline int v_scan_forward(const v_uint8& a) +{ return v_scan_forward(v_reinterpret_as_s8(a)); } +inline int v_scan_forward(const v_uint16& a) +{ return v_scan_forward(v_reinterpret_as_s16(a)); } +inline int v_scan_forward(const v_uint32& a) +{ return v_scan_forward(v_reinterpret_as_s32(a)); } +inline int v_scan_forward(const v_float32& a) +{ return v_scan_forward(v_reinterpret_as_s32(a)); } +inline int v_scan_forward(const v_uint64& a) +{ return v_scan_forward(v_reinterpret_as_s64(a)); } +#if CV_SIMD_SCALABLE_64F +inline int v_scan_forward(const v_float64& a) +{ return v_scan_forward(v_reinterpret_as_s64(a)); } +#endif + +//////////// Pack triplets //////////// +// TODO + + ////// FP16 support /////// inline v_float32 v_load_expand(const float16_t* ptr) @@ -484,6 +1275,15 @@ inline v_float32 v_load_expand(const float16_t* ptr) return vundefined_f32m1(); } +////////////// Rounding ////////////// +// TODO + +//////// Dot Product //////// +// TODO + +//////// Fast Dot Product //////// +// TODO + inline void v_cleanup() {} CV_CPU_OPTIMIZATION_HAL_NAMESPACE_END diff --git a/modules/core/test/test_intrin_utils.hpp b/modules/core/test/test_intrin_utils.hpp index 763702bf38..ac05768c35 100644 --- a/modules/core/test/test_intrin_utils.hpp +++ b/modules/core/test/test_intrin_utils.hpp @@ -503,6 +503,34 @@ template struct TheTest return *this; } + TheTest & test_interleave_pq() + { + Data dataA; + R a = dataA; + Data resP = v_interleave_pairs(a); + Data resQ = v_interleave_quads(a); + for (int i = 0; i < VTraits::vlanes()/4; ++i) + { + SCOPED_TRACE(cv::format("i=%d", i)); + EXPECT_EQ(resP[4*i], dataA[4*i ]); + EXPECT_EQ(resP[4*i + 1], dataA[4*i+2]); + EXPECT_EQ(resP[4*i + 2], dataA[4*i+1]); + EXPECT_EQ(resP[4*i + 3], dataA[4*i+3]); + } + for (int i = 0; i < VTraits::vlanes()/8; ++i) + { + SCOPED_TRACE(cv::format("i=%d", i)); + EXPECT_EQ(resQ[8*i], dataA[8*i ]); + EXPECT_EQ(resQ[8*i + 1], dataA[8*i+4]); + EXPECT_EQ(resQ[8*i + 2], dataA[8*i+1]); + EXPECT_EQ(resQ[8*i + 3], dataA[8*i+5]); + EXPECT_EQ(resQ[8*i + 4], dataA[8*i+2]); + EXPECT_EQ(resQ[8*i + 5], dataA[8*i+6]); + EXPECT_EQ(resQ[8*i + 6], dataA[8*i+3]); + EXPECT_EQ(resQ[8*i + 7], dataA[8*i+7]); + } + return *this; + } // float32x4 only TheTest & test_interleave_2channel() @@ -578,16 +606,18 @@ template struct TheTest TheTest & test_addsub() { - Data dataA, dataB; + Data dataA, dataB, dataC; dataB.reverse(); - R a = dataA, b = dataB; + dataA[1] = static_cast(std::numeric_limits::max()); + R a = dataA, b = dataB, c = dataC; - Data resC = v_add(a, b), resD = v_sub(a, b); + Data resD = v_add(a, b), resE = v_add(a, b, c), resF = v_sub(a, b); for (int i = 0; i < VTraits::vlanes(); ++i) { SCOPED_TRACE(cv::format("i=%d", i)); - EXPECT_EQ(saturate_cast(dataA[i] + dataB[i]), resC[i]); - EXPECT_EQ(saturate_cast(dataA[i] - dataB[i]), resD[i]); + EXPECT_EQ(saturate_cast(dataA[i] + dataB[i]), resD[i]); + EXPECT_EQ(saturate_cast(dataA[i] + dataB[i] + dataC[i]), resE[i]); + EXPECT_EQ(saturate_cast(dataA[i] - dataB[i]), resF[i]); } return *this; @@ -614,16 +644,18 @@ template struct TheTest TheTest & test_mul() { - Data dataA, dataB; + Data dataA, dataB, dataC; dataA[1] = static_cast(std::numeric_limits::max()); dataB.reverse(); - R a = dataA, b = dataB; + R a = dataA, b = dataB, c = dataC; - Data resC = v_mul(a, b); + Data resD = v_mul(a, b); + Data resE = v_mul(a, b, c); for (int i = 0; i < VTraits::vlanes(); ++i) { SCOPED_TRACE(cv::format("i=%d", i)); - EXPECT_EQ(saturate_cast(dataA[i] * dataB[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataA[i] * dataB[i]), resD[i]); + EXPECT_EQ(saturate_cast(dataA[i] * dataB[i] * dataC[i]), resE[i]); } return *this; @@ -699,7 +731,7 @@ template struct TheTest for (int i = 0; i < VTraits::vlanes(); ++i) { SCOPED_TRACE(cv::format("i=%d", i)); - R_type ssub = dataA[i] - dataB[i] < std::numeric_limits::min() ? std::numeric_limits::min() : dataA[i] - dataB[i]; + R_type ssub = dataA[i] - dataB[i] < std::numeric_limits::lowest() ? std::numeric_limits::lowest() : dataA[i] - dataB[i]; EXPECT_EQ((u_type)std::abs(ssub), resC[i]); } @@ -1573,19 +1605,27 @@ template struct TheTest v_transpose4x4(a, b, c, d, e, f, g, h); - Data res[4] = {e, f, g, h}; - // for (int i = 0; i < VTraits::vlanes(); i += 4) - // { - int i = 0; - for (int j = 0; j < 4; ++j) - { - SCOPED_TRACE(cv::format("i=%d j=%d", i, j)); - EXPECT_EQ(dataA[i + j], res[j][i]); - EXPECT_EQ(dataB[i + j], res[j][i + 1]); - EXPECT_EQ(dataC[i + j], res[j][i + 2]); - EXPECT_EQ(dataD[i + j], res[j][i + 3]); - } - // } + // Data res[4] = {e, f, g, h}; // Generates incorrect data in certain RVV case. + Data res0 = e, res1 = f, res2 = g, res3 = h; + EXPECT_EQ(dataA[0], res0[0]); + EXPECT_EQ(dataB[0], res0[1]); + EXPECT_EQ(dataC[0], res0[2]); + EXPECT_EQ(dataD[0], res0[3]); + + EXPECT_EQ(dataA[1], res1[0]); + EXPECT_EQ(dataB[1], res1[1]); + EXPECT_EQ(dataC[1], res1[2]); + EXPECT_EQ(dataD[1], res1[3]); + + EXPECT_EQ(dataA[2], res2[0]); + EXPECT_EQ(dataB[2], res2[1]); + EXPECT_EQ(dataC[2], res2[2]); + EXPECT_EQ(dataD[2], res2[3]); + + EXPECT_EQ(dataA[3], res3[0]); + EXPECT_EQ(dataB[3], res3[1]); + EXPECT_EQ(dataC[3], res3[2]); + EXPECT_EQ(dataD[3], res3[3]); return *this; } @@ -1737,7 +1777,34 @@ void test_hal_intrin_uint8() // typedef v_uint8 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_expand() + .test_expand_q() + .test_addsub() + .test_arithm_wrap() + .test_mul() + .test_mul_expand() + .test_logic() .test_min_max() + .test_absdiff() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() + .test_rotate<0>().test_rotate<1>().test_rotate<8>().test_rotate<15>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_unpack() + .test_reverse() +#if 0 // not implemented in rvv backend yet. + .test_interleave() + .test_cmp() + .test_dotprod_expand() + .test_reduce() + .test_reduce_sad() + .test_pack<1>().test_pack<2>().test_pack<3>().test_pack<8>() + .test_pack_u<1>().test_pack_u<2>().test_pack_u<3>().test_pack_u<8>() + .test_pack_b() + .test_popcount() +#endif ; } @@ -1747,7 +1814,34 @@ void test_hal_intrin_int8() // typedef v_int8 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_expand() + .test_expand_q() + .test_addsub() + .test_arithm_wrap() + .test_mul() + .test_mul_expand() + .test_logic() .test_min_max() + .test_absdiff() + .test_absdiffs() + .test_abs() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() + .test_rotate<0>().test_rotate<1>().test_rotate<8>().test_rotate<15>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_unpack() + .test_reverse() +#if 0 + .test_interleave() + .test_cmp() + .test_dotprod_expand() + .test_reduce() + .test_reduce_sad() + .test_pack<1>().test_pack<2>().test_pack<3>().test_pack<8>() + .test_popcount() +#endif ; } @@ -1759,7 +1853,35 @@ void test_hal_intrin_uint16() // typedef v_uint16 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_expand() + .test_addsub() + .test_arithm_wrap() + .test_mul() + .test_mul_expand() + .test_mul_hi() + .test_shift<1>() + .test_shift<8>() + .test_logic() .test_min_max() + .test_absdiff() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() + .test_rotate<0>().test_rotate<1>().test_rotate<4>().test_rotate<7>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_unpack() + .test_reverse() +#if 0 + .test_interleave() + .test_cmp() + .test_dotprod_expand() + .test_reduce() + .test_reduce_sad() + .test_pack<1>().test_pack<2>().test_pack<7>().test_pack<16>() + .test_pack_u<1>().test_pack_u<2>().test_pack_u<7>().test_pack_u<16>() + .test_popcount() +#endif ; } @@ -1769,7 +1891,38 @@ void test_hal_intrin_int16() // typedef v_int16 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_expand() + .test_addsub() + .test_arithm_wrap() + .test_mul() + .test_mul_expand() + .test_mul_hi() + .test_shift<1>() + .test_shift<8>() + .test_logic() .test_min_max() + .test_absdiff() + .test_absdiffs() + .test_abs() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() + .test_rotate<0>().test_rotate<1>().test_rotate<4>().test_rotate<7>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_unpack() + .test_reverse() +#if 0 + .test_interleave() + + .test_cmp() + .test_dotprod() + .test_dotprod_expand() + .test_reduce() + .test_reduce_sad() + .test_pack<1>().test_pack<2>().test_pack<7>().test_pack<16>() + .test_popcount() +#endif ; } @@ -1781,7 +1934,34 @@ void test_hal_intrin_uint32() // typedef v_uint32 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_expand() + .test_addsub() + .test_mul() + .test_mul_expand() + .test_shift<1>() + .test_shift<8>() + .test_logic() .test_min_max() + .test_absdiff() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_rotate<0>().test_rotate<1>().test_rotate<2>().test_rotate<3>() + .test_extract_n<0>().test_extract_n<1>() + .test_broadcast_element<0>().test_broadcast_element<1>() + .test_extract_highest() + .test_broadcast_highest() + .test_unpack() + .test_transpose() + .test_reverse() +#if 0 + .test_interleave() + .test_cmp() + .test_reduce() + .test_reduce_sad() + .test_pack<1>().test_pack<2>().test_pack<15>().test_pack<32>() + .test_popcount() +#endif ; } @@ -1791,7 +1971,37 @@ void test_hal_intrin_int32() // typedef v_int32 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_expand() + .test_addsub() + .test_mul() + .test_abs() + .test_shift<1>().test_shift<8>() + .test_dotprod_expand_f64() + .test_logic() .test_min_max() + .test_absdiff() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_rotate<0>().test_rotate<1>().test_rotate<2>().test_rotate<3>() + .test_extract_n<0>().test_extract_n<1>() + .test_broadcast_element<0>().test_broadcast_element<1>() + .test_extract_highest() + .test_broadcast_highest() + .test_unpack() + .test_transpose() + .test_reverse() +#if 0 + .test_interleave() + .test_cmp() + .test_dotprod() + .test_reduce() + .test_reduce_sad() + .test_pack<1>().test_pack<2>().test_pack<15>().test_pack<32>() + .test_float_cvt32() + .test_float_cvt64() + .test_popcount() +#endif ; } @@ -1803,7 +2013,20 @@ void test_hal_intrin_uint64() // typedef v_uint64 R; TheTest() .test_loadstore() + .test_addsub() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_extract<0>().test_extract<1>() + .test_rotate<0>().test_rotate<1>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_reverse() ; +#if 0 + #if CV_SIMD_64F + .test_cmp64() + #endif +#endif } void test_hal_intrin_int64() @@ -1812,7 +2035,21 @@ void test_hal_intrin_int64() // typedef v_int64 R; TheTest() .test_loadstore() + .test_addsub() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_extract<0>().test_extract<1>() + .test_rotate<0>().test_rotate<1>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_cvt64_double() + .test_reverse() ; +#if 0 + #if CV_SIMD_64F + .test_cmp64() + #endif +#endif } //============= Floating point ===================================================================== @@ -1822,18 +2059,64 @@ void test_hal_intrin_float32() // typedef v_float32 R; TheTest() .test_loadstore() + .test_interleave_pq() + .test_addsub() + .test_abs() + .test_mul() + .test_div() + .test_sqrt_abs() .test_min_max() + .test_float_absdiff() + .test_mask() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_rotate<0>().test_rotate<1>().test_rotate<2>().test_rotate<3>() + .test_extract_n<0>().test_extract_n<1>() + .test_broadcast_element<0>().test_broadcast_element<1>() + .test_extract_highest() + .test_broadcast_highest() + .test_unpack() + .test_transpose() + .test_reverse() +#if 0 + .test_interleave() + .test_interleave_2channel() + .test_cmp() + .test_reduce() + .test_reduce_sad() + .test_float_math() + .test_float_cvt64() + .test_matmul() + .test_reduce_sum4() +#endif ; } void test_hal_intrin_float64() { DUMP_ENTRY(v_float64); -#if CV_SIMD_64F +#if CV_SIMD_SCALABLE_64F // typedef v_float64 R; TheTest() .test_loadstore() + .test_addsub() + .test_mul() + .test_div() + .test_abs() + .test_sqrt_abs() .test_min_max() + .test_float_absdiff() + .test_mask() + .test_extract<0>().test_extract<1>() + .test_rotate<0>().test_rotate<1>() + .test_extract_n<0>().test_extract_n<1>() + .test_extract_highest() + .test_reverse() +#if 0 + .test_cmp() + .test_unpack() + .test_float_cvt32() + .test_float_math() +#endif ; #endif @@ -1851,6 +2134,7 @@ void test_hal_intrin_uint8() TheTest() .test_loadstore() .test_interleave() + .test_interleave_pq() .test_expand() .test_expand_q() .test_addsub() @@ -1874,6 +2158,7 @@ void test_hal_intrin_uint8() .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() .test_rotate<0>().test_rotate<1>().test_rotate<8>().test_rotate<15>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() #if CV_SIMD_WIDTH == 32 .test_pack<9>().test_pack<10>().test_pack<13>().test_pack<15>() @@ -1891,6 +2176,7 @@ void test_hal_intrin_int8() TheTest() .test_loadstore() .test_interleave() + .test_interleave_pq() .test_expand() .test_expand_q() .test_addsub() @@ -1914,6 +2200,7 @@ void test_hal_intrin_int8() .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() .test_rotate<0>().test_rotate<1>().test_rotate<8>().test_rotate<15>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() ; } @@ -1927,6 +2214,7 @@ void test_hal_intrin_uint16() TheTest() .test_loadstore() .test_interleave() + .test_interleave_pq() .test_expand() .test_addsub() .test_arithm_wrap() @@ -1951,6 +2239,7 @@ void test_hal_intrin_uint16() .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() .test_rotate<0>().test_rotate<1>().test_rotate<4>().test_rotate<7>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() ; } @@ -1962,6 +2251,7 @@ void test_hal_intrin_int16() TheTest() .test_loadstore() .test_interleave() + .test_interleave_pq() .test_expand() .test_addsub() .test_arithm_wrap() @@ -1988,6 +2278,7 @@ void test_hal_intrin_int16() .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() .test_rotate<0>().test_rotate<1>().test_rotate<4>().test_rotate<7>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() ; } @@ -2001,6 +2292,7 @@ void test_hal_intrin_uint32() TheTest() .test_loadstore() .test_interleave() + // .test_interleave_pq() //not implemented in AVX .test_expand() .test_addsub() .test_mul() @@ -2022,6 +2314,8 @@ void test_hal_intrin_uint32() .test_rotate<0>().test_rotate<1>().test_rotate<2>().test_rotate<3>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() .test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() + .test_extract_highest() + .test_broadcast_highest() .test_transpose() ; } @@ -2033,6 +2327,7 @@ void test_hal_intrin_int32() TheTest() .test_loadstore() .test_interleave() + // .test_interleave_pq() //not implemented in AVX .test_expand() .test_addsub() .test_mul() @@ -2058,6 +2353,8 @@ void test_hal_intrin_int32() .test_float_cvt32() .test_float_cvt64() .test_transpose() + .test_extract_highest() + .test_broadcast_highest() ; } @@ -2079,6 +2376,7 @@ void test_hal_intrin_uint64() .test_extract<0>().test_extract<1>() .test_rotate<0>().test_rotate<1>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() ; } @@ -2099,6 +2397,7 @@ void test_hal_intrin_int64() .test_extract<0>().test_extract<1>() .test_rotate<0>().test_rotate<1>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() .test_cvt64_double() ; @@ -2113,9 +2412,11 @@ void test_hal_intrin_float32() .test_loadstore() .test_interleave() .test_interleave_2channel() + // .test_interleave_pq() //not implemented in AVX .test_addsub() .test_mul() .test_div() + .test_abs() .test_cmp() .test_sqrt_abs() .test_min_max() @@ -2134,6 +2435,8 @@ void test_hal_intrin_float32() .test_rotate<0>().test_rotate<1>().test_rotate<2>().test_rotate<3>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() .test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() + .test_extract_highest() + .test_broadcast_highest() #if CV_SIMD_WIDTH == 32 .test_extract<4>().test_extract<5>().test_extract<6>().test_extract<7>() .test_rotate<4>().test_rotate<5>().test_rotate<6>().test_rotate<7>() @@ -2151,6 +2454,7 @@ void test_hal_intrin_float64() .test_addsub() .test_mul() .test_div() + .test_abs() .test_cmp() .test_sqrt_abs() .test_min_max() @@ -2163,6 +2467,7 @@ void test_hal_intrin_float64() .test_extract<0>().test_extract<1>() .test_rotate<0>().test_rotate<1>() .test_extract_n<0>().test_extract_n<1>().test_extract_n() + .test_extract_highest() //.test_broadcast_element<0>().test_broadcast_element<1>().test_broadcast_element() #if CV_SIMD_WIDTH == 32 .test_extract<2>().test_extract<3>()