diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 85348c0b79..406556ae6d 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -44,6 +44,7 @@ #include "precomp.hpp" #include "opencl_kernels_core.hpp" #include +#include namespace cv { @@ -1998,10 +1999,10 @@ int cv::solveCubic( InputArray _coeffs, OutputArray _roots ) double Qcubed = Q * Q * Q; double d = Qcubed - R * R; - if( d >= 0 ) + if( d > 0 ) { - double theta = acos(R / std::sqrt(Qcubed)); - double sqrtQ = std::sqrt(Q); + double theta = acos(R / sqrt(Qcubed)); + double sqrtQ = sqrt(Q); double t0 = -2 * sqrtQ; double t1 = theta * (1./3); double t2 = a1 * (1./3); @@ -2010,11 +2011,27 @@ int cv::solveCubic( InputArray _coeffs, OutputArray _roots ) x2 = t0 * cos(t1 + (4.*CV_PI/3)) - t2; n = 3; } + else if( d == 0 ) + { + if(R >= 0) + { + x0 = -2*pow(R, 1./3) - a1/3; + x1 = pow(R, 1./3) - a1/3; + } + else + { + x0 = 2*pow(-R, 1./3) - a1/3; + x1 = -pow(-R, 1./3) - a1/3; + } + x2 = 0; + n = x0 == x1 ? 1 : 2; + x1 = x0 == x1 ? 0 : x1; + } else { double e; - d = std::sqrt(-d); - e = std::pow(d + fabs(R), 0.333333333333); + d = sqrt(-d); + e = pow(d + fabs(R), 1./3); if( R > 0 ) e = -e; x0 = (e + Q / e) - a1 * (1./3); diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index e44051914e..0f8bc49c7b 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2330,6 +2330,17 @@ void Core_SolvePolyTest::run( int ) pass = pass && div < err_eps; } + //test x^3 = 0 + cv::Mat coeffs_5623(4, 1, CV_64FC1); + cv::Mat r_5623(3, 1, CV_64FC2); + coeffs_5623.at(0) = 1; + coeffs_5623.at(1) = 0; + coeffs_5623.at(2) = 0; + coeffs_5623.at(3) = 0; + double prec_5623 = cv::solveCubic(coeffs_5623, r_5623); + pass = pass && r_5623.at(0) == 0 && r_5623.at(1) == 0 && r_5623.at(2) == 0; + pass = pass && prec_5623 == 1; + if (!pass) { ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);