diff --git a/modules/calib3d/src/polynom_solver.cpp b/modules/calib3d/src/polynom_solver.cpp index beb91cafc0..5025199dd3 100644 --- a/modules/calib3d/src/polynom_solver.cpp +++ b/modules/calib3d/src/polynom_solver.cpp @@ -65,7 +65,8 @@ int solve_deg3(double a, double b, double c, double d, return 3; } else { - x0 = pow(2 * R, 1 / 3.0) - b_a_3; + double cube_root = cv::cubeRoot(2 * R); + x0 = cube_root - b_a_3; return 1; } } @@ -82,8 +83,15 @@ int solve_deg3(double a, double b, double c, double d, } // D > 0, only one real root - double AD = pow(fabs(R) + sqrt(D), 1.0 / 3.0) * (R > 0 ? 1 : (R < 0 ? -1 : 0)); - double BD = (AD == 0) ? 0 : -Q / AD; + double AD = 0.; + double BD = 0.; + double R_abs = fabs(R); + if (R_abs > DBL_EPSILON) + { + AD = cv::cubeRoot(R_abs + sqrt(D)); + AD = (R >= 0) ? AD : -AD; + BD = -Q / AD; + } // Calculate the only real root x0 = AD + BD - b_a_3; diff --git a/modules/core/include/opencv2/core/base.hpp b/modules/core/include/opencv2/core/base.hpp index 546140e9f1..12504974d9 100644 --- a/modules/core/include/opencv2/core/base.hpp +++ b/modules/core/include/opencv2/core/base.hpp @@ -587,6 +587,21 @@ _AccTp normInf(const _Tp* a, const _Tp* b, int n) */ CV_EXPORTS_W float cubeRoot(float val); +/** @overload + +cubeRoot with argument of `double` type calls `std::cbrt(double)` (C++11) or falls back on `pow()` for C++98 compilation mode. +*/ +static inline +double cubeRoot(double val) +{ +#ifdef CV_CXX11 + return std::cbrt(val); +#else + double v = pow(abs(val), 1/3.); // pow doesn't support negative inputs with fractional exponents + return val >= 0 ? v : -v; +#endif +} + /** @brief Calculates the angle of a 2D vector in degrees. The function fastAtan2 calculates the full-range angle of an input 2D vector. The angle is measured