From 936428cb3b7f918082bf1923a1a6eccf279b2020 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 21 Feb 2020 20:30:18 +0000 Subject: [PATCH] core(MatExpr) fetch result before InputArray wrap - avoid multiple expression evaluations - avoid issues with reduced support of InputArray::EXPR --- modules/core/include/opencv2/core/mat.hpp | 2 ++ modules/core/include/opencv2/core/mat.inl.hpp | 6 ++-- modules/core/src/matrix_expressions.cpp | 33 +++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index fe16ee78ee..4007031b2f 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -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; diff --git a/modules/core/include/opencv2/core/mat.inl.hpp b/modules/core/include/opencv2/core/mat.inl.hpp index 55b4e625be..9b7df87d8b 100644 --- a/modules/core/include/opencv2/core/mat.inl.hpp +++ b/modules/core/include/opencv2/core/mat.inl.hpp @@ -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 diff --git a/modules/core/src/matrix_expressions.cpp b/modules/core/src/matrix_expressions.cpp index 57beb68e71..d4f8b743cf 100644 --- a/modules/core/src/matrix_expressions.cpp +++ b/modules/core/src/matrix_expressions.cpp @@ -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(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::