8#ifndef META_OCEAN_MATH_EQUATION_H
9#define META_OCEAN_MATH_EQUATION_H
22template <
typename T>
class EquationT;
66 static bool solveLinear(
const T a,
const T b, T& x);
80 static bool solveQuadratic(
const T a,
const T b,
const T c, T& x1, T& x2);
97 static unsigned int solveCubic(
const T a,
const T b,
const T c,
const T d, T& x1, T& x2, T& x3,
const bool refine =
true);
113 static unsigned int solveQuartic(
const T a,
const T b,
const T c,
const T d,
const T e, T* x,
const bool refine =
true);
130 static unsigned int optimizeCubic(
const T a,
const T b,
const T c,
const T d, T& x,
const unsigned int maxIterations = 10u,
const T updateFactor = T(1.0));
148 static unsigned int optimizeQuartic(
const T a,
const T b,
const T c,
const T d,
const T e, T& x,
const unsigned int maxIterations = 10u,
const T updateFactor = T(1.0));
182 const T value = b * b - T(4) * a * c;
193 x1 = -b / (T(2) * a);
212 if (std::is_same<T, float>::value)
242 const T alpha = b * a1;
243 const T beta = c * a1;
244 const T gamma = d * a1;
249 const T alpha2 = alpha * alpha;
252 const T q = (alpha2 - T(3) * beta) * T(0.11111111111111111111111111111111);
255 const T r = (T(2) * alpha2 * alpha - T(9) * alpha * beta + T(27) * gamma) * T(0.018518518518518518518518518518519);
261 const T q3 = q * q * q;
269 const T angle_3 =
NumericT<T>::acos(minmax<T>(-1, r / (q * sqrtQ), 1)) * T(0.33333333333333333333333333333333);
272 const T alpha_3 = alpha * T(0.33333333333333333333333333333333);
274 const T factor = T(-2) * sqrtQ;
280 x2 = factor *
NumericT<T>::cos(angle_3 + T(2.0943951023931954923084289221863)) - alpha_3;
283 x3 = factor *
NumericT<T>::cos(angle_3 - T(2.0943951023931954923084289221863)) - alpha_3;
287 const T value1 = a * x1 * x1 * x1 + b * x1 * x1 + c * x1 + d;
288 const T value2 = a * x2 * x2 * x2 + b * x2 * x2 + c * x2 + d;
289 const T value3 = a * x3 * x3 * x3 + b * x3 * x3 + c * x3 + d;
292 if (!std::is_same<T, float>::value)
302 optimizeCubic(a, b, c, d, x1);
303 optimizeCubic(a, b, c, d, x2);
304 optimizeCubic(a, b, c, d, x3);
320 x1 = m + n - alpha * T(0.33333333333333333333333333333333);
324 const T value1 = a * x1 * x1 * x1 + b * x1 * x1 + c * x1 + d;
327 if (!std::is_same<T, float>::value)
336 optimizeCubic(a, b, c, d, x1);
346 ocean_assert(x !=
nullptr);
359 const T a1 = T(1.0) / a;
362 const T b_a = b * a1;
365 const T c_a = c * a1;
368 const T b_a2 = b_a * b_a;
371 const T b_a3 = b_a2 * b_a;
374 const T d_a = d * a1;
377 const T alpha = T(-0.375) * b_a2 + c_a;
380 const T beta = T(0.125) * b_a3 - T(0.5) * b_a * c_a + d_a;
383 const T gamma = T(-0.01171875) * b_a3 * b_a + T(0.0625) * b_a2 * c_a - T(0.25) * b_a * d_a + e * a1;
387 unsigned int solutions = 0u;
391 const std::complex<T> cx1 = std::complex<T>(T(-0.25)) * std::complex<T>(b / a) +
NumericT<T>::sqrt(std::complex<T>(T(0.5)) * (std::complex<T>(-alpha) +
NumericT<T>::sqrt(std::complex<T>(alpha * alpha - 4 * gamma))));
392 const std::complex<T> cx2 = std::complex<T>(T(-0.25)) * std::complex<T>(b / a) +
NumericT<T>::sqrt(std::complex<T>(T(0.5)) * (std::complex<T>(-alpha) -
NumericT<T>::sqrt(std::complex<T>(alpha * alpha - 4 * gamma))));
393 const std::complex<T> cx3 = std::complex<T>(T(-0.25)) * std::complex<T>(b / a) -
NumericT<T>::sqrt(std::complex<T>(T(0.5)) * (std::complex<T>(-alpha) +
NumericT<T>::sqrt(std::complex<T>(alpha * alpha - 4 * gamma))));
394 const std::complex<T> cx4 = std::complex<T>(T(-0.25)) * std::complex<T>(b / a) -
NumericT<T>::sqrt(std::complex<T>(T(0.5)) * (std::complex<T>(-alpha) -
NumericT<T>::sqrt(std::complex<T>(alpha * alpha - 4 * gamma))));
398 x[solutions++] = cx1.real();
403 x[solutions++] = cx2.real();
408 x[solutions++] = cx3.real();
413 x[solutions++] = cx4.real();
419 const std::complex<T> p(T(-0.08333333333333333333333333333333) * alpha * alpha - gamma);
422 const std::complex<T> q(T(-0.00925925925925925925925925925926) * alpha * alpha * alpha + T(0.33333333333333333333333333333333) * alpha * gamma - T(0.125) * beta * beta);
424 const std::complex<T> qqSqr =
NumericT<T>::sqrt(std::complex<T>(T(0.25)) * q * q + std::complex<T>(T(0.03703703703703703703703703703704)) * p * p * p);
426 const std::complex<T> r(std::complex<T>(T(-0.5)) * q + qqSqr);
432 const std::complex<T> u =
NumericT<T>::pow(std::complex<T>(r), T(0.33333333333333333333333333333333));
442 y = std::complex<T>(T(-0.83333333333333333333333333333333) * alpha) + u -
NumericT<T>::pow(std::complex<T>(q), T(0.33333333333333333333333333333333));
446 y = std::complex<T>(T(-0.83333333333333333333333333333333) * alpha) + u - p / (std::complex<T>(3) * u);
449 const std::complex<T> w(
NumericT<T>::sqrt(std::complex<T>(alpha) + std::complex<T>(T(2)) * y));
458 const std::complex<T> beta2_w(std::complex<T>(T(2) * beta) / w);
459 const std::complex<T> alpha3y2 = std::complex<T>(T(3) * alpha) + std::complex<T>(T(2)) * y;
460 const std::complex<T> b_a4(T(-0.25) * b_a);
465 const std::complex<T> cx1 = b_a4 + std::complex<T>(T(0.5)) * (w + sqrtPositive);
466 const std::complex<T> cx2 = b_a4 + std::complex<T>(T(0.5)) * (w - sqrtPositive);
467 const std::complex<T> cx3 = b_a4 + std::complex<T>(T(0.5)) * (-w + sqrtNegative);
468 const std::complex<T> cx4 = b_a4 + std::complex<T>(T(0.5)) * (-w - sqrtNegative);
472 x[solutions++] = cx1.real();
477 x[solutions++] = cx2.real();
482 x[solutions++] = cx3.real();
487 x[solutions++] = cx4.real();
495 for (
unsigned int n = 0u; n < solutions; ++n)
497 optimizeQuartic(a, b, c, d, e, x[n]);
503 unsigned int nOutput = 0u;
504 for (
unsigned int nInput = 0u; nInput < solutions; ++nInput)
506 const T value = x[nInput];
508 if (
NumericT<T>::isWeakEqualEps(value * value * value * value * a + value * value * value * b + value * value * c + value * d + e))
512 if (nOutput != nInput)
514 x[nOutput] = x[nInput];
527unsigned int EquationT<T>::optimizeCubic(
const T a,
const T b,
const T c,
const T d, T& root,
const unsigned int maxIterations,
const T updateFactor)
529 ocean_assert(maxIterations >= 1u);
530 ocean_assert(updateFactor > T(0) && updateFactor <= T(2));
537 for (
unsigned int nIteration = 0u; nIteration < maxIterations; ++nIteration)
541 const T fx = a * x * x * x + b * x * x + c * x + d;
548 const T fdx = T(3) * a * x * x + T(2) * b * x + c;
555 const T delta = fx / fdx;
556 const T newX = x - delta * updateFactor;
558 const T newFx = a * newX * newX * newX + b * newX * newX + c * newX + d;
571 return nIteration + 1u;
575 return maxIterations;
579unsigned int EquationT<T>::optimizeQuartic(
const T a,
const T b,
const T c,
const T d,
const T e, T& root,
const unsigned int maxIterations,
const T updateFactor)
581 ocean_assert(maxIterations >= 1u);
582 ocean_assert(updateFactor > T(0) && updateFactor <= T(2));
589 for (
unsigned int nIteration = 0u; nIteration < maxIterations; ++nIteration)
596 const T fx = a * x4 + b * x3 + c * x2 + d * x + e;
603 const T fdx = T(4) * a * x3 + T(3) * b * x2 + T(2) * c * x + d;
610 const T delta = fx / fdx;
611 const T newX = x - delta * updateFactor;
613 const T newFx = a * newX * newX * newX * newX + b * newX * newX * newX + c * newX * newX + d * newX + e;
626 return nIteration + 1u;
630 return maxIterations;
This class provides several functions to solve equations with different degree using floating point v...
Definition Equation.h:53
static unsigned int solveQuartic(const T a, const T b, const T c, const T d, const T e, T *x, const bool refine=true)
Solves a quartic equation with the form:
Definition Equation.h:343
static unsigned int optimizeCubic(const T a, const T b, const T c, const T d, T &x, const unsigned int maxIterations=10u, const T updateFactor=T(1.0))
Optimizes a root of a cubic equation using Newton-Raphson iterations.
Definition Equation.h:527
static unsigned int optimizeQuartic(const T a, const T b, const T c, const T d, const T e, T &x, const unsigned int maxIterations=10u, const T updateFactor=T(1.0))
Optimizes a root of a quartic equation using Newton-Raphson iterations.
Definition Equation.h:579
static bool solveQuadratic(const T a, const T b, const T c, T &x1, T &x2)
Solves an quadratic equation with the form:
Definition Equation.h:168
static bool solveLinear(const T a, const T b, T &x)
Solves a linear eqation with the form:
Definition Equation.h:152
static unsigned int solveCubic(const T a, const T b, const T c, const T d, T &x1, T &x2, T &x3, const bool refine=true)
Solves a cubic equation with the from:
Definition Equation.h:229
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T pow(const T x, const T y)
Returns x raised to the power of y.
Definition Numeric.h:1866
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1537
static constexpr T eps()
Returns a small epsilon.
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2096
static constexpr T copySign(const T signReceiver, const T signProvider)
Copies the sign of a given value to another one.
Definition Numeric.h:3273
static T cos(const T value)
Returns the cosine of a given value.
Definition Numeric.h:1588
static T acos(const T value)
Returns the arccosine of a given value.
Definition Numeric.h:2916
The namespace covering the entire Ocean framework.
Definition Accessor.h:15