// fbc_cv is free software and uses the same licence as OpenCV // Email: fengbingchun@163.com #ifndef FBC_CV_CORE_MATX_HPP_ #define FBC_CV_CORE_MATX_HPP_ // reference: include/opencv2/core/matx.hpp #ifndef __cplusplus #error matx.hpp header must be compiled as C++ #endif #include "fbcdef.hpp" #include "base.hpp" #include "interface.hpp" #include "saturate.hpp" namespace yt_tinycv { ////////////////////////////// Small Matrix /////////////////////////// // Template class for small matrices whose type and size are known at compilation time template class Matx { public: enum { rows = m, cols = n, channels = rows*cols, shortdim = (m < n ? m : n) }; typedef _Tp value_type; typedef Matx<_Tp, m, n> mat_type; typedef Matx<_Tp, shortdim, 1> diag_type; //! default constructor Matx(); Matx(_Tp v0); //!< 1x1 matrix Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix explicit Matx(const _Tp* vals); //!< initialize from a plain array static Matx all(_Tp alpha); static Matx zeros(); static Matx ones(); static Matx eye(); static Matx diag(const diag_type& d); //! dot product computed with the default precision _Tp dot(const Matx<_Tp, m, n>& v) const; //! dot product computed in double-precision arithmetics double ddot(const Matx<_Tp, m, n>& v) const; //! conversion to another data type template operator Matx() const; //! change the matrix shape template Matx<_Tp, m1, n1> reshape() const; //! extract part of the matrix template Matx<_Tp, m1, n1> get_minor(int i, int j) const; //! extract the matrix row Matx<_Tp, 1, n> row(int i) const; //! extract the matrix column Matx<_Tp, m, 1> col(int i) const; //! extract the matrix diagonal diag_type diag() const; //! element access const _Tp& operator ()(int i, int j) const; _Tp& operator ()(int i, int j); //! 1D element access const _Tp& operator ()(int i) const; _Tp& operator ()(int i); _Tp val[m*n]; //< matrix elements }; typedef Matx Matx12f; typedef Matx Matx12d; typedef Matx Matx13f; typedef Matx Matx13d; typedef Matx Matx14f; typedef Matx Matx14d; typedef Matx Matx16f; typedef Matx Matx16d; typedef Matx Matx21f; typedef Matx Matx21d; typedef Matx Matx31f; typedef Matx Matx31d; typedef Matx Matx41f; typedef Matx Matx41d; typedef Matx Matx61f; typedef Matx Matx61d; typedef Matx Matx22f; typedef Matx Matx22d; typedef Matx Matx23f; typedef Matx Matx23d; typedef Matx Matx32f; typedef Matx Matx32d; typedef Matx Matx33f; typedef Matx Matx33d; 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) { FBC_StaticAssert(channels >= 2, "Matx should have at least 2 elements."); 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) { FBC_StaticAssert(channels >= 3, "Matx should have at least 3 elements."); 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) { FBC_StaticAssert(channels >= 4, "Matx should have at least 4 elements."); 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) { FBC_StaticAssert(channels >= 5, "Matx should have at least 5 elements."); 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) { FBC_StaticAssert(channels >= 6, "Matx should have at least 6 elements."); 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) { FBC_StaticAssert(channels >= 7, "Matx should have at least 7 elements."); 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) { FBC_StaticAssert(channels >= 8, "Matx should have at least 8 elements."); 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) { FBC_StaticAssert(channels >= 9, "Matx should have at least 9 elements."); 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(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 < shortdim; i++) M(i, i) = 1; return M; } 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 < shortdim; i++) M(i, i) = d(i, 0); 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 < channels; 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 < channels; i++) s += (double)val[i] * M.val[i]; return s; } 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 { FBC_StaticAssert(m1*n1 == m*n, "Input and destnarion matrices must have the same number of elements"); 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 { FBC_Assert(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 { FBC_Assert((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 { FBC_Assert((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 < shortdim; i++) d.val[i] = val[i*n + i]; return d; } template inline const _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const { FBC_Assert((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) { FBC_Assert((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 { FBC_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row"); FBC_Assert((unsigned)i < (unsigned)(m + n - 1)); return val[i]; } template inline _Tp& Matx<_Tp, m, n>::operator ()(int i) { FBC_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row"); FBC_Assert((unsigned)i < (unsigned)(m + n - 1)); return val[i]; } 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) { switch (normType) { case NORM_INF: return (double)normInf<_Tp, _Tp>(M.val, m*n); case NORM_L1: return (double)normL1<_Tp, _Tp>(M.val, m*n); case NORM_L2SQR: return (double)normL2Sqr<_Tp, _Tp>(M.val, m*n); default: case NORM_L2: return std::sqrt((double)normL2Sqr<_Tp, _Tp>(M.val, m*n)); } } ///////////////////////////// Matx out-of-class operators //////////////////////////////// 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 static inline Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]); return M; } template static inline Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]); return M; } 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) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return M; } template static inline Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return M; } template static inline Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return M; } template static inline Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return M; } template static inline Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return M; } template static inline Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a) { Matx<_Tp, m, n> M; for (int i = 0; i < m*n; i++) M.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return M; } template static inline Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b) { Matx<_Tp, m, n> M; 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); M.val[i*n + j] = s; } return M; } 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); } ///////////////////////////////////////// Vec /////////////////////////////////// // Template class for short numerical vectors, a partial case of Matx template class Vec : public Matx<_Tp, cn, 1> { public: typedef _Tp value_type; enum { channels = cn }; //! default constructor Vec(); Vec(_Tp v0); //!< 1-element vector constructor Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor explicit Vec(const _Tp* values); Vec(const Vec<_Tp, cn>& v); static Vec all(_Tp alpha); //! per-element multiplication Vec mul(const Vec<_Tp, cn>& v) const; //! conversion to another data type template operator Vec() const; /*! element access */ const _Tp& operator [](int i) const; _Tp& operator[](int i); const _Tp& operator ()(int i) const; _Tp& operator ()(int i); }; typedef Vec Vec2b; typedef Vec Vec3b; typedef Vec Vec4b; typedef Vec Vec2s; typedef Vec Vec3s; typedef Vec Vec4s; typedef Vec Vec2w; typedef Vec Vec3w; typedef Vec Vec4w; typedef Vec Vec2i; typedef Vec Vec3i; typedef Vec Vec4i; typedef Vec Vec6i; typedef Vec Vec2f; typedef Vec Vec3f; typedef Vec Vec4f; typedef Vec Vec6f; typedef Vec Vec2d; typedef Vec Vec3d; typedef Vec Vec4d; typedef Vec Vec6d; 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(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<_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 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 const _Tp& Vec<_Tp, cn>::operator [](int i) const { FBC_Assert((unsigned)i < (unsigned)cn); return this->val[i]; } template inline _Tp& Vec<_Tp, cn>::operator [](int i) { FBC_Assert((unsigned)i < (unsigned)cn); return this->val[i]; } template inline const _Tp& Vec<_Tp, cn>::operator ()(int i) const { FBC_Assert((unsigned)i < (unsigned)cn); return this->val[i]; } template inline _Tp& Vec<_Tp, cn>::operator ()(int i) { FBC_Assert((unsigned)i < (unsigned)cn); return this->val[i]; } ////////////////////////////// Vec out-of-class operators //////////////////////////////// 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) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]); return v; } template static inline Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]); return v; } 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) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return v; } template static inline Vec<_Tp, cn> operator * (int alpha, const Vec<_Tp, cn>& a) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return v; } template static inline Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, float alpha) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return v; } template static inline Vec<_Tp, cn> operator * (float alpha, const Vec<_Tp, cn>& a) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return v; } template static inline Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, double alpha) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return v; } template static inline Vec<_Tp, cn> operator * (double alpha, const Vec<_Tp, cn>& a) { Vec<_Tp, cn> v; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * alpha); return v; } template static inline Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, int alpha) { Vec<_Tp, cn> v; double ialpha = 1. / alpha; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * ialpha); return v; } template static inline Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, float alpha) { Vec<_Tp, cn> v; float ialpha = 1.f / alpha; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * ialpha); return v; } template static inline Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, double alpha) { Vec<_Tp, cn> v; double ialpha = 1. / alpha; for (int i = 0; i < cn; i++) v.val[i] = saturate_cast<_Tp>(a.val[i] * ialpha); return v; } 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; } } //yt_tinycv #endif //FBC_CV_CORE_MATX_HPP_