moved the matrix expressions from mat.hpp to matop.cpp. That should improve build...
authorVadim Pisarevsky <no@email>
Tue, 21 Sep 2010 15:15:44 +0000 (15:15 +0000)
committerVadim Pisarevsky <no@email>
Tue, 21 Sep 2010 15:15:44 +0000 (15:15 +0000)
modules/core/include/opencv2/core/core.hpp
modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/operations.hpp
modules/core/src/matop.cpp [new file with mode: 0644]
tests/cv/src/operations.cpp

index 51dc082..0103fc5 100644 (file)
@@ -86,23 +86,8 @@ typedef std::basic_string<wchar_t> WString;
 
 class Mat;
 class MatND;
-template<typename M> class CV_EXPORTS MatExpr_Base_;
-typedef MatExpr_Base_<Mat> MatExpr_Base;
-template<typename E, typename M> class MatExpr_;
-template<typename A1, typename M, typename Op> class MatExpr_Op1_;
-template<typename A1, typename A2, typename M, typename Op> class MatExpr_Op2_;
-template<typename A1, typename A2, typename A3, typename M, typename Op> class MatExpr_Op3_;
-template<typename A1, typename A2, typename A3, typename A4,
-typename M, typename Op> class MatExpr_Op4_;
-template<typename A1, typename A2, typename A3, typename A4,
-typename A5, typename M, typename Op> class MatExpr_Op5_;
-template<typename M> class CV_EXPORTS MatOp_DivRS_;
-template<typename M> class CV_EXPORTS MatOp_Inv_;
-template<typename M> class CV_EXPORTS MatOp_MulDiv_;
-template<typename M> class CV_EXPORTS MatOp_Repeat_;
-template<typename M> class CV_EXPORTS MatOp_Set_;
-template<typename M> class CV_EXPORTS MatOp_Scale_;
-template<typename M> class CV_EXPORTS MatOp_T_;
+class CV_EXPORTS MatExpr;
+class CV_EXPORTS MatOp_Base;
 
 template<typename _Tp> class CV_EXPORTS MatIterator_;
 template<typename _Tp> class CV_EXPORTS MatConstIterator_;
@@ -928,7 +913,11 @@ public:
     //! another helper conversion method. \see cvScalarToRawData
     template<typename T2> void convertTo(T2* buf, int channels, int unroll_to=0) const;
     
+    // returns (v0, -v1, -v2, -v3)
     Scalar_<_Tp> conj() const;
+    
+    // returns true iff v1 == v2 == v3 == 0
+    bool isReal() const;
 };
 
 typedef Scalar_<double> Scalar;
@@ -1244,9 +1233,6 @@ protected:
 
 //////////////////////////////// Mat ////////////////////////////////
 
-typedef MatExpr_<MatExpr_Op4_<Size, int, Scalar,
-    int, Mat, MatOp_Set_<Mat> >, Mat> MatExpr_Initializer;
-    
 enum { MAGIC_MASK=0xFFFF0000, TYPE_MASK=0x00000FFF, DEPTH_MASK=7 };
 
 static inline size_t getElemSize(int type) { return CV_ELEM_SIZE(type); }
@@ -1500,15 +1486,11 @@ public:
     template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt);
     //! builds matrix from comma initializer
     template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);
-    //! helper constructor to compile matrix expressions
-    Mat(const MatExpr_Base& expr);
     //! destructor - calls release()
     ~Mat();
     //! assignment operators
     Mat& operator = (const Mat& m);
-    Mat& operator = (const MatExpr_Base& expr);
-
-    operator MatExpr_<Mat, Mat>() const;
+    Mat& operator = (const MatExpr& expr);
 
     //! returns a new matrix header for the specified row
     Mat row(int y) const;
@@ -1549,18 +1531,12 @@ public:
     Mat reshape(int _cn, int _rows=0) const;
 
     //! matrix transposition by means of matrix expressions
-    MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat>
-    t() const;
+    MatExpr t() const;
     //! matrix inversion by means of matrix expressions
-    MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat>
-        inv(int method=DECOMP_LU) const;
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
+    MatExpr inv(int method=DECOMP_LU) const;
     //! per-element matrix multiplication by means of matrix expressions
-    mul(const Mat& m, double scale=1) const;
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>& m, double scale=1) const;
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>    
-    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat>& m, double scale=1) const;
+    MatExpr mul(const Mat& m, double scale=1) const;
+    MatExpr mul(const MatExpr& m, double scale=1) const;
     
     //! computes cross-product of 2 3D vectors
     Mat cross(const Mat& m) const;
@@ -1568,12 +1544,12 @@ public:
     double dot(const Mat& m) const;
 
     //! Matlab-style matrix initialization
-    static MatExpr_Initializer zeros(int rows, int cols, int type);
-    static MatExpr_Initializer zeros(Size size, int type);
-    static MatExpr_Initializer ones(int rows, int cols, int type);
-    static MatExpr_Initializer ones(Size size, int type);
-    static MatExpr_Initializer eye(int rows, int cols, int type);
-    static MatExpr_Initializer eye(Size size, int type);
+    static MatExpr zeros(int rows, int cols, int type);
+    static MatExpr zeros(Size size, int type);
+    static MatExpr ones(int rows, int cols, int type);
+    static MatExpr ones(Size size, int type);
+    static MatExpr eye(int rows, int cols, int type);
+    static MatExpr eye(Size size, int type);
 
     //! allocates new matrix data unless the matrix already has specified size and type.
     // previous data is unreferenced if needed.
@@ -2301,8 +2277,6 @@ public:
     Mat_(const Mat_& m, const Range& rowRange, const Range& colRange);
     //! selects a submatrix
     Mat_(const Mat_& m, const Rect& roi);
-    //! to support complex matrix expressions
-    Mat_(const MatExpr_Base& expr);
     //! makes a matrix out of Vec, std::vector, Point_ or Point3_. The matrix will have a single column
     explicit Mat_(const vector<_Tp>& vec, bool copyData=false);
     template<int n> explicit Mat_(const Vec<_Tp, n>& vec, bool copyData=true);
@@ -2329,7 +2303,7 @@ public:
     //! cross-product
     Mat_ cross(const Mat_& m) const;
     //! to support complex matrix expressions
-    Mat_& operator = (const MatExpr_Base& expr);
+    Mat_& operator = (const MatExpr& expr);
     //! data type conversion
     template<typename T2> operator Mat_<T2>() const;
     //! overridden forms of Mat::row() etc.
@@ -2338,19 +2312,6 @@ public:
     Mat_ diag(int d=0) const;
     Mat_ clone() const;
 
-    //! transposition, inversion, per-element multiplication
-    MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat> t() const;
-    MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat> inv(int method=DECOMP_LU) const;
-
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-    mul(const Mat_& m, double scale=1) const;
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat,
-        MatOp_Scale_<Mat> >, Mat>& m, double scale=1) const;
-    MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>    
-    mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat,
-        MatOp_DivRS_<Mat> >, Mat>& m, double scale=1) const;
-
     //! overridden forms of Mat::elemSize() etc.
     size_t elemSize() const;
     size_t elemSize1() const;
@@ -2362,12 +2323,12 @@ public:
     size_t stepT() const;
 
     //! overridden forms of Mat::zeros() etc. Data type is omitted, of course
-    static MatExpr_Initializer zeros(int rows, int cols);
-    static MatExpr_Initializer zeros(Size size);
-    static MatExpr_Initializer ones(int rows, int cols);
-    static MatExpr_Initializer ones(Size size);
-    static MatExpr_Initializer eye(int rows, int cols);
-    static MatExpr_Initializer eye(Size size);
+    static MatExpr zeros(int rows, int cols);
+    static MatExpr zeros(Size size);
+    static MatExpr ones(int rows, int cols);
+    static MatExpr ones(Size size);
+    static MatExpr eye(int rows, int cols);
+    static MatExpr eye(Size size);
 
     //! some more overriden methods
     Mat_ reshape(int _rows) const;
@@ -2386,9 +2347,6 @@ public:
     _Tp& operator ()(int i);
     const _Tp& operator ()(int i) const;
 
-    //! to support matrix expressions
-    operator MatExpr_<Mat, Mat>() const;
-    
     //! conversion to vector.
     operator vector<_Tp>() const;
     //! conversion to Vec
@@ -2541,8 +2499,7 @@ template<typename _Tp> class CV_EXPORTS MatOp_Iter_;
  Mat R = (Mat_<double>(2,2) << a, -b, b, a);
  \endcode
 */ 
-template<typename _Tp> class CV_EXPORTS MatCommaInitializer_ :
-    public MatExpr_<MatExpr_Op1_<MatIterator_<_Tp>, Mat_<_Tp>, MatOp_Iter_<_Tp> >, Mat_<_Tp> >
+template<typename _Tp> class CV_EXPORTS MatCommaInitializer_
 {
 public:
     //! the constructor, created by "matrix << firstValue" operator, where matrix is cv::Mat
@@ -2553,7 +2510,10 @@ public:
     //operator Mat_<_Tp>() const;
     //! another form of conversion operator
     Mat_<_Tp> operator *() const;
-    void assignTo(Mat& m, int type=-1) const;
+    operator Mat_<_Tp>() const;
+    virtual void assignTo(Mat& m, int type=-1) const;
+protected:
+    MatIterator_<_Tp> it;
 };
 
 
index 1d715e0..40cf91f 100644 (file)
@@ -317,7 +317,7 @@ inline Mat& Mat::operator = (const Mat& m)
     }
     return *this;
 }
-
+    
 inline Mat Mat::row(int y) const { return Mat(*this, Range(y, y+1), Range::all()); }
 inline Mat Mat::col(int x) const { return Mat(*this, Range::all(), Range(x, x+1)); }
 inline Mat Mat::rowRange(int startrow, int endrow) const
@@ -943,2248 +943,469 @@ process( const Mat_<T1>& m1, const Mat_<T2>& m2, Mat_<T3>& m3, Op op )
     }
 }
 
