Commit d0a36868 authored by Vitaly Tuzov's avatar Vitaly Tuzov Committed by Alexander Alekhin

Merge pull request #11904 from terfendail/matx_solve_fix

Fixed Matx::solve function for non-square matrixes (#11904)
parent 999aba38
...@@ -61,7 +61,16 @@ namespace cv ...@@ -61,7 +61,16 @@ namespace cv
namespace internal namespace internal
{ {
template<typename _Tp, int m> struct Matx_FastInvOp template<typename _Tp, int m, int n> struct Matx_FastInvOp
{
bool operator()(const Matx<_Tp, m, n>&, Matx<_Tp, n, m>&, int) const
{
CV_Assert(false);
return false;
}
};
template<typename _Tp, int m> struct Matx_FastInvOp<_Tp, m, m>
{ {
bool operator()(const Matx<_Tp, m, m>& a, Matx<_Tp, m, m>& b, int method) const bool operator()(const Matx<_Tp, m, m>& a, Matx<_Tp, m, m>& b, int method) const
{ {
...@@ -78,7 +87,7 @@ template<typename _Tp, int m> struct Matx_FastInvOp ...@@ -78,7 +87,7 @@ template<typename _Tp, int m> struct Matx_FastInvOp
} }
}; };
template<typename _Tp> struct Matx_FastInvOp<_Tp, 2> template<typename _Tp> struct Matx_FastInvOp<_Tp, 2, 2>
{ {
bool operator()(const Matx<_Tp, 2, 2>& a, Matx<_Tp, 2, 2>& b, int) const bool operator()(const Matx<_Tp, 2, 2>& a, Matx<_Tp, 2, 2>& b, int) const
{ {
...@@ -94,7 +103,7 @@ template<typename _Tp> struct Matx_FastInvOp<_Tp, 2> ...@@ -94,7 +103,7 @@ template<typename _Tp> struct Matx_FastInvOp<_Tp, 2>
} }
}; };
template<typename _Tp> struct Matx_FastInvOp<_Tp, 3> template<typename _Tp> struct Matx_FastInvOp<_Tp, 3, 3>
{ {
bool operator()(const Matx<_Tp, 3, 3>& a, Matx<_Tp, 3, 3>& b, int) const bool operator()(const Matx<_Tp, 3, 3>& a, Matx<_Tp, 3, 3>& b, int) const
{ {
...@@ -118,7 +127,17 @@ template<typename _Tp> struct Matx_FastInvOp<_Tp, 3> ...@@ -118,7 +127,17 @@ template<typename _Tp> struct Matx_FastInvOp<_Tp, 3>
}; };
template<typename _Tp, int m, int n> struct Matx_FastSolveOp template<typename _Tp, int m, int l, int n> struct Matx_FastSolveOp
{
bool operator()(const Matx<_Tp, m, l>&, const Matx<_Tp, m, n>&,
Matx<_Tp, l, n>&, int) const
{
CV_Assert(false);
return false;
}
};
template<typename _Tp, int m, int n> struct Matx_FastSolveOp<_Tp, m, m, n>
{ {
bool operator()(const Matx<_Tp, m, m>& a, const Matx<_Tp, m, n>& b, bool operator()(const Matx<_Tp, m, m>& a, const Matx<_Tp, m, n>& b,
Matx<_Tp, m, n>& x, int method) const Matx<_Tp, m, n>& x, int method) const
...@@ -132,7 +151,7 @@ template<typename _Tp, int m, int n> struct Matx_FastSolveOp ...@@ -132,7 +151,7 @@ template<typename _Tp, int m, int n> struct Matx_FastSolveOp
} }
}; };
template<typename _Tp> struct Matx_FastSolveOp<_Tp, 2, 1> template<typename _Tp> struct Matx_FastSolveOp<_Tp, 2, 2, 1>
{ {
bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b, bool operator()(const Matx<_Tp, 2, 2>& a, const Matx<_Tp, 2, 1>& b,
Matx<_Tp, 2, 1>& x, int) const Matx<_Tp, 2, 1>& x, int) const
...@@ -147,7 +166,7 @@ template<typename _Tp> struct Matx_FastSolveOp<_Tp, 2, 1> ...@@ -147,7 +166,7 @@ template<typename _Tp> struct Matx_FastSolveOp<_Tp, 2, 1>
} }
}; };
template<typename _Tp> struct Matx_FastSolveOp<_Tp, 3, 1> template<typename _Tp> struct Matx_FastSolveOp<_Tp, 3, 3, 1>
{ {
bool operator()(const Matx<_Tp, 3, 3>& a, const Matx<_Tp, 3, 1>& b, bool operator()(const Matx<_Tp, 3, 3>& a, const Matx<_Tp, 3, 1>& b,
Matx<_Tp, 3, 1>& x, int) const Matx<_Tp, 3, 1>& x, int) const
...@@ -195,7 +214,7 @@ Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const ...@@ -195,7 +214,7 @@ Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const
Matx<_Tp, n, m> b; Matx<_Tp, n, m> b;
bool ok; bool ok;
if( m == n && (method == DECOMP_LU || method == DECOMP_CHOLESKY) ) if( m == n && (method == DECOMP_LU || method == DECOMP_CHOLESKY) )
ok = cv::internal::Matx_FastInvOp<_Tp, m>()(*reinterpret_cast<const Matx<_Tp, m, m>*>(this), reinterpret_cast<Matx<_Tp, m, m>&>(b), method); ok = cv::internal::Matx_FastInvOp<_Tp, m, n>()(*this, b, method);
else else
{ {
Mat A(*this, false), B(b, false); Mat A(*this, false), B(b, false);
...@@ -210,8 +229,8 @@ Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) c ...@@ -210,8 +229,8 @@ Matx<_Tp, n, l> Matx<_Tp, m, n>::solve(const Matx<_Tp, m, l>& rhs, int method) c
{ {
Matx<_Tp, n, l> x; Matx<_Tp, n, l> x;
bool ok; bool ok;
if( method == DECOMP_LU || method == DECOMP_CHOLESKY ) if( m == n && (method == DECOMP_LU || method == DECOMP_CHOLESKY) )
ok = cv::internal::Matx_FastSolveOp<_Tp, m, l>()(*this, rhs, x, method); ok = cv::internal::Matx_FastSolveOp<_Tp, m, n, l>()(*this, rhs, x, method);
else else
{ {
Mat A(*this, false), B(rhs, false), X(x, false); Mat A(*this, false), B(rhs, false), X(x, false);
......
...@@ -3129,6 +3129,21 @@ TEST(Core_QR_Solver, accuracy64f) ...@@ -3129,6 +3129,21 @@ TEST(Core_QR_Solver, accuracy64f)
ASSERT_FALSE(solve(A, B, solutionQR, DECOMP_QR)); ASSERT_FALSE(solve(A, B, solutionQR, DECOMP_QR));
} }
TEST(Core_Solve, regression_11888)
{
cv::Matx<float, 3, 2> A(
2, 1,
3, 1,
6, 1
);
cv::Vec<float, 3> b(4, 5, 7);
cv::Matx<float, 2, 1> xQR = A.solve(b, DECOMP_QR);
cv::Matx<float, 2, 1> xSVD = A.solve(b, DECOMP_SVD);
EXPECT_LE(cvtest::norm(xQR, xSVD, CV_RELATIVE_L2), FLT_EPSILON);
cv::Matx<float, 2, 3> iA = A.inv(DECOMP_SVD);
EXPECT_LE(cvtest::norm(A*iA, Matx<float, 3, 3>::eye(), CV_RELATIVE_L2), 0.6);
}
softdouble naiveExp(softdouble x) softdouble naiveExp(softdouble x)
{ {
int exponent = x.getExp(); int exponent = x.getExp();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment