Update to 2.0.0 tree from current Fremantle build
[opencv] / include / opencv / cxmat.hpp
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 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #ifndef _OPENCV_CORE_MAT_OPERATIONS_H_
44 #define _OPENCV_CORE_MAT_OPERATIONS_H_
45
46 #ifndef SKIP_INCLUDES
47 #include <limits.h>
48 #endif // SKIP_INCLUDES
49
50 #ifdef __cplusplus
51
52 namespace cv
53 {
54
55 //////////////////////////////// Mat ////////////////////////////////
56
57 inline Mat::Mat()
58     : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0) {}
59
60 inline Mat::Mat(int _rows, int _cols, int _type)
61     : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
62 {
63     if( _rows > 0 && _cols > 0 )
64         create( _rows, _cols, _type );
65 }
66
67 inline Mat::Mat(int _rows, int _cols, int _type, const Scalar& _s)
68     : flags(0), rows(0), cols(0), step(0), data(0), refcount(0),
69     datastart(0), dataend(0)
70 {
71     if(_rows > 0 && _cols > 0)
72     {
73         create(_rows, _cols, _type);
74         *this = _s;
75     }
76 }
77
78 inline Mat::Mat(Size _size, int _type)
79     : flags(0), rows(0), cols(0), step(0), data(0), refcount(0),
80     datastart(0), dataend(0)
81 {
82     if( _size.height > 0 && _size.width > 0 )
83         create( _size.height, _size.width, _type );
84 }
85     
86 inline Mat::Mat(Size _size, int _type, const Scalar& _s)
87 : flags(0), rows(0), cols(0), step(0), data(0), refcount(0),
88 datastart(0), dataend(0)
89 {
90     if( _size.height > 0 && _size.width > 0 )
91     {
92         create( _size.height, _size.width, _type );
93         *this = _s;
94     }
95 }    
96
97 inline Mat::Mat(const Mat& m)
98     : flags(m.flags), rows(m.rows), cols(m.cols), step(m.step), data(m.data),
99     refcount(m.refcount), datastart(m.datastart), dataend(m.dataend)
100 {
101     if( refcount )
102         CV_XADD(refcount, 1);
103 }
104
105 inline Mat::Mat(int _rows, int _cols, int _type, void* _data, size_t _step)
106     : flags(MAGIC_VAL + (_type & TYPE_MASK)), rows(_rows), cols(_cols),
107     step(_step), data((uchar*)_data), refcount(0),
108     datastart((uchar*)_data), dataend((uchar*)_data)
109 {
110     size_t minstep = cols*elemSize();
111     if( step == AUTO_STEP )
112     {
113         step = minstep;
114         flags |= CONTINUOUS_FLAG;
115     }
116     else
117     {
118         if( rows == 1 ) step = minstep;
119         CV_DbgAssert( step >= minstep );
120         flags |= step == minstep ? CONTINUOUS_FLAG : 0;
121     }
122     dataend += step*(rows-1) + minstep;
123 }
124
125 inline Mat::Mat(Size _size, int _type, void* _data, size_t _step)
126     : flags(MAGIC_VAL + (_type & TYPE_MASK)), rows(_size.height), cols(_size.width),
127     step(_step), data((uchar*)_data), refcount(0),
128     datastart((uchar*)_data), dataend((uchar*)_data)
129 {
130     size_t minstep = cols*elemSize();
131     if( step == AUTO_STEP )
132     {
133         step = minstep;
134         flags |= CONTINUOUS_FLAG;
135     }
136     else
137     {
138         if( rows == 1 ) step = minstep;
139         CV_DbgAssert( step >= minstep );
140         flags |= step == minstep ? CONTINUOUS_FLAG : 0;
141     }
142     dataend += step*(rows-1) + minstep;
143 }
144
145 inline Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
146 {
147     flags = m.flags;
148     step = m.step; refcount = m.refcount;
149     data = m.data; datastart = m.datastart; dataend = m.dataend;
150
151     if( rowRange == Range::all() )
152         rows = m.rows;
153     else
154     {
155         CV_Assert( 0 <= rowRange.start && rowRange.start <= rowRange.end && rowRange.end <= m.rows );
156         rows = rowRange.size();
157         data += step*rowRange.start;
158     }
159
160     if( colRange == Range::all() )
161         cols = m.cols;
162     else
163     {
164         CV_Assert( 0 <= colRange.start && colRange.start <= colRange.end && colRange.end <= m.cols );
165         cols = colRange.size();
166         data += colRange.start*elemSize();
167         flags &= cols < m.cols ? ~CONTINUOUS_FLAG : -1;
168     }
169
170     if( rows == 1 )
171         flags |= CONTINUOUS_FLAG;
172
173     if( refcount )
174         CV_XADD(refcount, 1);
175     if( rows <= 0 || cols <= 0 )
176         rows = cols = 0;
177 }
178
179 inline Mat::Mat(const Mat& m, const Rect& roi)
180     : flags(m.flags), rows(roi.height), cols(roi.width),
181     step(m.step), data(m.data + roi.y*step), refcount(m.refcount),
182     datastart(m.datastart), dataend(m.dataend)
183 {
184     flags &= roi.width < m.cols ? ~CONTINUOUS_FLAG : -1;
185     data += roi.x*elemSize();
186     CV_Assert( 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols &&
187         0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows );
188     if( refcount )
189         CV_XADD(refcount, 1);
190     if( rows <= 0 || cols <= 0 )
191         rows = cols = 0;
192 }
193
194 inline Mat::Mat(const CvMat* m, bool copyData)
195     : flags(MAGIC_VAL + (m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))),
196     rows(m->rows), cols(m->cols), step(m->step), data(m->data.ptr), refcount(0),
197     datastart(m->data.ptr), dataend(m->data.ptr)
198 {
199     if( step == 0 )
200         step = cols*elemSize();
201     size_t minstep = cols*elemSize();
202     dataend += step*(rows-1) + minstep;
203     if( copyData )
204     {
205         data = datastart = dataend = 0;
206         Mat(m->rows, m->cols, m->type, m->data.ptr, m->step).copyTo(*this);
207     }
208 }
209
210 template<typename _Tp> inline Mat::Mat(const vector<_Tp>& vec, bool copyData)
211     : flags(MAGIC_VAL | DataType<_Tp>::type | CV_MAT_CONT_FLAG),
212     rows(0), cols(0), step(0), data(0), refcount(0),
213     datastart(0), dataend(0)
214 {
215     if(vec.empty())
216         return;
217     if( !copyData )
218     {
219         rows = (int)vec.size();
220         cols = 1;
221         step = sizeof(_Tp);
222         data = datastart = (uchar*)&vec[0];
223         dataend = datastart + rows*step;
224     }
225     else
226         Mat((int)vec.size(), 1, DataType<_Tp>::type, (uchar*)&vec[0]).copyTo(*this);
227 }
228     
229 inline Mat::~Mat()
230 {
231     release();
232 }
233
234 inline Mat& Mat::operator = (const Mat& m)
235 {
236     if( this != &m )
237     {
238         if( m.refcount )
239             CV_XADD(m.refcount, 1);
240         release();
241         flags = m.flags;
242         rows = m.rows; cols = m.cols;
243         step = m.step; data = m.data;
244         datastart = m.datastart; dataend = m.dataend;
245         refcount = m.refcount;
246     }
247     return *this;
248 }
249
250 inline Mat Mat::row(int y) const { return Mat(*this, Range(y, y+1), Range::all()); }
251 inline Mat Mat::col(int x) const { return Mat(*this, Range::all(), Range(x, x+1)); }
252 inline Mat Mat::rowRange(int startrow, int endrow) const
253     { return Mat(*this, Range(startrow, endrow), Range::all()); }
254 inline Mat Mat::rowRange(const Range& r) const
255     { return Mat(*this, r, Range::all()); }
256 inline Mat Mat::colRange(int startcol, int endcol) const
257     { return Mat(*this, Range::all(), Range(startcol, endcol)); }
258 inline Mat Mat::colRange(const Range& r) const
259     { return Mat(*this, Range::all(), r); }
260
261 inline Mat Mat::diag(int d) const
262 {
263     Mat m = *this;
264     size_t esz = elemSize();
265     int len;
266
267     if( d >= 0 )
268     {
269         len = std::min(cols - d, rows);
270         m.data += esz*d;
271     }
272     else
273     {
274         len = std::min(rows + d, cols);
275         m.data -= step*d;
276     }
277     CV_DbgAssert( len > 0 );
278     m.rows = len;
279     m.cols = 1;
280     m.step += esz;
281     if( m.rows > 1 )
282         m.flags &= ~CONTINUOUS_FLAG;
283     else
284         m.flags |= CONTINUOUS_FLAG;
285     return m;
286 }
287
288 inline Mat Mat::diag(const Mat& d)
289 {
290     Mat m(d.rows, d.rows, d.type(), Scalar(0)), md = m.diag();
291     d.copyTo(md);
292     return m;
293 }
294
295 inline Mat Mat::clone() const
296 {
297     Mat m;
298     copyTo(m);
299     return m;
300 }
301
302 inline void Mat::assignTo( Mat& m, int type ) const
303 {
304     if( type < 0 )
305         m = *this;
306     else
307         convertTo(m, type);
308 }
309
310 inline void Mat::create(int _rows, int _cols, int _type)
311 {
312     _type &= TYPE_MASK;
313     if( rows == _rows && cols == _cols && type() == _type && data )
314         return;
315     if( data )
316         release();
317     CV_DbgAssert( _rows >= 0 && _cols >= 0 );
318     if( _rows > 0 && _cols > 0 )
319     {
320         flags = MAGIC_VAL + CONTINUOUS_FLAG + _type;
321         rows = _rows;
322         cols = _cols;
323         step = elemSize()*cols;
324         int64 _nettosize = (int64)step*rows;
325         size_t nettosize = (size_t)_nettosize;
326         if( _nettosize != (int64)nettosize )
327             CV_Error(CV_StsNoMem, "Too big buffer is allocated");
328         size_t datasize = alignSize(nettosize, (int)sizeof(*refcount));
329         datastart = data = (uchar*)fastMalloc(datasize + sizeof(*refcount));
330         dataend = data + nettosize;
331         refcount = (int*)(data + datasize);
332         *refcount = 1;
333     }
334 }
335
336 inline void Mat::create(Size _size, int _type)
337 {
338     create(_size.height, _size.width, _type);
339 }
340
341 inline void Mat::addref()
342 { if( refcount ) CV_XADD(refcount, 1); }
343
344 inline void Mat::release()
345 {
346     if( refcount && CV_XADD(refcount, -1) == 1 )
347         fastFree(datastart);
348     data = datastart = dataend = 0;
349     step = rows = cols = 0;
350     refcount = 0;
351 }
352
353 inline void Mat::locateROI( Size& wholeSize, Point& ofs ) const
354 {
355     size_t esz = elemSize(), minstep;
356     ptrdiff_t delta1 = data - datastart, delta2 = dataend - datastart;
357     CV_DbgAssert( step > 0 );
358     if( delta1 == 0 )
359         ofs.x = ofs.y = 0;
360     else
361     {
362         ofs.y = (int)(delta1/step);
363         ofs.x = (int)((delta1 - step*ofs.y)/esz);
364         CV_DbgAssert( data == datastart + ofs.y*step + ofs.x*esz );
365     }
366     minstep = (ofs.x + cols)*esz;
367     wholeSize.height = (int)((delta2 - minstep)/step + 1);
368     wholeSize.height = std::max(wholeSize.height, ofs.y + rows);
369     wholeSize.width = (int)((delta2 - step*(wholeSize.height-1))/esz);
370     wholeSize.width = std::max(wholeSize.width, ofs.x + cols);
371 }
372
373 inline Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright )
374 {
375     Size wholeSize; Point ofs;
376     size_t esz = elemSize();
377     locateROI( wholeSize, ofs );
378     int row1 = std::max(ofs.y - dtop, 0), row2 = std::min(ofs.y + rows + dbottom, wholeSize.height);
379     int col1 = std::max(ofs.x - dleft, 0), col2 = std::min(ofs.x + cols + dright, wholeSize.width);
380     data += (row1 - ofs.y)*step + (col1 - ofs.x)*esz;
381     rows = row2 - row1; cols = col2 - col1;
382     if( esz*cols == step || rows == 1 )
383         flags |= CONTINUOUS_FLAG;
384     else
385         flags &= ~CONTINUOUS_FLAG;
386     return *this;
387 }
388
389 inline Mat Mat::operator()( Range rowRange, Range colRange ) const
390 {
391     return Mat(*this, rowRange, colRange);
392 }
393
394 inline Mat Mat::operator()( const Rect& roi ) const
395 { return Mat(*this, roi); }
396
397 inline Mat::operator CvMat() const
398 {
399     CvMat m = cvMat(rows, cols, type(), data);
400     m.step = (int)step;
401     m.type = (m.type & ~CONTINUOUS_FLAG) | (flags & CONTINUOUS_FLAG);
402     return m;
403 }
404
405 inline Mat::operator IplImage() const
406 {
407     IplImage img;
408     cvInitImageHeader(&img, size(), cvIplDepth(flags), channels());
409     cvSetData(&img, data, (int)step);
410     return img;
411 }
412
413 inline bool Mat::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; }
414 inline size_t Mat::elemSize() const { return CV_ELEM_SIZE(flags); }
415 inline size_t Mat::elemSize1() const { return CV_ELEM_SIZE1(flags); }
416 inline int Mat::type() const { return CV_MAT_TYPE(flags); }
417 inline int Mat::depth() const { return CV_MAT_DEPTH(flags); }
418 inline int Mat::channels() const { return CV_MAT_CN(flags); }
419 inline size_t Mat::step1() const { return step/elemSize1(); }
420 inline Size Mat::size() const { return Size(cols, rows); }
421 inline bool Mat::empty() const { return data == 0; }
422
423 inline uchar* Mat::ptr(int y)
424 {
425     CV_DbgAssert( (unsigned)y < (unsigned)rows );
426     return data + step*y;
427 }
428
429 inline const uchar* Mat::ptr(int y) const
430 {
431     CV_DbgAssert( (unsigned)y < (unsigned)rows );
432     return data + step*y;
433 }
434
435 template<typename _Tp> inline _Tp* Mat::ptr(int y)
436 {
437     CV_DbgAssert( (unsigned)y < (unsigned)rows );
438     return (_Tp*)(data + step*y);
439 }
440
441 template<typename _Tp> inline const _Tp* Mat::ptr(int y) const
442 {
443     CV_DbgAssert( (unsigned)y < (unsigned)rows );
444     return (const _Tp*)(data + step*y);
445 }
446
447 template<typename _Tp> inline _Tp& Mat::at(int y, int x)
448 {
449     CV_DbgAssert( (unsigned)y < (unsigned)rows && (unsigned)x < (unsigned)cols &&
450         sizeof(_Tp) == elemSize() );
451     return ((_Tp*)(data + step*y))[x];
452 }
453
454 template<typename _Tp> inline const _Tp& Mat::at(int y, int x) const
455 {
456     CV_DbgAssert( (unsigned)y < (unsigned)rows && (unsigned)x < (unsigned)cols &&
457         sizeof(_Tp) == elemSize() );
458     return ((const _Tp*)(data + step*y))[x];
459 }
460
461 template<typename _Tp> inline _Tp& Mat::at(Point pt)
462 {
463     CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && (unsigned)pt.x < (unsigned)cols &&
464         sizeof(_Tp) == elemSize() );
465     return ((_Tp*)(data + step*pt.y))[pt.x];
466 }
467
468 template<typename _Tp> inline const _Tp& Mat::at(Point pt) const
469 {
470     CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && (unsigned)pt.x < (unsigned)cols &&
471         sizeof(_Tp) == elemSize() );
472     return ((const _Tp*)(data + step*pt.y))[pt.x];
473 }
474     
475 template<typename _Tp> inline MatConstIterator_<_Tp> Mat::begin() const
476 {
477     CV_DbgAssert( elemSize() == sizeof(_Tp) );
478     return MatConstIterator_<_Tp>((const Mat_<_Tp>*)this);
479 }
480
481 template<typename _Tp> inline MatConstIterator_<_Tp> Mat::end() const
482 {
483     CV_DbgAssert( elemSize() == sizeof(_Tp) );
484     MatConstIterator_<_Tp> it((const Mat_<_Tp>*)this);
485     it.ptr = it.sliceEnd = (_Tp*)(data + step*(rows-1)) + cols;
486     return it;
487 }
488
489 template<typename _Tp> inline MatIterator_<_Tp> Mat::begin()
490 {
491     CV_DbgAssert( elemSize() == sizeof(_Tp) );
492     return MatIterator_<_Tp>((Mat_<_Tp>*)this);
493 }
494
495 template<typename _Tp> inline MatIterator_<_Tp> Mat::end()
496 {
497     CV_DbgAssert( elemSize() == sizeof(_Tp) );
498     MatIterator_<_Tp> it((Mat_<_Tp>*)this);
499     it.ptr = it.sliceEnd = (_Tp*)(data + step*(rows-1)) + cols;
500     return it;
501 }
502     
503     
504 static inline void swap( Mat& a, Mat& b )
505 {
506     std::swap( a.flags, b.flags );
507     std::swap( a.rows, b.rows ); std::swap( a.cols, b.cols );
508     std::swap( a.step, b.step ); std::swap( a.data, b.data );
509     std::swap( a.datastart, b.datastart );
510     std::swap( a.dataend, b.dataend );
511     std::swap( a.refcount, b.refcount );
512 }
513
514 inline SVD::SVD() {}
515 inline SVD::SVD( const Mat& m, int flags ) { operator ()(m, flags); }
516 inline void SVD::solveZ( const Mat& m, Mat& dst )
517 {
518     SVD svd(m);
519     svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst);
520 }
521
522 ///////////////////////////////// Mat_<_Tp> ////////////////////////////////////
523
524 template<typename _Tp> inline Mat_<_Tp>::Mat_() :
525     Mat() { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; }
526     
527 template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols) :
528     Mat(_rows, _cols, DataType<_Tp>::type) {}
529
530 template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, const _Tp& value) :
531     Mat(_rows, _cols, DataType<_Tp>::type) { *this = value; }
532
533 template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _size) :
534     Mat(_size.height, _size.width, DataType<_Tp>::type) {}
535     
536 template<typename _Tp> inline Mat_<_Tp>::Mat_(Size _size, const _Tp& value) :
537     Mat(_size.height, _size.width, DataType<_Tp>::type) { *this = value; }
538     
539 template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat& m) : Mat()
540 { flags = (flags & ~CV_MAT_TYPE_MASK) | DataType<_Tp>::type; *this = m; }
541
542 template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m) : Mat(m) {}
543
544 template<typename _Tp> inline Mat_<_Tp>::Mat_(int _rows, int _cols, _Tp* _data, size_t _step)
545     : Mat(_rows, _cols, DataType<_Tp>::type, _data, _step) {}
546
547 template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m, const Range& rowRange, const Range& colRange)
548     : Mat(m, rowRange, colRange) {}
549
550 template<typename _Tp> inline Mat_<_Tp>::Mat_(const Mat_& m, const Rect& roi)
551     : Mat(m, roi) {}
552
553 template<typename _Tp> template<int n> inline Mat_<_Tp>::Mat_(const Vec<_Tp, n>& vec)
554     : Mat(n, 1, DataType<_Tp>::type)
555 {
556     _Tp* d = (_Tp*)data;
557     for( int i = 0; i < n; i++ )
558         d[i] = vec[i];
559 }
560
561 template<typename _Tp> inline Mat_<_Tp>::Mat_(const vector<_Tp>& vec, bool copyData)
562     : Mat(vec, copyData)
563 {}
564
565 template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat& m)
566 {
567     if( DataType<_Tp>::type == m.type() )
568     {
569         Mat::operator = (m);
570         return *this;
571     }
572     if( DataType<_Tp>::depth == m.depth() )
573     {
574         return (*this = m.reshape(DataType<_Tp>::channels));
575     }
576     CV_DbgAssert(DataType<_Tp>::channels == m.channels());
577     m.convertTo(*this, type());
578     return *this;
579 }
580
581 template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const Mat_& m)
582 {
583     Mat::operator=(m);
584     return *this;
585 }
586
587 template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const _Tp& s)
588 {
589     Mat::operator=(Scalar(s));
590     return *this;
591 }
592
593 template<typename _Tp> inline void Mat_<_Tp>::create(int _rows, int _cols)
594 {
595     Mat::create(_rows, _cols, DataType<_Tp>::type);
596 }
597
598 template<typename _Tp> inline void Mat_<_Tp>::create(Size _size)
599 {
600     Mat::create(_size, DataType<_Tp>::type);
601 }
602
603 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::cross(const Mat_& m) const
604 { return Mat_<_Tp>(Mat::cross(m)); }
605
606 template<typename _Tp> template<typename T2> inline Mat_<_Tp>::operator Mat_<T2>() const
607 { return Mat_<T2>(*this); }
608
609 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::row(int y) const
610 { return Mat_(*this, Range(y, y+1), Range::all()); }
611 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::col(int x) const
612 { return Mat_(*this, Range::all(), Range(x, x+1)); }
613 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::diag(int d) const
614 { return Mat_(Mat::diag(d)); }
615 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::clone() const
616 { return Mat_(Mat::clone()); }
617
618 template<typename _Tp> inline size_t Mat_<_Tp>::elemSize() const
619 {
620     CV_DbgAssert( Mat::elemSize() == sizeof(_Tp) );
621     return sizeof(_Tp);
622 }
623
624 template<typename _Tp> inline size_t Mat_<_Tp>::elemSize1() const
625 {
626     CV_DbgAssert( Mat::elemSize1() == sizeof(_Tp)/DataType<_Tp>::channels );
627     return sizeof(_Tp)/DataType<_Tp>::channels;
628 }
629 template<typename _Tp> inline int Mat_<_Tp>::type() const
630 {
631     CV_DbgAssert( Mat::type() == DataType<_Tp>::type );
632     return DataType<_Tp>::type;
633 }
634 template<typename _Tp> inline int Mat_<_Tp>::depth() const
635 {
636     CV_DbgAssert( Mat::depth() == DataType<_Tp>::depth );
637     return DataType<_Tp>::depth;
638 }
639 template<typename _Tp> inline int Mat_<_Tp>::channels() const
640 {
641     CV_DbgAssert( Mat::channels() == DataType<_Tp>::channels );
642     return DataType<_Tp>::channels;
643 }
644 template<typename _Tp> inline size_t Mat_<_Tp>::stepT() const { return step/elemSize(); }
645 template<typename _Tp> inline size_t Mat_<_Tp>::step1() const { return step/elemSize1(); }
646
647 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::reshape(int _rows) const
648 { return Mat_<_Tp>(Mat::reshape(0,_rows)); }
649
650 template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::adjustROI( int dtop, int dbottom, int dleft, int dright )
651 { return (Mat_<_Tp>&)(Mat::adjustROI(dtop, dbottom, dleft, dright));  }
652
653 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Range& rowRange, const Range& colRange ) const
654 { return Mat_<_Tp>(*this, rowRange, colRange); }
655
656 template<typename _Tp> inline Mat_<_Tp> Mat_<_Tp>::operator()( const Rect& roi ) const
657 { return Mat_<_Tp>(roi); }
658
659 template<typename _Tp> inline _Tp* Mat_<_Tp>::operator [](int y)
660 { return (_Tp*)ptr(y); }
661 template<typename _Tp> inline const _Tp* Mat_<_Tp>::operator [](int y) const
662 { return (const _Tp*)ptr(y); }
663
664 template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(int row, int col)
665 {
666     CV_DbgAssert( (unsigned)row < (unsigned)rows && (unsigned)col < (unsigned)cols );
667     return ((_Tp*)(data + step*row))[col];
668 }
669
670 template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(int row, int col) const
671 {
672     CV_DbgAssert( (unsigned)row < (unsigned)rows && (unsigned)col < (unsigned)cols );
673     return ((const _Tp*)(data + step*row))[col];
674 }
675
676 template<typename _Tp> inline _Tp& Mat_<_Tp>::operator ()(Point pt)
677 {
678     CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && (unsigned)pt.x < (unsigned)cols );
679     return ((_Tp*)(data + step*pt.y))[pt.x];
680 }
681
682 template<typename _Tp> inline const _Tp& Mat_<_Tp>::operator ()(Point pt) const
683 {
684     CV_DbgAssert( (unsigned)pt.y < (unsigned)rows && (unsigned)pt.x < (unsigned)cols );
685     return ((const _Tp*)(data + step*pt.y))[pt.x];
686 }
687
688 template<typename _Tp> inline Mat_<_Tp>::operator vector<_Tp>() const
689 {
690     CV_Assert( rows == 1 || cols == 1 );
691     return isContinuous() ? vector<_Tp>((size_t)(rows + cols - 1), (_Tp*)data) :
692         (vector<_Tp>)((Mat_<_Tp>)this->t());
693 }
694
695 template<typename T1, typename T2, typename Op> inline void
696 process( const Mat_<T1>& m1, Mat_<T2>& m2, Op op )
697 {
698     int y, x, rows = m1.rows, cols = m1.cols;
699     int c1 = m1.channels(), c2 = m2.channels();
700
701     CV_DbgAssert( m1.size() == m2.size() );
702
703     for( y = 0; y < rows; y++ )
704     {
705         const T1* src = m1[y];
706         T2* dst = m2[y];
707
708         for( x = 0; x < cols; x++ )
709             dst[x] = op(src[x]);
710     }
711 }
712
713 template<typename T1, typename T2, typename T3, typename Op> inline void
714 process( const Mat_<T1>& m1, const Mat_<T2>& m2, Mat_<T3>& m3, Op op )
715 {
716     int y, x, rows = m1.rows, cols = m1.cols;
717
718     CV_DbgAssert( m1.size() == m2.size() );
719
720     for( y = 0; y < rows; y++ )
721     {
722         const T1* src1 = m1[y];
723         const T2* src2 = m2[y];
724         T3* dst = m3[y];
725
726         for( x = 0; x < cols; x++ )
727             dst[x] = op( src1[x], src2[x] );
728     }
729 }
730
731 template<typename M> class CV_EXPORTS MatExpr_Base_
732 {
733 public:
734     MatExpr_Base_() {}
735     virtual ~MatExpr_Base_() {}
736     virtual void assignTo(M& m, int type=-1) const = 0;
737 };
738
739 template<typename E, typename M> class CV_EXPORTS MatExpr_ : public MatExpr_Base_<M>
740 {
741 public:
742     MatExpr_(const E& _e) : e(_e) {}
743     ~MatExpr_() {}
744     operator M() const { return (M)e; }
745     void assignTo(M& m, int type=-1) const { e.assignTo(m, type); }
746
747     M row(int y) const { return ((M)e).row(y); }
748     M col(int x) const { return ((M)e).col(x); }
749     M diag(int d=0) const { return ((M)e).diag(d); }
750
751     M operator()( const Range& rowRange, const Range& colRange ) const
752     { return ((M)e)(rowRange, colRange); }
753     M operator()( const Rect& roi ) const { return ((M)e)(roi); }
754
755     M cross(const M& m) const { return ((M)e).cross(m); }
756     double dot(const M& m) const { return ((M)e).dot(m); }
757
758     MatExpr_<MatExpr_Op2_<M, double, M, MatOp_T_<Mat> >, M> t() const
759     { return ((M)e).t(); }
760     MatExpr_<MatExpr_Op2_<M, int, M, MatOp_Inv_<Mat> >, M> inv(int method=DECOMP_LU) const
761     { return ((M)e).inv(method); }
762
763     MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
764     mul(const M& m, double scale=1) const
765     { return ((M)e).mul(m, scale); }
766     template<typename A> MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M >
767     mul(const MatExpr_<A, M>& m, double scale=1) const
768     { return ((M)e).mul(m, scale); }
769
770     E e;
771 };
772
773
774 inline Mat::Mat(const MatExpr_Base& expr)
775  : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
776 {
777     expr.assignTo(*this);
778 }
779
780 inline Mat& Mat::operator = (const MatExpr_Base& expr)
781 {
782     expr.assignTo(*this);
783     return *this;
784 }
785
786 template<typename _Tp> inline Mat_<_Tp>::Mat_(const MatExpr_Base& e) : Mat()
787 {
788     e.assignTo(*this, DataType<_Tp>::type);
789 }
790
791 template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr_Base& e)
792 {
793     e.assignTo(*this, DataType<_Tp>::type);
794     return *this;
795 }
796
797 template<typename _Tp> inline Mat_<_Tp>::operator MatExpr_<Mat_<_Tp>, Mat_<_Tp> >() const
798 { return MatExpr_<Mat_<_Tp>, Mat_<_Tp> >(*this); }
799
800 inline Mat::operator MatExpr_<Mat, Mat>() const
801 { return MatExpr_<Mat, Mat>(*this); }
802
803 template<typename M> class CV_EXPORTS MatOp_Sub_
804 {
805 public:
806     MatOp_Sub_() {}
807
808     static void apply(const M& a, const M& b, M& c, int type=-1)
809     {
810         if( type == a.type() || type < 0 )
811         {
812             subtract( a, b, c );
813         }
814         else
815         {
816             Mat temp;
817             apply(a, b, temp);
818             temp.convertTo(c, type);
819         }
820     }
821 };
822
823 template<typename M> class CV_EXPORTS MatOp_Scale_
824 {
825 public:
826     MatOp_Scale_() {}
827
828     static void apply(const M& a, double alpha, M& c, int type=-1)
829     {
830         a.convertTo(c, type, alpha, 0);
831     }
832 };
833
834 template<typename M> class CV_EXPORTS MatOp_ScaleAddS_
835 {
836 public:
837     MatOp_ScaleAddS_() {}
838
839     static void apply(const M& a, double alpha, double beta, M& c, int type=-1)
840     {
841         a.convertTo(c, type, alpha, beta);
842     }
843 };
844
845 template<typename M> class CV_EXPORTS MatOp_AddS_
846 {
847 public:
848     MatOp_AddS_() {}
849
850     static void apply(const M& a, const Scalar& s, M& c, int type=-1)
851     {
852         if( type == a.type() || type < 0 )
853         {
854             add(a, s, c);
855         }
856         else
857         {
858             Mat temp;
859             apply(a, s, temp);
860             temp.convertTo(c, type);
861         }
862     }
863 };
864
865 template<typename M> class CV_EXPORTS MatOp_AddEx_
866 {
867 public:
868     MatOp_AddEx_() {}
869
870     static void apply(const M& a, double alpha, const M& b,
871                       double beta, double gamma, M& c, int type=-1)
872     {
873         if( type == a.type() || type < 0 )
874         {
875             addWeighted(a, alpha, b, beta, gamma, c);
876         }
877         else
878         {
879             Mat temp;
880             apply(a, alpha, b, beta, gamma, temp);
881             temp.convertTo(c, type);
882         }
883     }
884 };
885
886 template<typename M> class CV_EXPORTS MatOp_Bin_
887 {
888 public:
889     MatOp_Bin_() {}
890
891     static void apply(const M& a, const M& b, int _op, M& c, int type=-1)
892     {
893         char op = (char)_op;
894         if( type == a.type() || type < 0 )
895         {
896             if( op == '&' )
897                 bitwise_and( a, b, c );
898             else if( op == '|' )
899                 bitwise_or( a, b, c );
900             else if( op == '^' )
901                 bitwise_xor( a, b, c );
902             else if( op == 'm' )
903                 min( a, b, c );
904             else if( op == 'M' )
905                 max( a, b, c );
906             else if( op == 'a' )
907                 absdiff( a, b, c );
908             else
909                 assert(0);
910         }
911         else
912         {
913             Mat temp;
914             apply(a, b, op, temp);
915             temp.convertTo(c, type);
916         }
917     }
918 };
919
920 template<typename M> class CV_EXPORTS MatOp_BinS_
921 {
922 public:
923     MatOp_BinS_() {}
924
925     static void apply(const M& a, const Scalar& s, int _op, M& c, int type=-1)
926     {
927         char op = (char)_op;
928         if( type == a.type() || type < 0 )
929         {
930             if( op == '&' )
931                 bitwise_and( a, s, c );
932             else if( op == '|' )
933                 bitwise_or( a, s, c );
934             else if( op == '^' )
935                 bitwise_xor( a, s, c );
936             else if( op == 'm' )
937                 min( a, s[0], c );
938             else if( op == 'M' )
939                 max( a, s[0], c );
940             else if( op == 'a' )
941                 absdiff( a, s, c );
942             else if( op == '~' )
943                 bitwise_not( a, c );
944             else
945                 assert(0);
946         }
947         else
948         {
949             Mat temp;
950             apply(a, s, op, temp);
951             temp.convertTo(c, type);
952         }
953     }
954 };
955
956 template<typename M> class CV_EXPORTS MatOp_T_
957 {
958 public:
959     MatOp_T_() {}
960
961     static void apply(const M& a, double scale, M& c, int type=-1)
962     {
963         if( type == a.type() || type < 0 )
964         {
965             transpose(a, c);
966             if( fabs(scale - 1) > DBL_EPSILON )
967                 c.convertTo(c, -1, scale, 0);
968         }
969         else
970         {
971             Mat temp;
972             apply(a, scale, temp);
973             temp.convertTo(c, type);
974         }
975     }
976 };
977
978
979 template<typename M> class CV_EXPORTS MatOp_MatMul_
980 {
981 public:
982     MatOp_MatMul_() {}
983
984     static void apply(const M& a, const M& b, double scale, int flags, M& c, int type=-1)
985     {
986         if( type == a.type() || type < 0 )
987         {
988             gemm(a, b, scale, Mat(), 0, c, flags);
989         }
990         else
991         {
992             Mat temp;
993             apply(a, b, scale, flags, temp);
994             temp.convertTo(c, type);
995         }
996     }
997 };
998
999
1000 template<typename M> class CV_EXPORTS MatOp_MatMulAdd_
1001 {
1002 public:
1003     MatOp_MatMulAdd_() {}
1004
1005     static void apply(const M& a, const M& b, double alpha,
1006         const M& c, double beta, int flags, M& d, int type=-1)
1007     {
1008         if( type == a.type() || type < 0 )
1009         {
1010             gemm(a, b, alpha, c, beta, d, flags);
1011         }
1012         else
1013         {
1014             Mat temp;
1015             apply(a, b, alpha, c, beta, flags, temp);
1016             temp.convertTo(d, type);
1017         }
1018     }
1019 };
1020
1021
1022 template<typename M> class CV_EXPORTS MatOp_Cmp_
1023 {
1024 public:
1025     MatOp_Cmp_() {}
1026
1027     static void apply(const M& a, const M& b, int op, M& c, int type=-1)
1028     {
1029         if( type == CV_8UC1 || type == -1 )
1030         {
1031             compare(a, b, c, op);
1032         }
1033         else
1034         {
1035             Mat temp;
1036             apply(a, b, op, temp);
1037             temp.convertTo(c, type);
1038         }
1039     }
1040 };
1041
1042 template<typename M> class CV_EXPORTS MatOp_CmpS_
1043 {
1044 public:
1045     MatOp_CmpS_() {}
1046
1047     static void apply(const M& a, double alpha, int op, M& c, int type=-1)
1048     {
1049         if( type == CV_8UC1 || type == -1 )
1050         {
1051             compare(a, alpha, c, op);
1052         }
1053         else
1054         {
1055             Mat temp;
1056             apply(a, alpha, op, temp);
1057             temp.convertTo(c, type);
1058         }
1059     }
1060 };
1061
1062 template<typename M> class CV_EXPORTS MatOp_MulDiv_
1063 {
1064 public:
1065     MatOp_MulDiv_() {}
1066
1067     static void apply(const M& a, const M& b, double alpha, char op, M& c, int type=-1)
1068     {
1069         if( type == a.type() || type == -1 )
1070         {
1071             if( op == '*' )
1072                 multiply( a, b, c, alpha );
1073             else
1074                 divide( a, b, c, alpha );
1075         }
1076         else
1077         {
1078             Mat temp;
1079             apply(a, b, alpha, op, temp);
1080             temp.convertTo(c, type);
1081         }
1082     }
1083 };
1084
1085 template<typename M> class CV_EXPORTS MatOp_DivRS_
1086 {
1087 public:
1088     MatOp_DivRS_() {}
1089
1090     static void apply(const M& a, double alpha, M& c, int type=-1)
1091     {
1092         if( type == a.type() || type == -1 )
1093         {
1094             c.create(a.rows, a.cols, a.type());
1095             divide( alpha, a, c );
1096         }
1097         else
1098         {
1099             Mat temp;
1100             apply(a, alpha, temp);
1101             temp.convertTo(c, type);
1102         }
1103     }
1104 };
1105
1106
1107 template<typename M> class CV_EXPORTS MatOp_Inv_
1108 {
1109 public:
1110     MatOp_Inv_() {}
1111
1112     static void apply(const M& a, int method, M& c, int type=-1)
1113     {
1114         if( type == a.type() || type == -1 )
1115         {
1116             invert(a, c, method);
1117         }
1118         else
1119         {
1120             Mat temp;
1121             apply(a, method, temp);
1122             temp.convertTo(c, type);
1123         }
1124     }
1125 };
1126
1127
1128 template<typename M> class CV_EXPORTS MatOp_Solve_
1129 {
1130 public:
1131     MatOp_Solve_() {}
1132
1133     static void apply(const M& a, const M& b, int method, M& c, int type=-1)
1134     {
1135         if( type == a.type() || type == -1 )
1136         {
1137             solve(a, b, c, method);
1138         }
1139         else
1140         {
1141             Mat temp;
1142             apply(a, b, method, temp);
1143             temp.convertTo(c, type);
1144         }
1145     }
1146 };
1147
1148 template<typename M> class CV_EXPORTS MatOp_Set_
1149 {
1150 public:
1151     MatOp_Set_() {}
1152
1153     static void apply(Size size, int type0, const Scalar& s, int mtype, M& c, int type=-1)
1154     {
1155         if( type < 0 )
1156             type = type0;
1157         c.create(size.height, size.width, type);
1158         if( mtype == 0 )
1159             c = Scalar(0);
1160         else if( mtype == 1 )
1161             c = s;
1162         else if( mtype == 2 )
1163             setIdentity(c, s);
1164     }
1165 };
1166
1167 template<typename A1, typename M, typename Op>
1168 class CV_EXPORTS MatExpr_Op1_
1169 {
1170 public:
1171     MatExpr_Op1_(const A1& _a1) : a1(_a1) {}
1172     void assignTo(Mat& m, int type=-1) const { Op::apply(a1, (M&)m, type); }
1173     operator M() const { M result; assignTo(result); return result; }
1174
1175     A1 a1;
1176 };
1177
1178 template<typename A1, typename A2, typename M, typename Op>
1179 class CV_EXPORTS MatExpr_Op2_
1180 {
1181 public:
1182     MatExpr_Op2_(const A1& _a1, const A2& _a2) : a1(_a1), a2(_a2) {}
1183     void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, (M&)m, type); }
1184     operator M() const { M result; assignTo(result); return result; }
1185
1186     A1 a1; A2 a2;
1187 };
1188
1189 template<typename A1, typename A2, typename A3, typename M, typename Op>
1190 class CV_EXPORTS MatExpr_Op3_
1191 {
1192 public:
1193     MatExpr_Op3_(const A1& _a1, const A2& _a2, const A3& _a3) : a1(_a1), a2(_a2), a3(_a3) {}
1194     void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, (M&)m, type); }
1195     operator M() const { M result; assignTo(result); return result; }
1196
1197     A1 a1; A2 a2; A3 a3;
1198 };
1199
1200 template<typename A1, typename A2, typename A3, typename A4, typename M, typename Op>
1201 class CV_EXPORTS MatExpr_Op4_
1202 {
1203 public:
1204     MatExpr_Op4_(const A1& _a1, const A2& _a2, const A3& _a3, const A4& _a4)
1205         : a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
1206     void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, a4, (M&)m, type); }
1207     operator M() const { M result; assignTo(result); return result; }
1208
1209     A1 a1; A2 a2; A3 a3; A4 a4;
1210 };
1211
1212 template<typename A1, typename A2, typename A3, typename A4, typename A5, typename M, typename Op>
1213 class CV_EXPORTS MatExpr_Op5_
1214 {
1215 public:
1216     MatExpr_Op5_(const A1& _a1, const A2& _a2, const A3& _a3, const A4& _a4, const A5& _a5)
1217         : a1(_a1), a2(_a2), a3(_a3), a4(_a4), a5(_a5) {}
1218     void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, a4, a5, (M&)m, type); }
1219     operator M() const { M result; assignTo(result); return result; }
1220
1221     A1 a1; A2 a2; A3 a3; A4 a4; A5 a5;
1222 };
1223
1224 template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename M, typename Op>
1225 class CV_EXPORTS MatExpr_Op6_
1226 {
1227 public:
1228     MatExpr_Op6_(const A1& _a1, const A2& _a2, const A3& _a3,
1229                     const A4& _a4, const A5& _a5, const A6& _a6)
1230         : a1(_a1), a2(_a2), a3(_a3), a4(_a4), a5(_a5), a6(_a6) {}
1231     void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, a4, a5, a6, (M&)m, type); }
1232     operator M() const { M result; assignTo(result); return result; }
1233
1234     A1 a1; A2 a2; A3 a3; A4 a4; A5 a5; A6 a6;
1235 };
1236
1237 ///////////////////////////////// Arithmetical Operations ///////////////////////////////////
1238
1239 // A + B
1240 static inline MatExpr_<MatExpr_Op5_<Mat, double, Mat, double, double, Mat, MatOp_AddEx_<Mat> >, Mat>
1241 operator + (const Mat& a, const Mat& b)
1242 {
1243     typedef MatExpr_Op5_<Mat, double, Mat, double, double, Mat, MatOp_AddEx_<Mat> > MatExpr_Temp;
1244     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, 1, b, 1, 0));
1245 }
1246
1247 template<typename _Tp> static inline
1248 MatExpr_<MatExpr_Op5_<Mat_<_Tp>, double, Mat_<_Tp>,
1249 double, double, Mat_<_Tp>, MatOp_AddEx_<Mat> >, Mat_<_Tp> >
1250 operator + (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
1251 {
1252     typedef MatExpr_Op5_<Mat_<_Tp>, double, Mat_<_Tp>, double, double, Mat_<_Tp>, MatOp_AddEx_<Mat> > MatExpr_Temp;
1253     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, 1, b, 1, 0));
1254 }
1255
1256 // E1 + E2
1257 template<typename A, typename B, typename M> static inline
1258 MatExpr_<MatExpr_Op5_<M, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1259 operator + (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b )
1260 {
1261     typedef MatExpr_Op5_<M, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1262     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, 1, (M)b, 1, 0));
1263 }
1264
1265 // A - B
1266 static inline MatExpr_<MatExpr_Op2_<Mat, Mat, Mat, MatOp_Sub_<Mat> >, Mat>
1267 operator - (const Mat& a, const Mat& b)
1268 {
1269     typedef MatExpr_Op2_<Mat, Mat, Mat, MatOp_Sub_<Mat> > MatExpr_Temp;
1270     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b));
1271 }
1272
1273 template<typename _Tp> static inline
1274 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, Mat_<_Tp>, Mat_<_Tp>, MatOp_Sub_<Mat> >, Mat_<_Tp> >
1275 operator - (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
1276 {
1277     typedef MatExpr_Op2_<Mat_<_Tp>, Mat_<_Tp>, Mat_<_Tp>, MatOp_Sub_<Mat> > MatExpr_Temp;
1278     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, b));
1279 }
1280
1281 // E1 - E2
1282 template<typename A, typename B, typename M> static inline
1283 MatExpr_<MatExpr_Op2_<M, M, M, MatOp_Sub_<Mat> >, M>
1284 operator - (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b )
1285 {
1286     typedef MatExpr_Op2_<M, M, M, MatOp_Sub_<Mat> > MatExpr_Temp;
1287     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, (M)b));
1288 }
1289
1290 // -(E1 - E2)
1291 template<typename A, typename B, typename M> static inline
1292 MatExpr_<MatExpr_Op2_<B, A, M, MatOp_Sub_<Mat> >, M>
1293 operator - (const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a )
1294 {
1295     typedef MatExpr_Op2_<B, A, M, MatOp_Sub_<Mat> > MatExpr_Temp;
1296     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a2, a.e.a1));
1297 }
1298
1299 // (A - B)*alpha
1300 template<typename A, typename B, typename M> static inline
1301 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1302 operator * (const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a,
1303             double alpha)
1304 {
1305     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1306     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, alpha, a.e.a2, -alpha, 0));
1307 }
1308
1309 // alpha*(A - B)
1310 template<typename A, typename B, typename M> static inline
1311 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1312 operator * (double alpha,
1313             const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a)
1314 { return a*alpha; }
1315
1316
1317 // A*alpha
1318 static inline
1319 MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
1320 operator * (const Mat& a, double alpha)
1321 {
1322     typedef MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> > MatExpr_Temp;
1323     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha));
1324 }
1325
1326 // A*alpha
1327 template<typename _Tp> static inline
1328 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_Scale_<Mat> >, Mat_<_Tp> >
1329 operator * (const Mat_<_Tp>& a, double alpha)
1330 {
1331     typedef MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_Scale_<Mat> > MatExpr_Temp;
1332     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, alpha));
1333 }
1334
1335 // alpha*A
1336 static inline
1337 MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
1338 operator * (double alpha, const Mat& a)
1339 { return a*alpha; }
1340
1341 // alpha*A
1342 template<typename _Tp> static inline
1343 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_Scale_<Mat> >, Mat_<_Tp> >
1344 operator * (double alpha, const Mat_<_Tp>& a)
1345 { return a*alpha; }
1346
1347 // A/alpha
1348 static inline
1349 MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
1350 operator / (const Mat& a, double alpha)
1351 { return a*(1./alpha); }
1352
1353 // A/alpha
1354 template<typename _Tp> static inline
1355 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_Scale_<Mat> >, Mat_<_Tp> >
1356 operator / (const Mat_<_Tp>& a, double alpha)
1357 { return a*(1./alpha); }
1358
1359 // -A
1360 static inline
1361 MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
1362 operator - (const Mat& a)
1363 { return a*(-1); }
1364
1365 // -A
1366 template<typename _Tp> static inline
1367 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_Scale_<Mat> >, Mat_<_Tp> >
1368 operator - (const Mat_<_Tp>& a)
1369 { return a*(-1); }
1370
1371 // E*alpha
1372 template<typename A, typename M> static inline
1373 MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
1374 operator * (const MatExpr_<A, M>& a, double alpha)
1375 {
1376     typedef MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> > MatExpr_Temp;
1377     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, alpha));
1378 }
1379
1380 // alpha*E
1381 template<typename A, typename M> static inline
1382 MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
1383 operator * (double alpha, const MatExpr_<A, M>& a)
1384 { return a*alpha; }
1385
1386 // E/alpha
1387 template<typename A, typename M> static inline
1388 MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
1389 operator / (const MatExpr_<A, M>& a, double alpha)
1390 { return a*(1./alpha); }
1391
1392 // (E*alpha)*beta ~ E*(alpha*beta)
1393 template<typename A, typename M> static inline
1394 MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
1395 operator * (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1396             double beta)
1397 { return a.e.a1*(a.e.a2*beta); }
1398
1399 // beta*(E*alpha) ~ E*(alpha*beta)
1400 template<typename A, typename M> static inline
1401 MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
1402 operator * (double beta,
1403             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1404 { return a.e.a1*(a.e.a2*beta); }
1405
1406 // (E*alpha)/beta ~ E*(alpha/beta)
1407 template<typename A, typename M> static inline
1408 MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
1409 operator / (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1410             double beta)
1411 { return a.e.a1*(a.e.a2/beta); }
1412
1413 // -E ~ E*(-1)
1414 template<typename A, typename M> static inline
1415 MatExpr_<MatExpr_Op2_<MatExpr_<A, M>, double, M, MatOp_Scale_<Mat> >, M>
1416 operator - (const MatExpr_<A, M>& a)
1417 { return a*(-1); }
1418
1419 // -(E*alpha) ~ E*(-alpha)
1420 template<typename A, typename M> static inline
1421 MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
1422 operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1423 { return a.e.a1*(-a.e.a2); }
1424
1425 // A + alpha
1426 template<typename _Tp> static inline
1427 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, double, double, Mat_<_Tp>, MatOp_ScaleAddS_<Mat> >, Mat_<_Tp> >
1428 operator + (const Mat_<_Tp>& a, double alpha)
1429 {
1430     typedef MatExpr_Op3_<Mat_<_Tp>, double, double, Mat_<_Tp>,
1431         MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
1432     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, 1, alpha));
1433 }
1434
1435 // A + alpha
1436 template<typename _Tp> static inline
1437 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, Scalar, Mat_<_Tp>, MatOp_AddS_<Mat> >, Mat_<_Tp> >
1438 operator + (const Mat_<_Tp>& a, const Scalar& alpha)
1439 {
1440     typedef MatExpr_Op2_<Mat_<_Tp>, Scalar, Mat_<_Tp>,
1441         MatOp_AddS_<Mat> > MatExpr_Temp;
1442     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, alpha));
1443 }
1444
1445 // alpha + A
1446 template<typename _Tp> static inline
1447 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, double, double, Mat_<_Tp>, MatOp_ScaleAddS_<Mat> >, Mat_<_Tp> >
1448 operator + (double alpha, const Mat_<_Tp>& a)
1449 { return a + alpha; }
1450
1451 // alpha + A
1452 template<typename _Tp> static inline
1453 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, Scalar, Mat_<_Tp>, MatOp_AddS_<Mat> >, Mat_<_Tp> >
1454 operator + (const Scalar& alpha, const Mat_<_Tp>& a)
1455 { return a + alpha; }
1456
1457 // A - alpha
1458 template<typename _Tp> static inline
1459 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, double, double, Mat_<_Tp>, MatOp_ScaleAddS_<Mat> >, Mat_<_Tp> >
1460 operator - (const Mat_<_Tp>& a, double alpha)
1461 { return a + (-alpha); }
1462
1463 // A - alpha
1464 template<typename _Tp> static inline
1465 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, Scalar, Mat_<_Tp>, MatOp_AddS_<Mat> >, Mat_<_Tp> >
1466 operator - (const Mat_<_Tp>& a, const Scalar& alpha)
1467 { return a + (-alpha); }
1468
1469 // alpha - A
1470 template<typename _Tp> static inline
1471 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, double, double, Mat_<_Tp>, MatOp_ScaleAddS_<Mat> >, Mat_<_Tp> >
1472 operator - (double alpha, const Mat_<_Tp>& a)
1473 {
1474     typedef MatExpr_Op3_<Mat_<_Tp>, double, double, Mat_<_Tp>,
1475         MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
1476     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, -1, alpha));
1477 }
1478
1479 // E + alpha
1480 template<typename A, typename M> static inline
1481 MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1482 operator + (const MatExpr_<A, M>& a, double alpha)
1483 {
1484     typedef MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
1485     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, 1, alpha));
1486 }
1487
1488 // E + alpha
1489 template<typename A, typename M> static inline
1490 MatExpr_<MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> >, M>
1491 operator + (const MatExpr_<A, M>& a, const Scalar& alpha)
1492 {
1493     typedef MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> > MatExpr_Temp;
1494     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, alpha));
1495 }
1496
1497 // alpha + E
1498 template<typename A, typename M> static inline
1499 MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1500 operator + (double alpha, const MatExpr_<A, M>& a)
1501 { return a + alpha; }
1502
1503 // alpha + E
1504 template<typename A, typename M> static inline
1505 MatExpr_<MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> >, M>
1506 operator + (const Scalar& alpha, const MatExpr_<A, M>& a)
1507 { return a + alpha; }
1508
1509 // E - alpha
1510 template<typename A, typename M> static inline
1511 MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1512 operator - (const MatExpr_<A, M>& a, double alpha)
1513 { return a + (-alpha); }
1514
1515 // E - alpha
1516 template<typename A, typename M> static inline
1517 MatExpr_<MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> >, M>
1518 operator - (const MatExpr_<A, M>& a, const Scalar& alpha)
1519 { return a + (-alpha); }
1520
1521 // alpha - E
1522 template<typename A, typename M> static inline
1523 MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1524 operator - (double alpha, const MatExpr_<A, M>& a)
1525 {
1526     typedef MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
1527     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a, -1, alpha));
1528 }
1529
1530 // E*alpha + beta
1531 template<typename A, typename M> static inline
1532 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1533 operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1534             double beta)
1535 {
1536     typedef MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
1537     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, beta));
1538 }
1539
1540 // beta + E*alpha
1541 template<typename A, typename M> static inline
1542 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1543 operator + (double beta,
1544             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1545 { return a + beta; }
1546
1547 // E*alpha - beta
1548 template<typename A, typename M> static inline
1549 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1550 operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1551             double beta)
1552 { return a + (-beta); }
1553
1554 // beta - E*alpha
1555 template<typename A, typename M> static inline
1556 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1557 operator - (double beta,
1558             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1559 { return (a.e.a1*(-a.e.a2)) + beta; }
1560
1561 // (E*alpha + gamma) + beta ~ E*alpha + (gamma + beta)
1562 template<typename A, typename M> static inline
1563 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1564 operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1565             double beta)
1566 { return a.e.a1*a.e.a2 + (a.e.a3 + beta); }
1567
1568 // beta + (E*alpha + gamma)
1569 template<typename A, typename M> static inline
1570 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1571 operator + (double beta, const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1572 { return a + beta; }
1573
1574 // (E*alpha + gamma) - beta
1575 template<typename A, typename M> static inline
1576 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1577 operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1578             double beta)
1579 { return a + (-beta); }
1580
1581 // beta - (E*alpha + gamma)
1582 template<typename A, typename M> static inline
1583 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1584 operator - (double beta, const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1585 { return a.e.a1*(-a.e.a2) + (beta - a.e.a3); }
1586
1587 // (E*alpha + gamma)*beta
1588 template<typename A, typename M> static inline
1589 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1590 operator * (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1591             double beta)
1592 { return a.e.a1*(a.e.a2*beta) + (a.e.a3*beta); }
1593
1594 // beta*(E*alpha + gamma)
1595 template<typename A, typename M> static inline
1596 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1597 operator * (double beta, const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1598 { return a*beta; }
1599
1600 // -(E*alpha + beta)
1601 template<typename A, typename M> static inline
1602 MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
1603 operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1604 { return a*(-1); }
1605
1606 // (A*u + B*v + w) + beta
1607 template<typename A, typename B, typename M> static inline
1608 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1609 operator + (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a,
1610             double beta )
1611 {
1612     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1613     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3, a.e.a4, a.e.a5 + beta));
1614 }
1615
1616 // beta + (A*u + B*v + w)
1617 template<typename A, typename B, typename M> static inline
1618 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1619 operator + (double beta,
1620             const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
1621 { return a + beta; }
1622
1623 // (A*u + B*v + w) - beta
1624 template<typename A, typename B, typename M> static inline
1625 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1626 operator - (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a,
1627             double beta)
1628 { return a + (-beta); }
1629
1630 // beta - (A*u + B*v + w)
1631 template<typename A, typename B, typename M> static inline
1632 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1633 operator - (double beta,
1634             const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
1635 {
1636     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1637     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, a.e.a3, -a.e.a4, -a.e.a5 + beta));
1638 }
1639
1640 // (A*u + B*v + w)*beta
1641 template<typename A, typename B, typename M> static inline
1642 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1643 operator * (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a,
1644             double beta )
1645 {
1646     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1647     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1,
1648         a.e.a2*beta, a.e.a3, a.e.a4*beta, a.e.a5*beta));
1649 }
1650
1651 // beta*(A*u + B*v + w)
1652 template<typename A, typename B, typename M> static inline
1653 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1654 operator * (double beta,
1655             const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
1656 { return a * beta; }
1657
1658 // -(A*u + B*v + w)
1659 template<typename A, typename B, typename M> static inline
1660 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1661 operator - (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
1662 { return a*(-1); }
1663
1664 // A*alpha + B
1665 template<typename A, typename M> static inline
1666 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1667 operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1668             const M& b )
1669 {
1670     typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1671     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, 1, 0));
1672 }
1673
1674 // B + A*alpha
1675 template<typename A, typename M> static inline
1676 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1677 operator + (const M& b,
1678             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1679 { return a + b; }
1680
1681 // (A*alpha + beta) + B
1682 template<typename A, typename M> static inline
1683 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1684 operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1685             const M& b )
1686 {
1687     typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1688     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, 1, a.e.a3));
1689 }
1690
1691 // B + (A*alpha + beta)
1692 template<typename A, typename M> static inline
1693 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1694 operator + (const M& b,
1695             const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1696 { return a + b; }
1697
1698
1699 // A*alpha + E
1700 template<typename A, typename B, typename M> static inline
1701 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1702 operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1703             const MatExpr_<B, M>& b )
1704 { return a + (M)b; }
1705
1706 // E + A*alpha
1707 template<typename A, typename B, typename M> static inline
1708 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1709 operator + (const MatExpr_<B, M>& b,
1710             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1711 { return a + (M)b; }
1712
1713 // (A*alpha + beta) + E
1714 template<typename A, typename B, typename M> static inline
1715 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1716 operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1717             const MatExpr_<B, M>& b )
1718 { return a + (M)b; }
1719
1720 // E + (A*alpha + beta)
1721 template<typename A, typename B, typename M> static inline
1722 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1723 operator + (const MatExpr_<B, M>& b,
1724             const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1725 { return a + b; }
1726
1727 // A*alpha + B*beta
1728 template<typename A, typename B, typename M> static inline
1729 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1730 operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1731             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
1732 {
1733     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1734     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, b.e.a2, 0));
1735 }
1736
1737 // (A*alpha + beta) + B*gamma
1738 template<typename A, typename B, typename M> static inline
1739 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1740 operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1741             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
1742 {
1743     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1744     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, b.e.a2, a.e.a3));
1745 }
1746
1747 // B*gamma + (A*alpha + beta)
1748 template<typename A, typename B, typename M> static inline
1749 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1750 operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b,
1751             const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a )
1752 { return a + b; }
1753
1754 // (A*alpha + beta) + (B*gamma + theta)
1755 template<typename A, typename B, typename M> static inline
1756 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1757 operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1758             const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
1759 {
1760     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1761     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, b.e.a2, a.e.a3 + b.e.a3));
1762 }
1763
1764 // A*alpha - B
1765 template<typename A, typename M> static inline
1766 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1767 operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1768             const M& b )
1769 {
1770     typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1771     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, -1, 0));
1772 }
1773
1774 // B - A*alpha
1775 template<typename A, typename M> static inline
1776 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1777 operator - (const M& b,
1778             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1779 {
1780     typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1781     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, b, 1, 0));
1782 }
1783
1784 // (A*alpha + beta) - B
1785 template<typename A, typename M> static inline
1786 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1787 operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1788             const M& b )
1789 {
1790     typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1791     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, -1, a.e.a3));
1792 }
1793
1794 // B - (A*alpha + beta)
1795 template<typename A, typename M> static inline
1796 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1797 operator - (const M& b,
1798             const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1799 {
1800     typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1801     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, -1, a.e.a3));
1802 }
1803
1804 // A*alpha - E
1805 template<typename A, typename B, typename M> static inline
1806 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1807 operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1808             const MatExpr_<B, M>& b )
1809 { return a - (M)b; }
1810
1811 // E - A*alpha
1812 template<typename A, typename B, typename M> static inline
1813 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1814 operator - (const MatExpr_<B, M>& b,
1815             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
1816 { return (M)b - a; }
1817
1818 // (A*alpha + beta) - E
1819 template<typename A, typename B, typename M> static inline
1820 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1821 operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1822             const MatExpr_<B, M>& b )
1823 { return a - (M)b; }
1824
1825 // E - (A*alpha + beta)
1826 template<typename A, typename B, typename M> static inline
1827 MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
1828 operator - (const MatExpr_<B, M>& b,
1829             const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
1830 { return (M)b - a; }
1831
1832 // A*alpha - B*beta
1833 template<typename A, typename B, typename M> static inline
1834 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1835 operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1836             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
1837 {
1838     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1839     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, -b.e.a2, 0));
1840 }
1841
1842 // (A*alpha + beta) - B*gamma
1843 template<typename A, typename B, typename M> static inline
1844 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1845 operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1846             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
1847 {
1848     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1849     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, -b.e.a2, a.e.a3));
1850 }
1851
1852 // B*gamma - (A*alpha + beta)
1853 template<typename A, typename B, typename M> static inline
1854 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1855 operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b,
1856             const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a )
1857 {
1858     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1859     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, b.e.a1, b.e.a2, -a.e.a3));
1860 }
1861
1862 // (A*alpha + beta) - (B*gamma + theta)
1863 template<typename A, typename B, typename M> static inline
1864 MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
1865 operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
1866             const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
1867 {
1868     typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
1869     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, -b.e.a2, a.e.a3 - b.e.a3));
1870 }
1871
1872 /////////////////////////////// Mat Multiplication ///////////////////////////////////
1873
1874 // A^t
1875 inline MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat>
1876 Mat::t() const
1877 {
1878     typedef MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> > MatExpr_Temp;
1879     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, 1));
1880 }
1881
1882 template<typename _Tp> inline
1883 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_T_<Mat> >, Mat_<_Tp> >
1884 Mat_<_Tp>::t() const
1885 {
1886     typedef MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_T_<Mat> > MatExpr_Temp;
1887     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(*this, 1));
1888 }
1889
1890 // A*B
1891 static inline
1892 MatExpr_<MatExpr_Op4_<Mat, Mat, double, int, Mat, MatOp_MatMul_<Mat> >, Mat>
1893 operator * ( const Mat& a, const Mat& b )
1894 {
1895     typedef MatExpr_Op4_<Mat, Mat, double, int, Mat, MatOp_MatMul_<Mat> > MatExpr_Temp;
1896     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 1, 0));
1897 }
1898
1899 template<typename _Tp> static inline
1900 MatExpr_<MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, int, Mat_<_Tp>,
1901 MatOp_MatMul_<Mat> >, Mat_<_Tp> >
1902 operator * ( const Mat_<_Tp>& a, const Mat_<_Tp>& b )
1903 {
1904     typedef MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, int, Mat_<_Tp>,
1905         MatOp_MatMul_<Mat> > MatExpr_Temp;
1906     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, b, 1, 0));
1907 }
1908
1909 template<typename A, typename B, typename M> static inline
1910 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1911 operator * ( const MatExpr_<A, M>& a, const MatExpr_<B, M>& b )
1912 {
1913     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1914     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, (M)b, 1, 0));
1915 }
1916
1917 // (A*alpha)*B
1918 template<typename A, typename M> static inline
1919 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1920 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a, const M& b )
1921 {
1922     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1923     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2, 0));
1924 }
1925
1926 // A*(B*alpha)
1927 template<typename A, typename M> static inline
1928 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1929 operator * ( const M& b, const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a )
1930 {
1931     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1932     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(b, (M)a.e.a1, a.e.a2, 0));
1933 }
1934
1935 // A^t*B
1936 template<typename A, typename M> static inline
1937 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1938 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& a, const M& b )
1939 {
1940     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1941     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2, GEMM_1_T));
1942 }
1943
1944 // A*B^t
1945 template<typename A, typename M> static inline
1946 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1947 operator * ( const M& a, const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& b )
1948 {
1949     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1950     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a, (M)b.e.a1, b.e.a2, GEMM_2_T));
1951 }
1952
1953 // (A*alpha)*(B*beta)
1954 template<typename A, typename B, typename M> static inline
1955 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1956 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1957              const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
1958 {
1959     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1960     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1, a.e.a2*b.e.a2, 0));
1961 }
1962
1963 // A^t*(B*alpha)
1964 template<typename A, typename B, typename M> static inline
1965 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1966 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& a,
1967              const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
1968 {
1969     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1970     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1, a.e.a2*b.e.a2, GEMM_1_T));
1971 }
1972
1973 // (A*alpha)*B^t
1974 template<typename A, typename B, typename M> static inline
1975 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1976 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
1977              const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& b )
1978 {
1979     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1980     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1, a.e.a2*b.e.a2, GEMM_2_T));
1981 }
1982
1983 // A^t*B^t
1984 template<typename A, typename B, typename M> static inline
1985 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
1986 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& a,
1987              const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& b )
1988 {
1989     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
1990     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1,
1991         (M)b.e.a1, a.e.a2*b.e.a2, GEMM_1_T+GEMM_2_T));
1992 }
1993
1994 // (A*B)*alpha
1995 template<typename A, typename B, typename M> static inline
1996 MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>
1997 operator * ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
1998              double alpha )
1999 {
2000     typedef MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2001     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3*alpha, a.e.a4));
2002 }
2003
2004 // alpha*(A*B)
2005 template<typename A, typename B, typename M> static inline
2006 MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
2007 operator * ( double alpha,
2008              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2009 {
2010     return a*alpha;
2011 }
2012
2013 // -(A*B)
2014 template<typename A, typename B, typename M> static inline
2015 MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>
2016 operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2017 {
2018     return a*(-1);
2019 }
2020
2021 // (A*alpha + beta)*B
2022 template<typename A, typename M> static inline
2023 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2024 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& a, const M& b )
2025 {
2026     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2027     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2, b, a.e.a3, 0));
2028 }
2029
2030 // A*(B*alpha + beta)
2031 template<typename A, typename M> static inline
2032 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2033 operator * ( const M& a, const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
2034 {
2035     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2036     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a, (M)b.e.a1, b.e.a2, a, b.e.a3, 0));
2037 }
2038
2039 // (A*alpha + beta)*(B*gamma)
2040 template<typename A, typename B, typename M> static inline
2041 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2042 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
2043              const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
2044 {
2045     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2046     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
2047         a.e.a2*b.e.a2, (M)b.e.a1, a.e.a3*b.e.a2, 0));
2048 }
2049
2050 // (A*gamma)*(B*alpha + beta)
2051 template<typename A, typename B, typename M> static inline
2052 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2053 operator * ( const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& a,
2054              const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
2055 {
2056     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2057     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
2058         a.e.a2*b.e.a2, (M)a.e.a1, a.e.a2*b.e.a3, 0));
2059 }
2060
2061 // (A*alpha + beta)*B^t
2062 template<typename A, typename B, typename M> static inline
2063 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2064 operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
2065              const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& b )
2066 {
2067     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2068     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
2069         a.e.a2*b.e.a2, (M)b.e.a1, a.e.a3*b.e.a2, GEMM_2_T));
2070 }
2071
2072 // A^t*(B*alpha + beta)
2073 template<typename A, typename B, typename M> static inline
2074 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2075 operator * ( const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& a,
2076              const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
2077 {
2078     typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
2079     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
2080         a.e.a2*b.e.a2, (M)a.e.a1, a.e.a2*b.e.a3, GEMM_1_T));
2081 }
2082
2083 // (A*B + C)*alpha
2084 template<typename A, typename B, typename C, typename M> static inline
2085 MatExpr_<MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2086 operator * ( const MatExpr_<MatExpr_Op6_<A, B, double, C,
2087              double, int, M, MatOp_MatMulAdd_<Mat> >, M>& a, double alpha )
2088 {
2089     typedef MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2090     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2,
2091         a.e.a3*alpha, a.e.a4, a.e.a5*alpha, a.e.a6));
2092 }
2093
2094 // alpha*(A*B + C)
2095 template<typename A, typename B, typename C, typename M> static inline
2096 MatExpr_<MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2097 operator * ( double alpha, const MatExpr_<MatExpr_Op6_<A, B, double, C,
2098              double, int, M, MatOp_MatMulAdd_<Mat> >, M>& a )
2099 { return a*alpha; }
2100
2101 // -(A*B + C)
2102 template<typename A, typename B, typename C, typename M> static inline
2103 MatExpr_<MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2104 operator - ( const MatExpr_<MatExpr_Op6_<A, B, double, C,
2105              double, int, M, MatOp_MatMulAdd_<Mat> >, M>& a )
2106 { return a*(-1); }
2107
2108
2109 // (A*B) + C
2110 template<typename A, typename B, typename M> static inline
2111 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2112 operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2113              const M& b )
2114 {
2115     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2116     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2117         (M)a.e.a1, (M)a.e.a2, a.e.a3, b, 1, a.e.a4));
2118 }
2119
2120 // C + (A*B)
2121 template<typename A, typename B, typename M> static inline
2122 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2123 operator + ( const M& b,
2124              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2125 { return a + b; }
2126
2127
2128 // (A*B) - C
2129 template<typename A, typename B, typename M> static inline
2130 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2131 operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2132              const M& b )
2133 {
2134     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2135     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2136         (M)a.e.a1, (M)a.e.a2, a.e.a3, b, -1, a.e.a4));
2137 }
2138
2139 // C - (A*B)
2140 template<typename A, typename B, typename M> static inline
2141 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2142 operator - ( const M& b,
2143              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2144 {
2145     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2146     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2147         (M)a.e.a1, (M)a.e.a2, -a.e.a3, b, 1, a.e.a4));
2148 }
2149
2150
2151 // (A*B) + C
2152 template<typename A, typename B, typename C, typename M> static inline
2153 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2154 operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2155              const MatExpr_<C, M>& b )
2156 {
2157     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2158     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2159         (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b, 1, a.e.a4));
2160 }
2161
2162 // C + (A*B)
2163 template<typename A, typename B, typename C, typename M> static inline
2164 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2165 operator + ( const MatExpr_<C, M>& b,
2166              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2167 { return a + b; }
2168
2169
2170 // (A*B) - C
2171 template<typename A, typename B, typename C, typename M> static inline
2172 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2173 operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2174              const MatExpr_<C, M>& b )
2175 {
2176     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2177     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2178         (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b, -1, a.e.a4));
2179 }
2180
2181 // C - (A*B)
2182 template<typename A, typename B, typename C, typename M> static inline
2183 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2184 operator - ( const MatExpr_<C, M>& b,
2185              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2186 {
2187     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2188     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2189         (M)a.e.a1, (M)a.e.a2, -a.e.a3, (M)b, 1, a.e.a4));
2190 }
2191
2192
2193 // (A*B) + C*alpha
2194 template<typename A, typename B, typename C, typename M> static inline
2195 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2196 operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2197              const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b )
2198 {
2199     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2200     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2201         (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4));
2202 }
2203
2204 // C*alpha + (A*B)
2205 template<typename A, typename B, typename C, typename M> static inline
2206 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2207 operator + ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b,
2208              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2209 { return a + b; }
2210
2211
2212 // (A*B) - (C*alpha)
2213 template<typename A, typename B, typename C, typename M> static inline
2214 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2215 operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2216              const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b )
2217 {
2218     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2219     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2220         (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, -b.e.a2, a.e.a4));
2221 }
2222
2223 // (C*alpha) - (A*B)
2224 template<typename A, typename B, typename C, typename M> static inline
2225 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2226 operator - ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b,
2227              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2228 {
2229     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2230     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2231         (M)a.e.a1, (M)a.e.a2, -a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4));
2232 }
2233
2234
2235 // (A*B) + C^t
2236 template<typename A, typename B, typename C, typename M> static inline
2237 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2238 operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2239              const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b )
2240 {
2241     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2242     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2243         (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4 + GEMM_3_T));
2244 }
2245
2246 // C^t + (A*B)
2247 template<typename A, typename B, typename C, typename M> static inline
2248 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2249 operator + ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b,
2250              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2251 { return a + b; }
2252
2253
2254 // (A*B) - C^t
2255 template<typename A, typename B, typename C, typename M> static inline
2256 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2257 operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
2258              const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b )
2259 {
2260     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2261     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2262         (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, -b.e.a2, a.e.a4+GEMM_3_T));
2263 }
2264
2265 // C^t - (A*B)
2266 template<typename A, typename B, typename C, typename M> static inline
2267 MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
2268 operator - ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b,
2269              const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
2270 {
2271     typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
2272     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
2273         (M)a.e.a1, (M)a.e.a2, -a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4+GEMM_3_T));
2274 }
2275
2276
2277 ////////////////////////////// Augmenting algebraic operations //////////////////////////////////
2278
2279 static inline Mat& operator += (const Mat& a, const Mat& b)
2280 {
2281     add(a, b, (Mat&)a);
2282     return (Mat&)a;
2283 }
2284
2285 static inline Mat& operator -= (const Mat& a, const Mat& b)
2286 {
2287     subtract(a, b, (Mat&)a);
2288     return (Mat&)a;
2289 }
2290
2291 static inline Mat& operator *= (const Mat& a, const Mat& b)
2292 {
2293     gemm(a, b, 1, Mat(), 0, (Mat&)a, 0);
2294     return (Mat&)a;
2295 }
2296
2297 static inline Mat& operator *= (const Mat& a, double alpha)
2298 {
2299     a.convertTo((Mat&)a, -1, alpha);
2300     return (Mat&)a;
2301 }
2302
2303 static inline Mat& operator += (const Mat& a, const Scalar& s)
2304 {
2305     add(a, s, (Mat&)a);
2306     return (Mat&)a;
2307 }
2308
2309 static inline Mat& operator -= (const Mat& a, const Scalar& s)
2310 { return (a += -s); }
2311
2312 template<typename _Tp> static inline
2313 Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2314 {
2315     (Mat&)a += (const Mat&)b;
2316     return (Mat_<_Tp>&)a;
2317 }
2318
2319 template<typename _Tp> static inline
2320 Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2321 {
2322     (Mat&)a -= (const Mat&)b;
2323     return (Mat_<_Tp>&)a;
2324 }
2325
2326 template<typename _Tp> static inline
2327 Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2328 {
2329     (Mat&)a *= (const Mat&)b;
2330     return (Mat_<_Tp>&)a;
2331 }
2332
2333 template<typename _Tp> static inline
2334 Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Scalar& s)
2335 {
2336     (Mat&)a += s;
2337     return (Mat_<_Tp>&)a;
2338 }
2339
2340 template<typename _Tp> static inline
2341 Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Scalar& s)
2342 {
2343     (Mat&)a -= s;
2344     return (Mat_<_Tp>&)a;
2345 }
2346
2347 template<typename A, typename M> static inline
2348 M& operator += (const M& a, const MatExpr_<A, M>& b)
2349 { return (a += (M)b); }
2350
2351 template<typename A, typename M> static inline
2352 M& operator -= (const M& a, const MatExpr_<A, M>& b)
2353 { return (a -= (M)b); }
2354
2355 template<typename A, typename M> static inline
2356 M& operator *= (const M& a, const MatExpr_<A, M>& b)
2357 { return (a *= (M)b); }
2358
2359 template<typename A, typename M> static inline
2360 M& operator += (const M& a,
2361                 const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
2362 {
2363     M& _a = (M&)a;
2364     scaleAdd( b.e.a1, Scalar(b.e.a2), _a, _a );
2365     return _a;
2366 }
2367
2368 template<typename A, typename M> static inline
2369 M& operator -= (const M& a,
2370                 const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
2371 {
2372     M& _a = (M&)a;
2373     scaleAdd( b.e.a1, -Scalar(b.e.a2), _a, _a );
2374     return _a;
2375 }
2376
2377 template<typename A, typename M> static inline
2378 M& operator += (const M& a,
2379                 const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b)
2380 {
2381     M& _a = (M&)a;
2382     MatOp_AddEx_<Mat>::apply( a, 1, (M)b.e.a1, b.e.a2, b.e.a3, _a );
2383     return _a;
2384 }
2385
2386 template<typename A, typename M> static inline
2387 M& operator -= (const M& a,
2388                 const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b)
2389 {
2390     M& _a = (M&)a;
2391     MatOp_AddEx_<Mat>::apply( a, 1, (M)b.e.a1, -b.e.a2, -b.e.a3, _a );
2392     return _a;
2393 }
2394
2395 template<typename A, typename B, typename M> static inline
2396 M& operator += (const M& a,
2397                 const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& b)
2398 {
2399     M& _a = (M&)a;
2400     MatOp_MatMulAdd_<Mat>::apply( (M)b.e.a1, (M)b.e.a2, b.e.a3, a, 1, b.e.a4, _a );
2401     return _a;
2402 }
2403
2404 template<typename A, typename B, typename M> static inline
2405 M& operator -= (const M& a,
2406                 const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& b)
2407 {
2408     M& _a = (M&)a;
2409     MatOp_MatMulAdd_<Mat>::apply( (M)b.e.a1, (M)b.e.a2, -b.e.a3, a, 1, b.e.a4, _a );
2410     return _a;
2411 }
2412
2413 template<typename A, typename M> static inline
2414 M& operator *= (const M& a,
2415                 const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
2416 {
2417     M& _a = (M&)a;
2418     MatOp_MatMul_<Mat>::apply( a, (M)b.e.a1, b.e.a2, 0, _a );
2419     return _a;
2420 }
2421
2422 template<typename A, typename M> static inline
2423 M& operator *= (const M& a,
2424                 const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b)
2425 {
2426     M& _a = (M&)a;
2427     MatOp_MatMulAdd_<Mat>::apply( a, (M)b.e.a1, b.e.a2, a, b.e.a3, 0, _a );
2428     return _a;
2429 }
2430
2431 template<typename A, typename M> static inline
2432 M& operator *= (const M& a,
2433                 const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& b)
2434 {
2435     M& _a = (M&)a;
2436     MatOp_MatMul_<Mat>::apply( a, (M)b.e.a1, b.e.a2, GEMM_2_T, _a );
2437     return _a;
2438 }
2439
2440 ////////////////////////////// Logical operations ///////////////////////////////
2441
2442 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
2443 operator & (const Mat& a, const Mat& b)
2444 {
2445     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
2446     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, '&'));
2447 }
2448
2449 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
2450 operator | (const Mat& a, const Mat& b)
2451 {
2452     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
2453     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, '|'));
2454 }
2455
2456 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
2457 operator ^ (const Mat& a, const Mat& b)
2458 {
2459     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
2460     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, '^'));
2461 }
2462
2463 template<typename _Tp> static inline
2464 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2465             MatOp_Bin_<Mat> >, Mat_<_Tp> >
2466 operator & (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2467 {
2468     typedef MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2469         MatOp_Bin_<Mat> > MatExpr_Temp;
2470     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(
2471         a, b, '&'));
2472 }
2473
2474 template<typename _Tp> static inline
2475 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2476             MatOp_Bin_<Mat> >, Mat_<_Tp> >
2477 operator | (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2478 {
2479     typedef MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2480         MatOp_Bin_<Mat> > MatExpr_Temp;
2481     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(
2482         a, b, '|'));
2483 }
2484
2485 template<typename _Tp> static inline
2486 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2487             MatOp_Bin_<Mat> >, Mat_<_Tp> >
2488 operator ^ (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2489 {
2490     typedef MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2491         MatOp_Bin_<Mat> > MatExpr_Temp;
2492     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(
2493         a, b, '^'));
2494 }
2495
2496 template<typename A, typename B, typename M> static inline
2497 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2498 operator & (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
2499 { return (M)a & (M)b; }
2500
2501 template<typename A, typename M> static inline
2502 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2503 operator & (const MatExpr_<A, M>& a, const M& b)
2504 { return (M)a & b; }
2505
2506 template<typename A, typename M> static inline
2507 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2508 operator & (const M& a, const MatExpr_<A, M>& b)
2509 { return a & (M)b; }
2510
2511 template<typename A, typename B, typename M> static inline
2512 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2513 operator | (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
2514 { return (M)a | (M)b; }
2515
2516 template<typename A, typename M> static inline
2517 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2518 operator | (const MatExpr_<A, M>& a, const M& b)
2519 { return (M)a | b; }
2520
2521 template<typename A, typename M> static inline
2522 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2523 operator | (const M& a, const MatExpr_<A, M>& b)
2524 { return a | (M)b; }
2525
2526 template<typename A, typename B, typename M> static inline
2527 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2528 operator ^ (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
2529 { return (M)a ^ (M)b; }
2530
2531 template<typename A, typename M> static inline
2532 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2533 operator ^ (const MatExpr_<A, M>& a, const M& b)
2534 { return (M)a ^ b; }
2535
2536 template<typename A, typename M> static inline
2537 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2538 operator ^ (const M& a, const MatExpr_<A, M>& b)
2539 { return a ^ (M)b; }
2540
2541 static inline Mat& operator &= (const Mat& a, const Mat& b)
2542 {
2543     MatOp_Bin_<Mat>::apply( a, b, '&', (Mat&)a );
2544     return (Mat&)a;
2545 }
2546
2547 static inline Mat& operator |= (const Mat& a, const Mat& b)
2548 {
2549     MatOp_Bin_<Mat>::apply( a, b, '|', (Mat&)a );
2550     return (Mat&)a;
2551 }
2552
2553 static inline Mat& operator ^= (const Mat& a, const Mat& b)
2554 {
2555     MatOp_Bin_<Mat>::apply( a, b, '^', (Mat&)a );
2556     return (Mat&)a;
2557 }
2558
2559 template<typename _Tp> static inline Mat_<_Tp>&
2560 operator &= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2561 {
2562     (Mat&)a &= (const Mat&)b;
2563     return (Mat_<_Tp>&)a;
2564 }
2565
2566 template<typename _Tp> static inline Mat_<_Tp>&
2567 operator |= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2568 {
2569     (Mat&)a |= (const Mat&)b;
2570     return (Mat_<_Tp>&)a;
2571 }
2572
2573 template<typename _Tp> static inline Mat_<_Tp>&
2574 operator ^= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2575 {
2576     (Mat&)a ^= (const Mat&)b;
2577     return (Mat_<_Tp>&)a;
2578 }
2579
2580 template<typename A, typename M> static inline M&
2581 operator &= (const M& a, const MatExpr_<A, M>& b)
2582 { return (a &= (M)b); }
2583
2584 template<typename A, typename M> static inline M&
2585 operator |= (const M& a, const MatExpr_<A, M>& b)
2586 { return (a |= (M)b); }
2587
2588 template<typename A, typename M> static inline M&
2589 operator ^= (const M& a, const MatExpr_<A, M>& b)
2590 { return (a ^= (M)b); }
2591
2592 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2593 operator & (const Mat& a, const Scalar& s)
2594 {
2595     typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
2596     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, s, '&'));
2597 }
2598
2599 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2600 operator & (const Scalar& s, const Mat& a)
2601 { return a & s; }
2602
2603 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2604 operator | (const Mat& a, const Scalar& s)
2605 {
2606     typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
2607     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, s, '|'));
2608 }
2609
2610 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2611 operator | (const Scalar& s, const Mat& a)
2612 { return a | s; }
2613
2614 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2615 operator ^ (const Mat& a, const Scalar& s)
2616 {
2617     typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
2618     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, s, '^'));
2619 }
2620
2621 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2622 operator ^ (const Scalar& s, const Mat& a)
2623 { return a ^ s; }
2624
2625 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2626 operator ~ (const Mat& a)
2627 {
2628     typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
2629     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, Scalar(), '~'));
2630 }
2631
2632 template<typename _Tp> static inline
2633 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2634 operator & (const Mat_<_Tp>& a, const Scalar& s)
2635 {
2636     typedef MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> > MatExpr_Temp;
2637     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, s, '&'));
2638 }
2639
2640 template<typename _Tp> static inline
2641 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2642 operator & (const Scalar& s, const Mat_<_Tp>& a)
2643 { return a & s; }
2644
2645 template<typename _Tp> static inline
2646 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2647 operator | (const Mat_<_Tp>& a, const Scalar& s)
2648 {
2649     typedef MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> > MatExpr_Temp;
2650     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, s, '|'));
2651 }
2652
2653 template<typename _Tp> static inline
2654 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2655 operator | (const Scalar& s, const Mat_<_Tp>& a)
2656 { return a | s; }
2657
2658 template<typename _Tp> static inline
2659 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2660 operator ^ (const Mat_<_Tp>& a, const Scalar& s)
2661 {
2662     typedef MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> > MatExpr_Temp;
2663     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, s, '^'));
2664 }
2665
2666 template<typename _Tp> static inline
2667 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2668 operator ^ (const Scalar& s, const Mat_<_Tp>& a)
2669 { return a ^ s; }
2670
2671 template<typename _Tp> static inline
2672 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> >, Mat_<_Tp> >
2673 operator ~ (const Mat_<_Tp>& a)
2674 {
2675     typedef MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>, MatOp_BinS_<Mat> > MatExpr_Temp;
2676     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, Scalar(), '~'));
2677 }
2678
2679 template<typename A, typename M> static inline
2680 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2681 operator & (const MatExpr_<A, M>& a, const Scalar& s)
2682 { return (M)a & s; }
2683
2684 template<typename A, typename M> static inline
2685 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2686 operator & (const Scalar& s, const MatExpr_<A, M>& a)
2687 { return (M)a & s; }
2688
2689 template<typename A, typename M> static inline
2690 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2691 operator | (const MatExpr_<A, M>& a, const Scalar& s)
2692 { return (M)a | s; }
2693
2694 template<typename A, typename M> static inline
2695 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2696 operator | (const Scalar& s, const MatExpr_<A, M>& a)
2697 { return (M)a | s; }
2698
2699 template<typename A, typename M> static inline
2700 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2701 operator ^ (const MatExpr_<A, M>& a, const Scalar& s)
2702 { return (M)a ^ s; }
2703
2704 template<typename A, typename M> static inline
2705 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2706 operator ^ (const Scalar& s, const MatExpr_<A, M>& a)
2707 { return (M)a ^ s; }
2708
2709 template<typename A, typename M> static inline
2710 MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
2711 operator ~ (const MatExpr_<A, M>& a)
2712 { return ~(M)a; }
2713
2714 static inline Mat& operator &= (const Mat& a, const Scalar& s)
2715 {
2716     MatOp_BinS_<Mat>::apply( a, s, '&', (Mat&)a );
2717     return (Mat&)a;
2718 }
2719
2720 static inline Mat& operator |= (const Mat& a, const Scalar& s)
2721 {
2722     MatOp_BinS_<Mat>::apply( a, s, '|', (Mat&)a );
2723     return (Mat&)a;
2724 }
2725
2726 static inline Mat& operator ^= (const Mat& a, const Scalar& s)
2727 {
2728     MatOp_BinS_<Mat>::apply( a, s, '^', (Mat&)a );
2729     return (Mat&)a;
2730 }
2731
2732 template<typename _Tp> static inline Mat_<_Tp>&
2733 operator &= (const Mat_<_Tp>& a, const Scalar& s)
2734 {
2735     (Mat&)a &= s;
2736     return (Mat_<_Tp>&)a;
2737 }
2738
2739 template<typename _Tp> static inline Mat_<_Tp>&
2740 operator |= (const Mat_<_Tp>& a, const Scalar& s)
2741 {
2742     (Mat&)a |= s;
2743     return (Mat_<_Tp>&)a;
2744 }
2745
2746 template<typename _Tp> static inline Mat_<_Tp>&
2747 operator ^= (const Mat_<_Tp>& a, const Scalar& s)
2748 {
2749     (Mat&)a ^= s;
2750     return (Mat_<_Tp>&)a;
2751 }
2752
2753 ////////////////////////////// Comparison operations ///////////////////////////////
2754
2755 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
2756 operator == (const Mat& a, const Mat& b)
2757 {
2758     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
2759     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_EQ));
2760 }
2761
2762 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
2763 operator >= (const Mat& a, const Mat& b)
2764 {
2765     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
2766     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_GE));
2767 }
2768
2769 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
2770 operator > (const Mat& a, const Mat& b)
2771 {
2772     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
2773     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_GT));
2774 }
2775
2776 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
2777 operator <= (const Mat& a, const Mat& b)
2778 { return b >= a; }
2779
2780 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
2781 operator < (const Mat& a, const Mat& b)
2782 { return b > a; }
2783
2784 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
2785 operator != (const Mat& a, const Mat& b)
2786 {
2787     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
2788     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_NE));
2789 }
2790
2791 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2792 operator == (const Mat& a, double alpha)
2793 {
2794     typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
2795     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_EQ));
2796 }
2797
2798 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2799 operator >= (const Mat& a, double alpha)
2800 {
2801     typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
2802     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_GE));
2803 }
2804
2805 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2806 operator > (const Mat& a, double alpha)
2807 {
2808     typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
2809     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_GT));
2810 }
2811
2812 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2813 operator <= (const Mat& a, double alpha)
2814 {
2815     typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
2816     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_LE));
2817 }
2818
2819 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2820 operator < (const Mat& a, double alpha)
2821 {
2822     typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
2823     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_LT));
2824 }
2825
2826 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2827 operator != (const Mat& a, double alpha)
2828 {
2829     typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
2830     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_NE));
2831 }
2832
2833 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2834 operator == (double alpha, const Mat& a)
2835 { return a == alpha; }
2836
2837 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2838 operator >= (double alpha, const Mat& a)
2839 { return a <= alpha; }
2840
2841 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2842 operator > (double alpha, const Mat& a)
2843 { return a < alpha; }
2844
2845 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2846 operator <= (double alpha, const Mat& a)
2847 { return a >= alpha; }
2848
2849 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2850 operator < (double alpha, const Mat& a)
2851 { return a > alpha; }
2852
2853 static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
2854 operator != (double alpha, const Mat& a)
2855 { return a != alpha; }
2856
2857 /////////////////////////////// Miscellaneous operations //////////////////////////////
2858
2859 // max(A, B)
2860 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
2861 max(const Mat& a, const Mat& b)
2862 {
2863     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
2864     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 'M'));
2865 }
2866
2867 // min(A, B)
2868 static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
2869 min(const Mat& a, const Mat& b)
2870 {
2871     typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
2872     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 'm'));
2873 }
2874
2875 // abs(A)
2876 static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
2877 abs(const Mat& a)
2878 {
2879     typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
2880     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, Scalar(0), 'a'));
2881 }
2882
2883 // max(A, B)
2884 template<typename _Tp> static inline
2885 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2886             MatOp_Bin_<Mat> >, Mat_<_Tp> >
2887 max(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2888 {
2889     typedef MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2890         MatOp_Bin_<Mat> > MatExpr_Temp;
2891     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(
2892         a, b, 'M'));
2893 }
2894
2895 // min(A, B)
2896 template<typename _Tp> static inline
2897 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2898             MatOp_Bin_<Mat> >, Mat_<_Tp> >
2899 min(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2900 {
2901     typedef MatExpr_Op3_<Mat_<_Tp>, Mat_<_Tp>, int, Mat_<_Tp>,
2902         MatOp_Bin_<Mat> > MatExpr_Temp;
2903     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(
2904         a, b, 'm'));
2905 }
2906
2907 // abs(A)
2908 template<typename _Tp> static inline
2909 MatExpr_<MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>,
2910             MatOp_BinS_<Mat> >, Mat_<_Tp> >
2911 abs(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
2912 {
2913     typedef MatExpr_Op3_<Mat_<_Tp>, Scalar, int, Mat_<_Tp>,
2914         MatOp_Bin_<Mat> > MatExpr_Temp;
2915     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(
2916         a, Scalar(0), 'a'));
2917 }
2918
2919 // max(A, B)
2920 template<typename A, typename B, typename M> static inline
2921 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2922 max(const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
2923 { return max((M)a, (M)b); }
2924
2925 template<typename A, typename M> static inline
2926 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2927 max(const MatExpr_<A, M>& a, const M& b)
2928 { return max((M)a, b); }
2929
2930 template<typename A, typename M> static inline
2931 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2932 max(const M& a, const MatExpr_<A, M>& b)
2933 { return max(a, (M)b); }
2934
2935 // min(A, B)
2936 template<typename A, typename B, typename M> static inline
2937 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2938 min(const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
2939 { return min((M)a, (M)b); }
2940
2941 template<typename A, typename M> static inline
2942 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2943 min(const MatExpr_<A, M>& a, const M& b)
2944 { return min((M)a, b); }
2945
2946 template<typename A, typename M> static inline
2947 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2948 min(const M& a, const MatExpr_<A, M>& b)
2949 { return min(a, (M)b); }
2950
2951 // abs(A)
2952 template<typename A, typename B, typename M> static inline
2953 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
2954 abs(const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a)
2955 {
2956     typedef MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> > MatExpr_Temp;
2957     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)a.e.a2, 'a'));
2958 }
2959
2960 template<typename _Tp> void merge(const Mat_<_Tp>* mvbegin, size_t count, Mat& dst)
2961 { merge( (const Mat*)mvbegin, count, dst ); }
2962
2963 static inline void split(const Mat& m, vector<Mat>& mv)
2964 {
2965     mv.resize(m.channels());
2966     if(m.channels() > 0)
2967         split(m, &mv[0]);
2968 }
2969     
2970 template<typename _Tp> void split(const Mat& src, vector<Mat_<_Tp> >& mv)
2971 { split(src, (vector<Mat>&)mv ); }
2972     
2973 static inline void merge(const vector<Mat>& mv, Mat& dst)
2974 { merge(&mv[0], mv.size(), dst); }
2975
2976 static inline void mixChannels(const vector<Mat>& src, vector<Mat>& dst,
2977                                const int* fromTo, int npairs)
2978 {
2979     mixChannels(&src[0], (int)src.size(), &dst[0], (int)dst.size(), fromTo, npairs);
2980 }
2981     
2982 ///// Element-wise multiplication
2983
2984 inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
2985 Mat::mul(const Mat& m, double scale) const
2986 {
2987     typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
2988     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, m, scale, '*'));
2989 }
2990
2991 inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
2992 Mat::mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>& m, double scale) const
2993 {
2994     typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
2995     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, m.e.a1, m.e.a2*scale, '*'));
2996 }
2997
2998 inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
2999 Mat::mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat>& m, double scale) const
3000 {
3001     typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3002     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, m.e.a1, scale/m.e.a2, '/'));
3003 }
3004
3005 template<typename _Tp> inline
3006 MatExpr_<MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, char, Mat_<_Tp>, MatOp_MulDiv_<Mat> >, Mat_<_Tp> >
3007 Mat_<_Tp>::mul(const Mat_<_Tp>& m, double scale) const
3008 {
3009     typedef MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, char, Mat_<_Tp>, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3010     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(*this, m, scale, '*'));
3011 }
3012
3013 template<typename _Tp> inline
3014 MatExpr_<MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, char, Mat_<_Tp>, MatOp_MulDiv_<Mat> >, Mat_<_Tp> >
3015 Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_Scale_<Mat> >, Mat_<_Tp> >& m, double scale) const
3016 {
3017     typedef MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, char, Mat_<_Tp>, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3018     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(*this, m.e.a1, m.e.a2*scale, '*'));
3019 }
3020
3021 template<typename _Tp> inline
3022 MatExpr_<MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, char, Mat_<_Tp>, MatOp_MulDiv_<Mat> >, Mat_<_Tp> >
3023 Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_DivRS_<Mat> >, Mat_<_Tp> >& m, double scale) const
3024 {
3025     typedef MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double, char, Mat_<_Tp>, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3026     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(*this, m.e.a1, scale/m.e.a2, '/'));
3027 }
3028
3029 template<typename A, typename B, typename M> static inline
3030 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3031 operator * (const MatExpr_<MatExpr_Op4_<A, B, double, char, M, MatOp_MulDiv_<Mat> >, M>& a,
3032             double alpha)
3033 {
3034     typedef MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3035     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)a.e.a2, a.e.a3*alpha, a.e.a4));
3036 }
3037
3038 template<typename A, typename B, typename M> static inline
3039 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3040 operator * (double alpha,
3041             const MatExpr_<MatExpr_Op4_<A, B, double, char, M, MatOp_MulDiv_<Mat> >, M>& a)
3042 { return a*alpha; }
3043
3044
3045 ////// Element-wise division
3046
3047 static inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
3048 operator / (const Mat& a, const Mat& b)
3049 {
3050     typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3051     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 1, '/'));
3052 }
3053
3054 template<typename _Tp> static inline
3055 MatExpr_<MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double,
3056 char, Mat_<_Tp>, MatOp_MulDiv_<Mat> >, Mat_<_Tp> >
3057 operator / (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
3058 {
3059     typedef MatExpr_Op4_<Mat_<_Tp>, Mat_<_Tp>, double,
3060         char, Mat_<_Tp>, MatOp_MulDiv_<Mat> > MatExpr_Temp;
3061     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, b, 1, '/'));
3062 }
3063
3064 template<typename A, typename B, typename M> static inline
3065 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3066 operator / (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
3067 { return (M)a/(M)b; }
3068
3069 template<typename A, typename M> static inline
3070 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3071 operator / (const MatExpr_<A, M>& a, const M& b)
3072 { return (M)a/b; }
3073
3074 template<typename A, typename M> static inline
3075 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3076 operator / (const M& a, const MatExpr_<A, M>& b)
3077 { return a/(M)b; }
3078
3079 template<typename A, typename M> static inline
3080 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3081 operator / (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
3082             const M& b)
3083 { return ((M)a.e.a1/b)*a.e.a2; }
3084
3085 template<typename A, typename M> static inline
3086 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3087 operator / (const M& a,
3088             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
3089 { return (a/(M)b.e.a1)*(1./b.e.a2); }
3090
3091 template<typename A, typename B, typename M> static inline
3092 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3093 operator / (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
3094             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b)
3095 { return ((M)a.e.a1/(M)b.e.a1)*(a.e.a2/b.e.a2); }
3096
3097 template<typename A, typename M> static inline
3098 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3099 operator / (const M& a,
3100             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_DivRS_<Mat> >, M>& b)
3101 { return a.mul((M)b.e.a1, 1./b.e.a2); }
3102
3103 template<typename A, typename B, typename M> static inline
3104 MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
3105 operator / (const MatExpr_<A, M>& a,
3106             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_DivRS_<Mat> >, M>& b)
3107 { return ((M)a).mul((M)b.e.a1, 1./b.e.a2); }
3108
3109 static inline
3110 MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat >
3111 operator / (double alpha, const Mat& a)
3112 {
3113     typedef MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> > MatExpr_Temp;
3114     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha));
3115 }
3116
3117 static inline Mat& operator /= (const Mat& a, double alpha)
3118 {
3119     MatOp_Scale_<Mat>::apply( a, 1./alpha, (Mat&)a );
3120     return (Mat&)a;
3121 }
3122
3123 template<typename _Tp>
3124 static inline Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, double alpha)
3125 {
3126     MatOp_Scale_<Mat>::apply( a, 1./alpha, (Mat&)a );
3127     return (Mat_<_Tp>&)a;
3128 }
3129
3130 template<typename _Tp> static inline
3131 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>, MatOp_DivRS_<Mat> >, Mat_<_Tp> >
3132 operator / (double alpha, const Mat_<_Tp>& a)
3133 {
3134     typedef MatExpr_Op2_<Mat_<_Tp>, double, Mat_<_Tp>,
3135         MatOp_DivRS_<Mat> > MatExpr_Temp;
3136     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(a, alpha));
3137 }
3138
3139 template<typename A, typename M> static inline
3140 MatExpr_<MatExpr_Op2_<M, double, M, MatOp_DivRS_<Mat> >, M>
3141 operator / (double alpha, const MatExpr_<A, M>& a)
3142 { return alpha/(M)a; }
3143
3144 template<typename A, typename M> static inline
3145 MatExpr_<MatExpr_Op2_<M, double, M, MatOp_DivRS_<Mat> >, M>
3146 operator / (double alpha,
3147             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
3148 { return (alpha/a.e.a2)/(M)a.e.a1; }
3149
3150 template<typename A, typename M> static inline
3151 MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
3152 operator / (double alpha,
3153             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_DivRS_<Mat> >, M>& a)
3154 { return (M)a.e.a1*(alpha/a.e.a2); }
3155
3156 static inline Mat& operator /= (const Mat& a, const Mat& b)
3157 {
3158     MatOp_MulDiv_<Mat>::apply( a, b, 1, '/', (Mat&)a );
3159     return (Mat&)a;
3160 }
3161
3162 template<typename A, typename M>
3163 static inline M& operator /= (const M& a, const MatExpr_<MatExpr_Op2_<A, double,
3164                               M, MatOp_Scale_<Mat> >, M>& b)
3165 {
3166     MatOp_MulDiv_<Mat>::apply( a, (M)b.e.a1, 1./b.e.a2, '/', (M&)a );
3167     return (M&)a;
3168 }
3169
3170 template<typename A, typename M>
3171 static inline M& operator /= (const M& a, const MatExpr_<MatExpr_Op2_<A, double,
3172                               M, MatOp_DivRS_<Mat> >, M>& b)
3173 {
3174     MatOp_MulDiv_<Mat>::apply( a, (M)b.e.a1, 1./b.e.a2, '*', (M&)a );
3175     return (M&)a;
3176 }
3177
3178 // Mat Inversion and solving linear systems
3179
3180 inline MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat>
3181 Mat::inv(int method) const
3182 {
3183     typedef MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> > MatExpr_Temp;
3184     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, method));
3185 }
3186
3187 template<typename _Tp> inline
3188 MatExpr_<MatExpr_Op2_<Mat_<_Tp>, int, Mat_<_Tp>, MatOp_Inv_<Mat> >, Mat_<_Tp> >
3189 Mat_<_Tp>::inv(int method) const
3190 {
3191     typedef MatExpr_Op2_<Mat_<_Tp>, int, Mat_<_Tp>, MatOp_Inv_<Mat> > MatExpr_Temp;
3192     return MatExpr_<MatExpr_Temp, Mat_<_Tp> >(MatExpr_Temp(*this, method));
3193 }
3194
3195 template<typename A, typename M> static inline
3196 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Solve_<Mat> >, M>
3197 operator * (const MatExpr_<MatExpr_Op2_<A, int, M, MatOp_Inv_<Mat> >, M>& a,
3198             const M& b)
3199 {
3200     typedef MatExpr_Op3_<M, M, int, M, MatOp_Solve_<Mat> > MatExpr_Temp;
3201     return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2));
3202 }
3203
3204 template<typename A, typename B, typename M> static inline
3205 MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Solve_<Mat> >, M>
3206 operator * (const MatExpr_<MatExpr_Op2_<A, int, M, MatOp_Inv_<Mat> >, M>& a,
3207             const MatExpr_<B, M>& b)
3208 { return a*(M)b; }
3209
3210
3211 /////////////////////////////// Initialization ////////////////////////////////////////
3212
3213 inline MatExpr_Initializer Mat::zeros(int rows, int cols, int type)
3214 {
3215     typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
3216     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(Size(cols, rows), type, 0, 0));
3217 }
3218
3219 inline MatExpr_Initializer Mat::zeros(Size size, int type)
3220 {
3221     return zeros(size.height, size.width, type);
3222 }
3223
3224 inline MatExpr_Initializer Mat::ones(int rows, int cols, int type)
3225 {
3226     typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
3227     return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(Size(cols, rows), type, 1, 1));
3228 }
3229
3230 inline MatExpr_Initializer Mat::ones(Size size, int type)
3231 {
3232     return ones(size.height, size.width, type);
3233 }
3234
3235 inline MatExpr_Initializer Mat::eye(int rows, int cols, int type)
3236 {
3237     typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
3238     return MatExpr_Initializer(MatExpr_Temp(Size(cols, rows), type, 1, 2));
3239 }
3240
3241 inline MatExpr_Initializer Mat::eye(Size size, int type)
3242 {
3243     return eye(size.height, size.width, type);
3244 }
3245
3246 static inline MatExpr_Initializer operator * (const MatExpr_Initializer& a, double alpha)
3247 {
3248     typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
3249     return MatExpr_Initializer(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3*alpha, a.e.a4));
3250 }
3251
3252 static inline MatExpr_Initializer operator * (double alpha, MatExpr_Initializer& a)
3253 {
3254     typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
3255     return MatExpr_Initializer(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3*alpha, a.e.a4));
3256 }
3257
3258 template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::zeros(int rows, int cols)
3259 { return Mat::zeros(rows, cols, DataType<_Tp>::type); }
3260
3261 template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::zeros(Size size)
3262 { return Mat::zeros(size, DataType<_Tp>::type); }
3263
3264 template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::ones(int rows, int cols)
3265 { return Mat::ones(rows, cols, DataType<_Tp>::type); }
3266
3267 template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::ones(Size size)
3268 { return Mat::ones(size, DataType<_Tp>::type); }
3269
3270 template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::eye(int rows, int cols)
3271 { return Mat::eye(rows, cols, DataType<_Tp>::type); }
3272
3273 template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::eye(Size size)
3274 { return Mat::eye(size, DataType<_Tp>::type); }
3275
3276
3277 //////////// Iterators & Comma initializers //////////////////
3278
3279 template<typename _Tp> inline MatConstIterator_<_Tp>::MatConstIterator_()
3280     : m(0), ptr(0), sliceEnd(0) {}
3281
3282 template<typename _Tp> inline MatConstIterator_<_Tp>::MatConstIterator_(const Mat_<_Tp>* _m) : m(_m)
3283 {
3284     if( !_m )
3285         ptr = sliceEnd = 0;
3286     else
3287     {
3288         ptr = (_Tp*)_m->data;
3289         sliceEnd = ptr + (_m->isContinuous() ? _m->rows*_m->cols : _m->cols);
3290     }
3291 }
3292
3293 template<typename _Tp> inline MatConstIterator_<_Tp>::
3294     MatConstIterator_(const Mat_<_Tp>* _m, int _row, int _col) : m(_m)
3295 {
3296     if( !_m )
3297         ptr = sliceEnd = 0;
3298     else
3299     {
3300         CV_DbgAssert( (unsigned)_row < _m->rows && (unsigned)_col < _m->cols );
3301         ptr = (_Tp*)(_m->data + _m->step*_row);
3302         sliceEnd = _m->isContinuous() ? (_Tp*)_m->data + _m->rows*_m->cols : ptr + _m->cols;
3303         ptr += _col;
3304     }
3305 }
3306
3307 template<typename _Tp> inline MatConstIterator_<_Tp>::
3308     MatConstIterator_(const Mat_<_Tp>* _m, Point _pt) : m(_m)
3309 {
3310     if( !_m )
3311         ptr = sliceEnd = 0;
3312     else
3313     {
3314         CV_DbgAssert( (unsigned)_pt.y < (unsigned)_m->rows && (unsigned)_pt.x < (unsigned)_m->cols );
3315         ptr = (_Tp*)(_m->data + _m->step*_pt.y);
3316         sliceEnd = _m->isContinuous() ? (_Tp*)_m->data + _m->rows*_m->cols : ptr + _m->cols;
3317         ptr += _pt.x;
3318     }
3319 }
3320
3321 template<typename _Tp> inline MatConstIterator_<_Tp>::
3322     MatConstIterator_(const MatConstIterator_& it)
3323     : m(it.m), ptr(it.ptr), sliceEnd(it.sliceEnd) {}
3324
3325 template<typename _Tp> inline MatConstIterator_<_Tp>&
3326     MatConstIterator_<_Tp>::operator = (const MatConstIterator_& it )
3327 {
3328     m = it.m; ptr = it.ptr; sliceEnd = it.sliceEnd;
3329     return *this;
3330 }
3331
3332 template<typename _Tp> inline _Tp MatConstIterator_<_Tp>::operator *() const { return *ptr; }
3333
3334 template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator += (int ofs)
3335 {
3336     if( !m || ofs == 0 )
3337         return *this;
3338     ptr += ofs;
3339     if( m->isContinuous() )
3340     {
3341         if( ptr > sliceEnd )
3342             ptr = sliceEnd;
3343         else if( ptr < (_Tp*)m->data )
3344             ptr = (_Tp*)m->data;
3345     }
3346     else if( ptr >= sliceEnd || ptr < sliceEnd - m->cols )
3347     {
3348         ptr -= ofs;
3349         Point pt = pos();
3350         int cols = m->cols;
3351         ofs += pt.y*cols + pt.x;
3352         if( ofs > cols*m->rows )
3353             ofs = cols*m->rows;
3354         else if( ofs < 0 )
3355             ofs = 0;
3356         pt.y = ofs/cols;
3357         pt.x = ofs - pt.y*cols;
3358         ptr = (_Tp*)(m->data + m->step*pt.y);
3359         sliceEnd = ptr + cols;
3360         ptr += pt.x;
3361     }
3362     return *this;
3363 }
3364
3365 template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator -= (int ofs)
3366 { return (*this += -ofs); }
3367
3368 template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator --()
3369 { return (*this += -1); }
3370
3371 template<typename _Tp> inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator --(int)
3372 {
3373     MatConstIterator_ b = *this;
3374     *this += -1;
3375     return b;
3376 }
3377
3378 template<typename _Tp> inline MatConstIterator_<_Tp>& MatConstIterator_<_Tp>::operator ++()
3379 {
3380     if( m && ++ptr >= sliceEnd )
3381     {
3382         --ptr;
3383         *this += 1;
3384     }
3385     return *this;
3386 }
3387
3388 template<typename _Tp> inline MatConstIterator_<_Tp> MatConstIterator_<_Tp>::operator ++(int)
3389 {
3390     MatConstIterator_ b = *this;
3391     if( m && ++ptr >= sliceEnd )
3392     {
3393         --ptr;
3394         *this += 1;
3395     }
3396     return b;
3397 }
3398
3399 template<typename _Tp> inline Point MatConstIterator_<_Tp>::pos() const
3400 {
3401     if( !m )
3402         return Point();
3403     if( m->isContinuous() )
3404     {
3405         int ofs = ptr - (_Tp*)m->data, y = ofs / m->cols, x = ofs - y*m->cols;
3406         return Point(x,y);
3407     }
3408     else
3409     {
3410         int stepT = m->stepT(), y = (ptr - (_Tp*)m->data)/stepT, x = (ptr - (_Tp*)m->data) - y*stepT;
3411         return Point(x,y);
3412     }
3413 }
3414
3415 template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_() : MatConstIterator_<_Tp>() {}
3416
3417 template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m)
3418     : MatConstIterator_<_Tp>(_m) {}
3419
3420 template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(Mat_<_Tp>* _m, int _row, int _col)
3421     : MatConstIterator_<_Tp>(_m, _row, _col) {}
3422
3423 template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const Mat_<_Tp>* _m, Point _pt)
3424     : MatConstIterator_<_Tp>(_m, _pt) {}
3425
3426 template<typename _Tp> inline MatIterator_<_Tp>::MatIterator_(const MatIterator_& it)
3427     : MatConstIterator_<_Tp>(it) {}
3428
3429 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator = (const MatIterator_<_Tp>& it )
3430 {
3431     this->m = it.m; this->ptr = it.ptr; this->sliceEnd = it.sliceEnd;
3432     return *this;
3433 }
3434
3435 template<typename _Tp> inline _Tp& MatIterator_<_Tp>::operator *() const { return *(this->ptr); }
3436
3437 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator += (int ofs)
3438 {
3439     MatConstIterator_<_Tp>::operator += (ofs);
3440     return *this;
3441 }
3442
3443 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator -= (int ofs)
3444 {
3445     MatConstIterator_<_Tp>::operator += (-ofs);
3446     return *this;
3447 }
3448
3449 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator --()
3450 {
3451     MatConstIterator_<_Tp>::operator += (-1);
3452     return *this;
3453 }
3454
3455 template<typename _Tp> inline MatIterator_<_Tp> MatIterator_<_Tp>::operator --(int)
3456 {
3457     MatIterator_ b = *this;
3458     MatConstIterator_<_Tp>::operator += (-1);
3459     return b;
3460 }
3461
3462 template<typename _Tp> inline MatIterator_<_Tp>& MatIterator_<_Tp>::operator ++()
3463 {
3464     if( this->m && ++this->ptr >= this->sliceEnd )
3465     {
3466         --this->ptr;
3467         MatConstIterator_<_Tp>::operator += (1);
3468     }
3469     return *this;
3470 }
3471
3472 template<typename _Tp> inline MatIterator_<_Tp> MatIterator_<_Tp>::operator ++(int)
3473 {
3474     MatIterator_ b = *this;
3475     if( this->m && ++this->ptr >= this->sliceEnd )
3476     {
3477         --this->ptr;
3478         MatConstIterator_<_Tp>::operator += (1);
3479     }
3480     return b;
3481 }
3482
3483 template<typename _Tp> static inline bool
3484 operator == (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
3485 { return a.m == b.m && a.ptr == b.ptr; }
3486
3487 template<typename _Tp> static inline bool
3488 operator != (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
3489 { return !(a == b); }
3490
3491 template<typename _Tp> static inline bool
3492 operator < (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
3493 { return a.ptr < b.ptr; }
3494
3495 template<typename _Tp> static inline bool
3496 operator > (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
3497 { return a.ptr > b.ptr; }
3498
3499 template<typename _Tp> static inline bool
3500 operator <= (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
3501 { return a.ptr <= b.ptr; }
3502
3503 template<typename _Tp> static inline bool
3504 operator >= (const MatConstIterator_<_Tp>& a, const MatConstIterator_<_Tp>& b)
3505 { return a.ptr >= b.ptr; }
3506
3507 template<typename _Tp> static inline int
3508 operator - (const MatConstIterator_<_Tp>& b, const MatConstIterator_<_Tp>& a)
3509 {
3510     if( a.m != b.m )
3511         return INT_MAX;
3512     if( a.sliceEnd == b.sliceEnd )
3513         return b.ptr - a.ptr;
3514     {
3515         Point ap = a.pos(), bp = b.pos();
3516         if( bp.y > ap.y )
3517             return (bp.y - ap.y - 1)*a.m->cols + (a.m->cols - ap.x) + bp.x;
3518         if( bp.y < ap.y )
3519             return -((ap.y - bp.y - 1)*a.m->cols + (a.m->cols - bp.x) + ap.x);
3520         return bp.x - ap.x;
3521     }
3522 }
3523
3524 template<typename _Tp> static inline MatConstIterator_<_Tp>
3525 operator + (const MatConstIterator_<_Tp>& a, int ofs)
3526 { MatConstIterator_<_Tp> b = a; return b += ofs; }
3527
3528 template<typename _Tp> static inline MatConstIterator_<_Tp>
3529 operator + (int ofs, const MatConstIterator_<_Tp>& a)
3530 { MatConstIterator_<_Tp> b = a; return b += ofs; }
3531
3532 template<typename _Tp> static inline MatConstIterator_<_Tp>
3533 operator - (const MatConstIterator_<_Tp>& a, int ofs)
3534 { MatConstIterator_<_Tp> b = a; return b += -ofs; }
3535
3536 template<typename _Tp> inline _Tp MatConstIterator_<_Tp>::operator [](int i) const
3537 { return *(*this + i); }
3538
3539 template<typename _Tp> static inline MatIterator_<_Tp>
3540 operator + (const MatIterator_<_Tp>& a, int ofs)
3541 { MatIterator_<_Tp> b = a; return b += ofs; }
3542
3543 template<typename _Tp> static inline MatIterator_<_Tp>
3544 operator + (int ofs, const MatIterator_<_Tp>& a)
3545 { MatIterator_<_Tp> b = a; return b += ofs; }
3546
3547 template<typename _Tp> static inline MatIterator_<_Tp>
3548 operator - (const MatIterator_<_Tp>& a, int ofs)
3549 { MatIterator_<_Tp> b = a; return b += -ofs; }
3550
3551 template<typename _Tp> inline _Tp& MatIterator_<_Tp>::operator [](int i) const
3552 { return *(*this + i); }
3553
3554 template<typename _Tp> inline MatConstIterator_<_Tp> Mat_<_Tp>::begin() const
3555 { return Mat::begin<_Tp>(); }
3556
3557 template<typename _Tp> inline MatConstIterator_<_Tp> Mat_<_Tp>::end() const
3558 { return Mat::end<_Tp>(); }
3559
3560 template<typename _Tp> inline MatIterator_<_Tp> Mat_<_Tp>::begin()
3561 { return Mat::begin<_Tp>(); }
3562
3563 template<typename _Tp> inline MatIterator_<_Tp> Mat_<_Tp>::end()
3564 { return Mat::end<_Tp>(); }
3565
3566 template<typename _Tp> class CV_EXPORTS MatOp_Iter_
3567 {
3568 public:    
3569     MatOp_Iter_() {}
3570
3571     static void apply(const MatIterator_<_Tp>& a, Mat& c, int type=-1)
3572     {
3573         if( type < 0 )
3574             c = *a.m;
3575         else
3576             a.m->convertTo(c, type);
3577     }
3578 };
3579
3580 template<typename _Tp> inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) :
3581     MatExpr_<MatExpr_Op1_<MatIterator_<_Tp>, Mat_<_Tp>,
3582         MatOp_Iter_<_Tp> >, Mat_<_Tp> >(MatIterator_<_Tp>(_m)) {}
3583
3584 template<typename _Tp> template<typename T2> inline MatCommaInitializer_<_Tp>&
3585 MatCommaInitializer_<_Tp>::operator , (T2 v)
3586 {
3587     CV_DbgAssert( this->e.a1 < this->e.a1.m->end() );
3588     *this->e.a1 = _Tp(v); ++this->e.a1;
3589     return *this;
3590 }
3591
3592 template<typename _Tp> inline MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const
3593 {
3594     CV_DbgAssert( this->e.a1 == this->e.a1.m->end() );
3595     return *this->e.a1.m;
3596 }
3597
3598 template<typename _Tp> inline Mat_<_Tp> MatCommaInitializer_<_Tp>::operator *() const
3599 {
3600     CV_DbgAssert( this->e.a1 == this->e.a1.m->end() );
3601     return *this->e.a1.m;
3602 }
3603
3604 template<typename _Tp> inline void
3605 MatCommaInitializer_<_Tp>::assignTo(Mat& m, int type) const
3606 {
3607     Mat_<_Tp>(*this).assignTo(m, type);
3608 }
3609
3610 template<typename _Tp, typename T2> static inline MatCommaInitializer_<_Tp>
3611 operator << (const Mat_<_Tp>& m, T2 val)
3612 {
3613     MatCommaInitializer_<_Tp> commaInitializer((Mat_<_Tp>*)&m);
3614     return (commaInitializer, val);
3615 }
3616
3617 //////////////////////////////// MatND ////////////////////////////////
3618
3619 inline MatND::MatND()
3620  : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0)
3621 {
3622 }
3623
3624 inline MatND::MatND(int _dims, const int* _sizes, int _type)
3625  : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0)
3626 {
3627     create(_dims, _sizes, _type);
3628 }
3629
3630 inline MatND::MatND(int _dims, const int* _sizes, int _type, const Scalar& _s)
3631  : flags(MAGIC_VAL), dims(0), refcount(0), data(0), datastart(0), dataend(0)
3632 {
3633     create(_dims, _sizes, _type);
3634     *this = _s;
3635 }
3636
3637 inline MatND::MatND(const MatND& m)
3638  : flags(m.flags), dims(m.dims), refcount(m.refcount),
3639  data(m.data), datastart(m.datastart), dataend(m.dataend)
3640 {
3641     int i, d = dims;
3642     for( i = 0; i < d; i++ )
3643     {
3644         size[i] = m.size[i];
3645         step[i] = m.step[i];
3646     }
3647     if( refcount )
3648         CV_XADD(refcount, 1);
3649 }
3650
3651 inline MatND::MatND(const CvMatND* m, bool copyData)
3652   : flags(MAGIC_VAL|(m->type & (CV_MAT_TYPE_MASK|CV_MAT_CONT_FLAG))),
3653   dims(m->dims), refcount(0), data(m->data.ptr)
3654 {
3655     int i, d = dims;
3656     for( i = 0; i < d; i++ )
3657     {
3658         size[i] = m->dim[i].size;
3659         step[i] = m->dim[i].step;
3660     }
3661     datastart = data;
3662     dataend = datastart + size[0]*step[0];
3663     if( copyData )
3664     {
3665         MatND temp(*this);
3666         temp.copyTo(*this);
3667     }
3668 }
3669
3670 inline MatND::~MatND() { release(); }
3671
3672 inline MatND& MatND::operator = (const MatND& m)
3673 {
3674     if( this != &m )
3675     {
3676         if( m.refcount )
3677             CV_XADD(m.refcount, 1);
3678         release();
3679         flags = m.flags;
3680         dims = m.dims;
3681         data = m.data;
3682         datastart = m.datastart;
3683         dataend = m.dataend;
3684         refcount = m.refcount;
3685         int i, d = dims;
3686         for( i = 0; i < d; i++ )
3687         {
3688             size[i] = m.size[i];
3689             step[i] = m.step[i];
3690         }
3691     }
3692     return *this;
3693 }
3694
3695 inline MatND MatND::clone() const
3696 {
3697     MatND temp;
3698     this->copyTo(temp);
3699     return temp;
3700 }
3701
3702 inline MatND MatND::operator()(const Range* ranges) const
3703 {
3704     return MatND(*this, ranges);
3705 }
3706
3707 inline void MatND::assignTo( MatND& m, int type ) const
3708 {
3709     if( type < 0 )
3710         m = *this;
3711     else
3712         convertTo(m, type);
3713 }
3714
3715 inline void MatND::addref()
3716 {
3717     if( refcount ) CV_XADD(refcount, 1);
3718 }
3719
3720 inline void MatND::release()
3721 {
3722     if( refcount && CV_XADD(refcount, -1) == 1 )
3723         fastFree(datastart);
3724     dims = 0;
3725     data = datastart = dataend = 0;
3726     refcount = 0;
3727 }
3728
3729 inline bool MatND::isContinuous() const { return (flags & CONTINUOUS_FLAG) != 0; }
3730 inline size_t MatND::elemSize() const { return getElemSize(flags); }
3731 inline size_t MatND::elemSize1() const { return CV_ELEM_SIZE1(flags); }
3732 inline int MatND::type() const { return CV_MAT_TYPE(flags); }
3733 inline int MatND::depth() const { return CV_MAT_DEPTH(flags); }
3734 inline int MatND::channels() const { return CV_MAT_CN(flags); }
3735
3736 inline size_t MatND::step1(int i) const
3737 { CV_DbgAssert((unsigned)i < (unsigned)dims); return step[i]/elemSize1(); }
3738
3739 inline uchar* MatND::ptr(int i0)
3740 {
3741     CV_DbgAssert( dims == 1 && data &&
3742         (unsigned)i0 < (unsigned)size[0] );
3743     return data + i0*step[0];
3744 }
3745
3746 inline const uchar* MatND::ptr(int i0) const
3747 {
3748     CV_DbgAssert( dims == 1 && data &&
3749         (unsigned)i0 < (unsigned)size[0] );
3750     return data + i0*step[0];
3751 }
3752
3753 inline uchar* MatND::ptr(int i0, int i1)
3754 {
3755     CV_DbgAssert( dims == 2 && data &&
3756         (unsigned)i0 < (unsigned)size[0] &&
3757         (unsigned)i1 < (unsigned)size[1] );
3758     return data + i0*step[0] + i1*step[1];
3759 }
3760
3761 inline const uchar* MatND::ptr(int i0, int i1) const
3762 {
3763     CV_DbgAssert( dims == 2 && data &&
3764         (unsigned)i0 < (unsigned)size[0] &&
3765         (unsigned)i1 < (unsigned)size[1] );
3766     return data + i0*step[0] + i1*step[1];
3767 }
3768
3769 inline uchar* MatND::ptr(int i0, int i1, int i2)
3770 {
3771     CV_DbgAssert( dims == 3 && data &&
3772         (unsigned)i0 < (unsigned)size[0] &&
3773         (unsigned)i1 < (unsigned)size[1] &&
3774         (unsigned)i2 < (unsigned)size[2] );
3775     return data + i0*step[0] + i1*step[1] + i2*step[2];
3776 }
3777
3778 inline const uchar* MatND::ptr(int i0, int i1, int i2) const
3779 {
3780     CV_DbgAssert( dims == 3 && data &&
3781         (unsigned)i0 < (unsigned)size[0] &&
3782         (unsigned)i1 < (unsigned)size[1] &&
3783         (unsigned)i2 < (unsigned)size[2] );
3784     return data + i0*step[0] + i1*step[1] + i2*step[2];
3785 }
3786
3787 inline uchar* MatND::ptr(const int* idx)
3788 {
3789     int i, d = dims;
3790     uchar* p = data;
3791     CV_DbgAssert( data );
3792     for( i = 0; i < d; i++ )
3793     {
3794         CV_DbgAssert( (unsigned)idx[i] < (unsigned)size[i] );
3795         p += idx[i]*step[i];
3796     }
3797     return p;
3798 }
3799
3800 inline const uchar* MatND::ptr(const int* idx) const
3801 {
3802     int i, d = dims;
3803     uchar* p = data;
3804     CV_DbgAssert( data );
3805     for( i = 0; i < d; i++ )
3806     {
3807         CV_DbgAssert( (unsigned)idx[i] < (unsigned)size[i] );
3808         p += idx[i]*step[i];
3809     }
3810     return p;
3811 }
3812
3813 template<typename _Tp> inline _Tp& MatND::at(int i0)
3814 { return *(_Tp*)ptr(i0); }
3815 template<typename _Tp> inline const _Tp& MatND::at(int i0) const
3816 { return *(const _Tp*)ptr(i0); }
3817 template<typename _Tp> inline _Tp& MatND::at(int i0, int i1)
3818 { return *(_Tp*)ptr(i0, i1); }
3819 template<typename _Tp> inline const _Tp& MatND::at(int i0, int i1) const
3820 { return *(const _Tp*)ptr(i0, i1); }
3821 template<typename _Tp> inline _Tp& MatND::at(int i0, int i1, int i2)
3822 { return *(_Tp*)ptr(i0, i1, i2); }
3823 template<typename _Tp> inline const _Tp& MatND::at(int i0, int i1, int i2) const
3824 { return *(const _Tp*)ptr(i0, i1, i2); }
3825 template<typename _Tp> inline _Tp& MatND::at(const int* idx)
3826 { return *(_Tp*)ptr(idx); }
3827 template<typename _Tp> inline const _Tp& MatND::at(const int* idx) const
3828 { return *(const _Tp*)ptr(idx); }
3829
3830 inline NAryMatNDIterator::NAryMatNDIterator()
3831 {
3832 }
3833
3834 inline void subtract(const MatND& a, const Scalar& s, MatND& c, const MatND& mask=MatND())
3835 {
3836     add(a, -s, c, mask);
3837 }
3838
3839
3840 template<typename _Tp> inline MatND_<_Tp>::MatND_()
3841 {
3842     flags = MAGIC_VAL | DataType<_Tp>::type;
3843 }
3844
3845 template<typename _Tp> inline MatND_<_Tp>::MatND_(int _dims, const int* _sizes)
3846 : MatND(_dims, _sizes, DataType<_Tp>::type)
3847 {
3848 }
3849
3850 template<typename _Tp> inline MatND_<_Tp>::MatND_(int _dims, const int* _sizes, const _Tp& _s)
3851 : MatND(_dims, _sizes, DataType<_Tp>::type, Scalar(_s))
3852 {
3853 }
3854
3855 template<typename _Tp> inline MatND_<_Tp>::MatND_(const MatND& m)
3856 {
3857     if( m.type() == DataType<_Tp>::type )
3858         *this = (const MatND_<_Tp>&)m;
3859     else
3860         m.convertTo(this, DataType<_Tp>::type);
3861 }
3862
3863 template<typename _Tp> inline MatND_<_Tp>::MatND_(const MatND_<_Tp>& m) : MatND(m)
3864 {
3865 }
3866
3867 template<typename _Tp> inline MatND_<_Tp>::MatND_(const MatND_<_Tp>& m, const Range* ranges)
3868 : MatND(m, ranges)
3869 {
3870 }
3871
3872 template<typename _Tp> inline MatND_<_Tp>::MatND_(const CvMatND* m, bool copyData)
3873 {
3874     *this = MatND(m, copyData || CV_MAT_TYPE(m->type) != DataType<_Tp>::type);
3875 }
3876
3877 template<typename _Tp> inline MatND_<_Tp>& MatND_<_Tp>::operator = (const MatND& m)
3878 {
3879     if( DataType<_Tp>::type == m.type() )
3880     {
3881         Mat::operator = (m);
3882         return *this;
3883     }
3884     if( DataType<_Tp>::depth == m.depth() )
3885     {
3886         return (*this = m.reshape(DataType<_Tp>::channels));
3887     }
3888     CV_DbgAssert(DataType<_Tp>::channels == m.channels());
3889     m.convertTo(*this, DataType<_Tp>::type);
3890     return *this;
3891 }
3892
3893 template<typename _Tp> inline MatND_<_Tp>& MatND_<_Tp>::operator = (const MatND_<_Tp>& m)
3894 {
3895     return ((MatND&)*this = m);
3896 }
3897
3898 template<typename _Tp> inline MatND_<_Tp>& MatND_<_Tp>::operator = (const _Tp& s)
3899 {
3900     return (MatND&)*this = Scalar(s);
3901 }
3902
3903 template<typename _Tp> inline void MatND_<_Tp>::create(int _dims, const int* _sizes)
3904 {
3905     MatND::create(_dims, _sizes, DataType<_Tp>::type);
3906 }
3907
3908 template<typename _Tp> template<typename _Tp2> inline MatND_<_Tp>::operator MatND_<_Tp2>() const
3909 {
3910     return MatND_<_Tp2>((const MatND&)*this);
3911 }
3912
3913 template<typename _Tp> inline MatND_<_Tp> MatND_<_Tp>::clone() const
3914 {
3915     MatND_<_Tp> temp;
3916     this->copyTo(temp);
3917     return temp;
3918 }
3919
3920 template<typename _Tp> inline MatND_<_Tp>
3921 MatND_<_Tp>::operator()(const Range* ranges) const
3922 { return MatND_<_Tp>(*this, ranges); }
3923
3924 template<typename _Tp> inline size_t MatND_<_Tp>::elemSize() const
3925 { return CV_ELEM_SIZE(DataType<_Tp>::type); }
3926
3927 template<typename _Tp> inline size_t MatND_<_Tp>::elemSize1() const
3928 { return CV_ELEM_SIZE1(DataType<_Tp>::type); }
3929
3930 template<typename _Tp> inline int MatND_<_Tp>::type() const
3931 { return DataType<_Tp>::type; }
3932
3933 template<typename _Tp> inline int MatND_<_Tp>::depth() const
3934 { return DataType<_Tp>::depth; }
3935
3936 template<typename _Tp> inline int MatND_<_Tp>::channels() const
3937 { return DataType<_Tp>::channels; }
3938
3939 template<typename _Tp> inline size_t MatND_<_Tp>::stepT(int i) const
3940 {
3941     CV_DbgAssert( (unsigned)i < (unsigned)dims );
3942     return step[i]/elemSize();
3943 }
3944
3945 template<typename _Tp> inline size_t MatND_<_Tp>::step1(int i) const
3946 {
3947     CV_DbgAssert( (unsigned)i < (unsigned)dims );
3948     return step[i]/elemSize1();
3949 }
3950
3951 template<typename _Tp> inline _Tp& MatND_<_Tp>::operator ()(const int* idx)
3952 {
3953     uchar* ptr = data;
3954     int i, d = dims;
3955     for( i = 0; i < d; i++ )
3956     {
3957         int ii = idx[i];
3958         CV_DbgAssert( (unsigned)ii < (unsigned)size[i] );
3959         ptr += ii*step[i];
3960     }
3961     return *(_Tp*)ptr;
3962 }
3963
3964 template<typename _Tp> inline const _Tp& MatND_<_Tp>::operator ()(const int* idx) const
3965 {
3966     const uchar* ptr = data;
3967     int i, d = dims;
3968     for( i = 0; i < d; i++ )
3969     {
3970         int ii = idx[i];
3971         CV_DbgAssert( (unsigned)ii < (unsigned)size[i] );
3972         ptr += ii*step[i];
3973     }
3974     return *(const _Tp*)ptr;
3975 }
3976
3977 template<typename _Tp> inline _Tp& MatND_<_Tp>::operator ()(int i0)
3978 {
3979     CV_DbgAssert( dims == 1 &&
3980                  (unsigned)i0 < (unsigned)size[0] );
3981     
3982     return *(_Tp*)(data + i0*step[0]);
3983 }
3984
3985 template<typename _Tp> inline const _Tp& MatND_<_Tp>::operator ()(int i0) const
3986 {
3987     CV_DbgAssert( dims == 1 &&
3988                  (unsigned)i0 < (unsigned)size[0] );
3989     
3990     return *(const _Tp*)(data + i0*step[0]);
3991 }
3992     
3993     
3994 template<typename _Tp> inline _Tp& MatND_<_Tp>::operator ()(int i0, int i1)
3995 {
3996     CV_DbgAssert( dims == 2 &&
3997                  (unsigned)i0 < (unsigned)size[0] &&
3998                  (unsigned)i1 < (unsigned)size[1] );
3999     
4000     return *(_Tp*)(data + i0*step[0] + i1*step[1]);
4001 }
4002
4003 template<typename _Tp> inline const _Tp& MatND_<_Tp>::operator ()(int i0, int i1) const
4004 {
4005     CV_DbgAssert( dims == 2 &&
4006                  (unsigned)i0 < (unsigned)size[0] &&
4007                  (unsigned)i1 < (unsigned)size[1] );
4008     
4009     return *(const _Tp*)(data + i0*step[0] + i1*step[1]);
4010 }
4011     
4012     
4013 template<typename _Tp> inline _Tp& MatND_<_Tp>::operator ()(int i0, int i1, int i2)
4014 {
4015     CV_DbgAssert( dims == 3 &&
4016         (unsigned)i0 < (unsigned)size[0] &&
4017         (unsigned)i1 < (unsigned)size[1] &&
4018         (unsigned)i2 < (unsigned)size[2] );
4019
4020     return *(_Tp*)(data + i0*step[0] + i1*step[1] + i2*step[2]);
4021 }
4022
4023 template<typename _Tp> inline const _Tp& MatND_<_Tp>::operator ()(int i0, int i1, int i2) const
4024 {
4025     CV_DbgAssert( dims == 3 &&
4026         (unsigned)i0 < (unsigned)size[0] &&
4027         (unsigned)i1 < (unsigned)size[1] &&
4028         (unsigned)i2 < (unsigned)size[2] );
4029
4030     return *(const _Tp*)(data + i0*step[0] + i1*step[1] + i2*step[2]);
4031 }
4032
4033     
4034 static inline void merge(const vector<MatND>& mv, MatND& dst)
4035 {
4036     merge(&mv[0], mv.size(), dst);
4037 }
4038     
4039 static inline void split(const MatND& m, vector<MatND>& mv)
4040 {
4041     mv.resize(m.channels());
4042     if(m.channels() > 0)
4043         split(m, &mv[0]);
4044 }
4045
4046 static inline void mixChannels(const vector<MatND>& src, vector<MatND>& dst,
4047                                const int* fromTo, int npairs)
4048 {
4049     mixChannels(&src[0], (int)src.size(), &dst[0], (int)dst.size(), fromTo, npairs);
4050 }   
4051
4052 //////////////////////////////// SparseMat ////////////////////////////////
4053
4054 inline SparseMat::SparseMat()
4055 : flags(MAGIC_VAL), hdr(0)
4056 {
4057 }
4058
4059 inline SparseMat::SparseMat(int _dims, const int* _sizes, int _type)
4060 : flags(MAGIC_VAL), hdr(0)
4061 {
4062     create(_dims, _sizes, _type);
4063 }
4064
4065 inline SparseMat::SparseMat(const SparseMat& m)
4066 : flags(m.flags), hdr(m.hdr)
4067 {
4068     addref();
4069 }
4070
4071 inline SparseMat::~SparseMat()
4072 {
4073     release();
4074 }
4075
4076 inline SparseMat& SparseMat::operator = (const SparseMat& m)
4077 {
4078     if( this != &m )
4079     {
4080         if( m.hdr )
4081             CV_XADD(&m.hdr->refcount, 1);
4082         release();
4083         flags = m.flags;
4084         hdr = m.hdr;
4085     }
4086     return *this;
4087 }
4088
4089 inline SparseMat& SparseMat::operator = (const Mat& m)
4090 { return (*this = SparseMat(m)); }
4091
4092 inline SparseMat& SparseMat::operator = (const MatND& m)
4093 { return (*this = SparseMat(m)); }
4094
4095 inline SparseMat SparseMat::clone() const
4096 {
4097     SparseMat temp;
4098     this->copyTo(temp);
4099     return temp;
4100 }
4101
4102
4103 inline void SparseMat::assignTo( SparseMat& m, int type ) const
4104 {
4105     if( type < 0 )
4106         m = *this;
4107     else
4108         convertTo(m, type);
4109 }
4110
4111 inline void SparseMat::addref()
4112 { if( hdr ) CV_XADD(&hdr->refcount, 1); }
4113
4114 inline void SparseMat::release()
4115 {
4116     if( hdr && CV_XADD(&hdr->refcount, -1) == 1 )
4117         delete hdr;
4118     hdr = 0;
4119 }
4120
4121 inline size_t SparseMat::elemSize() const
4122 { return CV_ELEM_SIZE(flags); }
4123
4124 inline size_t SparseMat::elemSize1() const
4125 { return CV_ELEM_SIZE1(flags); }
4126
4127 inline int SparseMat::type() const
4128 { return CV_MAT_TYPE(flags); }
4129
4130 inline int SparseMat::depth() const
4131 { return CV_MAT_DEPTH(flags); }
4132
4133 inline int SparseMat::channels() const
4134 { return CV_MAT_CN(flags); }
4135
4136 inline const int* SparseMat::size() const
4137 {
4138     return hdr ? hdr->size : 0;
4139 }
4140
4141 inline int SparseMat::size(int i) const
4142 {
4143     if( hdr )
4144     {
4145         CV_DbgAssert((unsigned)i < (unsigned)hdr->dims);
4146         return hdr->size[i];
4147     }
4148     return 0;
4149 }
4150
4151 inline int SparseMat::dims() const
4152 {
4153     return hdr ? hdr->dims : 0;
4154 }
4155
4156 inline size_t SparseMat::nzcount() const
4157 {
4158     return hdr ? hdr->nodeCount : 0;
4159 }
4160
4161 inline size_t SparseMat::hash(int i0) const
4162 {
4163     return (size_t)i0;
4164 }
4165
4166 inline size_t SparseMat::hash(int i0, int i1) const
4167 {
4168     return (size_t)(unsigned)i0*HASH_SCALE + (unsigned)i1;
4169 }
4170
4171 inline size_t SparseMat::hash(int i0, int i1, int i2) const
4172 {
4173     return ((size_t)(unsigned)i0*HASH_SCALE + (unsigned)i1)*HASH_SCALE + (unsigned)i2;
4174 }
4175
4176 inline size_t SparseMat::hash(const int* idx) const
4177 {
4178     size_t h = (unsigned)idx[0];
4179     if( !hdr )
4180         return 0;
4181     int i, d = hdr->dims;
4182     for( i = 1; i < d; i++ )
4183         h = h*HASH_SCALE + (unsigned)idx[i];
4184     return h;
4185 }
4186
4187 template<typename _Tp> inline _Tp& SparseMat::ref(int i0, size_t* hashval)
4188 { return *(_Tp*)((SparseMat*)this)->ptr(i0, true, hashval); }
4189     
4190 template<typename _Tp> inline _Tp& SparseMat::ref(int i0, int i1, size_t* hashval)
4191 { return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, true, hashval); }
4192
4193 template<typename _Tp> inline _Tp& SparseMat::ref(int i0, int i1, int i2, size_t* hashval)
4194 { return *(_Tp*)((SparseMat*)this)->ptr(i0, i1, i2, true, hashval); }
4195
4196 template<typename _Tp> inline _Tp& SparseMat::ref(const int* idx, size_t* hashval)
4197 { return *(_Tp*)((SparseMat*)this)->ptr(idx, true, hashval); }
4198
4199 template<typename _Tp> inline _Tp SparseMat::value(int i0, size_t* hashval) const
4200 {
4201     const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, false, hashval);
4202     return p ? *p : _Tp();
4203 }    
4204     
4205 template<typename _Tp> inline _Tp SparseMat::value(int i0, int i1, size_t* hashval) const
4206 {
4207     const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, false, hashval);
4208     return p ? *p : _Tp();
4209 }
4210
4211 template<typename _Tp> inline _Tp SparseMat::value(int i0, int i1, int i2, size_t* hashval) const
4212 {
4213     const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, false, hashval);
4214     return p ? *p : _Tp();
4215 }
4216
4217 template<typename _Tp> inline _Tp SparseMat::value(const int* idx, size_t* hashval) const
4218 {
4219     const _Tp* p = (const _Tp*)((SparseMat*)this)->ptr(idx, false, hashval);
4220     return p ? *p : _Tp();
4221 }
4222
4223 template<typename _Tp> inline const _Tp* SparseMat::find(int i0, size_t* hashval) const
4224 { return (const _Tp*)((SparseMat*)this)->ptr(i0, true, hashval); }
4225     
4226 template<typename _Tp> inline const _Tp* SparseMat::find(int i0, int i1, size_t* hashval) const
4227 { return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, true, hashval); }
4228
4229 template<typename _Tp> inline const _Tp* SparseMat::find(int i0, int i1, int i2, size_t* hashval) const
4230 { return (const _Tp*)((SparseMat*)this)->ptr(i0, i1, i2, true, hashval); }
4231
4232 template<typename _Tp> inline const _Tp* SparseMat::find(const int* idx, size_t* hashval) const
4233 { return (const _Tp*)((SparseMat*)this)->ptr(idx, true, hashval); }
4234
4235 template<typename _Tp> inline _Tp& SparseMat::value(Node* n)
4236 { return *(_Tp*)((uchar*)n + hdr->valueOffset); }
4237
4238 template<typename _Tp> inline const _Tp& SparseMat::value(const Node* n) const
4239 { return *(const _Tp*)((const uchar*)n + hdr->valueOffset); }
4240
4241 inline SparseMat::Node* SparseMat::node(size_t nidx)
4242 { return (Node*)&hdr->pool[nidx]; }
4243
4244 inline const SparseMat::Node* SparseMat::node(size_t nidx) const
4245 { return (const Node*)&hdr->pool[nidx]; }
4246
4247 inline SparseMatIterator SparseMat::begin()
4248 { return SparseMatIterator(this); }
4249
4250 inline SparseMatConstIterator SparseMat::begin() const
4251 { return SparseMatConstIterator(this); }
4252
4253 inline SparseMatIterator SparseMat::end()
4254 { SparseMatIterator it(this); it.seekEnd(); return it; }
4255     
4256 inline SparseMatConstIterator SparseMat::end() const
4257 { SparseMatConstIterator it(this); it.seekEnd(); return it; }
4258     
4259 template<typename _Tp> inline SparseMatIterator_<_Tp> SparseMat::begin()
4260 { return SparseMatIterator_<_Tp>(this); }
4261     
4262 template<typename _Tp> inline SparseMatConstIterator_<_Tp> SparseMat::begin() const
4263 { return SparseMatConstIterator_<_Tp>(this); }
4264     
4265 template<typename _Tp> inline SparseMatIterator_<_Tp> SparseMat::end()
4266 { SparseMatIterator_<_Tp> it(this); it.seekEnd(); return it; }
4267
4268 template<typename _Tp> inline SparseMatConstIterator_<_Tp> SparseMat::end() const
4269 { SparseMatConstIterator_<_Tp> it(this); it.seekEnd(); return it; }
4270     
4271     
4272 inline SparseMatConstIterator::SparseMatConstIterator()
4273 : m(0), hashidx(0), ptr(0)
4274 {
4275 }
4276
4277 inline SparseMatConstIterator::SparseMatConstIterator(const SparseMatConstIterator& it)
4278 : m(it.m), hashidx(it.hashidx), ptr(it.ptr)
4279 {
4280 }
4281
4282 static inline bool operator == (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2)
4283 { return it1.m == it2.m && it1.hashidx == it2.hashidx && it1.ptr == it2.ptr; }
4284
4285 static inline bool operator != (const SparseMatConstIterator& it1, const SparseMatConstIterator& it2)
4286 { return !(it1 == it2); }
4287
4288
4289 inline SparseMatConstIterator& SparseMatConstIterator::operator = (const SparseMatConstIterator& it)
4290 {
4291     if( this != &it )
4292     {
4293         m = it.m;
4294         hashidx = it.hashidx;
4295         ptr = it.ptr;
4296     }
4297     return *this;
4298 }
4299
4300 template<typename _Tp> inline const _Tp& SparseMatConstIterator::value() const
4301 { return *(_Tp*)ptr; }
4302
4303 inline const SparseMat::Node* SparseMatConstIterator::node() const
4304 {
4305     return ptr && m && m->hdr ?
4306         (const SparseMat::Node*)(ptr - m->hdr->valueOffset) : 0;
4307 }
4308
4309 inline SparseMatConstIterator SparseMatConstIterator::operator ++(int)
4310 {
4311     SparseMatConstIterator it = *this;
4312     ++*this;
4313     return it;
4314 }
4315
4316     
4317 inline void SparseMatConstIterator::seekEnd()
4318 {
4319     if( m && m->hdr )
4320     {
4321         hashidx = m->hdr->hashtab.size();
4322         ptr = 0;
4323     }
4324 }
4325     
4326 inline SparseMatIterator::SparseMatIterator()
4327 {}
4328
4329 inline SparseMatIterator::SparseMatIterator(SparseMat* _m)
4330 : SparseMatConstIterator(_m)
4331 {}
4332
4333 inline SparseMatIterator::SparseMatIterator(const SparseMatIterator& it)
4334 : SparseMatConstIterator(it)
4335 {
4336 }
4337
4338 inline SparseMatIterator& SparseMatIterator::operator = (const SparseMatIterator& it)
4339 {
4340     (SparseMatConstIterator&)*this = it;
4341     return *this;
4342 }
4343
4344 template<typename _Tp> inline _Tp& SparseMatIterator::value() const
4345 { return *(_Tp*)ptr; }
4346
4347 inline SparseMat::Node* SparseMatIterator::node() const
4348 {
4349     return (SparseMat::Node*)SparseMatConstIterator::node();
4350 }
4351
4352 inline SparseMatIterator& SparseMatIterator::operator ++()
4353 {
4354     SparseMatConstIterator::operator ++();
4355     return *this;
4356 }
4357
4358 inline SparseMatIterator SparseMatIterator::operator ++(int)
4359 {
4360     SparseMatIterator it = *this;
4361     ++*this;
4362     return it;
4363 }
4364
4365
4366 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_()
4367 { flags = MAGIC_VAL | DataType<_Tp>::type; }
4368
4369 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(int _dims, const int* _sizes)
4370 : SparseMat(_dims, _sizes, DataType<_Tp>::type)
4371 {}
4372
4373 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const SparseMat& m)
4374 {
4375     if( m.type() == DataType<_Tp>::type )
4376         *this = (const SparseMat_<_Tp>&)m;
4377     else
4378         m.convertTo(this, DataType<_Tp>::type);
4379 }
4380
4381 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const SparseMat_<_Tp>& m)
4382 {
4383     this->flags = m.flags;
4384     this->hdr = m.hdr;
4385     if( this->hdr )
4386         CV_XADD(&this->hdr->refcount, 1);
4387 }
4388
4389 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const Mat& m)
4390 {
4391     SparseMat sm(m);
4392     *this = sm;
4393 }
4394
4395 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const MatND& m)
4396 {
4397     SparseMat sm(m);
4398     *this = sm;
4399 }
4400
4401 template<typename _Tp> inline SparseMat_<_Tp>::SparseMat_(const CvSparseMat* m)
4402 {
4403     SparseMat sm(m);
4404     *this = sm;
4405 }
4406
4407 template<typename _Tp> inline SparseMat_<_Tp>&
4408 SparseMat_<_Tp>::operator = (const SparseMat_<_Tp>& m)
4409 {
4410     if( this != &m )
4411     {
4412         if( m.hdr ) CV_XADD(&m.hdr->refcount, 1);
4413         release();
4414         flags = m.flags;
4415         hdr = m.hdr;
4416     }
4417     return *this;
4418 }
4419
4420 template<typename _Tp> inline SparseMat_<_Tp>&
4421 SparseMat_<_Tp>::operator = (const SparseMat& m)
4422 {
4423     if( m.type() == DataType<_Tp>::type )
4424         return (*this = (const SparseMat_<_Tp>&)m);
4425     m.convertTo(*this, DataType<_Tp>::type);
4426     return *this;
4427 }
4428
4429 template<typename _Tp> inline SparseMat_<_Tp>&
4430 SparseMat_<_Tp>::operator = (const Mat& m)
4431 { return (*this = SparseMat(m)); }
4432
4433 template<typename _Tp> inline SparseMat_<_Tp>&
4434 SparseMat_<_Tp>::operator = (const MatND& m)
4435 { return (*this = SparseMat(m)); }
4436
4437 template<typename _Tp> inline SparseMat_<_Tp>
4438 SparseMat_<_Tp>::clone() const
4439 {
4440     SparseMat_<_Tp> m;
4441     this->copyTo(m);
4442     return m;
4443 }
4444
4445 template<typename _Tp> inline void
4446 SparseMat_<_Tp>::create(int _dims, const int* _sizes)
4447 {
4448     SparseMat::create(_dims, _sizes, DataType<_Tp>::type);
4449 }
4450
4451 template<typename _Tp> inline
4452 SparseMat_<_Tp>::operator CvSparseMat*() const
4453 {
4454     return SparseMat::operator CvSparseMat*();
4455 }
4456
4457 template<typename _Tp> inline int SparseMat_<_Tp>::type() const
4458 { return DataType<_Tp>::type; }
4459
4460 template<typename _Tp> inline int SparseMat_<_Tp>::depth() const
4461 { return DataType<_Tp>::depth; }
4462
4463 template<typename _Tp> inline int SparseMat_<_Tp>::channels() const
4464 { return DataType<_Tp>::channels; }
4465
4466 template<typename _Tp> inline _Tp&
4467 SparseMat_<_Tp>::ref(int i0, size_t* hashval)
4468 { return SparseMat::ref<_Tp>(i0, hashval); }
4469
4470 template<typename _Tp> inline _Tp
4471 SparseMat_<_Tp>::operator()(int i0, size_t* hashval) const
4472 { return SparseMat::value<_Tp>(i0, hashval); }    
4473     
4474 template<typename _Tp> inline _Tp&
4475 SparseMat_<_Tp>::ref(int i0, int i1, size_t* hashval)
4476 { return SparseMat::ref<_Tp>(i0, i1, hashval); }
4477
4478 template<typename _Tp> inline _Tp
4479 SparseMat_<_Tp>::operator()(int i0, int i1, size_t* hashval) const
4480 { return SparseMat::value<_Tp>(i0, i1, hashval); }
4481
4482 template<typename _Tp> inline _Tp&
4483 SparseMat_<_Tp>::ref(int i0, int i1, int i2, size_t* hashval)
4484 { return SparseMat::ref<_Tp>(i0, i1, i2, hashval); }
4485
4486 template<typename _Tp> inline _Tp
4487 SparseMat_<_Tp>::operator()(int i0, int i1, int i2, size_t* hashval) const
4488 { return SparseMat::value<_Tp>(i0, i1, i2, hashval); }
4489
4490 template<typename _Tp> inline _Tp&
4491 SparseMat_<_Tp>::ref(const int* idx, size_t* hashval)
4492 { return SparseMat::ref<_Tp>(idx, hashval); }
4493
4494 template<typename _Tp> inline _Tp
4495 SparseMat_<_Tp>::operator()(const int* idx, size_t* hashval) const
4496 { return SparseMat::value<_Tp>(idx, hashval); }
4497
4498 template<typename _Tp> inline SparseMatIterator_<_Tp> SparseMat_<_Tp>::begin()
4499 { return SparseMatIterator_<_Tp>(this); }
4500
4501 template<typename _Tp> inline SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::begin() const
4502 { return SparseMatConstIterator_<_Tp>(this); }
4503
4504 template<typename _Tp> inline SparseMatIterator_<_Tp> SparseMat_<_Tp>::end()
4505 { SparseMatIterator_<_Tp> it(this); it.seekEnd(); return it; }
4506     
4507 template<typename _Tp> inline SparseMatConstIterator_<_Tp> SparseMat_<_Tp>::end() const
4508 { SparseMatConstIterator_<_Tp> it(this); it.seekEnd(); return it; }
4509
4510 template<typename _Tp> inline
4511 SparseMatConstIterator_<_Tp>::SparseMatConstIterator_()
4512 {}
4513
4514 template<typename _Tp> inline
4515 SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMat_<_Tp>* _m)
4516 : SparseMatConstIterator(_m)
4517 {}
4518
4519 template<typename _Tp> inline
4520 SparseMatConstIterator_<_Tp>::SparseMatConstIterator_(const SparseMatConstIterator_<_Tp>& it)
4521 : SparseMatConstIterator(it)
4522 {}
4523
4524 template<typename _Tp> inline SparseMatConstIterator_<_Tp>&
4525 SparseMatConstIterator_<_Tp>::operator = (const SparseMatConstIterator_<_Tp>& it)
4526 { return ((SparseMatConstIterator&)*this = it); }
4527
4528 template<typename _Tp> inline const _Tp&
4529 SparseMatConstIterator_<_Tp>::operator *() const
4530 { return *(const _Tp*)this->ptr; }
4531
4532 template<typename _Tp> inline SparseMatConstIterator_<_Tp>&
4533 SparseMatConstIterator_<_Tp>::operator ++()
4534 {
4535     SparseMatConstIterator::operator ++();
4536     return *this;
4537 }
4538
4539 template<typename _Tp> inline SparseMatConstIterator_<_Tp>
4540 SparseMatConstIterator_<_Tp>::operator ++(int)
4541 {
4542     SparseMatConstIterator it = *this;
4543     SparseMatConstIterator::operator ++();
4544     return it;
4545 }
4546
4547 template<typename _Tp> inline
4548 SparseMatIterator_<_Tp>::SparseMatIterator_()
4549 {}
4550
4551 template<typename _Tp> inline
4552 SparseMatIterator_<_Tp>::SparseMatIterator_(SparseMat_<_Tp>* _m)
4553 : SparseMatConstIterator_<_Tp>(_m)
4554 {}
4555
4556 template<typename _Tp> inline
4557 SparseMatIterator_<_Tp>::SparseMatIterator_(const SparseMatIterator_<_Tp>& it)
4558 : SparseMatConstIterator_<_Tp>(it)
4559 {}
4560
4561 template<typename _Tp> inline SparseMatIterator_<_Tp>&
4562 SparseMatIterator_<_Tp>::operator = (const SparseMatIterator_<_Tp>& it)
4563 { return ((SparseMatIterator&)*this = it); }
4564
4565 template<typename _Tp> inline _Tp&
4566 SparseMatIterator_<_Tp>::operator *() const
4567 { return *(_Tp*)this->ptr; }
4568
4569 template<typename _Tp> inline SparseMatIterator_<_Tp>&
4570 SparseMatIterator_<_Tp>::operator ++()
4571 {
4572     SparseMatConstIterator::operator ++();
4573     return *this;
4574 }
4575
4576 template<typename _Tp> inline SparseMatIterator_<_Tp>
4577 SparseMatIterator_<_Tp>::operator ++(int)
4578 {
4579     SparseMatIterator it = *this;
4580     SparseMatConstIterator::operator ++();
4581     return it;
4582 }
4583     
4584 }
4585
4586 #endif
4587 #endif