-template<typename M> class CV_EXPORTS MatExpr_Base_
-{
+
+class CV_EXPORTS MatOp
+{    
 public:
-    MatExpr_Base_() {}
-    virtual ~MatExpr_Base_() {}
-    virtual void assignTo(M& m, int type=-1) const = 0;
+    MatOp() {};
+    virtual ~MatOp() {};
+    
+    virtual bool elementWise(const MatExpr& expr) const;
+    virtual void assign(const MatExpr& expr, Mat& m, int type=-1) const = 0;
+    virtual void roi(const MatExpr& expr, const Range& rowRange,
+                     const Range& colRange, MatExpr& res) const;
+    virtual void diag(const MatExpr& expr, int d, MatExpr& res) const;
+    virtual void augAssignAdd(const MatExpr& expr, Mat& m) const;
+    virtual void augAssignSubtract(const MatExpr& expr, Mat& m) const;
+    virtual void augAssignMultiply(const MatExpr& expr, Mat& m) const;
+    virtual void augAssignDivide(const MatExpr& expr, Mat& m) const;
+    virtual void augAssignAnd(const MatExpr& expr, Mat& m) const;
+    virtual void augAssignOr(const MatExpr& expr, Mat& m) const;
+    virtual void augAssignXor(const MatExpr& expr, Mat& m) const;
+    
+    virtual void add(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    virtual void add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const;
+    
+    virtual void subtract(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    virtual void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const;
+    
+    virtual void multiply(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale=1) const;
+    virtual void multiply(const MatExpr& expr1, double s, MatExpr& res) const;
+    
+    virtual void divide(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale=1) const;
+    virtual void divide(double s, const MatExpr& expr, MatExpr& res) const;
+        
+    virtual void abs(const MatExpr& expr, MatExpr& res) const;
+    
+    virtual void transpose(const MatExpr& expr, MatExpr& res) const;
+    virtual void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    virtual void invert(const MatExpr& expr, int method, MatExpr& res) const;
 };
 
-template<typename E, typename M> class CV_EXPORTS MatExpr_ : public MatExpr_Base_<M>
+    
+class CV_EXPORTS MatExpr
 {
 public:
-    MatExpr_(const E& _e) : e(_e) {}
-    ~MatExpr_() {}
-    operator M() const { return (M)e; }
-    void assignTo(M& m, int type=-1) const { e.assignTo(m, type); }
-
-    M row(int y) const { return ((M)e).row(y); }
-    M col(int x) const { return ((M)e).col(x); }
-    M diag(int d=0) const { return ((M)e).diag(d); }
-
-    M operator()( const Range& rowRange, const Range& colRange ) const
-    { return ((M)e)(rowRange, colRange); }
-    M operator()( const Rect& roi ) const { return ((M)e)(roi); }
-
-    M cross(const M& m) const { return ((M)e).cross(m); }
-    double dot(const M& m) const { return ((M)e).dot(m); }
-
-    MatExpr_<MatExpr_Op2_<M, double, M, MatOp_T_<Mat> >, M> t() const
-    { return ((M)e).t(); }
-    MatExpr_<MatExpr_Op2_<M, int, M, MatOp_Inv_<Mat> >, M> inv(int method=DECOMP_LU) const
-    { return ((M)e).inv(method); }
-
-    MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-    mul(const M& m, double scale=1) const
-    { return ((M)e).mul(m, scale); }
-    template<typename A> MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M >
-    mul(const MatExpr_<A, M>& m, double scale=1) const
-    { return ((M)e).mul(m, scale); }
-
-    E e;
+    MatExpr() : op(0), flags(0), a(Mat()), b(Mat()), c(Mat()), alpha(0), beta(0), s(Scalar()) {}
+    MatExpr(const MatOp* _op, int _flags, const Mat& _a=Mat(), const Mat& _b=Mat(),
+            const Mat& _c=Mat(), double _alpha=1, double _beta=1, const Scalar& _s=Scalar())
+        : op(_op), flags(_flags), a(_a), b(_b), c(_c), alpha(_alpha), beta(_beta), s(_s) {}
+    explicit MatExpr(const Mat& m);
+    operator Mat() const
+    {
+        Mat m;
+        op->assign(*this, m);
+        return m;
+    }
+    
+    template<typename _Tp> operator Mat_<_Tp>() const
+    {
+        Mat_<_Tp> m;
+        op->assign(*this, m, DataType<_Tp>::type);
+        return m;
+    }
+    
+    MatExpr row(int y) const;
+    MatExpr col(int x) const;
+    MatExpr diag(int d=0) const;
+    MatExpr operator()( const Range& rowRange, const Range& colRange ) const;
+    MatExpr operator()( const Rect& roi ) const;
+    
+    Mat cross(const Mat& m) const;
+    double dot(const Mat& m) const;
+    
+    MatExpr t() const;
+    MatExpr inv(int method = DECOMP_LU) const;
+    MatExpr mul(const MatExpr& e, double scale=1) const;
+    MatExpr mul(const Mat& m, double scale=1) const;
+    
+    const MatOp* op;
+    int flags;
+    
+    Mat a, b, c;
+    double alpha, beta;
+    Scalar s;
 };
+    
+
+CV_EXPORTS MatExpr operator + (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator + (const Mat& a, const Scalar& s);
+CV_EXPORTS MatExpr operator + (const Scalar& s, const Mat& a);
+CV_EXPORTS MatExpr operator + (const MatExpr& e, const Mat& m);
+CV_EXPORTS MatExpr operator + (const Mat& m, const MatExpr& e);
+CV_EXPORTS MatExpr operator + (const MatExpr& e, const Scalar& s);
+CV_EXPORTS MatExpr operator + (const Scalar& s, const MatExpr& e);
+CV_EXPORTS MatExpr operator + (const MatExpr& e1, const MatExpr& e2);
+
+CV_EXPORTS MatExpr operator - (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator - (const Mat& a, const Scalar& s);
+CV_EXPORTS MatExpr operator - (const Scalar& s, const Mat& a);
+CV_EXPORTS MatExpr operator - (const MatExpr& e, const Mat& m);
+CV_EXPORTS MatExpr operator - (const Mat& m, const MatExpr& e);
+CV_EXPORTS MatExpr operator - (const MatExpr& e, const Scalar& s);
+CV_EXPORTS MatExpr operator - (const Scalar& s, const MatExpr& e);
+CV_EXPORTS MatExpr operator - (const MatExpr& e1, const MatExpr& e2);
+
+CV_EXPORTS MatExpr operator - (const Mat& m);
+CV_EXPORTS MatExpr operator - (const MatExpr& e);
+
+CV_EXPORTS MatExpr operator * (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator * (const Mat& a, double s);
+CV_EXPORTS MatExpr operator * (double s, const Mat& a);
+CV_EXPORTS MatExpr operator * (const MatExpr& e, const Mat& m);
+CV_EXPORTS MatExpr operator * (const Mat& m, const MatExpr& e);
+CV_EXPORTS MatExpr operator * (const MatExpr& e, double s);
+CV_EXPORTS MatExpr operator * (double s, const MatExpr& e);
+CV_EXPORTS MatExpr operator * (const MatExpr& e1, const MatExpr& e2);
+    
+CV_EXPORTS MatExpr operator / (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator / (const Mat& a, double s);
+CV_EXPORTS MatExpr operator / (double s, const Mat& a);
+CV_EXPORTS MatExpr operator / (const MatExpr& e, const Mat& m);
+CV_EXPORTS MatExpr operator / (const Mat& m, const MatExpr& e);
+CV_EXPORTS MatExpr operator / (const MatExpr& e, double s);
+CV_EXPORTS MatExpr operator / (double s, const MatExpr& e);
+CV_EXPORTS MatExpr operator / (const MatExpr& e1, const MatExpr& e2);    
+
+CV_EXPORTS MatExpr operator < (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator < (const Mat& a, double s);
+CV_EXPORTS MatExpr operator < (double s, const Mat& a);
+
+CV_EXPORTS MatExpr operator <= (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator <= (const Mat& a, double s);
+CV_EXPORTS MatExpr operator <= (double s, const Mat& a);
+
+CV_EXPORTS MatExpr operator == (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator == (const Mat& a, double s);
+CV_EXPORTS MatExpr operator == (double s, const Mat& a);
+
+CV_EXPORTS MatExpr operator != (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator != (const Mat& a, double s);
+CV_EXPORTS MatExpr operator != (double s, const Mat& a);
+
+CV_EXPORTS MatExpr operator >= (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator >= (const Mat& a, double s);
+CV_EXPORTS MatExpr operator >= (double s, const Mat& a);
+
+CV_EXPORTS MatExpr operator > (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator > (const Mat& a, double s);
+CV_EXPORTS MatExpr operator > (double s, const Mat& a);    
+    
+CV_EXPORTS MatExpr min(const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr min(const Mat& a, double s);
+CV_EXPORTS MatExpr min(double s, const Mat& a);
 
+CV_EXPORTS MatExpr max(const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr max(const Mat& a, double s);
+CV_EXPORTS MatExpr max(double s, const Mat& a);
 
-inline Mat::Mat(const MatExpr_Base& expr)
- : flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
+template<typename _Tp> static inline MatExpr min(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
 {
-    expr.assignTo(*this);
+    return cv::min((const Mat&)a, (const Mat&)b);
 }
 
-inline Mat& Mat::operator = (const MatExpr_Base& expr)
+template<typename _Tp> static inline MatExpr min(const Mat_<_Tp>& a, double s)
 {
-    expr.assignTo(*this);
-    return *this;
+    return cv::min((const Mat&)a, s);
 }
 
-template<typename _Tp> inline Mat_<_Tp>::Mat_(const MatExpr_Base& e) : Mat()
+template<typename _Tp> static inline MatExpr min(double s, const Mat_<_Tp>& a)
 {
-    e.assignTo(*this, DataType<_Tp>::type);
-}
+    return cv::min((const Mat&)a, s);
+}    
 
-template<typename _Tp> inline Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr_Base& e)
+template<typename _Tp> static inline MatExpr max(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
 {
-    e.assignTo(*this, DataType<_Tp>::type);
-    return *this;
+    return cv::max((const Mat&)a, (const Mat&)b);
 }
 
-template<typename _Tp> inline Mat_<_Tp>::operator MatExpr_<Mat, Mat>() const
-{ return MatExpr_<Mat, Mat>(*this); }
-
-inline Mat::operator MatExpr_<Mat, Mat>() const
-{ return MatExpr_<Mat, Mat>(*this); }
-
-template<typename M> class CV_EXPORTS MatOp_Sub_
+template<typename _Tp> static inline MatExpr max(const Mat_<_Tp>& a, double s)
 {
-public:
-    MatOp_Sub_() {}
-
-    static void apply(const M& a, const M& b, M& c, int type=-1)
-    {
-        if( type == a.type() || type < 0 )
-        {
-            subtract( a, b, c );
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+    return cv::max((const Mat&)a, s);
+}
 
-template<typename M> class CV_EXPORTS MatOp_Scale_
+template<typename _Tp> static inline MatExpr max(double s, const Mat_<_Tp>& a)
 {
-public:
-    MatOp_Scale_() {}
+    return cv::max((const Mat&)a, s);
+}        
+    
+CV_EXPORTS MatExpr operator & (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator & (const Mat& a, const Scalar& s);
+CV_EXPORTS MatExpr operator & (const Scalar& s, const Mat& a);
 
-    static void apply(const M& a, double alpha, M& c, int type=-1)
-    {
-        a.convertTo(c, type, alpha, 0);
-    }
-};
+CV_EXPORTS MatExpr operator | (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator | (const Mat& a, const Scalar& s);
+CV_EXPORTS MatExpr operator | (const Scalar& s, const Mat& a);
 
-template<typename M> class CV_EXPORTS MatOp_ScaleAddS_
-{
-public:
-    MatOp_ScaleAddS_() {}
+CV_EXPORTS MatExpr operator ^ (const Mat& a, const Mat& b);
+CV_EXPORTS MatExpr operator ^ (const Mat& a, const Scalar& s);
+CV_EXPORTS MatExpr operator ^ (const Scalar& s, const Mat& a);
 
-    static void apply(const M& a, double alpha, double beta, M& c, int type=-1)
-    {
-        a.convertTo(c, type, alpha, beta);
-    }
-};
+CV_EXPORTS MatExpr operator ~(const Mat& m);
+    
+CV_EXPORTS MatExpr abs(const Mat& m);
+CV_EXPORTS MatExpr abs(const MatExpr& e);
+    
+template<typename _Tp> static inline MatExpr abs(const Mat_<_Tp>& m)
+{
+    return cv::abs((const Mat&)m);
+}
 
-template<typename M> class CV_EXPORTS MatOp_AddS_
+////////////////////////////// Augmenting algebraic operations //////////////////////////////////
+    
+inline Mat& Mat::operator = (const MatExpr& e)
 {
-public:
-    MatOp_AddS_() {}
+    e.op->assign(e, *this);
+    return *this;
+}    
 
-    static void apply(const M& a, const Scalar& s, M& c, int type=-1)
-    {
-        if( type == a.type() || type < 0 )
-        {
-            add(a, s, c);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, s, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> Mat_<_Tp>& Mat_<_Tp>::operator = (const MatExpr& e)
+{
+    e.op->assign(e, *this, DataType<_Tp>::type);
+    return *this;
+}
 
-template<typename M> class CV_EXPORTS MatOp_AddEx_
+static inline Mat& operator += (const Mat& a, const Mat& b)
 {
-public:
-    MatOp_AddEx_() {}
+    add(a, b, (Mat&)a);
+    return (Mat&)a;
+}
 
-    static void apply(const M& a, double alpha, const M& b,
-                      double beta, double gamma, M& c, int type=-1)
-    {
-        if( type == a.type() || type < 0 )
-        {
-            addWeighted(a, alpha, b, beta, gamma, c);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, alpha, b, beta, gamma, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+static inline Mat& operator += (const Mat& a, const Scalar& s)
+{
+    add(a, s, (Mat&)a);
+    return (Mat&)a;
+}    
 
-template<typename M> class CV_EXPORTS MatOp_Bin_
+template<typename _Tp> static inline
+Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
 {
-public:
-    MatOp_Bin_() {}
+    add(a, b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}
 
-    static void apply(const M& a, const M& b, int _op, M& c, int type=-1)
-    {
-        char op = (char)_op;
-        if( type == a.type() || type < 0 )
-        {
-            if( op == '&' )
-                bitwise_and( a, b, c );
-            else if( op == '|' )
-                bitwise_or( a, b, c );
-            else if( op == '^' )
-                bitwise_xor( a, b, c );
-            else if( op == 'm' )
-                min( a, b, c );
-            else if( op == 'M' )
-                max( a, b, c );
-            else if( op == 'a' )
-                absdiff( a, b, c );
-            else
-                assert(0);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, op, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Scalar& s)
+{
+    add(a, s, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}    
 
-template<typename M> class CV_EXPORTS MatOp_BinS_
+static inline Mat& operator += (const Mat& a, const MatExpr& b)
 {
-public:
-    MatOp_BinS_() {}
+    b.op->augAssignAdd(b, (Mat&)a); 
+    return (Mat&)a;
+}
 
-    static void apply(const M& a, const Scalar& s, int _op, M& c, int type=-1)
-    {
-        char op = (char)_op;
-        if( type == a.type() || type < 0 )
-        {
-            if( op == '&' )
-                bitwise_and( a, s, c );
-            else if( op == '|' )
-                bitwise_or( a, s, c );
-            else if( op == '^' )
-                bitwise_xor( a, s, c );
-            else if( op == 'm' )
-                min( a, s[0], c );
-            else if( op == 'M' )
-                max( a, s[0], c );
-            else if( op == 'a' )
-                absdiff( a, s, c );
-            else if( op == '~' )
-                bitwise_not( a, c );
-            else
-                assert(0);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, s, op, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const MatExpr& b)
+{
+    b.op->augAssignAdd(b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}
+    
+static inline Mat& operator -= (const Mat& a, const Mat& b)
+{
+    subtract(a, b, (Mat&)a);
+    return (Mat&)a;
+}
 
-template<typename M> class CV_EXPORTS MatOp_T_
+static inline Mat& operator -= (const Mat& a, const Scalar& s)
 {
-public:
-    MatOp_T_() {}
+    subtract(a, s, (Mat&)a);
+    return (Mat&)a;
+}    
 
-    static void apply(const M& a, double scale, M& c, int type=-1)
-    {
-        if( type == a.type() || type < 0 )
-        {
-            transpose(a, c);
-            if( fabs(scale - 1) > DBL_EPSILON )
-                c.convertTo(c, -1, scale, 0);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, scale, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
+{
+    subtract(a, b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}
 
+template<typename _Tp> static inline
+Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Scalar& s)
+{
+    subtract(a, s, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}    
 
-template<typename M> class CV_EXPORTS MatOp_MatMul_
+static inline Mat& operator -= (const Mat& a, const MatExpr& b)
 {
-public:
-    MatOp_MatMul_() {}
+    b.op->augAssignSubtract(b, (Mat&)a); 
+    return (Mat&)a;
+}
 
-    static void apply(const M& a, const M& b, double scale, int flags, M& c, int type=-1)
-    {
-        if( type == a.type() || type < 0 )
-        {
-            gemm(a, b, scale, Mat(), 0, c, flags);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, scale, flags, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const MatExpr& b)
+{
+    b.op->augAssignSubtract(b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}    
 
+static inline Mat& operator *= (const Mat& a, const Mat& b)
+{
+    gemm(a, b, 1, Mat(), 0, (Mat&)a, 0);
+    return (Mat&)a;
+}
 
-template<typename M> class CV_EXPORTS MatOp_MatMulAdd_
+static inline Mat& operator *= (const Mat& a, double s)
 {
-public:
-    MatOp_MatMulAdd_() {}
+    a.convertTo((Mat&)a, -1, s);
+    return (Mat&)a;
+}    
 
-    static void apply(const M& a, const M& b, double alpha,
-        const M& c, double beta, int flags, M& d, int type=-1)
-    {
-        if( type == a.type() || type < 0 )
-        {
-            gemm(a, b, alpha, c, beta, d, flags);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, alpha, c, beta, flags, temp);
-            temp.convertTo(d, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
+{
+    gemm(a, b, 1, Mat(), 0, (Mat&)a, 0);
+    return (Mat_<_Tp>&)a;
+}
 
+template<typename _Tp> static inline
+Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, double s)
+{
+    a.convertTo((Mat&)a, -1, s);
+    return (Mat_<_Tp>&)a;
+}    
 
-template<typename M> class CV_EXPORTS MatOp_Cmp_
+static inline Mat& operator *= (const Mat& a, const MatExpr& b)
 {
-public:
-    MatOp_Cmp_() {}
+    b.op->augAssignMultiply(b, (Mat&)a); 
+    return (Mat&)a;
+}
 
-    static void apply(const M& a, const M& b, int op, M& c, int type=-1)
-    {
-        if( type == CV_8UC1 || type == -1 )
-        {
-            compare(a, b, c, op);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, op, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const MatExpr& b)
+{
+    b.op->augAssignMultiply(b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}    
+    
+static inline Mat& operator /= (const Mat& a, const Mat& b)
+{
+    divide(a, b, (Mat&)a);
+    return (Mat&)a;
+}
 
-template<typename M> class CV_EXPORTS MatOp_CmpS_
+static inline Mat& operator /= (const Mat& a, double s)
 {
-public:
-    MatOp_CmpS_() {}
+    a.convertTo((Mat&)a, -1, 1./s);
+    return (Mat&)a;
+}    
 
-    static void apply(const M& a, double alpha, int op, M& c, int type=-1)
-    {
-        if( type == CV_8UC1 || type == -1 )
-        {
-            compare(a, alpha, c, op);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, alpha, op, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+template<typename _Tp> static inline
+Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
+{
+    divide(a, b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}
 
-template<typename M> class CV_EXPORTS MatOp_MulDiv_
+template<typename _Tp> static inline
+Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, double s)
 {
-public:
-    MatOp_MulDiv_() {}
+    a.convertTo((Mat&)a, -1, 1./s);
+    return (Mat_<_Tp>&)a;
+}    
 
-    static void apply(const M& a, const M& b, double alpha, char op, M& c, int type=-1)
-    {
-        if( type == a.type() || type == -1 )
-        {
-            if( op == '*' )
-                multiply( a, b, c, alpha );
-            else
-                divide( a, b, c, alpha );
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, alpha, op, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+static inline Mat& operator /= (const Mat& a, const MatExpr& b)
+{
+    b.op->augAssignDivide(b, (Mat&)a); 
+    return (Mat&)a;
+}
 
-template<typename M> class CV_EXPORTS MatOp_DivRS_
+template<typename _Tp> static inline
+Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, const MatExpr& b)
 {
-public:
-    MatOp_DivRS_() {}
+    b.op->augAssignDivide(b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}
 
-    static void apply(const M& a, double alpha, M& c, int type=-1)
-    {
-        if( type == a.type() || type == -1 )
-        {
-            c.create(a.rows, a.cols, a.type());
-            divide( alpha, a, c );
-        }
-        else
-        {
-            Mat temp;
-            apply(a, alpha, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
+////////////////////////////// Logical operations ///////////////////////////////
 
+static inline Mat& operator &= (const Mat& a, const Mat& b)
+{
+    bitwise_and(a, b, (Mat&)a);
+    return (Mat&)a;
+}
 
-template<typename M> class CV_EXPORTS MatOp_Inv_
+static inline Mat& operator &= (const Mat& a, const Scalar& s)
 {
-public:
-    MatOp_Inv_() {}
+    bitwise_and(a, s, (Mat&)a);
+    return (Mat&)a;
+}    
 
-    static void apply(const M& a, int method, M& c, int type=-1)
-    {
-        if( type == a.type() || type == -1 )
-        {
-            invert(a, c, method);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, method, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
-
-
-template<typename M> class CV_EXPORTS MatOp_Solve_
-{
-public:
-    MatOp_Solve_() {}
-
-    static void apply(const M& a, const M& b, int method, M& c, int type=-1)
-    {
-        if( type == a.type() || type == -1 )
-        {
-            solve(a, b, c, method);
-        }
-        else
-        {
-            Mat temp;
-            apply(a, b, method, temp);
-            temp.convertTo(c, type);
-        }
-    }
-};
-
-template<typename M> class CV_EXPORTS MatOp_Set_
-{
-public:
-    MatOp_Set_() {}
-
-    static void apply(Size size, int type0, const Scalar& s, int mtype, M& c, int type=-1)
-    {
-        if( type < 0 )
-            type = type0;
-        c.create(size.height, size.width, type);
-        if( mtype == 0 )
-            c = Scalar(0);
-        else if( mtype == 1 )
-            c = s;
-        else if( mtype == 2 )
-            setIdentity(c, s);
-    }
-};
-
-template<typename A1, typename M, typename Op>
-class CV_EXPORTS MatExpr_Op1_
-{
-public:
-    MatExpr_Op1_(const A1& _a1) : a1(_a1) {}
-    void assignTo(Mat& m, int type=-1) const { Op::apply(a1, (M&)m, type); }
-    operator M() const { M result; assignTo(result); return result; }
-
-    A1 a1;
-};
-
-template<typename A1, typename A2, typename M, typename Op>
-class CV_EXPORTS MatExpr_Op2_
-{
-public:
-    MatExpr_Op2_(const A1& _a1, const A2& _a2) : a1(_a1), a2(_a2) {}
-    void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, (M&)m, type); }
-    operator M() const { M result; assignTo(result); return result; }
-
-    A1 a1; A2 a2;
-};
-
-template<typename A1, typename A2, typename A3, typename M, typename Op>
-class CV_EXPORTS MatExpr_Op3_
-{
-public:
-    MatExpr_Op3_(const A1& _a1, const A2& _a2, const A3& _a3) : a1(_a1), a2(_a2), a3(_a3) {}
-    void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, (M&)m, type); }
-    operator M() const { M result; assignTo(result); return result; }
-
-    A1 a1; A2 a2; A3 a3;
-};
-
-template<typename A1, typename A2, typename A3, typename A4, typename M, typename Op>
-class CV_EXPORTS MatExpr_Op4_
-{
-public:
-    MatExpr_Op4_(const A1& _a1, const A2& _a2, const A3& _a3, const A4& _a4)
-        : a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
-    void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, a4, (M&)m, type); }
-    operator M() const { M result; assignTo(result); return result; }
-
-    A1 a1; A2 a2; A3 a3; A4 a4;
-};
-
-template<typename A1, typename A2, typename A3, typename A4, typename A5, typename M, typename Op>
-class CV_EXPORTS MatExpr_Op5_
-{
-public:
-    MatExpr_Op5_(const A1& _a1, const A2& _a2, const A3& _a3, const A4& _a4, const A5& _a5)
-        : a1(_a1), a2(_a2), a3(_a3), a4(_a4), a5(_a5) {}
-    void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, a4, a5, (M&)m, type); }
-    operator M() const { M result; assignTo(result); return result; }
-
-    A1 a1; A2 a2; A3 a3; A4 a4; A5 a5;
-};
-
-template<typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename M, typename Op>
-class CV_EXPORTS MatExpr_Op6_
-{
-public:
-    MatExpr_Op6_(const A1& _a1, const A2& _a2, const A3& _a3,
-                    const A4& _a4, const A5& _a5, const A6& _a6)
-        : a1(_a1), a2(_a2), a3(_a3), a4(_a4), a5(_a5), a6(_a6) {}
-    void assignTo(Mat& m, int type=-1) const { Op::apply(a1, a2, a3, a4, a5, a6, (M&)m, type); }
-    operator M() const { M result; assignTo(result); return result; }
-
-    A1 a1; A2 a2; A3 a3; A4 a4; A5 a5; A6 a6;
-};
-
-///////////////////////////////// Arithmetical Operations ///////////////////////////////////
-
-// A + B
-static inline MatExpr_<MatExpr_Op5_<Mat, double, Mat, double, double, Mat, MatOp_AddEx_<Mat> >, Mat>
-operator + (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op5_<Mat, double, Mat, double, double, Mat, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, 1, b, 1, 0));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op5_<Mat, double, Mat,
-double, double, Mat, MatOp_AddEx_<Mat> >, Mat >
-operator + (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op5_<Mat, double, Mat, double, double, Mat, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, 1, b, 1, 0));
-}
-
-// E1 + E2
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<M, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b )
-{
-    typedef MatExpr_Op5_<M, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, 1, (M)b, 1, 0));
-}
-
-// A - B
-static inline MatExpr_<MatExpr_Op2_<Mat, Mat, Mat, MatOp_Sub_<Mat> >, Mat>
-operator - (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op2_<Mat, Mat, Mat, MatOp_Sub_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, Mat, Mat, MatOp_Sub_<Mat> >, Mat >
-operator - (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op2_<Mat, Mat, Mat, MatOp_Sub_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, b));
-}
-
-// E1 - E2
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, M, M, MatOp_Sub_<Mat> >, M>
-operator - (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b )
-{
-    typedef MatExpr_Op2_<M, M, M, MatOp_Sub_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, (M)b));
-}
-
-// -(E1 - E2)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op2_<B, A, M, MatOp_Sub_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op2_<B, A, M, MatOp_Sub_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a2, a.e.a1));
-}
-
-// (A - B)*alpha
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a,
-            double alpha)
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, alpha, a.e.a2, -alpha, 0));
-}
-
-// alpha*(A - B)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator * (double alpha,
-            const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a)
-{ return a*alpha; }
-
-
-// A*alpha
-static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
-operator * (const Mat& a, double alpha)
-{
-    typedef MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha));
-}
-
-// A*alpha
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat >
-operator * (const Mat_<_Tp>& a, double alpha)
-{
-    typedef MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, alpha));
-}
-
-// alpha*A
-static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
-operator * (double alpha, const Mat& a)
-{ return a*alpha; }
-
-// alpha*A
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat >
-operator * (double alpha, const Mat_<_Tp>& a)
-{ return a*alpha; }
-
-// A/alpha
-static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
-operator / (const Mat& a, double alpha)
-{ return a*(1./alpha); }
-
-// A/alpha
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat >
-operator / (const Mat_<_Tp>& a, double alpha)
-{ return a*(1./alpha); }
-
-// -A
-static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>
-operator - (const Mat& a)
-{ return a*(-1); }
-
-// -A
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat >
-operator - (const Mat_<_Tp>& a)
-{ return a*(-1); }
-
-// E*alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
-operator * (const MatExpr_<A, M>& a, double alpha)
-{
-    typedef MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, alpha));
-}
-
-// alpha*E
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
-operator * (double alpha, const MatExpr_<A, M>& a)
-{
-    typedef MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, alpha));
-}
-
-// E/alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
-operator / (const MatExpr_<A, M>& a, double alpha)
-{
-    typedef MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, (1./alpha)));
-}
-
-// (E*alpha)*beta ~ E*(alpha*beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            double beta)
-{ return a.e.a1*(a.e.a2*beta); }
-
-// beta*(E*alpha) ~ E*(alpha*beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
-operator * (double beta,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return a.e.a1*(a.e.a2*beta); }
-
-// (E*alpha)/beta ~ E*(alpha/beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
-operator / (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            double beta)
-{ return a.e.a1*(a.e.a2/beta); }
-
-// -E ~ E*(-1)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
-operator - (const MatExpr_<A, M>& a)
-{ return a*(-1.); }
-
-// -(E*alpha) ~ E*(-alpha)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return a.e.a1*(-a.e.a2); }
-
-// A + alpha
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, double, double, Mat, MatOp_ScaleAddS_<Mat> >, Mat >
-operator + (const Mat_<_Tp>& a, double alpha)
-{
-    typedef MatExpr_Op3_<Mat, double, double, Mat,
-        MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, 1, alpha));
-}
-
-// A + alpha
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> >, Mat >
-operator + (const Mat_<_Tp>& a, const Scalar& alpha)
-{
-    typedef MatExpr_Op2_<Mat, Scalar, Mat,
-        MatOp_AddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, alpha));
-}
-
-static inline
-MatExpr_<MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> >, Mat >
-operator + (const Mat& a, const Scalar& alpha)
-{
-    typedef MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha));
-}
-
-
-// alpha + A
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, double, double, Mat, MatOp_ScaleAddS_<Mat> >, Mat >
-operator + (double alpha, const Mat_<_Tp>& a)
-{ return a + alpha; }
-
-// alpha + A
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> >, Mat >
-operator + (const Scalar& alpha, const Mat_<_Tp>& a)
-{ return a + alpha; }
-
-static inline
-MatExpr_<MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> >, Mat >
-operator + (const Scalar& alpha, const Mat& a)
-{ return a + alpha; }
-
-// A - alpha
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, double, double, Mat, MatOp_ScaleAddS_<Mat> >, Mat >
-operator - (const Mat_<_Tp>& a, double alpha)
-{ return a + (-alpha); }
-
-// A - alpha
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> >, Mat >
-operator - (const Mat_<_Tp>& a, const Scalar& alpha)
-{ return a + (-alpha); }
-
-static inline
-MatExpr_<MatExpr_Op2_<Mat, Scalar, Mat, MatOp_AddS_<Mat> >, Mat >
-operator - (const Mat& a, const Scalar& alpha)
-{ return a + (-alpha); }
-
-// alpha - A
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, double, double, Mat, MatOp_ScaleAddS_<Mat> >, Mat >
-operator - (double alpha, const Mat_<_Tp>& a)
-{
-    typedef MatExpr_Op3_<Mat, double, double, Mat,
-        MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, -1, alpha));
-}
-
-// E + alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator + (const MatExpr_<A, M>& a, double alpha)
-{
-    typedef MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, 1, alpha));
-}
-
-// E + alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> >, M>
-operator + (const MatExpr_<A, M>& a, const Scalar& alpha)
-{
-    typedef MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, alpha));
-}
-
-// alpha + E
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator + (double alpha, const MatExpr_<A, M>& a)
-{ return a + alpha; }
-
-// alpha + E
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> >, M>
-operator + (const Scalar& alpha, const MatExpr_<A, M>& a)
-{ return a + alpha; }
-
-// E - alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (const MatExpr_<A, M>& a, double alpha)
-{ return a + (-alpha); }
-
-// E - alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, Scalar, M, MatOp_AddS_<Mat> >, M>
-operator - (const MatExpr_<A, M>& a, const Scalar& alpha)
-{ return a + (-alpha); }
-
-// alpha - E
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (double alpha, const MatExpr_<A, M>& a)
-{
-    typedef MatExpr_Op3_<M, double, double, M, MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a, -1, alpha));
-}
-
-// E*alpha + beta
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            double beta)
-{
-    typedef MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, beta));
-}
-
-// beta + E*alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator + (double beta,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return a + beta; }
-
-// E*alpha - beta
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            double beta)
-{ return a + (-beta); }
-
-// beta - E*alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (double beta,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return (a.e.a1*(-a.e.a2)) + beta; }
-
-// (E*alpha + gamma) + beta ~ E*alpha + (gamma + beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            double beta)
-{ return a.e.a1*a.e.a2 + (a.e.a3 + beta); }
-
-// beta + (E*alpha + gamma)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator + (double beta, const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return a + beta; }
-
-// (E*alpha + gamma) - beta
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            double beta)
-{ return a + (-beta); }
-
-// beta - (E*alpha + gamma)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (double beta, const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return a.e.a1*(-a.e.a2) + (beta - a.e.a3); }
-
-// (E*alpha + gamma)*beta
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            double beta)
-{ return a.e.a1*(a.e.a2*beta) + (a.e.a3*beta); }
-
-// beta*(E*alpha + gamma)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator * (double beta, const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return a*beta; }
-
-// -(E*alpha + beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return a*(-1); }
-
-// (A*u + B*v + w) + beta
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a,
-            double beta )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3, a.e.a4, a.e.a5 + beta));
-}
-
-// beta + (A*u + B*v + w)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (double beta,
-            const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
-{ return a + beta; }
-
-// (A*u + B*v + w) - beta
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a,
-            double beta)
-{ return a + (-beta); }
-
-// beta - (A*u + B*v + w)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (double beta,
-            const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, a.e.a3, -a.e.a4, -a.e.a5 + beta));
-}
-
-// (A*u + B*v + w)*beta
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a,
-            double beta )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1,
-        a.e.a2*beta, a.e.a3, a.e.a4*beta, a.e.a5*beta));
-}
-
-// beta*(A*u + B*v + w)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator * (double beta,
-            const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
-{ return a * beta; }
-
-// -(A*u + B*v + w)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>& a)
-{ return a*(-1); }
-
-// A*alpha + B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const M& b )
-{
-    typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, 1, 0));
-}
-
-// B + A*alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const M& b,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return a + b; }
-
-// (A*alpha + beta) + B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const M& b )
-{
-    typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, 1, a.e.a3));
-}
-
-// B + (A*alpha + beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const M& b,
-            const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return a + b; }
-
-
-// A*alpha + E
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const MatExpr_<B, M>& b )
-{ return a + (M)b; }
-
-// E + A*alpha
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<B, M>& b,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return a + (M)b; }
-
-// (A*alpha + beta) + E
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const MatExpr_<B, M>& b )
-{ return a + (M)b; }
-
-// E + (A*alpha + beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<B, M>& b,
-            const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return a + b; }
-
-// A*alpha + B*beta
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, b.e.a2, 0));
-}
-
-// (A*alpha + beta) + B*gamma
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, b.e.a2, a.e.a3));
-}
-
-// B*gamma + (A*alpha + beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b,
-            const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a )
-{ return a + b; }
-
-// (A*alpha + beta) + (B*gamma + theta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator + (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, b.e.a2, a.e.a3 + b.e.a3));
-}
-
-// A*alpha - B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const M& b )
-{
-    typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, -1, 0));
-}
-
-// B - A*alpha
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const M& b,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{
-    typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, b, 1, 0));
-}
-
-// (A*alpha + beta) - B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const M& b )
-{
-    typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b, -1, a.e.a3));
-}
-
-// B - (A*alpha + beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const M& b,
-            const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{
-    typedef MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, b, 1, -a.e.a3));
-}
-
-// A*alpha - E
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const MatExpr_<B, M>& b )
-{ return a - (M)b; }
-
-// E - A*alpha
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<B, M>& b,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return (M)b - a; }
-
-// (A*alpha + beta) - E
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const MatExpr_<B, M>& b )
-{ return a - (M)b; }
-
-// E - (A*alpha + beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, M, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<B, M>& b,
-            const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a)
-{ return (M)b - a; }
-
-// A*alpha - B*beta
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, -b.e.a2, 0));
-}
-
-// (A*alpha + beta) - B*gamma
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, -b.e.a2, a.e.a3));
-}
-
-// B*gamma - (A*alpha + beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b,
-            const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, -a.e.a2, b.e.a1, b.e.a2, -a.e.a3));
-}
-
-// (A*alpha + beta) - (B*gamma + theta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> >, M>
-operator - (const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op3_<B, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op5_<A, double, B, double, double, M, MatOp_AddEx_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, b.e.a1, -b.e.a2, a.e.a3 - b.e.a3));
-}
-
-/////////////////////////////// Mat Multiplication ///////////////////////////////////
-
-// A^t
-inline MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat>
-Mat::t() const
-{
-    typedef MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, 1));
-}
-
-template<typename _Tp> inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat >
-Mat_<_Tp>::t() const
-{
-    typedef MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, 1));
-}
-
-// A*B
-static inline
-MatExpr_<MatExpr_Op4_<Mat, Mat, double, int, Mat, MatOp_MatMul_<Mat> >, Mat>
-operator * ( const Mat& a, const Mat& b )
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, int, Mat, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 1, 0));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op4_<Mat, Mat, double, int, Mat,
-MatOp_MatMul_<Mat> >, Mat >
-operator * ( const Mat_<_Tp>& a, const Mat_<_Tp>& b )
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, int, Mat,
-        MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, b, 1, 0));
-}
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<A, M>& a, const MatExpr_<B, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a, (M)b, 1, 0));
-}
-
-// (A*alpha)*B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a, const M& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2, 0));
-}
-
-// A*(B*alpha)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const M& b, const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(b, (M)a.e.a1, a.e.a2, 0));
-}
-
-// A^t*B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& a, const M& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2, GEMM_1_T));
-}
-
-// A*B^t
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const M& a, const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a, (M)b.e.a1, b.e.a2, GEMM_2_T));
-}
-
-// (A*alpha)*(B*beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1, a.e.a2*b.e.a2, 0));
-}
-
-// A^t*(B*alpha)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1, a.e.a2*b.e.a2, GEMM_1_T));
-}
-
-// (A*alpha)*B^t
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1, a.e.a2*b.e.a2, GEMM_2_T));
-}
-
-// A^t*B^t
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1,
-        (M)b.e.a1, a.e.a2*b.e.a2, GEMM_1_T+GEMM_2_T));
-}
-
-// (A*B)*alpha
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             double alpha )
-{
-    typedef MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3*alpha, a.e.a4));
-}
-
-// alpha*(A*B)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator * ( double alpha,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{
-    return a*alpha;
-}
-
-// -(A*B)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{
-    return a*(-1);
-}
-
-// (A*alpha + beta)*B
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& a, const M& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2, b, a.e.a3, 0));
-}
-
-// A*(B*alpha + beta)
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const M& a, const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a, (M)b.e.a1, b.e.a2, a, b.e.a3, 0));
-}
-
-// (A*alpha + beta)*(B*gamma)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
-        a.e.a2*b.e.a2, (M)b.e.a1, a.e.a3*b.e.a2, 0));
-}
-
-// (A*gamma)*(B*alpha + beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
-        a.e.a2*b.e.a2, (M)a.e.a1, a.e.a2*b.e.a3, 0));
-}
-
-// (A*alpha + beta)*B^t
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
-        a.e.a2*b.e.a2, (M)b.e.a1, a.e.a3*b.e.a2, GEMM_2_T));
-}
-
-// A^t*(B*alpha + beta)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_T_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_ScaleAddS_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op4_<M, M, double, int, M, MatOp_MatMul_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)b.e.a1,
-        a.e.a2*b.e.a2, (M)a.e.a1, a.e.a2*b.e.a3, GEMM_1_T));
-}
-
-// (A*B + C)*alpha
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( const MatExpr_<MatExpr_Op6_<A, B, double, C,
-             double, int, M, MatOp_MatMulAdd_<Mat> >, M>& a, double alpha )
-{
-    typedef MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(a.e.a1, a.e.a2,
-        a.e.a3*alpha, a.e.a4, a.e.a5*alpha, a.e.a6));
-}
-
-// alpha*(A*B + C)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator * ( double alpha, const MatExpr_<MatExpr_Op6_<A, B, double, C,
-             double, int, M, MatOp_MatMulAdd_<Mat> >, M>& a )
-{ return a*alpha; }
-
-// -(A*B + C)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<A, B, double, C, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op6_<A, B, double, C,
-             double, int, M, MatOp_MatMulAdd_<Mat> >, M>& a )
-{ return a*(-1); }
-
-
-// (A*B) + C
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const M& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, b, 1, a.e.a4));
-}
-
-// C + (A*B)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const M& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{ return a + b; }
-
-
-// (A*B) - C
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const M& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, b, -1, a.e.a4));
-}
-
-// C - (A*B)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const M& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, -a.e.a3, b, 1, a.e.a4));
-}
-
-
-// (A*B) + C
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const MatExpr_<C, M>& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b, 1, a.e.a4));
-}
-
-// C + (A*B)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<C, M>& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{ return a + b; }
-
-
-// (A*B) - C
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const MatExpr_<C, M>& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b, -1, a.e.a4));
-}
-
-// C - (A*B)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<C, M>& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, -a.e.a3, (M)b, 1, a.e.a4));
-}
-
-
-// (A*B) + C*alpha
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4));
-}
-
-// C*alpha + (A*B)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{ return a + b; }
-
-
-// (A*B) - (C*alpha)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, -b.e.a2, a.e.a4));
-}
-
-// (C*alpha) - (A*B)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_Scale_<Mat> >, M>& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, -a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4));
-}
-
-
-// (A*B) + C^t
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4 + GEMM_3_T));
-}
-
-// C^t + (A*B)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator + ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{ return a + b; }
-
-
-// (A*B) - C^t
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a,
-             const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, a.e.a3, (M)b.e.a1, -b.e.a2, a.e.a4+GEMM_3_T));
-}
-
-// C^t - (A*B)
-template<typename A, typename B, typename C, typename M> static inline
-MatExpr_<MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> >, M>
-operator - ( const MatExpr_<MatExpr_Op2_<C, double, M, MatOp_T_<Mat> >, M>& b,
-             const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& a )
-{
-    typedef MatExpr_Op6_<M, M, double, M, double, int, M, MatOp_MatMulAdd_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp(
-        (M)a.e.a1, (M)a.e.a2, -a.e.a3, (M)b.e.a1, b.e.a2, a.e.a4+GEMM_3_T));
-}
-
-
-////////////////////////////// Augmenting algebraic operations //////////////////////////////////
-
-static inline Mat& operator += (const Mat& a, const Mat& b)
-{
-    add(a, b, (Mat&)a);
-    return (Mat&)a;
-}
-
-static inline Mat& operator -= (const Mat& a, const Mat& b)
-{
-    subtract(a, b, (Mat&)a);
-    return (Mat&)a;
-}
-
-static inline Mat& operator *= (const Mat& a, const Mat& b)
-{
-    gemm(a, b, 1, Mat(), 0, (Mat&)a, 0);
-    return (Mat&)a;
-}
-
-static inline Mat& operator *= (const Mat& a, double alpha)
-{
-    a.convertTo((Mat&)a, -1, alpha);
-    return (Mat&)a;
-}
-
-static inline Mat& operator += (const Mat& a, const Scalar& s)
-{
-    add(a, s, (Mat&)a);
-    return (Mat&)a;
-}
-
-static inline Mat& operator -= (const Mat& a, const Scalar& s)
-{ return (a += -s); }
-
-template<typename _Tp> static inline
-Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    (Mat&)a += (const Mat&)b;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline
-Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    (Mat&)a -= (const Mat&)b;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline
-Mat_<_Tp>& operator *= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    (Mat&)a *= (const Mat&)b;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline
-Mat_<_Tp>& operator += (const Mat_<_Tp>& a, const Scalar& s)
-{
-    (Mat&)a += s;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline
-Mat_<_Tp>& operator -= (const Mat_<_Tp>& a, const Scalar& s)
-{
-    (Mat&)a -= s;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename A, typename M> static inline
-M& operator += (const M& a, const MatExpr_<A, M>& b)
-{ return (a += (M)b); }
-
-template<typename A, typename M> static inline
-M& operator -= (const M& a, const MatExpr_<A, M>& b)
-{ return (a -= (M)b); }
-
-template<typename A, typename M> static inline
-M& operator *= (const M& a, const MatExpr_<A, M>& b)
-{ return (a *= (M)b); }
-
-template<typename A, typename M> static inline
-M& operator += (const M& a,
-                const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    scaleAdd( b.e.a1, b.e.a2, _a, _a );
-    return _a;
-}
-
-template<typename A, typename M> static inline
-M& operator -= (const M& a,
-                const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    scaleAdd( b.e.a1, -b.e.a2, _a, _a );
-    return _a;
-}
-
-template<typename A, typename M> static inline
-M& operator += (const M& a,
-                const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_AddEx_<Mat>::apply( a, 1, (M)b.e.a1, b.e.a2, b.e.a3, _a );
-    return _a;
-}
-
-template<typename A, typename M> static inline
-M& operator -= (const M& a,
-                const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_AddEx_<Mat>::apply( a, 1, (M)b.e.a1, -b.e.a2, -b.e.a3, _a );
-    return _a;
-}
-
-template<typename A, typename B, typename M> static inline
-M& operator += (const M& a,
-                const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_MatMulAdd_<Mat>::apply( (M)b.e.a1, (M)b.e.a2, b.e.a3, a, 1, b.e.a4, _a );
-    return _a;
-}
-
-template<typename A, typename B, typename M> static inline
-M& operator -= (const M& a,
-                const MatExpr_<MatExpr_Op4_<A, B, double, int, M, MatOp_MatMul_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_MatMulAdd_<Mat>::apply( (M)b.e.a1, (M)b.e.a2, -b.e.a3, a, 1, b.e.a4, _a );
-    return _a;
-}
-
-template<typename A, typename M> static inline
-M& operator *= (const M& a,
-                const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_MatMul_<Mat>::apply( a, (M)b.e.a1, b.e.a2, 0, _a );
-    return _a;
-}
-
-template<typename A, typename M> static inline
-M& operator *= (const M& a,
-                const MatExpr_<MatExpr_Op3_<A, double, double, M, MatOp_ScaleAddS_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_MatMulAdd_<Mat>::apply( a, (M)b.e.a1, b.e.a2, a, b.e.a3, 0, _a );
-    return _a;
-}
-
-template<typename A, typename M> static inline
-M& operator *= (const M& a,
-                const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_T_<Mat> >, M>& b)
-{
-    M& _a = (M&)a;
-    MatOp_MatMul_<Mat>::apply( a, (M)b.e.a1, b.e.a2, GEMM_2_T, _a );
-    return _a;
-}
-
-////////////////////////////// Logical operations ///////////////////////////////
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
-operator & (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, '&'));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
-operator | (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, '|'));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
-operator ^ (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, '^'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat,
-            MatOp_Bin_<Mat> >, Mat >
-operator & (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat,
-        MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(
-        a, b, '&'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat,
-            MatOp_Bin_<Mat> >, Mat >
-operator | (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat,
-        MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(
-        a, b, '|'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat,
-            MatOp_Bin_<Mat> >, Mat >
-operator ^ (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat,
-        MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(
-        a, b, '^'));
-}
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator & (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
-{ return (M)a & (M)b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator & (const MatExpr_<A, M>& a, const M& b)
-{ return (M)a & b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator & (const M& a, const MatExpr_<A, M>& b)
-{ return a & (M)b; }
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator | (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
-{ return (M)a | (M)b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator | (const MatExpr_<A, M>& a, const M& b)
-{ return (M)a | b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator | (const M& a, const MatExpr_<A, M>& b)
-{ return a | (M)b; }
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator ^ (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
-{ return (M)a ^ (M)b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator ^ (const MatExpr_<A, M>& a, const M& b)
-{ return (M)a ^ b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-operator ^ (const M& a, const MatExpr_<A, M>& b)
-{ return a ^ (M)b; }
-
-static inline Mat& operator &= (const Mat& a, const Mat& b)
-{
-    MatOp_Bin_<Mat>::apply( a, b, '&', (Mat&)a );
-    return (Mat&)a;
-}
-
-static inline Mat& operator |= (const Mat& a, const Mat& b)
-{
-    MatOp_Bin_<Mat>::apply( a, b, '|', (Mat&)a );
-    return (Mat&)a;
-}
-
-static inline Mat& operator ^= (const Mat& a, const Mat& b)
-{
-    MatOp_Bin_<Mat>::apply( a, b, '^', (Mat&)a );
-    return (Mat&)a;
-}
-
-template<typename _Tp> static inline Mat_<_Tp>&
-operator &= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    (Mat&)a &= (const Mat&)b;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline Mat_<_Tp>&
-operator |= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    (Mat&)a |= (const Mat&)b;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline Mat_<_Tp>&
-operator ^= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    (Mat&)a ^= (const Mat&)b;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename A, typename M> static inline M&
-operator &= (const M& a, const MatExpr_<A, M>& b)
-{ return (a &= (M)b); }
-
-template<typename A, typename M> static inline M&
-operator |= (const M& a, const MatExpr_<A, M>& b)
-{ return (a |= (M)b); }
-
-template<typename A, typename M> static inline M&
-operator ^= (const M& a, const MatExpr_<A, M>& b)
-{ return (a ^= (M)b); }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator & (const Mat& a, const Scalar& s)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, s, '&'));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator & (const Scalar& s, const Mat& a)
-{ return a & s; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator | (const Mat& a, const Scalar& s)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, s, '|'));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator | (const Scalar& s, const Mat& a)
-{ return a | s; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator ^ (const Mat& a, const Scalar& s)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, s, '^'));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator ^ (const Scalar& s, const Mat& a)
-{ return a ^ s; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-operator ~ (const Mat& a)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, Scalar(), '~'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator & (const Mat_<_Tp>& a, const Scalar& s)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, s, '&'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator & (const Scalar& s, const Mat_<_Tp>& a)
-{ return a & s; }
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator | (const Mat_<_Tp>& a, const Scalar& s)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, s, '|'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator | (const Scalar& s, const Mat_<_Tp>& a)
-{ return a | s; }
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator ^ (const Mat_<_Tp>& a, const Scalar& s)
+template<typename _Tp> static inline Mat_<_Tp>&
+operator &= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
 {
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, s, '^'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator ^ (const Scalar& s, const Mat_<_Tp>& a)
-{ return a ^ s; }
+    bitwise_and(a, b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}    
 
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat >
-operator ~ (const Mat_<_Tp>& a)
+template<typename _Tp> static inline Mat_<_Tp>&
+operator &= (const Mat_<_Tp>& a, const Scalar& s)
 {
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, Scalar(), '~'));
-}
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator & (const MatExpr_<A, M>& a, const Scalar& s)
-{ return (M)a & s; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator & (const Scalar& s, const MatExpr_<A, M>& a)
-{ return (M)a & s; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator | (const MatExpr_<A, M>& a, const Scalar& s)
-{ return (M)a | s; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator | (const Scalar& s, const MatExpr_<A, M>& a)
-{ return (M)a | s; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator ^ (const MatExpr_<A, M>& a, const Scalar& s)
-{ return (M)a ^ s; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator ^ (const Scalar& s, const MatExpr_<A, M>& a)
-{ return (M)a ^ s; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, Scalar, int, M, MatOp_BinS_<Mat> >, M >
-operator ~ (const MatExpr_<A, M>& a)
-{ return ~(M)a; }
-
-static inline Mat& operator &= (const Mat& a, const Scalar& s)
+    bitwise_and(a, s, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}        
+    
+static inline Mat& operator |= (const Mat& a, const Mat& b)
 {
-    MatOp_BinS_<Mat>::apply( a, s, '&', (Mat&)a );
+    bitwise_or(a, b, (Mat&)a);
     return (Mat&)a;
 }
 
 static inline Mat& operator |= (const Mat& a, const Scalar& s)
 {
-    MatOp_BinS_<Mat>::apply( a, s, '|', (Mat&)a );
-    return (Mat&)a;
-}
-
-static inline Mat& operator ^= (const Mat& a, const Scalar& s)
-{
-    MatOp_BinS_<Mat>::apply( a, s, '^', (Mat&)a );
+    bitwise_or(a, s, (Mat&)a);
     return (Mat&)a;
-}
+}    
 
 template<typename _Tp> static inline Mat_<_Tp>&
-operator &= (const Mat_<_Tp>& a, const Scalar& s)
+operator |= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
 {
-    (Mat&)a &= s;
+    bitwise_or(a, b, (Mat&)a);
     return (Mat_<_Tp>&)a;
-}
+}    
 
 template<typename _Tp> static inline Mat_<_Tp>&
 operator |= (const Mat_<_Tp>& a, const Scalar& s)
 {
-    (Mat&)a |= s;
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline Mat_<_Tp>&
-operator ^= (const Mat_<_Tp>& a, const Scalar& s)
-{
-    (Mat&)a ^= s;
+    bitwise_or(a, s, (Mat&)a);
     return (Mat_<_Tp>&)a;
-}
-
-////////////////////////////// Comparison operations ///////////////////////////////
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
-operator == (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_EQ));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
-operator >= (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_GE));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
-operator > (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_GT));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
-operator <= (const Mat& a, const Mat& b)
-{ return b >= a; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
-operator < (const Mat& a, const Mat& b)
-{ return b > a; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> >, Mat>
-operator != (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Cmp_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, CMP_NE));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator == (const Mat& a, double alpha)
-{
-    typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_EQ));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator >= (const Mat& a, double alpha)
-{
-    typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_GE));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator > (const Mat& a, double alpha)
+}        
+    
+static inline Mat& operator ^= (const Mat& a, const Mat& b)
 {
-    typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_GT));
+    bitwise_xor(a, b, (Mat&)a);
+    return (Mat&)a;
 }
 
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator <= (const Mat& a, double alpha)
+static inline Mat& operator ^= (const Mat& a, const Scalar& s)
 {
-    typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_LE));
-}
+    bitwise_xor(a, s, (Mat&)a);
+    return (Mat&)a;
+}    
 
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator < (const Mat& a, double alpha)
+template<typename _Tp> static inline Mat_<_Tp>&
+operator ^= (const Mat_<_Tp>& a, const Mat_<_Tp>& b)
 {
-    typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_LT));
-}
+    bitwise_xor(a, b, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}    
 
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator != (const Mat& a, double alpha)
+template<typename _Tp> static inline Mat_<_Tp>&
+operator ^= (const Mat_<_Tp>& a, const Scalar& s)
 {
-    typedef MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha, CMP_NE));
-}
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator == (double alpha, const Mat& a)
-{ return a == alpha; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator >= (double alpha, const Mat& a)
-{ return a <= alpha; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator > (double alpha, const Mat& a)
-{ return a < alpha; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator <= (double alpha, const Mat& a)
-{ return a >= alpha; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator < (double alpha, const Mat& a)
-{ return a > alpha; }
-
-static inline MatExpr_<MatExpr_Op3_<Mat, double, int, Mat, MatOp_CmpS_<Mat> >, Mat>
-operator != (double alpha, const Mat& a)
-{ return a != alpha; }
+    bitwise_xor(a, s, (Mat&)a);
+    return (Mat_<_Tp>&)a;
+}        
 
 /////////////////////////////// Miscellaneous operations //////////////////////////////
 
-// max(A, B)
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
-max(const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 'M'));
-}
-
-// min(A, B)
-static inline MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> >, Mat>
-min(const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat, MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 'm'));
-}
-
-// abs(A)
-static inline MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> >, Mat>
-abs(const Mat& a)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat, MatOp_BinS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, Scalar(0), 'a'));
-}
-
-// max(A, B)
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat,
-            MatOp_Bin_<Mat> >, Mat >
-max(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat,
-        MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(
-        a, b, 'M'));
-}
-
-// min(A, B)
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Mat, int, Mat,
-            MatOp_Bin_<Mat> >, Mat >
-min(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op3_<Mat, Mat, int, Mat,
-        MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(
-        a, b, 'm'));
-}
-
-// abs(A)
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op3_<Mat, Scalar, int, Mat,
-            MatOp_BinS_<Mat> >, Mat >
-abs(const Mat_<_Tp>& a, const Mat_<_Tp>& b)
-{
-    typedef MatExpr_Op3_<Mat, Scalar, int, Mat,
-        MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(
-        a, Scalar(0), 'a'));
-}
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-max(const MatExpr_<A, M>& a, const M& b)
-{ return max((M)a, b); }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-max(const M& a, const MatExpr_<A, M>& b)
-{ return max(a, (M)b); }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-min(const MatExpr_<A, M>& a, const M& b)
-{ return min((M)a, b); }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-min(const M& a, const MatExpr_<A, M>& b)
-{ return min(a, (M)b); }
-
-// abs(A)
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> >, M>
-abs(const MatExpr_<MatExpr_Op2_<A, B, M, MatOp_Sub_<Mat> >, M>& a)
-{
-    typedef MatExpr_Op3_<M, M, int, M, MatOp_Bin_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)a.e.a2, 'a'));
-}
-
+static inline void merge(const vector<Mat>& mv, Mat& dst)
+{ merge(&mv[0], mv.size(), dst); }
+    
 template<typename _Tp> void merge(const Mat_<_Tp>* mvbegin, size_t count, Mat& dst)
 { merge( (const Mat*)mvbegin, count, dst ); }
 
