
srcnativelibs.Include.OpenCV.opencv2.core.operations.hpp Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sikulixlibslux Show documentation
Show all versions of sikulixlibslux Show documentation
... for visual testing and automation (Linux native support)
The newest version!
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_CORE_OPERATIONS_HPP__
#define __OPENCV_CORE_OPERATIONS_HPP__
#ifndef SKIP_INCLUDES
#include
#include
#endif // SKIP_INCLUDES
#ifdef __cplusplus
/////// exchange-add operation for atomic operations on reference counters ///////
#if defined __INTEL_COMPILER && !(defined WIN32 || defined _WIN32) // atomic increment on the linux version of the Intel(tm) compiler
#define CV_XADD(addr,delta) _InterlockedExchangeAdd(const_cast(reinterpret_cast(addr)), delta)
#elif defined __GNUC__
#if defined __clang__ && __clang_major__ >= 3 && !defined __ANDROID__ && !defined __EMSCRIPTEN__
#ifdef __ATOMIC_SEQ_CST
#define CV_XADD(addr, delta) __c11_atomic_fetch_add((_Atomic(int)*)(addr), (delta), __ATOMIC_SEQ_CST)
#else
#define CV_XADD(addr, delta) __atomic_fetch_add((_Atomic(int)*)(addr), (delta), 5)
#endif
#elif __GNUC__*10 + __GNUC_MINOR__ >= 42
#if !(defined WIN32 || defined _WIN32) && (defined __i486__ || defined __i586__ || \
defined __i686__ || defined __MMX__ || defined __SSE__ || defined __ppc__) || \
(defined __GNUC__ && defined _STLPORT_MAJOR) || \
defined __EMSCRIPTEN__
#define CV_XADD __sync_fetch_and_add
#else
#include
#define CV_XADD __gnu_cxx::__exchange_and_add
#endif
#else
#include
#if __GNUC__*10 + __GNUC_MINOR__ >= 34
#define CV_XADD __gnu_cxx::__exchange_and_add
#else
#define CV_XADD __exchange_and_add
#endif
#endif
#elif defined WIN32 || defined _WIN32 || defined WINCE
namespace cv { CV_EXPORTS int _interlockedExchangeAdd(int* addr, int delta); }
#define CV_XADD cv::_interlockedExchangeAdd
#else
static inline int CV_XADD(int* addr, int delta)
{ int tmp = *addr; *addr += delta; return tmp; }
#endif
#include
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4127) //conditional expression is constant
#endif
namespace cv
{
using std::cos;
using std::sin;
using std::max;
using std::min;
using std::exp;
using std::log;
using std::pow;
using std::sqrt;
/////////////// saturate_cast (used in image & signal processing) ///////////////////
template static inline _Tp saturate_cast(uchar v) { return _Tp(v); }
template static inline _Tp saturate_cast(schar v) { return _Tp(v); }
template static inline _Tp saturate_cast(ushort v) { return _Tp(v); }
template static inline _Tp saturate_cast(short v) { return _Tp(v); }
template static inline _Tp saturate_cast(unsigned v) { return _Tp(v); }
template static inline _Tp saturate_cast(int v) { return _Tp(v); }
template static inline _Tp saturate_cast(float v) { return _Tp(v); }
template static inline _Tp saturate_cast(double v) { return _Tp(v); }
template<> inline uchar saturate_cast(schar v)
{ return (uchar)std::max((int)v, 0); }
template<> inline uchar saturate_cast(ushort v)
{ return (uchar)std::min((unsigned)v, (unsigned)UCHAR_MAX); }
template<> inline uchar saturate_cast(int v)
{ return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }
template<> inline uchar saturate_cast(short v)
{ return saturate_cast((int)v); }
template<> inline uchar saturate_cast(unsigned v)
{ return (uchar)std::min(v, (unsigned)UCHAR_MAX); }
template<> inline uchar saturate_cast(float v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline uchar saturate_cast(double v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline schar saturate_cast(uchar v)
{ return (schar)std::min((int)v, SCHAR_MAX); }
template<> inline schar saturate_cast(ushort v)
{ return (schar)std::min((unsigned)v, (unsigned)SCHAR_MAX); }
template<> inline schar saturate_cast(int v)
{
return (schar)((unsigned)(v-SCHAR_MIN) <= (unsigned)UCHAR_MAX ?
v : v > 0 ? SCHAR_MAX : SCHAR_MIN);
}
template<> inline schar saturate_cast(short v)
{ return saturate_cast((int)v); }
template<> inline schar saturate_cast(unsigned v)
{ return (schar)std::min(v, (unsigned)SCHAR_MAX); }
template<> inline schar saturate_cast(float v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline schar saturate_cast(double v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline ushort saturate_cast(schar v)
{ return (ushort)std::max((int)v, 0); }
template<> inline ushort saturate_cast(short v)
{ return (ushort)std::max((int)v, 0); }
template<> inline ushort saturate_cast(int v)
{ return (ushort)((unsigned)v <= (unsigned)USHRT_MAX ? v : v > 0 ? USHRT_MAX : 0); }
template<> inline ushort saturate_cast(unsigned v)
{ return (ushort)std::min(v, (unsigned)USHRT_MAX); }
template<> inline ushort saturate_cast(float v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline ushort saturate_cast(double v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline short saturate_cast(ushort v)
{ return (short)std::min((int)v, SHRT_MAX); }
template<> inline short saturate_cast(int v)
{
return (short)((unsigned)(v - SHRT_MIN) <= (unsigned)USHRT_MAX ?
v : v > 0 ? SHRT_MAX : SHRT_MIN);
}
template<> inline short saturate_cast(unsigned v)
{ return (short)std::min(v, (unsigned)SHRT_MAX); }
template<> inline short saturate_cast(float v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline short saturate_cast(double v)
{ int iv = cvRound(v); return saturate_cast(iv); }
template<> inline int saturate_cast(float v) { return cvRound(v); }
template<> inline int saturate_cast(double v) { return cvRound(v); }
// we intentionally do not clip negative numbers, to make -1 become 0xffffffff etc.
template<> inline unsigned saturate_cast(float v){ return cvRound(v); }
template<> inline unsigned saturate_cast(double v) { return cvRound(v); }
inline int fast_abs(uchar v) { return v; }
inline int fast_abs(schar v) { return std::abs((int)v); }
inline int fast_abs(ushort v) { return v; }
inline int fast_abs(short v) { return std::abs((int)v); }
inline int fast_abs(int v) { return std::abs(v); }
inline float fast_abs(float v) { return std::abs(v); }
inline double fast_abs(double v) { return std::abs(v); }
//////////////////////////////// Matx /////////////////////////////////
template inline Matx<_Tp, m, n>::Matx()
{
for(int i = 0; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0)
{
val[0] = v0;
for(int i = 1; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1)
{
assert(channels >= 2);
val[0] = v0; val[1] = v1;
for(int i = 2; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2)
{
assert(channels >= 3);
val[0] = v0; val[1] = v1; val[2] = v2;
for(int i = 3; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
{
assert(channels >= 4);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
for(int i = 4; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4)
{
assert(channels >= 5);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4;
for(int i = 5; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5)
{
assert(channels >= 6);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5;
for(int i = 6; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6)
{
assert(channels >= 7);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5; val[6] = v6;
for(int i = 7; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7)
{
assert(channels >= 8);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
for(int i = 8; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8)
{
assert(channels >= 9);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
val[8] = v8;
for(int i = 9; i < channels; i++) val[i] = _Tp(0);
}
template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8, _Tp v9)
{
assert(channels >= 10);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
val[8] = v8; val[9] = v9;
for(int i = 10; i < channels; i++) val[i] = _Tp(0);
}
template
inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8, _Tp v9, _Tp v10, _Tp v11)
{
assert(channels == 12);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11;
}
template
inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8, _Tp v9, _Tp v10, _Tp v11,
_Tp v12, _Tp v13, _Tp v14, _Tp v15)
{
assert(channels == 16);
val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11;
val[12] = v12; val[13] = v13; val[14] = v14; val[15] = v15;
}
template inline Matx<_Tp, m, n>::Matx(const _Tp* values)
{
for( int i = 0; i < channels; i++ ) val[i] = values[i];
}
template inline Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha)
{
Matx<_Tp, m, n> M;
for( int i = 0; i < m*n; i++ ) M.val[i] = alpha;
return M;
}
template inline
Matx<_Tp,m,n> Matx<_Tp,m,n>::zeros()
{
return all(0);
}
template inline
Matx<_Tp,m,n> Matx<_Tp,m,n>::ones()
{
return all(1);
}
template inline
Matx<_Tp,m,n> Matx<_Tp,m,n>::eye()
{
Matx<_Tp,m,n> M;
for(int i = 0; i < MIN(m,n); i++)
M(i,i) = 1;
return M;
}
template inline _Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const
{
_Tp s = 0;
for( int i = 0; i < m*n; i++ ) s += val[i]*M.val[i];
return s;
}
template inline double Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const
{
double s = 0;
for( int i = 0; i < m*n; i++ ) s += (double)val[i]*M.val[i];
return s;
}
template inline
Matx<_Tp,m,n> Matx<_Tp,m,n>::diag(const typename Matx<_Tp,m,n>::diag_type& d)
{
Matx<_Tp,m,n> M;
for(int i = 0; i < MIN(m,n); i++)
M(i,i) = d(i, 0);
return M;
}
template inline
Matx<_Tp,m,n> Matx<_Tp,m,n>::randu(_Tp a, _Tp b)
{
Matx<_Tp,m,n> M;
Mat matM(M, false);
cv::randu(matM, Scalar(a), Scalar(b));
return M;
}
template inline
Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b)
{
Matx<_Tp,m,n> M;
Mat matM(M, false);
cv::randn(matM, Scalar(a), Scalar(b));
return M;
}
template template
inline Matx<_Tp, m, n>::operator Matx() const
{
Matx M;
for( int i = 0; i < m*n; i++ ) M.val[i] = saturate_cast(val[i]);
return M;
}
template template inline
Matx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const
{
CV_DbgAssert(m1*n1 == m*n);
return (const Matx<_Tp, m1, n1>&)*this;
}
template
template inline
Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const
{
CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n);
Matx<_Tp, m1, n1> s;
for( int di = 0; di < m1; di++ )
for( int dj = 0; dj < n1; dj++ )
s(di, dj) = (*this)(i+di, j+dj);
return s;
}
template inline
Matx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const
{
CV_DbgAssert((unsigned)i < (unsigned)m);
return Matx<_Tp, 1, n>(&val[i*n]);
}
template inline
Matx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const
{
CV_DbgAssert((unsigned)j < (unsigned)n);
Matx<_Tp, m, 1> v;
for( int i = 0; i < m; i++ )
v.val[i] = val[i*n + j];
return v;
}
template inline
typename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const
{
diag_type d;
for( int i = 0; i < MIN(m, n); i++ )
d.val[i] = val[i*n + i];
return d;
}
template inline
const _Tp& Matx<_Tp, m, n>::operator ()(int i, int j) const
{
CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );
return this->val[i*n + j];
}
template inline
_Tp& Matx<_Tp, m, n>::operator ()(int i, int j)
{
CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );
return val[i*n + j];
}
template inline
const _Tp& Matx<_Tp, m, n>::operator ()(int i) const
{
CV_DbgAssert( (m == 1 || n == 1) && (unsigned)i < (unsigned)(m+n-1) );
return val[i];
}
template inline
_Tp& Matx<_Tp, m, n>::operator ()(int i)
{
CV_DbgAssert( (m == 1 || n == 1) && (unsigned)i < (unsigned)(m+n-1) );
return val[i];
}
template static inline
Matx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b)
{
for( int i = 0; i < m*n; i++ )
a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);
return a;
}
template static inline
Matx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b)
{
for( int i = 0; i < m*n; i++ )
a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);
return a;
}
template inline
Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp)
{
for( int i = 0; i < m*n; i++ )
val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]);
}
template inline
Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp)
{
for( int i = 0; i < m*n; i++ )
val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]);
}
template template inline
Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp)
{
for( int i = 0; i < m*n; i++ )
val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
}
template inline
Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp)
{
for( int i = 0; i < m*n; i++ )
val[i] = saturate_cast<_Tp>(a.val[i] * b.val[i]);
}
template template inline
Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp)
{
for( int i = 0; i < m; i++ )
for( int j = 0; j < n; j++ )
{
_Tp s = 0;
for( int k = 0; k < l; k++ )
s += a(i, k) * b(k, j);
val[i*n + j] = s;
}
}
template inline
Matx<_Tp,m,n>::Matx(const Matx<_Tp, n, m>& a, Matx_TOp)
{
for( int i = 0; i < m; i++ )
for( int j = 0; j < n; j++ )
val[i*n + j] = a(j, i);
}
template static inline
Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
{
return Matx<_Tp, m, n>(a, b, Matx_AddOp());
}
template static inline
Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
{
return Matx<_Tp, m, n>(a, b, Matx_SubOp());
}
template static inline
Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha)
{
for( int i = 0; i < m*n; i++ )
a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
return a;
}
template static inline
Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha)
{
for( int i = 0; i < m*n; i++ )
a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
return a;
}
template static inline
Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha)
{
for( int i = 0; i < m*n; i++ )
a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
return a;
}
template static inline
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha)
{
return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha)
{
return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha)
{
return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a)
{
return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a)
{
return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a)
{
return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a)
{
return Matx<_Tp, m, n>(a, -1, Matx_ScaleOp());
}
template static inline
Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b)
{
return Matx<_Tp, m, n>(a, b, Matx_MatMulOp());
}
template static inline
Vec<_Tp, m> operator * (const Matx<_Tp, m, n>& a, const Vec<_Tp, n>& b)
{
Matx<_Tp, m, 1> c(a, b, Matx_MatMulOp());
return reinterpret_cast&>(c);
}
template static inline
Point_<_Tp> operator * (const Matx<_Tp, 2, 2>& a, const Point_<_Tp>& b)
{
Matx<_Tp, 2, 1> tmp = a*Vec<_Tp,2>(b.x, b.y);
return Point_<_Tp>(tmp.val[0], tmp.val[1]);
}
template static inline
Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point3_<_Tp>& b)
{
Matx<_Tp, 3, 1> tmp = a*Vec<_Tp,3>(b.x, b.y, b.z);
return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]);
}
template static inline
Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point_<_Tp>& b)
{
Matx<_Tp, 3, 1> tmp = a*Vec<_Tp,3>(b.x, b.y, 1);
return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]);
}
template static inline
Matx<_Tp, 4, 1> operator * (const Matx<_Tp, 4, 4>& a, const Point3_<_Tp>& b)
{
return a*Matx<_Tp, 4, 1>(b.x, b.y, b.z, 1);
}
template static inline
Scalar operator * (const Matx<_Tp, 4, 4>& a, const Scalar& b)
{
Matx c(Matx(a), b, Matx_MatMulOp());
return static_cast(c);
}
static inline
Scalar operator * (const Matx& a, const Scalar& b)
{
Matx c(a, b, Matx_MatMulOp());
return static_cast(c);
}
template inline
Matx<_Tp, m, n> Matx<_Tp, m, n>::mul(const Matx<_Tp, m, n>& a) const
{
return Matx<_Tp, m, n>(*this, a, Matx_MulOp());
}
CV_EXPORTS int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n);
CV_EXPORTS int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n);
CV_EXPORTS bool Cholesky(float* A, size_t astep, int m, float* b, size_t bstep, int n);
CV_EXPORTS bool Cholesky(double* A, size_t astep, int m, double* b, size_t bstep, int n);
template struct Matx_DetOp
{
double operator ()(const Matx<_Tp, m, m>& a) const
{
Matx<_Tp, m, m> temp = a;
double p = LU(temp.val, m*sizeof(_Tp), m, 0, 0, 0);
if( p == 0 )
return p;
for( int i = 0; i < m; i++ )
p *= temp(i, i);
return 1./p;
}
};
template struct Matx_DetOp<_Tp, 1>
{
double operator ()(const Matx<_Tp, 1, 1>& a) const
{
return a(0,0);
}
};
template struct Matx_DetOp<_Tp, 2>
{
double operator ()(const Matx<_Tp, 2, 2>& a) const
{
return a(0,0)*a(1,1) - a(0,1)*a(1,0);
}
};
template struct Matx_DetOp<_Tp, 3>
{
double operator ()(const Matx<_Tp, 3, 3>& a) const
{
return a(0,0)*(a(1,1)*a(2,2) - a(2,1)*a(1,2)) -
a(0,1)*(a(1,0)*a(2,2) - a(2,0)*a(1,2)) +
a(0,2)*(a(1,0)*a(2,1) - a(2,0)*a(1,1));
}
};
template static inline
double determinant(const Matx<_Tp, m, m>& a)
{
return Matx_DetOp<_Tp, m>()(a);
}
template static inline
double trace(const Matx<_Tp, m, n>& a)
{
_Tp s = 0;
for( int i = 0; i < std::min(m, n); i++ )
s += a(i,i);
return s;
}
template inline
Matx<_Tp, n, m> Matx<_Tp, m, n>::t() const
{
return Matx<_Tp, n, m>(*this, Matx_TOp());
}
template struct Matx_FastInvOp
{
bool operator()(const Matx<_Tp, m, m>& a, Matx<_Tp, m, m>& b, int method) const
{
Matx<_Tp, m, m> temp = a;
// assume that b is all 0's on input => make it a unity matrix
for( int i = 0; i < m; i++ )
b(i, i) = (_Tp)1;
if( method == DECOMP_CHOLESKY )
return Cholesky(temp.val, m*sizeof(_Tp), m, b.val, m*sizeof(_Tp), m);
return LU(temp.val, m*sizeof(_Tp), m, b.val, m*sizeof(_Tp), m) != 0;
}
};
template struct Matx_FastInvOp<_Tp, 2>
{
bool operator()(const Matx<_Tp, 2, 2>& a, Matx<_Tp, 2, 2>& b, int) const
{
_Tp d = determinant(a);
if( d == 0 )
return false;
d = 1/d;
b(1,1) = a(0,0)*d;
b(0,0) = a(1,1)*d;
b(0,1) = -a(0,1)*d;
b(1,0) = -a(1,0)*d;
return true;
}
};
template struct Matx_FastInvOp<_Tp, 3>
{
bool operator()(const Matx<_Tp, 3, 3>& a, Matx<_Tp, 3, 3>& b, int) const
{
_Tp d = (_Tp)determinant(a);
if( d == 0 )
return false;
d = 1/d;
b(0,0) = (a(1,1) * a(2,2) - a(1,2) * a(2,1)) * d;
b(0,1) = (a(0,2) * a(2,1) - a(0,1) * a(2,2)) * d;
b(0,2) = (a(0,1) * a(1,2) - a(0,2) * a(1,1)) * d;
b(1,0) = (a(1,2) * a(2,0) - a(1,0) * a(2,2)) * d;
b(1,1) = (a(0,0) * a(2,2) - a(0,2) * a(2,0)) * d;
b(1,2) = (a(0,2) * a(1,0) - a(0,0) * a(1,2)) * d;
b(2,0) = (a(1,0) * a(2,1) - a(1,1) * a(2,0)) * d;
b(2,1) = (a(0,1) * a(2,0) - a(0,0) * a(2,1)) * d;
b(2,2) = (a(0,0) * a(1,1) - a(0,1) * a(1,0)) * d;
return true;
}
};
template inline
Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const
{
Matx<_Tp, n, m> b;
bool ok;
if( method == DECOMP_LU || method == DECOMP_CHOLESKY )
ok = Matx_FastInvOp<_Tp, m>()(*this, b, method);
else
{
Mat A(*this, false), B(b, false);
ok = (invert(A, B, method) != 0);
}
return ok ? b : Matx<_Tp, n, m>::zeros();
}
template struct Matx_FastSolveOp
{
bool operator()(const Matx<_Tp, m, m>& a, const Matx<_Tp, m, n>& b,
Matx<_Tp, m, n>& x, int method) const
{
Matx<_Tp, m, m> temp = a;
x = b;
if( method == DECOMP_CHOLESKY )
return Cholesky(temp.val, m*sizeof(_Tp), m, x.val, n*sizeof(_Tp), n);
return LU(temp.val, m*sizeof(_Tp), m, x.val, n*sizeof(_Tp), n) != 0;
}
};
template struct Matx_FastSolveOp<_Tp, 2, 1>
{
bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b,
Matx<_Tp, 2, 1>& x, int) const
{
_Tp d = determinant(a);
if( d == 0 )
return false;
d = 1/d;
x(0) = (b(0)*a(1,1) - b(1)*a(0,1))*d;
x(1) = (b(1)*a(0,0) - b(0)*a(1,0))*d;
return true;
}
};
template struct Matx_FastSolveOp<_Tp, 3, 1>
{
bool operator()(const Matx<_Tp, 3, 3>& a, const Matx<_Tp, 3, 1>& b,
Matx<_Tp, 3, 1>& x, int) const
{
_Tp d = (_Tp)determinant(a);
if( d == 0 )
return false;
d = 1/d;
x(0) = d*(b(0)*(a(1,1)*a(2,2) - a(1,2)*a(2,1)) -
a(0,1)*(b(1)*a(2,2) - a(1,2)*b(2)) +
a(0,2)*(b(1)*a(2,1) - a(1,1)*b(2)));
x(1) = d*(a(0,0)*(b(1)*a(2,2) - a(1,2)*b(2)) -
b(0)*(a(1,0)*a(2,2) - a(1,2)*a(2,0)) +
a(0,2)*(a(1,0)*b(2) - b(1)*a(2,0)));
x(2) = d*(a(0,0)*(a(1,1)*b(2) - b(1)*a(2,1)) -
a(0,1)*(a(1,0)*b(2) - b(1)*a(2,0)) +
b(0)*(a(1,0)*a(2,1) - a(1,1)*a(2,0)));
return true;
}
};
template template inline
Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) const
{
Matx<_Tp, n, l> x;
bool ok;
if( method == DECOMP_LU || method == DECOMP_CHOLESKY )
ok = Matx_FastSolveOp<_Tp, m, l>()(*this, rhs, x, method);
else
{
Mat A(*this, false), B(rhs, false), X(x, false);
ok = cv::solve(A, B, X, method);
}
return ok ? x : Matx<_Tp, n, l>::zeros();
}
template inline
Vec<_Tp, n> Matx<_Tp, m, n>::solve(const Vec<_Tp, m>& rhs, int method) const
{
Matx<_Tp, n, 1> x = solve(reinterpret_cast&>(rhs), method);
return reinterpret_cast&>(x);
}
template static inline
_AccTp normL2Sqr(const _Tp* a, int n)
{
_AccTp s = 0;
int i=0;
#if CV_ENABLE_UNROLLED
for( ; i <= n - 4; i += 4 )
{
_AccTp v0 = a[i], v1 = a[i+1], v2 = a[i+2], v3 = a[i+3];
s += v0*v0 + v1*v1 + v2*v2 + v3*v3;
}
#endif
for( ; i < n; i++ )
{
_AccTp v = a[i];
s += v*v;
}
return s;
}
template static inline
_AccTp normL1(const _Tp* a, int n)
{
_AccTp s = 0;
int i = 0;
#if CV_ENABLE_UNROLLED
for(; i <= n - 4; i += 4 )
{
s += (_AccTp)fast_abs(a[i]) + (_AccTp)fast_abs(a[i+1]) +
(_AccTp)fast_abs(a[i+2]) + (_AccTp)fast_abs(a[i+3]);
}
#endif
for( ; i < n; i++ )
s += fast_abs(a[i]);
return s;
}
template static inline
_AccTp normInf(const _Tp* a, int n)
{
_AccTp s = 0;
for( int i = 0; i < n; i++ )
s = std::max(s, (_AccTp)fast_abs(a[i]));
return s;
}
template static inline
_AccTp normL2Sqr(const _Tp* a, const _Tp* b, int n)
{
_AccTp s = 0;
int i= 0;
#if CV_ENABLE_UNROLLED
for(; i <= n - 4; i += 4 )
{
_AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]);
s += v0*v0 + v1*v1 + v2*v2 + v3*v3;
}
#endif
for( ; i < n; i++ )
{
_AccTp v = _AccTp(a[i] - b[i]);
s += v*v;
}
return s;
}
CV_EXPORTS float normL2Sqr_(const float* a, const float* b, int n);
CV_EXPORTS float normL1_(const float* a, const float* b, int n);
CV_EXPORTS int normL1_(const uchar* a, const uchar* b, int n);
CV_EXPORTS int normHamming(const uchar* a, const uchar* b, int n);
CV_EXPORTS int normHamming(const uchar* a, const uchar* b, int n, int cellSize);
template<> inline float normL2Sqr(const float* a, const float* b, int n)
{
if( n >= 8 )
return normL2Sqr_(a, b, n);
float s = 0;
for( int i = 0; i < n; i++ )
{
float v = a[i] - b[i];
s += v*v;
}
return s;
}
template static inline
_AccTp normL1(const _Tp* a, const _Tp* b, int n)
{
_AccTp s = 0;
int i= 0;
#if CV_ENABLE_UNROLLED
for(; i <= n - 4; i += 4 )
{
_AccTp v0 = _AccTp(a[i] - b[i]), v1 = _AccTp(a[i+1] - b[i+1]), v2 = _AccTp(a[i+2] - b[i+2]), v3 = _AccTp(a[i+3] - b[i+3]);
s += std::abs(v0) + std::abs(v1) + std::abs(v2) + std::abs(v3);
}
#endif
for( ; i < n; i++ )
{
_AccTp v = _AccTp(a[i] - b[i]);
s += std::abs(v);
}
return s;
}
template<> inline float normL1(const float* a, const float* b, int n)
{
if( n >= 8 )
return normL1_(a, b, n);
float s = 0;
for( int i = 0; i < n; i++ )
{
float v = a[i] - b[i];
s += std::abs(v);
}
return s;
}
template<> inline int normL1(const uchar* a, const uchar* b, int n)
{
return normL1_(a, b, n);
}
template static inline
_AccTp normInf(const _Tp* a, const _Tp* b, int n)
{
_AccTp s = 0;
for( int i = 0; i < n; i++ )
{
_AccTp v0 = a[i] - b[i];
s = std::max(s, std::abs(v0));
}
return s;
}
template static inline
double norm(const Matx<_Tp, m, n>& M)
{
return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n));
}
template static inline
double norm(const Matx<_Tp, m, n>& M, int normType)
{
return normType == NORM_INF ? (double)normInf<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) :
normType == NORM_L1 ? (double)normL1<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) :
std::sqrt((double)normL2Sqr<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n));
}
template static inline
bool operator == (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
{
for( int i = 0; i < m*n; i++ )
if( a.val[i] != b.val[i] ) return false;
return true;
}
template static inline
bool operator != (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
{
return !(a == b);
}
template 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);
return (commaInitializer, val);
}
template inline
MatxCommaInitializer<_Tp, m, n>::MatxCommaInitializer(Matx<_Tp, m, n>* _mtx)
: dst(_mtx), idx(0)
{}
template template inline
MatxCommaInitializer<_Tp, m, n>& MatxCommaInitializer<_Tp, m, n>::operator , (_T2 value)
{
CV_DbgAssert( idx < m*n );
dst->val[idx++] = saturate_cast<_Tp>(value);
return *this;
}
template inline
Matx<_Tp, m, n> MatxCommaInitializer<_Tp, m, n>::operator *() const
{
CV_DbgAssert( idx == n*m );
return *dst;
}
/////////////////////////// short vector (Vec) /////////////////////////////
template inline Vec<_Tp, cn>::Vec()
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0)
: Matx<_Tp, cn, 1>(v0)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1)
: Matx<_Tp, cn, 1>(v0, v1)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2)
: Matx<_Tp, cn, 1>(v0, v1, v2)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8)
{}
template inline Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
_Tp v4, _Tp v5, _Tp v6, _Tp v7,
_Tp v8, _Tp v9)
: Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9)
{}
template inline Vec<_Tp, cn>::Vec(const _Tp* values)
: Matx<_Tp, cn, 1>(values)
{}
template inline Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m)
: Matx<_Tp, cn, 1>(m.val)
{}
template inline
Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp op)
: Matx<_Tp, cn, 1>(a, b, op)
{}
template inline
Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp op)
: Matx<_Tp, cn, 1>(a, b, op)
{}
template template inline
Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp op)
: Matx<_Tp, cn, 1>(a, alpha, op)
{}
template inline Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha)
{
Vec v;
for( int i = 0; i < cn; i++ ) v.val[i] = alpha;
return v;
}
template inline Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const
{
Vec<_Tp, cn> w;
for( int i = 0; i < cn; i++ ) w.val[i] = saturate_cast<_Tp>(this->val[i]*v.val[i]);
return w;
}
template Vec<_Tp, 2> conjugate(const Vec<_Tp, 2>& v)
{
return Vec<_Tp, 2>(v[0], -v[1]);
}
template Vec<_Tp, 4> conjugate(const Vec<_Tp, 4>& v)
{
return Vec<_Tp, 4>(v[0], -v[1], -v[2], -v[3]);
}
template<> inline Vec Vec::conj() const
{
return conjugate(*this);
}
template<> inline Vec Vec::conj() const
{
return conjugate(*this);
}
template<> inline Vec Vec::conj() const
{
return conjugate(*this);
}
template<> inline Vec Vec::conj() const
{
return conjugate(*this);
}
template inline Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>&) const
{
CV_Error(CV_StsError, "for arbitrary-size vector there is no cross-product defined");
return Vec<_Tp, cn>();
}
template template
inline Vec<_Tp, cn>::operator Vec() const
{
Vec v;
for( int i = 0; i < cn; i++ ) v.val[i] = saturate_cast(this->val[i]);
return v;
}
template inline Vec<_Tp, cn>::operator CvScalar() const
{
CvScalar s = {{0,0,0,0}};
int i;
for( i = 0; i < std::min(cn, 4); i++ ) s.val[i] = this->val[i];
for( ; i < 4; i++ ) s.val[i] = 0;
return s;
}
template inline const _Tp& Vec<_Tp, cn>::operator [](int i) const
{
CV_DbgAssert( (unsigned)i < (unsigned)cn );
return this->val[i];
}
template inline _Tp& Vec<_Tp, cn>::operator [](int i)
{
CV_DbgAssert( (unsigned)i < (unsigned)cn );
return this->val[i];
}
template inline const _Tp& Vec<_Tp, cn>::operator ()(int i) const
{
CV_DbgAssert( (unsigned)i < (unsigned)cn );
return this->val[i];
}
template inline _Tp& Vec<_Tp, cn>::operator ()(int i)
{
CV_DbgAssert( (unsigned)i < (unsigned)cn );
return this->val[i];
}
template static inline Vec<_Tp1, cn>&
operator += (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b)
{
for( int i = 0; i < cn; i++ )
a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);
return a;
}
template static inline Vec<_Tp1, cn>&
operator -= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b)
{
for( int i = 0; i < cn; i++ )
a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);
return a;
}
template static inline Vec<_Tp, cn>
operator + (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b)
{
return Vec<_Tp, cn>(a, b, Matx_AddOp());
}
template static inline Vec<_Tp, cn>
operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b)
{
return Vec<_Tp, cn>(a, b, Matx_SubOp());
}
template static inline
Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, int alpha)
{
for( int i = 0; i < cn; i++ )
a[i] = saturate_cast<_Tp>(a[i]*alpha);
return a;
}
template static inline
Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, float alpha)
{
for( int i = 0; i < cn; i++ )
a[i] = saturate_cast<_Tp>(a[i]*alpha);
return a;
}
template static inline
Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, double alpha)
{
for( int i = 0; i < cn; i++ )
a[i] = saturate_cast<_Tp>(a[i]*alpha);
return a;
}
template static inline
Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, int alpha)
{
double ialpha = 1./alpha;
for( int i = 0; i < cn; i++ )
a[i] = saturate_cast<_Tp>(a[i]*ialpha);
return a;
}
template static inline
Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, float alpha)
{
float ialpha = 1.f/alpha;
for( int i = 0; i < cn; i++ )
a[i] = saturate_cast<_Tp>(a[i]*ialpha);
return a;
}
template static inline
Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, double alpha)
{
double ialpha = 1./alpha;
for( int i = 0; i < cn; i++ )
a[i] = saturate_cast<_Tp>(a[i]*ialpha);
return a;
}
template static inline Vec<_Tp, cn>
operator * (const Vec<_Tp, cn>& a, int alpha)
{
return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator * (int alpha, const Vec<_Tp, cn>& a)
{
return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator * (const Vec<_Tp, cn>& a, float alpha)
{
return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator * (float alpha, const Vec<_Tp, cn>& a)
{
return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator * (const Vec<_Tp, cn>& a, double alpha)
{
return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator * (double alpha, const Vec<_Tp, cn>& a)
{
return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator / (const Vec<_Tp, cn>& a, int alpha)
{
return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator / (const Vec<_Tp, cn>& a, float alpha)
{
return Vec<_Tp, cn>(a, 1.f/alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator / (const Vec<_Tp, cn>& a, double alpha)
{
return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp());
}
template static inline Vec<_Tp, cn>
operator - (const Vec<_Tp, cn>& a)
{
Vec<_Tp,cn> t;
for( int i = 0; i < cn; i++ ) t.val[i] = saturate_cast<_Tp>(-a.val[i]);
return t;
}
template inline Vec<_Tp, 4> operator * (const Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2)
{
return Vec<_Tp, 4>(saturate_cast<_Tp>(v1[0]*v2[0] - v1[1]*v2[1] - v1[2]*v2[2] - v1[3]*v2[3]),
saturate_cast<_Tp>(v1[0]*v2[1] + v1[1]*v2[0] + v1[2]*v2[3] - v1[3]*v2[2]),
saturate_cast<_Tp>(v1[0]*v2[2] - v1[1]*v2[3] + v1[2]*v2[0] + v1[3]*v2[1]),
saturate_cast<_Tp>(v1[0]*v2[3] + v1[1]*v2[2] - v1[2]*v2[1] + v1[3]*v2[0]));
}
template inline Vec<_Tp, 4>& operator *= (Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2)
{
v1 = v1 * v2;
return v1;
}
template<> inline Vec Vec::cross(const Vec& v) const
{
return Vec(val[1]*v.val[2] - val[2]*v.val[1],
val[2]*v.val[0] - val[0]*v.val[2],
val[0]*v.val[1] - val[1]*v.val[0]);
}
template<> inline Vec Vec::cross(const Vec& v) const
{
return Vec(val[1]*v.val[2] - val[2]*v.val[1],
val[2]*v.val[0] - val[0]*v.val[2],
val[0]*v.val[1] - val[1]*v.val[0]);
}
template inline Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v)
{
double nv = norm(v);
return v * (nv ? 1./nv : 0.);
}
template static inline
VecCommaInitializer<_Tp, cn> operator << (const Vec<_Tp, cn>& vec, _T2 val)
{
VecCommaInitializer<_Tp, cn> commaInitializer((Vec<_Tp, cn>*)&vec);
return (commaInitializer, val);
}
template inline
VecCommaInitializer<_Tp, cn>::VecCommaInitializer(Vec<_Tp, cn>* _vec)
: MatxCommaInitializer<_Tp, cn, 1>(_vec)
{}
template template inline
VecCommaInitializer<_Tp, cn>& VecCommaInitializer<_Tp, cn>::operator , (_T2 value)
{
CV_DbgAssert( this->idx < cn );
this->dst->val[this->idx++] = saturate_cast<_Tp>(value);
return *this;
}
template inline
Vec<_Tp, cn> VecCommaInitializer<_Tp, cn>::operator *() const
{
CV_DbgAssert( this->idx == cn );
return *this->dst;
}
//////////////////////////////// Complex //////////////////////////////
template inline Complex<_Tp>::Complex() : re(0), im(0) {}
template inline Complex<_Tp>::Complex( _Tp _re, _Tp _im ) : re(_re), im(_im) {}
template template inline Complex<_Tp>::operator Complex() const
{ return Complex(saturate_cast(re), saturate_cast(im)); }
template inline Complex<_Tp> Complex<_Tp>::conj() const
{ return Complex<_Tp>(re, -im); }
template static inline
bool operator == (const Complex<_Tp>& a, const Complex<_Tp>& b)
{ return a.re == b.re && a.im == b.im; }
template