From 954536073d75c3cb15e11adfe949145bb93fdf7d Mon Sep 17 00:00:00 2001
From: Alexander Alekhin <alexander.a.alekhin@gmail.com>
Date: Mon, 15 Oct 2018 18:58:11 +0000
Subject: [PATCH] core: update solveLP() interface

---
 modules/core/include/opencv2/core/optim.hpp |  2 +-
 modules/core/src/lpsolver.cpp               | 23 ++++++++++++---------
 modules/core/test/test_lpsolver.cpp         |  8 +++----
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/modules/core/include/opencv2/core/optim.hpp b/modules/core/include/opencv2/core/optim.hpp
index c4729a9c10..36c798a5fa 100644
--- a/modules/core/include/opencv2/core/optim.hpp
+++ b/modules/core/include/opencv2/core/optim.hpp
@@ -293,7 +293,7 @@ and the remaining to \f$A\f$. It should contain 32- or 64-bit floating point num
 formulation above. It will contain 64-bit floating point numbers.
 @return One of cv::SolveLPResult
  */
-CV_EXPORTS_W int solveLP(const Mat& Func, const Mat& Constr, Mat& z);
+CV_EXPORTS_W int solveLP(InputArray Func, InputArray Constr, OutputArray z);
 
 //! @}
 
diff --git a/modules/core/src/lpsolver.cpp b/modules/core/src/lpsolver.cpp
index 1a1307d5b5..951da3fd7f 100644
--- a/modules/core/src/lpsolver.cpp
+++ b/modules/core/src/lpsolver.cpp
@@ -90,18 +90,20 @@ static void swap_columns(Mat_<double>& A,int col1,int col2);
 #define SWAP(type,a,b) {type tmp=(a);(a)=(b);(b)=tmp;}
 
 //return codes:-2 (no_sol - unbdd),-1(no_sol - unfsbl), 0(single_sol), 1(multiple_sol=>least_l2_norm)
-int solveLP(const Mat& Func, const Mat& Constr, Mat& z){
+int solveLP(InputArray Func_, InputArray Constr_, OutputArray z_)
+{
     dprintf(("call to solveLP\n"));
 
     //sanity check (size, type, no. of channels)
-    CV_Assert(Func.type()==CV_64FC1 || Func.type()==CV_32FC1);
-    CV_Assert(Constr.type()==CV_64FC1 || Constr.type()==CV_32FC1);
-    CV_Assert((Func.rows==1 && (Constr.cols-Func.cols==1))||
-            (Func.cols==1 && (Constr.cols-Func.rows==1)));
-    if (!z.empty())
-        CV_CheckTypeEQ(z.type(), CV_64FC1, "");
-    else
-        CV_CheckType(z.type(), z.type() == CV_64FC1 || z.type() == CV_8UC1/*empty cv::Mat*/, "");
+    CV_Assert(Func_.type()==CV_64FC1 || Func_.type()==CV_32FC1);
+    CV_Assert(Constr_.type()==CV_64FC1 || Constr_.type()==CV_32FC1);
+    CV_Assert((Func_.rows()==1 && (Constr_.cols()-Func_.cols()==1))||
+            (Func_.cols()==1 && (Constr_.cols()-Func_.rows()==1)));
+    if (z_.fixedType())
+        CV_CheckType(z_.type(), z_.type() == CV_64FC1 || z_.type() == CV_32FC1 || z_.type() == CV_32SC1, "");
+
+    Mat Func = Func_.getMat();
+    Mat Constr = Constr_.getMat();
 
     //copy arguments for we will shall modify them
     Mat_<double> bigC=Mat_<double>(1,(Func.rows==1?Func.cols:Func.rows)+1),
@@ -129,7 +131,7 @@ int solveLP(const Mat& Func, const Mat& Constr, Mat& z){
     }
 
     //return the optimal solution
-    z.create(c.cols,1,CV_64FC1);
+    Mat z(c.cols,1,CV_64FC1);
     MatIterator_<double> it=z.begin<double>();
     unsigned int nsize = (unsigned int)N.size();
     for(int i=1;i<=c.cols;i++,it++){
@@ -140,6 +142,7 @@ int solveLP(const Mat& Func, const Mat& Constr, Mat& z){
         }
     }
 
+    z.copyTo(z_);
     return res;
 }
 
diff --git a/modules/core/test/test_lpsolver.cpp b/modules/core/test/test_lpsolver.cpp
index 97f87f4c2f..99829cbefa 100644
--- a/modules/core/test/test_lpsolver.cpp
+++ b/modules/core/test/test_lpsolver.cpp
@@ -145,10 +145,10 @@ TEST(Core_LPSolver, issue_12337)
 {
     Mat A=(cv::Mat_<double>(3,1)<<3,1,2);
     Mat B=(cv::Mat_<double>(3,4)<<1,1,3,30,2,2,5,24,4,1,2,36);
-    EXPECT_ANY_THROW(Mat1f z_float; cv::solveLP(A, B, z_float));
-    EXPECT_NO_THROW(Mat1d z_double; cv::solveLP(A, B, z_double));
-    EXPECT_ANY_THROW(Mat1i z_int; cv::solveLP(A, B, z_int));
-    //need to update interface: EXPECT_ANY_THROW(Mat1b z_8u; cv::solveLP(A, B, z_8u));
+    Mat1f z_float; cv::solveLP(A, B, z_float);
+    Mat1d z_double; cv::solveLP(A, B, z_double);
+    Mat1i z_int; cv::solveLP(A, B, z_int);
+    EXPECT_ANY_THROW(Mat1b z_8u; cv::solveLP(A, B, z_8u));
 }
 
 }} // namespace