@@ -3193,315 +1414,49 @@ static inline void split(const Mat& m, vector<Mat>& mv)
     mv.resize(m.channels());
     if(m.channels() > 0)
         split(m, &mv[0]);
-}
+}    
     
 template<typename _Tp> void split(const Mat& src, vector<Mat_<_Tp> >& mv)
 { split(src, (vector<Mat>&)mv ); }
-    
-static inline void merge(const vector<Mat>& mv, Mat& dst)
-{ merge(&mv[0], mv.size(), dst); }
 
 static inline void mixChannels(const vector<Mat>& src, vector<Mat>& dst,
                                const int* fromTo, int npairs)
 {
     mixChannels(&src[0], (int)src.size(), &dst[0], (int)dst.size(), fromTo, npairs);
 }
+//////////////////////////////////////////////////////////////
     
-///// Element-wise multiplication
-
-inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-Mat::mul(const Mat& m, double scale) const
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, m, scale, '*'));
-}
-
-inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-Mat::mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>& m, double scale) const
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, m.e.a1, m.e.a2*scale, '*'));
-}
-
-inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-Mat::mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat>& m, double scale) const
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, m.e.a1, scale/m.e.a2, '/'));
-}
-
-template<typename _Tp> inline
-MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat >
-Mat_<_Tp>::mul(const Mat_<_Tp>& m, double scale) const
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(*this, m, scale, '*'));
-}
-
-template<typename _Tp> inline
-MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat >
-Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat >& m, double scale) const
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(*this, m.e.a1, m.e.a2*scale, '*'));
-}
-
-template<typename _Tp> inline
-MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat >
-Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat >& m, double scale) const
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(*this, m.e.a1, scale/m.e.a2, '/'));
-}
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op4_<A, B, double, char, M, MatOp_MulDiv_<Mat> >, M>& a,
-            double alpha)
-{
-    typedef MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, (M)a.e.a2, a.e.a3*alpha, a.e.a4));
-}
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator * (double alpha,
-            const MatExpr_<MatExpr_Op4_<A, B, double, char, M, MatOp_MulDiv_<Mat> >, M>& a)
-{ return a*alpha; }
-
-
-////// Element-wise division
-
-static inline MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
-operator / (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 1, '/'));
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op4_<Mat, Mat, double,
-char, Mat, MatOp_MulDiv_<Mat> >, Mat >
-operator / (const Mat& a, const Mat& b)
-{
-    typedef MatExpr_Op4_<Mat, Mat, double,
-        char, Mat, MatOp_MulDiv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, b, 1, '/'));
-}
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const MatExpr_<A, M>& a, const MatExpr_<B, M>& b)
-{ return (M)a/(M)b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const MatExpr_<A, M>& a, const M& b)
-{ return (M)a/b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const M& a, const MatExpr_<A, M>& b)
-{ return a/(M)b; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const M& b)
-{ return ((M)a.e.a1/b)*a.e.a2; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const M& a,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& b)
-{ return (a/(M)b.e.a1)*(1./b.e.a2); }
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a,
-            const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_Scale_<Mat> >, M>& b)
-{ return ((M)a.e.a1/(M)b.e.a1)*(a.e.a2/b.e.a2); }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const M& a,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_DivRS_<Mat> >, M>& b)
-{ return a.mul((M)b.e.a1, 1./b.e.a2); }
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op4_<M, M, double, char, M, MatOp_MulDiv_<Mat> >, M>
-operator / (const MatExpr_<A, M>& a,
-            const MatExpr_<MatExpr_Op2_<B, double, M, MatOp_DivRS_<Mat> >, M>& b)
-{ return ((M)a).mul((M)b.e.a1, 1./b.e.a2); }
-
-static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat >
-operator / (double alpha, const Mat& a)
-{
-    typedef MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(a, alpha));
-}
-
-static inline Mat& operator /= (const Mat& a, double alpha)
-{
-    MatOp_Scale_<Mat>::apply( a, 1./alpha, (Mat&)a );
-    return (Mat&)a;
-}
-
-template<typename _Tp>
-static inline Mat_<_Tp>& operator /= (const Mat_<_Tp>& a, double alpha)
-{
-    MatOp_Scale_<Mat>::apply( a, 1./alpha, (Mat&)a );
-    return (Mat_<_Tp>&)a;
-}
-
-template<typename _Tp> static inline
-MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat >
-operator / (double alpha, const Mat_<_Tp>& a)
-{
-    typedef MatExpr_Op2_<Mat, double, Mat,
-        MatOp_DivRS_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(a, alpha));
-}
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_DivRS_<Mat> >, M>
-operator / (double alpha, const MatExpr_<A, M>& a)
-{ return alpha/(M)a; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_DivRS_<Mat> >, M>
-operator / (double alpha,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_Scale_<Mat> >, M>& a)
-{ return (alpha/a.e.a2)/(M)a.e.a1; }
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op2_<M, double, M, MatOp_Scale_<Mat> >, M>
-operator / (double alpha,
-            const MatExpr_<MatExpr_Op2_<A, double, M, MatOp_DivRS_<Mat> >, M>& a)
-{ return (M)a.e.a1*(alpha/a.e.a2); }
-
-static inline Mat& operator /= (const Mat& a, const Mat& b)
-{
-    MatOp_MulDiv_<Mat>::apply( a, b, 1, '/', (Mat&)a );
-    return (Mat&)a;
-}
-
-template<typename A, typename M>
-static inline M& operator /= (const M& a, const MatExpr_<MatExpr_Op2_<A, double,
-                              M, MatOp_Scale_<Mat> >, M>& b)
-{
-    MatOp_MulDiv_<Mat>::apply( a, (M)b.e.a1, 1./b.e.a2, '/', (M&)a );
-    return (M&)a;
-}
-
-template<typename A, typename M>
-static inline M& operator /= (const M& a, const MatExpr_<MatExpr_Op2_<A, double,
-                              M, MatOp_DivRS_<Mat> >, M>& b)
-{
-    MatOp_MulDiv_<Mat>::apply( a, (M)b.e.a1, 1./b.e.a2, '*', (M&)a );
-    return (M&)a;
-}
-
-// Mat Inversion and solving linear systems
-
-inline MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat>
-Mat::inv(int method) const
-{
-    typedef MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(*this, method));
-}
-
-template<typename _Tp> inline
-MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat >
-Mat_<_Tp>::inv(int method) const
-{
-    typedef MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat >(MatExpr_Temp(*this, method));
-}
-
-template<typename A, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Solve_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op2_<A, int, M, MatOp_Inv_<Mat> >, M>& a,
-            const M& b)
-{
-    typedef MatExpr_Op3_<M, M, int, M, MatOp_Solve_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, M>(MatExpr_Temp((M)a.e.a1, b, a.e.a2));
-}
-
-template<typename A, typename B, typename M> static inline
-MatExpr_<MatExpr_Op3_<M, M, int, M, MatOp_Solve_<Mat> >, M>
-operator * (const MatExpr_<MatExpr_Op2_<A, int, M, MatOp_Inv_<Mat> >, M>& a,
-            const MatExpr_<B, M>& b)
-{ return a*(M)b; }
-
-
-/////////////////////////////// Initialization ////////////////////////////////////////
-
-inline MatExpr_Initializer Mat::zeros(int rows, int cols, int type)
-{
-    typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(Size(cols, rows), type, 0, 0));
-}
-
-inline MatExpr_Initializer Mat::zeros(Size size, int type)
-{
-    return zeros(size.height, size.width, type);
-}
-
-inline MatExpr_Initializer Mat::ones(int rows, int cols, int type)
+template<typename _Tp> inline MatExpr Mat_<_Tp>::zeros(int rows, int cols)
 {
-    typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
-    return MatExpr_<MatExpr_Temp, Mat>(MatExpr_Temp(Size(cols, rows), type, 1, 1));
+    return Mat::zeros(rows, cols, DataType<_Tp>::type);
 }
