Merge pull request #19583 from theroyalpekka:patch-1
authorMradul Agrawal <69335152+theroyalpekka@users.noreply.github.com>
Fri, 5 Mar 2021 13:55:52 +0000 (19:25 +0530)
committerGitHub <noreply@github.com>
Fri, 5 Mar 2021 13:55:52 +0000 (13:55 +0000)
* Update polynom_solver.cpp

This pull request is in the response to Issue  #19526. I have fixed the problem with the cube root calculation of 2*R. The Issue was in the usage of pow function with negative values of R, but if it is calculated for only positive values of R then changing x0 according to the parity of R, the Issue is resolved. Kindly consider it, Thanks!

* add cv::cubeRoot(double)

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
modules/calib3d/src/polynom_solver.cpp
modules/core/include/opencv2/core/base.hpp

index beb91cafc068aeb6cde49173f2df928a81240f45..5025199dd3ea7619ed412f734c308621464f37e7 100644 (file)
@@ -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;
index 546140e9f1d71a9f8d355fbddee345060170795a..12504974d974fb1bb097b9320a8182eb87fd0c89 100644 (file)
@@ -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