mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Merge branch 4.x
This commit is contained in:
@@ -697,7 +697,7 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType)
|
||||
#endif
|
||||
|
||||
/****************************************************************************************\
|
||||
* Thread sanitizer *
|
||||
* Sanitizers *
|
||||
\****************************************************************************************/
|
||||
#ifndef CV_THREAD_SANITIZER
|
||||
# if defined(__has_feature)
|
||||
@@ -707,6 +707,12 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define CV_DISABLE_UBSAN __attribute__((no_sanitize("undefined")))
|
||||
#else
|
||||
#define CV_DISABLE_UBSAN
|
||||
#endif
|
||||
|
||||
/****************************************************************************************\
|
||||
* exchange-add operation for atomic operations on reference counters *
|
||||
\****************************************************************************************/
|
||||
|
||||
@@ -361,6 +361,7 @@ CV_INLINE int cvRound( int value )
|
||||
}
|
||||
|
||||
/** @overload */
|
||||
CV_DISABLE_UBSAN
|
||||
CV_INLINE int cvFloor( float value )
|
||||
{
|
||||
#if defined CV__FASTMATH_ENABLE_GCC_MATH_BUILTINS || \
|
||||
|
||||
@@ -680,6 +680,13 @@ public:
|
||||
double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180);
|
||||
Mat R = (Mat_<double>(2,2) << a, -b, b, a);
|
||||
\endcode
|
||||
|
||||
\deprecated Use constructors with std::initializer_list instead:
|
||||
\code
|
||||
Mat_<int> m1({1, 2, 3, 4}); // 4x1 Mat
|
||||
Mat_<uchar> m2({2, 3}, {1, 2, 3, 4, 5, 6}); // 2x3 Mat
|
||||
|
||||
Mat_<double> R({2, 2}, {a, -b, b, a}); // from example
|
||||
*/
|
||||
template<typename _Tp> class MatCommaInitializer_
|
||||
{
|
||||
@@ -1261,7 +1268,7 @@ public:
|
||||
|
||||
/** @overload
|
||||
*/
|
||||
template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);
|
||||
template<typename _Tp> CV_DEPRECATED_EXTERNAL explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);
|
||||
|
||||
//! download data from GpuMat
|
||||
explicit Mat(const cuda::GpuMat& m);
|
||||
@@ -2618,7 +2625,7 @@ public:
|
||||
template<int m, int n> explicit Mat_(const Matx<typename DataType<_Tp>::channel_type, m, n>& mtx, bool copyData=true);
|
||||
explicit Mat_(const Point_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
|
||||
explicit Mat_(const Point3_<typename DataType<_Tp>::channel_type>& pt, bool copyData=true);
|
||||
explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer);
|
||||
CV_DEPRECATED_EXTERNAL explicit Mat_(const MatCommaInitializer_<_Tp>& commaInitializer);
|
||||
|
||||
Mat_(std::initializer_list<_Tp> values);
|
||||
explicit Mat_(const std::initializer_list<int> sizes, const std::initializer_list<_Tp> values);
|
||||
|
||||
@@ -3207,7 +3207,7 @@ MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const
|
||||
}
|
||||
|
||||
|
||||
template<typename _Tp, typename T2> static inline
|
||||
template<typename _Tp, typename T2> CV_DEPRECATED_EXTERNAL static inline
|
||||
MatCommaInitializer_<_Tp> operator << (const Mat_<_Tp>& m, T2 val)
|
||||
{
|
||||
MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m);
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
int idx;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _T2, int m, int n> static inline
|
||||
template<typename _Tp, typename _T2, int m, int n> CV_DEPRECATED_EXTERNAL static inline
|
||||
MatxCommaInitializer<_Tp, m, n> operator << (const Matx<_Tp, m, n>& mtx, _T2 val)
|
||||
{
|
||||
MatxCommaInitializer<_Tp, m, n> commaInitializer((Matx<_Tp, m, n>*)&mtx);
|
||||
@@ -738,7 +738,7 @@ public:
|
||||
Vec<_Tp, m> operator *() const;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _T2, int cn> static inline
|
||||
template<typename _Tp, typename _T2, int cn> CV_DEPRECATED_EXTERNAL static inline
|
||||
VecCommaInitializer<_Tp, cn> operator << (const Vec<_Tp, cn>& vec, _T2 val)
|
||||
{
|
||||
VecCommaInitializer<_Tp, cn> commaInitializer((Vec<_Tp, cn>*)&vec);
|
||||
|
||||
@@ -307,8 +307,12 @@ public:
|
||||
before opening the file.
|
||||
@param filename Name of the file to open or the text string to read the data from.
|
||||
Extension of the file (.xml, .yml/.yaml or .json) determines its format (XML, YAML or JSON
|
||||
respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz. If both
|
||||
FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
|
||||
respectively). Also you can append .gz to work with compressed files, for example myHugeMatrix.xml.gz.
|
||||
You can also specify a compression level from 0 to 9 by appending it to the extension
|
||||
(e.g. ".gz0" for no compression, ".gz9" for high compression).
|
||||
The last digit will be truncated internally to write/read.
|
||||
(e.g. If "a.xml.gz9" is specified, "a.xml.gz" is used for the actual file name.)
|
||||
If both FileStorage::WRITE and FileStorage::MEMORY flags are specified, source is used just to specify
|
||||
the output file format (e.g. mydata.xml, .yml etc.). A file name can also contain parameters.
|
||||
You can use this format, "*?base64" (e.g. "file.json?base64" (case sensitive)), as an alternative to
|
||||
FileStorage::BASE64 flag.
|
||||
|
||||
@@ -1245,6 +1245,26 @@ _Tp Point_<_Tp>::dot(const Point_& pt) const
|
||||
return saturate_cast<_Tp>(x*pt.x + y*pt.y);
|
||||
}
|
||||
|
||||
template<> inline
|
||||
int Point_<int>::dot(const Point_<int>& pt) const
|
||||
{
|
||||
const int64_t xx = (int64_t)x * pt.x;
|
||||
const int64_t yy = (int64_t)y * pt.y;
|
||||
|
||||
// detect int64 overflow before adding
|
||||
if (yy > 0 && xx > INT64_MAX - yy)
|
||||
{
|
||||
return INT32_MAX;
|
||||
}
|
||||
if (yy < 0 && xx < INT64_MIN - yy)
|
||||
{
|
||||
return INT32_MIN;
|
||||
}
|
||||
|
||||
const int64_t v = xx + yy;
|
||||
return cv::saturate_cast<int>(v);
|
||||
}
|
||||
|
||||
template<typename _Tp> inline
|
||||
double Point_<_Tp>::ddot(const Point_& pt) const
|
||||
{
|
||||
@@ -1490,6 +1510,50 @@ _Tp Point3_<_Tp>::dot(const Point3_& pt) const
|
||||
return saturate_cast<_Tp>(x*pt.x + y*pt.y + z*pt.z);
|
||||
}
|
||||
|
||||
template<> inline
|
||||
int Point3_<int>::dot(const Point3_<int>& pt) const
|
||||
{
|
||||
const int64_t xx = (int64_t)x * pt.x;
|
||||
const int64_t yy = (int64_t)y * pt.y;
|
||||
const int64_t zz = (int64_t)z * pt.z;
|
||||
|
||||
// Sort the three products so that lo <= mid <= hi.
|
||||
// We add in the order (lo + hi) first, then add mid.
|
||||
// This minimizes the absolute value of the intermediate sum,
|
||||
// reducing the chance of int64 overflow during addition.
|
||||
int64_t lo = xx, mid = yy, hi = zz;
|
||||
if (lo > mid) std::swap(lo, mid);
|
||||
if (mid > hi) std::swap(mid, hi);
|
||||
if (lo > mid) std::swap(lo, mid);
|
||||
|
||||
// Step 1: lo + hi
|
||||
// If lo + hi overflows int64, the final result must saturate to INT32_MAX/INT32_MIN.
|
||||
// The middle value (mid) cannot bring the result back into the int32 range,
|
||||
// so we can return immediately without considering mid.
|
||||
if (hi > 0 && lo > INT64_MAX - hi)
|
||||
{
|
||||
return INT32_MAX;
|
||||
}
|
||||
if (hi < 0 && lo < INT64_MIN - hi)
|
||||
{
|
||||
return INT32_MIN;
|
||||
}
|
||||
int64_t sum = lo + hi;
|
||||
|
||||
// Step 2: sum + mid
|
||||
if (mid > 0 && sum > INT64_MAX - mid)
|
||||
{
|
||||
return INT32_MAX;
|
||||
}
|
||||
if (mid < 0 && sum < INT64_MIN - mid)
|
||||
{
|
||||
return INT32_MIN;
|
||||
}
|
||||
sum += mid;
|
||||
|
||||
return cv::saturate_cast<int>(sum);
|
||||
}
|
||||
|
||||
template<typename _Tp> inline
|
||||
double Point3_<_Tp>::ddot(const Point3_& pt) const
|
||||
{
|
||||
|
||||
@@ -102,11 +102,18 @@ template<typename _Tp, size_t fixed_size = 1024/sizeof(_Tp)+8> class AutoBuffer
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef const _Tp* const_iterator;
|
||||
typedef _Tp* iterator;
|
||||
typedef const _Tp& const_reference;
|
||||
typedef _Tp& reference;
|
||||
|
||||
//! the default constructor
|
||||
AutoBuffer();
|
||||
//! constructor taking the real buffer size
|
||||
explicit AutoBuffer(size_t _size);
|
||||
AutoBuffer(size_t _size, const _Tp& value);
|
||||
|
||||
//! the copy constructor
|
||||
AutoBuffer(const AutoBuffer<_Tp, fixed_size>& buf);
|
||||
@@ -140,7 +147,25 @@ public:
|
||||
//! returns a reference to the element at specified location. No bounds checking is performed in Release builds.
|
||||
inline const _Tp& operator[] (size_t i) const { CV_DbgCheckLT(i, sz, "out of range"); return ptr[i]; }
|
||||
#endif
|
||||
|
||||
public:
|
||||
inline iterator begin() { return data(); }
|
||||
inline const_iterator begin() const { return data(); }
|
||||
inline const_iterator cbegin() const { return begin(); }
|
||||
inline iterator end() { return data()+size(); }
|
||||
inline const_iterator end() const { return data()+size(); }
|
||||
inline const_iterator cend() const { return end(); }
|
||||
public:
|
||||
inline bool empty() const { return !size(); }
|
||||
inline void clear() {resize(0);}
|
||||
inline const_reference front() const { return (*this)[0] ;}
|
||||
inline reference front() { return (*this)[0] ;}
|
||||
inline const_reference back() const { CV_DbgCheckGT(sz, (size_t)0, "out of range"); return (*this)[size()-1] ;}
|
||||
inline reference back() { CV_DbgCheckGT(sz, (size_t)0, "out of range"); return (*this)[size()-1] ;}
|
||||
public:
|
||||
inline void push_back( const _Tp& value ) {resize(size()+1); back() = value;}
|
||||
inline void push_back( _Tp&& value ) {resize(size()+1); back() = std::move(value);}
|
||||
inline void emplace_back( _Tp&& value ) {push_back(value);}
|
||||
inline void pop_back() {CV_DbgCheckGT(sz, (size_t)0, "out of range"); resize(size()-1);}
|
||||
protected:
|
||||
//! pointer to the real buffer, can point to buf if the buffer is small enough
|
||||
_Tp* ptr;
|
||||
@@ -1054,6 +1079,13 @@ AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size)
|
||||
allocate(_size);
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size, const _Tp& value)
|
||||
:AutoBuffer<_Tp, fixed_size>(_size)
|
||||
{
|
||||
std::fill(begin(), end(), value);
|
||||
}
|
||||
|
||||
template<typename _Tp, size_t fixed_size> inline
|
||||
AutoBuffer<_Tp, fixed_size>::AutoBuffer(const AutoBuffer<_Tp, fixed_size>& abuf )
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ static bool ocl_math_op(InputArray _src1, InputArray _src2, OutputArray _dst, in
|
||||
Fast cube root by Ken Turkowski
|
||||
(http://www.worldserver.com/turk/computergraphics/papers.html)
|
||||
\* ************************************************************************** */
|
||||
float cubeRoot( float value )
|
||||
CV_DISABLE_UBSAN float cubeRoot( float value )
|
||||
{
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
|
||||
+537
-27
@@ -1160,6 +1160,535 @@ struct NormDiffL2_SIMD<double, double> {
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T, typename ST>
|
||||
struct MaskedNormInf_SIMD {
|
||||
inline ST operator() (const T* src, const uchar* mask, int len, int cn) const {
|
||||
ST s = 0;
|
||||
if (cn == 1) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
s = std::max(s, (ST)cv_abs(src[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const T* elem = src + i * cn;
|
||||
int k = 0;
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for (; k <= cn - 4; k += 4) {
|
||||
s = std::max(s, (ST)cv_abs(elem[k]));
|
||||
s = std::max(s, (ST)cv_abs(elem[k + 1]));
|
||||
s = std::max(s, (ST)cv_abs(elem[k + 2]));
|
||||
s = std::max(s, (ST)cv_abs(elem[k + 3]));
|
||||
}
|
||||
#endif
|
||||
for (; k < cn; k++) {
|
||||
s = std::max(s, (ST)cv_abs(elem[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename ST>
|
||||
struct MaskedNormL1_SIMD {
|
||||
inline ST operator() (const T* src, const uchar* mask, int len, int cn) const {
|
||||
ST s = 0;
|
||||
if (cn == 1) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
s += (ST)cv_abs(src[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const T* elem = src + i * cn;
|
||||
int k = 0;
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for (; k <= cn - 4; k += 4) {
|
||||
s += (ST)cv_abs(elem[k]);
|
||||
s += (ST)cv_abs(elem[k + 1]);
|
||||
s += (ST)cv_abs(elem[k + 2]);
|
||||
s += (ST)cv_abs(elem[k + 3]);
|
||||
}
|
||||
#endif
|
||||
for (; k < cn; k++) {
|
||||
s += (ST)cv_abs(elem[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename ST>
|
||||
struct MaskedNormL2_SIMD {
|
||||
inline ST operator() (const T* src, const uchar* mask, int len, int cn) const {
|
||||
ST s = 0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for (; i <= len - 4; i += 4) {
|
||||
if (mask[i]) { T v0 = src[i]; s += (ST)v0 * v0; }
|
||||
if (mask[i + 1]) { T v1 = src[i + 1]; s += (ST)v1 * v1; }
|
||||
if (mask[i + 2]) { T v2 = src[i + 2]; s += (ST)v2 * v2; }
|
||||
if (mask[i + 3]) { T v3 = src[i + 3]; s += (ST)v3 * v3; }
|
||||
}
|
||||
#endif
|
||||
for (; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
T v = src[i];
|
||||
s += (ST)v * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const T* elem = src + i * cn;
|
||||
int k = 0;
|
||||
#if CV_ENABLE_UNROLLED
|
||||
for (; k <= cn - 4; k += 4) {
|
||||
T v0 = elem[k]; s += (ST)v0 * v0;
|
||||
T v1 = elem[k + 1]; s += (ST)v1 * v1;
|
||||
T v2 = elem[k + 2]; s += (ST)v2 * v2;
|
||||
T v3 = elem[k + 3]; s += (ST)v3 * v3;
|
||||
}
|
||||
#endif
|
||||
for (; k < cn; k++) {
|
||||
T v = elem[k];
|
||||
s += (ST)v * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaskedNormInf_SIMD<float, float> {
|
||||
inline float operator()(const float* src, const uchar* mask, int len, int cn) const {
|
||||
float result = 0.0f;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_float32>::vlanes();
|
||||
v_float32 acc = vx_setzero_f32();
|
||||
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint32 m = v_reinterpret_as_u32(vx_load_expand(mask + i));
|
||||
v_uint32 cmp = v_gt(m, vx_setzero_u32());
|
||||
v_float32 s = vx_load(src + i);
|
||||
s = v_abs(s);
|
||||
s = v_reinterpret_as_f32(v_and(v_reinterpret_as_u32(s), cmp));
|
||||
acc = v_max(acc, s);
|
||||
}
|
||||
result = v_reduce_max(acc);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i])
|
||||
result = std::max(result, std::abs(src[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const float* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_float32>::vlanes();
|
||||
v_float32 acc = vx_setzero_f32();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
v_float32 s = vx_load(elem + k);
|
||||
acc = v_max(acc, v_abs(s));
|
||||
}
|
||||
|
||||
result = std::max(result, v_reduce_max(acc));
|
||||
|
||||
for (; k < cn; k++)
|
||||
result = std::max(result, std::abs(elem[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#if CV_SIMD_64F
|
||||
template <>
|
||||
struct MaskedNormL1_SIMD<float, double> {
|
||||
inline double operator()(const float* src, const uchar* mask, int len, int cn) const {
|
||||
double result = 0.0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_float32>::vlanes();
|
||||
v_float64 acc = vx_setzero_f64();
|
||||
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint32 cmp = v_gt(vx_load_expand_q(mask + i), vx_setzero_u32());
|
||||
v_float32 s = v_reinterpret_as_f32(v_and(v_reinterpret_as_u32(v_abs(vx_load(src + i))), cmp));
|
||||
acc = v_add(acc, v_cvt_f64(s));
|
||||
acc = v_add(acc, v_cvt_f64_high(s));
|
||||
}
|
||||
result = v_reduce_sum(acc);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i])
|
||||
result += std::abs(src[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const float* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_float32>::vlanes();
|
||||
v_float64 acc = vx_setzero_f64();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
v_float32 s = v_abs(vx_load(elem + k));
|
||||
acc = v_add(acc, v_cvt_f64(s));
|
||||
acc = v_add(acc, v_cvt_f64_high(s));
|
||||
}
|
||||
|
||||
result += v_reduce_sum(acc);
|
||||
|
||||
for (; k < cn; k++)
|
||||
result += std::abs(elem[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaskedNormL2_SIMD<float, double> {
|
||||
inline double operator()(const float* src, const uchar* mask, int len, int cn) const {
|
||||
double result = 0.0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_float32>::vlanes();
|
||||
v_float32 facc = vx_setzero_f32();
|
||||
v_float64 dacc = vx_setzero_f64();
|
||||
int flush = 0;
|
||||
|
||||
for (; i <= len - vstep; i += vstep, flush += vstep) {
|
||||
if (flush >= 64) {
|
||||
dacc = v_add(dacc, v_cvt_f64(facc));
|
||||
dacc = v_add(dacc, v_cvt_f64_high(facc));
|
||||
facc = vx_setzero_f32();
|
||||
flush = 0;
|
||||
}
|
||||
v_uint32 cmp = v_gt(vx_load_expand_q(mask + i), vx_setzero_u32());
|
||||
v_float32 s = v_reinterpret_as_f32(v_and(v_reinterpret_as_u32(vx_load(src + i)), cmp));
|
||||
facc = v_add(facc, v_mul(s, s));
|
||||
}
|
||||
|
||||
dacc = v_add(dacc, v_cvt_f64(facc));
|
||||
dacc = v_add(dacc, v_cvt_f64_high(facc));
|
||||
result = v_reduce_sum(dacc);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
double v = src[i];
|
||||
result += v * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const float* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_float32>::vlanes();
|
||||
v_float32 facc = vx_setzero_f32();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
v_float32 s = vx_load(elem + k);
|
||||
facc = v_add(facc, v_mul(s, s));
|
||||
}
|
||||
|
||||
v_float64 dacc = v_add(v_cvt_f64(facc), v_cvt_f64_high(facc));
|
||||
result += v_reduce_sum(dacc);
|
||||
|
||||
for (; k < cn; k++) {
|
||||
double v = elem[k];
|
||||
result += v * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct MaskedNormInf_SIMD<uchar, int> {
|
||||
inline int operator()(const uchar* src, const uchar* mask, int len, int cn) const {
|
||||
int result = 0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_uint8>::vlanes();
|
||||
v_uint8 acc = vx_setzero_u8();
|
||||
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint8 m = vx_load(mask + i);
|
||||
v_uint8 s = vx_load(src + i);
|
||||
v_uint8 sel = v_and(s, v_gt(m, vx_setzero_u8()));
|
||||
acc = v_max(acc, sel);
|
||||
}
|
||||
|
||||
result = (int)v_reduce_max(acc);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i])
|
||||
result = std::max(result, (int)src[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const uchar* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_uint8>::vlanes();
|
||||
v_uint8 acc = vx_setzero_u8();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
acc = v_max(acc, vx_load(elem + k));
|
||||
}
|
||||
|
||||
result = std::max(result, (int)v_reduce_max(acc));
|
||||
|
||||
for (; k < cn; k++)
|
||||
result = std::max(result, (int)elem[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaskedNormL1_SIMD<uchar, int> {
|
||||
inline int operator()(const uchar* src, const uchar* mask, int len, int cn) const {
|
||||
int result = 0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_uint8>::vlanes() / 4;
|
||||
v_uint32 acc = vx_setzero_u32();
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint32 m = vx_load_expand_q(mask + i);
|
||||
v_uint32 s = vx_load_expand_q(src + i);
|
||||
v_uint32 sel = v_and(s, v_gt(m, vx_setzero_u32()));
|
||||
acc = v_add(acc, sel);
|
||||
}
|
||||
|
||||
result = (int)v_reduce_sum(acc);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i])
|
||||
result += src[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const uchar* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_uint8>::vlanes() / 4;
|
||||
v_uint32 acc = vx_setzero_u32();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
v_uint32 s = vx_load_expand_q(elem + k);
|
||||
acc = v_add(acc, s);
|
||||
}
|
||||
|
||||
result += (int)v_reduce_sum(acc);
|
||||
|
||||
for (; k < cn; k++)
|
||||
result += elem[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaskedNormInf_SIMD<ushort, int> {
|
||||
inline int operator()(const ushort* src, const uchar* mask, int len, int cn) const {
|
||||
int result = 0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_uint16>::vlanes();
|
||||
v_uint16 acc = vx_setzero_u16();
|
||||
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint16 m = vx_load_expand(mask + i);
|
||||
v_uint16 cmp = v_gt(m, vx_setzero_u16());
|
||||
v_uint16 s = vx_load(src + i);
|
||||
v_uint16 sel = v_and(s, cmp);
|
||||
acc = v_max(acc, sel);
|
||||
}
|
||||
|
||||
result = (int)v_reduce_max(acc);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i])
|
||||
result = std::max(result, (int)src[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const ushort* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_uint16>::vlanes();
|
||||
v_uint16 acc = vx_setzero_u16();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
acc = v_max(acc, vx_load(elem + k));
|
||||
}
|
||||
|
||||
result = std::max(result, (int)v_reduce_max(acc));
|
||||
|
||||
for (; k < cn; k++)
|
||||
result = std::max(result, (int)elem[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaskedNormL1_SIMD<ushort, int> {
|
||||
inline int operator()(const ushort* src, const uchar* mask, int len, int cn) const {
|
||||
int result = 0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_uint16>::vlanes();
|
||||
v_uint32 acc32 = vx_setzero_u32();
|
||||
v_uint64 acc64 = vx_setzero_u64();
|
||||
int acc32_elems = 0;
|
||||
|
||||
for (; i <= len - vstep; i += vstep, acc32_elems += vstep) {
|
||||
if (acc32_elems >= 512) {
|
||||
v_uint64 lo64, hi64;
|
||||
v_expand(acc32, lo64, hi64);
|
||||
acc64 = v_add(acc64, v_add(lo64, hi64));
|
||||
acc32 = vx_setzero_u32();
|
||||
acc32_elems = 0;
|
||||
}
|
||||
v_uint16 m = vx_load_expand(mask + i);
|
||||
v_uint16 cmp = v_gt(m, vx_setzero_u16());
|
||||
v_uint16 s = v_and(vx_load(src + i), cmp);
|
||||
v_uint32 lo32, hi32;
|
||||
v_expand(s, lo32, hi32);
|
||||
acc32 = v_add(acc32, v_add(lo32, hi32));
|
||||
}
|
||||
|
||||
v_uint64 lo64, hi64;
|
||||
v_expand(acc32, lo64, hi64);
|
||||
acc64 = v_add(acc64, v_add(lo64, hi64));
|
||||
result = (int)v_reduce_sum(acc64);
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (mask[i])
|
||||
result += src[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const ushort* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_uint16>::vlanes();
|
||||
v_uint32 acc = vx_setzero_u32();
|
||||
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
v_uint32 lo32, hi32;
|
||||
v_expand(vx_load(elem + k), lo32, hi32);
|
||||
acc = v_add(acc, v_add(lo32, hi32));
|
||||
}
|
||||
|
||||
result += (int)v_reduce_sum(acc);
|
||||
|
||||
for (; k < cn; k++)
|
||||
result += elem[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MaskedNormL2_SIMD<ushort, double> {
|
||||
inline double operator()(const ushort* src, const uchar* mask, int len, int cn) const {
|
||||
double result = 0.0;
|
||||
if (cn == 1) {
|
||||
int i = 0;
|
||||
const int vstep = VTraits<v_uint16>::vlanes();
|
||||
v_uint64 acc = vx_setzero_u64();
|
||||
for (; i <= len - vstep; i += vstep) {
|
||||
v_uint16 m = vx_load_expand(mask + i);
|
||||
v_uint16 cmp = v_gt(m, vx_setzero_u16());
|
||||
v_uint16 s = v_and(vx_load(src + i), cmp);
|
||||
v_uint32 lo32, hi32;
|
||||
v_expand(s, lo32, hi32);
|
||||
v_uint64 lo64a, lo64b, hi64a, hi64b;
|
||||
v_expand(v_mul(lo32, lo32), lo64a, lo64b);
|
||||
v_expand(v_mul(hi32, hi32), hi64a, hi64b);
|
||||
acc = v_add(acc, v_add(v_add(lo64a, lo64b), v_add(hi64a, hi64b)));
|
||||
}
|
||||
result = (double)v_reduce_sum(acc);
|
||||
for (; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
double v = src[i];
|
||||
result += v * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (mask[i]) {
|
||||
const ushort* elem = src + i * cn;
|
||||
int k = 0;
|
||||
const int vstep = VTraits<v_uint16>::vlanes();
|
||||
v_uint64 acc = vx_setzero_u64();
|
||||
for (; k <= cn - vstep; k += vstep) {
|
||||
v_uint32 lo32, hi32;
|
||||
v_expand(vx_load(elem + k), lo32, hi32);
|
||||
v_uint64 lo64a, lo64b, hi64a, hi64b;
|
||||
v_expand(v_mul(lo32, lo32), lo64a, lo64b);
|
||||
v_expand(v_mul(hi32, hi32), hi64a, hi64b);
|
||||
acc = v_add(acc, v_add(v_add(lo64a, lo64b), v_add(hi64a, hi64b)));
|
||||
}
|
||||
|
||||
result += (double)v_reduce_sum(acc);
|
||||
|
||||
for (; k < cn; k++) {
|
||||
double v = elem[k];
|
||||
result += v * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename ST> int
|
||||
normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
||||
{
|
||||
@@ -1168,15 +1697,9 @@ normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
||||
{
|
||||
NormInf_SIMD<T, ST> op;
|
||||
result = std::max(result, op(src, len*cn));
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < len; i++, src += cn )
|
||||
if( mask[i] )
|
||||
{
|
||||
for( int k = 0; k < cn; k++ )
|
||||
result = std::max(result, (ST)cv_abs(src[k]));
|
||||
}
|
||||
} else {
|
||||
MaskedNormInf_SIMD<T, ST> op;
|
||||
result = std::max(result, op(src, mask, len, cn));
|
||||
}
|
||||
*_result = result;
|
||||
return 0;
|
||||
@@ -1190,15 +1713,9 @@ normL1_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
||||
{
|
||||
NormL1_SIMD<T, ST> op;
|
||||
result += op(src, len*cn);
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < len; i++, src += cn )
|
||||
if( mask[i] )
|
||||
{
|
||||
for( int k = 0; k < cn; k++ )
|
||||
result += cv_abs(src[k]);
|
||||
}
|
||||
} else {
|
||||
MaskedNormL1_SIMD<T, ST> op;
|
||||
result += op(src, mask, len, cn);
|
||||
}
|
||||
*_result = result;
|
||||
return 0;
|
||||
@@ -1215,15 +1732,8 @@ normL2_(const T* src, const uchar* mask, ST* _result, int len, int cn)
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < len; i++, src += cn )
|
||||
if( mask[i] )
|
||||
{
|
||||
for( int k = 0; k < cn; k++ )
|
||||
{
|
||||
ST v = (ST)src[k];
|
||||
result += v*v;
|
||||
}
|
||||
}
|
||||
MaskedNormL2_SIMD<T, ST> op;
|
||||
result += op(src, mask, len, cn);
|
||||
}
|
||||
*_result = result;
|
||||
return 0;
|
||||
|
||||
@@ -98,6 +98,50 @@ __kernel void copyToMask(__global const uchar * srcptr, int src_step, int src_of
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(SET_DIAG)
|
||||
|
||||
#ifdef cl_khr_fp64
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
|
||||
#endif
|
||||
|
||||
__kernel void setDiag(__global uchar* dst, int dst_step, int dst_offset,
|
||||
int dst_rows, int dst_cols,
|
||||
__global const uchar* src, int src_step, int src_offset,
|
||||
int len)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
int elem_size = (int)sizeof(T1) * cn;
|
||||
int dst_idx = mad24(y, dst_step, mad24(x, elem_size, dst_offset));
|
||||
|
||||
if (x == y && x < len)
|
||||
{
|
||||
#if IS_ROW_VECTOR
|
||||
int src_idx = src_offset + x * elem_size;
|
||||
#else
|
||||
int src_idx = mad24(x, src_step, src_offset);
|
||||
#endif
|
||||
__global T1* dst_ptr = (__global T1*)(dst + dst_idx);
|
||||
__global const T1* src_ptr = (__global const T1*)(src + src_idx);
|
||||
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
dst_ptr[c] = src_ptr[c];
|
||||
}
|
||||
else
|
||||
{
|
||||
__global T1* dst_ptr = (__global T1*)(dst + dst_idx);
|
||||
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
dst_ptr[c] = (T1)0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifndef dstST
|
||||
|
||||
@@ -529,7 +529,6 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
||||
bool write_base64 = (write_mode || append) && (_flags & FileStorage::BASE64) != 0;
|
||||
|
||||
bool isGZ = false;
|
||||
size_t fnamelen = 0;
|
||||
|
||||
std::vector<std::string> params;
|
||||
//if ( !mem_mode )
|
||||
@@ -552,18 +551,30 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
||||
flags = _flags;
|
||||
|
||||
if (!mem_mode) {
|
||||
char *dot_pos = strrchr((char *) filename.c_str(), '.');
|
||||
size_t dot_idx = filename.find_last_of('.');
|
||||
char compression = '\0';
|
||||
|
||||
if (dot_pos && dot_pos[1] == 'g' && dot_pos[2] == 'z' &&
|
||||
(dot_pos[3] == '\0' || (cv_isdigit(dot_pos[3]) && dot_pos[4] == '\0'))) {
|
||||
if (append) {
|
||||
CV_Error(cv::Error::StsNotImplemented, "Appending data to compressed file is not implemented");
|
||||
if (dot_idx != std::string::npos)
|
||||
{
|
||||
std::string ext = filename.substr(dot_idx);
|
||||
|
||||
// Instead of `ext.starts_with(".gz")
|
||||
if (ext.size() >= 3 && (ext[1] == 'g') && (ext[2] == 'z') )
|
||||
{
|
||||
if (ext.size() == 3)
|
||||
{
|
||||
// ".gz"
|
||||
isGZ = true;
|
||||
}
|
||||
|
||||
else if(ext.size() == 4 && cv_isdigit(ext[3]))
|
||||
{
|
||||
// ".gz[0-9]"
|
||||
isGZ = true;
|
||||
compression = ext[3];
|
||||
filename.pop_back(); // Replace `gz[0-9]' to 'gz'.
|
||||
}
|
||||
}
|
||||
isGZ = true;
|
||||
compression = dot_pos[3];
|
||||
if (compression)
|
||||
dot_pos[3] = '\0', fnamelen--;
|
||||
}
|
||||
|
||||
if (!isGZ) {
|
||||
@@ -575,6 +586,9 @@ bool FileStorage::Impl::open(const char *filename_or_buf, int _flags, const char
|
||||
}
|
||||
} else {
|
||||
#if USE_ZLIB
|
||||
if (append) {
|
||||
CV_Error(cv::Error::StsNotImplemented, "Appending data to compressed file is not implemented");
|
||||
}
|
||||
char mode[] = {write_mode ? 'w' : 'r', 'b', compression ? compression : '3', '\0'};
|
||||
gzfile = gzopen(filename.c_str(), mode);
|
||||
if (!gzfile)
|
||||
|
||||
@@ -1029,10 +1029,54 @@ UMat UMat::reshape(int new_cn, int new_rows) const
|
||||
return hdr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
namespace {
|
||||
static bool ocl_setDiag(const UMat& d, UMat& m, int len)
|
||||
{
|
||||
int cn = d.channels();
|
||||
int depth = d.depth();
|
||||
|
||||
if (depth == CV_64F && !ocl::Device::getDefault().doubleFPConfig())
|
||||
return false;
|
||||
|
||||
String opts = format("-D SET_DIAG -D T1=%s -D cn=%d -D IS_ROW_VECTOR=%d",
|
||||
ocl::memopTypeToStr(depth),
|
||||
cn,
|
||||
(d.rows == 1) ? 1 : 0);
|
||||
|
||||
ocl::Kernel k("setDiag", ocl::core::copyset_oclsrc, opts);
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
k.args(ocl::KernelArg::WriteOnly(m),
|
||||
ocl::KernelArg::ReadOnlyNoSize(d),
|
||||
len);
|
||||
|
||||
size_t globalsize[2] = { (size_t)len, (size_t)len };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UMat UMat::diag(const UMat& d, UMatUsageFlags usageFlags)
|
||||
{
|
||||
CV_Assert( d.cols == 1 || d.rows == 1 );
|
||||
CV_INSTRUMENT_REGION();
|
||||
|
||||
CV_Assert(d.cols == 1 || d.rows == 1);
|
||||
int len = d.rows + d.cols - 1;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
if (ocl::useOpenCL())
|
||||
{
|
||||
UMat m(len, len, d.type(), usageFlags);
|
||||
if (ocl_setDiag(d, m, len))
|
||||
{
|
||||
CV_IMPL_ADD(CV_IMPL_OCL);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UMat m(len, len, d.type(), Scalar(0), usageFlags);
|
||||
UMat md = m.diag();
|
||||
if( d.cols == 1 )
|
||||
|
||||
@@ -2995,6 +2995,14 @@ TEST(Core_Norm, NORM_L2_8UC4)
|
||||
EXPECT_EQ(kNorm, cv::norm(a, b, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Core_Norm, NORM_L2SQR_16SC4_large)
|
||||
{
|
||||
const int sizes[] = {1, 116, 40};
|
||||
Mat src(3, sizes, CV_16SC4, Scalar::all(16384));
|
||||
const double expected = static_cast<double>(src.total()) * src.channels() * 16384.0 * 16384.0;
|
||||
EXPECT_EQ(expected, cv::norm(src, NORM_L2SQR));
|
||||
}
|
||||
|
||||
TEST(Core_ConvertTo, regression_12121)
|
||||
{
|
||||
{
|
||||
|
||||
@@ -680,13 +680,26 @@ public:
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
};
|
||||
|
||||
|
||||
CxCore_DFTTest::CxCore_DFTTest() : CxCore_DXTBaseTest( true, true, false )
|
||||
{
|
||||
}
|
||||
|
||||
double CxCore_DFTTest::get_success_error_level( int test_case_idx, int i, int j )
|
||||
{
|
||||
CV_Assert(i == OUTPUT);
|
||||
CV_Assert(j == 0);
|
||||
|
||||
int depth = test_mat[i][j].depth();
|
||||
|
||||
// NOTE: non-default threshold intorduced for ARMPL integration
|
||||
if (depth == CV_32F)
|
||||
return 1.5e-4;
|
||||
|
||||
return CxCore_DXTBaseTest::get_success_error_level(test_case_idx, i, j);
|
||||
}
|
||||
|
||||
void CxCore_DFTTest::run_func()
|
||||
{
|
||||
@@ -745,6 +758,9 @@ public:
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
#if defined(HAVE_ARMPL)
|
||||
double get_success_error_level( int test_case_idx, int i, int j ) CV_OVERRIDE;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -752,6 +768,20 @@ CxCore_DCTTest::CxCore_DCTTest() : CxCore_DXTBaseTest( false, false, false )
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(HAVE_ARMPL)
|
||||
double CxCore_DCTTest::get_success_error_level(int, int i, int j)
|
||||
{
|
||||
CV_Assert(i == OUTPUT);
|
||||
CV_Assert(j == 0);
|
||||
|
||||
int depth = test_mat[i][j].depth();
|
||||
|
||||
if (depth == CV_32F)
|
||||
return 1.67e-5;
|
||||
|
||||
return 1e-12;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CxCore_DCTTest::run_func()
|
||||
{
|
||||
|
||||
@@ -292,17 +292,17 @@ template<typename R> struct TheTest
|
||||
}
|
||||
|
||||
// reinterpret_as
|
||||
v_uint8 vu8 = v_reinterpret_as_u8(r1); out.a.clear(); v_store((uchar*)out.a.d, vu8); EXPECT_EQ(data.a, out.a);
|
||||
v_int8 vs8 = v_reinterpret_as_s8(r1); out.a.clear(); v_store((schar*)out.a.d, vs8); EXPECT_EQ(data.a, out.a);
|
||||
v_uint16 vu16 = v_reinterpret_as_u16(r1); out.a.clear(); v_store((ushort*)out.a.d, vu16); EXPECT_EQ(data.a, out.a);
|
||||
v_int16 vs16 = v_reinterpret_as_s16(r1); out.a.clear(); v_store((short*)out.a.d, vs16); EXPECT_EQ(data.a, out.a);
|
||||
v_uint32 vu32 = v_reinterpret_as_u32(r1); out.a.clear(); v_store((unsigned*)out.a.d, vu32); EXPECT_EQ(data.a, out.a);
|
||||
v_int32 vs32 = v_reinterpret_as_s32(r1); out.a.clear(); v_store((int*)out.a.d, vs32); EXPECT_EQ(data.a, out.a);
|
||||
v_uint64 vu64 = v_reinterpret_as_u64(r1); out.a.clear(); v_store((uint64*)out.a.d, vu64); EXPECT_EQ(data.a, out.a);
|
||||
v_int64 vs64 = v_reinterpret_as_s64(r1); out.a.clear(); v_store((int64*)out.a.d, vs64); EXPECT_EQ(data.a, out.a);
|
||||
v_float32 vf32 = v_reinterpret_as_f32(r1); out.a.clear(); v_store((float*)out.a.d, vf32); EXPECT_EQ(data.a, out.a);
|
||||
AlignedData<R> out_u8; v_uint8 vu8 = v_reinterpret_as_u8(r1); v_store((uchar*)out_u8.a.d, vu8); EXPECT_EQ(data.a, out_u8.a);
|
||||
AlignedData<R> out_s8; v_int8 vs8 = v_reinterpret_as_s8(r1); v_store((schar*)out_s8.a.d, vs8); EXPECT_EQ(data.a, out_s8.a);
|
||||
AlignedData<R> out_u16; v_uint16 vu16 = v_reinterpret_as_u16(r1); v_store((ushort*)out_u16.a.d, vu16); EXPECT_EQ(data.a, out_u16.a);
|
||||
AlignedData<R> out_s16; v_int16 vs16 = v_reinterpret_as_s16(r1); v_store((short*)out_s16.a.d, vs16); EXPECT_EQ(data.a, out_s16.a);
|
||||
AlignedData<R> out_u32; v_uint32 vu32 = v_reinterpret_as_u32(r1); v_store((unsigned*)out_u32.a.d, vu32); EXPECT_EQ(data.a, out_u32.a);
|
||||
AlignedData<R> out_s32; v_int32 vs32 = v_reinterpret_as_s32(r1); v_store((int*)out_s32.a.d, vs32); EXPECT_EQ(data.a, out_s32.a);
|
||||
AlignedData<R> out_u64; v_uint64 vu64 = v_reinterpret_as_u64(r1); v_store((uint64*)out_u64.a.d, vu64); EXPECT_EQ(data.a, out_u64.a);
|
||||
AlignedData<R> out_s64; v_int64 vs64 = v_reinterpret_as_s64(r1); v_store((int64*)out_s64.a.d, vs64); EXPECT_EQ(data.a, out_s64.a);
|
||||
AlignedData<R> out_f32; v_float32 vf32 = v_reinterpret_as_f32(r1); v_store((float*)out_f32.a.d, vf32); EXPECT_EQ(data.a, out_f32.a);
|
||||
#if (CV_SIMD_64F || CV_SIMD_SCALABLE_64F)
|
||||
v_float64 vf64 = v_reinterpret_as_f64(r1); out.a.clear(); v_store((double*)out.a.d, vf64); EXPECT_EQ(data.a, out.a);
|
||||
AlignedData<R> out_f64; v_float64 vf64 = v_reinterpret_as_f64(r1); v_store((double*)out_f64.a.d, vf64); EXPECT_EQ(data.a, out_f64.a);
|
||||
#endif
|
||||
|
||||
#if CV_SIMD_WIDTH == 16
|
||||
|
||||
@@ -2218,9 +2218,19 @@ T fsWriteRead(const T& expectedValue, const char* ext)
|
||||
fs_w.release();
|
||||
|
||||
FileStorage fs_r(fname, FileStorage::READ);
|
||||
|
||||
T value;
|
||||
fs_r["value"] >> value;
|
||||
fs_r.release();
|
||||
|
||||
// If ext is `.gz[0-9]`, fname on storage will end with `.gz`.
|
||||
// FileStorage::Impl::open() truncates the last digit internally.
|
||||
if (isdigit(fname.back()))
|
||||
{
|
||||
fname.pop_back();
|
||||
}
|
||||
|
||||
remove(fname.c_str());
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -2275,7 +2285,7 @@ TEST_P(FileStorage_exact_type, long_int_mat)
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(Core_InputOutput,
|
||||
FileStorage_exact_type, Values(".yml", ".xml", ".json")
|
||||
FileStorage_exact_type, Values(".yml", ".xml", ".json", ".xml.gz", ".xml.gz0", ".xml.gz9")
|
||||
);
|
||||
|
||||
TEST(Core_InputOutput, YAML_Compatibility)
|
||||
|
||||
@@ -1370,6 +1370,8 @@ TEST(Core_Matx, from_initializer_list)
|
||||
Mat_<double> a = (Mat_<double>(2,2) << 10, 11, 12, 13);
|
||||
Matx22d b = {10, 11, 12, 13};
|
||||
ASSERT_EQ( cvtest::norm(a, b, NORM_INF), 0.);
|
||||
Mat_<double> c({2, 2}, {10, 11, 12, 13});
|
||||
ASSERT_EQ( cvtest::norm(c, b, NORM_INF), 0.);
|
||||
}
|
||||
|
||||
TEST(Core_Mat, regression_9507)
|
||||
@@ -1825,6 +1827,11 @@ TEST(Mat, from_initializer_list)
|
||||
auto D = Mat_<double>({2, 3}, {1, 2, 3, 4, 5, 6});
|
||||
EXPECT_EQ(2, D.rows);
|
||||
EXPECT_EQ(3, D.cols);
|
||||
|
||||
double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180);
|
||||
Mat R({2, 2}, {a, -b, b, a});
|
||||
ASSERT_EQ(CV_64FC1, R.type());
|
||||
ASSERT_EQ(cv::Size(2, 2), R.size());
|
||||
}
|
||||
|
||||
TEST(Mat_, from_initializer_list)
|
||||
@@ -1837,6 +1844,11 @@ TEST(Mat_, from_initializer_list)
|
||||
ASSERT_DOUBLE_EQ(cvtest::norm(A, B, NORM_INF), 0.);
|
||||
ASSERT_DOUBLE_EQ(cvtest::norm(A, C, NORM_INF), 0.);
|
||||
ASSERT_DOUBLE_EQ(cvtest::norm(B, C, NORM_INF), 0.);
|
||||
|
||||
double angle = 30, a = cos(angle*CV_PI/180), b = sin(angle*CV_PI/180);
|
||||
Mat_<double> R({2, 2}, {a, -b, b, a});
|
||||
ASSERT_EQ(CV_64FC1, R.type());
|
||||
ASSERT_EQ(cv::Size(2, 2), R.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3617,5 +3617,177 @@ TEST(Core_BFloat, convert)
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// See https://github.com/opencv/opencv/issues/28930
|
||||
typedef testing::TestWithParam<std::tuple<int,int,int,int, int>> Core_Point_DotProduct_regression28930;
|
||||
|
||||
TEST_P(Core_Point_DotProduct_regression28930, basic)
|
||||
{
|
||||
const int x1 = std::get<0>(GetParam());
|
||||
const int y1 = std::get<1>(GetParam());
|
||||
const int x2 = std::get<2>(GetParam());
|
||||
const int y2 = std::get<3>(GetParam());
|
||||
const int expect = std::get<4>(GetParam());
|
||||
|
||||
cv::Point pt1(x1, y1);
|
||||
cv::Point pt2(x2, y2);
|
||||
|
||||
EXPECT_EQ(pt1.dot(pt2), expect) << "Failed for: (" << x1 << "," << y1 << ") dot (" << x2 << "," << y2 << ")";
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/* */, Core_Point_DotProduct_regression28930,
|
||||
testing::Values(
|
||||
// 1. INT_MIN*INT_MIN + INT_MIN*INT_MIN = 2^62 + 2^62 => Saturates to MAX
|
||||
std::make_tuple( INT_MIN, INT_MIN,
|
||||
INT_MIN, INT_MIN,
|
||||
INT_MAX),
|
||||
|
||||
// 2. INT_MIN*INT_MAX + INT_MAX*INT_MAX = 4611686014132420609 + -4611686016279904256 = -2147483647
|
||||
std::make_tuple( INT_MAX, INT_MIN,
|
||||
INT_MAX, INT_MAX,
|
||||
-2147483647),
|
||||
|
||||
// 3. INT_MAX*INT_MAX + INT_MAX*INT_MIN = 4611686014132420609 + -4611686016279904256 = -2147483647
|
||||
std::make_tuple( INT_MAX, INT_MAX,
|
||||
INT_MAX, INT_MIN,
|
||||
-2147483647),
|
||||
|
||||
// 4. 46340^2 = 2147395600 (Under INT_MAX)
|
||||
std::make_tuple( 46340, 0,
|
||||
46340, 0,
|
||||
2147395600),
|
||||
|
||||
// 5. 46341^2 = 2147488281 (Over INT_MAX) => Saturates to MAX
|
||||
std::make_tuple( 46341, 0,
|
||||
46341, 0,
|
||||
INT_MAX),
|
||||
|
||||
// 6. -46340 * 46340 = -2147395600 (Over INT_MIN)
|
||||
std::make_tuple( -46340, 0,
|
||||
46340, 0,
|
||||
-2147395600),
|
||||
|
||||
// 7. -46341 * 46341 = -2147488281 (Under INT_MIN) => Saturates to MIN
|
||||
std::make_tuple( -46341, 0,
|
||||
46341, 0,
|
||||
INT_MIN),
|
||||
|
||||
// 8. Zero
|
||||
std::make_tuple( 0, 0,
|
||||
0, 0,
|
||||
0),
|
||||
|
||||
// 9. Simple max
|
||||
std::make_tuple( INT_MAX, 0,
|
||||
1, 0,
|
||||
INT_MAX)
|
||||
));
|
||||
|
||||
typedef testing::TestWithParam<std::tuple<int,int,int,int,int,int, int>> Core_Point3i_DotProduct_regression28930;
|
||||
|
||||
TEST_P(Core_Point3i_DotProduct_regression28930, basic)
|
||||
{
|
||||
const int x1 = std::get<0>(GetParam());
|
||||
const int y1 = std::get<1>(GetParam());
|
||||
const int z1 = std::get<2>(GetParam());
|
||||
const int x2 = std::get<3>(GetParam());
|
||||
const int y2 = std::get<4>(GetParam());
|
||||
const int z2 = std::get<5>(GetParam());
|
||||
const int expect = std::get<6>(GetParam());
|
||||
|
||||
cv::Point3i pt1(x1, y1, z1);
|
||||
cv::Point3i pt2(x2, y2, z2);
|
||||
|
||||
EXPECT_EQ(pt1.dot(pt2), expect) << "Failed for: (" << x1 << "," << y1 << "," << z1 << ") dot (" << x2 << "," << y2 << "," << z2 << ")";
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(/* */, Core_Point3i_DotProduct_regression28930,
|
||||
testing::Values(
|
||||
// 1. INT_MIN*INT_MIN + INT_MIN*INT_MIN = 2^62 + 2^62 => Saturates to MAX
|
||||
std::make_tuple( INT_MIN, INT_MIN, 0,
|
||||
INT_MIN, INT_MIN, 0,
|
||||
INT_MAX),
|
||||
|
||||
// 2. INT_MIN*INT_MAX + INT_MAX*INT_MAX = 4611686014132420609 + -4611686016279904256 = -2147483647
|
||||
std::make_tuple( INT_MAX, INT_MIN, 0,
|
||||
INT_MAX, INT_MAX, 0,
|
||||
-2147483647),
|
||||
|
||||
// 3. INT_MAX*INT_MAX + INT_MAX*INT_MIN = 4611686014132420609 + -4611686016279904256 = -2147483647
|
||||
std::make_tuple( INT_MAX, INT_MAX, 0,
|
||||
INT_MAX, INT_MIN, 0,
|
||||
-2147483647),
|
||||
|
||||
// 4. 46340^2 = 2147395600 (Under INT_MAX)
|
||||
std::make_tuple( 46340, 0, 0,
|
||||
46340, 0, 0,
|
||||
2147395600),
|
||||
|
||||
// 5. 46341^2 = 2147488281 (Over INT_MAX) => Saturates to MAX
|
||||
std::make_tuple( 46341, 0, 0,
|
||||
46341, 0, 0,
|
||||
INT_MAX),
|
||||
|
||||
// 6. -46340 * 46340 = -2147395600 (Over INT_MIN)
|
||||
std::make_tuple( -46340, 0, 0,
|
||||
46340, 0, 0,
|
||||
-2147395600),
|
||||
|
||||
// 7. -46341 * 46341 = -2147488281 (Under INT_MIN) => Saturates to MIN
|
||||
std::make_tuple( -46341, 0, 0,
|
||||
46341, 0, 0,
|
||||
INT_MIN),
|
||||
|
||||
// 8. Zero
|
||||
std::make_tuple( 0, 0, 0,
|
||||
0, 0, 0,
|
||||
0),
|
||||
|
||||
// 9. Simple max
|
||||
std::make_tuple( INT_MAX, 0, 0,
|
||||
1, 0, 0,
|
||||
INT_MAX),
|
||||
|
||||
// 10. All positive, no overflow
|
||||
std::make_tuple( 1, 2, 3,
|
||||
4, 5, 6,
|
||||
(1*4 + 2*5 + 3*6)),
|
||||
|
||||
// 11. All negative, no overflow
|
||||
std::make_tuple( -1, -2, -3,
|
||||
-4, -5, -6,
|
||||
(-1*-4 + -2*-5 + -3*-6)),
|
||||
|
||||
// 12. Three large positive products => saturate to MAX
|
||||
std::make_tuple( INT_MAX, INT_MAX, INT_MAX,
|
||||
INT_MAX, INT_MAX, INT_MAX,
|
||||
INT_MAX),
|
||||
|
||||
// 13. Three large positive products from INT_MIN*INT_MIN => saturate to MAX
|
||||
std::make_tuple( INT_MIN, INT_MIN, INT_MIN,
|
||||
INT_MIN, INT_MIN, INT_MIN,
|
||||
INT_MAX),
|
||||
|
||||
// 14. Three large negative products => saturate to MIN
|
||||
std::make_tuple( INT_MIN, INT_MIN, INT_MIN,
|
||||
INT_MAX, INT_MAX, INT_MAX,
|
||||
INT_MIN),
|
||||
|
||||
// 15. Mixed signs: + + -
|
||||
std::make_tuple( INT_MAX, INT_MAX, INT_MIN,
|
||||
INT_MAX, INT_MAX, INT_MAX,
|
||||
INT_MAX),
|
||||
|
||||
// 16. Mixed signs: + - +
|
||||
std::make_tuple( INT_MAX, INT_MIN, INT_MAX,
|
||||
INT_MAX, INT_MAX, INT_MAX,
|
||||
INT_MAX),
|
||||
|
||||
// 17. Mixed signs: - + -
|
||||
std::make_tuple( INT_MIN, INT_MAX, INT_MIN,
|
||||
INT_MAX, INT_MAX, INT_MAX,
|
||||
INT_MIN)
|
||||
));
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
|
||||
Reference in New Issue
Block a user