-
-inline MatExpr_Initializer Mat::ones(Size size, int type)
+    
+template<typename _Tp> inline MatExpr Mat_<_Tp>::zeros(Size sz)
 {
-    return ones(size.height, size.width, type);
-}
-
-inline MatExpr_Initializer Mat::eye(int rows, int cols, int type)
+    return Mat::zeros(sz, DataType<_Tp>::type);
+}    
+    
+template<typename _Tp> inline MatExpr Mat_<_Tp>::ones(int rows, int cols)
 {
-    typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
-    return MatExpr_Initializer(MatExpr_Temp(Size(cols, rows), type, 1, 2));
+    return Mat::ones(rows, cols, DataType<_Tp>::type);
 }
 
-inline MatExpr_Initializer Mat::eye(Size size, int type)
+template<typename _Tp> inline MatExpr Mat_<_Tp>::ones(Size sz)
 {
-    return eye(size.height, size.width, type);
-}
-
-static inline MatExpr_Initializer operator * (const MatExpr_Initializer& a, double alpha)
+    return Mat::ones(sz, DataType<_Tp>::type);
+}    
+    
+template<typename _Tp> inline MatExpr Mat_<_Tp>::eye(int rows, int cols)
 {
-    typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
-    return MatExpr_Initializer(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3*alpha, a.e.a4));
+    return Mat::eye(rows, cols, DataType<_Tp>::type);
 }
 
