1/*M///////////////////////////////////////////////////////////////////////////////////////
2//
3//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4//
5//  By downloading, copying, installing or using the software you agree to this license.
6//  If you do not agree to this license, do not download, install,
7//  copy or use the software.
8//
9//
10//                          License Agreement
11//                For Open Source Computer Vision Library
12//
13// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
16// Third party copyrights are property of their respective owners.
17//
18// Redistribution and use in source and binary forms, with or without modification,
19// are permitted provided that the following conditions are met:
20//
21//   * Redistribution's of source code must retain the above copyright notice,
22//     this list of conditions and the following disclaimer.
23//
24//   * Redistribution's in binary form must reproduce the above copyright notice,
25//     this list of conditions and the following disclaimer in the documentation
26//     and/or other materials provided with the distribution.
27//
28//   * The name of the copyright holders may not be used to endorse or promote products
29//     derived from this software without specific prior written permission.
30//
31// This software is provided by the copyright holders and contributors "as is" and
32// any express or implied warranties, including, but not limited to, the implied
33// warranties of merchantability and fitness for a particular purpose are disclaimed.
34// In no event shall the Intel Corporation or contributors be liable for any direct,
35// indirect, incidental, special, exemplary, or consequential damages
36// (including, but not limited to, procurement of substitute goods or services;
37// loss of use, data, or profits; or business interruption) however caused
38// and on any theory of liability, whether in contract, strict liability,
39// or tort (including negligence or otherwise) arising in any way out of
40// the use of this software, even if advised of the possibility of such damage.
41//
42//M*/
43
44#ifndef __OPENCV_CORE_MATX_HPP__
45#define __OPENCV_CORE_MATX_HPP__
46
47#ifndef __cplusplus
48#  error matx.hpp header must be compiled as C++
49#endif
50
51#include "opencv2/core/cvdef.h"
52#include "opencv2/core/base.hpp"
53#include "opencv2/core/traits.hpp"
54
55namespace cv
56{
57
58//! @addtogroup core_basic
59//! @{
60
61////////////////////////////// Small Matrix ///////////////////////////
62
63//! @cond IGNORED
64struct CV_EXPORTS Matx_AddOp {};
65struct CV_EXPORTS Matx_SubOp {};
66struct CV_EXPORTS Matx_ScaleOp {};
67struct CV_EXPORTS Matx_MulOp {};
68struct CV_EXPORTS Matx_DivOp {};
69struct CV_EXPORTS Matx_MatMulOp {};
70struct CV_EXPORTS Matx_TOp {};
71//! @endcond
72
73/** @brief Template class for small matrices whose type and size are known at compilation time
74
75If you need a more flexible type, use Mat . The elements of the matrix M are accessible using the
76M(i,j) notation. Most of the common matrix operations (see also @ref MatrixExpressions ) are
77available. To do an operation on Matx that is not implemented, you can easily convert the matrix to
78Mat and backwards:
79@code
80    Matx33f m(1, 2, 3,
81              4, 5, 6,
82              7, 8, 9);
83    cout << sum(Mat(m*m.t())) << endl;
84 @endcode
85 */
86template<typename _Tp, int m, int n> class Matx
87{
88public:
89    enum { depth    = DataType<_Tp>::depth,
90           rows     = m,
91           cols     = n,
92           channels = rows*cols,
93           type     = CV_MAKETYPE(depth, channels),
94           shortdim = (m < n ? m : n)
95         };
96
97    typedef _Tp                           value_type;
98    typedef Matx<_Tp, m, n>               mat_type;
99    typedef Matx<_Tp, shortdim, 1> diag_type;
100
101    //! default constructor
102    Matx();
103
104    Matx(_Tp v0); //!< 1x1 matrix
105    Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix
106    Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix
107    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix
108    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix
109    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix
110    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix
111    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix
112    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix
113    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 1x10, 2x5 or 5x2 or 10x1 matrix
114    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
115         _Tp v4, _Tp v5, _Tp v6, _Tp v7,
116         _Tp v8, _Tp v9, _Tp v10, _Tp v11); //!< 1x12, 2x6, 3x4, 4x3, 6x2 or 12x1 matrix
117    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
118         _Tp v4, _Tp v5, _Tp v6, _Tp v7,
119         _Tp v8, _Tp v9, _Tp v10, _Tp v11,
120         _Tp v12, _Tp v13, _Tp v14, _Tp v15); //!< 1x16, 4x4 or 16x1 matrix
121    explicit Matx(const _Tp* vals); //!< initialize from a plain array
122
123    static Matx all(_Tp alpha);
124    static Matx zeros();
125    static Matx ones();
126    static Matx eye();
127    static Matx diag(const diag_type& d);
128    static Matx randu(_Tp a, _Tp b);
129    static Matx randn(_Tp a, _Tp b);
130
131    //! dot product computed with the default precision
132    _Tp dot(const Matx<_Tp, m, n>& v) const;
133
134    //! dot product computed in double-precision arithmetics
135    double ddot(const Matx<_Tp, m, n>& v) const;
136
137    //! conversion to another data type
138    template<typename T2> operator Matx<T2, m, n>() const;
139
140    //! change the matrix shape
141    template<int m1, int n1> Matx<_Tp, m1, n1> reshape() const;
142
143    //! extract part of the matrix
144    template<int m1, int n1> Matx<_Tp, m1, n1> get_minor(int i, int j) const;
145
146    //! extract the matrix row
147    Matx<_Tp, 1, n> row(int i) const;
148
149    //! extract the matrix column
150    Matx<_Tp, m, 1> col(int i) const;
151
152    //! extract the matrix diagonal
153    diag_type diag() const;
154
155    //! transpose the matrix
156    Matx<_Tp, n, m> t() const;
157
158    //! invert the matrix
159    Matx<_Tp, n, m> inv(int method=DECOMP_LU, bool *p_is_ok = NULL) const;
160
161    //! solve linear system
162    template<int l> Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const;
163    Vec<_Tp, n> solve(const Vec<_Tp, m>& rhs, int method) const;
164
165    //! multiply two matrices element-wise
166    Matx<_Tp, m, n> mul(const Matx<_Tp, m, n>& a) const;
167
168    //! divide two matrices element-wise
169    Matx<_Tp, m, n> div(const Matx<_Tp, m, n>& a) const;
170
171    //! element access
172    const _Tp& operator ()(int i, int j) const;
173    _Tp& operator ()(int i, int j);
174
175    //! 1D element access
176    const _Tp& operator ()(int i) const;
177    _Tp& operator ()(int i);
178
179    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp);
180    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp);
181    template<typename _T2> Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp);
182    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp);
183    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp);
184    template<int l> Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp);
185    Matx(const Matx<_Tp, n, m>& a, Matx_TOp);
186
187    _Tp val[m*n]; //< matrix elements
188};
189
190typedef Matx<float, 1, 2> Matx12f;
191typedef Matx<double, 1, 2> Matx12d;
192typedef Matx<float, 1, 3> Matx13f;
193typedef Matx<double, 1, 3> Matx13d;
194typedef Matx<float, 1, 4> Matx14f;
195typedef Matx<double, 1, 4> Matx14d;
196typedef Matx<float, 1, 6> Matx16f;
197typedef Matx<double, 1, 6> Matx16d;
198
199typedef Matx<float, 2, 1> Matx21f;
200typedef Matx<double, 2, 1> Matx21d;
201typedef Matx<float, 3, 1> Matx31f;
202typedef Matx<double, 3, 1> Matx31d;
203typedef Matx<float, 4, 1> Matx41f;
204typedef Matx<double, 4, 1> Matx41d;
205typedef Matx<float, 6, 1> Matx61f;
206typedef Matx<double, 6, 1> Matx61d;
207
208typedef Matx<float, 2, 2> Matx22f;
209typedef Matx<double, 2, 2> Matx22d;
210typedef Matx<float, 2, 3> Matx23f;
211typedef Matx<double, 2, 3> Matx23d;
212typedef Matx<float, 3, 2> Matx32f;
213typedef Matx<double, 3, 2> Matx32d;
214
215typedef Matx<float, 3, 3> Matx33f;
216typedef Matx<double, 3, 3> Matx33d;
217
218typedef Matx<float, 3, 4> Matx34f;
219typedef Matx<double, 3, 4> Matx34d;
220typedef Matx<float, 4, 3> Matx43f;
221typedef Matx<double, 4, 3> Matx43d;
222
223typedef Matx<float, 4, 4> Matx44f;
224typedef Matx<double, 4, 4> Matx44d;
225typedef Matx<float, 6, 6> Matx66f;
226typedef Matx<double, 6, 6> Matx66d;
227
228/*!
229  traits
230*/
231template<typename _Tp, int m, int n> class DataType< Matx<_Tp, m, n> >
232{
233public:
234    typedef Matx<_Tp, m, n>                               value_type;
235    typedef Matx<typename DataType<_Tp>::work_type, m, n> work_type;
236    typedef _Tp                                           channel_type;
237    typedef value_type                                    vec_type;
238
239    enum { generic_type = 0,
240           depth        = DataType<channel_type>::depth,
241           channels     = m * n,
242           fmt          = DataType<channel_type>::fmt + ((channels - 1) << 8),
243           type         = CV_MAKETYPE(depth, channels)
244         };
245};
246
247/** @brief  Comma-separated Matrix Initializer
248*/
249template<typename _Tp, int m, int n> class MatxCommaInitializer
250{
251public:
252    MatxCommaInitializer(Matx<_Tp, m, n>* _mtx);
253    template<typename T2> MatxCommaInitializer<_Tp, m, n>& operator , (T2 val);
254    Matx<_Tp, m, n> operator *() const;
255
256    Matx<_Tp, m, n>* dst;
257    int idx;
258};
259
260/*
261 Utility methods
262*/
263template<typename _Tp, int m> static double determinant(const Matx<_Tp, m, m>& a);
264template<typename _Tp, int m, int n> static double trace(const Matx<_Tp, m, n>& a);
265template<typename _Tp, int m, int n> static double norm(const Matx<_Tp, m, n>& M);
266template<typename _Tp, int m, int n> static double norm(const Matx<_Tp, m, n>& M, int normType);
267
268
269
270/////////////////////// Vec (used as element of multi-channel images /////////////////////
271
272/** @brief Template class for short numerical vectors, a partial case of Matx
273
274This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) on which you
275can perform basic arithmetical operations, access individual elements using [] operator etc. The
276vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., which
277elements are dynamically allocated in the heap.
278
279The template takes 2 parameters:
280@tparam _Tp element type
281@tparam cn the number of elements
282
283In addition to the universal notation like Vec<float, 3>, you can use shorter aliases
284for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec<float, 3>.
285
286It is possible to convert Vec\<T,2\> to/from Point_, Vec\<T,3\> to/from Point3_ , and Vec\<T,4\>
287to CvScalar or Scalar_. Use operator[] to access the elements of Vec.
288
289All the expected vector operations are also implemented:
290-   v1 = v2 + v3
291-   v1 = v2 - v3
292-   v1 = v2 \* scale
293-   v1 = scale \* v2
294-   v1 = -v2
295-   v1 += v2 and other augmenting operations
296-   v1 == v2, v1 != v2
297-   norm(v1) (euclidean norm)
298The Vec class is commonly used to describe pixel types of multi-channel arrays. See Mat for details.
299*/
300template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>
301{
302public:
303    typedef _Tp value_type;
304    enum { depth    = Matx<_Tp, cn, 1>::depth,
305           channels = cn,
306           type     = CV_MAKETYPE(depth, channels)
307         };
308
309    //! default constructor
310    Vec();
311
312    Vec(_Tp v0); //!< 1-element vector constructor
313    Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor
314    Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor
315    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor
316    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor
317    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor
318    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor
319    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor
320    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor
321    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructor
322    explicit Vec(const _Tp* values);
323
324    Vec(const Vec<_Tp, cn>& v);
325
326    static Vec all(_Tp alpha);
327
328    //! per-element multiplication
329    Vec mul(const Vec<_Tp, cn>& v) const;
330
331    //! conjugation (makes sense for complex numbers and quaternions)
332    Vec conj() const;
333
334    /*!
335      cross product of the two 3D vectors.
336
337      For other dimensionalities the exception is raised
338    */
339    Vec cross(const Vec& v) const;
340    //! conversion to another data type
341    template<typename T2> operator Vec<T2, cn>() const;
342
343    /*! element access */
344    const _Tp& operator [](int i) const;
345    _Tp& operator[](int i);
346    const _Tp& operator ()(int i) const;
347    _Tp& operator ()(int i);
348
349    Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp);
350    Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp);
351    template<typename _T2> Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp);
352};
353
354/** @name Shorter aliases for the most popular specializations of Vec<T,n>
355  @{
356*/
357typedef Vec<uchar, 2> Vec2b;
358typedef Vec<uchar, 3> Vec3b;
359typedef Vec<uchar, 4> Vec4b;
360
361typedef Vec<short, 2> Vec2s;
362typedef Vec<short, 3> Vec3s;
363typedef Vec<short, 4> Vec4s;
364
365typedef Vec<ushort, 2> Vec2w;
366typedef Vec<ushort, 3> Vec3w;
367typedef Vec<ushort, 4> Vec4w;
368
369typedef Vec<int, 2> Vec2i;
370typedef Vec<int, 3> Vec3i;
371typedef Vec<int, 4> Vec4i;
372typedef Vec<int, 6> Vec6i;
373typedef Vec<int, 8> Vec8i;
374
375typedef Vec<float, 2> Vec2f;
376typedef Vec<float, 3> Vec3f;
377typedef Vec<float, 4> Vec4f;
378typedef Vec<float, 6> Vec6f;
379
380typedef Vec<double, 2> Vec2d;
381typedef Vec<double, 3> Vec3d;
382typedef Vec<double, 4> Vec4d;
383typedef Vec<double, 6> Vec6d;
384/** @} */
385
386/*!
387  traits
388*/
389template<typename _Tp, int cn> class DataType< Vec<_Tp, cn> >
390{
391public:
392    typedef Vec<_Tp, cn>                               value_type;
393    typedef Vec<typename DataType<_Tp>::work_type, cn> work_type;
394    typedef _Tp                                        channel_type;
395    typedef value_type                                 vec_type;
396
397    enum { generic_type = 0,
398           depth        = DataType<channel_type>::depth,
399           channels     = cn,
400           fmt          = DataType<channel_type>::fmt + ((channels - 1) << 8),
401           type         = CV_MAKETYPE(depth, channels)
402         };
403};
404
405/** @brief  Comma-separated Vec Initializer
406*/
407template<typename _Tp, int m> class VecCommaInitializer : public MatxCommaInitializer<_Tp, m, 1>
408{
409public:
410    VecCommaInitializer(Vec<_Tp, m>* _vec);
411    template<typename T2> VecCommaInitializer<_Tp, m>& operator , (T2 val);
412    Vec<_Tp, m> operator *() const;
413};
414
415template<typename _Tp, int cn> static Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v);
416
417//! @} core_basic
418
419//! @cond IGNORED
420
421///////////////////////////////////// helper classes /////////////////////////////////////
422namespace internal
423{
424
425template<typename _Tp, int m> struct Matx_DetOp
426{
427    double operator ()(const Matx<_Tp, m, m>& a) const
428    {
429        Matx<_Tp, m, m> temp = a;
430        double p = LU(temp.val, m*sizeof(_Tp), m, 0, 0, 0);
431        if( p == 0 )
432            return p;
433        for( int i = 0; i < m; i++ )
434            p *= temp(i, i);
435        return 1./p;
436    }
437};
438
439template<typename _Tp> struct Matx_DetOp<_Tp, 1>
440{
441    double operator ()(const Matx<_Tp, 1, 1>& a) const
442    {
443        return a(0,0);
444    }
445};
446
447template<typename _Tp> struct Matx_DetOp<_Tp, 2>
448{
449    double operator ()(const Matx<_Tp, 2, 2>& a) const
450    {
451        return a(0,0)*a(1,1) - a(0,1)*a(1,0);
452    }
453};
454
455template<typename _Tp> struct Matx_DetOp<_Tp, 3>
456{
457    double operator ()(const Matx<_Tp, 3, 3>& a) const
458    {
459        return a(0,0)*(a(1,1)*a(2,2) - a(2,1)*a(1,2)) -
460            a(0,1)*(a(1,0)*a(2,2) - a(2,0)*a(1,2)) +
461            a(0,2)*(a(1,0)*a(2,1) - a(2,0)*a(1,1));
462    }
463};
464
465template<typename _Tp> Vec<_Tp, 2> inline conjugate(const Vec<_Tp, 2>& v)
466{
467    return Vec<_Tp, 2>(v[0], -v[1]);
468}
469
470template<typename _Tp> Vec<_Tp, 4> inline conjugate(const Vec<_Tp, 4>& v)
471{
472    return Vec<_Tp, 4>(v[0], -v[1], -v[2], -v[3]);
473}
474
475} // internal
476
477
478
479////////////////////////////////// Matx Implementation ///////////////////////////////////
480
481template<typename _Tp, int m, int n> inline
482Matx<_Tp, m, n>::Matx()
483{
484    for(int i = 0; i < channels; i++) val[i] = _Tp(0);
485}
486
487template<typename _Tp, int m, int n> inline
488Matx<_Tp, m, n>::Matx(_Tp v0)
489{
490    val[0] = v0;
491    for(int i = 1; i < channels; i++) val[i] = _Tp(0);
492}
493
494template<typename _Tp, int m, int n> inline
495Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1)
496{
497    CV_StaticAssert(channels >= 2, "Matx should have at least 2 elaments.");
498    val[0] = v0; val[1] = v1;
499    for(int i = 2; i < channels; i++) val[i] = _Tp(0);
500}
501
502template<typename _Tp, int m, int n> inline
503Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2)
504{
505    CV_StaticAssert(channels >= 3, "Matx should have at least 3 elaments.");
506    val[0] = v0; val[1] = v1; val[2] = v2;
507    for(int i = 3; i < channels; i++) val[i] = _Tp(0);
508}
509
510template<typename _Tp, int m, int n> inline
511Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
512{
513    CV_StaticAssert(channels >= 4, "Matx should have at least 4 elaments.");
514    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
515    for(int i = 4; i < channels; i++) val[i] = _Tp(0);
516}
517
518template<typename _Tp, int m, int n> inline
519Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4)
520{
521    CV_StaticAssert(channels >= 5, "Matx should have at least 5 elaments.");
522    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4;
523    for(int i = 5; i < channels; i++) val[i] = _Tp(0);
524}
525
526template<typename _Tp, int m, int n> inline
527Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5)
528{
529    CV_StaticAssert(channels >= 6, "Matx should have at least 6 elaments.");
530    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
531    val[4] = v4; val[5] = v5;
532    for(int i = 6; i < channels; i++) val[i] = _Tp(0);
533}
534
535template<typename _Tp, int m, int n> inline
536Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6)
537{
538    CV_StaticAssert(channels >= 7, "Matx should have at least 7 elaments.");
539    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
540    val[4] = v4; val[5] = v5; val[6] = v6;
541    for(int i = 7; i < channels; i++) val[i] = _Tp(0);
542}
543
544template<typename _Tp, int m, int n> inline
545Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7)
546{
547    CV_StaticAssert(channels >= 8, "Matx should have at least 8 elaments.");
548    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
549    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
550    for(int i = 8; i < channels; i++) val[i] = _Tp(0);
551}
552
553template<typename _Tp, int m, int n> inline
554Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8)
555{
556    CV_StaticAssert(channels >= 9, "Matx should have at least 9 elaments.");
557    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
558    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
559    val[8] = v8;
560    for(int i = 9; i < channels; i++) val[i] = _Tp(0);
561}
562
563template<typename _Tp, int m, int n> inline
564Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9)
565{
566    CV_StaticAssert(channels >= 10, "Matx should have at least 10 elaments.");
567    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
568    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
569    val[8] = v8; val[9] = v9;
570    for(int i = 10; i < channels; i++) val[i] = _Tp(0);
571}
572
573
574template<typename _Tp, int m, int n> inline
575Matx<_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)
576{
577    CV_StaticAssert(channels == 12, "Matx should have at least 12 elaments.");
578    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
579    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
580    val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11;
581}
582
583template<typename _Tp, int m, int n> inline
584Matx<_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)
585{
586    CV_StaticAssert(channels == 16, "Matx should have at least 16 elaments.");
587    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;
588    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;
589    val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11;
590    val[12] = v12; val[13] = v13; val[14] = v14; val[15] = v15;
591}
592
593template<typename _Tp, int m, int n> inline
594Matx<_Tp, m, n>::Matx(const _Tp* values)
595{
596    for( int i = 0; i < channels; i++ ) val[i] = values[i];
597}
598
599template<typename _Tp, int m, int n> inline
600Matx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha)
601{
602    Matx<_Tp, m, n> M;
603    for( int i = 0; i < m*n; i++ ) M.val[i] = alpha;
604    return M;
605}
606
607template<typename _Tp, int m, int n> inline
608Matx<_Tp,m,n> Matx<_Tp,m,n>::zeros()
609{
610    return all(0);
611}
612
613template<typename _Tp, int m, int n> inline
614Matx<_Tp,m,n> Matx<_Tp,m,n>::ones()
615{
616    return all(1);
617}
618
619template<typename _Tp, int m, int n> inline
620Matx<_Tp,m,n> Matx<_Tp,m,n>::eye()
621{
622    Matx<_Tp,m,n> M;
623    for(int i = 0; i < shortdim; i++)
624        M(i,i) = 1;
625    return M;
626}
627
628template<typename _Tp, int m, int n> inline
629_Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const
630{
631    _Tp s = 0;
632    for( int i = 0; i < channels; i++ ) s += val[i]*M.val[i];
633    return s;
634}
635
636template<typename _Tp, int m, int n> inline
637double Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const
638{
639    double s = 0;
640    for( int i = 0; i < channels; i++ ) s += (double)val[i]*M.val[i];
641    return s;
642}
643
644template<typename _Tp, int m, int n> inline
645Matx<_Tp,m,n> Matx<_Tp,m,n>::diag(const typename Matx<_Tp,m,n>::diag_type& d)
646{
647    Matx<_Tp,m,n> M;
648    for(int i = 0; i < shortdim; i++)
649        M(i,i) = d(i, 0);
650    return M;
651}
652
653template<typename _Tp, int m, int n> template<typename T2>
654inline Matx<_Tp, m, n>::operator Matx<T2, m, n>() const
655{
656    Matx<T2, m, n> M;
657    for( int i = 0; i < m*n; i++ ) M.val[i] = saturate_cast<T2>(val[i]);
658    return M;
659}
660
661template<typename _Tp, int m, int n> template<int m1, int n1> inline
662Matx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const
663{
664    CV_StaticAssert(m1*n1 == m*n, "Input and destnarion matrices must have the same number of elements");
665    return (const Matx<_Tp, m1, n1>&)*this;
666}
667
668template<typename _Tp, int m, int n>
669template<int m1, int n1> inline
670Matx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const
671{
672    CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n);
673    Matx<_Tp, m1, n1> s;
674    for( int di = 0; di < m1; di++ )
675        for( int dj = 0; dj < n1; dj++ )
676            s(di, dj) = (*this)(i+di, j+dj);
677    return s;
678}
679
680template<typename _Tp, int m, int n> inline
681Matx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const
682{
683    CV_DbgAssert((unsigned)i < (unsigned)m);
684    return Matx<_Tp, 1, n>(&val[i*n]);
685}
686
687template<typename _Tp, int m, int n> inline
688Matx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const
689{
690    CV_DbgAssert((unsigned)j < (unsigned)n);
691    Matx<_Tp, m, 1> v;
692    for( int i = 0; i < m; i++ )
693        v.val[i] = val[i*n + j];
694    return v;
695}
696
697template<typename _Tp, int m, int n> inline
698typename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const
699{
700    diag_type d;
701    for( int i = 0; i < shortdim; i++ )
702        d.val[i] = val[i*n + i];
703    return d;
704}
705
706template<typename _Tp, int m, int n> inline
707const _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const
708{
709    CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );
710    return this->val[i*n + j];
711}
712
713template<typename _Tp, int m, int n> inline
714_Tp& Matx<_Tp, m, n>::operator ()(int i, int j)
715{
716    CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );
717    return val[i*n + j];
718}
719
720template<typename _Tp, int m, int n> inline
721const _Tp& Matx<_Tp, m, n>::operator ()(int i) const
722{
723    CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row");
724    CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) );
725    return val[i];
726}
727
728template<typename _Tp, int m, int n> inline
729_Tp& Matx<_Tp, m, n>::operator ()(int i)
730{
731    CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row");
732    CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) );
733    return val[i];
734}
735
736template<typename _Tp, int m, int n> inline
737Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp)
738{
739    for( int i = 0; i < channels; i++ )
740        val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]);
741}
742
743template<typename _Tp, int m, int n> inline
744Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp)
745{
746    for( int i = 0; i < channels; i++ )
747        val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]);
748}
749
750template<typename _Tp, int m, int n> template<typename _T2> inline
751Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp)
752{
753    for( int i = 0; i < channels; i++ )
754        val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
755}
756
757template<typename _Tp, int m, int n> inline
758Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp)
759{
760    for( int i = 0; i < channels; i++ )
761        val[i] = saturate_cast<_Tp>(a.val[i] * b.val[i]);
762}
763
764template<typename _Tp, int m, int n> inline
765Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp)
766{
767    for( int i = 0; i < channels; i++ )
768        val[i] = saturate_cast<_Tp>(a.val[i] / b.val[i]);
769}
770
771template<typename _Tp, int m, int n> template<int l> inline
772Matx<_Tp,m,n>::Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp)
773{
774    for( int i = 0; i < m; i++ )
775        for( int j = 0; j < n; j++ )
776        {
777            _Tp s = 0;
778            for( int k = 0; k < l; k++ )
779                s += a(i, k) * b(k, j);
780            val[i*n + j] = s;
781        }
782}
783
784template<typename _Tp, int m, int n> inline
785Matx<_Tp,m,n>::Matx(const Matx<_Tp, n, m>& a, Matx_TOp)
786{
787    for( int i = 0; i < m; i++ )
788        for( int j = 0; j < n; j++ )
789            val[i*n + j] = a(j, i);
790}
791
792template<typename _Tp, int m, int n> inline
793Matx<_Tp, m, n> Matx<_Tp, m, n>::mul(const Matx<_Tp, m, n>& a) const
794{
795    return Matx<_Tp, m, n>(*this, a, Matx_MulOp());
796}
797
798template<typename _Tp, int m, int n> inline
799Matx<_Tp, m, n> Matx<_Tp, m, n>::div(const Matx<_Tp, m, n>& a) const
800{
801    return Matx<_Tp, m, n>(*this, a, Matx_DivOp());
802}
803
804template<typename _Tp, int m, int n> inline
805Matx<_Tp, n, m> Matx<_Tp, m, n>::t() const
806{
807    return Matx<_Tp, n, m>(*this, Matx_TOp());
808}
809
810template<typename _Tp, int m, int n> inline
811Vec<_Tp, n> Matx<_Tp, m, n>::solve(const Vec<_Tp, m>& rhs, int method) const
812{
813    Matx<_Tp, n, 1> x = solve((const Matx<_Tp, m, 1>&)(rhs), method);
814    return (Vec<_Tp, n>&)(x);
815}
816
817template<typename _Tp, int m> static inline
818double determinant(const Matx<_Tp, m, m>& a)
819{
820    return cv::internal::Matx_DetOp<_Tp, m>()(a);
821}
822
823template<typename _Tp, int m, int n> static inline
824double trace(const Matx<_Tp, m, n>& a)
825{
826    _Tp s = 0;
827    for( int i = 0; i < std::min(m, n); i++ )
828        s += a(i,i);
829    return s;
830}
831
832template<typename _Tp, int m, int n> static inline
833double norm(const Matx<_Tp, m, n>& M)
834{
835    return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n));
836}
837
838template<typename _Tp, int m, int n> static inline
839double norm(const Matx<_Tp, m, n>& M, int normType)
840{
841    return normType == NORM_INF ? (double)normInf<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) :
842        normType == NORM_L1 ? (double)normL1<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) :
843        std::sqrt((double)normL2Sqr<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n));
844}
845
846
847
848//////////////////////////////// matx comma initializer //////////////////////////////////
849
850template<typename _Tp, typename _T2, int m, int n> static inline
851MatxCommaInitializer<_Tp, m, n> operator << (const Matx<_Tp, m, n>& mtx, _T2 val)
852{
853    MatxCommaInitializer<_Tp, m, n> commaInitializer((Matx<_Tp, m, n>*)&mtx);
854    return (commaInitializer, val);
855}
856
857template<typename _Tp, int m, int n> inline
858MatxCommaInitializer<_Tp, m, n>::MatxCommaInitializer(Matx<_Tp, m, n>* _mtx)
859    : dst(_mtx), idx(0)
860{}
861
862template<typename _Tp, int m, int n> template<typename _T2> inline
863MatxCommaInitializer<_Tp, m, n>& MatxCommaInitializer<_Tp, m, n>::operator , (_T2 value)
864{
865    CV_DbgAssert( idx < m*n );
866    dst->val[idx++] = saturate_cast<_Tp>(value);
867    return *this;
868}
869
870template<typename _Tp, int m, int n> inline
871Matx<_Tp, m, n> MatxCommaInitializer<_Tp, m, n>::operator *() const
872{
873    CV_DbgAssert( idx == n*m );
874    return *dst;
875}
876
877
878
879/////////////////////////////////// Vec Implementation ///////////////////////////////////
880
881template<typename _Tp, int cn> inline
882Vec<_Tp, cn>::Vec() {}
883
884template<typename _Tp, int cn> inline
885Vec<_Tp, cn>::Vec(_Tp v0)
886    : Matx<_Tp, cn, 1>(v0) {}
887
888template<typename _Tp, int cn> inline
889Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1)
890    : Matx<_Tp, cn, 1>(v0, v1) {}
891
892template<typename _Tp, int cn> inline
893Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2)
894    : Matx<_Tp, cn, 1>(v0, v1, v2) {}
895
896template<typename _Tp, int cn> inline
897Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3)
898    : Matx<_Tp, cn, 1>(v0, v1, v2, v3) {}
899
900template<typename _Tp, int cn> inline
901Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4)
902    : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4) {}
903
904template<typename _Tp, int cn> inline
905Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5)
906    : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5) {}
907
908template<typename _Tp, int cn> inline
909Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6)
910    : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6) {}
911
912template<typename _Tp, int cn> inline
913Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7)
914    : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7) {}
915
916template<typename _Tp, int cn> inline
917Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8)
918    : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8) {}
919
920template<typename _Tp, int cn> inline
921Vec<_Tp, cn>::Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9)
922    : Matx<_Tp, cn, 1>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {}
923
924template<typename _Tp, int cn> inline
925Vec<_Tp, cn>::Vec(const _Tp* values)
926    : Matx<_Tp, cn, 1>(values) {}
927
928template<typename _Tp, int cn> inline
929Vec<_Tp, cn>::Vec(const Vec<_Tp, cn>& m)
930    : Matx<_Tp, cn, 1>(m.val) {}
931
932template<typename _Tp, int cn> inline
933Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp op)
934    : Matx<_Tp, cn, 1>(a, b, op) {}
935
936template<typename _Tp, int cn> inline
937Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp op)
938    : Matx<_Tp, cn, 1>(a, b, op) {}
939
940template<typename _Tp, int cn> template<typename _T2> inline
941Vec<_Tp, cn>::Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp op)
942    : Matx<_Tp, cn, 1>(a, alpha, op) {}
943
944template<typename _Tp, int cn> inline
945Vec<_Tp, cn> Vec<_Tp, cn>::all(_Tp alpha)
946{
947    Vec v;
948    for( int i = 0; i < cn; i++ ) v.val[i] = alpha;
949    return v;
950}
951
952template<typename _Tp, int cn> inline
953Vec<_Tp, cn> Vec<_Tp, cn>::mul(const Vec<_Tp, cn>& v) const
954{
955    Vec<_Tp, cn> w;
956    for( int i = 0; i < cn; i++ ) w.val[i] = saturate_cast<_Tp>(this->val[i]*v.val[i]);
957    return w;
958}
959
960template<> inline
961Vec<float, 2> Vec<float, 2>::conj() const
962{
963    return cv::internal::conjugate(*this);
964}
965
966template<> inline
967Vec<double, 2> Vec<double, 2>::conj() const
968{
969    return cv::internal::conjugate(*this);
970}
971
972template<> inline
973Vec<float, 4> Vec<float, 4>::conj() const
974{
975    return cv::internal::conjugate(*this);
976}
977
978template<> inline
979Vec<double, 4> Vec<double, 4>::conj() const
980{
981    return cv::internal::conjugate(*this);
982}
983
984template<typename _Tp, int cn> inline
985Vec<_Tp, cn> Vec<_Tp, cn>::cross(const Vec<_Tp, cn>&) const
986{
987    CV_StaticAssert(cn == 3, "for arbitrary-size vector there is no cross-product defined");
988    return Vec<_Tp, cn>();
989}
990
991template<> inline
992Vec<float, 3> Vec<float, 3>::cross(const Vec<float, 3>& v) const
993{
994    return Vec<float,3>(val[1]*v.val[2] - val[2]*v.val[1],
995                     val[2]*v.val[0] - val[0]*v.val[2],
996                     val[0]*v.val[1] - val[1]*v.val[0]);
997}
998
999template<> inline
1000Vec<double, 3> Vec<double, 3>::cross(const Vec<double, 3>& v) const
1001{
1002    return Vec<double,3>(val[1]*v.val[2] - val[2]*v.val[1],
1003                     val[2]*v.val[0] - val[0]*v.val[2],
1004                     val[0]*v.val[1] - val[1]*v.val[0]);
1005}
1006
1007template<typename _Tp, int cn> template<typename T2> inline
1008Vec<_Tp, cn>::operator Vec<T2, cn>() const
1009{
1010    Vec<T2, cn> v;
1011    for( int i = 0; i < cn; i++ ) v.val[i] = saturate_cast<T2>(this->val[i]);
1012    return v;
1013}
1014
1015template<typename _Tp, int cn> inline
1016const _Tp& Vec<_Tp, cn>::operator [](int i) const
1017{
1018    CV_DbgAssert( (unsigned)i < (unsigned)cn );
1019    return this->val[i];
1020}
1021
1022template<typename _Tp, int cn> inline
1023_Tp& Vec<_Tp, cn>::operator [](int i)
1024{
1025    CV_DbgAssert( (unsigned)i < (unsigned)cn );
1026    return this->val[i];
1027}
1028
1029template<typename _Tp, int cn> inline
1030const _Tp& Vec<_Tp, cn>::operator ()(int i) const
1031{
1032    CV_DbgAssert( (unsigned)i < (unsigned)cn );
1033    return this->val[i];
1034}
1035
1036template<typename _Tp, int cn> inline
1037_Tp& Vec<_Tp, cn>::operator ()(int i)
1038{
1039    CV_DbgAssert( (unsigned)i < (unsigned)cn );
1040    return this->val[i];
1041}
1042
1043template<typename _Tp, int cn> inline
1044Vec<_Tp, cn> normalize(const Vec<_Tp, cn>& v)
1045{
1046    double nv = norm(v);
1047    return v * (nv ? 1./nv : 0.);
1048}
1049
1050
1051
1052//////////////////////////////// matx comma initializer //////////////////////////////////
1053
1054
1055template<typename _Tp, typename _T2, int cn> static inline
1056VecCommaInitializer<_Tp, cn> operator << (const Vec<_Tp, cn>& vec, _T2 val)
1057{
1058    VecCommaInitializer<_Tp, cn> commaInitializer((Vec<_Tp, cn>*)&vec);
1059    return (commaInitializer, val);
1060}
1061
1062template<typename _Tp, int cn> inline
1063VecCommaInitializer<_Tp, cn>::VecCommaInitializer(Vec<_Tp, cn>* _vec)
1064    : MatxCommaInitializer<_Tp, cn, 1>(_vec)
1065{}
1066
1067template<typename _Tp, int cn> template<typename _T2> inline
1068VecCommaInitializer<_Tp, cn>& VecCommaInitializer<_Tp, cn>::operator , (_T2 value)
1069{
1070    CV_DbgAssert( this->idx < cn );
1071    this->dst->val[this->idx++] = saturate_cast<_Tp>(value);
1072    return *this;
1073}
1074
1075template<typename _Tp, int cn> inline
1076Vec<_Tp, cn> VecCommaInitializer<_Tp, cn>::operator *() const
1077{
1078    CV_DbgAssert( this->idx == cn );
1079    return *this->dst;
1080}
1081
1082//! @endcond
1083
1084///////////////////////////// Matx out-of-class operators ////////////////////////////////
1085
1086//! @relates cv::Matx
1087//! @{
1088
1089template<typename _Tp1, typename _Tp2, int m, int n> static inline
1090Matx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b)
1091{
1092    for( int i = 0; i < m*n; i++ )
1093        a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);
1094    return a;
1095}
1096
1097template<typename _Tp1, typename _Tp2, int m, int n> static inline
1098Matx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b)
1099{
1100    for( int i = 0; i < m*n; i++ )
1101        a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);
1102    return a;
1103}
1104
1105template<typename _Tp, int m, int n> static inline
1106Matx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
1107{
1108    return Matx<_Tp, m, n>(a, b, Matx_AddOp());
1109}
1110
1111template<typename _Tp, int m, int n> static inline
1112Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
1113{
1114    return Matx<_Tp, m, n>(a, b, Matx_SubOp());
1115}
1116
1117template<typename _Tp, int m, int n> static inline
1118Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha)
1119{
1120    for( int i = 0; i < m*n; i++ )
1121        a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
1122    return a;
1123}
1124
1125template<typename _Tp, int m, int n> static inline
1126Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha)
1127{
1128    for( int i = 0; i < m*n; i++ )
1129        a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
1130    return a;
1131}
1132
1133template<typename _Tp, int m, int n> static inline
1134Matx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha)
1135{
1136    for( int i = 0; i < m*n; i++ )
1137        a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);
1138    return a;
1139}
1140
1141template<typename _Tp, int m, int n> static inline
1142Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha)
1143{
1144    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
1145}
1146
1147template<typename _Tp, int m, int n> static inline
1148Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha)
1149{
1150    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
1151}
1152
1153template<typename _Tp, int m, int n> static inline
1154Matx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha)
1155{
1156    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
1157}
1158
1159template<typename _Tp, int m, int n> static inline
1160Matx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a)
1161{
1162    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
1163}
1164
1165template<typename _Tp, int m, int n> static inline
1166Matx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a)
1167{
1168    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
1169}
1170
1171template<typename _Tp, int m, int n> static inline
1172Matx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a)
1173{
1174    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());
1175}
1176
1177template<typename _Tp, int m, int n> static inline
1178Matx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a)
1179{
1180    return Matx<_Tp, m, n>(a, -1, Matx_ScaleOp());
1181}
1182
1183template<typename _Tp, int m, int n, int l> static inline
1184Matx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b)
1185{
1186    return Matx<_Tp, m, n>(a, b, Matx_MatMulOp());
1187}
1188
1189template<typename _Tp, int m, int n> static inline
1190Vec<_Tp, m> operator * (const Matx<_Tp, m, n>& a, const Vec<_Tp, n>& b)
1191{
1192    Matx<_Tp, m, 1> c(a, b, Matx_MatMulOp());
1193    return (const Vec<_Tp, m>&)(c);
1194}
1195
1196template<typename _Tp, int m, int n> static inline
1197bool operator == (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
1198{
1199    for( int i = 0; i < m*n; i++ )
1200        if( a.val[i] != b.val[i] ) return false;
1201    return true;
1202}
1203
1204template<typename _Tp, int m, int n> static inline
1205bool operator != (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b)
1206{
1207    return !(a == b);
1208}
1209
1210//! @}
1211
1212////////////////////////////// Vec out-of-class operators ////////////////////////////////
1213
1214//! @relates cv::Vec
1215//! @{
1216
1217template<typename _Tp1, typename _Tp2, int cn> static inline
1218Vec<_Tp1, cn>& operator += (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b)
1219{
1220    for( int i = 0; i < cn; i++ )
1221        a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);
1222    return a;
1223}
1224
1225template<typename _Tp1, typename _Tp2, int cn> static inline
1226Vec<_Tp1, cn>& operator -= (Vec<_Tp1, cn>& a, const Vec<_Tp2, cn>& b)
1227{
1228    for( int i = 0; i < cn; i++ )
1229        a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);
1230    return a;
1231}
1232
1233template<typename _Tp, int cn> static inline
1234Vec<_Tp, cn> operator + (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b)
1235{
1236    return Vec<_Tp, cn>(a, b, Matx_AddOp());
1237}
1238
1239template<typename _Tp, int cn> static inline
1240Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a, const Vec<_Tp, cn>& b)
1241{
1242    return Vec<_Tp, cn>(a, b, Matx_SubOp());
1243}
1244
1245template<typename _Tp, int cn> static inline
1246Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, int alpha)
1247{
1248    for( int i = 0; i < cn; i++ )
1249        a[i] = saturate_cast<_Tp>(a[i]*alpha);
1250    return a;
1251}
1252
1253template<typename _Tp, int cn> static inline
1254Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, float alpha)
1255{
1256    for( int i = 0; i < cn; i++ )
1257        a[i] = saturate_cast<_Tp>(a[i]*alpha);
1258    return a;
1259}
1260
1261template<typename _Tp, int cn> static inline
1262Vec<_Tp, cn>& operator *= (Vec<_Tp, cn>& a, double alpha)
1263{
1264    for( int i = 0; i < cn; i++ )
1265        a[i] = saturate_cast<_Tp>(a[i]*alpha);
1266    return a;
1267}
1268
1269template<typename _Tp, int cn> static inline
1270Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, int alpha)
1271{
1272    double ialpha = 1./alpha;
1273    for( int i = 0; i < cn; i++ )
1274        a[i] = saturate_cast<_Tp>(a[i]*ialpha);
1275    return a;
1276}
1277
1278template<typename _Tp, int cn> static inline
1279Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, float alpha)
1280{
1281    float ialpha = 1.f/alpha;
1282    for( int i = 0; i < cn; i++ )
1283        a[i] = saturate_cast<_Tp>(a[i]*ialpha);
1284    return a;
1285}
1286
1287template<typename _Tp, int cn> static inline
1288Vec<_Tp, cn>& operator /= (Vec<_Tp, cn>& a, double alpha)
1289{
1290    double ialpha = 1./alpha;
1291    for( int i = 0; i < cn; i++ )
1292        a[i] = saturate_cast<_Tp>(a[i]*ialpha);
1293    return a;
1294}
1295
1296template<typename _Tp, int cn> static inline
1297Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, int alpha)
1298{
1299    return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
1300}
1301
1302template<typename _Tp, int cn> static inline
1303Vec<_Tp, cn> operator * (int alpha, const Vec<_Tp, cn>& a)
1304{
1305    return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
1306}
1307
1308template<typename _Tp, int cn> static inline
1309Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, float alpha)
1310{
1311    return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
1312}
1313
1314template<typename _Tp, int cn> static inline
1315Vec<_Tp, cn> operator * (float alpha, const Vec<_Tp, cn>& a)
1316{
1317    return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
1318}
1319
1320template<typename _Tp, int cn> static inline
1321Vec<_Tp, cn> operator * (const Vec<_Tp, cn>& a, double alpha)
1322{
1323    return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
1324}
1325
1326template<typename _Tp, int cn> static inline
1327Vec<_Tp, cn> operator * (double alpha, const Vec<_Tp, cn>& a)
1328{
1329    return Vec<_Tp, cn>(a, alpha, Matx_ScaleOp());
1330}
1331
1332template<typename _Tp, int cn> static inline
1333Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, int alpha)
1334{
1335    return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp());
1336}
1337
1338template<typename _Tp, int cn> static inline
1339Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, float alpha)
1340{
1341    return Vec<_Tp, cn>(a, 1.f/alpha, Matx_ScaleOp());
1342}
1343
1344template<typename _Tp, int cn> static inline
1345Vec<_Tp, cn> operator / (const Vec<_Tp, cn>& a, double alpha)
1346{
1347    return Vec<_Tp, cn>(a, 1./alpha, Matx_ScaleOp());
1348}
1349
1350template<typename _Tp, int cn> static inline
1351Vec<_Tp, cn> operator - (const Vec<_Tp, cn>& a)
1352{
1353    Vec<_Tp,cn> t;
1354    for( int i = 0; i < cn; i++ ) t.val[i] = saturate_cast<_Tp>(-a.val[i]);
1355    return t;
1356}
1357
1358template<typename _Tp> inline Vec<_Tp, 4> operator * (const Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2)
1359{
1360    return Vec<_Tp, 4>(saturate_cast<_Tp>(v1[0]*v2[0] - v1[1]*v2[1] - v1[2]*v2[2] - v1[3]*v2[3]),
1361                       saturate_cast<_Tp>(v1[0]*v2[1] + v1[1]*v2[0] + v1[2]*v2[3] - v1[3]*v2[2]),
1362                       saturate_cast<_Tp>(v1[0]*v2[2] - v1[1]*v2[3] + v1[2]*v2[0] + v1[3]*v2[1]),
1363                       saturate_cast<_Tp>(v1[0]*v2[3] + v1[1]*v2[2] - v1[2]*v2[1] + v1[3]*v2[0]));
1364}
1365
1366template<typename _Tp> inline Vec<_Tp, 4>& operator *= (Vec<_Tp, 4>& v1, const Vec<_Tp, 4>& v2)
1367{
1368    v1 = v1 * v2;
1369    return v1;
1370}
1371
1372//! @}
1373
1374} // cv
1375
1376#endif // __OPENCV_CORE_MATX_HPP__
1377