Home | History | Annotate | Download | only in src
      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:
     57     MatOp_Identity() {}
     58     virtual ~MatOp_Identity() {}
     59 
     60     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:
     71     MatOp_AddEx() {}
     72     virtual ~MatOp_AddEx() {}
     73 
     74     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:
     93     MatOp_Bin() {}
     94     virtual ~MatOp_Bin() {}
     95 
     96     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:
    111     MatOp_Cmp() {}
    112     virtual ~MatOp_Cmp() {}
    113 
    114     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:
    126     MatOp_GEMM() {}
    127     virtual ~MatOp_GEMM() {}
    128 
    129     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:
    147     MatOp_Invert() {}
    148     virtual ~MatOp_Invert() {}
    149 
    150     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:
    163     MatOp_T() {}
    164     virtual ~MatOp_T() {}
    165 
    166     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:
    180     MatOp_Solve() {}
    181     virtual ~MatOp_Solve() {}
    182 
    183     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:
    194     MatOp_Initializer() {}
    195     virtual ~MatOp_Initializer() {}
    196 
    197     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 
    206 static MatOp_Initializer* getGlobalMatOpInitializer()
    207 {
    208     static MatOp_Initializer initializer;
    209     return &initializer;
    210 }
    211 
    212 static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identity; }
    213 static inline bool isAddEx(const MatExpr& e) { return e.op == &g_MatOp_AddEx; }
    214 static inline bool isScaled(const MatExpr& e) { return isAddEx(e) && (!e.b.data || e.beta == 0) && e.s == Scalar(); }
    215 static inline bool isBin(const MatExpr& e, char c) { return e.op == &g_MatOp_Bin && e.flags == c; }
    216 static inline bool isCmp(const MatExpr& e) { return e.op == &g_MatOp_Cmp; }
    217 static inline bool isReciprocal(const MatExpr& e) { return isBin(e,'/') && (!e.b.data || e.beta == 0); }
    218 static inline bool isT(const MatExpr& e) { return e.op == &g_MatOp_T; }
    219 static inline bool isInv(const MatExpr& e) { return e.op == &g_MatOp_Invert; }
    220 static inline bool isSolve(const MatExpr& e) { return e.op == &g_MatOp_Solve; }
    221 static inline bool isGEMM(const MatExpr& e) { return e.op == &g_MatOp_GEMM; }
    222 static inline bool isMatProd(const MatExpr& e) { return e.op == &g_MatOp_GEMM && (!e.c.data || e.beta == 0); }
    223 static inline bool isInitializer(const MatExpr& e) { return e.op == getGlobalMatOpInitializer(); }
    224 
    225 /////////////////////////////////////////////////////////////////////////////////////////////////////
    226 
    227 MatOp::MatOp() {}
    228 MatOp::~MatOp() {}
    229 
    230 
    231 bool MatOp::elementWise(const MatExpr& /*expr*/) const
    232 {
    233     return false;
    234 }
    235 
    236 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 
    257 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 
    279 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 
    287 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 
    295 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 
    303 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 
    311 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 
    319 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 
    327 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 
    335 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 
    366 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 
    374 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 
    405 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 
    413 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 
    464 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 
    472 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 
    512 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 
    520 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 
    528 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 
    536 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 
    579 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 
    587 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 
    592 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 
    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 
    603 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 
    610 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 
    617 MatExpr MatExpr::diag(int d) const
    618 {
    619     MatExpr e;
    620     op->diag(*this, d, e);
    621     return e;
    622 }
    623 
    624 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 
    631 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 
    638 Mat MatExpr::cross(const Mat& m) const
    639 {
    640     return ((Mat)*this).cross(m);
    641 }
    642 
    643 double MatExpr::dot(const Mat& m) const
    644 {
    645     return ((Mat)*this).dot(m);
    646 }
    647 
    648 MatExpr MatExpr::t() const
    649 {
    650     MatExpr e;
    651     op->transpose(*this, e);
    652     return e;
    653 }
    654 
    655 MatExpr MatExpr::inv(int method) const
    656 {
    657     MatExpr e;
    658     op->invert(*this, method, e);
    659     return e;
    660 }
    661 
    662 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 
    669 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    788 MatExpr operator - (const Mat& m)
    789 {
    790     MatExpr e;
    791     MatOp_AddEx::makeExpr(e, m, Mat(), -1, 0);
    792     return e;
    793 }
    794 
    795 MatExpr operator - (const MatExpr& e)
    796 {
    797     MatExpr en;
    798     e.op->subtract(Scalar(0), e, en);
    799     return en;
    800 }
    801 
    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 
    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 
    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 
    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 
    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 
    837 MatExpr operator * (const MatExpr& e, double s)
    838 {
    839     MatExpr en;
    840     e.op->multiply(e, s, en);
    841     return en;
    842 }
    843 
    844 MatExpr operator * (double s, const MatExpr& e)
    845 {
    846     MatExpr en;
    847     e.op->multiply(e, s, en);
    848     return en;
    849 }
    850 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    900 MatExpr operator / (double s, const MatExpr& e)
    901 {
    902     MatExpr en;
    903     e.op->divide(s, e, en);
    904     return en;
    905 }
    906 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1145 MatExpr operator ~(const Mat& a)
   1146 {
   1147     MatExpr e;
   1148     MatOp_Bin::makeExpr(e, '~', a, Scalar());
   1149     return e;
   1150 }
   1151 
   1152 MatExpr abs(const Mat& a)
   1153 {
   1154     MatExpr e;
   1155     MatOp_Bin::makeExpr(e, 'a', a, Scalar());
   1156     return e;
   1157 }
   1158 
   1159 MatExpr abs(const MatExpr& e)
   1160 {
   1161     MatExpr en;
   1162     e.op->abs(e, en);
   1163     return en;
   1164 }
   1165 
   1166 
   1167 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 
   1181 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 
   1193 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 
   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 
   1211 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 
   1263 void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const
   1264 {
   1265     res = e;
   1266     res.s += s;
   1267 }
   1268 
   1269 
   1270 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 
   1278 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 
   1286 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 
   1295 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 
   1303 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 
   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 
   1320 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 
   1363 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 
   1374 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 
   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 
   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 
   1394 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 
   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 
   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 
   1419 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 
   1429 void MatOp_T::multiply(const MatExpr& e, double s, MatExpr& res) const
   1430 {
   1431     res = e;
   1432     res.alpha *= s;
   1433 }
   1434 
   1435 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 
   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 
   1450 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 
   1459 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 
   1476 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 
   1493 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 
   1500 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 
   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 
   1517 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 
   1526 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 
   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 
   1543 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 
   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 
   1559 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 
   1579 void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const
   1580 {
   1581     res = e;
   1582     res.alpha *= s;
   1583 }
   1584 
   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 
   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 
   1597 MatExpr Mat::t() const
   1598 {
   1599     MatExpr e;
   1600     MatOp_T::makeExpr(e, *this);
   1601     return e;
   1602 }
   1603 
   1604 MatExpr Mat::inv(int method) const
   1605 {
   1606     MatExpr e;
   1607     MatOp_Invert::makeExpr(e, method, *this);
   1608     return e;
   1609 }
   1610 
   1611 
   1612 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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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