-static inline MatExpr_Initializer operator * (double alpha, MatExpr_Initializer& a)
+template<typename _Tp> inline MatExpr Mat_<_Tp>::eye(Size sz)
 {
-    typedef MatExpr_Op4_<Size, int, Scalar, int, Mat, MatOp_Set_<Mat> > MatExpr_Temp;
-    return MatExpr_Initializer(MatExpr_Temp(a.e.a1, a.e.a2, a.e.a3*alpha, a.e.a4));
-}
-
-template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::zeros(int rows, int cols)
-{ return Mat::zeros(rows, cols, DataType<_Tp>::type); }
-
-template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::zeros(Size size)
-{ return Mat::zeros(size, DataType<_Tp>::type); }
-
-template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::ones(int rows, int cols)
-{ return Mat::ones(rows, cols, DataType<_Tp>::type); }
-
-template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::ones(Size size)
-{ return Mat::ones(size, DataType<_Tp>::type); }
-
-template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::eye(int rows, int cols)
-{ return Mat::eye(rows, cols, DataType<_Tp>::type); }
-
-template<typename _Tp> inline MatExpr_Initializer Mat_<_Tp>::eye(Size size)
-{ return Mat::eye(size, DataType<_Tp>::type); }
-
-
+    return Mat::eye(sz, DataType<_Tp>::type);
+}    
+    
 //////////// Iterators & Comma initializers //////////////////
 
 template<typename _Tp> inline MatConstIterator_<_Tp>::MatConstIterator_()
@@ -3796,38 +1751,28 @@ template<typename _Tp> inline MatIterator_<_Tp> Mat_<_Tp>::begin()
 template<typename _Tp> inline MatIterator_<_Tp> Mat_<_Tp>::end()
 { return Mat::end<_Tp>(); }
 
