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-2010, 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 /* ////////////////////////////////////////////////////////////////////
44 //
45 //  Mat basic operations: Copy, Set
46 //
47 // */
48 
49 #include "precomp.hpp"
50 
51 namespace cv
52 {
53 
54 class MatOp_Identity : public MatOp
55 {
56 public:
MatOp_Identity()57     MatOp_Identity() {}
~MatOp_Identity()58     virtual ~MatOp_Identity() {}
59 
elementWise(const MatExpr &) const60     bool elementWise(const MatExpr& /*expr*/) const { return true; }
61     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
62 
63     static void makeExpr(MatExpr& res, const Mat& m);
64 };
65 
66 static MatOp_Identity g_MatOp_Identity;
67 
68 class MatOp_AddEx : public MatOp
69 {
70 public:
MatOp_AddEx()71     MatOp_AddEx() {}
~MatOp_AddEx()72     virtual ~MatOp_AddEx() {}
73 
elementWise(const MatExpr &) const74     bool elementWise(const MatExpr& /*expr*/) const { return true; }
75     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
76 
77     void add(const MatExpr& e1, const Scalar& s, MatExpr& res) const;
78     void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const;
79     void multiply(const MatExpr& e1, double s, MatExpr& res) const;
80     void divide(double s, const MatExpr& e, MatExpr& res) const;
81 
82     void transpose(const MatExpr& e1, MatExpr& res) const;
83     void abs(const MatExpr& expr, MatExpr& res) const;
84 
85     static void makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s=Scalar());
86 };
87 
88 static MatOp_AddEx g_MatOp_AddEx;
89 
90 class MatOp_Bin : public MatOp
91 {
92 public:
MatOp_Bin()93     MatOp_Bin() {}
~MatOp_Bin()94     virtual ~MatOp_Bin() {}
95 
elementWise(const MatExpr &) const96     bool elementWise(const MatExpr& /*expr*/) const { return true; }
97     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
98 
99     void multiply(const MatExpr& e1, double s, MatExpr& res) const;
100     void divide(double s, const MatExpr& e, MatExpr& res) const;
101 
102     static void makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale=1);
103     static void makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s);
104 };
105 
106 static MatOp_Bin g_MatOp_Bin;
107 
108 class MatOp_Cmp : public MatOp
109 {
110 public:
MatOp_Cmp()111     MatOp_Cmp() {}
~MatOp_Cmp()112     virtual ~MatOp_Cmp() {}
113 
elementWise(const MatExpr &) const114     bool elementWise(const MatExpr& /*expr*/) const { return true; }
115     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
116 
117     static void makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b);
118     static void makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha);
119 };
120 
121 static MatOp_Cmp g_MatOp_Cmp;
122 
123 class MatOp_GEMM : public MatOp
124 {
125 public:
MatOp_GEMM()126     MatOp_GEMM() {}
~MatOp_GEMM()127     virtual ~MatOp_GEMM() {}
128 
elementWise(const MatExpr &) const129     bool elementWise(const MatExpr& /*expr*/) const { return false; }
130     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
131 
132     void add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
133     void subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
134     void multiply(const MatExpr& e, double s, MatExpr& res) const;
135 
136     void transpose(const MatExpr& expr, MatExpr& res) const;
137 
138     static void makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b,
139                          double alpha=1, const Mat& c=Mat(), double beta=1);
140 };
141 
142 static MatOp_GEMM g_MatOp_GEMM;
143 
144 class MatOp_Invert : public MatOp
145 {
146 public:
MatOp_Invert()147     MatOp_Invert() {}
~MatOp_Invert()148     virtual ~MatOp_Invert() {}
149 
elementWise(const MatExpr &) const150     bool elementWise(const MatExpr& /*expr*/) const { return false; }
151     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
152 
153     void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
154 
155     static void makeExpr(MatExpr& res, int method, const Mat& m);
156 };
157 
158 static MatOp_Invert g_MatOp_Invert;
159 
160 class MatOp_T : public MatOp
161 {
162 public:
MatOp_T()163     MatOp_T() {}
~MatOp_T()164     virtual ~MatOp_T() {}
165 
elementWise(const MatExpr &) const166     bool elementWise(const MatExpr& /*expr*/) const { return false; }
167     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
168 
169     void multiply(const MatExpr& e1, double s, MatExpr& res) const;
170     void transpose(const MatExpr& expr, MatExpr& res) const;
171 
172     static void makeExpr(MatExpr& res, const Mat& a, double alpha=1);
173 };
174 
175 static MatOp_T g_MatOp_T;
176 
177 class MatOp_Solve : public MatOp
178 {
179 public:
MatOp_Solve()180     MatOp_Solve() {}
~MatOp_Solve()181     virtual ~MatOp_Solve() {}
182 
elementWise(const MatExpr &) const183     bool elementWise(const MatExpr& /*expr*/) const { return false; }
184     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
185 
186     static void makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b);
187 };
188 
189 static MatOp_Solve g_MatOp_Solve;
190 
191 class MatOp_Initializer : public MatOp
192 {
193 public:
MatOp_Initializer()194     MatOp_Initializer() {}
~MatOp_Initializer()195     virtual ~MatOp_Initializer() {}
196 
elementWise(const MatExpr &) const197     bool elementWise(const MatExpr& /*expr*/) const { return false; }
198     void assign(const MatExpr& expr, Mat& m, int type=-1) const;
199 
200     void multiply(const MatExpr& e, double s, MatExpr& res) const;
201 
202     static void makeExpr(MatExpr& res, int method, Size sz, int type, double alpha=1);
203     static void makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha=1);
204 };
205 
getGlobalMatOpInitializer()206 static MatOp_Initializer* getGlobalMatOpInitializer()
207 {
208     static MatOp_Initializer initializer;
209     return &initializer;
210 }
211 
isIdentity(const MatExpr & e)212 static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identity; }
isAddEx(const MatExpr & e)213 static inline bool isAddEx(const MatExpr& e) { return e.op == &g_MatOp_AddEx; }
isScaled(const MatExpr & e)214 static inline bool isScaled(const MatExpr& e) { return isAddEx(e) && (!e.b.data || e.beta == 0) && e.s == Scalar(); }
isBin(const MatExpr & e,char c)215 static inline bool isBin(const MatExpr& e, char c) { return e.op == &g_MatOp_Bin && e.flags == c; }
isCmp(const MatExpr & e)216 static inline bool isCmp(const MatExpr& e) { return e.op == &g_MatOp_Cmp; }
isReciprocal(const MatExpr & e)217 static inline bool isReciprocal(const MatExpr& e) { return isBin(e,'/') && (!e.b.data || e.beta == 0); }
isT(const MatExpr & e)218 static inline bool isT(const MatExpr& e) { return e.op == &g_MatOp_T; }
isInv(const MatExpr & e)219 static inline bool isInv(const MatExpr& e) { return e.op == &g_MatOp_Invert; }
isSolve(const MatExpr & e)220 static inline bool isSolve(const MatExpr& e) { return e.op == &g_MatOp_Solve; }
isGEMM(const MatExpr & e)221 static inline bool isGEMM(const MatExpr& e) { return e.op == &g_MatOp_GEMM; }
isMatProd(const MatExpr & e)222 static inline bool isMatProd(const MatExpr& e) { return e.op == &g_MatOp_GEMM && (!e.c.data || e.beta == 0); }
isInitializer(const MatExpr & e)223 static inline bool isInitializer(const MatExpr& e) { return e.op == getGlobalMatOpInitializer(); }
224 
225 /////////////////////////////////////////////////////////////////////////////////////////////////////
226 
MatOp()227 MatOp::MatOp() {}
~MatOp()228 MatOp::~MatOp() {}
229 
230 
elementWise(const MatExpr &) const231 bool MatOp::elementWise(const MatExpr& /*expr*/) const
232 {
233     return false;
234 }
235 
roi(const MatExpr & expr,const Range & rowRange,const Range & colRange,MatExpr & e) const236 void MatOp::roi(const MatExpr& expr, const Range& rowRange, const Range& colRange, MatExpr& e) const
237 {
238     if( elementWise(expr) )
239     {
240         e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(),
241                     expr.alpha, expr.beta, expr.s);
242         if(expr.a.data)
243             e.a = expr.a(rowRange, colRange);
244         if(expr.b.data)
245             e.b = expr.b(rowRange, colRange);
246         if(expr.c.data)
247             e.c = expr.c(rowRange, colRange);
248     }
249     else
250     {
251         Mat m;
252         expr.op->assign(expr, m);
253         e = MatExpr(&g_MatOp_Identity, 0, m(rowRange, colRange), Mat(), Mat());
254     }
255 }
256 
diag(const MatExpr & expr,int d,MatExpr & e) const257 void MatOp::diag(const MatExpr& expr, int d, MatExpr& e) const
258 {
259     if( elementWise(expr) )
260     {
261         e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(),
262                     expr.alpha, expr.beta, expr.s);
263         if(expr.a.data)
264             e.a = expr.a.diag(d);
265         if(expr.b.data)
266             e.b = expr.b.diag(d);
267         if(expr.c.data)
268             e.c = expr.c.diag(d);
269     }
270     else
271     {
272         Mat m;
273         expr.op->assign(expr, m);
274         e = MatExpr(&g_MatOp_Identity, 0, m.diag(d), Mat(), Mat());
275     }
276 }
277 
278 
augAssignAdd(const MatExpr & expr,Mat & m) const279 void MatOp::augAssignAdd(const MatExpr& expr, Mat& m) const
280 {
281     Mat temp;
282     expr.op->assign(expr, temp);
283     m += temp;
284 }
285 
286 
augAssignSubtract(const MatExpr & expr,Mat & m) const287 void MatOp::augAssignSubtract(const MatExpr& expr, Mat& m) const
288 {
289     Mat temp;
290     expr.op->assign(expr, temp);
291     m -= temp;
292 }
293 
294 
augAssignMultiply(const MatExpr & expr,Mat & m) const295 void MatOp::augAssignMultiply(const MatExpr& expr, Mat& m) const
296 {
297     Mat temp;
298     expr.op->assign(expr, temp);
299     m *= temp;
300 }
301 
302 
augAssignDivide(const MatExpr & expr,Mat & m) const303 void MatOp::augAssignDivide(const MatExpr& expr, Mat& m) const
304 {
305     Mat temp;
306     expr.op->assign(expr, temp);
307     m /= temp;
308 }
309 
310 
augAssignAnd(const MatExpr & expr,Mat & m) const311 void MatOp::augAssignAnd(const MatExpr& expr, Mat& m) const
312 {
313     Mat temp;
314     expr.op->assign(expr, temp);
315     m &= temp;
316 }
317 
318 
augAssignOr(const MatExpr & expr,Mat & m) const319 void MatOp::augAssignOr(const MatExpr& expr, Mat& m) const
320 {
321     Mat temp;
322     expr.op->assign(expr, temp);
323     m |= temp;
324 }
325 
326 
augAssignXor(const MatExpr & expr,Mat & m) const327 void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const
328 {
329     Mat temp;
330     expr.op->assign(expr, temp);
331     m ^= temp;
332 }
333 
334 
add(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const335 void MatOp::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
336 {
337     if( this == e2.op )
338     {
339         double alpha = 1, beta = 1;
340         Scalar s;
341         Mat m1, m2;
342         if( isAddEx(e1) && (!e1.b.data || e1.beta == 0) )
343         {
344             m1 = e1.a;
345             alpha = e1.alpha;
346             s = e1.s;
347         }
348         else
349             e1.op->assign(e1, m1);
350 
351         if( isAddEx(e2) && (!e2.b.data || e2.beta == 0) )
352         {
353             m2 = e2.a;
354             beta = e2.alpha;
355             s += e2.s;
356         }
357         else
358             e2.op->assign(e2, m2);
359         MatOp_AddEx::makeExpr(res, m1, m2, alpha, beta, s);
360     }
361     else
362         e2.op->add(e1, e2, res);
363 }
364 
365 
add(const MatExpr & expr1,const Scalar & s,MatExpr & res) const366 void MatOp::add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const
367 {
368     Mat m1;
369     expr1.op->assign(expr1, m1);
370     MatOp_AddEx::makeExpr(res, m1, Mat(), 1, 0, s);
371 }
372 
373 
subtract(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const374 void MatOp::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
375 {
376     if( this == e2.op )
377     {
378         double alpha = 1, beta = -1;
379         Scalar s;
380         Mat m1, m2;
381         if( isAddEx(e1) && (!e1.b.data || e1.beta == 0) )
382         {
383             m1 = e1.a;
384             alpha = e1.alpha;
385             s = e1.s;
386         }
387         else
388             e1.op->assign(e1, m1);
389 
390         if( isAddEx(e2) && (!e2.b.data || e2.beta == 0) )
391         {
392             m2 = e2.a;
393             beta = -e2.alpha;
394             s -= e2.s;
395         }
396         else
397             e2.op->assign(e2, m2);
398         MatOp_AddEx::makeExpr(res, m1, m2, alpha, beta, s);
399     }
400     else
401         e2.op->subtract(e1, e2, res);
402 }
403 
404 
subtract(const Scalar & s,const MatExpr & expr,MatExpr & res) const405 void MatOp::subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const
406 {
407     Mat m;
408     expr.op->assign(expr, m);
409     MatOp_AddEx::makeExpr(res, m, Mat(), -1, 0, s);
410 }
411 
412 
multiply(const MatExpr & e1,const MatExpr & e2,MatExpr & res,double scale) const413 void MatOp::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
414 {
415     if( this == e2.op )
416     {
417         Mat m1, m2;
418 
419         if( isReciprocal(e1) )
420         {
421             if( isScaled(e2) )
422             {
423                 scale *= e2.alpha;
424                 m2 = e2.a;
425             }
426             else
427                 e2.op->assign(e2, m2);
428 
429             MatOp_Bin::makeExpr(res, '/', m2, e1.a, scale/e1.alpha);
430         }
431         else
432         {
433             char op = '*';
434             if( isScaled(e1) )
435             {
436                 m1 = e1.a;
437                 scale *= e1.alpha;
438             }
439             else
440                 e1.op->assign(e1, m1);
441 
442             if( isScaled(e2) )
443             {
444                 m2 = e2.a;
445                 scale *= e2.alpha;
446             }
447             else if( isReciprocal(e2) )
448             {
449                 op = '/';
450                 m2 = e2.a;
451                 scale /= e2.alpha;
452             }
453             else
454                 e2.op->assign(e2, m2);
455 
456             MatOp_Bin::makeExpr(res, op, m1, m2, scale);
457         }
458     }
459     else
460         e2.op->multiply(e1, e2, res, scale);
461 }
462 
463 
multiply(const MatExpr & expr,double s,MatExpr & res) const464 void MatOp::multiply(const MatExpr& expr, double s, MatExpr& res) const
465 {
466     Mat m;
467     expr.op->assign(expr, m);
468     MatOp_AddEx::makeExpr(res, m, Mat(), s, 0);
469 }
470 
471 
divide(const MatExpr & e1,const MatExpr & e2,MatExpr & res,double scale) const472 void MatOp::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
473 {
474     if( this == e2.op )
475     {
476         if( isReciprocal(e1) && isReciprocal(e2) )
477             MatOp_Bin::makeExpr(res, '/', e2.a, e1.a, e1.alpha/e2.alpha);
478         else
479         {
480             Mat m1, m2;
481             char op = '/';
482 
483             if( isScaled(e1) )
484             {
485                 m1 = e1.a;
486                 scale *= e1.alpha;
487             }
488             else
489                 e1.op->assign(e1, m1);
490 
491             if( isScaled(e2) )
492             {
493                 m2 = e2.a;
494                 scale /= e2.alpha;
495             }
496             else if( isReciprocal(e2) )
497             {
498                 m2 = e2.a;
499                 scale /= e2.alpha;
500                 op = '*';
501             }
502             else
503                 e2.op->assign(e2, m2);
504             MatOp_Bin::makeExpr(res, op, m1, m2, scale);
505         }
506     }
507     else
508         e2.op->divide(e1, e2, res, scale);
509 }
510 
511 
divide(double s,const MatExpr & expr,MatExpr & res) const512 void MatOp::divide(double s, const MatExpr& expr, MatExpr& res) const
513 {
514     Mat m;
515     expr.op->assign(expr, m);
516     MatOp_Bin::makeExpr(res, '/', m, Mat(), s);
517 }
518 
519 
abs(const MatExpr & expr,MatExpr & res) const520 void MatOp::abs(const MatExpr& expr, MatExpr& res) const
521 {
522     Mat m;
523     expr.op->assign(expr, m);
524     MatOp_Bin::makeExpr(res, 'a', m, Mat());
525 }
526 
527 
transpose(const MatExpr & expr,MatExpr & res) const528 void MatOp::transpose(const MatExpr& expr, MatExpr& res) const
529 {
530     Mat m;
531     expr.op->assign(expr, m);
532     MatOp_T::makeExpr(res, m, 1);
533 }
534 
535 
matmul(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const536 void MatOp::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
537 {
538     if( this == e2.op )
539     {
540         double scale = 1;
541         int flags = 0;
542         Mat m1, m2;
543 
544         if( isT(e1) )
545         {
546             flags = CV_GEMM_A_T;
547             scale = e1.alpha;
548             m1 = e1.a;
549         }
550         else if( isScaled(e1) )
551         {
552             scale = e1.alpha;
553             m1 = e1.a;
554         }
555         else
556             e1.op->assign(e1, m1);
557 
558         if( isT(e2) )
559         {
560             flags |= CV_GEMM_B_T;
561             scale *= e2.alpha;
562             m2 = e2.a;
563         }
564         else if( isScaled(e2) )
565         {
566             scale *= e2.alpha;
567             m2 = e2.a;
568         }
569         else
570             e2.op->assign(e2, m2);
571 
572         MatOp_GEMM::makeExpr(res, flags, m1, m2, scale);
573     }
574     else
575         e2.op->matmul(e1, e2, res);
576 }
577 
578 
invert(const MatExpr & expr,int method,MatExpr & res) const579 void MatOp::invert(const MatExpr& expr, int method, MatExpr& res) const
580 {
581     Mat m;
582     expr.op->assign(expr, m);
583     MatOp_Invert::makeExpr(res, method, m);
584 }
585 
586 
size(const MatExpr & expr) const587 Size MatOp::size(const MatExpr& expr) const
588 {
589     return !expr.a.empty() ? expr.a.size() : expr.b.empty() ? expr.b.size() : expr.c.size();
590 }
591 
type(const MatExpr & expr) const592 int MatOp::type(const MatExpr& expr) const
593 {
594     return !expr.a.empty() ? expr.a.type() : expr.b.empty() ? expr.b.type() : expr.c.type();
595 }
596 
597 //////////////////////////////////////////////////////////////////////////////////////////////////
598 
MatExpr(const Mat & m)599 MatExpr::MatExpr(const Mat& m) : op(&g_MatOp_Identity), flags(0), a(m), b(Mat()), c(Mat()), alpha(1), beta(0), s(Scalar())
600 {
601 }
602 
row(int y) const603 MatExpr MatExpr::row(int y) const
604 {
605     MatExpr e;
606     op->roi(*this, Range(y, y+1), Range::all(), e);
607     return e;
608 }
609 
col(int x) const610 MatExpr MatExpr::col(int x) const
611 {
612     MatExpr e;
613     op->roi(*this, Range::all(), Range(x, x+1), e);
614     return e;
615 }
616 
diag(int d) const617 MatExpr MatExpr::diag(int d) const
618 {
619     MatExpr e;
620     op->diag(*this, d, e);
621     return e;
622 }
623 
operator ()(const Range & rowRange,const Range & colRange) const624 MatExpr MatExpr::operator()( const Range& rowRange, const Range& colRange ) const
625 {
626     MatExpr e;
627     op->roi(*this, rowRange, colRange, e);
628     return e;
629 }
630 
operator ()(const Rect & roi) const631 MatExpr MatExpr::operator()( const Rect& roi ) const
632 {
633     MatExpr e;
634     op->roi(*this, Range(roi.y, roi.y + roi.height), Range(roi.x, roi.x + roi.width), e);
635     return e;
636 }
637 
cross(const Mat & m) const638 Mat MatExpr::cross(const Mat& m) const
639 {
640     return ((Mat)*this).cross(m);
641 }
642 
dot(const Mat & m) const643 double MatExpr::dot(const Mat& m) const
644 {
645     return ((Mat)*this).dot(m);
646 }
647 
t() const648 MatExpr MatExpr::t() const
649 {
650     MatExpr e;
651     op->transpose(*this, e);
652     return e;
653 }
654 
inv(int method) const655 MatExpr MatExpr::inv(int method) const
656 {
657     MatExpr e;
658     op->invert(*this, method, e);
659     return e;
660 }
661 
mul(const MatExpr & e,double scale) const662 MatExpr MatExpr::mul(const MatExpr& e, double scale) const
663 {
664     MatExpr en;
665     op->multiply(*this, e, en, scale);
666     return en;
667 }
668 
mul(const Mat & m,double scale) const669 MatExpr MatExpr::mul(const Mat& m, double scale) const
670 {
671     MatExpr e;
672     op->multiply(*this, MatExpr(m), e, scale);
673     return e;
674 }
675 
operator +(const Mat & a,const Mat & b)676 MatExpr operator + (const Mat& a, const Mat& b)
677 {
678     MatExpr e;
679     MatOp_AddEx::makeExpr(e, a, b, 1, 1);
680     return e;
681 }
682 
operator +(const Mat & a,const Scalar & s)683 MatExpr operator + (const Mat& a, const Scalar& s)
684 {
685     MatExpr e;
686     MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s);
687     return e;
688 }
689 
operator +(const Scalar & s,const Mat & a)690 MatExpr operator + (const Scalar& s, const Mat& a)
691 {
692     MatExpr e;
693     MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s);
694     return e;
695 }
696 
operator +(const MatExpr & e,const Mat & m)697 MatExpr operator + (const MatExpr& e, const Mat& m)
698 {
699     MatExpr en;
700     e.op->add(e, MatExpr(m), en);
701     return en;
702 }
703 
operator +(const Mat & m,const MatExpr & e)704 MatExpr operator + (const Mat& m, const MatExpr& e)
705 {
706     MatExpr en;
707     e.op->add(e, MatExpr(m), en);
708     return en;
709 }
710 
operator +(const MatExpr & e,const Scalar & s)711 MatExpr operator + (const MatExpr& e, const Scalar& s)
712 {
713     MatExpr en;
714     e.op->add(e, s, en);
715     return en;
716 }
717 
operator +(const Scalar & s,const MatExpr & e)718 MatExpr operator + (const Scalar& s, const MatExpr& e)
719 {
720     MatExpr en;
721     e.op->add(e, s, en);
722     return en;
723 }
724 
operator +(const MatExpr & e1,const MatExpr & e2)725 MatExpr operator + (const MatExpr& e1, const MatExpr& e2)
726 {
727     MatExpr en;
728     e1.op->add(e1, e2, en);
729     return en;
730 }
731 
operator -(const Mat & a,const Mat & b)732 MatExpr operator - (const Mat& a, const Mat& b)
733 {
734     MatExpr e;
735     MatOp_AddEx::makeExpr(e, a, b, 1, -1);
736     return e;
737 }
738 
operator -(const Mat & a,const Scalar & s)739 MatExpr operator - (const Mat& a, const Scalar& s)
740 {
741     MatExpr e;
742     MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, -s);
743     return e;
744 }
745 
operator -(const Scalar & s,const Mat & a)746 MatExpr operator - (const Scalar& s, const Mat& a)
747 {
748     MatExpr e;
749     MatOp_AddEx::makeExpr(e, a, Mat(), -1, 0, s);
750     return e;
751 }
752 
operator -(const MatExpr & e,const Mat & m)753 MatExpr operator - (const MatExpr& e, const Mat& m)
754 {
755     MatExpr en;
756     e.op->subtract(e, MatExpr(m), en);
757     return en;
758 }
759 
operator -(const Mat & m,const MatExpr & e)760 MatExpr operator - (const Mat& m, const MatExpr& e)
761 {
762     MatExpr en;
763     e.op->subtract(MatExpr(m), e, en);
764     return en;
765 }
766 
operator -(const MatExpr & e,const Scalar & s)767 MatExpr operator - (const MatExpr& e, const Scalar& s)
768 {
769     MatExpr en;
770     e.op->add(e, -s, en);
771     return en;
772 }
773 
operator -(const Scalar & s,const MatExpr & e)774 MatExpr operator - (const Scalar& s, const MatExpr& e)
775 {
776     MatExpr en;
777     e.op->subtract(s, e, en);
778     return en;
779 }
780 
operator -(const MatExpr & e1,const MatExpr & e2)781 MatExpr operator - (const MatExpr& e1, const MatExpr& e2)
782 {
783     MatExpr en;
784     e1.op->subtract(e1, e2, en);
785     return en;
786 }
787 
operator -(const Mat & m)788 MatExpr operator - (const Mat& m)
789 {
790     MatExpr e;
791     MatOp_AddEx::makeExpr(e, m, Mat(), -1, 0);
792     return e;
793 }
794 
operator -(const MatExpr & e)795 MatExpr operator - (const MatExpr& e)
796 {
797     MatExpr en;
798     e.op->subtract(Scalar(0), e, en);
799     return en;
800 }
801 
operator *(const Mat & a,const Mat & b)802 MatExpr operator * (const Mat& a, const Mat& b)
803 {
804     MatExpr e;
805     MatOp_GEMM::makeExpr(e, 0, a, b);
806     return e;
807 }
808 
operator *(const Mat & a,double s)809 MatExpr operator * (const Mat& a, double s)
810 {
811     MatExpr e;
812     MatOp_AddEx::makeExpr(e, a, Mat(), s, 0);
813     return e;
814 }
815 
operator *(double s,const Mat & a)816 MatExpr operator * (double s, const Mat& a)
817 {
818     MatExpr e;
819     MatOp_AddEx::makeExpr(e, a, Mat(), s, 0);
820     return e;
821 }
822 
operator *(const MatExpr & e,const Mat & m)823 MatExpr operator * (const MatExpr& e, const Mat& m)
824 {
825     MatExpr en;
826     e.op->matmul(e, MatExpr(m), en);
827     return en;
828 }
829 
operator *(const Mat & m,const MatExpr & e)830 MatExpr operator * (const Mat& m, const MatExpr& e)
831 {
832     MatExpr en;
833     e.op->matmul(MatExpr(m), e, en);
834     return en;
835 }
836 
operator *(const MatExpr & e,double s)837 MatExpr operator * (const MatExpr& e, double s)
838 {
839     MatExpr en;
840     e.op->multiply(e, s, en);
841     return en;
842 }
843 
operator *(double s,const MatExpr & e)844 MatExpr operator * (double s, const MatExpr& e)
845 {
846     MatExpr en;
847     e.op->multiply(e, s, en);
848     return en;
849 }
850 
operator *(const MatExpr & e1,const MatExpr & e2)851 MatExpr operator * (const MatExpr& e1, const MatExpr& e2)
852 {
853     MatExpr en;
854     e1.op->matmul(e1, e2, en);
855     return en;
856 }
857 
operator /(const Mat & a,const Mat & b)858 MatExpr operator / (const Mat& a, const Mat& b)
859 {
860     MatExpr e;
861     MatOp_Bin::makeExpr(e, '/', a, b);
862     return e;
863 }
864 
operator /(const Mat & a,double s)865 MatExpr operator / (const Mat& a, double s)
866 {
867     MatExpr e;
868     MatOp_AddEx::makeExpr(e, a, Mat(), 1./s, 0);
869     return e;
870 }
871 
operator /(double s,const Mat & a)872 MatExpr operator / (double s, const Mat& a)
873 {
874     MatExpr e;
875     MatOp_Bin::makeExpr(e, '/', a, Mat(), s);
876     return e;
877 }
878 
operator /(const MatExpr & e,const Mat & m)879 MatExpr operator / (const MatExpr& e, const Mat& m)
880 {
881     MatExpr en;
882     e.op->divide(e, MatExpr(m), en);
883     return en;
884 }
885 
operator /(const Mat & m,const MatExpr & e)886 MatExpr operator / (const Mat& m, const MatExpr& e)
887 {
888     MatExpr en;
889     e.op->divide(MatExpr(m), e, en);
890     return en;
891 }
892 
operator /(const MatExpr & e,double s)893 MatExpr operator / (const MatExpr& e, double s)
894 {
895     MatExpr en;
896     e.op->multiply(e, 1./s, en);
897     return en;
898 }
899 
operator /(double s,const MatExpr & e)900 MatExpr operator / (double s, const MatExpr& e)
901 {
902     MatExpr en;
903     e.op->divide(s, e, en);
904     return en;
905 }
906 
operator /(const MatExpr & e1,const MatExpr & e2)907 MatExpr operator / (const MatExpr& e1, const MatExpr& e2)
908 {
909     MatExpr en;
910     e1.op->divide(e1, e2, en);
911     return en;
912 }
913 
operator <(const Mat & a,const Mat & b)914 MatExpr operator < (const Mat& a, const Mat& b)
915 {
916     MatExpr e;
917     MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, b);
918     return e;
919 }
920 
operator <(const Mat & a,double s)921 MatExpr operator < (const Mat& a, double s)
922 {
923     MatExpr e;
924     MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s);
925     return e;
926 }
927 
operator <(double s,const Mat & a)928 MatExpr operator < (double s, const Mat& a)
929 {
930     MatExpr e;
931     MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s);
932     return e;
933 }
934 
operator <=(const Mat & a,const Mat & b)935 MatExpr operator <= (const Mat& a, const Mat& b)
936 {
937     MatExpr e;
938     MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, b);
939     return e;
940 }
941 
operator <=(const Mat & a,double s)942 MatExpr operator <= (const Mat& a, double s)
943 {
944     MatExpr e;
945     MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s);
946     return e;
947 }
948 
operator <=(double s,const Mat & a)949 MatExpr operator <= (double s, const Mat& a)
950 {
951     MatExpr e;
952     MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s);
953     return e;
954 }
955 
operator ==(const Mat & a,const Mat & b)956 MatExpr operator == (const Mat& a, const Mat& b)
957 {
958     MatExpr e;
959     MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, b);
960     return e;
961 }
962 
operator ==(const Mat & a,double s)963 MatExpr operator == (const Mat& a, double s)
964 {
965     MatExpr e;
966     MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s);
967     return e;
968 }
969 
operator ==(double s,const Mat & a)970 MatExpr operator == (double s, const Mat& a)
971 {
972     MatExpr e;
973     MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s);
974     return e;
975 }
976 
operator !=(const Mat & a,const Mat & b)977 MatExpr operator != (const Mat& a, const Mat& b)
978 {
979     MatExpr e;
980     MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, b);
981     return e;
982 }
983 
operator !=(const Mat & a,double s)984 MatExpr operator != (const Mat& a, double s)
985 {
986     MatExpr e;
987     MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s);
988     return e;
989 }
990 
operator !=(double s,const Mat & a)991 MatExpr operator != (double s, const Mat& a)
992 {
993     MatExpr e;
994     MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s);
995     return e;
996 }
997 
operator >=(const Mat & a,const Mat & b)998 MatExpr operator >= (const Mat& a, const Mat& b)
999 {
1000     MatExpr e;
1001     MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, b);
1002     return e;
1003 }
1004 
operator >=(const Mat & a,double s)1005 MatExpr operator >= (const Mat& a, double s)
1006 {
1007     MatExpr e;
1008     MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s);
1009     return e;
1010 }
1011 
operator >=(double s,const Mat & a)1012 MatExpr operator >= (double s, const Mat& a)
1013 {
1014     MatExpr e;
1015     MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s);
1016     return e;
1017 }
1018 
operator >(const Mat & a,const Mat & b)1019 MatExpr operator > (const Mat& a, const Mat& b)
1020 {
1021     MatExpr e;
1022     MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, b);
1023     return e;
1024 }
1025 
operator >(const Mat & a,double s)1026 MatExpr operator > (const Mat& a, double s)
1027 {
1028     MatExpr e;
1029     MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s);
1030     return e;
1031 }
1032 
operator >(double s,const Mat & a)1033 MatExpr operator > (double s, const Mat& a)
1034 {
1035     MatExpr e;
1036     MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s);
1037     return e;
1038 }
1039 
min(const Mat & a,const Mat & b)1040 MatExpr min(const Mat& a, const Mat& b)
1041 {
1042     MatExpr e;
1043     MatOp_Bin::makeExpr(e, 'm', a, b);
1044     return e;
1045 }
1046 
min(const Mat & a,double s)1047 MatExpr min(const Mat& a, double s)
1048 {
1049     MatExpr e;
1050     MatOp_Bin::makeExpr(e, 'n', a, s);
1051     return e;
1052 }
1053 
min(double s,const Mat & a)1054 MatExpr min(double s, const Mat& a)
1055 {
1056     MatExpr e;
1057     MatOp_Bin::makeExpr(e, 'n', a, s);
1058     return e;
1059 }
1060 
max(const Mat & a,const Mat & b)1061 MatExpr max(const Mat& a, const Mat& b)
1062 {
1063     MatExpr e;
1064     MatOp_Bin::makeExpr(e, 'M', a, b);
1065     return e;
1066 }
1067 
max(const Mat & a,double s)1068 MatExpr max(const Mat& a, double s)
1069 {
1070     MatExpr e;
1071     MatOp_Bin::makeExpr(e, 'N', a, s);
1072     return e;
1073 }
1074 
max(double s,const Mat & a)1075 MatExpr max(double s, const Mat& a)
1076 {
1077     MatExpr e;
1078     MatOp_Bin::makeExpr(e, 'N', a, s);
1079     return e;
1080 }
1081 
operator &(const Mat & a,const Mat & b)1082 MatExpr operator & (const Mat& a, const Mat& b)
1083 {
1084     MatExpr e;
1085     MatOp_Bin::makeExpr(e, '&', a, b);
1086     return e;
1087 }
1088 
operator &(const Mat & a,const Scalar & s)1089 MatExpr operator & (const Mat& a, const Scalar& s)
1090 {
1091     MatExpr e;
1092     MatOp_Bin::makeExpr(e, '&', a, s);
1093     return e;
1094 }
1095 
operator &(const Scalar & s,const Mat & a)1096 MatExpr operator & (const Scalar& s, const Mat& a)
1097 {
1098     MatExpr e;
1099     MatOp_Bin::makeExpr(e, '&', a, s);
1100     return e;
1101 }
1102 
operator |(const Mat & a,const Mat & b)1103 MatExpr operator | (const Mat& a, const Mat& b)
1104 {
1105     MatExpr e;
1106     MatOp_Bin::makeExpr(e, '|', a, b);
1107     return e;
1108 }
1109 
operator |(const Mat & a,const Scalar & s)1110 MatExpr operator | (const Mat& a, const Scalar& s)
1111 {
1112     MatExpr e;
1113     MatOp_Bin::makeExpr(e, '|', a, s);
1114     return e;
1115 }
1116 
operator |(const Scalar & s,const Mat & a)1117 MatExpr operator | (const Scalar& s, const Mat& a)
1118 {
1119     MatExpr e;
1120     MatOp_Bin::makeExpr(e, '|', a, s);
1121     return e;
1122 }
1123 
operator ^(const Mat & a,const Mat & b)1124 MatExpr operator ^ (const Mat& a, const Mat& b)
1125 {
1126     MatExpr e;
1127     MatOp_Bin::makeExpr(e, '^', a, b);
1128     return e;
1129 }
1130 
operator ^(const Mat & a,const Scalar & s)1131 MatExpr operator ^ (const Mat& a, const Scalar& s)
1132 {
1133     MatExpr e;
1134     MatOp_Bin::makeExpr(e, '^', a, s);
1135     return e;
1136 }
1137 
operator ^(const Scalar & s,const Mat & a)1138 MatExpr operator ^ (const Scalar& s, const Mat& a)
1139 {
1140     MatExpr e;
1141     MatOp_Bin::makeExpr(e, '^', a, s);
1142     return e;
1143 }
1144 
operator ~(const Mat & a)1145 MatExpr operator ~(const Mat& a)
1146 {
1147     MatExpr e;
1148     MatOp_Bin::makeExpr(e, '~', a, Scalar());
1149     return e;
1150 }
1151 
abs(const Mat & a)1152 MatExpr abs(const Mat& a)
1153 {
1154     MatExpr e;
1155     MatOp_Bin::makeExpr(e, 'a', a, Scalar());
1156     return e;
1157 }
1158 
abs(const MatExpr & e)1159 MatExpr abs(const MatExpr& e)
1160 {
1161     MatExpr en;
1162     e.op->abs(e, en);
1163     return en;
1164 }
1165 
1166 
size() const1167 Size MatExpr::size() const
1168 {
1169     if( isT(*this) || isInv(*this) )
1170         return Size(a.rows, a.cols);
1171     if( isGEMM(*this) )
1172         return Size(b.cols, a.rows);
1173     if( isSolve(*this) )
1174         return Size(b.cols, a.cols);
1175     if( isInitializer(*this) )
1176         return a.size();
1177     return op ? op->size(*this) : Size();
1178 }
1179 
1180 
type() const1181 int MatExpr::type() const
1182 {
1183     if( isInitializer(*this) )
1184         return a.type();
1185     if( isCmp(*this) )
1186         return CV_8U;
1187     return op ? op->type(*this) : -1;
1188 }
1189 
1190 
1191 /////////////////////////////////////////////////////////////////////////////////////////////////////
1192 
assign(const MatExpr & e,Mat & m,int _type) const1193 void MatOp_Identity::assign(const MatExpr& e, Mat& m, int _type) const
1194 {
1195     if( _type == -1 || _type == e.a.type() )
1196         m = e.a;
1197     else
1198     {
1199         CV_Assert( CV_MAT_CN(_type) == e.a.channels() );
1200         e.a.convertTo(m, _type);
1201     }
1202 }
1203 
makeExpr(MatExpr & res,const Mat & m)1204 inline void MatOp_Identity::makeExpr(MatExpr& res, const Mat& m)
1205 {
1206     res = MatExpr(&g_MatOp_Identity, 0, m, Mat(), Mat(), 1, 0);
1207 }
1208 
1209 /////////////////////////////////////////////////////////////////////////////////////////////////////
1210 
assign(const MatExpr & e,Mat & m,int _type) const1211 void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int _type) const
1212 {
1213     Mat temp, &dst = _type == -1 || e.a.type() == _type ? m : temp;
1214     if( e.b.data )
1215     {
1216         if( e.s == Scalar() || !e.s.isReal() )
1217         {
1218             if( e.alpha == 1 )
1219             {
1220                 if( e.beta == 1 )
1221                     cv::add(e.a, e.b, dst);
1222                 else if( e.beta == -1 )
1223                     cv::subtract(e.a, e.b, dst);
1224                 else
1225                     cv::scaleAdd(e.b, e.beta, e.a, dst);
1226             }
1227             else if( e.beta == 1 )
1228             {
1229                 if( e.alpha == -1 )
1230                     cv::subtract(e.b, e.a, dst);
1231                 else
1232                     cv::scaleAdd(e.a, e.alpha, e.b, dst);
1233             }
1234             else
1235                 cv::addWeighted(e.a, e.alpha, e.b, e.beta, 0, dst);
1236 
1237             if( !e.s.isReal() )
1238                 cv::add(dst, e.s, dst);
1239         }
1240         else
1241             cv::addWeighted(e.a, e.alpha, e.b, e.beta, e.s[0], dst);
1242     }
1243     else if( e.s.isReal() && (dst.data != m.data || fabs(e.alpha) != 1))
1244     {
1245         e.a.convertTo(m, _type, e.alpha, e.s[0]);
1246         return;
1247     }
1248     else if( e.alpha == 1 )
1249         cv::add(e.a, e.s, dst);
1250     else if( e.alpha == -1 )
1251         cv::subtract(e.s, e.a, dst);
1252     else
1253     {
1254         e.a.convertTo(dst, e.a.type(), e.alpha);
1255         cv::add(dst, e.s, dst);
1256     }
1257 
1258     if( dst.data != m.data )
1259         dst.convertTo(m, m.type());
1260 }
1261 
1262 
add(const MatExpr & e,const Scalar & s,MatExpr & res) const1263 void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const
1264 {
1265     res = e;
1266     res.s += s;
1267 }
1268 
1269 
subtract(const Scalar & s,const MatExpr & e,MatExpr & res) const1270 void MatOp_AddEx::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) const
1271 {
1272     res = e;
1273     res.alpha = -res.alpha;
1274     res.beta = -res.beta;
1275     res.s = s - res.s;
1276 }
1277 
multiply(const MatExpr & e,double s,MatExpr & res) const1278 void MatOp_AddEx::multiply(const MatExpr& e, double s, MatExpr& res) const
1279 {
1280     res = e;
1281     res.alpha *= s;
1282     res.beta *= s;
1283     res.s *= s;
1284 }
1285 
divide(double s,const MatExpr & e,MatExpr & res) const1286 void MatOp_AddEx::divide(double s, const MatExpr& e, MatExpr& res) const
1287 {
1288     if( isScaled(e) )
1289         MatOp_Bin::makeExpr(res, '/', e.a, Mat(), s/e.alpha);
1290     else
1291         MatOp::divide(s, e, res);
1292 }
1293 
1294 
transpose(const MatExpr & e,MatExpr & res) const1295 void MatOp_AddEx::transpose(const MatExpr& e, MatExpr& res) const
1296 {
1297     if( isScaled(e) )
1298         MatOp_T::makeExpr(res, e.a, e.alpha);
1299     else
1300         MatOp::transpose(e, res);
1301 }
1302 
abs(const MatExpr & e,MatExpr & res) const1303 void MatOp_AddEx::abs(const MatExpr& e, MatExpr& res) const
1304 {
1305     if( (!e.b.data || e.beta == 0) && fabs(e.alpha) == 1 )
1306         MatOp_Bin::makeExpr(res, 'a', e.a, -e.s*e.alpha);
1307     else if( e.b.data && e.alpha + e.beta == 0 && e.alpha*e.beta == -1 )
1308         MatOp_Bin::makeExpr(res, 'a', e.a, e.b);
1309     else
1310         MatOp::abs(e, res);
1311 }
1312 
makeExpr(MatExpr & res,const Mat & a,const Mat & b,double alpha,double beta,const Scalar & s)1313 inline void MatOp_AddEx::makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s)
1314 {
1315     res = MatExpr(&g_MatOp_AddEx, 0, a, b, Mat(), alpha, beta, s);
1316 }
1317 
1318 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1319 
assign(const MatExpr & e,Mat & m,int _type) const1320 void MatOp_Bin::assign(const MatExpr& e, Mat& m, int _type) const
1321 {
1322     Mat temp, &dst = _type == -1 || e.a.type() == _type ? m : temp;
1323 
1324     if( e.flags == '*' )
1325         cv::multiply(e.a, e.b, dst, e.alpha);
1326     else if( e.flags == '/' && e.b.data )
1327         cv::divide(e.a, e.b, dst, e.alpha);
1328     else if( e.flags == '/' && !e.b.data )
1329         cv::divide(e.alpha, e.a, dst );
1330     else if( e.flags == '&' && e.b.data )
1331         bitwise_and(e.a, e.b, dst);
1332     else if( e.flags == '&' && !e.b.data )
1333         bitwise_and(e.a, e.s, dst);
1334     else if( e.flags == '|' && e.b.data )
1335         bitwise_or(e.a, e.b, dst);
1336     else if( e.flags == '|' && !e.b.data )
1337         bitwise_or(e.a, e.s, dst);
1338     else if( e.flags == '^' && e.b.data )
1339         bitwise_xor(e.a, e.b, dst);
1340     else if( e.flags == '^' && !e.b.data )
1341         bitwise_xor(e.a, e.s, dst);
1342     else if( e.flags == '~' && !e.b.data )
1343         bitwise_not(e.a, dst);
1344     else if( e.flags == 'm' )
1345         cv::min(e.a, e.b, dst);
1346     else if( e.flags == 'n' )
1347         cv::min(e.a, e.s[0], dst);
1348     else if( e.flags == 'M' )
1349         cv::max(e.a, e.b, dst);
1350     else if( e.flags == 'N' )
1351         cv::max(e.a, e.s[0], dst);
1352     else if( e.flags == 'a' && e.b.data )
1353         cv::absdiff(e.a, e.b, dst);
1354     else if( e.flags == 'a' && !e.b.data )
1355         cv::absdiff(e.a, e.s, dst);
1356     else
1357         CV_Error(CV_StsError, "Unknown operation");
1358 
1359     if( dst.data != m.data )
1360         dst.convertTo(m, _type);
1361 }
1362 
multiply(const MatExpr & e,double s,MatExpr & res) const1363 void MatOp_Bin::multiply(const MatExpr& e, double s, MatExpr& res) const
1364 {
1365     if( e.flags == '*' || e.flags == '/' )
1366     {
1367         res = e;
1368         res.alpha *= s;
1369     }
1370     else
1371         MatOp::multiply(e, s, res);
1372 }
1373 
divide(double s,const MatExpr & e,MatExpr & res) const1374 void MatOp_Bin::divide(double s, const MatExpr& e, MatExpr& res) const
1375 {
1376     if( e.flags == '/' && (!e.b.data || e.beta == 0) )
1377         MatOp_AddEx::makeExpr(res, e.a, Mat(), s/e.alpha, 0);
1378     else
1379         MatOp::divide(s, e, res);
1380 }
1381 
makeExpr(MatExpr & res,char op,const Mat & a,const Mat & b,double scale)1382 inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale)
1383 {
1384     res = MatExpr(&g_MatOp_Bin, op, a, b, Mat(), scale, b.data ? 1 : 0);
1385 }
1386 
makeExpr(MatExpr & res,char op,const Mat & a,const Scalar & s)1387 inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s)
1388 {
1389     res = MatExpr(&g_MatOp_Bin, op, a, Mat(), Mat(), 1, 0, s);
1390 }
1391 
1392 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1393 
assign(const MatExpr & e,Mat & m,int _type) const1394 void MatOp_Cmp::assign(const MatExpr& e, Mat& m, int _type) const
1395 {
1396     Mat temp, &dst = _type == -1 || _type == CV_8U ? m : temp;
1397 
1398     if( e.b.data )
1399         cv::compare(e.a, e.b, dst, e.flags);
1400     else
1401         cv::compare(e.a, e.alpha, dst, e.flags);
1402 
1403     if( dst.data != m.data )
1404         dst.convertTo(m, _type);
1405 }
1406 
makeExpr(MatExpr & res,int cmpop,const Mat & a,const Mat & b)1407 inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b)
1408 {
1409     res = MatExpr(&g_MatOp_Cmp, cmpop, a, b, Mat(), 1, 1);
1410 }
1411 
makeExpr(MatExpr & res,int cmpop,const Mat & a,double alpha)1412 inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha)
1413 {
1414     res = MatExpr(&g_MatOp_Cmp, cmpop, a, Mat(), Mat(), alpha, 1);
1415 }
1416 
1417 /////////////////////////////////////////////////////////////////////////////////////////////////////////
1418 
assign(const MatExpr & e,Mat & m,int _type) const1419 void MatOp_T::assign(const MatExpr& e, Mat& m, int _type) const
1420 {
1421     Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1422 
1423     cv::transpose(e.a, dst);
1424 
1425     if( dst.data != m.data || e.alpha != 1 )
1426         dst.convertTo(m, _type, e.alpha);
1427 }
1428 
multiply(const MatExpr & e,double s,MatExpr & res) const1429 void MatOp_T::multiply(const MatExpr& e, double s, MatExpr& res) const
1430 {
1431     res = e;
1432     res.alpha *= s;
1433 }
1434 
transpose(const MatExpr & e,MatExpr & res) const1435 void MatOp_T::transpose(const MatExpr& e, MatExpr& res) const
1436 {
1437     if( e.alpha == 1 )
1438         MatOp_Identity::makeExpr(res, e.a);
1439     else
1440         MatOp_AddEx::makeExpr(res, e.a, Mat(), e.alpha, 0);
1441 }
1442 
makeExpr(MatExpr & res,const Mat & a,double alpha)1443 inline void MatOp_T::makeExpr(MatExpr& res, const Mat& a, double alpha)
1444 {
1445     res = MatExpr(&g_MatOp_T, 0, a, Mat(), Mat(), alpha, 0);
1446 }
1447 
1448 /////////////////////////////////////////////////////////////////////////////////////////////////////////
1449 
assign(const MatExpr & e,Mat & m,int _type) const1450 void MatOp_GEMM::assign(const MatExpr& e, Mat& m, int _type) const
1451 {
1452     Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1453 
1454     cv::gemm(e.a, e.b, e.alpha, e.c, e.beta, dst, e.flags);
1455     if( dst.data != m.data )
1456         dst.convertTo(m, _type);
1457 }
1458 
add(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const1459 void MatOp_GEMM::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
1460 {
1461     bool i1 = isIdentity(e1), i2 = isIdentity(e2);
1462     double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
1463 
1464     if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) )
1465         MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0),
1466                              e1.a, e1.b, alpha1, e2.a, alpha2);
1467     else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) )
1468         MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0),
1469                              e2.a, e2.b, alpha2, e1.a, alpha1);
1470     else if( this == e2.op )
1471         MatOp::add(e1, e2, res);
1472     else
1473         e2.op->add(e1, e2, res);
1474 }
1475 
subtract(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const1476 void MatOp_GEMM::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
1477 {
1478     bool i1 = isIdentity(e1), i2 = isIdentity(e2);
1479     double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
1480 
1481     if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) )
1482         MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0),
1483                              e1.a, e1.b, alpha1, e2.a, -alpha2);
1484     else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) )
1485         MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0),
1486                             e2.a, e2.b, -alpha2, e1.a, alpha1);
1487     else if( this == e2.op )
1488         MatOp::subtract(e1, e2, res);
1489     else
1490         e2.op->subtract(e1, e2, res);
1491 }
1492 
multiply(const MatExpr & e,double s,MatExpr & res) const1493 void MatOp_GEMM::multiply(const MatExpr& e, double s, MatExpr& res) const
1494 {
1495     res = e;
1496     res.alpha *= s;
1497     res.beta *= s;
1498 }
1499 
transpose(const MatExpr & e,MatExpr & res) const1500 void MatOp_GEMM::transpose(const MatExpr& e, MatExpr& res) const
1501 {
1502     res = e;
1503     res.flags = (!(e.flags & CV_GEMM_A_T) ? CV_GEMM_B_T : 0) |
1504                 (!(e.flags & CV_GEMM_B_T) ? CV_GEMM_A_T : 0) |
1505                 (!(e.flags & CV_GEMM_C_T) ? CV_GEMM_C_T : 0);
1506     swap(res.a, res.b);
1507 }
1508 
makeExpr(MatExpr & res,int flags,const Mat & a,const Mat & b,double alpha,const Mat & c,double beta)1509 inline void MatOp_GEMM::makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b,
1510                                  double alpha, const Mat& c, double beta)
1511 {
1512     res = MatExpr(&g_MatOp_GEMM, flags, a, b, c, alpha, beta);
1513 }
1514 
1515 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1516 
assign(const MatExpr & e,Mat & m,int _type) const1517 void MatOp_Invert::assign(const MatExpr& e, Mat& m, int _type) const
1518 {
1519     Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1520 
1521     cv::invert(e.a, dst, e.flags);
1522     if( dst.data != m.data )
1523         dst.convertTo(m, _type);
1524 }
1525 
matmul(const MatExpr & e1,const MatExpr & e2,MatExpr & res) const1526 void MatOp_Invert::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
1527 {
1528     if( isInv(e1) && isIdentity(e2) )
1529         MatOp_Solve::makeExpr(res, e1.flags, e1.a, e2.a);
1530     else if( this == e2.op )
1531         MatOp::matmul(e1, e2, res);
1532     else
1533         e2.op->matmul(e1, e2, res);
1534 }
1535 
makeExpr(MatExpr & res,int method,const Mat & m)1536 inline void MatOp_Invert::makeExpr(MatExpr& res, int method, const Mat& m)
1537 {
1538     res = MatExpr(&g_MatOp_Invert, method, m, Mat(), Mat(), 1, 0);
1539 }
1540 
1541 /////////////////////////////////////////////////////////////////////////////////////////////////////////
1542 
assign(const MatExpr & e,Mat & m,int _type) const1543 void MatOp_Solve::assign(const MatExpr& e, Mat& m, int _type) const
1544 {
1545     Mat temp, &dst = _type == -1 || _type == e.a.type() ? m : temp;
1546 
1547     cv::solve(e.a, e.b, dst, e.flags);
1548     if( dst.data != m.data )
1549         dst.convertTo(m, _type);
1550 }
1551 
makeExpr(MatExpr & res,int method,const Mat & a,const Mat & b)1552 inline void MatOp_Solve::makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b)
1553 {
1554     res = MatExpr(&g_MatOp_Solve, method, a, b, Mat(), 1, 1);
1555 }
1556 
1557 //////////////////////////////////////////////////////////////////////////////////////////////////////////
1558 
assign(const MatExpr & e,Mat & m,int _type) const1559 void MatOp_Initializer::assign(const MatExpr& e, Mat& m, int _type) const
1560 {
1561     if( _type == -1 )
1562         _type = e.a.type();
1563 
1564     if( e.a.dims <= 2 )
1565         m.create(e.a.size(), _type);
1566     else
1567         m.create(e.a.dims, e.a.size, _type);
1568 
1569     if( e.flags == 'I' && e.a.dims <= 2 )
1570         setIdentity(m, Scalar(e.alpha));
1571     else if( e.flags == '0' )
1572         m = Scalar();
1573     else if( e.flags == '1' )
1574         m = Scalar(e.alpha);
1575     else
1576         CV_Error(CV_StsError, "Invalid matrix initializer type");
1577 }
1578 
multiply(const MatExpr & e,double s,MatExpr & res) const1579 void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const
1580 {
1581     res = e;
1582     res.alpha *= s;
1583 }
1584 
makeExpr(MatExpr & res,int method,Size sz,int type,double alpha)1585 inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, Size sz, int type, double alpha)
1586 {
1587     res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)0), Mat(), Mat(), alpha, 0);
1588 }
1589 
makeExpr(MatExpr & res,int method,int ndims,const int * sizes,int type,double alpha)1590 inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha)
1591 {
1592     res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)0), Mat(), Mat(), alpha, 0);
1593 }
1594 
1595 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
1596 
t() const1597 MatExpr Mat::t() const
1598 {
1599     MatExpr e;
1600     MatOp_T::makeExpr(e, *this);
1601     return e;
1602 }
1603 
inv(int method) const1604 MatExpr Mat::inv(int method) const
1605 {
1606     MatExpr e;
1607     MatOp_Invert::makeExpr(e, method, *this);
1608     return e;
1609 }
1610 
1611 
mul(InputArray m,double scale) const1612 MatExpr Mat::mul(InputArray m, double scale) const
1613 {
1614     MatExpr e;
1615     if(m.kind() == _InputArray::EXPR)
1616     {
1617         const MatExpr& me = *(const MatExpr*)m.getObj();
1618         me.op->multiply(MatExpr(*this), me, e, scale);
1619     }
1620     else
1621         MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale);
1622     return e;
1623 }
1624 
zeros(int rows,int cols,int type)1625 MatExpr Mat::zeros(int rows, int cols, int type)
1626 {
1627     MatExpr e;
1628     MatOp_Initializer::makeExpr(e, '0', Size(cols, rows), type);
1629     return e;
1630 }
1631 
zeros(Size size,int type)1632 MatExpr Mat::zeros(Size size, int type)
1633 {
1634     MatExpr e;
1635     MatOp_Initializer::makeExpr(e, '0', size, type);
1636     return e;
1637 }
1638 
zeros(int ndims,const int * sizes,int type)1639 MatExpr Mat::zeros(int ndims, const int* sizes, int type)
1640 {
1641     MatExpr e;
1642     MatOp_Initializer::makeExpr(e, '0', ndims, sizes, type);
1643     return e;
1644 }
1645 
ones(int rows,int cols,int type)1646 MatExpr Mat::ones(int rows, int cols, int type)
1647 {
1648     MatExpr e;
1649     MatOp_Initializer::makeExpr(e, '1', Size(cols, rows), type);
1650     return e;
1651 }
1652 
ones(Size size,int type)1653 MatExpr Mat::ones(Size size, int type)
1654 {
1655     MatExpr e;
1656     MatOp_Initializer::makeExpr(e, '1', size, type);
1657     return e;
1658 }
1659 
ones(int ndims,const int * sizes,int type)1660 MatExpr Mat::ones(int ndims, const int* sizes, int type)
1661 {
1662     MatExpr e;
1663     MatOp_Initializer::makeExpr(e, '1', ndims, sizes, type);
1664     return e;
1665 }
1666 
eye(int rows,int cols,int type)1667 MatExpr Mat::eye(int rows, int cols, int type)
1668 {
1669     MatExpr e;
1670     MatOp_Initializer::makeExpr(e, 'I', Size(cols, rows), type);
1671     return e;
1672 }
1673 
eye(Size size,int type)1674 MatExpr Mat::eye(Size size, int type)
1675 {
1676     MatExpr e;
1677     MatOp_Initializer::makeExpr(e, 'I', size, type);
1678     return e;
1679 }
1680 
1681 }
1682 
1683 /* End of file. */
1684