1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge branch 4.x

This commit is contained in:
OpenCV Developers
2022-04-23 21:42:17 +00:00
324 changed files with 34982 additions and 9803 deletions
+10
View File
@@ -1739,6 +1739,16 @@ should be done separately if needed.
*/
CV_EXPORTS_W void transpose(InputArray src, OutputArray dst);
/** @brief Transpose for n-dimensional matrices.
*
* @note Input should be continuous single-channel matrix.
* @param src input array.
* @param order a permutation of [0,1,..,N-1] where N is the number of axes of src.
* The ith axis of dst will correspond to the axis numbered order[i] of the input.
* @param dst output array of the same type as src.
*/
CV_EXPORTS_W void transposeND(InputArray src, const std::vector<int>& order, OutputArray dst);
/** @brief Performs the matrix transformation of every array element.
The function cv::transform performs the matrix transformation of every
@@ -223,6 +223,53 @@ namespace nested {
CV_WRAP static inline bool testEchoBooleanFunction(bool flag) {
return flag;
}
class CV_EXPORTS_W CV_WRAP_AS(ExportClassName) OriginalClassName
{
public:
struct CV_EXPORTS_W_SIMPLE Params
{
CV_PROP_RW int int_value;
CV_PROP_RW float float_value;
CV_WRAP explicit Params(int int_param = 123, float float_param = 3.5f)
{
int_value = int_param;
float_value = float_param;
}
};
explicit OriginalClassName(const OriginalClassName::Params& params = OriginalClassName::Params())
{
params_ = params;
}
CV_WRAP int getIntParam() const
{
return params_.int_value;
}
CV_WRAP float getFloatParam() const
{
return params_.float_value;
}
CV_WRAP static std::string originalName()
{
return "OriginalClassName";
}
CV_WRAP static Ptr<OriginalClassName>
create(const OriginalClassName::Params& params = OriginalClassName::Params())
{
return makePtr<OriginalClassName>(params);
}
private:
OriginalClassName::Params params_;
};
typedef OriginalClassName::Params OriginalClassName_Params;
} // namespace nested
namespace fs {
@@ -1037,12 +1037,12 @@ inline scalartype v_reduce_sum(const _Tpvec& a) \
return (scalartype)msa_sum_##suffix(a.val); \
}
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_uint8x16, unsigned char, u8)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_int8x16, char, s8)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_uint16x8, unsigned short, u16)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_int16x8, short, s16)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_uint32x4, unsigned, u32)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_int32x4, int, s32)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_uint8x16, unsigned short, u8)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_int8x16, short, s8)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_uint16x8, unsigned, u16)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_int16x8, int, s16)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_uint32x4, uint64_t, u32)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_int32x4, int64_t, s32)
OPENCV_HAL_IMPL_MSA_REDUCE_SUM(v_float32x4, float, f32)
inline uint64 v_reduce_sum(const v_uint64x2& a)
@@ -591,28 +591,26 @@ inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b,
inline v_int16x8 v_mul_hi(const v_int16x8& a, const v_int16x8& b)
{
#if CV_NEON_AARCH64
int32x4_t c = vmull_high_s16(a.val, b.val);
#else // #if CV_NEON_AARCH64
int32x4_t c = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val));
#endif // #if CV_NEON_AARCH64
return v_int16x8(vcombine_s16(
vshrn_n_s32(vmull_s16( vget_low_s16(a.val), vget_low_s16(b.val)), 16),
vshrn_n_s32(
#if CV_NEON_AARCH64
vmull_high_s16(a.val, b.val)
#else // #if CV_NEON_AARCH64
vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val))
#endif // #if CV_NEON_AARCH64
, 16)
vshrn_n_s32(c, 16)
));
}
inline v_uint16x8 v_mul_hi(const v_uint16x8& a, const v_uint16x8& b)
{
#if CV_NEON_AARCH64
uint32x4_t c = vmull_high_u16(a.val, b.val);
#else // #if CV_NEON_AARCH64
uint32x4_t c = vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val));
#endif // #if CV_NEON_AARCH64
return v_uint16x8(vcombine_u16(
vshrn_n_u32(vmull_u16( vget_low_u16(a.val), vget_low_u16(b.val)), 16),
vshrn_n_u32(
#if CV_NEON_AARCH64
vmull_high_u16(a.val, b.val)
#else // #if CV_NEON_AARCH64
vmull_u16(vget_high_u16(a.val), vget_high_u16(b.val))
#endif // #if CV_NEON_AARCH64
, 16)
vshrn_n_u32(c, 16)
));
}
@@ -1937,10 +1935,14 @@ inline v_int32x4 v_round(const v_float32x4& a)
{
float32x4_t a_ = a.val;
int32x4_t result;
#if defined _MSC_VER
result = vcvtnq_s32_f32(a_);
#else
__asm__ ("fcvtns %0.4s, %1.4s"
: "=w"(result)
: "w"(a_)
: /* No clobbers */);
#endif
return v_int32x4(result);
}
#else
@@ -230,6 +230,7 @@ inline vint16mf2_t vwcvt_x_x_v_i16mf2 (vint8mf4_t src, size_t vl)
//////////// Types ////////////
#ifndef __clang__
struct v_uint8x16
{
typedef uchar lane_type;
@@ -531,7 +532,358 @@ struct v_float64x2
double val[2];
};
#endif
#else
struct v_uint8x16
{
typedef uchar lane_type;
enum { nlanes = 16 };
v_uint8x16() {}
explicit v_uint8x16(vuint8m1_t v)
{
*pval = 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};
*pval = vle8_v_u8m1(v, nlanes);
}
operator vuint8m1_t() const
{
return *pval;
}
uchar get0() const
{
return vmv_x(*pval);
}
inline v_uint8x16& operator=(const v_uint8x16& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_uint8x16(const v_uint8x16& vec) {
*pval = *(vec.pval);
}
uchar val[16];
vuint8m1_t* pval = (vuint8m1_t*)val;
};
struct v_int8x16
{
typedef schar lane_type;
enum { nlanes = 16 };
v_int8x16() {}
explicit v_int8x16(vint8m1_t v)
{
*pval = 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};
*pval = vle8_v_i8m1(v, nlanes);
}
operator vint8m1_t() const
{
return *pval;
}
schar get0() const
{
return vmv_x(*pval);
}
inline v_int8x16& operator=(const v_int8x16& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_int8x16(const v_int8x16& vec) {
*pval = *(vec.pval);
}
schar val[16];
vint8m1_t* pval = (vint8m1_t*)val;
};
struct v_uint16x8
{
typedef ushort lane_type;
enum { nlanes = 8 };
v_uint16x8() {}
explicit v_uint16x8(vuint16m1_t v)
{
*pval = 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};
*pval = vle16_v_u16m1(v, nlanes);
}
operator vuint16m1_t() const
{
return *pval;
}
ushort get0() const
{
return vmv_x(*pval);
}
inline v_uint16x8& operator=(const v_uint16x8& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_uint16x8(const v_uint16x8& vec) {
*pval = *(vec.pval);
}
ushort val[8];
vuint16m1_t* pval = (vuint16m1_t*)val;
};
struct v_int16x8
{
typedef short lane_type;
enum { nlanes = 8 };
v_int16x8() {}
explicit v_int16x8(vint16m1_t v)
{
*pval = 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};
*pval = vle16_v_i16m1(v, nlanes);
}
operator vint16m1_t() const
{
return *pval;
}
short get0() const
{
return vmv_x(*pval);
}
inline v_int16x8& operator=(const v_int16x8& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_int16x8(const v_int16x8& vec) {
*pval = *(vec.pval);
}
short val[8];
vint16m1_t* pval = (vint16m1_t*)val;
};
struct v_uint32x4
{
typedef unsigned lane_type;
enum { nlanes = 4 };
v_uint32x4() {}
explicit v_uint32x4(vuint32m1_t v)
{
*pval = v;
}
v_uint32x4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
{
unsigned v[] = {v0, v1, v2, v3};
*pval = vle32_v_u32m1(v, nlanes);
}
operator vuint32m1_t() const
{
return *pval;
}
unsigned get0() const
{
return vmv_x(*pval);
}
inline v_uint32x4& operator=(const v_uint32x4& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_uint32x4(const v_uint32x4& vec) {
*pval = *(vec.pval);
}
unsigned val[4];
vuint32m1_t* pval = (vuint32m1_t*)val;
};
struct v_int32x4
{
typedef int lane_type;
enum { nlanes = 4 };
v_int32x4() {}
explicit v_int32x4(vint32m1_t v)
{
*pval = v;
}
v_int32x4(int v0, int v1, int v2, int v3)
{
int v[] = {v0, v1, v2, v3};
*pval = vle32_v_i32m1(v, nlanes);
}
operator vint32m1_t() const
{
return *pval;
}
int get0() const
{
return vmv_x(*pval);
}
inline v_int32x4& operator=(const v_int32x4& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_int32x4(const v_int32x4& vec) {
*pval = *(vec.pval);
}
int val[4];
vint32m1_t* pval = (vint32m1_t*)val;
};
struct v_float32x4
{
typedef float lane_type;
enum { nlanes = 4 };
v_float32x4() {}
explicit v_float32x4(vfloat32m1_t v)
{
*pval = v;
}
v_float32x4(float v0, float v1, float v2, float v3)
{
float v[] = {v0, v1, v2, v3};
*pval = vle32_v_f32m1(v, nlanes);
}
operator vfloat32m1_t() const
{
return *pval;
}
float get0() const
{
return vfmv_f(*pval);
}
inline v_float32x4& operator=(const v_float32x4& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_float32x4(const v_float32x4& vec) {
*pval = *(vec.pval);
}
float val[4];
vfloat32m1_t* pval = (vfloat32m1_t*)val;
};
struct v_uint64x2
{
typedef uint64 lane_type;
enum { nlanes = 2 };
v_uint64x2() {}
explicit v_uint64x2(vuint64m1_t v)
{
*pval = v;
}
v_uint64x2(uint64 v0, uint64 v1)
{
uint64 v[] = {v0, v1};
*pval = vle64_v_u64m1(v, nlanes);
}
operator vuint64m1_t() const
{
return *pval;
}
uint64 get0() const
{
return vmv_x(*pval);
}
inline v_uint64x2& operator=(const v_uint64x2& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_uint64x2(const v_uint64x2& vec) {
*pval = *(vec.pval);
}
uint64 val[2];
vuint64m1_t* pval = (vuint64m1_t*)val;
};
struct v_int64x2
{
typedef int64 lane_type;
enum { nlanes = 2 };
v_int64x2() {}
explicit v_int64x2(vint64m1_t v)
{
*pval = v;
}
v_int64x2(int64 v0, int64 v1)
{
int64 v[] = {v0, v1};
*pval = vle64_v_i64m1(v, nlanes);
}
operator vint64m1_t() const
{
return *pval;
}
int64 get0() const
{
return vmv_x(*pval);
}
inline v_int64x2& operator=(const v_int64x2& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_int64x2(const v_int64x2& vec) {
*pval = *(vec.pval);
}
int64 val[2];
vint64m1_t* pval = (vint64m1_t*)val;
};
#if CV_SIMD128_64F
struct v_float64x2
{
typedef double lane_type;
enum { nlanes = 2 };
v_float64x2() {}
explicit v_float64x2(vfloat64m1_t v)
{
*pval = v;
}
v_float64x2(double v0, double v1)
{
double v[] = {v0, v1};
*pval = vle64_v_f64m1(v, nlanes);
}
operator vfloat64m1_t() const
{
return *pval;
}
double get0() const
{
return vfmv_f(*pval);
}
inline v_float64x2& operator=(const v_float64x2& vec) {
*pval = *(vec.pval);
return *this;
}
inline v_float64x2(const v_float64x2& vec) {
*pval = *(vec.pval);
}
double val[2];
vfloat64m1_t* pval = (vfloat64m1_t*)val;
};
#endif // CV_SIMD128_64F
#endif // __clang__
//////////// Initial ////////////
@@ -1819,6 +2171,7 @@ inline v_float32x4 v_cvt_f32(const v_int32x4& a)
}
#if CV_SIMD128_64F
#ifndef __clang__
inline v_float32x4 v_cvt_f32(const v_float64x2& a)
{
double arr[4] = {a.val[0], a.val[1], 0, 0};
@@ -1832,6 +2185,18 @@ inline v_float32x4 v_cvt_f32(const v_float64x2& a, const v_float64x2& b)
vfloat64m2_t tmp = vle64_v_f64m2(arr, 4);
return v_float32x4(vfncvt_f_f_w_f32m1(tmp, 4));
}
#else
inline v_float32x4 v_cvt_f32(const v_float64x2& a)
{
vfloat64m2_t zero = vfmv_v_f_f64m2(0, 4);
return v_float32x4(vfncvt_f_f_w_f32m1(vset_v_f64m1_f64m2(zero, 0, a), 4));
}
inline v_float32x4 v_cvt_f32(const v_float64x2& a, const v_float64x2& b)
{
vfloat64m2_t dst = vlmul_ext_v_f64m1_f64m2(a);
return v_float32x4(vfncvt_f_f_w_f32m1(vset_v_f64m1_f64m2(dst, 1, b), 4));
}
#endif
inline v_float64x2 v_cvt_f64(const v_int32x4& a)
{
@@ -2351,6 +2716,7 @@ OPENCV_HAL_IMPL_RVV_POPCOUNT_OP(v_uint64x2, v_int64x2, uint64, int64, u64)
//////////// SignMask ////////////
#ifndef __clang__
#define OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(_Tpvec, _Tp, suffix, vl, shift) \
inline int v_signmask(const _Tpvec& a) \
{ \
@@ -2381,6 +2747,36 @@ inline int v_signmask(const v_float64x2& a)
{ return v_signmask(v_reinterpret_as_u64(a)); }
#endif
#else
#define OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(_Tpvec, width, vl) \
inline int v_signmask(const _Tpvec& a) \
{ \
uint8_t ans[16] = {0};\
vsm(ans, vmslt(a, 0, vl), vl);\
return reinterpret_cast<int*>(ans)[0];\
}
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int8x16, 8, 16)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int16x8, 16, 8)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int32x4, 32, 4)
OPENCV_HAL_IMPL_RVV_SIGNMASK_OP(v_int64x2, 64, 2)
inline int v_signmask(const v_uint8x16& a)
{ return v_signmask(v_reinterpret_as_s8(a)); }
inline int v_signmask(const v_uint16x8& a)
{ return v_signmask(v_reinterpret_as_s16(a)); }
inline int v_signmask(const v_uint32x4& a)
{ return v_signmask(v_reinterpret_as_s32(a)); }
inline int v_signmask(const v_float32x4& a)
{ return v_signmask(v_reinterpret_as_s32(a)); }
inline int v_signmask(const v_uint64x2& a)
{ return v_signmask(v_reinterpret_as_s64(a)); }
#if CV_SIMD128_64F
inline int v_signmask(const v_float64x2& a)
{ return v_signmask(v_reinterpret_as_s64(a)); }
#endif
#endif
//////////// Scan forward ////////////
@@ -2520,6 +2916,7 @@ inline v_int32x4 v_trunc(const v_float32x4& a)
return v_int32x4(vfcvt_rtz_x_f_v_i32m1(a, 4));
}
#if CV_SIMD128_64F
#ifndef __clang__
inline v_int32x4 v_round(const v_float64x2& a)
{
double arr[4] = {a.val[0], a.val[1], 0, 0};
@@ -2554,6 +2951,42 @@ inline v_int32x4 v_trunc(const v_float64x2& a)
vfloat64m2_t tmp = vle64_v_f64m2(arr, 4);
return v_int32x4(vfncvt_rtz_x_f_w_i32m1(tmp, 4));
}
#else
inline v_int32x4 v_round(const v_float64x2& a)
{
vfloat64m2_t zero = vfmv_v_f_f64m2(0, 4);
return v_int32x4(vfncvt_x_f_w_i32m1(vset_v_f64m1_f64m2(zero, 0, a), 4));
}
inline v_int32x4 v_round(const v_float64x2& a, const v_float64x2& b)
{
vfloat64m2_t dst = vlmul_ext_v_f64m1_f64m2(a);
return v_int32x4(vfncvt_x_f_w_i32m1(vset_v_f64m1_f64m2(dst, 1, b), 4));
}
inline v_int32x4 v_floor(const v_float64x2& a)
{
vfloat64m2_t dst = vfmv_v_f_f64m2(0, 4);
dst = vset_v_f64m1_f64m2(dst, 0, a);
dst = vfsub_vf_f64m2(dst, 0.5, 2);
return v_int32x4(vfncvt_x_f_w_i32m1(dst, 4));
}
inline v_int32x4 v_ceil(const v_float64x2& a)
{
vfloat64m2_t dst = vfmv_v_f_f64m2(0, 4);
dst = vset_v_f64m1_f64m2(dst, 0, a);
dst = vfadd_vf_f64m2(dst, 0.5, 2);
return v_int32x4(vfncvt_x_f_w_i32m1(dst, 4));
}
inline v_int32x4 v_trunc(const v_float64x2& a)
{
vfloat64m2_t zero = vfmv_v_f_f64m2(0, 4);
return v_int32x4(vfncvt_rtz_x_f_w_i32m1(vset_v_f64m1_f64m2(zero, 0, a), 4));
}
#endif
#endif
@@ -719,7 +719,7 @@ typedef double v1f64 __attribute__ ((vector_size(8), aligned(8)));
v2i64 _c; \
_b = __builtin_msa_hadd_s_w(__a, __a); \
_c = __builtin_msa_hadd_s_d(_b, _b); \
(int16_t)(_c[0] + _c[1]); \
(int32_t)(_c[0] + _c[1]); \
})
@@ -736,7 +736,7 @@ typedef double v1f64 __attribute__ ((vector_size(8), aligned(8)));
({ \
v2i64 _b; \
_b = __builtin_msa_hadd_s_d(__a, __a); \
(int32_t)(_b[0] + _b[1]); \
(int64_t)(_b[0] + _b[1]); \
})
/* uint8_t msa_sum_u8(v16u8 __a)*/
@@ -756,7 +756,7 @@ typedef double v1f64 __attribute__ ((vector_size(8), aligned(8)));
v4i32 _c32; \
_b16 = __builtin_msa_hadd_s_h(__a, __a); \
_c32 = __builtin_msa_hadd_s_w(_b16, _b16); \
(int8_t)msa_sum_s32(_c32); \
(int16_t)msa_sum_s32(_c32); \
})
/* float msa_sum_f32(v4f32 __a)*/
@@ -382,6 +382,14 @@ public:
Vec(const Vec<_Tp, cn>& v);
static Vec all(_Tp alpha);
static Vec ones();
static Vec randn(_Tp a, _Tp b);
static Vec randu(_Tp a, _Tp b);
static Vec zeros();
#ifdef CV_CXX11
static Vec diag(_Tp alpha) = delete;
static Vec eye() = delete;
#endif
//! per-element multiplication
Vec mul(const Vec<_Tp, cn>& v) const;
@@ -1061,6 +1069,18 @@ Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha)
return v;
}
template<typename _Tp, int cn> inline
Vec<_Tp, cn> Vec<_Tp, cn>::ones()
{
return Vec::all(1);
}
template<typename _Tp, int cn> inline
Vec<_Tp, cn> Vec<_Tp, cn>::zeros()
{
return Vec::all(0);
}
template<typename _Tp, int cn> inline
Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const
{
@@ -230,6 +230,22 @@ Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b)
return M;
}
template<typename _Tp, int cn> inline
Vec<_Tp, cn> Vec<_Tp, cn>::randu(_Tp a, _Tp b)
{
Vec<_Tp,cn> V;
cv::randu(V, Scalar(a), Scalar(b));
return V;
}
template<typename _Tp, int cn> inline
Vec<_Tp, cn> Vec<_Tp, cn>::randn(_Tp a, _Tp b)
{
Vec<_Tp,cn> V;
cv::randn(V, Scalar(a), Scalar(b));
return V;
}
template<typename _Tp, int m, int n> inline
Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const
{
@@ -324,6 +324,7 @@ VSX_IMPL_1RG(vec_udword2, vec_float4, xvcvspuxds, vec_ctulo)
#define VSX_IMPL_CONVERT(rt, rg, fnm) \
VSX_FINLINE(rt) fnm(const rg& a) { return __builtin_convertvector(a, rt); }
#ifndef vec_permi
#if __clang_major__ < 5
// implement vec_permi in a dirty way
# define VSX_IMPL_CLANG_4_PERMI(Tvec) \
@@ -351,12 +352,14 @@ VSX_FINLINE(rt) fnm(const rg& a) { return __builtin_convertvector(a, rt); }
// vec_xxpermdi is missing little-endian supports in clang 4 just like gcc4
# define vec_permi(a, b, c) vec_xxpermdi(b, a, (3 ^ (((c) & 1) << 1 | (c) >> 1)))
#endif // __clang_major__ < 5
#endif
// shift left double by word immediate
#ifndef vec_sldw
# define vec_sldw vec_xxsldwi
#endif
#if __clang_major__ < 13
// Implement vec_rsqrt since clang only supports vec_rsqrte
#ifndef vec_rsqrt
VSX_FINLINE(vec_float4) vec_rsqrt(const vec_float4& a)
@@ -380,6 +383,7 @@ VSX_FINLINE(vec_udword2) vec_promote(unsigned long long a, int b)
ret[b & 1] = a;
return ret;
}
#endif
// vec_popcnt should return unsigned but clang has different thought just like gcc in vec_vpopcnt
#define VSX_IMPL_POPCNTU(Tvec, Tvec2, ucast) \