-template<typename _Tp> class CV_EXPORTS MatOp_Iter_
-{
-public:    
-    MatOp_Iter_() {}
-
-    static void apply(const MatIterator_<_Tp>& a, Mat& c, int type=-1)
-    {
-        if( type < 0 )
-            c = *a.m;
-        else
-            a.m->convertTo(c, type);
-    }
-};
-
-template<typename _Tp> inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) :
-    MatExpr_<MatExpr_Op1_<MatIterator_<_Tp>, Mat_<_Tp>,
-        MatOp_Iter_<_Tp> >, Mat_<_Tp> >(MatIterator_<_Tp>(_m)) {}
+template<typename _Tp> inline MatCommaInitializer_<_Tp>::MatCommaInitializer_(Mat_<_Tp>* _m) : it(_m) {}
 
 template<typename _Tp> template<typename T2> inline MatCommaInitializer_<_Tp>&
 MatCommaInitializer_<_Tp>::operator , (T2 v)
 {
-    CV_DbgAssert( this->e.a1 < this->e.a1.m->end() );
-    *this->e.a1 = _Tp(v); ++this->e.a1;
+    CV_DbgAssert( this->it < this->it.m->end() );
+    *this->it = _Tp(v); ++this->it;
     return *this;
 }
 
 template<typename _Tp> inline Mat_<_Tp> MatCommaInitializer_<_Tp>::operator *() const
 {
-    CV_DbgAssert( this->e.a1 == this->e.a1.m->end() );
-    return *this->e.a1.m;
+    CV_DbgAssert( this->it == this->it.m->end() );
+    return *this->it.m;
 }
 
+template<typename _Tp> inline MatCommaInitializer_<_Tp>::operator Mat_<_Tp>() const
+{
+    CV_DbgAssert( this->it == this->it.m->end() );
+    return *this->it.m;
+}    
+    
 template<typename _Tp> inline void
 MatCommaInitializer_<_Tp>::assignTo(Mat& m, int type) const
 {
index 5a902bf..ef530fe 100644 (file)
@@ -1996,6 +1996,11 @@ template<typename _Tp> inline Scalar_<_Tp> Scalar_<_Tp>::conj() const
                         saturate_cast<_Tp>(-this->val[3]));
 }
 
