diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index d8be98750ff29301cfe718bfa13f62ac6533e641..cc2ce6d8fd3b0d0c27598bfd331b369f67bd52f0 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -2525,11 +2525,12 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters ) num /= denom; if( num_same_root > 1) { - for( j = 0; j < num_same_root / 2; j++) - { - double old_num_re = num.re; - double old_num_im = num.im; + double old_num_re = num.re; + double old_num_im = num.im; + int square_root_times = num_same_root % 2 == 0 ? num_same_root / 2 : num_same_root / 2 - 1; + for( j = 0; j < square_root_times; j++) + { num.re = old_num_re*old_num_re + old_num_im*old_num_im; num.re = std::sqrt(num.re); num.re += old_num_re; @@ -2541,6 +2542,19 @@ double cv::solvePoly( InputArray _coeffs0, OutputArray _roots0, int maxIters ) num.im = std::sqrt(num.im); if( old_num_re < 0 ) num.im = -num.im; } + + if( num_same_root % 2 != 0){ + Mat cube_coefs(4, 1, CV_32FC1); + Mat cube_roots(3, 1, CV_32FC2); + cube_coefs.at(3) = -(std::powf(old_num_re, 3)); + cube_coefs.at(2) = -(15*std::powf(old_num_re, 2) + 27*std::powf(old_num_im, 2)); + cube_coefs.at(1) = -48*old_num_re; + cube_coefs.at(0) = 64; + cv::solveCubic(cube_coefs, cube_roots); + + num.re = std::cbrt(cube_roots.at(0)); + num.im = std::sqrtf(std::powf(num.re, 2) / 3 - old_num_re / (3*num.re)); + } } roots[i] = p - num; diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 8520def0d752a2a7a0a572affc5469ef95f736b3..c07af500d39df2d3e649ab51c955dd5ce3684bee 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2372,7 +2372,7 @@ TEST(Core_SolvePoly, regression_5599) double prec; prec = cv::solvePoly(coefs, r); EXPECT_LE(prec, 1e-6); - EXPECT_EQ(4, (int)r.total()); + EXPECT_EQ(4, r.total()); //std::cout << "Preciseness = " << prec << std::endl; //std::cout << "roots:\n" << r << "\n" << std::endl; ASSERT_EQ(CV_32FC2, r.type()); @@ -2388,7 +2388,7 @@ TEST(Core_SolvePoly, regression_5599) double prec; prec = cv::solvePoly(coefs, r); EXPECT_LE(prec, 1e-6); - EXPECT_EQ(2, (int)r.total()); + EXPECT_EQ(2, r.total()); //std::cout << "Preciseness = " << prec << std::endl; //std::cout << "roots:\n" << r << "\n" << std::endl; ASSERT_EQ(CV_32FC2, r.type());