core(MatExpr) fetch result before InputArray wrap
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 21 Feb 2020 20:30:18 +0000 (20:30 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Mon, 6 Apr 2020 15:28:32 +0000 (15:28 +0000)
- avoid multiple expression evaluations
- avoid issues with reduced support of InputArray::EXPR

modules/core/include/opencv2/core/mat.hpp
modules/core/include/opencv2/core/mat.inl.hpp
modules/core/src/matrix_expressions.cpp

index fe16ee7..4007031 100644 (file)
@@ -3580,6 +3580,8 @@ public:
     Mat cross(const Mat& m) const;
     double dot(const Mat& m) const;
 
+    void swap(MatExpr& b);
+
     const MatOp* op;
     int flags;
 
index 55b4e62..9b7df87 100644 (file)
@@ -150,9 +150,6 @@ _InputArray::_InputArray(const Mat_<_Tp>& m)
 inline _InputArray::_InputArray(const double& val)
 { init(FIXED_TYPE + FIXED_SIZE + MATX + CV_64F + ACCESS_READ, &val, Size(1,1)); }
 
-inline _InputArray::_InputArray(const MatExpr& expr)
-{ init(FIXED_TYPE + FIXED_SIZE + EXPR + ACCESS_READ, &expr); }
-
 inline _InputArray::_InputArray(const cuda::GpuMat& d_mat)
 { init(CUDA_GPU_MAT + ACCESS_READ, &d_mat); }
 
@@ -4054,6 +4051,9 @@ inline void UMatData::markDeviceCopyObsolete(bool flag)
 
 //! @endcond
 
+static inline
+void swap(MatExpr& a, MatExpr& b) { a.swap(b); }
+
 } //cv
 
 #ifdef _MSC_VER
index 57beb68..d4f8b74 100644 (file)
@@ -1821,4 +1821,37 @@ MatExpr Mat::eye(Size size, int type)
     return e;
 }
 
+void MatExpr::swap(MatExpr& other)
+{
+    using std::swap;
+
+    swap(op, other.op);
+    swap(flags, other.flags);
+
+    swap(a, other.a);
+    swap(b, other.b);
+    swap(c, other.c);
+
+    swap(alpha, other.alpha);
+    swap(beta, other.beta);
+
+    swap(s, other.s);
+}
+
+_InputArray::_InputArray(const MatExpr& expr)
+{
+#if 1
+    if (!isIdentity(expr))
+    {
+        Mat result = expr;  // TODO improve through refcount == 1 of expr.a (inplace operation is possible - except gemm?)
+        MatExpr result_expr(result);
+        swap(const_cast<MatExpr&>(expr), result_expr);
+    }
+    CV_Assert(isIdentity(expr));
+    init(FIXED_TYPE + FIXED_SIZE + MAT + ACCESS_READ, &expr.a);
+#else
+    init(FIXED_TYPE + FIXED_SIZE + EXPR + ACCESS_READ, &expr);
+#endif
+}
+
 } // cv::