+template<typename _Tp> inline bool Scalar_<_Tp>::isReal() const
+{
+    return this->val[1] == 0 && this->val[2] == 0 && this->val[3] == 0;
+}
+    
 template<typename _Tp> static inline
 Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, _Tp alpha)
 {
diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp
new file mode 100644 (file)
index 0000000..9ec5cde
--- /dev/null
@@ -0,0 +1,1715 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
+// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+/* ////////////////////////////////////////////////////////////////////
+//
+//  Mat basic operations: Copy, Set
+//
+// */
+
+#include "precomp.hpp"
+
+namespace cv
+{
+
+class MatOp_Identity : public MatOp
+{
+public:
+    MatOp_Identity() {}
+    virtual ~MatOp_Identity() {}
+
+    bool elementWise(const MatExpr& expr) const { return true; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+        
+    void add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
+    void add(const MatExpr& e1, const Scalar& s, MatExpr& res) const;
+    void subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
+    void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const;
+    void multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale=1) const;
+    void multiply(const MatExpr& e1, double s, MatExpr& res) const;
+    void divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale=1) const;
+    void divide(double s, const MatExpr& e, MatExpr& res) const;
+
+    void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, const Mat& m);
+};
+
+static MatOp_Identity g_MatOp_Identity;
+    
+class MatOp_AddEx : public MatOp
+{
+public:
+    MatOp_AddEx() {}
+    virtual ~MatOp_AddEx() {}
+    
+    bool elementWise(const MatExpr& expr) const { return true; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    void add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
+    void add(const MatExpr& e1, const Scalar& s, MatExpr& res) const;
+    
+    void subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
+    void subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const;
+    
+    void multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale=1) const;
+    void multiply(const MatExpr& e1, double s, MatExpr& res) const;
+    
+    void divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale=1) const;
+    void divide(double s, const MatExpr& e, MatExpr& res) const;
+    
+    void transpose(const MatExpr& e1, MatExpr& res) const;
+    void abs(const MatExpr& expr, MatExpr& res) const;
+    void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s=Scalar());
+};
+
+static MatOp_AddEx g_MatOp_AddEx;
+    
+class MatOp_Bin : public MatOp
+{
+public:
+    MatOp_Bin() {}
+    virtual ~MatOp_Bin() {}
+    
+    bool elementWise(const MatExpr& expr) const { return true; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+        
+    void multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale=1) const;
+    void multiply(const MatExpr& e1, double s, MatExpr& res) const;
+    
+    void divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale=1) const;
+    void divide(double s, const MatExpr& e, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale=1);
+    static void makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s);
+};
+
+static MatOp_Bin g_MatOp_Bin;
+    
+class MatOp_Cmp : public MatOp
+{
+public:
+    MatOp_Cmp() {}
+    virtual ~MatOp_Cmp() {}
+    
+    bool elementWise(const MatExpr& expr) const { return true; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    static void makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b);
+    static void makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha);
+};
+    
+static MatOp_Cmp g_MatOp_Cmp;
+    
+class MatOp_GEMM : public MatOp
+{
+public:
+    MatOp_GEMM() {}
+    virtual ~MatOp_GEMM() {}
+    
+    bool elementWise(const MatExpr& expr) const { return false; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    void add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
+    void subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const;
+    void multiply(const MatExpr& e, double s, MatExpr& res) const;
+    
+    void transpose(const MatExpr& expr, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b,
+                         double alpha=1, const Mat& c=Mat(), double beta=1);
+};
+
+static MatOp_GEMM g_MatOp_GEMM;
+
+class MatOp_Invert : public MatOp
+{
+public:
+    MatOp_Invert() {}
+    virtual ~MatOp_Invert() {}
+    
+    bool elementWise(const MatExpr& expr) const { return false; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, int method, const Mat& m);
+};    
+
+static MatOp_Invert g_MatOp_Invert;
+
+class MatOp_T : public MatOp
+{
+public:
+    MatOp_T() {}
+    virtual ~MatOp_T() {}
+    
+    bool elementWise(const MatExpr& expr) const { return false; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    void multiply(const MatExpr& e1, double s, MatExpr& res) const;
+    void transpose(const MatExpr& expr, MatExpr& res) const;
+    void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, const Mat& a, double alpha=1);
+};
+
+static MatOp_T g_MatOp_T;
+
+class MatOp_Solve : public MatOp
+{
+public:
+    MatOp_Solve() {}
+    virtual ~MatOp_Solve() {}
+    
+    bool elementWise(const MatExpr& expr) const { return false; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    static void makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b);
+};
+
+static MatOp_Solve g_MatOp_Solve;
+
+class MatOp_Initializer : public MatOp
+{
+public:
+    MatOp_Initializer() {}
+    virtual ~MatOp_Initializer() {}
+    
+    bool elementWise(const MatExpr& expr) const { return false; }
+    void assign(const MatExpr& expr, Mat& m, int type=-1) const;
+    
+    void multiply(const MatExpr& e, double s, MatExpr& res) const;
+    
+    static void makeExpr(MatExpr& res, int method, Size sz, int type, double alpha=1);
+};
+
+static MatOp_Initializer g_MatOp_Initializer;
+    
+static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identity; }
+static inline bool isAddEx(const MatExpr& e) { return e.op == &g_MatOp_AddEx; }
+static inline bool isScaled(const MatExpr& e) { return isAddEx(e) && (!e.b.data || e.beta == 0) && e.s == Scalar(); }
+static inline bool isBin(const MatExpr& e, char c) { return e.op == &g_MatOp_Bin && e.flags == c; }
+static inline bool isReciprocal(const MatExpr& e) { return isBin(e,'/') && (!e.b.data || e.beta == 0); }
+static inline bool isT(const MatExpr& e) { return e.op == &g_MatOp_T; }
+static inline bool isInv(const MatExpr& e) { return e.op == &g_MatOp_Invert; }
+static inline bool isGEMM(const MatExpr& e) { return e.op == &g_MatOp_GEMM; }
+static inline bool isMatProd(const MatExpr& e) { return e.op == &g_MatOp_GEMM && (!e.c.data || e.beta == 0); }
+static inline bool isInitializer(const MatExpr& e) { return e.op == &g_MatOp_Initializer; }
+    
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+bool MatOp::elementWise(const MatExpr& expr) const
+{
+    return false;
+}
+    
+void MatOp::roi(const MatExpr& expr, const Range& rowRange, const Range& colRange, MatExpr& e) const
+{
+    if( elementWise(expr) )
+    {
+        e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(),
+                    expr.alpha, expr.beta, expr.s);
+        if(expr.a.data)
+            e.a = expr.a(rowRange, colRange);
+        if(expr.b.data)
+            e.b = expr.b(rowRange, colRange);
+        if(expr.c.data)
+            e.c = expr.c(rowRange, colRange);
+    }
+    else
+    {
+        Mat m;
+        expr.op->assign(expr, m);
+        e = MatExpr(&g_MatOp_Identity, 0, m(rowRange, colRange), Mat(), Mat());
+    }
+}
+    
+void MatOp::diag(const MatExpr& expr, int d, MatExpr& e) const
+{
+    if( elementWise(expr) )
+    {
+        e = MatExpr(expr.op, expr.flags, Mat(), Mat(), Mat(),
+                    expr.alpha, expr.beta, expr.s);
+        if(expr.a.data)
+            e.a = expr.a.diag(d);
+        if(expr.b.data)
+            e.b = expr.b.diag(d);
+        if(expr.c.data)
+            e.c = expr.c.diag(d);
+    }
+    else
+    {
+        Mat m;
+        expr.op->assign(expr, m);
+        e = MatExpr(&g_MatOp_Identity, 0, m.diag(d), Mat(), Mat());
+    }
+}
+
+    
+void MatOp::augAssignAdd(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m += temp;
+}
+
+    
+void MatOp::augAssignSubtract(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m -= temp;
+}
+
+    
+void MatOp::augAssignMultiply(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m *= temp;
+}
+
+    
+void MatOp::augAssignDivide(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m /= temp;
+}
+    
+    
+void MatOp::augAssignAnd(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m &= temp;
+}
+
+    
+void MatOp::augAssignOr(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m |= temp;
+}
+
+    
+void MatOp::augAssignXor(const MatExpr& expr, Mat& m) const
+{
+    Mat temp;
+    expr.op->assign(expr, temp);
+    m /= temp;
+}
+    
+
+void MatOp::add(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const
+{
+    if( this == expr2.op )
+    {
+        Mat m1, m2;
+        expr1.op->assign(expr1, m1);
+        expr2.op->assign(expr2, m2);
+        MatOp_AddEx::makeExpr(res, m1, m2, 1, 1);
+    }
+    else
+        expr2.op->add(expr1, expr2, res); 
+}
+
+    
+void MatOp::add(const MatExpr& expr1, const Scalar& s, MatExpr& res) const
+{
+    Mat m1;
+    expr1.op->assign(expr1, m1);
+    MatOp_AddEx::makeExpr(res, m1, Mat(), 1, 0, s);
+}
+
+    
+void MatOp::subtract(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const
+{
+    if( this == expr2.op )
+    {
+        Mat m1, m2;
+        expr1.op->assign(expr1, m1);
+        expr2.op->assign(expr2, m2);
+        MatOp_AddEx::makeExpr(res, m1, m2, 1, -1);
+    }
+    else
+        expr2.op->subtract(expr1, expr2, res);
+}
+
+    
+void MatOp::subtract(const Scalar& s, const MatExpr& expr, MatExpr& res) const
+{
+    Mat m;
+    expr.op->assign(expr, m);
+    MatOp_AddEx::makeExpr(res, m, Mat(), -1, 0, s);
+}
+
+    
+void MatOp::multiply(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale) const
+{
+    if( this == expr2.op )
+    {
+        Mat m1, m2;
+        expr1.op->assign(expr1, m1);
+        expr2.op->assign(expr2, m2);
+        MatOp_Bin::makeExpr(res, '*', m1, m2, scale);
+    }
+    else
+        expr2.op->multiply(expr1, expr2, res, scale);
+}
+    
+void MatOp::multiply(const MatExpr& expr, double s, MatExpr& res) const
+{
+    Mat m;
+    expr.op->assign(expr, m);
+    MatOp_AddEx::makeExpr(res, m, Mat(), s, 0); 
+}
+    
+    
+void MatOp::divide(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res, double scale) const
+{
+    if( this == expr2.op )
+    {
+        Mat m1, m2;
+        expr1.op->assign(expr1, m1);
+        expr2.op->assign(expr2, m2);
+        MatOp_Bin::makeExpr(res, '/', m1, m2, scale);
+    }
+    else
+        expr2.op->divide(expr1, expr2, res, scale);
+}
+
+    
+void MatOp::divide(double s, const MatExpr& expr, MatExpr& res) const
+{
+    Mat m;
+    expr.op->assign(expr, m);
+    MatOp_Bin::makeExpr(res, '/', m, Mat(), s);
+}
+
+    
+void MatOp::abs(const MatExpr& expr, MatExpr& res) const
+{
+    Mat m;
+    expr.op->assign(expr, m);
+    MatOp_Bin::makeExpr(res, 'a', m, Mat());
+}
+
+    
+void MatOp::transpose(const MatExpr& expr, MatExpr& res) const
+{
+    Mat m;
+    expr.op->assign(expr, m);
+    MatOp_T::makeExpr(res, m, 1);
+}
+
+    
+void MatOp::matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const
+{
+    if( this == expr2.op )
+    {
+        Mat m1, m2;
+        expr1.op->assign(expr1, m1);
+        expr2.op->assign(expr2, m2);
+        MatOp_GEMM::makeExpr(res, 0, m1, m2);
+    }
+    else
+        expr2.op->matmul(expr1, expr2, res);
+}
+
+    
+void MatOp::invert(const MatExpr& expr, int method, MatExpr& res) const
+{
+    Mat m;
+    expr.op->assign(expr, m);
+    MatOp_Invert::makeExpr(res, method, m);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+MatExpr::MatExpr(const Mat& m) : op(&g_MatOp_Identity), flags(0), a(m), b(Mat()), c(Mat()), alpha(1), beta(0), s(Scalar())
+{
+}
+    
+MatExpr MatExpr::row(int y) const
+{
+    MatExpr e;
+    op->roi(*this, Range(y, y+1), Range::all(), e);
+    return e;
+}
+
+MatExpr MatExpr::col(int x) const
+{
+    MatExpr e;
+    op->roi(*this, Range::all(), Range(x, x+1), e);
+    return e;
+}
+
+MatExpr MatExpr::diag(int d) const
+{
+    MatExpr e;
+    op->diag(*this, d, e);
+    return e;
+}
+
+MatExpr MatExpr::operator()( const Range& rowRange, const Range& colRange ) const
+{
+    MatExpr e;
+    op->roi(*this, rowRange, colRange, e);
+    return e;
+}
+
+MatExpr MatExpr::operator()( const Rect& roi ) const
+{
+    MatExpr e;
+    op->roi(*this, Range(roi.y, roi.y + roi.height), Range(roi.x, roi.x + roi.width), e);
+    return e;
+}
+
+Mat MatExpr::cross(const Mat& m) const
+{
+    return ((Mat)*this).cross(m);
+}
+
+double MatExpr::dot(const Mat& m) const
+{
+    return ((Mat)*this).dot(m);
+}
+
+MatExpr MatExpr::t() const
+{
+    MatExpr e;
+    op->transpose(*this, e);
+    return e;
+}
+
+MatExpr MatExpr::inv(int method) const
+{
+    MatExpr e;
+    op->invert(*this, method, e);
+    return e;
+}
+
+MatExpr MatExpr::mul(const MatExpr& e, double scale) const
+{
+    MatExpr en;
+    op->multiply(*this, e, en, scale);
+    return en;
+}
+
+MatExpr MatExpr::mul(const Mat& m, double scale) const
+{
+    MatExpr e;
+    op->multiply(*this, MatExpr(m), e, scale);
+    return e;
+}
+
+MatExpr operator + (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, b, 1, 1);
+    return e;
+}
+    
+MatExpr operator + (const Mat& a, const Scalar& s)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s);
+    return e;
+}
+                   
+MatExpr operator + (const Scalar& s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, s);
+    return e;
+}                   
+                   
+MatExpr operator + (const MatExpr& e, const Mat& m)
+{
+    MatExpr en;
+    e.op->add(e, MatExpr(m), en);
+    return en;
+}
+                   
+MatExpr operator + (const Mat& m, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->add(e, MatExpr(m), en);
+    return en;
+} 
+                   
+MatExpr operator + (const MatExpr& e, const Scalar& s)
+{
+    MatExpr en;
+    e.op->add(e, s, en);
+    return en;
+}
+                   
+MatExpr operator + (const Scalar& s, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->add(e, s, en);
+    return en;
+}
+
+MatExpr operator + (const MatExpr& e1, const MatExpr& e2)
+{
+    MatExpr en;
+    e1.op->add(e1, e2, en);
+    return en;
+}
+
+MatExpr operator - (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, b, 1, -1);
+    return e;
+}
+    
+MatExpr operator - (const Mat& a, const Scalar& s)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), 1, 0, -s);
+    return e;
+}
+    
+MatExpr operator - (const Scalar& s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), -1, 0, s);
+    return e;
+}
+    
+MatExpr operator - (const MatExpr& e, const Mat& m)
+{
+    MatExpr en;
+    e.op->subtract(e, MatExpr(m), en);
+    return en;
+}
+    
+MatExpr operator - (const Mat& m, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->subtract(MatExpr(m), e, en);
+    return en;
+}
+    
+MatExpr operator - (const MatExpr& e, const Scalar& s)
+{
+    MatExpr en;
+    e.op->add(e, -s, en);
+    return en;
+}
+    
+MatExpr operator - (const Scalar& s, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->subtract(s, e, en);
+    return en;
+}
+    
+MatExpr operator - (const MatExpr& e1, const MatExpr& e2)
+{
+    MatExpr en;
+    e1.op->subtract(e1, e2, en);
+    return en;
+}
+
+MatExpr operator - (const Mat& m)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, m, Mat(), -1, 0);
+    return e;
+}
+    
+MatExpr operator - (const MatExpr& e)
+{
+    MatExpr en;
+    e.op->subtract(Scalar(0), e, en);
+    return en;
+}
+
+MatExpr operator * (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_GEMM::makeExpr(e, 0, a, b);
+    return e;
+}
+
+MatExpr operator * (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), s, 0);
+    return e;
+}
+
+MatExpr operator * (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), s, 0);
+    return e;
+}
+
+MatExpr operator * (const MatExpr& e, const Mat& m)
+{
+    MatExpr en;
+    e.op->matmul(e, MatExpr(m), en);
+    return en;
+}
+
+MatExpr operator * (const Mat& m, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->matmul(MatExpr(m), e, en);
+    return en;
+}
+
+MatExpr operator * (const MatExpr& e, double s)
+{
+    MatExpr en;
+    e.op->multiply(e, s, en);
+    return en;
+}
+
+MatExpr operator * (double s, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->multiply(e, s, en);
+    return en;
+}
+
+MatExpr operator * (const MatExpr& e1, const MatExpr& e2)
+{
+    MatExpr en;
+    e1.op->matmul(e1, e2, en);
+    return en;
+}
+
+MatExpr operator / (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '/', a, b);
+    return e;
+}
+    
+MatExpr operator / (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_AddEx::makeExpr(e, a, Mat(), 1./s, 0);
+    return e;
+}
+    
+MatExpr operator / (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '/', a, Mat(), s);
+    return e;
+}
+    
+MatExpr operator / (const MatExpr& e, const Mat& m)
+{
+    MatExpr en;
+    e.op->divide(e, MatExpr(m), en);
+    return en;
+}
+    
+MatExpr operator / (const Mat& m, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->divide(MatExpr(m), e, en);
+    return en;
+}
+    
+MatExpr operator / (const MatExpr& e, double s)
+{
+    MatExpr en;
+    e.op->multiply(e, 1./s, en);
+    return en;
+}
+    
+MatExpr operator / (double s, const MatExpr& e)
+{
+    MatExpr en;
+    e.op->divide(s, e, en);
+    return en;
+}
+    
+MatExpr operator / (const MatExpr& e1, const MatExpr& e2)
+{
+    MatExpr en;
+    e1.op->divide(e1, e2, en);
+    return en;
+}
+
+MatExpr operator < (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, b);
+    return e;
+}
+    
+MatExpr operator < (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s);
+    return e;
+}
+    
+MatExpr operator < (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s);
+    return e;
+}
+
+MatExpr operator <= (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, b);
+    return e;
+}
+
+MatExpr operator <= (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s);
+    return e;
+}
+
+MatExpr operator <= (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s);
+    return e;
+}
+
+MatExpr operator == (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, b);
+    return e;
+}
+
+MatExpr operator == (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s);
+    return e;
+}
+
+MatExpr operator == (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_EQ, a, s);
+    return e;
+}
+
+MatExpr operator != (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, b);
+    return e;
+}
+
+MatExpr operator != (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s);
+    return e;
+}
+
+MatExpr operator != (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_NE, a, s);
+    return e;
+}
+    
+MatExpr operator >= (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, b);
+    return e;
+}
+
+MatExpr operator >= (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_GE, a, s);
+    return e;
+}
+
+MatExpr operator >= (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_LE, a, s);
+    return e;
+}
+
+MatExpr operator > (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, b);
+    return e;
+}
+
+MatExpr operator > (const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_GT, a, s);
+    return e;
+}
+
+MatExpr operator > (double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Cmp::makeExpr(e, CV_CMP_LT, a, s);
+    return e;
+}    
+    
+MatExpr min(const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'm', a, b);
+    return e;
+}
+    
+MatExpr min(const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'm', a, s);
+    return e;
+}
+    
+MatExpr min(double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'm', a, s);
+    return e;
+}
+
+MatExpr max(const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'M', a, b);
+    return e;
+}
+    
+MatExpr max(const Mat& a, double s)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'M', a, s);
+    return e;
+}
+    
+MatExpr max(double s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'M', a, s);
+    return e;
+}
+
+MatExpr operator & (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '&', a, b);
+    return e;
+}
+    
+MatExpr operator & (const Mat& a, const Scalar& s)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '&', a, s);
+    return e;
+}
+    
+MatExpr operator & (const Scalar& s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '&', a, s);
+    return e;
+}
+    
+MatExpr operator | (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '|', a, b);
+    return e;
+}
+    
+MatExpr operator | (const Mat& a, const Scalar& s)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '|', a, s);
+    return e;
+}
+    
+MatExpr operator | (const Scalar& s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '|', a, s);
+    return e;
+}
+
+MatExpr operator ^ (const Mat& a, const Mat& b)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '^', a, b);
+    return e;
+}
+
+MatExpr operator ^ (const Mat& a, const Scalar& s)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '^', a, s);
+    return e;
+}
+
+MatExpr operator ^ (const Scalar& s, const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '^', a, s);
+    return e;
+}
+
+MatExpr operator ~(const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '~', a, Scalar());
+    return e;
+}
+
+MatExpr abs(const Mat& a)
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, 'a', a, Scalar());
+    return e;
+}
+
+MatExpr abs(const MatExpr& e)
+{
+    MatExpr en;
+    e.op->abs(e, en);
+    return en;
+}
+
+    
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+inline void MatOp_Identity::makeExpr(MatExpr& res, const Mat& m)
+{
+    res = MatExpr(&g_MatOp_Identity, 0, m, Mat(), Mat(), 1, 0);
+}
+                  
+void MatOp_Identity::assign(const MatExpr& e, Mat& m, int type) const
+{
+    if( type == -1 || type == e.a.type() )
+        m = e.a;
+    else
+    {
+        CV_Assert( CV_MAT_CN(type) == e.a.channels() );
+        e.a.convertTo(m, type);
+    }
+}
+
+void MatOp_Identity::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    if( isIdentity(e2) )
+    {
+        if( isIdentity(e1) )
+            MatOp_AddEx::makeExpr(res, e1.a, e2.a, 1, 1);
+        else
+            MatOp::add(e1, e2, res);
+    }
+    else
+        e2.op->add(e1, e2, res);
+}
+
+void MatOp_Identity::add(const MatExpr& e, const Scalar& s, MatExpr& res) const
+{
+    MatOp_AddEx::makeExpr(res, e.a, Mat(), 1, 0, s);
+}    
+    
+void MatOp_Identity::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    if( isIdentity(e2) )
+    {
+        if( isIdentity(e1) )
+            MatOp_AddEx::makeExpr(res, e1.a, e2.a, 1, -1);
+        else
+            MatOp::subtract(e1, e2, res);
+    }
+    else
+        e2.op->subtract(e1, e2, res);
+}
+
+void MatOp_Identity::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) const
+{
+    MatOp_AddEx::makeExpr(res, e.a, Mat(), -1, 0, s);
+}        
+    
+void MatOp_Identity::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
+{
+    if( isIdentity(e2) )
+    {
+        if( isIdentity(e1) )
+            MatOp_Bin::makeExpr(res, '*', e1.a, e2.a, scale);
+        else
+            MatOp::multiply(e1, e2, res, scale);
+    }
+    else
+        e2.op->multiply(e1, e2, res, scale);
+}
+    
+void MatOp_Identity::multiply(const MatExpr& e, double s, MatExpr& res) const
+{
+    MatOp_AddEx::makeExpr(res, e.a, Mat(), s, 0);
+}        
+    
+void MatOp_Identity::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
+{
+    if( isIdentity(e2) )
+    {
+        if( isIdentity(e1) )
+            MatOp_Bin::makeExpr(res, '/', e1.a, e2.a, scale);
+        else
+            MatOp::divide(e1, e2, res, scale);
+    }
+    else
+        e2.op->divide(e1, e2, res, scale);
+}
+
+void MatOp_Identity::divide(double s, const MatExpr& e, MatExpr& res) const
+{
+    MatOp_Bin::makeExpr(res, '/', e.a, Mat(), s);
+} 
+
+void MatOp_Identity::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    if( isIdentity(e2) )
+    {
+        if( isIdentity(e1) )
+            MatOp_GEMM::makeExpr(res, 0, e1.a, e2.a);
+        else
+            MatOp::matmul(e1, e2, res);
+    }
+    else
+        e2.op->matmul(e1, e2, res);
+}
+    
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void MatOp_AddEx::assign(const MatExpr& e, Mat& m, int type) const
+{    
+    Mat temp, &dst = type == -1 || e.a.type() == type ? m : temp;
+    if( e.b.data )
+    {
+        if( e.s == Scalar() || !e.s.isReal() )
+        {
+            if( e.alpha == 1 )
+            {
+                if( e.beta == 1 )
+                    cv::add(e.a, e.b, dst);
+                else if( e.beta == -1 )
+                    cv::subtract(e.a, e.b, dst);
+                else
+                    cv::scaleAdd(e.b, e.beta, e.a, dst);
+            }
+            else if( e.beta == 1 )
+            {
+                if( e.alpha == -1 )
+                    cv::subtract(e.b, e.a, dst);
+                else
+                    cv::scaleAdd(e.a, e.alpha, e.b, dst);
+            }
+            else
+                cv::addWeighted(e.a, e.alpha, e.b, e.beta, 0, dst);
+            
+            if( !e.s.isReal() )
+                cv::add(dst, e.s, dst);
+        }
+        else
+            cv::addWeighted(e.a, e.alpha, e.b, e.beta, e.s[0], dst);
+    }
+    else if( e.s.isReal() && (dst.data != m.data || fabs(e.alpha) != 1))
+    {
+        e.a.convertTo(m, type, e.alpha, e.s[0]);
+        return;
+    }
+    else if( e.alpha == 1 )
+        cv::add(e.a, e.s, dst);
+    else if( e.alpha == -1 )
+        cv::subtract(e.s, e.a, dst);
+    else
+    {
+        e.a.convertTo(dst, e.a.type(), e.alpha);
+        cv::add(dst, e.s, dst);
+    }
+    
+    if( dst.data != m.data )
+        dst.convertTo(m, m.type());
+}
+
+    
+void MatOp_AddEx::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    
+    if( ((isAddEx(e2) && !e2.b.data) || i2) && ((isAddEx(e1) && !e1.b.data) || i1) )
+        MatOp_AddEx::makeExpr(res, e1.a, e2.a, i1 ? 1 : e1.alpha, i2 ? 1 : e2.alpha,
+                              (i1 ? Scalar() : e1.s) + (i2 ? Scalar() : e2.s));
+    else if( e2.op == this )
+        MatOp::add(e1, e2, res);
+    else
+        e2.op->add(e1, e2, res);
+}
+    
+    
+void MatOp_AddEx::add(const MatExpr& e, const Scalar& s, MatExpr& res) const
+{
+    res = e;
+    res.s += s;
+}
+
+    
+void MatOp_AddEx::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    
+    if( ((isAddEx(e2) && !e2.b.data) || i2) && ((isAddEx(e1) && !e1.b.data) || i1) )
+        MatOp_AddEx::makeExpr(res, e1.a, e2.a, i1 ? 1 : e1.alpha, i2 ? -1 : -e2.alpha,
+                              (i1 ? Scalar() : e1.s) - (i2 ? Scalar() : e2.s));
+    else if( e2.op == this )
+        MatOp::subtract(e1, e2, res);
+    else
+        e2.op->subtract(e1, e2, res);
+}
+
+    
+void MatOp_AddEx::subtract(const Scalar& s, const MatExpr& e, MatExpr& res) const
+{
+    res = e;
+    res.alpha = -res.alpha;
+    res.beta = -res.beta;
+    res.s = s - res.s;
+}
+
+    
+void MatOp_AddEx::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    
+    if( (isScaled(e1) || i1) && (isScaled(e2) || i2) )
+        MatOp_Bin::makeExpr(res, '*', e1.a, e2.a, scale*(i1 ? 1 : e1.alpha)*(i2 ? 1 : e2.alpha));
+    else if( this == e2.op )
+        MatOp::multiply(e1, e2, res, scale);
+    else
+        e2.op->multiply(e1, e2, res, scale);
+}
+
+    
+void MatOp_AddEx::multiply(const MatExpr& e, double s, MatExpr& res) const
+{
+    res = e;
+    res.alpha *= s;
+    res.beta *= s;
+    res.s *= s;
+}
+
+    
+void MatOp_AddEx::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    
+    if( (isScaled(e1) || i1) && (isScaled(e2) || i2) )
+        MatOp_Bin::makeExpr(res, '/', e1.a, e2.a, scale*(i1 ? 1 : e1.alpha)*(i2 ? 1 : 1./e2.alpha));
+    else if( this == e2.op )
+        MatOp::divide(e1, e2, res, scale);
+    else
+        e2.op->divide(e1, e2, res, scale);
+}
+
+    
+void MatOp_AddEx::divide(double s, const MatExpr& e, MatExpr& res) const
+{
+    if( isScaled(e) )
+        MatOp_Bin::makeExpr(res, '/', e.a, Mat(), s/e.alpha);
+    else
+        MatOp::divide(s, e, res);
+}
+
+
+void MatOp_AddEx::transpose(const MatExpr& e, MatExpr& res) const
+{
+    if( isScaled(e) )
+        MatOp_T::makeExpr(res, e.a, e.alpha);
+    else
+        MatOp::transpose(e, res);
+}
+    
+void MatOp_AddEx::abs(const MatExpr& e, MatExpr& res) const
+{
+    if( (!e.b.data || e.beta == 0) && fabs(e.alpha) == 1 )
+        MatOp_Bin::makeExpr(res, 'a', e.a, -e.s*e.alpha);
+    else if( e.b.data && e.alpha + e.beta == 0 && e.alpha*e.beta == -1 )
+        MatOp_Bin::makeExpr(res, 'a', e.a, e.b);
+    else
+        MatOp::abs(e, res);
+}
+
+void MatOp_AddEx::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
+    
+    if( (isScaled(e1) || i1) && (isScaled(e2) || i2) )
+        MatOp_GEMM::makeExpr(res, 0, e1.a, e2.a, alpha1*alpha2);
+    else if( this == e2.op )
+        MatOp::matmul(e1, e2, res);
+    else
+        e2.op->matmul(e1, e2, res);
+}
+
+    
+inline void MatOp_AddEx::makeExpr(MatExpr& res, const Mat& a, const Mat& b, double alpha, double beta, const Scalar& s)
+{
+    res = MatExpr(&g_MatOp_AddEx, 0, a, b, Mat(), alpha, beta, s);
+}
+    
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_Bin::assign(const MatExpr& e, Mat& m, int type) const
+{
+    Mat temp, &dst = type == -1 || e.a.type() == type ? m : temp;
+    
+    if( e.flags == '*' )
+        cv::multiply(e.a, e.b, dst, e.alpha);
+    else if( e.flags == '/' && e.b.data )
+        cv::divide(e.a, e.b, dst, e.alpha);
+    else if( e.flags == '/' && !e.b.data )
+        cv::divide(e.alpha, e.a, dst );
+    else if( e.flags == '&' && e.b.data )
+        bitwise_and(e.a, e.b, dst);
+    else if( e.flags == '&' && !e.b.data )
+        bitwise_and(e.a, e.s, dst);
+    else if( e.flags == '|' && e.b.data )
+        bitwise_or(e.a, e.b, dst);
+    else if( e.flags == '|' && !e.b.data )
+        bitwise_or(e.a, e.s, dst);
+    else if( e.flags == '^' && e.b.data )
+        bitwise_xor(e.a, e.b, dst);
+    else if( e.flags == '^' && !e.b.data )
+        bitwise_xor(e.a, e.s, dst);
+    else if( e.flags == '~' && !e.b.data )
+        bitwise_not(e.a, dst);
+    else if( e.flags == 'm' && e.b.data )
+        cv::min(e.a, e.b, dst);
+    else if( e.flags == 'm' && !e.b.data )
+        cv::min(e.a, e.s[0], dst);
+    else if( e.flags == 'M' && e.b.data )
+        cv::max(e.a, e.b, dst);
+    else if( e.flags == 'M' && !e.b.data )
+        cv::max(e.a, e.s[0], dst);
+    else if( e.flags == 'a' && e.b.data )
+        cv::absdiff(e.a, e.b, dst);
+    else if( e.flags == 'a' && !e.b.data )
+        cv::absdiff(e.a, e.s, dst);
+    else
+        CV_Error(CV_StsError, "Unknown operation");
+    
+    if( dst.data != m.data )
+        dst.convertTo(m, type);
+}
+
+void MatOp_Bin::multiply(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
+{
+    if( isReciprocal(e1) && (isIdentity(e2) || isScaled(e2)) )
+        MatOp_Bin::makeExpr(res, '/', e2.a, e1.a, e1.alpha*(isIdentity(e2) ? 1 : e2.alpha)*scale);
+    else if( isReciprocal(e2) && (isIdentity(e1) || isScaled(e1)) )
+        MatOp_Bin::makeExpr(res, '/', e1.a, e2.a, (isIdentity(e1) ? 1 : e1.alpha)*e2.alpha*scale);
+    else if( e2.op == this )
+        MatOp::multiply(e1, e2, res, scale);
+    else
+        e2.op->multiply(e1, e2, res, scale);
+}
+
+void MatOp_Bin::multiply(const MatExpr& e, double s, MatExpr& res) const
+{
+    if( e.flags == '*' || e.flags == '/' )
+    {
+        res = e;
+        res.alpha *= s;
+    }
+    else
+        MatOp::multiply(e, s, res);
+}
+
+void MatOp_Bin::divide(const MatExpr& e1, const MatExpr& e2, MatExpr& res, double scale) const
+{
+    if( isReciprocal(e2) )
+    {
+        if( isIdentity(e1) || isScaled(e1) )
+        {
+            MatOp_Bin::makeExpr(res, '*', e1.a, e2.a, (isIdentity(e1) ? 1 : e1.alpha)*scale/e2.alpha);
+            return;
+        }
+        if( isReciprocal(e1) )
+        {
+            MatOp_Bin::makeExpr(res, '/', e2.a, e1.a, e1.alpha*scale/e2.alpha);
+            return;
+        }
+    }
+    if( e2.op == this )
+        MatOp::divide(e1, e2, res, scale);
+    else
+        e2.op->divide(e1, e2, res, scale);
+}
+
+void MatOp_Bin::divide(double s, const MatExpr& e, MatExpr& res) const
+{
+    if( e.flags == '/' && !e.b.data )
+        MatOp_AddEx::makeExpr(res, e.a, Mat(), s/e.alpha, 0);
+    else
+        MatOp::divide(s, e, res);
+}
+
+inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Mat& b, double scale)
+{
+    res = MatExpr(&g_MatOp_Bin, op, a, b, Mat(), scale, b.data ? 1 : 0);
+}
+
+inline void MatOp_Bin::makeExpr(MatExpr& res, char op, const Mat& a, const Scalar& s)
+{
+    res = MatExpr(&g_MatOp_Bin, op, a, Mat(), Mat(), 1, 0, s);
+}
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_Cmp::assign(const MatExpr& e, Mat& m, int type) const
+{
+    Mat temp, &dst = type == -1 || type == CV_8U ? m : temp;
+    
+    if( e.b.data )
+        cv::compare(e.a, e.b, dst, e.flags);
+    else
+        cv::compare(e.a, e.alpha, dst, e.flags);
+    
+    if( dst.data != m.data )
+        dst.convertTo(m, type);
+}
+
+inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, const Mat& b)
+{
+    res = MatExpr(&g_MatOp_Cmp, cmpop, a, b, Mat(), 1, 1);
+}
+        
+inline void MatOp_Cmp::makeExpr(MatExpr& res, int cmpop, const Mat& a, double alpha)
+{
+    res = MatExpr(&g_MatOp_Cmp, cmpop, a, Mat(), Mat(), alpha, 1);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_T::assign(const MatExpr& e, Mat& m, int type) const
+{
+    Mat temp, &dst = type == -1 || type == e.a.type() ? m : temp;
+    
+    cv::transpose(e.a, dst);
+    
+    if( dst.data != m.data || e.alpha != 1 )
+        dst.convertTo(m, type, e.alpha);
+}
+
+void MatOp_T::multiply(const MatExpr& e, double s, MatExpr& res) const
+{
+    res = e;
+    res.alpha *= s;
+}
+    
+void MatOp_T::transpose(const MatExpr& e, MatExpr& res) const
+{
+    if( e.alpha == 1 )
+        MatOp_Identity::makeExpr(res, e.a);
+    else
+        MatOp_AddEx::makeExpr(res, e.a, Mat(), e.alpha, 0);
+}
+    
+void MatOp_T::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
+    
+    if( isT(e1) && (isT(e2) || isScaled(e2) || i2))
+        MatOp_GEMM::makeExpr(res, CV_GEMM_A_T + (isT(e2) ? CV_GEMM_B_T : 0),
+                             e1.a, e2.a, e1.alpha*alpha2);
+    else if( isT(e2) && (isT(e1) || isScaled(e1) || i1))
+        MatOp_GEMM::makeExpr(res, CV_GEMM_B_T + (isT(e1) ? CV_GEMM_A_T : 0),
+                             e1.a, e2.a, e2.alpha*alpha1);
+    else if( this == e2.op )
+        MatOp::matmul(e1, e2, res);
+    else
+        e2.op->matmul(e1, e2, res);
+}
+
+inline void MatOp_T::makeExpr(MatExpr& res, const Mat& a, double alpha)
+{
+    res = MatExpr(&g_MatOp_T, 0, a, Mat(), Mat(), alpha, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_GEMM::assign(const MatExpr& e, Mat& m, int type) const
+{
+    Mat temp, &dst = type == -1 || type == e.a.type() ? m : temp;
+    
+    cv::gemm(e.a, e.b, e.alpha, e.c, e.beta, dst, e.flags);
+    if( dst.data != m.data )
+        dst.convertTo(m, type);
+}
+
+void MatOp_GEMM::add(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
+    
+    if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) )
+        MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0),
+                             e1.a, e1.b, alpha1, e2.a, alpha2);
+    else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) )
+        MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0),
+                             e2.a, e2.b, alpha2, e1.a, alpha1);
+    else if( this == e2.op )
+        MatOp::add(e1, e2, res);
+    else
+        e2.op->add(e1, e2, res);
+}
+    
+void MatOp_GEMM::subtract(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    bool i1 = isIdentity(e1), i2 = isIdentity(e2);
+    double alpha1 = i1 ? 1 : e1.alpha, alpha2 = i2 ? 1 : e2.alpha;
+    
+    if( isMatProd(e1) && (i2 || isScaled(e2) || isT(e2)) )
+        MatOp_GEMM::makeExpr(res, (e1.flags & ~CV_GEMM_C_T)|(isT(e2) ? CV_GEMM_C_T : 0),
+                             e1.a, e1.b, alpha1, e2.a, -alpha2);
+    else if( isMatProd(e2) && (i1 || isScaled(e1) || isT(e1)) )
+        MatOp_GEMM::makeExpr(res, (e2.flags & ~CV_GEMM_C_T)|(isT(e1) ? CV_GEMM_C_T : 0),
+                            e2.a, e2.b, -alpha2, e1.a, alpha1);
+    else if( this == e2.op )
+        MatOp::subtract(e1, e2, res);
+    else
+        e2.op->subtract(e1, e2, res);
+}
+
+void MatOp_GEMM::multiply(const MatExpr& e, double s, MatExpr& res) const
+{
+    res = e;
+    res.alpha *= s;
+    res.beta *= s;
+}
+    
+void MatOp_GEMM::transpose(const MatExpr& e, MatExpr& res) const
+{
+    res = e;
+    res.flags ^= CV_GEMM_A_T | CV_GEMM_B_T | CV_GEMM_C_T;
+    swap(res.a, res.b);
+}
+
+inline void MatOp_GEMM::makeExpr(MatExpr& res, int flags, const Mat& a, const Mat& b,
+                                 double alpha, const Mat& c, double beta)
+{
+    res = MatExpr(&g_MatOp_GEMM, flags, a, b, c, alpha, beta);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_Invert::assign(const MatExpr& e, Mat& m, int type) const
+{
+    Mat temp, &dst = type == -1 || type == e.a.type() ? m : temp;
+    
+    cv::invert(e.a, dst, e.flags);
+    if( dst.data != m.data )
+        dst.convertTo(m, type);
+}
+
+void MatOp_Invert::matmul(const MatExpr& e1, const MatExpr& e2, MatExpr& res) const
+{
+    if( isInv(e1) && isIdentity(e2) )
+        MatOp_Solve::makeExpr(res, e1.flags, e1.a, e2.a);
+    else if( this == e2.op )
+        MatOp::matmul(e1, e2, res);
+    else
+        e2.op->matmul(e1, e2, res);
+}
+
+inline void MatOp_Invert::makeExpr(MatExpr& res, int method, const Mat& m)
+{
+    res = MatExpr(&g_MatOp_Invert, method, m, Mat(), Mat(), 1, 0);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_Solve::assign(const MatExpr& e, Mat& m, int type) const
+{
+    Mat temp, &dst = type == -1 || type == e.a.type() ? m : temp;
+    
+    cv::solve(e.a, e.b, dst, e.flags);
+    if( dst.data != m.data )
+        dst.convertTo(m, type);
+}
+
+inline void MatOp_Solve::makeExpr(MatExpr& res, int method, const Mat& a, const Mat& b)
+{
+    res = MatExpr(&g_MatOp_Solve, method, a, b, Mat(), 1, 1);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+    
+void MatOp_Initializer::assign(const MatExpr& e, Mat& m, int type) const
+{
+    if( type == -1 )
+        type = e.a.type();
+    m.create(e.a.size(), type);
+    if( e.flags == 'I' )
+        setIdentity(m, Scalar(e.alpha));
+    else if( e.flags == '0' )
+        m = Scalar();
+    else if( e.flags == '1' )
+        m = Scalar(e.alpha);
+    else
+        CV_Error(CV_StsError, "Invalid matrix initializer type");
+}
+
+void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const
+{
+    res = e;
+    res.alpha *= s;
+}
+    
+inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, Size sz, int type, double alpha)
+{
+    res = MatExpr(&g_MatOp_Initializer, method, Mat(sz, type, (void*)0), Mat(), Mat(), alpha, 0);
+}    
+
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+MatExpr Mat::t() const
+{
+    MatExpr e;
+    MatOp_T::makeExpr(e, *this);
+    return e;
+}
+    
+MatExpr Mat::inv(int method) const
+{
+    MatExpr e;
+    MatOp_Invert::makeExpr(e, method, *this);
+    return e;
+}
+    
+
+MatExpr Mat::mul(const Mat& m, double scale) const
+{
+    MatExpr e;
+    MatOp_Bin::makeExpr(e, '*', *this, m, scale);
+    return e;
+}
+    
+MatExpr Mat::mul(const MatExpr& m, double scale) const
+{
+    MatExpr e;
+    m.op->multiply(MatExpr(*this), m, e, scale);
+    return e;
+}
+
+MatExpr Mat::zeros(int rows, int cols, int type)
+{
+    MatExpr e;
+    MatOp_Initializer::makeExpr(e, '0', Size(cols, rows), type);
+    return e;
+}
+    
+MatExpr Mat::zeros(Size size, int type)
+{
+    MatExpr e;
+    MatOp_Initializer::makeExpr(e, '0', size, type);
+    return e;
+}
+    
+MatExpr Mat::ones(int rows, int cols, int type)
+{
+    MatExpr e;
+    MatOp_Initializer::makeExpr(e, '1', Size(cols, rows), type);
+    return e;
+}
+    
+MatExpr Mat::ones(Size size, int type)
+{
+    MatExpr e;
+    MatOp_Initializer::makeExpr(e, '1', size, type);
+    return e;
+}
+
+MatExpr Mat::eye(int rows, int cols, int type)
+{
+    MatExpr e;
+    MatOp_Initializer::makeExpr(e, 'I', Size(cols, rows), type);
+    return e;
+}
+
+MatExpr Mat::eye(Size size, int type)
+{
+    MatExpr e;
+    MatOp_Initializer::makeExpr(e, 'I', size, type);
+    return e;
+}
+        
+}
+
+/* End of file. */
index 82a1e6d..319bf0f 100644 (file)
@@ -342,7 +342,7 @@ bool CV_OperationsTest::TestMat()
         m = mi.clone(); m+=(3.0 * mi * mt + d1); CHECK_DIFF_FLT(m, mi + d1 * 4);
         m = mi.clone(); m-=(3.0 * mi * mt + d1); CHECK_DIFF_FLT(m, mi - d1 * 4);
         m = mi.clone(); m*=(mt * 1.0); CHECK_DIFF_FLT(m, d1);
-        m = mi.clone(); m*=(mt * 1.0 + 1.0); CHECK_DIFF_FLT(m, d1 + mi);
+        m = mi.clone(); m*=(mt * 1.0 + Mat::eye(m.size(), m.type())); CHECK_DIFF_FLT(m, d1 + mi);
         m = mi.clone(); m*=mt_tr.t(); CHECK_DIFF_FLT(m, d1);
 
         CHECK_DIFF_FLT( (mi * 2) * mt, d2);
@@ -611,7 +611,7 @@ bool CV_OperationsTest::TestTemplateMat()
         if (Mat_<Point3f>(1, 1).channels() != 3) throw test_excep();
         if (Mat_<Point3d>(1, 1).channels() != 3) throw test_excep();
 
-        Mat_<uchar> eye = Mat_<uchar>::zeros(2, 2);  CHECK_DIFF(Mat_<uchar>::zeros(Size(2, 2)), eye);
+        Mat_<uchar> eye = Mat_<uchar>::zeros(2, 2); CHECK_DIFF(Mat_<uchar>::zeros(Size(2, 2)), eye);
         eye.at<uchar>(Point(0,0)) = 1; eye.at<uchar>(1, 1) = 1;
                 
         CHECK_DIFF(Mat_<uchar>::eye(2, 2), eye);