Merge pull request #18228 from joy2myself:rvv

This commit is contained in:
Vadim Pisarevsky
2020-12-02 13:27:35 +00:00
4 changed files with 2765 additions and 1523 deletions
@@ -170,6 +170,7 @@
#if defined CV_CPU_COMPILE_RVV
# define CV_RVV 1
# include <riscv_vector.h>
#endif
#endif // CV_ENABLE_INTRINSICS && !CV_DISABLE_OPTIMIZATION && !__CUDACC__
@@ -202,7 +202,7 @@ using namespace CV_CPU_OPTIMIZATION_HAL_NAMESPACE;
# undef CV_RVV
#endif
#if (CV_SSE2 || CV_NEON || CV_VSX || CV_MSA || CV_WASM_SIMD) && !defined(CV_FORCE_SIMD128_CPP)
#if (CV_SSE2 || CV_NEON || CV_VSX || CV_MSA || CV_WASM_SIMD || CV_RVV) && !defined(CV_FORCE_SIMD128_CPP)
#define CV__SIMD_FORWARD 128
#include "opencv2/core/hal/intrin_forward.hpp"
#endif
+2743 -1522
View File
@@ -5,306 +5,2310 @@
#ifndef OPENCV_HAL_INTRIN_RVV_HPP
#define OPENCV_HAL_INTRIN_RVV_HPP
#include <limits>
#include <cstring>
#include <algorithm>
#include "opencv2/core/saturate.hpp"
#define CV_SIMD128_CPP 1
#if defined(CV_FORCE_SIMD128_CPP) || defined(CV_DOXYGEN)
#define CV_SIMD128 1
#define CV_SIMD128_64F 1
#endif
namespace cv
{
#ifndef CV_DOXYGEN
CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
#endif
#define CV_SIMD128 1
#define CV_SIMD128_64F 1
template<typename _Tp, int n> struct v_reg
//////////// Unsupported native intrinsics in C++ ////////////
struct vuint8mf2_t
{
typedef _Tp lane_type;
enum { nlanes = n };
explicit v_reg(const _Tp* ptr) { for( int i = 0; i < n; i++ ) s[i] = ptr[i]; }
v_reg(_Tp s0, _Tp s1) { s[0] = s0; s[1] = s1; }
v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3) { s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; }
v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3,
_Tp s4, _Tp s5, _Tp s6, _Tp s7)
uchar val[8] = {0};
vuint8mf2_t() {}
vuint8mf2_t(const uchar* ptr)
{
s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3;
s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7;
}
v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3,
_Tp s4, _Tp s5, _Tp s6, _Tp s7,
_Tp s8, _Tp s9, _Tp s10, _Tp s11,
_Tp s12, _Tp s13, _Tp s14, _Tp s15)
{
s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3;
s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7;
s[8] = s8; s[9] = s9; s[10] = s10; s[11] = s11;
s[12] = s12; s[13] = s13; s[14] = s14; s[15] = s15;
}
v_reg() {}
v_reg(const v_reg<_Tp, n> & r)
{
for( int i = 0; i < n; i++ )
s[i] = r.s[i];
}
_Tp get0() const { return s[0]; }
_Tp get(const int i) const { return s[i]; }
v_reg<_Tp, n> high() const
{
v_reg<_Tp, n> c;
int i;
for( i = 0; i < n/2; i++ )
for (int i = 0; i < 8; ++i)
{
c.s[i] = s[i+(n/2)];
c.s[i+(n/2)] = 0;
val[i] = ptr[i];
}
return c;
}
static v_reg<_Tp, n> zero()
};
struct vint8mf2_t
{
schar val[8] = {0};
vint8mf2_t() {}
vint8mf2_t(const schar* ptr)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (_Tp)0;
return c;
for (int i = 0; i < 8; ++i)
{
val[i] = ptr[i];
}
}
static v_reg<_Tp, n> all(_Tp s)
};
struct vuint16mf2_t
{
ushort val[4] = {0};
vuint16mf2_t() {}
vuint16mf2_t(const ushort* ptr)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = s;
return c;
for (int i = 0; i < 4; ++i)
{
val[i] = ptr[i];
}
}
template<typename _Tp2, int n2> v_reg<_Tp2, n2> reinterpret_as() const
};
struct vint16mf2_t
{
short val[4] = {0};
vint16mf2_t() {}
vint16mf2_t(const short* ptr)
{
size_t bytes = std::min(sizeof(_Tp2)*n2, sizeof(_Tp)*n);
v_reg<_Tp2, n2> c;
std::memcpy(&c.s[0], &s[0], bytes);
return c;
for (int i = 0; i < 4; ++i)
{
val[i] = ptr[i];
}
}
v_reg& operator=(const v_reg<_Tp, n> & r)
};
struct vuint32mf2_t
{
unsigned val[2] = {0};
vuint32mf2_t() {}
vuint32mf2_t(const unsigned* ptr)
{
for( int i = 0; i < n; i++ )
s[i] = r.s[i];
return *this;
val[0] = ptr[0];
val[1] = ptr[1];
}
};
struct vint32mf2_t
{
int val[2] = {0};
vint32mf2_t() {}
vint32mf2_t(const int* ptr)
{
val[0] = ptr[0];
val[1] = ptr[1];
}
};
struct vfloat32mf2_t
{
float val[2] = {0};
vfloat32mf2_t() {}
vfloat32mf2_t(const float* ptr)
{
val[0] = ptr[0];
val[1] = ptr[1];
}
};
struct vuint64mf2_t
{
uint64 val[1] = {0};
vuint64mf2_t() {}
vuint64mf2_t(const uint64* ptr)
{
val[0] = ptr[0];
}
};
struct vint64mf2_t
{
int64 val[1] = {0};
vint64mf2_t() {}
vint64mf2_t(const int64* ptr)
{
val[0] = ptr[0];
}
};
struct vfloat64mf2_t
{
double val[1] = {0};
vfloat64mf2_t() {}
vfloat64mf2_t(const double* ptr)
{
val[0] = ptr[0];
}
};
struct vuint8mf4_t
{
uchar val[4] = {0};
vuint8mf4_t() {}
vuint8mf4_t(const uchar* ptr)
{
for (int i = 0; i < 4; ++i)
{
val[i] = ptr[i];
}
}
};
struct vint8mf4_t
{
schar val[4] = {0};
vint8mf4_t() {}
vint8mf4_t(const schar* ptr)
{
for (int i = 0; i < 4; ++i)
{
val[i] = ptr[i];
}
}
_Tp s[n];
};
typedef v_reg<uchar, 16> v_uint8x16;
typedef v_reg<schar, 16> v_int8x16;
typedef v_reg<ushort, 8> v_uint16x8;
typedef v_reg<short, 8> v_int16x8;
typedef v_reg<unsigned, 4> v_uint32x4;
typedef v_reg<int, 4> v_int32x4;
typedef v_reg<float, 4> v_float32x4;
typedef v_reg<double, 2> v_float64x2;
typedef v_reg<uint64, 2> v_uint64x2;
typedef v_reg<int64, 2> v_int64x2;
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator+(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator+=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator-(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator-=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator*(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator*=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator/(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator/=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator&(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator&=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator|(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator|=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator^(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n>& operator^=(v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b);
template<typename _Tp, int n> CV_INLINE v_reg<_Tp, n> operator~(const v_reg<_Tp, n>& a);
#ifndef CV_DOXYGEN
#define CV__HAL_INTRIN_EXPAND_WITH_INTEGER_TYPES(macro_name, ...) \
__CV_EXPAND(macro_name(uchar, __VA_ARGS__)) \
__CV_EXPAND(macro_name(schar, __VA_ARGS__)) \
__CV_EXPAND(macro_name(ushort, __VA_ARGS__)) \
__CV_EXPAND(macro_name(short, __VA_ARGS__)) \
__CV_EXPAND(macro_name(unsigned, __VA_ARGS__)) \
__CV_EXPAND(macro_name(int, __VA_ARGS__)) \
__CV_EXPAND(macro_name(uint64, __VA_ARGS__)) \
__CV_EXPAND(macro_name(int64, __VA_ARGS__)) \
#define CV__HAL_INTRIN_EXPAND_WITH_FP_TYPES(macro_name, ...) \
__CV_EXPAND(macro_name(float, __VA_ARGS__)) \
__CV_EXPAND(macro_name(double, __VA_ARGS__)) \
#define CV__HAL_INTRIN_EXPAND_WITH_ALL_TYPES(macro_name, ...) \
CV__HAL_INTRIN_EXPAND_WITH_INTEGER_TYPES(macro_name, __VA_ARGS__) \
CV__HAL_INTRIN_EXPAND_WITH_FP_TYPES(macro_name, __VA_ARGS__) \
#define CV__HAL_INTRIN_IMPL_BIN_OP_(_Tp, bin_op) \
template<int n> inline \
v_reg<_Tp, n> operator bin_op (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
#define OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(_Tpvec, _Tp, suffix, width, n) \
inline _Tpvec vle##width##_v_##suffix##mf2(const _Tp* ptr) \
{ \
v_reg<_Tp, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = saturate_cast<_Tp>(a.s[i] bin_op b.s[i]); \
return c; \
return _Tpvec(ptr); \
} \
template<int n> inline \
v_reg<_Tp, n>& operator bin_op##= (v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
inline void vse##width##_v_##suffix##mf2(_Tp* ptr, _Tpvec v) \
{ \
for( int i = 0; i < n; i++ ) \
a.s[i] = saturate_cast<_Tp>(a.s[i] bin_op b.s[i]); \
return a; \
for (int i = 0; i < n; ++i) \
{ \
ptr[i] = v.val[i]; \
} \
}
#define CV__HAL_INTRIN_IMPL_BIN_OP(bin_op) CV__HAL_INTRIN_EXPAND_WITH_ALL_TYPES(CV__HAL_INTRIN_IMPL_BIN_OP_, bin_op)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vuint8mf2_t, uint8_t, u8, 8, 8)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vint8mf2_t, int8_t, i8, 8, 8)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vuint16mf2_t, uint16_t, u16, 16, 4)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vint16mf2_t, int16_t, i16, 16, 4)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vuint32mf2_t, uint32_t, u32, 32, 2)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vint32mf2_t, int32_t, i32, 32, 2)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vfloat32mf2_t, float32_t, f32, 32, 2)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vuint64mf2_t, uint64_t, u64, 64, 1)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vint64mf2_t, int64_t, i64, 64, 1)
OPENCV_HAL_IMPL_RVV_NATIVE_LOADSTORE_MF2(vfloat64mf2_t, float64_t, f64, 64, 1)
CV__HAL_INTRIN_IMPL_BIN_OP(+)
CV__HAL_INTRIN_IMPL_BIN_OP(-)
CV__HAL_INTRIN_IMPL_BIN_OP(*)
CV__HAL_INTRIN_EXPAND_WITH_FP_TYPES(CV__HAL_INTRIN_IMPL_BIN_OP_, /)
#define CV__HAL_INTRIN_IMPL_BIT_OP_(_Tp, bit_op) \
template<int n> CV_INLINE \
v_reg<_Tp, n> operator bit_op (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
#define OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(_Tpwvec, _Tpvec, _wTp, wcvt, suffix, width, n) \
inline _Tpwvec wcvt (_Tpvec v) \
{ \
v_reg<_Tp, n> c; \
typedef typename V_TypeTraits<_Tp>::int_type itype; \
for( int i = 0; i < n; i++ ) \
c.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int((itype)(V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) bit_op \
V_TypeTraits<_Tp>::reinterpret_int(b.s[i]))); \
return c; \
} \
template<int n> CV_INLINE \
v_reg<_Tp, n>& operator bit_op##= (v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
{ \
typedef typename V_TypeTraits<_Tp>::int_type itype; \
for( int i = 0; i < n; i++ ) \
a.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int((itype)(V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) bit_op \
V_TypeTraits<_Tp>::reinterpret_int(b.s[i]))); \
return a; \
_wTp tmp[n]; \
for (int i = 0; i < n; ++i) \
{ \
tmp[i] = (_wTp)v.val[i]; \
} \
vsetvlmax_e##width##m1(); \
return vle##width##_v_##suffix##m1(tmp); \
}
#define CV__HAL_INTRIN_IMPL_BIT_OP(bit_op) \
CV__HAL_INTRIN_EXPAND_WITH_INTEGER_TYPES(CV__HAL_INTRIN_IMPL_BIT_OP_, bit_op) \
CV__HAL_INTRIN_EXPAND_WITH_FP_TYPES(CV__HAL_INTRIN_IMPL_BIT_OP_, bit_op) /* TODO: FIXIT remove this after masks refactoring */
OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(vuint16m1_t, vuint8mf2_t, ushort, vwcvtu_x_x_v_u16m1, u16, 16, 8)
OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(vint16m1_t, vint8mf2_t, short, vwcvt_x_x_v_i16m1, i16, 16, 8)
OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(vuint32m1_t, vuint16mf2_t, unsigned, vwcvtu_x_x_v_u32m1, u32, 32, 4)
OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(vint32m1_t, vint16mf2_t, int, vwcvt_x_x_v_i32m1, i32, 32, 4)
OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(vuint64m1_t, vuint32mf2_t, uint64, vwcvtu_x_x_v_u64m1, u64, 64, 2)
OPENCV_HAL_IMPL_RVV_NATIVE_WCVT(vint64m1_t, vint32mf2_t, int64, vwcvt_x_x_v_i64m1, i64, 64, 2)
inline vuint8mf4_t vle8_v_u8mf4 (const uint8_t *base)
{
return vuint8mf4_t(base);
}
inline vint8mf4_t vle8_v_i8mf4 (const int8_t *base)
{
return vint8mf4_t(base);
}
CV__HAL_INTRIN_IMPL_BIT_OP(&)
CV__HAL_INTRIN_IMPL_BIT_OP(|)
CV__HAL_INTRIN_IMPL_BIT_OP(^)
inline vuint16mf2_t vwcvtu_x_x_v_u16mf2 (vuint8mf4_t src)
{
ushort tmp[4];
for (int i = 0; i < 4; ++i)
{
tmp[i] = (ushort)src.val[i];
}
return vle16_v_u16mf2(tmp);
}
inline vint16mf2_t vwcvt_x_x_v_i16mf2 (vint8mf4_t src)
{
short tmp[4];
for (int i = 0; i < 4; ++i)
{
tmp[i] = (short)src.val[i];
}
return vle16_v_i16mf2(tmp);
}
#define CV__HAL_INTRIN_IMPL_BITWISE_NOT_(_Tp, dummy) \
template<int n> CV_INLINE \
v_reg<_Tp, n> operator ~ (const v_reg<_Tp, n>& a) \
{ \
v_reg<_Tp, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int(~V_TypeTraits<_Tp>::reinterpret_int(a.s[i])); \
return c; \
} \
//////////// Types ////////////
CV__HAL_INTRIN_EXPAND_WITH_INTEGER_TYPES(CV__HAL_INTRIN_IMPL_BITWISE_NOT_, ~)
struct v_uint8x16
{
typedef uchar lane_type;
enum { nlanes = 16 };
v_uint8x16() {}
explicit v_uint8x16(vuint8m1_t v)
{
vsetvlmax_e8m1();
vse8_v_u8m1(val, v);
}
v_uint8x16(uchar v0, uchar v1, uchar v2, uchar v3, uchar v4, uchar v5, uchar v6, uchar v7,
uchar v8, uchar v9, uchar v10, uchar v11, uchar v12, uchar v13, uchar v14, uchar v15)
{
uchar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vuint8m1_t() const
{
vsetvlmax_e8m1();
return vle8_v_u8m1(val);
}
uchar get0() const
{
return val[0];
}
uchar val[16];
};
struct v_int8x16
{
typedef schar lane_type;
enum { nlanes = 16 };
v_int8x16() {}
explicit v_int8x16(vint8m1_t v)
{
vsetvlmax_e8m1();
vse8_v_i8m1(val, v);
}
v_int8x16(schar v0, schar v1, schar v2, schar v3, schar v4, schar v5, schar v6, schar v7,
schar v8, schar v9, schar v10, schar v11, schar v12, schar v13, schar v14, schar v15)
{
schar v[] = {v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vint8m1_t() const
{
vsetvlmax_e8m1();
return vle8_v_i8m1(val);
}
schar get0() const
{
return val[0];
}
schar val[16];
};
struct v_uint16x8
{
typedef ushort lane_type;
enum { nlanes = 8 };
v_uint16x8() {}
explicit v_uint16x8(vuint16m1_t v)
{
vsetvlmax_e16m1();
vse16_v_u16m1(val, v);
}
v_uint16x8(ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5, ushort v6, ushort v7)
{
ushort v[] = {v0, v1, v2, v3, v4, v5, v6, v7};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vuint16m1_t() const
{
vsetvlmax_e16m1();
return vle16_v_u16m1(val);
}
ushort get0() const
{
return val[0];
}
ushort val[8];
};
struct v_int16x8
{
typedef short lane_type;
enum { nlanes = 8 };
v_int16x8() {}
explicit v_int16x8(vint16m1_t v)
{
vsetvlmax_e16m1();
vse16_v_i16m1(val, v);
}
v_int16x8(short v0, short v1, short v2, short v3, short v4, short v5, short v6, short v7)
{
short v[] = {v0, v1, v2, v3, v4, v5, v6, v7};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vint16m1_t() const
{
vsetvlmax_e16m1();
return vle16_v_i16m1(val);
}
short get0() const
{
return val[0];
}
short val[8];
};
struct v_uint32x4
{
typedef unsigned lane_type;
enum { nlanes = 4 };
v_uint32x4() {}
explicit v_uint32x4(vuint32m1_t v)
{
vsetvlmax_e32m1();
vse32_v_u32m1(val, v);
}
v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
{
unsigned v[] = {v0, v1, v2, v3};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vuint32m1_t() const
{
vsetvlmax_e32m1();
return vle32_v_u32m1(val);
}
unsigned get0() const
{
return val[0];
}
unsigned val[4];
};
struct v_int32x4
{
typedef int lane_type;
enum { nlanes = 4 };
v_int32x4() {}
explicit v_int32x4(vint32m1_t v)
{
vsetvlmax_e32m1();
vse32_v_i32m1(val, v);
}
v_int32x4(int v0, int v1, int v2, int v3)
{
int v[] = {v0, v1, v2, v3};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vint32m1_t() const
{
vsetvlmax_e32m1();
return vle32_v_i32m1(val);
}
int get0() const
{
return val[0];
}
int val[4];
};
struct v_float32x4
{
typedef float lane_type;
enum { nlanes = 4 };
v_float32x4() {}
explicit v_float32x4(vfloat32m1_t v)
{
vsetvlmax_e32m1();
vse32_v_f32m1(val, v);
}
v_float32x4(float v0, float v1, float v2, float v3)
{
float v[] = {v0, v1, v2, v3};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vfloat32m1_t() const
{
vsetvlmax_e32m1();
return vle32_v_f32m1(val);
}
float get0() const
{
return val[0];
}
float val[4];
};
struct v_uint64x2
{
typedef uint64 lane_type;
enum { nlanes = 2 };
v_uint64x2() {}
explicit v_uint64x2(vuint64m1_t v)
{
vsetvlmax_e64m1();
vse64_v_u64m1(val, v);
}
v_uint64x2(uint64 v0, uint64 v1)
{
uint64 v[] = {v0, v1};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vuint64m1_t() const
{
vsetvlmax_e64m1();
return vle64_v_u64m1(val);
}
uint64 get0() const
{
return val[0];
}
uint64 val[2];
};
struct v_int64x2
{
typedef int64 lane_type;
enum { nlanes = 2 };
v_int64x2() {}
explicit v_int64x2(vint64m1_t v)
{
vsetvlmax_e64m1();
vse64_v_i64m1(val, v);
}
v_int64x2(int64 v0, int64 v1)
{
int64 v[] = {v0, v1};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vint64m1_t() const
{
vsetvlmax_e64m1();
return vle64_v_i64m1(val);
}
int64 get0() const
{
return val[0];
}
int64 val[2];
};
#if CV_SIMD128_64F
struct v_float64x2
{
typedef double lane_type;
enum { nlanes = 2 };
v_float64x2() {}
explicit v_float64x2(vfloat64m1_t v)
{
vsetvlmax_e64m1();
vse64_v_f64m1(val, v);
}
v_float64x2(double v0, double v1)
{
double v[] = {v0, v1};
for (int i = 0; i < nlanes; ++i)
{
val[i] = v[i];
}
}
operator vfloat64m1_t() const
{
vsetvlmax_e64m1();
return vle64_v_f64m1(val);
}
double get0() const
{
return val[0];
}
double val[2];
};
#endif
#define OPENCV_HAL_IMPL_MATH_FUNC(func, cfunc, _Tp2) \
template<typename _Tp, int n> inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a) \
{ \
v_reg<_Tp2, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = cfunc(a.s[i]); \
return c; \
}
//////////// Initial ////////////
#define OPENCV_HAL_IMPL_MATH_FUNC_FLOAT(func, cfunc) \
inline v_reg<int, 4> func(const v_reg<float, 4>& a) \
#define OPENCV_HAL_IMPL_RVV_INIT_INTEGER(_Tpvec, _Tp, width, suffix1, suffix2) \
inline v_##_Tpvec v_setzero_##suffix1() \
{ \
v_reg<int, 4> c; \
for( int i = 0; i < 4; i++ ) \
c.s[i] = cfunc(a.s[i]); \
return c; \
vsetvlmax_e##width##m1(); \
return v_##_Tpvec(vzero_##suffix2##m1()); \
} \
inline v_reg<int, 4> func(const v_reg<double, 2>& a) \
inline v_##_Tpvec v_setall_##suffix1(_Tp v) \
{ \
v_reg<int, 4> c; \
for( int i = 0; i < 2; i++ ) \
vsetvlmax_e##width##m1(); \
return v_##_Tpvec(vmv_v_x_##suffix2##m1(v)); \
}
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(uint8x16, uchar, 8, u8, u8)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(int8x16, schar, 8, s8, i8)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(uint16x8, ushort, 16, u16, u16)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(int16x8, short, 16, s16, i16)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(uint32x4, unsigned, 32, u32, u32)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(int32x4, int, 32, s32, i32)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(uint64x2, uint64, 64, u64, u64)
OPENCV_HAL_IMPL_RVV_INIT_INTEGER(int64x2, int64, 64, s64, i64)
#define OPENCV_HAL_IMPL_RVV_INIT_FP(_Tpv, _Tp, width, suffix) \
inline v_##_Tpv v_setzero_##suffix() \
{ \
vsetvlmax_e##width##m1(); \
return v_##_Tpv(vzero_##suffix##m1()); \
} \
inline v_##_Tpv v_setall_##suffix(_Tp v) \
{ \
vsetvlmax_e##width##m1(); \
return v_##_Tpv(vfmv_v_f_##suffix##m1(v)); \
}
OPENCV_HAL_IMPL_RVV_INIT_FP(float32x4, float, 32, f32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_INIT_FP(float64x2, double, 64, f64)
#endif
//////////// Reinterpret ////////////
#define OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(_Tpvec, suffix) \
inline v_##_Tpvec v_reinterpret_as_##suffix(const v_##_Tpvec& v) { return v; }
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(uint8x16, u8)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(int8x16, s8)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(uint16x8, u16)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(int16x8, s16)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(uint32x4, u32)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(int32x4, s32)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(float32x4, f32)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(uint64x2, u64)
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(int64x2, s64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_SELF_REINTERPRET(float64x2, f64)
#endif
#define OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(_Tpvec1, _Tpvec2, _nTpvec1, _nTpvec2, suffix1, suffix2, nsuffix1, nsuffix2, width1, width2) \
inline v_##_Tpvec1 v_reinterpret_as_##suffix1(const v_##_Tpvec2& v) \
{ \
vsetvlmax_e##width2##m1(); \
return v_##_Tpvec1((_nTpvec1)vle##width2##_v_##nsuffix2##m1(v.val)); \
} \
inline v_##_Tpvec2 v_reinterpret_as_##suffix2(const v_##_Tpvec1& v) \
{ \
vsetvlmax_e##width1##m1(); \
return v_##_Tpvec2((_nTpvec2)vle##width1##_v_##nsuffix1##m1(v.val)); \
}
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, int8x16, vuint8m1_t, vint8m1_t, u8, s8, u8, i8, 8, 8)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, int16x8, vuint16m1_t, vint16m1_t, u16, s16, u16, i16, 16, 16)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, int32x4, vuint32m1_t, vint32m1_t, u32, s32, u32, i32, 32, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, float32x4, vuint32m1_t, vfloat32m1_t, u32, f32, u32, f32, 32, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int32x4, float32x4, vint32m1_t, vfloat32m1_t, s32, f32, i32, f32, 32, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint64x2, int64x2, vuint64m1_t, vint64m1_t, u64, s64, u64, i64, 64, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, uint16x8, vuint8m1_t, vuint16m1_t, u8, u16, u8, u16, 8, 16)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, uint32x4, vuint8m1_t, vuint32m1_t, u8, u32, u8, u32, 8, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, uint64x2, vuint8m1_t, vuint64m1_t, u8, u64, u8, u64, 8, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, uint32x4, vuint16m1_t, vuint32m1_t, u16, u32, u16, u32, 16, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, uint64x2, vuint16m1_t, vuint64m1_t, u16, u64, u16, u64, 16, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, uint64x2, vuint32m1_t, vuint64m1_t, u32, u64, u32, u64, 32, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int8x16, int16x8, vint8m1_t, vint16m1_t, s8, s16, i8, i16, 8, 16)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int8x16, int32x4, vint8m1_t, vint32m1_t, s8, s32, i8, i32, 8, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int8x16, int64x2, vint8m1_t, vint64m1_t, s8, s64, i8, i64, 8, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int16x8, int32x4, vint16m1_t, vint32m1_t, s16, s32, i16, i32, 16, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int16x8, int64x2, vint16m1_t, vint64m1_t, s16, s64, i16, i64, 16, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int32x4, int64x2, vint32m1_t, vint64m1_t, s32, s64, i32, i64, 32, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, int16x8, vuint8m1_t, vint16m1_t, u8, s16, u8, i16, 8, 16)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, int32x4, vuint8m1_t, vint32m1_t, u8, s32, u8, i32, 8, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, int64x2, vuint8m1_t, vint64m1_t, u8, s64, u8, i64, 8, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, int8x16, vuint16m1_t, vint8m1_t, u16, s8, u16, i8, 16, 8)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, int32x4, vuint16m1_t, vint32m1_t, u16, s32, u16, i32, 16, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, int64x2, vuint16m1_t, vint64m1_t, u16, s64, u16, i64, 16, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, int8x16, vuint32m1_t, vint8m1_t, u32, s8, u32, i8, 32, 8)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, int16x8, vuint32m1_t, vint16m1_t, u32, s16, u32, i16, 32, 16)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, int64x2, vuint32m1_t, vint64m1_t, u32, s64, u32, i64, 32, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint64x2, int8x16, vuint64m1_t, vint8m1_t, u64, s8, u64, i8, 64, 8)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint64x2, int16x8, vuint64m1_t, vint16m1_t, u64, s16, u64, i16, 64, 16)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint64x2, int32x4, vuint64m1_t, vint32m1_t, u64, s32, u64, i32, 64, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, float32x4, vuint8m1_t, vfloat32m1_t, u8, f32, u8, f32, 8, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, float32x4, vuint16m1_t, vfloat32m1_t, u16, f32, u16, f32, 16, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint64x2, float32x4, vuint64m1_t, vfloat32m1_t, u64, f32, u64, f32, 64, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int8x16, float32x4, vint8m1_t, vfloat32m1_t, s8, f32, i8, f32, 8, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int16x8, float32x4, vint16m1_t, vfloat32m1_t, s16, f32, i16, f32, 16, 32)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int64x2, float32x4, vint64m1_t, vfloat32m1_t, s64, f32, i64, f32, 64, 32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint64x2, float64x2, vuint64m1_t, vfloat64m1_t, u64, f64, u64, f64, 64, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int64x2, float64x2, vint64m1_t, vfloat64m1_t, s64, f64, i64, f64, 64, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint8x16, float64x2, vuint8m1_t, vfloat64m1_t, u8, f64, u8, f64, 8, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint16x8, float64x2, vuint16m1_t, vfloat64m1_t, u16, f64, u16, f64, 16, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(uint32x4, float64x2, vuint32m1_t, vfloat64m1_t, u32, f64, u32, f64, 32, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int8x16, float64x2, vint8m1_t, vfloat64m1_t, s8, f64, i8, f64, 8, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int16x8, float64x2, vint16m1_t, vfloat64m1_t, s16, f64, i16, f64, 16, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(int32x4, float64x2, vint32m1_t, vfloat64m1_t, s32, f64, i32, f64, 32, 64)
OPENCV_HAL_IMPL_RVV_ONE_TIME_REINTERPRET(float32x4, float64x2, vfloat32m1_t, vfloat64m1_t, f32, f64, f32, f64, 32, 64)
#endif
////////////// Extract //////////////
#define OPENCV_HAL_IMPL_RVV_EXTRACT(_Tpvec, _Tp, suffix, width, vmv) \
template <int s> \
inline _Tpvec v_extract(const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vslideup_vx_##suffix##m1(vslidedown_vx_##suffix##m1(vzero_##suffix##m1(), a, s), b, _Tpvec::nlanes - s)); \
} \
template<int i> inline _Tp v_extract_n(_Tpvec v) \
{ \
vsetvlmax_e##width##m1(); \
return _Tp(vmv(vslidedown_vx_##suffix##m1(vzero_##suffix##m1(), v, i))); \
}
OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint8x16, uchar, u8, 8, vmv_x_s_u8m1_u8)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_int8x16, schar, i8, 8, vmv_x_s_i8m1_i8)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint16x8, ushort, u16, 16, vmv_x_s_u16m1_u16)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_int16x8, short, i16, 16, vmv_x_s_i16m1_i16)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint32x4, uint, u32, 32, vmv_x_s_u32m1_u32)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_int32x4, int, i32, 32, vmv_x_s_i32m1_i32)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_uint64x2, uint64, u64, 64, vmv_x_s_u64m1_u64)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_int64x2, int64, i64, 64, vmv_x_s_i64m1_i64)
OPENCV_HAL_IMPL_RVV_EXTRACT(v_float32x4, float, f32, 32, vfmv_f_s_f32m1_f32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_EXTRACT(v_float64x2, double, f64, 64, vfmv_f_s_f64m1_f64)
#endif
////////////// Load/Store //////////////
#define OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(_Tpvec, _nTpvec, _Tp, hvl, width, suffix) \
inline _Tpvec v_load(const _Tp* ptr) \
{ \
vsetvlmax_e8m1(); \
return _Tpvec((_nTpvec)vle8_v_u8m1((uchar*)ptr)); \
} \
inline _Tpvec v_load_aligned(const _Tp* ptr) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vle##width##_v_##suffix##m1(ptr)); \
} \
inline _Tpvec v_load_low(const _Tp* ptr) \
{ \
vsetvl_e##width##m1(hvl); \
_Tpvec res = _Tpvec(vle##width##_v_##suffix##m1(ptr)); \
vsetvlmax_e##width##m1(); \
return res; \
} \
inline void v_store(_Tp* ptr, const _Tpvec& a) \
{ \
vsetvlmax_e8m1(); \
vse8_v_u8m1((uchar*)ptr, vle8_v_u8m1((uchar*)a.val)); \
} \
inline void v_store_aligned(_Tp* ptr, const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
vse##width##_v_##suffix##m1(ptr, a); \
} \
inline void v_store_aligned_nocache(_Tp* ptr, const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
vse##width##_v_##suffix##m1(ptr, a); \
} \
inline void v_store(_Tp* ptr, const _Tpvec& a, hal::StoreMode /*mode*/) \
{ \
vsetvlmax_e##width##m1(); \
vse##width##_v_##suffix##m1(ptr, a); \
} \
inline void v_store_low(_Tp* ptr, const _Tpvec& a) \
{ \
_Tp CV_DECL_ALIGNED(32) tmp_ptr[_Tpvec::nlanes] = {0}; \
vsetvlmax_e##width##m1(); \
vse##width##_v_##suffix##m1(tmp_ptr, a); \
for(int i = 0; i < _Tpvec::nlanes/2; ++i) \
{ \
c.s[i] = cfunc(a.s[i]); \
c.s[i + 2] = 0; \
ptr[i] = tmp_ptr[i]; \
} \
return c; \
}
OPENCV_HAL_IMPL_MATH_FUNC(v_sqrt, std::sqrt, _Tp)
OPENCV_HAL_IMPL_MATH_FUNC(v_sin, std::sin, _Tp)
OPENCV_HAL_IMPL_MATH_FUNC(v_cos, std::cos, _Tp)
OPENCV_HAL_IMPL_MATH_FUNC(v_exp, std::exp, _Tp)
OPENCV_HAL_IMPL_MATH_FUNC(v_log, std::log, _Tp)
OPENCV_HAL_IMPL_MATH_FUNC(v_abs, (typename V_TypeTraits<_Tp>::abs_type)std::abs,
typename V_TypeTraits<_Tp>::abs_type)
OPENCV_HAL_IMPL_MATH_FUNC_FLOAT(v_round, cvRound)
OPENCV_HAL_IMPL_MATH_FUNC_FLOAT(v_floor, cvFloor)
OPENCV_HAL_IMPL_MATH_FUNC_FLOAT(v_ceil, cvCeil)
OPENCV_HAL_IMPL_MATH_FUNC_FLOAT(v_trunc, int)
#define OPENCV_HAL_IMPL_MINMAX_FUNC(func, cfunc) \
template<typename _Tp, int n> inline v_reg<_Tp, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
} \
inline void v_store_high(_Tp* ptr, const _Tpvec& a) \
{ \
v_reg<_Tp, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = cfunc(a.s[i], b.s[i]); \
return c; \
_Tp CV_DECL_ALIGNED(32) tmp_ptr[_Tpvec::nlanes] = {0}; \
vsetvlmax_e##width##m1(); \
vse##width##_v_##suffix##m1(tmp_ptr, a); \
for(int i = 0; i < _Tpvec::nlanes/2; ++i) \
{ \
ptr[i] = tmp_ptr[i+_Tpvec::nlanes/2]; \
} \
}
#define OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(func, cfunc) \
template<typename _Tp, int n> inline _Tp func(const v_reg<_Tp, n>& a) \
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_uint8x16, vuint8m1_t, uchar, 8, 8, u8)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_int8x16, vint8m1_t, schar, 8, 8, i8)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_uint16x8, vuint16m1_t, ushort, 4, 16, u16)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_int16x8, vint16m1_t, short, 4, 16, i16)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_uint32x4, vuint32m1_t, unsigned, 2, 32, u32)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_int32x4, vint32m1_t, int, 2, 32, i32)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_uint64x2, vuint64m1_t, uint64, 1, 64, u64)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_int64x2, vint64m1_t, int64, 1, 64, i64)
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_float32x4, vfloat32m1_t, float, 2, 32, f32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_LOADSTORE_OP(v_float64x2, vfloat64m1_t, double, 1, 64, f64)
#endif
inline v_int8x16 v_load_halves(const schar* ptr0, const schar* ptr1)
{
schar CV_DECL_ALIGNED(32) elems[16] =
{
ptr0[0], ptr0[1], ptr0[2], ptr0[3], ptr0[4], ptr0[5], ptr0[6], ptr0[7],
ptr1[0], ptr1[1], ptr1[2], ptr1[3], ptr1[4], ptr1[5], ptr1[6], ptr1[7]
};
vsetvlmax_e8m1();
return v_int8x16(vle8_v_i8m1(elems));
}
inline v_uint8x16 v_load_halves(const uchar* ptr0, const uchar* ptr1) { return v_reinterpret_as_u8(v_load_halves((schar*)ptr0, (schar*)ptr1)); }
inline v_int16x8 v_load_halves(const short* ptr0, const short* ptr1)
{
short CV_DECL_ALIGNED(32) elems[8] =
{
ptr0[0], ptr0[1], ptr0[2], ptr0[3], ptr1[0], ptr1[1], ptr1[2], ptr1[3]
};
vsetvlmax_e16m1();
return v_int16x8(vle16_v_i16m1(elems));
}
inline v_uint16x8 v_load_halves(const ushort* ptr0, const ushort* ptr1) { return v_reinterpret_as_u16(v_load_halves((short*)ptr0, (short*)ptr1)); }
inline v_int32x4 v_load_halves(const int* ptr0, const int* ptr1)
{
int CV_DECL_ALIGNED(32) elems[4] =
{
ptr0[0], ptr0[1], ptr1[0], ptr1[1]
};
vsetvlmax_e32m1();
return v_int32x4(vle32_v_i32m1(elems));
}
inline v_float32x4 v_load_halves(const float* ptr0, const float* ptr1)
{
float CV_DECL_ALIGNED(32) elems[4] =
{
ptr0[0], ptr0[1], ptr1[0], ptr1[1]
};
vsetvlmax_e32m1();
return v_float32x4(vle32_v_f32m1(elems));
}
inline v_uint32x4 v_load_halves(const unsigned* ptr0, const unsigned* ptr1) { return v_reinterpret_as_u32(v_load_halves((int*)ptr0, (int*)ptr1)); }
inline v_int64x2 v_load_halves(const int64* ptr0, const int64* ptr1)
{
int64 CV_DECL_ALIGNED(32) elems[2] =
{
ptr0[0], ptr1[0]
};
vsetvlmax_e64m1();
return v_int64x2(vle64_v_i64m1(elems));
}
inline v_uint64x2 v_load_halves(const uint64* ptr0, const uint64* ptr1) { return v_reinterpret_as_u64(v_load_halves((int64*)ptr0, (int64*)ptr1)); }
#if CV_SIMD128_64F
inline v_float64x2 v_load_halves(const double* ptr0, const double* ptr1)
{
double CV_DECL_ALIGNED(32) elems[2] =
{
ptr0[0], ptr1[0]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
#endif
////////////// 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]]
};
vsetvlmax_e8m1();
return v_int8x16(vle8_v_i8m1(elems));
}
inline v_int8x16 v_lut_pairs(const schar* tab, const int* idx)
{
schar CV_DECL_ALIGNED(32) elems[16] =
{
tab[idx[0]],
tab[idx[0] + 1],
tab[idx[1]],
tab[idx[1] + 1],
tab[idx[2]],
tab[idx[2] + 1],
tab[idx[3]],
tab[idx[3] + 1],
tab[idx[4]],
tab[idx[4] + 1],
tab[idx[5]],
tab[idx[5] + 1],
tab[idx[6]],
tab[idx[6] + 1],
tab[idx[7]],
tab[idx[7] + 1]
};
vsetvlmax_e8m1();
return v_int8x16(vle8_v_i8m1(elems));
}
inline v_int8x16 v_lut_quads(const schar* tab, const int* idx)
{
schar CV_DECL_ALIGNED(32) elems[16] =
{
tab[idx[0]],
tab[idx[0] + 1],
tab[idx[0] + 2],
tab[idx[0] + 3],
tab[idx[1]],
tab[idx[1] + 1],
tab[idx[1] + 2],
tab[idx[1] + 3],
tab[idx[2]],
tab[idx[2] + 1],
tab[idx[2] + 2],
tab[idx[2] + 3],
tab[idx[3]],
tab[idx[3] + 1],
tab[idx[3] + 2],
tab[idx[3] + 3]
};
vsetvlmax_e8m1();
return v_int8x16(vle8_v_i8m1(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]]
};
vsetvlmax_e16m1();
return v_int16x8(vle16_v_i16m1(elems));
}
inline v_int16x8 v_lut_pairs(const short* tab, const int* idx)
{
short CV_DECL_ALIGNED(32) elems[8] =
{
tab[idx[0]],
tab[idx[0] + 1],
tab[idx[1]],
tab[idx[1] + 1],
tab[idx[2]],
tab[idx[2] + 1],
tab[idx[3]],
tab[idx[3] + 1]
};
vsetvlmax_e16m1();
return v_int16x8(vle16_v_i16m1(elems));
}
inline v_int16x8 v_lut_quads(const short* tab, const int* idx)
{
short CV_DECL_ALIGNED(32) elems[8] =
{
tab[idx[0]],
tab[idx[0] + 1],
tab[idx[0] + 2],
tab[idx[0] + 3],
tab[idx[1]],
tab[idx[1] + 1],
tab[idx[1] + 2],
tab[idx[1] + 3]
};
vsetvlmax_e16m1();
return v_int16x8(vle16_v_i16m1(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]]
};
vsetvlmax_e32m1();
return v_int32x4(vle32_v_i32m1(elems));
}
inline v_int32x4 v_lut_pairs(const int* tab, const int* idx)
{
int CV_DECL_ALIGNED(32) elems[4] =
{
tab[idx[0]],
tab[idx[0] + 1],
tab[idx[1]],
tab[idx[1] + 1]
};
vsetvlmax_e32m1();
return v_int32x4(vle32_v_i32m1(elems));
}
inline v_int32x4 v_lut_quads(const int* tab, const int* idx)
{
vsetvlmax_e32m1();
return v_int32x4(vle32_v_i32m1(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)
{
int64_t CV_DECL_ALIGNED(32) elems[2] =
{
tab[idx[0]],
tab[idx[1]]
};
vsetvlmax_e64m1();
return v_int64x2(vle64_v_i64m1(elems));
}
inline v_int64x2 v_lut_pairs(const int64* tab, const int* idx)
{
vsetvlmax_e64m1();
return v_int64x2(vle64_v_i64m1(tab + idx[0]));
}
inline v_uint64x2 v_lut(const uint64* tab, const int* idx) { return v_reinterpret_as_u64(v_lut((const int64_t *)tab, idx)); }
inline v_uint64x2 v_lut_pairs(const uint64* 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]]
};
vsetvlmax_e32m1();
return v_float32x4(vle32_v_f32m1(elems));
}
inline v_float32x4 v_lut_pairs(const float* tab, const int* idx)
{
float CV_DECL_ALIGNED(32) elems[4] =
{
tab[idx[0]],
tab[idx[0] + 1],
tab[idx[1]],
tab[idx[1] + 1]
};
vsetvlmax_e32m1();
return v_float32x4(vle32_v_f32m1(elems));
}
inline v_float32x4 v_lut_quads(const float* tab, const int* idx)
{
vsetvlmax_e32m1();
return v_float32x4(vle32_v_f32m1(tab + idx[0]));
}
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
{
int CV_DECL_ALIGNED(32) elems[4] =
{
tab[v_extract_n<0>(idxvec)],
tab[v_extract_n<1>(idxvec)],
tab[v_extract_n<2>(idxvec)],
tab[v_extract_n<3>(idxvec)]
};
vsetvlmax_e32m1();
return v_int32x4(vle32_v_i32m1(elems));
}
inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
{
unsigned CV_DECL_ALIGNED(32) elems[4] =
{
tab[v_extract_n<0>(idxvec)],
tab[v_extract_n<1>(idxvec)],
tab[v_extract_n<2>(idxvec)],
tab[v_extract_n<3>(idxvec)]
};
vsetvlmax_e32m1();
return v_uint32x4(vle32_v_u32m1(elems));
}
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
{
float CV_DECL_ALIGNED(32) elems[4] =
{
tab[v_extract_n<0>(idxvec)],
tab[v_extract_n<1>(idxvec)],
tab[v_extract_n<2>(idxvec)],
tab[v_extract_n<3>(idxvec)]
};
vsetvlmax_e32m1();
return v_float32x4(vle32_v_f32m1(elems));
}
inline void v_lut_deinterleave(const float* tab, const v_int32x4& idxvec, v_float32x4& x, v_float32x4& y)
{
int CV_DECL_ALIGNED(32) idx[4];
v_store_aligned(idx, idxvec);
x = v_float32x4(tab[idx[0]], tab[idx[1]], tab[idx[2]], tab[idx[3]]);
y = v_float32x4(tab[idx[0]+1], tab[idx[1]+1], tab[idx[2]+1], tab[idx[3]+1]);
}
#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]]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
inline v_float64x2 v_lut_pairs(const double* tab, const int* idx)
{
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(tab + idx[0]));
}
inline v_float64x2 v_lut(const double* tab, const v_int32x4& idxvec)
{
double CV_DECL_ALIGNED(32) elems[2] =
{
tab[v_extract_n<0>(idxvec)],
tab[v_extract_n<1>(idxvec)]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
inline void v_lut_deinterleave(const double* tab, const v_int32x4& idxvec, v_float64x2& x, v_float64x2& y)
{
int CV_DECL_ALIGNED(32) idx[4] = {0};
v_store_aligned(idx, idxvec);
x = v_float64x2(tab[idx[0]], tab[idx[1]]);
y = v_float64x2(tab[idx[0]+1], tab[idx[1]+1]);
}
#endif
////////////// Pack boolean ////////////////////
inline v_uint8x16 v_pack_b(const v_uint16x8& a, const v_uint16x8& b)
{
ushort CV_DECL_ALIGNED(32) ptr[16] = {0};
v_store(ptr, a);
v_store(ptr + 8, b);
vsetvlmax_e8m1();
return v_uint8x16(vnsrl_wx_u8m1(vle16_v_u16m2(ptr), 0));
}
inline v_uint8x16 v_pack_b(const v_uint32x4& a, const v_uint32x4& b,
const v_uint32x4& c, const v_uint32x4& d)
{
unsigned CV_DECL_ALIGNED(32) ptr[16] = {0};
v_store(ptr, a);
v_store(ptr + 4, b);
v_store(ptr + 8, c);
v_store(ptr + 12, d);
vsetvlmax_e8m1();
return v_uint8x16(vnsrl_wx_u8m1(vnsrl_wx_u16m2(vle32_v_u32m4(ptr), 0), 0));
}
inline v_uint8x16 v_pack_b(const v_uint64x2& a, const v_uint64x2& b, const v_uint64x2& c,
const v_uint64x2& d, const v_uint64x2& e, const v_uint64x2& f,
const v_uint64x2& g, const v_uint64x2& h)
{
uint64 CV_DECL_ALIGNED(32) ptr[16] = {0};
v_store(ptr, a);
v_store(ptr + 2, b);
v_store(ptr + 4, c);
v_store(ptr + 6, d);
v_store(ptr + 8, e);
v_store(ptr + 10, f);
v_store(ptr + 12, g);
v_store(ptr + 14, h);
vsetvlmax_e8m1();
return v_uint8x16(vnsrl_wx_u8m1(vnsrl_wx_u16m2(vnsrl_wx_u32m4(vle64_v_u64m8(ptr), 0), 0), 0));
}
////////////// Arithmetics //////////////
#define OPENCV_HAL_IMPL_RVV_BIN_OP(bin_op, _Tpvec, intrin, width) \
inline _Tpvec operator bin_op (const _Tpvec& a, const _Tpvec& b) \
{ \
_Tp c = a.s[0]; \
for( int i = 1; i < n; i++ ) \
c = cfunc(c, a.s[i]); \
return c; \
vsetvlmax_e##width##m1(); \
return _Tpvec(intrin(a, b)); \
} \
inline _Tpvec& operator bin_op##= (_Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
a = _Tpvec(intrin(a, b)); \
return a; \
}
OPENCV_HAL_IMPL_MINMAX_FUNC(v_min, std::min)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_uint8x16, vsaddu_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_uint8x16, vssubu_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_uint8x16, vdivu_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_int8x16, vsadd_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_int8x16, vssub_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_int8x16, vdiv_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_uint16x8, vsaddu_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_uint16x8, vssubu_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_uint16x8, vdivu_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_int16x8, vsadd_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_int16x8, vssub_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_int16x8, vdiv_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_uint32x4, vadd_vv_u32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_uint32x4, vsub_vv_u32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(*, v_uint32x4, vmul_vv_u32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_uint32x4, vdivu_vv_u32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_int32x4, vadd_vv_i32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_int32x4, vsub_vv_i32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(*, v_int32x4, vmul_vv_i32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_int32x4, vdiv_vv_i32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_float32x4, vfadd_vv_f32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_float32x4, vfsub_vv_f32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(*, v_float32x4, vfmul_vv_f32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_float32x4, vfdiv_vv_f32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_uint64x2, vadd_vv_u64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_uint64x2, vsub_vv_u64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(*, v_uint64x2, vmul_vv_u64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_uint64x2, vdivu_vv_u64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_int64x2, vadd_vv_i64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_int64x2, vsub_vv_i64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(*, v_int64x2, vmul_vv_i64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_int64x2, vdiv_vv_i64m1, 64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_BIN_OP(+, v_float64x2, vfadd_vv_f64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(-, v_float64x2, vfsub_vv_f64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(*, v_float64x2, vfmul_vv_f64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_OP(/, v_float64x2, vfdiv_vv_f64m1, 64)
#endif
OPENCV_HAL_IMPL_MINMAX_FUNC(v_max, std::max)
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_min, std::min)
////////////// Bitwise logic //////////////
OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_max, std::max)
#define OPENCV_HAL_IMPL_RVV_LOGIC_OP(_Tpvec, suffix, width) \
OPENCV_HAL_IMPL_RVV_BIN_OP(&, _Tpvec, vand_vv_##suffix##m1, width) \
OPENCV_HAL_IMPL_RVV_BIN_OP(|, _Tpvec, vor_vv_##suffix##m1, width) \
OPENCV_HAL_IMPL_RVV_BIN_OP(^, _Tpvec, vxor_vv_##suffix##m1, width) \
inline _Tpvec operator ~ (const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vnot_v_##suffix##m1(a)); \
}
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint8x16, u8, 8)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int8x16, i8, 8)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint16x8, u16, 16)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int16x8, i16, 16)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint32x4, u32, 32)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int32x4, i32, 32)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_uint64x2, u64, 64)
OPENCV_HAL_IMPL_RVV_LOGIC_OP(v_int64x2, i64, 64)
#define OPENCV_HAL_IMPL_RVV_FLT_BIT_OP(bin_op, intrin) \
inline v_float32x4 operator bin_op (const v_float32x4& a, const v_float32x4& b) \
{ \
vsetvlmax_e32m1(); \
return v_float32x4(vreinterpret_v_i32m1_f32m1(intrin(vreinterpret_v_f32m1_i32m1(a), vreinterpret_v_f32m1_i32m1(b)))); \
} \
inline v_float32x4& operator bin_op##= (v_float32x4& a, const v_float32x4& b) \
{ \
vsetvlmax_e32m1(); \
a = v_float32x4(vreinterpret_v_i32m1_f32m1(intrin(vreinterpret_v_f32m1_i32m1(a), vreinterpret_v_f32m1_i32m1(b)))); \
return a; \
}
OPENCV_HAL_IMPL_RVV_FLT_BIT_OP(&, vand_vv_i32m1)
OPENCV_HAL_IMPL_RVV_FLT_BIT_OP(|, vor_vv_i32m1)
OPENCV_HAL_IMPL_RVV_FLT_BIT_OP(^, vxor_vv_i32m1)
inline v_float32x4 operator ~ (const v_float32x4& a)
{
vsetvlmax_e32m1();
return v_float32x4(vreinterpret_v_i32m1_f32m1(vnot_v_i32m1(vreinterpret_v_f32m1_i32m1(a))));
}
#if CV_SIMD128_64F
#define OPENCV_HAL_IMPL_RVV_FLT64_BIT_OP(bin_op, intrin) \
inline v_float64x2 operator bin_op (const v_float64x2& a, const v_float64x2& b) \
{ \
vsetvlmax_e64m1(); \
return v_float64x2(vreinterpret_v_i64m1_f64m1(intrin(vreinterpret_v_f64m1_i64m1(a), vreinterpret_v_f64m1_i64m1(b)))); \
} \
inline v_float64x2& operator bin_op##= (v_float64x2& a, const v_float64x2& b) \
{ \
vsetvlmax_e64m1(); \
a = v_float64x2(vreinterpret_v_i64m1_f64m1(intrin(vreinterpret_v_f64m1_i64m1(a), vreinterpret_v_f64m1_i64m1(b)))); \
return a; \
}
OPENCV_HAL_IMPL_RVV_FLT64_BIT_OP(&, vand_vv_i64m1)
OPENCV_HAL_IMPL_RVV_FLT64_BIT_OP(|, vor_vv_i64m1)
OPENCV_HAL_IMPL_RVV_FLT64_BIT_OP(^, vxor_vv_i64m1)
inline v_float64x2 operator ~ (const v_float64x2& a)
{
vsetvlmax_e64m1();
return v_float64x2(vreinterpret_v_i64m1_f64m1(vnot_v_i64m1(vreinterpret_v_f64m1_i64m1(a))));
}
#endif
////////////// Bitwise shifts //////////////
#define OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(_Tpvec, suffix, width) \
inline _Tpvec operator << (const _Tpvec& a, int n) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsll_vx_##suffix##m1(a, uint8_t(n))); \
} \
inline _Tpvec operator >> (const _Tpvec& a, int n) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsrl_vx_##suffix##m1(a, uint8_t(n))); \
} \
template<int n> inline _Tpvec v_shl(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsll_vx_##suffix##m1(a, uint8_t(n))); \
} \
template<int n> inline _Tpvec v_shr(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsrl_vx_##suffix##m1(a, uint8_t(n))); \
}
#define OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(_Tpvec, suffix, width) \
inline _Tpvec operator << (const _Tpvec& a, int n) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsll_vx_##suffix##m1(a, uint8_t(n))); \
} \
inline _Tpvec operator >> (const _Tpvec& a, int n) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsra_vx_##suffix##m1(a, uint8_t(n))); \
} \
template<int n> inline _Tpvec v_shl(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsll_vx_##suffix##m1(a, uint8_t(n))); \
} \
template<int n> inline _Tpvec v_shr(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vsra_vx_##suffix##m1(a, uint8_t(n))); \
}
OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint8x16, u8, 8)
OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint16x8, u16, 16)
OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint32x4, u32, 32)
OPENCV_HAL_IMPL_RVV_UNSIGNED_SHIFT_OP(v_uint64x2, u64, 64)
OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int8x16, i8, 8)
OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int16x8, i16, 16)
OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int32x4, i32, 32)
OPENCV_HAL_IMPL_RVV_SIGNED_SHIFT_OP(v_int64x2, i64, 64)
////////////// Comparison //////////////
#define OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, op, intrin, suffix, width) \
inline _Tpvec operator op (const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vmerge_vxm_##suffix##m1(intrin(a, b), vzero_##suffix##m1(), 1)); \
}
#define OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, op, intrin, suffix, width) \
inline _Tpvec operator op (const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vfmerge_vfm_##suffix##m1(intrin(a, b), vzero_##suffix##m1(), 1)); \
}
#define OPENCV_HAL_IMPL_RVV_UNSIGNED_CMP(_Tpvec, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, ==, vmseq_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, !=, vmsne_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, <, vmsltu_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, >, vmsgtu_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, <=, vmsleu_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, >=, vmsgeu_vv_##suffix##m1_b##width, suffix, width)
#define OPENCV_HAL_IMPL_RVV_SIGNED_CMP(_Tpvec, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, ==, vmseq_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, !=, vmsne_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, <, vmslt_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, >, vmsgt_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, <=, vmsle_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_INT_CMP_OP(_Tpvec, >=, vmsge_vv_##suffix##m1_b##width, suffix, width)
#define OPENCV_HAL_IMPL_RVV_FLOAT_CMP(_Tpvec, suffix, width) \
OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, ==, vmfeq_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, !=, vmfne_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, <, vmflt_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, >, vmfgt_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, <=, vmfle_vv_##suffix##m1_b##width, suffix, width) \
OPENCV_HAL_IMPL_RVV_FLOAT_CMP_OP(_Tpvec, >=, vmfge_vv_##suffix##m1_b##width, suffix, width)
OPENCV_HAL_IMPL_RVV_UNSIGNED_CMP(v_uint8x16, u8, 8)
OPENCV_HAL_IMPL_RVV_UNSIGNED_CMP(v_uint16x8, u16, 16)
OPENCV_HAL_IMPL_RVV_UNSIGNED_CMP(v_uint32x4, u32, 32)
OPENCV_HAL_IMPL_RVV_UNSIGNED_CMP(v_uint64x2, u64, 64)
OPENCV_HAL_IMPL_RVV_SIGNED_CMP(v_int8x16, i8, 8)
OPENCV_HAL_IMPL_RVV_SIGNED_CMP(v_int16x8, i16, 16)
OPENCV_HAL_IMPL_RVV_SIGNED_CMP(v_int32x4, i32, 32)
OPENCV_HAL_IMPL_RVV_SIGNED_CMP(v_int64x2, i64, 64)
OPENCV_HAL_IMPL_RVV_FLOAT_CMP(v_float32x4, f32, 32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_FLOAT_CMP(v_float64x2, f64, 64)
#endif
inline v_float32x4 v_not_nan(const v_float32x4& a)
{ return a == a; }
#if CV_SIMD128_64F
inline v_float64x2 v_not_nan(const v_float64x2& a)
{ return a == a; }
#endif
////////////// Min/Max //////////////
#define OPENCV_HAL_IMPL_RVV_BIN_FUNC(_Tpvec, func, intrin, width) \
inline _Tpvec func(const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(intrin(a, b)); \
}
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint8x16, v_min, vminu_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint8x16, v_max, vmaxu_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int8x16, v_min, vmin_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int8x16, v_max, vmax_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint16x8, v_min, vminu_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint16x8, v_max, vmaxu_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int16x8, v_min, vmin_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int16x8, v_max, vmax_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint32x4, v_min, vminu_vv_u32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint32x4, v_max, vmaxu_vv_u32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int32x4, v_min, vmin_vv_i32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int32x4, v_max, vmax_vv_i32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float32x4, v_min, vfmin_vv_f32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float32x4, v_max, vfmax_vv_f32m1, 32)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint64x2, v_min, vminu_vv_u64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint64x2, v_max, vmaxu_vv_u64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int64x2, v_min, vmin_vv_i64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int64x2, v_max, vmax_vv_i64m1, 64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float64x2, v_min, vfmin_vv_f64m1, 64)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_float64x2, v_max, vfmax_vv_f64m1, 64)
#endif
////////////// Arithmetics wrap //////////////
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint8x16, v_add_wrap, vadd_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int8x16, v_add_wrap, vadd_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint16x8, v_add_wrap, vadd_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int16x8, v_add_wrap, vadd_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint8x16, v_sub_wrap, vsub_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int8x16, v_sub_wrap, vsub_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint16x8, v_sub_wrap, vsub_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int16x8, v_sub_wrap, vsub_vv_i16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint8x16, v_mul_wrap, vmul_vv_u8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int8x16, v_mul_wrap, vmul_vv_i8m1, 8)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_uint16x8, v_mul_wrap, vmul_vv_u16m1, 16)
OPENCV_HAL_IMPL_RVV_BIN_FUNC(v_int16x8, v_mul_wrap, vmul_vv_i16m1, 16)
////////////// Reduce //////////////
#define OPENCV_HAL_IMPL_RVV_REDUCE_SUM(_Tpvec, _wTpvec, _nwTpvec, scalartype, suffix, wsuffix, wwidth, red) \
inline scalartype v_reduce_sum(const _Tpvec& a) \
{ \
vsetvlmax_e##wwidth##m1(); \
_nwTpvec zero = vzero_##wsuffix##m1(); \
_nwTpvec res = vzero_##wsuffix##m1(); \
res = v##red##_vs_##suffix##m1_##wsuffix##m1(res, a, zero); \
return (scalartype)(_wTpvec(res).get0()); \
}
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint8x16, v_uint16x8, vuint16m1_t, unsigned, u8, u16, 16, wredsumu)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int8x16, v_int16x8, vint16m1_t, int, i8, i16, 16, wredsum)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint16x8, v_uint32x4, vuint32m1_t, unsigned, u16, u32, 32, wredsumu)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int16x8, v_int32x4, vint32m1_t, int, i16, i32, 32, wredsum)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint32x4, v_uint64x2, vuint64m1_t, unsigned, u32, u64, 64, wredsumu)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int32x4, v_int64x2, vint64m1_t, int, i32, i64, 64, wredsum)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_float32x4, v_float32x4, vfloat32m1_t, float, f32, f32, 32, fredsum)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_uint64x2, v_uint64x2, vuint64m1_t, uint64, u64, u64, 64, redsum)
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_int64x2, v_int64x2, vint64m1_t, int64, i64, i64, 64, redsum)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_REDUCE_SUM(v_float64x2, v_float64x2, vfloat64m1_t, double, f64, f64, 64, fredsum)
#endif
#define OPENCV_HAL_IMPL_RVV_REDUCE(_Tpvec, func, scalartype, suffix, width, red) \
inline scalartype v_reduce_##func(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
_Tpvec res = _Tpvec(v##red##_vs_##suffix##m1_##suffix##m1(a, a, a)); \
return scalartype(res.get0()); \
}
OPENCV_HAL_IMPL_RVV_REDUCE(v_uint8x16, min, uchar, u8, 8, redminu)
OPENCV_HAL_IMPL_RVV_REDUCE(v_int8x16, min, schar, i8, 8, redmin)
OPENCV_HAL_IMPL_RVV_REDUCE(v_uint16x8, min, ushort, u16, 16, redminu)
OPENCV_HAL_IMPL_RVV_REDUCE(v_int16x8, min, short, i16, 16, redmin)
OPENCV_HAL_IMPL_RVV_REDUCE(v_uint32x4, min, unsigned, u32, 32, redminu)
OPENCV_HAL_IMPL_RVV_REDUCE(v_int32x4, min, int, i32, 32, redmin)
OPENCV_HAL_IMPL_RVV_REDUCE(v_float32x4, min, float, f32, 32, fredmin)
OPENCV_HAL_IMPL_RVV_REDUCE(v_uint8x16, max, uchar, u8, 8, redmaxu)
OPENCV_HAL_IMPL_RVV_REDUCE(v_int8x16, max, schar, i8, 8, redmax)
OPENCV_HAL_IMPL_RVV_REDUCE(v_uint16x8, max, ushort, u16, 16, redmaxu)
OPENCV_HAL_IMPL_RVV_REDUCE(v_int16x8, max, short, i16, 16, redmax)
OPENCV_HAL_IMPL_RVV_REDUCE(v_uint32x4, max, unsigned, u32, 32, redmaxu)
OPENCV_HAL_IMPL_RVV_REDUCE(v_int32x4, max, int, i32, 32, redmax)
OPENCV_HAL_IMPL_RVV_REDUCE(v_float32x4, max, float, f32, 32, fredmax)
inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
const v_float32x4& c, const v_float32x4& d)
{
float CV_DECL_ALIGNED(32) elems[4] =
{
v_reduce_sum(a),
v_reduce_sum(b),
v_reduce_sum(c),
v_reduce_sum(d)
};
vsetvlmax_e32m1();
return v_float32x4(vle32_v_f32m1(elems));
}
////////////// Square-Root //////////////
inline v_float32x4 v_sqrt(const v_float32x4& x)
{
vsetvlmax_e32m1();
return v_float32x4(vfsqrt_v_f32m1(x));
}
inline v_float32x4 v_invsqrt(const v_float32x4& x)
{
v_float32x4 one = v_setall_f32(1.0f);
return one / v_sqrt(x);
}
#if CV_SIMD128_64F
inline v_float64x2 v_sqrt(const v_float64x2& x)
{
vsetvlmax_e64m1();
return v_float64x2(vfsqrt_v_f64m1(x));
}
inline v_float64x2 v_invsqrt(const v_float64x2& x)
{
v_float64x2 one = v_setall_f64(1.0f);
return one / v_sqrt(x);
}
#endif
inline v_float32x4 v_magnitude(const v_float32x4& a, const v_float32x4& b)
{
vsetvlmax_e32m1();
v_float32x4 x(vfmacc_vv_f32m1(vfmul_vv_f32m1(a, a), b, b));
return v_sqrt(x);
}
inline v_float32x4 v_sqr_magnitude(const v_float32x4& a, const v_float32x4& b)
{
vsetvlmax_e32m1();
return v_float32x4(vfmacc_vv_f32m1(vfmul_vv_f32m1(a, a), b, b));
}
#if CV_SIMD128_64F
inline v_float64x2 v_magnitude(const v_float64x2& a, const v_float64x2& b)
{
vsetvlmax_e64m1();
v_float64x2 x(vfmacc_vv_f64m1(vfmul_vv_f64m1(a, a), b, b));
return v_sqrt(x);
}
inline v_float64x2 v_sqr_magnitude(const v_float64x2& a, const v_float64x2& b)
{
vsetvlmax_e64m1();
return v_float64x2(vfmacc_vv_f64m1(vfmul_vv_f64m1(a, a), b, b));
}
#endif
////////////// Multiply-Add //////////////
inline v_float32x4 v_fma(const v_float32x4& a, const v_float32x4& b, const v_float32x4& c)
{
vsetvlmax_e32m1();
return v_float32x4(vfmacc_vv_f32m1(c, a, b));
}
inline v_int32x4 v_fma(const v_int32x4& a, const v_int32x4& b, const v_int32x4& c)
{
vsetvlmax_e32m1();
return v_int32x4(vmacc_vv_i32m1(c, a, b));
}
inline v_float32x4 v_muladd(const v_float32x4& a, const v_float32x4& b, const v_float32x4& c)
{
return v_fma(a, b, c);
}
inline v_int32x4 v_muladd(const v_int32x4& a, const v_int32x4& b, const v_int32x4& c)
{
return v_fma(a, b, c);
}
#if CV_SIMD128_64F
inline v_float64x2 v_fma(const v_float64x2& a, const v_float64x2& b, const v_float64x2& c)
{
vsetvlmax_e64m1();
return v_float64x2(vfmacc_vv_f64m1(c, a, b));
}
inline v_float64x2 v_muladd(const v_float64x2& a, const v_float64x2& b, const v_float64x2& c)
{
return v_fma(a, b, c);
}
#endif
////////////// Check all/any //////////////
#define OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(_Tpvec, suffix, shift, width) \
inline bool v_check_all(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
v_uint64x2 v = v_uint64x2((vuint64m1_t)vsrl_vx_##suffix##m1(vnot_v_##suffix##m1(a), shift)); \
return (v.val[0] | v.val[1]) == 0; \
} \
inline bool v_check_any(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
v_uint64x2 v = v_uint64x2((vuint64m1_t)vsrl_vx_##suffix##m1(a, shift)); \
return (v.val[0] | v.val[1]) != 0; \
}
OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_uint8x16, u8, 7, 8)
OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_uint16x8, u16, 15, 16)
OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_uint32x4, u32, 31, 32)
OPENCV_HAL_IMPL_RVV_CHECK_ALLANY(v_uint64x2, u64, 63, 64)
inline bool v_check_all(const v_int8x16& a)
{ return v_check_all(v_reinterpret_as_u8(a)); }
inline bool v_check_any(const v_int8x16& a)
{ return v_check_any(v_reinterpret_as_u8(a)); }
inline bool v_check_all(const v_int16x8& a)
{ return v_check_all(v_reinterpret_as_u16(a)); }
inline bool v_check_any(const v_int16x8& a)
{ return v_check_any(v_reinterpret_as_u16(a)); }
inline bool v_check_all(const v_int32x4& a)
{ return v_check_all(v_reinterpret_as_u32(a)); }
inline bool v_check_any(const v_int32x4& a)
{ return v_check_any(v_reinterpret_as_u32(a)); }
inline bool v_check_all(const v_float32x4& a)
{ return v_check_all(v_reinterpret_as_u32(a)); }
inline bool v_check_any(const v_float32x4& a)
{ return v_check_any(v_reinterpret_as_u32(a)); }
inline bool v_check_all(const v_int64x2& a)
{ return v_check_all(v_reinterpret_as_u64(a)); }
inline bool v_check_any(const v_int64x2& a)
{ return v_check_any(v_reinterpret_as_u64(a)); }
#if CV_SIMD128_64F
inline bool v_check_all(const v_float64x2& a)
{ return v_check_all(v_reinterpret_as_u64(a)); }
inline bool v_check_any(const v_float64x2& a)
{ return v_check_any(v_reinterpret_as_u64(a)); }
#endif
////////////// abs //////////////
#define OPENCV_HAL_IMPL_RVV_ABSDIFF(_Tpvec, abs) \
inline _Tpvec v_##abs(const _Tpvec& a, const _Tpvec& b) \
{ \
return v_max(a, b) - v_min(a, b); \
}
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_uint8x16, absdiff)
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_uint16x8, absdiff)
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_uint32x4, absdiff)
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_float32x4, absdiff)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_float64x2, absdiff)
#endif
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_int8x16, absdiffs)
OPENCV_HAL_IMPL_RVV_ABSDIFF(v_int16x8, absdiffs)
#define OPENCV_HAL_IMPL_RVV_ABSDIFF_S(_Tpvec, _rTpvec, _nwTpvec, sub, rshr, width) \
inline _rTpvec v_absdiff(const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _rTpvec(rshr((_nwTpvec)sub(v_max(a, b), v_min(a, b)), 0)); \
}
OPENCV_HAL_IMPL_RVV_ABSDIFF_S(v_int8x16, v_uint8x16, vuint16m2_t, vwsub_vv_i16m2, vnclipu_wx_u8m1, 8)
OPENCV_HAL_IMPL_RVV_ABSDIFF_S(v_int16x8, v_uint16x8, vuint32m2_t, vwsub_vv_i32m2, vnclipu_wx_u16m1, 16)
OPENCV_HAL_IMPL_RVV_ABSDIFF_S(v_int32x4, v_uint32x4, vuint64m2_t, vwsub_vv_i64m2, vnclipu_wx_u32m1, 32)
#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_uint8x16, v_int8x16, s8)
OPENCV_HAL_IMPL_RVV_ABS(v_uint16x8, v_int16x8, s16)
OPENCV_HAL_IMPL_RVV_ABS(v_uint32x4, v_int32x4, s32)
OPENCV_HAL_IMPL_RVV_ABS(v_float32x4, v_float32x4, f32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_ABS(v_float64x2, v_float64x2, 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_uint8x16, unsigned)
OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_int8x16, unsigned)
OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_uint16x8, unsigned)
OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_int16x8, unsigned)
OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_uint32x4, unsigned)
OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_int32x4, unsigned)
OPENCV_HAL_IMPL_RVV_REDUCE_SAD(v_float32x4, float)
////////////// Select //////////////
#define OPENCV_HAL_IMPL_RVV_SELECT(_Tpvec, merge, ne, width) \
inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(merge(ne(mask, 0), b, a)); \
}
OPENCV_HAL_IMPL_RVV_SELECT(v_uint8x16, vmerge_vvm_u8m1, vmsne_vx_u8m1_b8, 8)
OPENCV_HAL_IMPL_RVV_SELECT(v_int8x16, vmerge_vvm_i8m1, vmsne_vx_i8m1_b8, 8)
OPENCV_HAL_IMPL_RVV_SELECT(v_uint16x8, vmerge_vvm_u16m1, vmsne_vx_u16m1_b16, 16)
OPENCV_HAL_IMPL_RVV_SELECT(v_int16x8, vmerge_vvm_i16m1, vmsne_vx_i16m1_b16, 16)
OPENCV_HAL_IMPL_RVV_SELECT(v_uint32x4, vmerge_vvm_u32m1, vmsne_vx_u32m1_b32, 32)
OPENCV_HAL_IMPL_RVV_SELECT(v_int32x4, vmerge_vvm_i32m1, vmsne_vx_i32m1_b32, 32)
OPENCV_HAL_IMPL_RVV_SELECT(v_float32x4, vmerge_vvm_f32m1, vmfne_vf_f32m1_b32, 32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_SELECT(v_float64x2, vmerge_vvm_f64m1, vmfne_vf_f64m1_b64, 64)
#endif
////////////// Rotate shift //////////////
#define OPENCV_HAL_IMPL_RVV_ROTATE_OP(_Tpvec, suffix, width) \
template<int n> inline _Tpvec v_rotate_right(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vslidedown_vx_##suffix##m1(vzero_##suffix##m1(), a, n)); \
} \
template<int n> inline _Tpvec v_rotate_left(const _Tpvec& a) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vslideup_vx_##suffix##m1(vzero_##suffix##m1(), a, n)); \
} \
template<> inline _Tpvec v_rotate_left<0>(const _Tpvec& a) \
{ return a; } \
template<int n> inline _Tpvec v_rotate_right(const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vslideup_vx_##suffix##m1(vslidedown_vx_##suffix##m1(vzero_##suffix##m1(), a, n), b, _Tpvec::nlanes - n)); \
} \
template<int n> inline _Tpvec v_rotate_left(const _Tpvec& a, const _Tpvec& b) \
{ \
vsetvlmax_e##width##m1(); \
return _Tpvec(vslideup_vx_##suffix##m1(vslidedown_vx_##suffix##m1(vzero_##suffix##m1(), b, _Tpvec::nlanes - n), a, n)); \
} \
template<> inline _Tpvec v_rotate_left<0>(const _Tpvec& a, const _Tpvec& b) \
{ CV_UNUSED(b); return a; }
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_uint8x16, u8, 8)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_int8x16, i8, 8)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_uint16x8, u16, 16)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_int16x8, i16, 16)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_uint32x4, u32, 32)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_int32x4, i32, 32)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_float32x4, f32, 32)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_uint64x2, u64, 64)
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_int64x2, i64, 64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_ROTATE_OP(v_float64x2, f64, 64)
#endif
////////////// Convert to float //////////////
inline v_float32x4 v_cvt_f32(const v_int32x4& a)
{
vsetvlmax_e32m1();
return v_float32x4(vfcvt_f_x_v_f32m1(a));
}
#if CV_SIMD128_64F
inline v_float32x4 v_cvt_f32(const v_float64x2& a)
{
double arr[4] = {a.val[0], a.val[1], 0, 0};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
vsetvlmax_e32m1();
return v_float32x4(vfncvt_f_f_w_f32m1(tmp));
}
inline v_float32x4 v_cvt_f32(const v_float64x2& a, const v_float64x2& b)
{
double arr[4] = {a.val[0], a.val[1], b.val[0], b.val[1]};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
vsetvlmax_e32m1();
return v_float32x4(vfncvt_f_f_w_f32m1(tmp));
}
inline v_float64x2 v_cvt_f64(const v_int32x4& a)
{
double CV_DECL_ALIGNED(32) ptr[4] = {0};
vsetvlmax_e64m2();
vse64_v_f64m2(ptr, vfwcvt_f_x_v_f64m2(a));
double CV_DECL_ALIGNED(32) elems[2] =
{
ptr[0], ptr[1]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
inline v_float64x2 v_cvt_f64_high(const v_int32x4& a)
{
double CV_DECL_ALIGNED(32) ptr[4] = {0};
vsetvlmax_e64m2();
vse64_v_f64m2(ptr, vfwcvt_f_x_v_f64m2(a));
double CV_DECL_ALIGNED(32) elems[2] =
{
ptr[2], ptr[3]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
inline v_float64x2 v_cvt_f64(const v_float32x4& a)
{
double CV_DECL_ALIGNED(32) ptr[4] = {0};
vsetvlmax_e64m2();
vse64_v_f64m2(ptr, vfwcvt_f_f_v_f64m2(a));
double CV_DECL_ALIGNED(32) elems[2] =
{
ptr[0], ptr[1]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
inline v_float64x2 v_cvt_f64_high(const v_float32x4& a)
{
double CV_DECL_ALIGNED(32) ptr[4] = {0};
vsetvlmax_e64m2();
vse64_v_f64m2(ptr, vfwcvt_f_f_v_f64m2(a));
double CV_DECL_ALIGNED(32) elems[2] =
{
ptr[2], ptr[3]
};
vsetvlmax_e64m1();
return v_float64x2(vle64_v_f64m1(elems));
}
inline v_float64x2 v_cvt_f64(const v_int64x2& a)
{
vsetvlmax_e64m1();
return v_float64x2(vfcvt_f_x_v_f64m1(a));
}
#endif
////////////// Broadcast //////////////
#define OPENCV_HAL_IMPL_RVV_BROADCAST(_Tpvec, suffix) \
template<int i> inline _Tpvec v_broadcast_element(_Tpvec v) \
{ \
return v_setall_##suffix(v_extract_n<i>(v)); \
}
OPENCV_HAL_IMPL_RVV_BROADCAST(v_uint8x16, u8)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_int8x16, s8)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_uint16x8, u16)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_int16x8, s16)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_uint32x4, u32)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_int32x4, s32)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_uint64x2, u64)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_int64x2, s64)
OPENCV_HAL_IMPL_RVV_BROADCAST(v_float32x4, f32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_BROADCAST(v_float64x2, f64)
#endif
////////////// Transpose4x4 //////////////
#define OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(_Tpvec, _Tp, suffix) \
inline void v_transpose4x4(const v_##_Tpvec& a0, const v_##_Tpvec& a1, \
const v_##_Tpvec& a2, const v_##_Tpvec& a3, \
v_##_Tpvec& b0, v_##_Tpvec& b1, \
v_##_Tpvec& b2, v_##_Tpvec& b3) \
{ \
_Tp CV_DECL_ALIGNED(32) elems0[4] = \
{ \
v_extract_n<0>(a0), \
v_extract_n<0>(a1), \
v_extract_n<0>(a2), \
v_extract_n<0>(a3) \
}; \
b0 = v_load(elems0); \
_Tp CV_DECL_ALIGNED(32) elems1[4] = \
{ \
v_extract_n<1>(a0), \
v_extract_n<1>(a1), \
v_extract_n<1>(a2), \
v_extract_n<1>(a3) \
}; \
b1 = v_load(elems1); \
_Tp CV_DECL_ALIGNED(32) elems2[4] = \
{ \
v_extract_n<2>(a0), \
v_extract_n<2>(a1), \
v_extract_n<2>(a2), \
v_extract_n<2>(a3) \
}; \
b2 = v_load(elems2); \
_Tp CV_DECL_ALIGNED(32) elems3[4] = \
{ \
v_extract_n<3>(a0), \
v_extract_n<3>(a1), \
v_extract_n<3>(a2), \
v_extract_n<3>(a3) \
}; \
b3 = v_load(elems3); \
}
OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(uint32x4, unsigned, u32)
OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(int32x4, int, i32)
OPENCV_HAL_IMPL_RVV_TRANSPOSE4x4(float32x4, float, f32)
////////////// Reverse //////////////
#define OPENCV_HAL_IMPL_RVV_REVERSE(_Tpvec, _Tp, width, suffix) \
inline _Tpvec v_reverse(const _Tpvec& a) \
{ \
_Tp CV_DECL_ALIGNED(32) ptr[_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptra[_Tpvec::nlanes] = {0}; \
v_store(ptra, a); \
for (int i = 0; i < _Tpvec::nlanes; i++) \
{ \
ptr[i] = ptra[_Tpvec::nlanes-i-1]; \
} \
return v_load(ptr); \
}
OPENCV_HAL_IMPL_RVV_REVERSE(v_uint8x16, uchar, 8, u8)
OPENCV_HAL_IMPL_RVV_REVERSE(v_int8x16, schar, 8, i8)
OPENCV_HAL_IMPL_RVV_REVERSE(v_uint16x8, ushort, 16, u16)
OPENCV_HAL_IMPL_RVV_REVERSE(v_int16x8, short, 16, i16)
OPENCV_HAL_IMPL_RVV_REVERSE(v_uint32x4, unsigned, 32, u32)
OPENCV_HAL_IMPL_RVV_REVERSE(v_int32x4, int, 32, i32)
OPENCV_HAL_IMPL_RVV_REVERSE(v_float32x4, float, 32, f32)
OPENCV_HAL_IMPL_RVV_REVERSE(v_uint64x2, uint64, 64, u64)
OPENCV_HAL_IMPL_RVV_REVERSE(v_int64x2, int64, 64, i64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_REVERSE(v_float64x2, double, 64, f64)
#endif
//////////// Value reordering ////////////
#define OPENCV_HAL_IMPL_RVV_EXPAND(_Tpwvec, _Tp, _Tpvec, width, suffix, wcvt) \
inline void v_expand(const _Tpvec& a, _Tpwvec& b0, _Tpwvec& b1) \
{ \
_Tp CV_DECL_ALIGNED(32) lptr[_Tpvec::nlanes/2] = {0}; \
_Tp CV_DECL_ALIGNED(32) hptr[_Tpvec::nlanes/2] = {0}; \
v_store_low(lptr, a); \
v_store_high(hptr, a); \
b0 = _Tpwvec(wcvt(vle##width##_v_##suffix##mf2(lptr))); \
b1 = _Tpwvec(wcvt(vle##width##_v_##suffix##mf2(hptr))); \
} \
inline _Tpwvec v_expand_low(const _Tpvec& a) \
{ \
_Tp CV_DECL_ALIGNED(32) lptr[_Tpvec::nlanes/2] = {0}; \
v_store_low(lptr, a); \
return _Tpwvec(wcvt(vle##width##_v_##suffix##mf2(lptr))); \
} \
inline _Tpwvec v_expand_high(const _Tpvec& a) \
{ \
_Tp CV_DECL_ALIGNED(32) hptr[_Tpvec::nlanes/2] = {0}; \
v_store_high(hptr, a); \
return _Tpwvec(wcvt(vle##width##_v_##suffix##mf2(hptr))); \
} \
inline _Tpwvec v_load_expand(const _Tp* ptr) \
{ \
return _Tpwvec(wcvt(vle##width##_v_##suffix##mf2(ptr))); \
}
OPENCV_HAL_IMPL_RVV_EXPAND(v_uint16x8, uchar, v_uint8x16, 8, u8, vwcvtu_x_x_v_u16m1)
OPENCV_HAL_IMPL_RVV_EXPAND(v_int16x8, schar, v_int8x16, 8, i8, vwcvt_x_x_v_i16m1)
OPENCV_HAL_IMPL_RVV_EXPAND(v_uint32x4, ushort, v_uint16x8, 16, u16, vwcvtu_x_x_v_u32m1)
OPENCV_HAL_IMPL_RVV_EXPAND(v_int32x4, short, v_int16x8, 16, i16, vwcvt_x_x_v_i32m1)
OPENCV_HAL_IMPL_RVV_EXPAND(v_uint64x2, uint, v_uint32x4, 32, u32, vwcvtu_x_x_v_u64m1)
OPENCV_HAL_IMPL_RVV_EXPAND(v_int64x2, int, v_int32x4, 32, i32, vwcvt_x_x_v_i64m1)
inline v_uint32x4 v_load_expand_q(const uchar* ptr)
{
vsetvlmax_e32m1();
return v_uint32x4(vwcvtu_x_x_v_u32m1(vwcvtu_x_x_v_u16mf2(vle8_v_u8mf4(ptr))));
}
inline v_int32x4 v_load_expand_q(const schar* ptr)
{
vsetvlmax_e32m1();
return v_int32x4(vwcvt_x_x_v_i32m1(vwcvt_x_x_v_i16mf2(vle8_v_i8mf4(ptr))));
}
#define OPENCV_HAL_IMPL_RVV_PACK(_Tpvec, _Tp, _wTpvec, _wTp, width, suffix, rshr, shr) \
inline _Tpvec v_pack(const _wTpvec& a, const _wTpvec& b) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, b); \
vsetvlmax_e##width##m2(); \
return _Tpvec(shr(vle##width##_v_##suffix##m2(arr), 0)); \
} \
inline void v_pack_store(_Tp* ptr, const _wTpvec& a) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, _wTpvec(vzero_##suffix##m1())); \
vsetvlmax_e##width##m2(); \
v_store(ptr, _Tpvec(shr(vle##width##_v_##suffix##m2(arr), 0))); \
} \
template<int n> inline \
_Tpvec v_rshr_pack(const _wTpvec& a, const _wTpvec& b) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, b); \
vsetvlmax_e##width##m2(); \
return _Tpvec(rshr(vle##width##_v_##suffix##m2(arr), n)); \
} \
template<int n> inline \
void v_rshr_pack_store(_Tp* ptr, const _wTpvec& a) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, _wTpvec(vzero_##suffix##m1())); \
vsetvlmax_e##width##m2(); \
v_store(ptr, _Tpvec(rshr(vle##width##_v_##suffix##m2(arr), n))); \
}
OPENCV_HAL_IMPL_RVV_PACK(v_uint8x16, uchar, v_uint16x8, ushort, 16, u16, vnclipu_wx_u8m1, vnclipu_wx_u8m1)
OPENCV_HAL_IMPL_RVV_PACK(v_int8x16, schar, v_int16x8, short, 16, i16, vnclip_wx_i8m1, vnclip_wx_i8m1)
OPENCV_HAL_IMPL_RVV_PACK(v_uint16x8, ushort, v_uint32x4, unsigned, 32, u32, vnclipu_wx_u16m1, vnclipu_wx_u16m1)
OPENCV_HAL_IMPL_RVV_PACK(v_int16x8, short, v_int32x4, int, 32, i32, vnclip_wx_i16m1, vnclip_wx_i16m1)
OPENCV_HAL_IMPL_RVV_PACK(v_uint32x4, unsigned, v_uint64x2, uint64, 64, u64, vnclipu_wx_u32m1, vnsrl_wx_u32m1)
OPENCV_HAL_IMPL_RVV_PACK(v_int32x4, int, v_int64x2, int64, 64, i64, vnclip_wx_i32m1, vnsra_wx_i32m1)
#define OPENCV_HAL_IMPL_RVV_PACK_U(_Tpvec, _Tp, _wTpvec, _wTp, width, suffix, rshr, cast) \
inline _Tpvec v_pack_u(const _wTpvec& a, const _wTpvec& b) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, b); \
vsetvlmax_e##width##m2(); \
return _Tpvec(rshr(cast(vmax_vx_##suffix##m2(vle##width##_v_##suffix##m2(arr), 0)), 0)); \
} \
inline void v_pack_u_store(_Tp* ptr, const _wTpvec& a) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, _wTpvec(vzero_##suffix##m1())); \
vsetvlmax_e##width##m2(); \
v_store(ptr, _Tpvec(rshr(cast(vmax_vx_##suffix##m2(vle##width##_v_##suffix##m2(arr), 0)), 0))); \
} \
template<int n> inline \
_Tpvec v_rshr_pack_u(const _wTpvec& a, const _wTpvec& b) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, b); \
vsetvlmax_e##width##m2(); \
return _Tpvec(rshr(cast(vmax_vx_##suffix##m2(vle##width##_v_##suffix##m2(arr), 0)), n)); \
} \
template<int n> inline \
void v_rshr_pack_u_store(_Tp* ptr, const _wTpvec& a) \
{ \
_wTp CV_DECL_ALIGNED(32) arr[_Tpvec::nlanes] = {0}; \
v_store(arr, a); \
v_store(arr + _wTpvec::nlanes, _wTpvec(vzero_##suffix##m1())); \
vsetvlmax_e##width##m2(); \
v_store(ptr, _Tpvec(rshr(cast(vmax_vx_##suffix##m2(vle##width##_v_##suffix##m2(arr), 0)), n))); \
}
OPENCV_HAL_IMPL_RVV_PACK_U(v_uint8x16, uchar, v_int16x8, short, 16, i16, vnclipu_wx_u8m1, vreinterpret_v_i16m2_u16m2)
OPENCV_HAL_IMPL_RVV_PACK_U(v_uint16x8, ushort, v_int32x4, int, 32, i32, vnclipu_wx_u16m1, vreinterpret_v_i32m2_u32m2)
#define OPENCV_HAL_IMPL_RVV_UNPACKS(_Tpvec, _Tp, width, suffix) \
inline void v_zip(const v_##_Tpvec& a0, const v_##_Tpvec& a1, v_##_Tpvec& b0, v_##_Tpvec& b1) \
{ \
_Tp CV_DECL_ALIGNED(32) ptra0[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptra1[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb0[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb1[v_##_Tpvec::nlanes] = {0}; \
v_store(ptra0, a0); \
v_store(ptra1, a1); \
int i; \
for( i = 0; i < v_##_Tpvec::nlanes/2; i++ ) \
{ \
ptrb0[i*2] = ptra0[i]; \
ptrb0[i*2+1] = ptra1[i]; \
} \
for( ; i < v_##_Tpvec::nlanes; i++ ) \
{ \
ptrb1[i*2-v_##_Tpvec::nlanes] = ptra0[i]; \
ptrb1[i*2-v_##_Tpvec::nlanes+1] = ptra1[i]; \
} \
b0 = v_load(ptrb0); \
b1 = v_load(ptrb1); \
} \
inline v_##_Tpvec v_combine_low(const v_##_Tpvec& a, const v_##_Tpvec& b) \
{ \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes/2] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes/2] = {0}; \
v_store_low(ptra, a); \
v_store_low(ptrb, b); \
return v_load_halves(ptra, ptrb); \
} \
inline v_##_Tpvec v_combine_high(const v_##_Tpvec& a, const v_##_Tpvec& b) \
{ \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes/2] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes/2] = {0}; \
v_store_high(ptra, a); \
v_store_high(ptrb, b); \
return v_load_halves(ptra, ptrb); \
} \
inline void v_recombine(const v_##_Tpvec& a, const v_##_Tpvec& b, v_##_Tpvec& c, v_##_Tpvec& d) \
{ \
c = v_combine_low(a, b); \
d = v_combine_high(a, b); \
}
OPENCV_HAL_IMPL_RVV_UNPACKS(uint8x16, uchar, 8, u8)
OPENCV_HAL_IMPL_RVV_UNPACKS(int8x16, schar, 8, i8)
OPENCV_HAL_IMPL_RVV_UNPACKS(uint16x8, ushort, 16, u16)
OPENCV_HAL_IMPL_RVV_UNPACKS(int16x8, short, 16, i16)
OPENCV_HAL_IMPL_RVV_UNPACKS(uint32x4, unsigned, 32, u32)
OPENCV_HAL_IMPL_RVV_UNPACKS(int32x4, int, 32, i32)
OPENCV_HAL_IMPL_RVV_UNPACKS(float32x4, float, 32, f32)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_UNPACKS(float64x2, double, 64, f64)
#endif
#define OPENCV_HAL_IMPL_RVV_INTERLEAVED(_Tpvec, _Tp, suffix, width) \
inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b) \
{ \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes] = {0}; \
int i, i2; \
for( i = i2 = 0; i < v_##_Tpvec::nlanes; i++, i2 += 2 ) \
{ \
ptra[i] = ptr[i2]; \
ptrb[i] = ptr[i2+1]; \
} \
a = v_load(ptra); \
b = v_load(ptrb); \
} \
inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b, v_##_Tpvec& c) \
{ \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrc[v_##_Tpvec::nlanes] = {0}; \
int i, i3; \
for( i = i3 = 0; i < v_##_Tpvec::nlanes; i++, i3 += 3 ) \
{ \
ptra[i] = ptr[i3]; \
ptrb[i] = ptr[i3+1]; \
ptrc[i] = ptr[i3+2]; \
} \
a = v_load(ptra); \
b = v_load(ptrb); \
c = v_load(ptrc); \
} \
inline void v_load_deinterleave(const _Tp* ptr, v_##_Tpvec& a, v_##_Tpvec& b, \
v_##_Tpvec& c, v_##_Tpvec& d) \
{ \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrc[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrd[v_##_Tpvec::nlanes] = {0}; \
int i, i4; \
for( i = i4 = 0; i < v_##_Tpvec::nlanes; i++, i4 += 4 ) \
{ \
ptra[i] = ptr[i4]; \
ptrb[i] = ptr[i4+1]; \
ptrc[i] = ptr[i4+2]; \
ptrd[i] = ptr[i4+3]; \
} \
a = v_load(ptra); \
b = v_load(ptrb); \
c = v_load(ptrc); \
d = v_load(ptrd); \
} \
inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b, \
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED) \
{ \
int i, i2; \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes] = {0}; \
v_store(ptra, a); \
v_store(ptrb, b); \
for( i = i2 = 0; i < v_##_Tpvec::nlanes; i++, i2 += 2 ) \
{ \
ptr[i2] = ptra[i]; \
ptr[i2+1] = ptrb[i]; \
} \
} \
inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b, \
const v_##_Tpvec& c, hal::StoreMode /*mode*/=hal::STORE_UNALIGNED) \
{ \
int i, i3; \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrc[v_##_Tpvec::nlanes] = {0}; \
v_store(ptra, a); \
v_store(ptrb, b); \
v_store(ptrc, c); \
for( i = i3 = 0; i < v_##_Tpvec::nlanes; i++, i3 += 3 ) \
{ \
ptr[i3] = ptra[i]; \
ptr[i3+1] = ptrb[i]; \
ptr[i3+2] = ptrc[i]; \
} \
} \
inline void v_store_interleave( _Tp* ptr, const v_##_Tpvec& a, const v_##_Tpvec& b, \
const v_##_Tpvec& c, const v_##_Tpvec& d, \
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED ) \
{ \
int i, i4; \
_Tp CV_DECL_ALIGNED(32) ptra[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrb[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrc[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrd[v_##_Tpvec::nlanes] = {0}; \
v_store(ptra, a); \
v_store(ptrb, b); \
v_store(ptrc, c); \
v_store(ptrd, d); \
for( i = i4 = 0; i < v_##_Tpvec::nlanes; i++, i4 += 4 ) \
{ \
ptr[i4] = ptra[i]; \
ptr[i4+1] = ptrb[i]; \
ptr[i4+2] = ptrc[i]; \
ptr[i4+3] = ptrd[i]; \
} \
} \
inline v_##_Tpvec v_interleave_pairs(const v_##_Tpvec& vec) \
{ \
_Tp CV_DECL_ALIGNED(32) ptr[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrvec[v_##_Tpvec::nlanes] = {0}; \
v_store(ptrvec, vec); \
for (int i = 0; i < v_##_Tpvec::nlanes/4; i++) \
{ \
ptr[4*i ] = ptrvec[4*i ]; \
ptr[4*i+1] = ptrvec[4*i+2]; \
ptr[4*i+2] = ptrvec[4*i+1]; \
ptr[4*i+3] = ptrvec[4*i+3]; \
} \
return v_load(ptr); \
} \
inline v_##_Tpvec v_interleave_quads(const v_##_Tpvec& vec) \
{ \
_Tp CV_DECL_ALIGNED(32) ptr[v_##_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrvec[v_##_Tpvec::nlanes] = {0}; \
v_store(ptrvec, vec); \
for (int i = 0; i < v_##_Tpvec::nlanes/8; i++) \
{ \
ptr[8*i ] = ptrvec[4*i ]; \
ptr[8*i+1] = ptrvec[4*i+4]; \
ptr[8*i+2] = ptrvec[4*i+1]; \
ptr[8*i+3] = ptrvec[4*i+5]; \
ptr[8*i+4] = ptrvec[4*i+2]; \
ptr[8*i+5] = ptrvec[4*i+6]; \
ptr[8*i+6] = ptrvec[4*i+3]; \
ptr[8*i+7] = ptrvec[4*i+7]; \
} \
return v_load(ptr); \
}
OPENCV_HAL_IMPL_RVV_INTERLEAVED(uint8x16, uchar, u8, 8)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(int8x16, schar, i8, 8)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(uint16x8, ushort, u16, 16)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(int16x8, short, i16, 16)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(uint32x4, unsigned, u32, 32)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(int32x4, int, i32, 32)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(float32x4, float, f32, 32)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(uint64x2, uint64, u64, 64)
OPENCV_HAL_IMPL_RVV_INTERLEAVED(int64x2, int64, i64, 64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_INTERLEAVED(float64x2, double, f64, 64)
#endif
//////////// PopCount ////////////
static const unsigned char popCountTable[] =
{
@@ -325,1354 +2329,571 @@ static const unsigned char popCountTable[] =
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,
};
template<typename _Tp, int n>
inline v_reg<typename V_TypeTraits<_Tp>::abs_type, n> v_popcount(const v_reg<_Tp, n>& a)
{
v_reg<typename V_TypeTraits<_Tp>::abs_type, n> b = v_reg<typename V_TypeTraits<_Tp>::abs_type, n>::zero();
for (int i = 0; i < n*(int)sizeof(_Tp); i++)
b.s[i/sizeof(_Tp)] += popCountTable[v_reinterpret_as_u8(a).s[i]];
return b;
}
template<typename _Tp, int n>
inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
v_reg<_Tp, n>& minval, v_reg<_Tp, n>& maxval )
{
for( int i = 0; i < n; i++ )
{
minval.s[i] = std::min(a.s[i], b.s[i]);
maxval.s[i] = std::max(a.s[i], b.s[i]);
}
}
#define OPENCV_HAL_IMPL_CMP_OP(cmp_op) \
template<typename _Tp, int n> \
inline v_reg<_Tp, n> operator cmp_op(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
#define OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(_rTpvec, _Tpvec, _rTp, _Tp, suffix) \
inline _rTpvec v_popcount(const _Tpvec& a) \
{ \
typedef typename V_TypeTraits<_Tp>::int_type itype; \
v_reg<_Tp, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = V_TypeTraits<_Tp>::reinterpret_from_int((itype)-(int)(a.s[i] cmp_op b.s[i])); \
return c; \
uchar CV_DECL_ALIGNED(32) ptra[16] = {0}; \
v_store(ptra, v_reinterpret_as_u8(a)); \
_rTp CV_DECL_ALIGNED(32) ptr[_Tpvec::nlanes] = {0}; \
v_store(ptr, v_setzero_##suffix()); \
for (int i = 0; i < _Tpvec::nlanes*(int)sizeof(_Tp); i++) \
ptr[i/sizeof(_Tp)] += popCountTable[ptra[i]]; \
return v_load(ptr); \
}
OPENCV_HAL_IMPL_CMP_OP(<)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint8x16, v_uint8x16, uchar, uchar, u8)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint8x16, v_int8x16, uchar, schar, u8)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint16x8, v_uint16x8, ushort, ushort, u16)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint16x8, v_int16x8, ushort, short, u16)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint32x4, v_uint32x4, unsigned, unsigned, u32)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint32x4, v_int32x4, unsigned, int, u32)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint64x2, v_uint64x2, uint64, uint64, u64)
OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint64x2, v_int64x2, uint64, int64, u64)
OPENCV_HAL_IMPL_CMP_OP(>)
//////////// SignMask ////////////
OPENCV_HAL_IMPL_CMP_OP(<=)
OPENCV_HAL_IMPL_CMP_OP(>=)
OPENCV_HAL_IMPL_CMP_OP(==)
OPENCV_HAL_IMPL_CMP_OP(!=)
template<int n>
inline v_reg<float, n> v_not_nan(const v_reg<float, n>& a)
{
typedef typename V_TypeTraits<float>::int_type itype;
v_reg<float, n> c;
for (int i = 0; i < n; i++)
c.s[i] = V_TypeTraits<float>::reinterpret_from_int((itype)-(int)(a.s[i] == a.s[i]));
return c;
}
template<int n>
inline v_reg<double, n> v_not_nan(const v_reg<double, n>& a)
{
typedef typename V_TypeTraits<double>::int_type itype;
v_reg<double, n> c;
for (int i = 0; i < n; i++)
c.s[i] = V_TypeTraits<double>::reinterpret_from_int((itype)-(int)(a.s[i] == a.s[i]));
return c;
}
#define OPENCV_HAL_IMPL_ARITHM_OP(func, bin_op, cast_op, _Tp2) \
template<typename _Tp, int n> \
inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
#define OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(_Tpvec, _Tp, suffix, width, shift) \
inline int v_signmask(const _Tpvec& a) \
{ \
typedef _Tp2 rtype; \
v_reg<rtype, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = cast_op(a.s[i] bin_op b.s[i]); \
return c; \
int mask = 0; \
vsetvlmax_e##width##m1(); \
_Tpvec tmp = _Tpvec(vsrl_vx_##suffix##m1(a, shift)); \
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
mask |= (int)(tmp.val[i]) << i; \
return mask; \
}
OPENCV_HAL_IMPL_ARITHM_OP(v_add_wrap, +, (_Tp), _Tp)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_uint8x16, uchar, u8, 8, 7)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_uint16x8, ushort, u16, 16, 15)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_uint32x4, unsigned, u32, 32, 31)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_uint64x2, uint64, u64, 64, 63)
OPENCV_HAL_IMPL_ARITHM_OP(v_sub_wrap, -, (_Tp), _Tp)
inline int v_signmask(const v_int8x16& a)
{ return v_signmask(v_reinterpret_as_u8(a)); }
inline int v_signmask(const v_int16x8& a)
{ return v_signmask(v_reinterpret_as_u16(a)); }
inline int v_signmask(const v_int32x4& a)
{ return v_signmask(v_reinterpret_as_u32(a)); }
inline int v_signmask(const v_float32x4& a)
{ return v_signmask(v_reinterpret_as_u32(a)); }
inline int v_signmask(const v_int64x2& a)
{ return v_signmask(v_reinterpret_as_u64(a)); }
#if CV_SIMD128_64F
inline int v_signmask(const v_float64x2& a)
{ return v_signmask(v_reinterpret_as_u64(a)); }
#endif
OPENCV_HAL_IMPL_ARITHM_OP(v_mul_wrap, *, (_Tp), _Tp)
template<typename T> inline T _absdiff(T a, T b)
{
return a > b ? a - b : b - a;
}
//////////// Scan forward ////////////
template<typename _Tp, int n>
inline v_reg<typename V_TypeTraits<_Tp>::abs_type, n> v_absdiff(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> & b)
{
typedef typename V_TypeTraits<_Tp>::abs_type rtype;
v_reg<rtype, n> c;
const rtype mask = (rtype)(std::numeric_limits<_Tp>::is_signed ? (1 << (sizeof(rtype)*8 - 1)) : 0);
for( int i = 0; i < n; i++ )
{
rtype ua = a.s[i] ^ mask;
rtype ub = b.s[i] ^ mask;
c.s[i] = _absdiff(ua, ub);
}
return c;
}
inline v_float32x4 v_absdiff(const v_float32x4& a, const v_float32x4& b)
{
v_float32x4 c;
for( int i = 0; i < c.nlanes; i++ )
c.s[i] = _absdiff(a.s[i], b.s[i]);
return c;
}
inline v_float64x2 v_absdiff(const v_float64x2& a, const v_float64x2& b)
{
v_float64x2 c;
for( int i = 0; i < c.nlanes; i++ )
c.s[i] = _absdiff(a.s[i], b.s[i]);
return c;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_absdiffs(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++)
c.s[i] = saturate_cast<_Tp>(std::abs(a.s[i] - b.s[i]));
return c;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_invsqrt(const v_reg<_Tp, n>& a)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = 1.f/std::sqrt(a.s[i]);
return c;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = std::sqrt(a.s[i]*a.s[i] + b.s[i]*b.s[i]);
return c;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_sqr_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = a.s[i]*a.s[i] + b.s[i]*b.s[i];
return c;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_fma(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<_Tp, n>& c)
{
v_reg<_Tp, n> d;
for( int i = 0; i < n; i++ )
d.s[i] = a.s[i]*b.s[i] + c.s[i];
return d;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<_Tp, n>& c)
{
return v_fma(a, b, c);
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
v_reg<w_type, n/2> c;
for( int i = 0; i < (n/2); i++ )
c.s[i] = (w_type)a.s[i*2]*b.s[i*2] + (w_type)a.s[i*2+1]*b.s[i*2+1];
return c;
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::w_type, n / 2>& c)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
v_reg<w_type, n/2> s;
for( int i = 0; i < (n/2); i++ )
s.s[i] = (w_type)a.s[i*2]*b.s[i*2] + (w_type)a.s[i*2+1]*b.s[i*2+1] + c.s[i];
return s;
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{ return v_dotprod(a, b); }
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_dotprod_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::w_type, n / 2>& c)
{ return v_dotprod(a, b, c); }
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
typedef typename V_TypeTraits<_Tp>::q_type q_type;
v_reg<q_type, n/4> s;
for( int i = 0; i < (n/4); i++ )
s.s[i] = (q_type)a.s[i*4 ]*b.s[i*4 ] + (q_type)a.s[i*4 + 1]*b.s[i*4 + 1] +
(q_type)a.s[i*4 + 2]*b.s[i*4 + 2] + (q_type)a.s[i*4 + 3]*b.s[i*4 + 3];
return s;
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::q_type, n / 4>& c)
{
typedef typename V_TypeTraits<_Tp>::q_type q_type;
v_reg<q_type, n/4> s;
for( int i = 0; i < (n/4); i++ )
s.s[i] = (q_type)a.s[i*4 ]*b.s[i*4 ] + (q_type)a.s[i*4 + 1]*b.s[i*4 + 1] +
(q_type)a.s[i*4 + 2]*b.s[i*4 + 2] + (q_type)a.s[i*4 + 3]*b.s[i*4 + 3] + c.s[i];
return s;
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{ return v_dotprod_expand(a, b); }
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::q_type, n/4>
v_dotprod_expand_fast(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
const v_reg<typename V_TypeTraits<_Tp>::q_type, n / 4>& c)
{ return v_dotprod_expand(a, b, c); }
template<typename _Tp, int n> inline void v_mul_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>& c,
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>& d)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
for( int i = 0; i < (n/2); i++ )
{
c.s[i] = (w_type)a.s[i]*b.s[i];
d.s[i] = (w_type)a.s[i+(n/2)]*b.s[i+(n/2)];
}
}
template<typename _Tp, int n> inline v_reg<_Tp, n> v_mul_hi(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
v_reg<_Tp, n> c;
for (int i = 0; i < n; i++)
c.s[i] = (_Tp)(((w_type)a.s[i] * b.s[i]) >> sizeof(_Tp)*8);
return c;
}
template<typename _Tp, int n> inline void v_hsum(const v_reg<_Tp, n>& a,
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>& c)
{
typedef typename V_TypeTraits<_Tp>::w_type w_type;
for( int i = 0; i < (n/2); i++ )
{
c.s[i] = (w_type)a.s[i*2] + a.s[i*2+1];
}
}
#define OPENCV_HAL_IMPL_SHIFT_OP(shift_op) \
template<typename _Tp, int n> inline v_reg<_Tp, n> operator shift_op(const v_reg<_Tp, n>& a, int imm) \
#define OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(_Tpvec, _Tp, suffix) \
inline int v_scan_forward(const _Tpvec& a) \
{ \
v_reg<_Tp, n> c; \
for( int i = 0; i < n; i++ ) \
c.s[i] = (_Tp)(a.s[i] shift_op imm); \
return c; \
_Tp CV_DECL_ALIGNED(32) ptr[_Tpvec::nlanes] = {0}; \
v_store(ptr, v_reinterpret_as_##suffix(a)); \
for (int i = 0; i < _Tpvec::nlanes; i++) \
if(int(ptr[i]) < 0) \
return i; \
return 0; \
}
OPENCV_HAL_IMPL_SHIFT_OP(<< )
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_uint8x16, uchar, u8)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_int8x16, schar, s8)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_uint16x8, ushort, u16)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_int16x8, short, s16)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_uint32x4, unsigned, u32)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_int32x4, int, s32)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_float32x4, float, f32)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_uint64x2, uint64, u64)
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_int64x2, int64, s64)
#if CV_SIMD128_64F
OPENCV_HAL_IMPL_RVV_SCAN_FORWOARD_OP(v_float64x2, double, f64)
#endif
OPENCV_HAL_IMPL_SHIFT_OP(>> )
//////////// Pack triplets ////////////
#define OPENCV_HAL_IMPL_ROTATE_SHIFT_OP(suffix,opA,opB) \
template<int imm, typename _Tp, int n> inline v_reg<_Tp, n> v_rotate_##suffix(const v_reg<_Tp, n>& a) \
#define OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(_Tpvec, _Tp) \
inline _Tpvec v_pack_triplets(const _Tpvec& vec) \
{ \
v_reg<_Tp, n> b; \
for (int i = 0; i < n; i++) \
_Tp CV_DECL_ALIGNED(32) ptr[_Tpvec::nlanes] = {0}; \
_Tp CV_DECL_ALIGNED(32) ptrvec[_Tpvec::nlanes] = {0}; \
v_store(ptrvec, vec); \
for (int i = 0; i < _Tpvec::nlanes/4; i++) \
{ \
int sIndex = i opA imm; \
if (0 <= sIndex && sIndex < n) \
{ \
b.s[i] = a.s[sIndex]; \
} \
else \
{ \
b.s[i] = 0; \
} \
ptr[3*i ] = ptrvec[4*i ]; \
ptr[3*i+1] = ptrvec[4*i+2]; \
ptr[3*i+2] = ptrvec[4*i+2]; \
} \
return b; \
} \
template<int imm, typename _Tp, int n> inline v_reg<_Tp, n> v_rotate_##suffix(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \
{ \
v_reg<_Tp, n> c; \
for (int i = 0; i < n; i++) \
{ \
int aIndex = i opA imm; \
int bIndex = i opA imm opB n; \
if (0 <= bIndex && bIndex < n) \
{ \
c.s[i] = b.s[bIndex]; \
} \
else if (0 <= aIndex && aIndex < n) \
{ \
c.s[i] = a.s[aIndex]; \
} \
else \
{ \
c.s[i] = 0; \
} \
} \
return c; \
return v_load(ptr); \
}
OPENCV_HAL_IMPL_ROTATE_SHIFT_OP(left, -, +)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_uint8x16, uchar)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_int8x16, schar)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_uint16x8, ushort)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_int16x8, short)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_uint32x4, unsigned)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_int32x4, int)
OPENCV_HAL_IMPL_RVV_PACK_TRIPLETS(v_float32x4, float)
OPENCV_HAL_IMPL_ROTATE_SHIFT_OP(right, +, -)
template<typename _Tp, int n> inline typename V_TypeTraits<_Tp>::sum_type v_reduce_sum(const v_reg<_Tp, n>& a)
////// FP16 support ///////
#if CV_FP16
inline v_float32x4 v_load_expand(const float16_t* ptr)
{
typename V_TypeTraits<_Tp>::sum_type c = a.s[0];
for( int i = 1; i < n; i++ )
c += a.s[i];
return c;
return v_float32x4(vfwcvt_f_f_v_f32m1(vle16_v_f16mf2(ptr)));
}
inline v_float32x4 v_reduce_sum4(const v_float32x4& a, const v_float32x4& b,
const v_float32x4& c, const v_float32x4& d)
inline void v_pack_store(float16_t* ptr, const v_float32x4& v)
{
v_float32x4 r;
r.s[0] = a.s[0] + a.s[1] + a.s[2] + a.s[3];
r.s[1] = b.s[0] + b.s[1] + b.s[2] + b.s[3];
r.s[2] = c.s[0] + c.s[1] + c.s[2] + c.s[3];
r.s[3] = d.s[0] + d.s[1] + d.s[2] + d.s[3];
return r;
vse16_v_f16mf2(ptr, vfncvt_f_f_w_f16mf2(v));
}
#else
inline v_float32x4 v_load_expand(const float16_t* ptr)
{
const int N = 4;
float buf[N];
for( int i = 0; i < N; i++ ) buf[i] = (float)ptr[i];
return v_load(buf);
}
template<typename _Tp, int n> inline typename V_TypeTraits< typename V_TypeTraits<_Tp>::abs_type >::sum_type v_reduce_sad(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
inline void v_pack_store(float16_t* ptr, const v_float32x4& v)
{
typename V_TypeTraits< typename V_TypeTraits<_Tp>::abs_type >::sum_type c = _absdiff(a.s[0], b.s[0]);
for (int i = 1; i < n; i++)
c += _absdiff(a.s[i], b.s[i]);
return c;
const int N = 4;
float buf[N];
v_store(buf, v);
for( int i = 0; i < N; i++ ) ptr[i] = float16_t(buf[i]);
}
template<typename _Tp, int n> inline int v_signmask(const v_reg<_Tp, n>& a)
{
int mask = 0;
for( int i = 0; i < n; i++ )
mask |= (V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) < 0) << i;
return mask;
}
template <typename _Tp, int n> inline int v_scan_forward(const v_reg<_Tp, n>& a)
{
for (int i = 0; i < n; i++)
if(V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) < 0)
return i;
return 0;
}
template<typename _Tp, int n> inline bool v_check_all(const v_reg<_Tp, n>& a)
{
for( int i = 0; i < n; i++ )
if( V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) >= 0 )
return false;
return true;
}
template<typename _Tp, int n> inline bool v_check_any(const v_reg<_Tp, n>& a)
{
for( int i = 0; i < n; i++ )
if( V_TypeTraits<_Tp>::reinterpret_int(a.s[i]) < 0 )
return true;
return false;
}
template<typename _Tp, int n> inline v_reg<_Tp, n> v_select(const v_reg<_Tp, n>& mask,
const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
typedef V_TypeTraits<_Tp> Traits;
typedef typename Traits::int_type int_type;
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
{
int_type m = Traits::reinterpret_int(mask.s[i]);
CV_DbgAssert(m == 0 || m == (~(int_type)0)); // restrict mask values: 0 or 0xff/0xffff/etc
c.s[i] = m ? a.s[i] : b.s[i];
}
return c;
}
template<typename _Tp, int n> inline void v_expand(const v_reg<_Tp, n>& a,
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>& b0,
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>& b1)
{
for( int i = 0; i < (n/2); i++ )
{
b0.s[i] = a.s[i];
b1.s[i] = a.s[i+(n/2)];
}
}
template<typename _Tp, int n>
inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_expand_low(const v_reg<_Tp, n>& a)
{
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2> b;
for( int i = 0; i < (n/2); i++ )
b.s[i] = a.s[i];
return b;
}
template<typename _Tp, int n>
inline v_reg<typename V_TypeTraits<_Tp>::w_type, n/2>
v_expand_high(const v_reg<_Tp, n>& a)
{
v_reg<typename V_TypeTraits<_Tp>::w_type, n/2> b;
for( int i = 0; i < (n/2); i++ )
b.s[i] = a.s[i+(n/2)];
return b;
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::int_type, n>
v_reinterpret_as_int(const v_reg<_Tp, n>& a)
{
v_reg<typename V_TypeTraits<_Tp>::int_type, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = V_TypeTraits<_Tp>::reinterpret_int(a.s[i]);
return c;
}
template<typename _Tp, int n> inline v_reg<typename V_TypeTraits<_Tp>::uint_type, n>
v_reinterpret_as_uint(const v_reg<_Tp, n>& a)
{
v_reg<typename V_TypeTraits<_Tp>::uint_type, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = V_TypeTraits<_Tp>::reinterpret_uint(a.s[i]);
return c;
}
template<typename _Tp, int n> inline void v_zip( const v_reg<_Tp, n>& a0, const v_reg<_Tp, n>& a1,
v_reg<_Tp, n>& b0, v_reg<_Tp, n>& b1 )
{
int i;
for( i = 0; i < n/2; i++ )
{
b0.s[i*2] = a0.s[i];
b0.s[i*2+1] = a1.s[i];
}
for( ; i < n; i++ )
{
b1.s[i*2-n] = a0.s[i];
b1.s[i*2-n+1] = a1.s[i];
}
}
template<typename _Tp>
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load(const _Tp* ptr)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
return v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128>(ptr);
////////////// Rounding //////////////
inline v_int32x4 v_round(const v_float32x4& a)
{
vsetvlmax_e32m1();
return v_int32x4(vfcvt_x_f_v_i32m1(a));
}
template<typename _Tp>
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_aligned(const _Tp* ptr)
inline v_int32x4 v_floor(const v_float32x4& a)
{
CV_Assert(isAligned<sizeof(v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128>)>(ptr));
return v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128>(ptr);
v_float32x4 ZP5 = v_setall_f32(0.5f);
v_float32x4 t = a - ZP5;
vsetvlmax_e32m1();
return v_int32x4(vfcvt_x_f_v_i32m1(t));
}
template<typename _Tp>
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_low(const _Tp* ptr)
inline v_int32x4 v_ceil(const v_float32x4& a)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
v_float32x4 ZP5 = v_setall_f32(0.5f);
v_float32x4 t = a + ZP5;
vsetvlmax_e32m1();
return v_int32x4(vfcvt_x_f_v_i32m1(t));
}
inline v_int32x4 v_trunc(const v_float32x4& a)
{
vsetvlmax_e32m1();
return v_int32x4(vfcvt_rtz_x_f_v_i32m1(a));
}
#if CV_SIMD128_64F
inline v_int32x4 v_round(const v_float64x2& a)
{
double arr[4] = {a.val[0], a.val[1], 0, 0};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
return v_int32x4(vfncvt_x_f_w_i32m1(tmp));
}
inline v_int32x4 v_round(const v_float64x2& a, const v_float64x2& b)
{
double arr[4] = {a.val[0], a.val[1], b.val[0], b.val[1]};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
return v_int32x4(vfncvt_x_f_w_i32m1(tmp));
}
inline v_int32x4 v_floor(const v_float64x2& a)
{
double arr[4] = {a.val[0]-0.5f, a.val[1]-0.5f, 0, 0};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
return v_int32x4(vfncvt_x_f_w_i32m1(tmp));
}
inline v_int32x4 v_ceil(const v_float64x2& a)
{
double arr[4] = {a.val[0]+0.5f, a.val[1]+0.5f, 0, 0};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
return v_int32x4(vfncvt_x_f_w_i32m1(tmp));
}
inline v_int32x4 v_trunc(const v_float64x2& a)
{
double arr[4] = {a.val[0], a.val[1], 0, 0};
vsetvlmax_e64m2();
vfloat64m2_t tmp = vle64_v_f64m2(arr);
return v_int32x4(vfncvt_rtz_x_f_w_i32m1(tmp));
}
#endif
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
for( int i = 0; i < c.nlanes/2; i++ )
{
c.s[i] = ptr[i];
}
return c;
//////// Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b)
{
int CV_DECL_ALIGNED(32) ptr[8] = {0};
v_int32x4 t1, t2;
vsetvlmax_e32m2();
vse32_v_i32m2(ptr, vwmul_vv_i32m2(a, b));
v_load_deinterleave(ptr, t1, t2);
return t1 + t2;
}
inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{
int CV_DECL_ALIGNED(32) ptr[8] = {0};
v_int32x4 t1, t2;
vsetvlmax_e32m2();
vse32_v_i32m2(ptr, vwmul_vv_i32m2(a, b));
v_load_deinterleave(ptr, t1, t2);
return t1 + t2 + c;
}
template<typename _Tp>
inline v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> v_load_halves(const _Tp* loptr, const _Tp* hiptr)
// 32 >> 64
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(loptr));
CV_Assert(isAligned<sizeof(_Tp)>(hiptr));
int64 CV_DECL_ALIGNED(32) ptr[4] = {0};
v_int64x2 t1, t2;
vsetvlmax_e64m2();
vse64_v_i64m2(ptr, vwmul_vv_i64m2(a, b));
v_load_deinterleave(ptr, t1, t2);
return t1 + t2;
}
inline v_int64x2 v_dotprod(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{
int64 CV_DECL_ALIGNED(32) ptr[4] = {0};
v_int64x2 t1, t2;
vsetvlmax_e64m2();
vse64_v_i64m2(ptr, vwmul_vv_i64m2(a, b));
v_load_deinterleave(ptr, t1, t2);
return t1 + t2 + c;
}
// 8 >> 32
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b)
{
unsigned CV_DECL_ALIGNED(32) ptr[16] = {0};
v_uint32x4 t1, t2, t3, t4;
vsetvlmax_e32m4();
vse32_v_u32m4(ptr, vqmaccu_vv_u32m4(vzero_u32m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4;
}
inline v_uint32x4 v_dotprod_expand(const v_uint8x16& a, const v_uint8x16& b,
const v_uint32x4& c)
{
unsigned CV_DECL_ALIGNED(32) ptr[16] = {0};
v_uint32x4 t1, t2, t3, t4;
vsetvlmax_e32m4();
vse32_v_u32m4(ptr, vqmaccu_vv_u32m4(vzero_u32m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4 + c;
}
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b)
{
int CV_DECL_ALIGNED(32) ptr[16] = {0};
v_int32x4 t1, t2, t3, t4;
vsetvlmax_e32m4();
vse32_v_i32m4(ptr, vqmacc_vv_i32m4(vzero_i32m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4;
}
inline v_int32x4 v_dotprod_expand(const v_int8x16& a, const v_int8x16& b,
const v_int32x4& c)
{
int CV_DECL_ALIGNED(32) ptr[16] = {0};
v_int32x4 t1, t2, t3, t4;
vsetvlmax_e32m4();
vse32_v_i32m4(ptr, vqmacc_vv_i32m4(vzero_i32m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4 + c;
}
// 16 >> 64
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b)
{
uint64 CV_DECL_ALIGNED(32) ptr[8] = {0};
v_uint64x2 t1, t2, t3, t4;
vsetvlmax_e64m4();
vse64_v_u64m4(ptr, vqmaccu_vv_u64m4(vzero_u64m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4;
}
inline v_uint64x2 v_dotprod_expand(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{
uint64 CV_DECL_ALIGNED(32) ptr[8] = {0};
v_uint64x2 t1, t2, t3, t4;
vsetvlmax_e64m4();
vse64_v_u64m4(ptr, vqmaccu_vv_u64m4(vzero_u64m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4 + c;
}
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b)
{
int64 CV_DECL_ALIGNED(32) ptr[8] = {0};
v_int64x2 t1, t2, t3, t4;
vsetvlmax_e64m4();
vse64_v_i64m4(ptr, vqmacc_vv_i64m4(vzero_i64m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4;
}
inline v_int64x2 v_dotprod_expand(const v_int16x8& a, const v_int16x8& b,
const v_int64x2& c)
{
int64 CV_DECL_ALIGNED(32) ptr[8] = {0};
v_int64x2 t1, t2, t3, t4;
vsetvlmax_e64m4();
vse64_v_i64m4(ptr, vqmacc_vv_i64m4(vzero_i64m4(), a, b));
v_load_deinterleave(ptr, t1, t2, t3, t4);
return t1 + t2 + t3 + t4 + c;
}
// 32 >> 64f
#if CV_SIMD128_64F
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b)
{ return v_cvt_f64(v_dotprod(a, b)); }
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b,
const v_float64x2& c)
{ return v_dotprod_expand(a, b) + c; }
#endif
v_reg<_Tp, V_TypeTraits<_Tp>::nlanes128> c;
for( int i = 0; i < c.nlanes/2; i++ )
{
c.s[i] = loptr[i];
c.s[i+c.nlanes/2] = hiptr[i];
}
return c;
//////// Fast Dot Product ////////
// 16 >> 32
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b)
{
int CV_DECL_ALIGNED(32) ptr[8] = {0};
vsetvlmax_e32m2();
vse32_v_i32m2(ptr, vwmul_vv_i32m2(a, b));
v_int32x4 t1 = v_load(ptr);
v_int32x4 t2 = v_load(ptr+4);
return t1 + t2;
}
inline v_int32x4 v_dotprod_fast(const v_int16x8& a, const v_int16x8& b, const v_int32x4& c)
{
int CV_DECL_ALIGNED(32) ptr[8] = {0};
vsetvlmax_e32m2();
vse32_v_i32m2(ptr, vwmul_vv_i32m2(a, b));
v_int32x4 t1 = v_load(ptr);
v_int32x4 t2 = v_load(ptr+4);
return t1 + t2 + c;
}
template<typename _Tp>
inline v_reg<typename V_TypeTraits<_Tp>::w_type, V_TypeTraits<_Tp>::nlanes128 / 2>
v_load_expand(const _Tp* ptr)
// 32 >> 64
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
int64 CV_DECL_ALIGNED(32) ptr[4] = {0};
vsetvlmax_e64m2();
vse64_v_i64m2(ptr, vwmul_vv_i64m2(a, b));
v_int64x2 t1 = v_load(ptr);
v_int64x2 t2 = v_load(ptr+2);
return t1 + t2;
}
inline v_int64x2 v_dotprod_fast(const v_int32x4& a, const v_int32x4& b, const v_int64x2& c)
{
int64 CV_DECL_ALIGNED(32) ptr[4] = {0};
vsetvlmax_e64m2();
vse64_v_i64m2(ptr, vwmul_vv_i64m2(a, b));
v_int64x2 t1 = v_load(ptr);
v_int64x2 t2 = v_load(ptr+2);
return t1 + t2 + c;
}
// 8 >> 32
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b)
{
unsigned CV_DECL_ALIGNED(32) ptr[16] = {0};
vsetvlmax_e32m4();
vse32_v_u32m4(ptr, vqmaccu_vv_u32m4(vzero_u32m4(), a, b));
v_uint32x4 t1 = v_load(ptr);
v_uint32x4 t2 = v_load(ptr+4);
v_uint32x4 t3 = v_load(ptr+8);
v_uint32x4 t4 = v_load(ptr+12);
return t1 + t2 + t3 + t4;
}
inline v_uint32x4 v_dotprod_expand_fast(const v_uint8x16& a, const v_uint8x16& b, const v_uint32x4& c)
{
unsigned CV_DECL_ALIGNED(32) ptr[16] = {0};
vsetvlmax_e32m4();
vse32_v_u32m4(ptr, vqmaccu_vv_u32m4(vzero_u32m4(), a, b));
v_uint32x4 t1 = v_load(ptr);
v_uint32x4 t2 = v_load(ptr+4);
v_uint32x4 t3 = v_load(ptr+8);
v_uint32x4 t4 = v_load(ptr+12);
return t1 + t2 + t3 + t4 + c;
}
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b)
{
int CV_DECL_ALIGNED(32) ptr[16] = {0};
vsetvlmax_e32m4();
vse32_v_i32m4(ptr, vqmacc_vv_i32m4(vzero_i32m4(), a, b));
v_int32x4 t1 = v_load(ptr);
v_int32x4 t2 = v_load(ptr+4);
v_int32x4 t3 = v_load(ptr+8);
v_int32x4 t4 = v_load(ptr+12);
return t1 + t2 + t3 + t4;
}
inline v_int32x4 v_dotprod_expand_fast(const v_int8x16& a, const v_int8x16& b, const v_int32x4& c)
{
int CV_DECL_ALIGNED(32) ptr[16] = {0};
vsetvlmax_e32m4();
vse32_v_i32m4(ptr, vqmacc_vv_i32m4(vzero_i32m4(), a, b));
v_int32x4 t1 = v_load(ptr);
v_int32x4 t2 = v_load(ptr+4);
v_int32x4 t3 = v_load(ptr+8);
v_int32x4 t4 = v_load(ptr+12);
return t1 + t2 + t3 + t4 + c;
}
// 16 >> 64
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b)
{
uint64 CV_DECL_ALIGNED(32) ptr[8] = {0};
vsetvlmax_e64m4();
vse64_v_u64m4(ptr, vqmaccu_vv_u64m4(vzero_u64m4(), a, b));
v_uint64x2 t1 = v_load(ptr);
v_uint64x2 t2 = v_load(ptr+2);
v_uint64x2 t3 = v_load(ptr+4);
v_uint64x2 t4 = v_load(ptr+6);
return t1 + t2 + t3 + t4;
}
inline v_uint64x2 v_dotprod_expand_fast(const v_uint16x8& a, const v_uint16x8& b, const v_uint64x2& c)
{
uint64 CV_DECL_ALIGNED(32) ptr[8] = {0};
vsetvlmax_e64m4();
vse64_v_u64m4(ptr, vqmaccu_vv_u64m4(vzero_u64m4(), a, b));
v_uint64x2 t1 = v_load(ptr);
v_uint64x2 t2 = v_load(ptr+2);
v_uint64x2 t3 = v_load(ptr+4);
v_uint64x2 t4 = v_load(ptr+6);
return t1 + t2 + t3 + t4 + c;
}
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b)
{
int64 CV_DECL_ALIGNED(32) ptr[8] = {0};
vsetvlmax_e64m4();
vse64_v_i64m4(ptr, vqmacc_vv_i64m4(vzero_i64m4(), a, b));
v_int64x2 t1 = v_load(ptr);
v_int64x2 t2 = v_load(ptr+2);
v_int64x2 t3 = v_load(ptr+4);
v_int64x2 t4 = v_load(ptr+6);
return t1 + t2 + t3 + t4;
}
inline v_int64x2 v_dotprod_expand_fast(const v_int16x8& a, const v_int16x8& b, const v_int64x2& c)
{
int64 CV_DECL_ALIGNED(32) ptr[8] = {0};
vsetvlmax_e64m4();
vse64_v_i64m4(ptr, vqmacc_vv_i64m4(vzero_i64m4(), a, b));
v_int64x2 t1 = v_load(ptr);
v_int64x2 t2 = v_load(ptr+2);
v_int64x2 t3 = v_load(ptr+4);
v_int64x2 t4 = v_load(ptr+6);
return t1 + t2 + t3 + t4 + c;
}
// 32 >> 64f
#if CV_SIMD128_64F
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_cvt_f64(v_dotprod_fast(a, b)); }
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_dotprod_expand_fast(a, b) + c; }
#endif
typedef typename V_TypeTraits<_Tp>::w_type w_type;
v_reg<w_type, V_TypeTraits<w_type>::nlanes128> c;
for( int i = 0; i < c.nlanes; i++ )
{
c.s[i] = ptr[i];
}
return c;
}
template<typename _Tp>
inline v_reg<typename V_TypeTraits<_Tp>::q_type, V_TypeTraits<_Tp>::nlanes128 / 4>
v_load_expand_q(const _Tp* ptr)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
typedef typename V_TypeTraits<_Tp>::q_type q_type;
v_reg<q_type, V_TypeTraits<q_type>::nlanes128> c;
for( int i = 0; i < c.nlanes; i++ )
{
c.s[i] = ptr[i];
}
return c;
}
template<typename _Tp, int n> inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
v_reg<_Tp, n>& b)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
int i, i2;
for( i = i2 = 0; i < n; i++, i2 += 2 )
{
a.s[i] = ptr[i2];
b.s[i] = ptr[i2+1];
}
}
template<typename _Tp, int n> inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
v_reg<_Tp, n>& b, v_reg<_Tp, n>& c)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
int i, i3;
for( i = i3 = 0; i < n; i++, i3 += 3 )
{
a.s[i] = ptr[i3];
b.s[i] = ptr[i3+1];
c.s[i] = ptr[i3+2];
}
}
template<typename _Tp, int n>
inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a,
v_reg<_Tp, n>& b, v_reg<_Tp, n>& c,
v_reg<_Tp, n>& d)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
int i, i4;
for( i = i4 = 0; i < n; i++, i4 += 4 )
{
a.s[i] = ptr[i4];
b.s[i] = ptr[i4+1];
c.s[i] = ptr[i4+2];
d.s[i] = ptr[i4+3];
}
}
template<typename _Tp, int n>
inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
const v_reg<_Tp, n>& b,
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
int i, i2;
for( i = i2 = 0; i < n; i++, i2 += 2 )
{
ptr[i2] = a.s[i];
ptr[i2+1] = b.s[i];
}
}
template<typename _Tp, int n>
inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c,
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
int i, i3;
for( i = i3 = 0; i < n; i++, i3 += 3 )
{
ptr[i3] = a.s[i];
ptr[i3+1] = b.s[i];
ptr[i3+2] = c.s[i];
}
}
template<typename _Tp, int n> inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a,
const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c,
const v_reg<_Tp, n>& d,
hal::StoreMode /*mode*/=hal::STORE_UNALIGNED)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
int i, i4;
for( i = i4 = 0; i < n; i++, i4 += 4 )
{
ptr[i4] = a.s[i];
ptr[i4+1] = b.s[i];
ptr[i4+2] = c.s[i];
ptr[i4+3] = d.s[i];
}
}
template<typename _Tp, int n>
inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
for( int i = 0; i < n; i++ )
ptr[i] = a.s[i];
}
template<typename _Tp, int n>
inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a, hal::StoreMode /*mode*/)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
v_store(ptr, a);
}
template<typename _Tp, int n>
inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
for( int i = 0; i < (n/2); i++ )
ptr[i] = a.s[i];
}
template<typename _Tp, int n>
inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a)
{
#if CV_STRONG_ALIGNMENT
CV_Assert(isAligned<sizeof(_Tp)>(ptr));
#endif
for( int i = 0; i < (n/2); i++ )
ptr[i] = a.s[i+(n/2)];
}
template<typename _Tp, int n>
inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a)
{
CV_Assert(isAligned<sizeof(v_reg<_Tp, n>)>(ptr));
v_store(ptr, a);
}
template<typename _Tp, int n>
inline void v_store_aligned_nocache(_Tp* ptr, const v_reg<_Tp, n>& a)
{
CV_Assert(isAligned<sizeof(v_reg<_Tp, n>)>(ptr));
v_store(ptr, a);
}
template<typename _Tp, int n>
inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a, hal::StoreMode /*mode*/)
{
CV_Assert(isAligned<sizeof(v_reg<_Tp, n>)>(ptr));
v_store(ptr, a);
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_combine_low(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
v_reg<_Tp, n> c;
for( int i = 0; i < (n/2); i++ )
{
c.s[i] = a.s[i];
c.s[i+(n/2)] = b.s[i];
}
return c;
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_combine_high(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
v_reg<_Tp, n> c;
for( int i = 0; i < (n/2); i++ )
{
c.s[i] = a.s[i+(n/2)];
c.s[i+(n/2)] = b.s[i+(n/2)];
}
return c;
}
template<typename _Tp, int n>
inline void v_recombine(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b,
v_reg<_Tp, n>& low, v_reg<_Tp, n>& high)
{
for( int i = 0; i < (n/2); i++ )
{
low.s[i] = a.s[i];
low.s[i+(n/2)] = b.s[i];
high.s[i] = a.s[i+(n/2)];
high.s[i+(n/2)] = b.s[i+(n/2)];
}
}
template<typename _Tp, int n>
inline v_reg<_Tp, n> v_reverse(const v_reg<_Tp, n>& a)
{
v_reg<_Tp, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = a.s[n-i-1];
return c;
}
template<int s, typename _Tp, int n>
inline v_reg<_Tp, n> v_extract(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
v_reg<_Tp, n> r;
const int shift = n - s;
int i = 0;
for (; i < shift; ++i)
r.s[i] = a.s[i+s];
for (; i < n; ++i)
r.s[i] = b.s[i-shift];
return r;
}
template<int s, typename _Tp, int n>
inline _Tp v_extract_n(const v_reg<_Tp, n>& v)
{
CV_DbgAssert(s >= 0 && s < n);
return v.s[s];
}
template<int i, typename _Tp, int n>
inline v_reg<_Tp, n> v_broadcast_element(const v_reg<_Tp, n>& a)
{
CV_DbgAssert(i >= 0 && i < n);
return v_reg<_Tp, n>::all(a.s[i]);
}
template<int n> inline v_reg<int, n> v_round(const v_reg<float, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = cvRound(a.s[i]);
return c;
}
template<int n> inline v_reg<int, n*2> v_round(const v_reg<double, n>& a, const v_reg<double, n>& b)
{
v_reg<int, n*2> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = cvRound(a.s[i]);
c.s[i+n] = cvRound(b.s[i]);
}
return c;
}
template<int n> inline v_reg<int, n> v_floor(const v_reg<float, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = cvFloor(a.s[i]);
return c;
}
template<int n> inline v_reg<int, n> v_ceil(const v_reg<float, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = cvCeil(a.s[i]);
return c;
}
template<int n> inline v_reg<int, n> v_trunc(const v_reg<float, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (int)(a.s[i]);
return c;
}
template<int n> inline v_reg<int, n*2> v_round(const v_reg<double, n>& a)
{
v_reg<int, n*2> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = cvRound(a.s[i]);
c.s[i+n] = 0;
}
return c;
}
template<int n> inline v_reg<int, n*2> v_floor(const v_reg<double, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = cvFloor(a.s[i]);
c.s[i+n] = 0;
}
return c;
}
template<int n> inline v_reg<int, n*2> v_ceil(const v_reg<double, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = cvCeil(a.s[i]);
c.s[i+n] = 0;
}
return c;
}
template<int n> inline v_reg<int, n*2> v_trunc(const v_reg<double, n>& a)
{
v_reg<int, n> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = cvCeil(a.s[i]);
c.s[i+n] = 0;
}
return c;
}
template<int n> inline v_reg<float, n> v_cvt_f32(const v_reg<int, n>& a)
{
v_reg<float, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (float)a.s[i];
return c;
}
template<int n> inline v_reg<float, n*2> v_cvt_f32(const v_reg<double, n>& a)
{
v_reg<float, n*2> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = (float)a.s[i];
c.s[i+n] = 0;
}
return c;
}
template<int n> inline v_reg<float, n*2> v_cvt_f32(const v_reg<double, n>& a, const v_reg<double, n>& b)
{
v_reg<float, n*2> c;
for( int i = 0; i < n; i++ )
{
c.s[i] = (float)a.s[i];
c.s[i+n] = (float)b.s[i];
}
return c;
}
CV_INLINE v_reg<double, 2> v_cvt_f64(const v_reg<int, 4>& a)
{
enum { n = 2 };
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i];
return c;
}
CV_INLINE v_reg<double, 2> v_cvt_f64_high(const v_reg<int, 4>& a)
{
enum { n = 2 };
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i + 2];
return c;
}
CV_INLINE v_reg<double, 2> v_cvt_f64(const v_reg<float, 4>& a)
{
enum { n = 2 };
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i];
return c;
}
CV_INLINE v_reg<double, 2> v_cvt_f64_high(const v_reg<float, 4>& a)
{
enum { n = 2 };
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i + 2];
return c;
}
CV_INLINE v_reg<double, 2> v_cvt_f64(const v_reg<int64, 2>& a)
{
enum { n = 2 };
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i];
return c;
}
CV_INLINE v_reg<double, 2> v_cvt_f64_high(const v_reg<int64, 2>& a)
{
enum { n = 2 };
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = (double)a.s[i];
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;
for( int i = 0; i < n; i++ )
c.s[i] = tab[idx.s[i]];
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;
for( int i = 0; i < n; i++ )
c.s[i] = tab[idx.s[i]];
return c;
}
template<int n> inline v_reg<double, n> v_lut(const double* tab, const v_reg<int, n*2>& idx)
{
v_reg<double, n> c;
for( int i = 0; i < n; i++ )
c.s[i] = tab[idx.s[i]];
return c;
}
inline v_int32x4 v_lut(const int* tab, const v_int32x4& idxvec)
{
return v_lut(tab, idxvec.s);
}
inline v_uint32x4 v_lut(const unsigned* tab, const v_int32x4& idxvec)
{
return v_lut(tab, idxvec.s);
}
inline v_float32x4 v_lut(const float* tab, const v_int32x4& idxvec)
{
return v_lut(tab, idxvec.s);
}
inline v_float64x2 v_lut(const double* tab, const v_int32x4& idxvec)
{
return v_lut(tab, idxvec.s);
}
template<int n> inline void v_lut_deinterleave(const float* tab, const v_reg<int, n>& idx,
v_reg<float, n>& x, v_reg<float, n>& y)
{
for( int i = 0; i < n; i++ )
{
int j = idx.s[i];
x.s[i] = tab[j];
y.s[i] = tab[j+1];
}
}
template<int n> inline void v_lut_deinterleave(const double* tab, const v_reg<int, n*2>& idx,
v_reg<double, n>& x, v_reg<double, n>& y)
{
for( int i = 0; i < n; i++ )
{
int j = idx.s[i];
x.s[i] = tab[j];
y.s[i] = tab[j+1];
}
}
template<typename _Tp, int n> inline v_reg<_Tp, n> v_interleave_pairs(const v_reg<_Tp, n>& vec)
{
v_reg<_Tp, 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<_Tp, 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<_Tp, n> c;
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;
}
template<typename _Tp>
inline void v_transpose4x4( v_reg<_Tp, 4>& a0, const v_reg<_Tp, 4>& a1,
const v_reg<_Tp, 4>& a2, const v_reg<_Tp, 4>& a3,
v_reg<_Tp, 4>& b0, v_reg<_Tp, 4>& b1,
v_reg<_Tp, 4>& b2, v_reg<_Tp, 4>& b3 )
{
b0 = v_reg<_Tp, 4>(a0.s[0], a1.s[0], a2.s[0], a3.s[0]);
b1 = v_reg<_Tp, 4>(a0.s[1], a1.s[1], a2.s[1], a3.s[1]);
b2 = v_reg<_Tp, 4>(a0.s[2], a1.s[2], a2.s[2], a3.s[2]);
b3 = v_reg<_Tp, 4>(a0.s[3], a1.s[3], a2.s[3], a3.s[3]);
}
#define OPENCV_HAL_IMPL_C_INIT_ZERO(_Tpvec, _Tp, suffix) \
inline _Tpvec v_setzero_##suffix() { return _Tpvec::zero(); }
OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint8x16, uchar, u8)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_int8x16, schar, s8)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint16x8, ushort, u16)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_int16x8, short, s16)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint32x4, unsigned, u32)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_int32x4, int, s32)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_float32x4, float, f32)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_float64x2, double, f64)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint64x2, uint64, u64)
OPENCV_HAL_IMPL_C_INIT_ZERO(v_int64x2, int64, s64)
#define OPENCV_HAL_IMPL_C_INIT_VAL(_Tpvec, _Tp, suffix) \
inline _Tpvec v_setall_##suffix(_Tp val) { return _Tpvec::all(val); }
OPENCV_HAL_IMPL_C_INIT_VAL(v_uint8x16, uchar, u8)
OPENCV_HAL_IMPL_C_INIT_VAL(v_int8x16, schar, s8)
OPENCV_HAL_IMPL_C_INIT_VAL(v_uint16x8, ushort, u16)
OPENCV_HAL_IMPL_C_INIT_VAL(v_int16x8, short, s16)
OPENCV_HAL_IMPL_C_INIT_VAL(v_uint32x4, unsigned, u32)
OPENCV_HAL_IMPL_C_INIT_VAL(v_int32x4, int, s32)
OPENCV_HAL_IMPL_C_INIT_VAL(v_float32x4, float, f32)
OPENCV_HAL_IMPL_C_INIT_VAL(v_float64x2, double, f64)
OPENCV_HAL_IMPL_C_INIT_VAL(v_uint64x2, uint64, u64)
OPENCV_HAL_IMPL_C_INIT_VAL(v_int64x2, int64, s64)
#define OPENCV_HAL_IMPL_C_REINTERPRET(_Tpvec, _Tp, suffix) \
template<typename _Tp0, int n0> inline _Tpvec \
v_reinterpret_as_##suffix(const v_reg<_Tp0, n0>& a) \
{ return a.template reinterpret_as<_Tp, _Tpvec::nlanes>(); }
OPENCV_HAL_IMPL_C_REINTERPRET(v_uint8x16, uchar, u8)
OPENCV_HAL_IMPL_C_REINTERPRET(v_int8x16, schar, s8)
OPENCV_HAL_IMPL_C_REINTERPRET(v_uint16x8, ushort, u16)
OPENCV_HAL_IMPL_C_REINTERPRET(v_int16x8, short, s16)
OPENCV_HAL_IMPL_C_REINTERPRET(v_uint32x4, unsigned, u32)
OPENCV_HAL_IMPL_C_REINTERPRET(v_int32x4, int, s32)
OPENCV_HAL_IMPL_C_REINTERPRET(v_float32x4, float, f32)
OPENCV_HAL_IMPL_C_REINTERPRET(v_float64x2, double, f64)
OPENCV_HAL_IMPL_C_REINTERPRET(v_uint64x2, uint64, u64)
OPENCV_HAL_IMPL_C_REINTERPRET(v_int64x2, int64, s64)
#define OPENCV_HAL_IMPL_C_SHIFTL(_Tpvec, _Tp) \
template<int n> inline _Tpvec v_shl(const _Tpvec& a) \
{ return a << n; }
OPENCV_HAL_IMPL_C_SHIFTL(v_uint16x8, ushort)
OPENCV_HAL_IMPL_C_SHIFTL(v_int16x8, short)
OPENCV_HAL_IMPL_C_SHIFTL(v_uint32x4, unsigned)
OPENCV_HAL_IMPL_C_SHIFTL(v_int32x4, int)
OPENCV_HAL_IMPL_C_SHIFTL(v_uint64x2, uint64)
OPENCV_HAL_IMPL_C_SHIFTL(v_int64x2, int64)
#define OPENCV_HAL_IMPL_C_SHIFTR(_Tpvec, _Tp) \
template<int n> inline _Tpvec v_shr(const _Tpvec& a) \
{ return a >> n; }
OPENCV_HAL_IMPL_C_SHIFTR(v_uint16x8, ushort)
OPENCV_HAL_IMPL_C_SHIFTR(v_int16x8, short)
OPENCV_HAL_IMPL_C_SHIFTR(v_uint32x4, unsigned)
OPENCV_HAL_IMPL_C_SHIFTR(v_int32x4, int)
OPENCV_HAL_IMPL_C_SHIFTR(v_uint64x2, uint64)
OPENCV_HAL_IMPL_C_SHIFTR(v_int64x2, int64)
#define OPENCV_HAL_IMPL_C_RSHIFTR(_Tpvec, _Tp) \
template<int n> inline _Tpvec v_rshr(const _Tpvec& a) \
{ \
_Tpvec c; \
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
c.s[i] = (_Tp)((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
return c; \
}
OPENCV_HAL_IMPL_C_RSHIFTR(v_uint16x8, ushort)
OPENCV_HAL_IMPL_C_RSHIFTR(v_int16x8, short)
OPENCV_HAL_IMPL_C_RSHIFTR(v_uint32x4, unsigned)
OPENCV_HAL_IMPL_C_RSHIFTR(v_int32x4, int)
OPENCV_HAL_IMPL_C_RSHIFTR(v_uint64x2, uint64)
OPENCV_HAL_IMPL_C_RSHIFTR(v_int64x2, int64)
#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tpnvec, _Tpn, pack_suffix, cast) \
inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \
{ \
_Tpnvec c; \
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
{ \
c.s[i] = cast<_Tpn>(a.s[i]); \
c.s[i+_Tpvec::nlanes] = cast<_Tpn>(b.s[i]); \
} \
return c; \
}
OPENCV_HAL_IMPL_C_PACK(v_uint16x8, v_uint8x16, uchar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_int8x16, schar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK(v_uint32x4, v_uint16x8, ushort, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_int16x8, short, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK(v_uint64x2, v_uint32x4, unsigned, pack, static_cast)
OPENCV_HAL_IMPL_C_PACK(v_int64x2, v_int32x4, int, pack, static_cast)
OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_uint8x16, uchar, pack_u, saturate_cast)
OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_uint16x8, ushort, pack_u, saturate_cast)
#define OPENCV_HAL_IMPL_C_RSHR_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix, cast) \
template<int n> inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \
{ \
_Tpnvec c; \
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
{ \
c.s[i] = cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
c.s[i+_Tpvec::nlanes] = cast<_Tpn>((b.s[i] + ((_Tp)1 << (n - 1))) >> n); \
} \
return c; \
}
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_int8x16, schar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_int16x8, short, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack, static_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int64x2, int64, v_int32x4, int, pack, static_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u, saturate_cast)
#define OPENCV_HAL_IMPL_C_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix, cast) \
inline void v_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \
{ \
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
ptr[i] = cast<_Tpn>(a.s[i]); \
}
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_int16x8, short, pack, saturate_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack, static_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack, static_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u, saturate_cast)
OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u, saturate_cast)
#define OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix, cast) \
template<int n> inline void v_rshr_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \
{ \
for( int i = 0; i < _Tpvec::nlanes; i++ ) \
ptr[i] = cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \
}
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_int16x8, short, pack, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack, static_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack, static_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u, saturate_cast)
OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u, saturate_cast)
template<typename _Tpm, typename _Tp, int n>
inline void _pack_b(_Tpm* mptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b)
{
for (int i = 0; i < n; ++i)
{
mptr[i] = (_Tpm)a.s[i];
mptr[i + n] = (_Tpm)b.s[i];
}
}
inline v_uint8x16 v_pack_b(const v_uint16x8& a, const v_uint16x8& b)
{
v_uint8x16 mask;
_pack_b(mask.s, a, b);
return mask;
}
inline v_uint8x16 v_pack_b(const v_uint32x4& a, const v_uint32x4& b,
const v_uint32x4& c, const v_uint32x4& d)
{
v_uint8x16 mask;
_pack_b(mask.s, a, b);
_pack_b(mask.s + 8, c, d);
return mask;
}
inline v_uint8x16 v_pack_b(const v_uint64x2& a, const v_uint64x2& b, const v_uint64x2& c,
const v_uint64x2& d, const v_uint64x2& e, const v_uint64x2& f,
const v_uint64x2& g, const v_uint64x2& h)
{
v_uint8x16 mask;
_pack_b(mask.s, a, b);
_pack_b(mask.s + 4, c, d);
_pack_b(mask.s + 8, e, f);
_pack_b(mask.s + 12, g, h);
return mask;
}
inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0,
const v_float32x4& m1, const v_float32x4& m2,
const v_float32x4& m3)
{
return v_float32x4(v.s[0]*m0.s[0] + v.s[1]*m1.s[0] + v.s[2]*m2.s[0] + v.s[3]*m3.s[0],
v.s[0]*m0.s[1] + v.s[1]*m1.s[1] + v.s[2]*m2.s[1] + v.s[3]*m3.s[1],
v.s[0]*m0.s[2] + v.s[1]*m1.s[2] + v.s[2]*m2.s[2] + v.s[3]*m3.s[2],
v.s[0]*m0.s[3] + v.s[1]*m1.s[3] + v.s[2]*m2.s[3] + v.s[3]*m3.s[3]);
vsetvlmax_e32m1();
vfloat32m1_t res = vfmul_vf_f32m1(m0, v_extract_n<0>(v));
res = vfmacc_vf_f32m1(res, v_extract_n<1>(v), m1);
res = vfmacc_vf_f32m1(res, v_extract_n<2>(v), m2);
res = vfmacc_vf_f32m1(res, v_extract_n<3>(v), m3);
return v_float32x4(res);
}
inline v_float32x4 v_matmuladd(const v_float32x4& v, const v_float32x4& m0,
const v_float32x4& m1, const v_float32x4& m2,
const v_float32x4& m3)
const v_float32x4& a)
{
return v_float32x4(v.s[0]*m0.s[0] + v.s[1]*m1.s[0] + v.s[2]*m2.s[0] + m3.s[0],
v.s[0]*m0.s[1] + v.s[1]*m1.s[1] + v.s[2]*m2.s[1] + m3.s[1],
v.s[0]*m0.s[2] + v.s[1]*m1.s[2] + v.s[2]*m2.s[2] + m3.s[2],
v.s[0]*m0.s[3] + v.s[1]*m1.s[3] + v.s[2]*m2.s[3] + m3.s[3]);
vsetvlmax_e32m1();
vfloat32m1_t res = vfmul_vf_f32m1(m0, v_extract_n<0>(v));
res = vfmacc_vf_f32m1(res, v_extract_n<1>(v), m1);
res = vfmacc_vf_f32m1(res, v_extract_n<2>(v), m2);
return v_float32x4(res) + a;
}
#define OPENCV_HAL_IMPL_RVV_MUL_EXPAND(_Tpvec, _Tpwvec, _Tpw, suffix, wmul, width) \
inline void v_mul_expand(const _Tpvec& a, const _Tpvec& b, _Tpwvec& c, _Tpwvec& d) \
{ \
_Tpw CV_DECL_ALIGNED(32) ptr[_Tpwvec::nlanes*2] = {0}; \
vsetvlmax_e##width##m2(); \
vse##width##_v_##suffix##m2(ptr, wmul(a, b)); \
vsetvlmax_e##width##m1(); \
c = _Tpwvec(vle##width##_v_##suffix##m1(ptr)); \
d = _Tpwvec(vle##width##_v_##suffix##m1(ptr+_Tpwvec::nlanes)); \
}
OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_uint8x16, v_uint16x8, ushort, u16, vwmulu_vv_u16m2, 16)
OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_int8x16, v_int16x8, short, i16, vwmul_vv_i16m2, 16)
OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_uint16x8, v_uint32x4, unsigned, u32, vwmulu_vv_u32m2, 32)
OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_int16x8, v_int32x4, int, i32, vwmul_vv_i32m2, 32)
OPENCV_HAL_IMPL_RVV_MUL_EXPAND(v_uint32x4, v_uint64x2, uint64, u64, vwmulu_vv_u64m2, 64)
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b)
{
vsetvlmax_e16m1();
return v_int16x8(vnsra_wx_i16m1(vwmul_vv_i32m2(a, b), 16));
}
inline v_uint16x8 v_mul_hi(const v_uint16x8& a, const v_uint16x8& b)
{
vsetvlmax_e16m1();
return v_uint16x8(vnsrl_wx_u16m1(vwmulu_vv_u32m2(a, b), 16));
}
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b)
{ return v_fma(v_cvt_f64(a), v_cvt_f64(b), v_cvt_f64_high(a) * v_cvt_f64_high(b)); }
inline v_float64x2 v_dotprod_expand(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_fma(v_cvt_f64(a), v_cvt_f64(b), v_fma(v_cvt_f64_high(a), v_cvt_f64_high(b), c)); }
//////// Saturating Multiply ////////
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b)
{ return v_dotprod_expand(a, b); }
inline v_float64x2 v_dotprod_expand_fast(const v_int32x4& a, const v_int32x4& b, const v_float64x2& c)
{ return v_dotprod_expand(a, b, c); }
////// FP16 support ///////
inline v_reg<float, V_TypeTraits<float>::nlanes128>
v_load_expand(const float16_t* ptr)
{
v_reg<float, V_TypeTraits<float>::nlanes128> v;
for( int i = 0; i < v.nlanes; i++ )
{
v.s[i] = ptr[i];
}
return v;
#define OPENCV_HAL_IMPL_RVV_MUL_SAT(_Tpvec, _wTpvec) \
inline _Tpvec operator * (const _Tpvec& a, const _Tpvec& b) \
{ \
_wTpvec c, d; \
v_mul_expand(a, b, c, d); \
return v_pack(c, d); \
} \
inline _Tpvec& operator *= (_Tpvec& a, const _Tpvec& b) \
{ \
a = a * b; \
return a; \
}
inline void
v_pack_store(float16_t* ptr, const v_reg<float, V_TypeTraits<float>::nlanes128>& v)
{
for( int i = 0; i < v.nlanes; i++ )
{
ptr[i] = float16_t(v.s[i]);
}
}
OPENCV_HAL_IMPL_RVV_MUL_SAT(v_uint8x16, v_uint16x8)
OPENCV_HAL_IMPL_RVV_MUL_SAT(v_int8x16, v_int16x8)
OPENCV_HAL_IMPL_RVV_MUL_SAT(v_uint16x8, v_uint32x4)
OPENCV_HAL_IMPL_RVV_MUL_SAT(v_int16x8, v_int32x4)
inline void v_cleanup() {}
#ifndef CV_DOXYGEN
CV_CPU_OPTIMIZATION_HAL_NAMESPACE_END
#endif
}
#endif
@@ -0,0 +1,20 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR riscv64)
set(RISCV_GCC_INSTALL_ROOT /opt/RISCV CACHE PATH "Path to GCC for RISC-V cross compiler installation directory")
set(CMAKE_SYSROOT ${RISCV_GCC_INSTALL_ROOT}/sysroot CACHE PATH "RISC-V sysroot")
set(CMAKE_C_COMPILER ${RISCV_GCC_INSTALL_ROOT}/bin/riscv64-unknown-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${RISCV_GCC_INSTALL_ROOT}/bin/riscv64-unknown-linux-gnu-g++)
# Don't run the linker on compiler check
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_C_FLAGS "-march=rv64gcv_zvqmac ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-march=rv64gcv_zvqmac ${CXX_FLAGS}")
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)