Ocean
Loading...
Searching...
No Matches
Equation.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_MATH_EQUATION_H
9#define META_OCEAN_MATH_EQUATION_H
10
11#include "ocean/math/Math.h"
12#include "ocean/math/Numeric.h"
13
15
16#include <complex>
17
18namespace Ocean
19{
20
21// Forward declaration.
22template <typename T> class EquationT;
23
24/**
25 * Definition of the Equation object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
26 * @see EquationT
27 * @ingroup math
28 */
30
31/**
32 * Definition of the Equation class using double values
33 * @see EquationT
34 * @ingroup math
35 */
37
38/**
39 * Definition of the Equation class using float values
40 * @see EquationT
41 * @ingroup math
42 */
44
45/**
46 * This class provides several functions to solve equations with different degree using floating point values with the precission specified by type T.
47 * @tparam T Type of passed floating point values
48 * @see Equation, EquationF, EquationD.
49 * @ingroup math
50 */
51template <typename T>
53{
54 public:
55
56 /**
57 * Solves a linear eqation with the form:
58 * <pre>
59 * ax + b = 0
60 * </pre>
61 * @param a A parameter, with range (-infinity, infinity) \ {0}, (must not be 0)
62 * @param b B parameter, with range (-infinity, infinity)
63 * @param x Resulting solution
64 * @return True, if succeeded
65 */
66 static bool solveLinear(const T a, const T b, T& x);
67
68 /**
69 * Solves an quadratic equation with the form:
70 * <pre>
71 * ax^2 + bx + c = 0
72 * </pre>
73 * @param a A parameter, with range (-infinity, infinity) \ {0}, (must not be 0)
74 * @param b B parameter, with range (-infinity, infinity)
75 * @param c C parameter, with range (-infinity, infinity)
76 * @param x1 First resulting solution, with range (-infinity, infinity)
77 * @param x2 Second resulting solution, with range (-infinity, infinity)
78 * @return True, if succeeded
79 */
80 static bool solveQuadratic(const T a, const T b, const T c, T& x1, T& x2);
81
82 /**
83 * Solves a cubic equation with the from:
84 * <pre>
85 * ax^3 + bx^2 + cx + d = 0
86 * </pre>
87 * @param a A parameter, with range (-infinity, infinity) \ {0}, (must not be 0)
88 * @param b B parameter, with range (-infinity, infinity)
89 * @param c C parameter, with range (-infinity, infinity)
90 * @param d D parameter, with range (-infinity, infinity)
91 * @param x1 First resulting solution, with range (-infinity, infinity)
92 * @param x2 Second resulting solution, with range (-infinity, infinity)
93 * @param x3 Third resulting solution, with range (-infinity, infinity)
94 * @param refine True, to refine the calculated solutions with an iterative algorithm; False, to use the roots as calculated
95 * @return The number of solutions, with range [0, 3]
96 */
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);
98
99 /**
100 * Solves a quartic equation with the form:
101 * <pre>
102 * ax^4 + bx^3 + cx^2 + dx + e = 0
103 * </pre>
104 * @param a A parameter, with range (-infinity, infinity) \ {0}, (must not be 0)
105 * @param b B parameter, with range (-infinity, infinity)
106 * @param c C parameter, with range (-infinity, infinity)
107 * @param d D parameter, with range (-infinity, infinity)
108 * @param e E parameter, with range (-infinity, infinity)
109 * @param x Array with at least four scalar values receiving the (at most) four solutions
110 * @param refine True, to refine the calculated solutions with an iterative algorithm; False, to use the roots as calculated
111 * @return The number of solutions, with range [0, 4]
112 */
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);
114
115 /**
116 * Optimizes a root of a cubic equation using Newton-Raphson iterations.
117 * The function optimizes a known x for the following equation:
118 * <pre>
119 * ax^3 + bx^2 + cx + d = 0
120 * </pre>
121 * @param a A parameter, with range (-infinity, infinity) \ {0}, (must not be 0)
122 * @param b B parameter, with range (-infinity, infinity)
123 * @param c C parameter, with range (-infinity, infinity)
124 * @param d D parameter, with range (-infinity, infinity)
125 * @param x The known root to optimize, with range (-infinity, infinity)
126 * @param maxIterations The maximum number of Newton-Raphson iterations, with range [1, infinity)
127 * @param updateFactor The update factor for the Newton-Raphson iterations, with range (0, 2]
128 * @return The number of applied iterations, with range [0, maxIterations], 0 if the root could not be optimized
129 */
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));
131
132 /**
133 * Optimizes a root of a quartic equation using Newton-Raphson iterations.
134 * The function optimizes a known x for the following equation:
135 * <pre>
136 * ax^4 + bx^3 + cx^2 + dx + e = 0
137 * </pre>
138 * @param a A parameter, with range (-infinity, infinity) \ {0}, (must not be 0)
139 * @param b B parameter, with range (-infinity, infinity)
140 * @param c C parameter, with range (-infinity, infinity)
141 * @param d D parameter, with range (-infinity, infinity)
142 * @param e E parameter, with range (-infinity, infinity)
143 * @param x The known root to optimize, with range (-infinity, infinity)
144 * @param maxIterations The maximum number of Newton-Raphson iterations, with range [1, infinity)
145 * @param updateFactor The update factor for the Newton-Raphson iterations, with range (0, 2]
146 * @return The number of applied iterations, with range [0, maxIterations], 0 if the root could not be optimized
147 */
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));
149};
150
151template <typename T>
152bool EquationT<T>::solveLinear(const T a, const T b, T& x)
153{
154 ocean_assert(NumericT<T>::isNotEqualEps(a));
155
156 // ax + b = 0
157
159 {
160 return false;
161 }
162
163 x = -b / a;
164 return true;
165}
166
167template <typename T>
168bool EquationT<T>::solveQuadratic(const T a, const T b, const T c, T& x1, T& x2)
169{
170 ocean_assert(NumericT<T>::isNotEqualEps(a));
171
172 // ax^2 + bx + c = 0
173
174 // see Numerical Recipes in C++
175 // x = (-b ± sqrt(b^2 - 4ac)) / 2a
176
178 {
179 return false;
180 }
181
182 const T value = b * b - T(4) * a * c;
183
184 if (value < T(0))
185 {
186 return false;
187 }
188
189 if (NumericT<T>::isEqualEps(value))
190 {
191 // x = (-b ± sqrt(0)) / 2a
192
193 x1 = -b / (T(2) * a);
194 x2 = x1;
195
196 return true;
197 }
198
199 const T q = T(-0.5) * (b + NumericT<T>::copySign(NumericT<T>::sqrt(value), b));
200
202 {
203 x1 = 0;
204 x2 = 0;
205 return true;
206 }
207
208 x1 = q / a;
209 x2 = c / q;
210
211#ifdef OCEAN_DEBUG
212 if (std::is_same<T, float>::value)
213 {
214 // for 32 bit float values we have to weaken the zero accuracy
215 ocean_assert(NumericT<T>::isEqual(a * x1 * x1 + b * x1 + c, T(0), NumericT<T>::weakEps() * NumericT<T>::abs(x1)));
216 ocean_assert(NumericT<T>::isEqual(a * x2 * x2 + b * x2 + c, T(0), NumericT<T>::weakEps() * NumericT<T>::abs(x2)));
217 }
218 else
219 {
220 ocean_assert(NumericT<T>::isWeakEqualEps(a * x1 * x1 + b * x1 + c));
221 ocean_assert(NumericT<T>::isWeakEqualEps(a * x2 * x2 + b * x2 + c));
222 }
223#endif
224
225 return true;
226}
227
228template <typename T>
229unsigned int EquationT<T>::solveCubic(const T a, const T b, const T c, const T d, T& x1, T& x2, T& x3, const bool refine)
230{
231 ocean_assert(NumericT<T>::isNotEqualEps(a));
232
233 // ax^3 + bx^2 + cx + d = 0
234 // see Numerical Recipes in C++
235
237 {
238 return 0u;
239 }
240
241 const T a1 = 1 / a;
242 const T alpha = b * a1;
243 const T beta = c * a1;
244 const T gamma = d * a1;
245
246 // x^3 + alpha x^2 + beta x + gamma = 0
247
248 // alpha2 = alpha^2
249 const T alpha2 = alpha * alpha;
250
251 // q = (alpha^2 - 3*beta) / 9
252 const T q = (alpha2 - T(3) * beta) * T(0.11111111111111111111111111111111);
253
254 // r = (2*alpha^3 - 9*alpha*beta + 27*gamma) / 54
255 const T r = (T(2) * alpha2 * alpha - T(9) * alpha * beta + T(27) * gamma) * T(0.018518518518518518518518518518519);
256
257 // r2 = r^2
258 const T r2 = r * r;
259
260 // q3 = q^3
261 const T q3 = q * q * q;
262
263 if (r2 <= q3 + NumericT<T>::eps() && q > NumericT<T>::eps())
264 {
265 const T sqrtQ = NumericT<T>::sqrt(q);
266
267 // angle = arccos(r / sqrt(q^3))
268 // angle_3 = angle / 3
269 const T angle_3 = NumericT<T>::acos(minmax<T>(-1, r / (q * sqrtQ), 1)) * T(0.33333333333333333333333333333333);
270
271 // alpha_3 = alpha / 3
272 const T alpha_3 = alpha * T(0.33333333333333333333333333333333);
273
274 const T factor = T(-2) * sqrtQ;
275
276 // x1 = -2 sqrt(q) * cos(angle / 3) - alpha / 3
277 x1 = factor * NumericT<T>::cos(angle_3) - alpha_3;
278
279 // x2 = -2 sqrt(q) * cos((angle + 2pi) / 3) - alpha / 3
280 x2 = factor * NumericT<T>::cos(angle_3 + T(2.0943951023931954923084289221863)) - alpha_3;
281
282 // x3 = -2 sqrt(q) * cos((angle - 2pi) / 3) - alpha / 3
283 x3 = factor * NumericT<T>::cos(angle_3 - T(2.0943951023931954923084289221863)) - alpha_3;
284
285#ifdef OCEAN_DEBUG
286
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;
290
291 // the accuracy for 32 bit float values may be very poor so that we cannot define any assert
292 if (!std::is_same<T, float>::value)
293 {
294 ocean_assert_accuracy(NumericT<T>::isEqual(value1, T(0), T(1e-3)));
295 ocean_assert_accuracy(NumericT<T>::isEqual(value2, T(0), T(1e-3)));
296 ocean_assert_accuracy(NumericT<T>::isEqual(value3, T(0), T(1e-3)));
297 }
298#endif
299
300 if (refine)
301 {
302 optimizeCubic(a, b, c, d, x1);
303 optimizeCubic(a, b, c, d, x2);
304 optimizeCubic(a, b, c, d, x3);
305 }
306
307 return 3u;
308 }
309
310 ocean_assert(r2 - q3 >= -NumericT<T>::eps());
311
312 // m = -sign(r) * [abs(r) + sqrt(r^2 - q^3)]^(1/3)
313 const T m = -NumericT<T>::copySign(pow(NumericT<T>::abs(r) + NumericT<T>::sqrt(std::max(T(0), r2 - q3)), T(0.33333333333333333333333333333333)), r);
314
315 // n = 0, if m == 0
316 // n = q / m, if m != 0
317 const T n = NumericT<T>::isEqualEps(m) ? 0 : q / m;
318
319 // x1 = (m + n) - alpha / 3
320 x1 = m + n - alpha * T(0.33333333333333333333333333333333);
321
322#ifdef OCEAN_DEBUG
323
324 const T value1 = a * x1 * x1 * x1 + b * x1 * x1 + c * x1 + d;
325
326 // the accuracy for 32 bit float values may be very poor so that we cannot define any assert
327 if (!std::is_same<T, float>::value)
328 {
329 ocean_assert(NumericT<T>::isEqual(value1, T(0), T(1e-3)));
330 }
331
332#endif
333
334 if (refine)
335 {
336 optimizeCubic(a, b, c, d, x1);
337 }
338
339 return 1u;
340}
341
342template <typename T>
343unsigned int EquationT<T>::solveQuartic(const T a, const T b, const T c, const T d, const T e, T* x, const bool refine)
344{
345 ocean_assert(NumericT<T>::isNotEqualEps(a));
346 ocean_assert(x != nullptr);
347
348 // ax^4 + bx^3 + cx^2 + dx + e = 0
349
351 {
352 return 0u;
353 }
354
355 // simplification using substitution:
356 /// y^4 + alpha * y^2 + beta * y + gamma = 0
357
358 // 1 / a
359 const T a1 = T(1.0) / a;
360
361 // b / a
362 const T b_a = b * a1;
363
364 // c / a
365 const T c_a = c * a1;
366
367 // (b * b) / (a * a)
368 const T b_a2 = b_a * b_a;
369
370 // (b * b * b) / (a * a * a)
371 const T b_a3 = b_a2 * b_a;
372
373 // d / a
374 const T d_a = d * a1;
375
376 //const T alpha = T(-0.375) * (b / a) * (b / a) + c / a;
377 const T alpha = T(-0.375) * b_a2 + c_a;
378
379 //const T beta = T(0.125) * (b / a) * (b / a) * (b / a) - T(0.5) * (b / a) * (c / a) + (d / a);
380 const T beta = T(0.125) * b_a3 - T(0.5) * b_a * c_a + d_a;
381
382 //const T gamma = T(-0.01171875) * (b / a) * (b / a) * (b / a) * (b / a) + T(0.0625) * (b / a) * (b / a) * (c / a) - T(0.25) * (b / a) * (d / a) + e / 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;
384
385 // y^4 + alpha y^2 + beta y + gamma = 0
386
387 unsigned int solutions = 0u;
388
389 if (NumericT<T>::isEqualEps(beta))
390 {
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))));
395
396 ocean_assert((std::is_same<T, float>::value) || NumericT<T>::isWeakEqualEps(cx1 * cx1 * cx1 * cx1 * a + cx1 * cx1 * cx1 * b + cx1 * cx1 * c + cx1 * d + e));
397 ocean_assert((std::is_same<T, float>::value) || NumericT<T>::isWeakEqualEps(cx2 * cx2 * cx2 * cx2 * a + cx2 * cx2 * cx2 * b + cx2 * cx2 * c + cx2 * d + e));
398 ocean_assert((std::is_same<T, float>::value) || NumericT<T>::isWeakEqualEps(cx3 * cx3 * cx3 * cx3 * a + cx3 * cx3 * cx3 * b + cx3 * cx3 * c + cx3 * d + e));
399 ocean_assert((std::is_same<T, float>::value) || NumericT<T>::isWeakEqualEps(cx4 * cx4 * cx4 * cx4 * a + cx4 * cx4 * cx4 * b + cx4 * cx4 * c + cx4 * d + e));
400
401 if (NumericT<T>::isEqualEps(cx1.imag()))
402 {
403 x[solutions++] = cx1.real();
404 }
405
406 if (NumericT<T>::isEqualEps(cx2.imag()))
407 {
408 x[solutions++] = cx2.real();
409 }
410
411 if (NumericT<T>::isEqualEps(cx3.imag()))
412 {
413 x[solutions++] = cx3.real();
414 }
415
416 if (NumericT<T>::isEqualEps(cx4.imag()))
417 {
418 x[solutions++] = cx4.real();
419 }
420 }
421 else
422 {
423 //const std::complex<T> p(-(alpha * alpha) / T(12.0) - gamma);
424 const std::complex<T> p(T(-0.08333333333333333333333333333333) * alpha * alpha - gamma);
425
426 //const std::complex<T> q(-(alpha * alpha * alpha) / T(108.0) + (alpha * gamma) / T(3.0) - (beta * beta) / T(8.0));
427 const std::complex<T> q(T(-0.00925925925925925925925925925926) * alpha * alpha * alpha + T(0.33333333333333333333333333333333) * alpha * gamma - T(0.125) * beta * beta);
428
429 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);
430
431 const std::complex<T> r(std::complex<T>(T(-0.5)) * q + qqSqr);
433 {
434 return 0u;
435 }
436
437 const std::complex<T> u = NumericT<T>::pow(std::complex<T>(r), T(0.33333333333333333333333333333333));
438
440 {
441 return 0u;
442 }
443
444 std::complex<T> y;
445 if (NumericT<T>::isEqualEps(u.real()) && NumericT<T>::isEqualEps(u.imag()))
446 {
447 y = std::complex<T>(T(-0.83333333333333333333333333333333) * alpha) + u - NumericT<T>::pow(std::complex<T>(q), T(0.33333333333333333333333333333333));
448 }
449 else
450 {
451 y = std::complex<T>(T(-0.83333333333333333333333333333333) * alpha) + u - p / (std::complex<T>(3) * u);
452 }
453
454 const std::complex<T> w(NumericT<T>::sqrt(std::complex<T>(alpha) + std::complex<T>(T(2)) * y));
455
456 //const std::complex<T> cx1 = std::complex<T>(T(-0.25)) * std::complex<T>(b / a) + std::complex<T>(T(0.5)) * (w + NumericT<T>::sqrt(std::complex<T>(-1) * (std::complex<T>(3) * std::complex<T>(alpha) + std::complex<T>(2) * y + std::complex<T>(2) * std::complex<T>(beta) / w)));
457
459 {
460 return 0u;
461 }
462
463 const std::complex<T> beta2_w(std::complex<T>(T(2) * beta) / w);
464 const std::complex<T> alpha3y2 = std::complex<T>(T(3) * alpha) + std::complex<T>(T(2)) * y;
465 const std::complex<T> b_a4(T(-0.25) * b_a);
466
467 const std::complex<T> sqrtPositive(NumericT<T>::sqrt(-alpha3y2 - beta2_w));
468 const std::complex<T> sqrtNegative(NumericT<T>::sqrt(-alpha3y2 + beta2_w));
469
470 const std::complex<T> cx1 = b_a4 + std::complex<T>(T(0.5)) * (w + sqrtPositive);
471 const std::complex<T> cx2 = b_a4 + std::complex<T>(T(0.5)) * (w - sqrtPositive);
472 const std::complex<T> cx3 = b_a4 + std::complex<T>(T(0.5)) * (-w + sqrtNegative);
473 const std::complex<T> cx4 = b_a4 + std::complex<T>(T(0.5)) * (-w - sqrtNegative);
474
475 if (NumericT<T>::isEqualEps(cx1.imag()))
476 {
477 x[solutions++] = cx1.real();
478 }
479
480 if (NumericT<T>::isEqualEps(cx2.imag()))
481 {
482 x[solutions++] = cx2.real();
483 }
484
485 if (NumericT<T>::isEqualEps(cx3.imag()))
486 {
487 x[solutions++] = cx3.real();
488 }
489
490 if (NumericT<T>::isEqualEps(cx4.imag()))
491 {
492 x[solutions++] = cx4.real();
493 }
494 }
495
496 // first, we try to refine/optimize the solutions
497
498 if (refine)
499 {
500 for (unsigned int n = 0u; n < solutions; ++n)
501 {
502 optimizeQuartic(a, b, c, d, e, x[n]);
503 }
504 }
505
506 // finally, we remove all solutions which are not accurate enough
507
508 unsigned int nOutput = 0u;
509 for (unsigned int nInput = 0u; nInput < solutions; ++nInput)
510 {
511 const T value = x[nInput];
512
513 if (NumericT<T>::isWeakEqualEps(value * value * value * value * a + value * value * value * b + value * value * c + value * d + e))
514 {
515 // the solution is accurate enough
516
517 if (nOutput != nInput)
518 {
519 x[nOutput] = x[nInput];
520 }
521
522 ++nOutput;
523 }
524 }
525
526 solutions = nOutput;
527
528 return solutions;
529}
530
531template <typename T>
532unsigned 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)
533{
534 ocean_assert(maxIterations >= 1u);
535 ocean_assert(updateFactor > T(0) && updateFactor <= T(2));
536
537 // Newton-Raphson iteration: xNew = xOld - f(xOld) / f'(xOld)
538
539 // where f(x) = ax^3 + bx^2 + cx + d
540 // and f'(x) = 3ax^2 + 2bx + c
541
542 for (unsigned int nIteration = 0u; nIteration < maxIterations; ++nIteration)
543 {
544 const T x = root;
545
546 const T fx = a * x * x * x + b * x * x + c * x + d;
547
549 {
550 return nIteration;
551 }
552
553 const T fdx = T(3) * a * x * x + T(2) * b * x + c;
554
556 {
557 return nIteration;
558 }
559
560 const T delta = fx / fdx;
561 const T newX = x - delta * updateFactor;
562
563 const T newFx = a * newX * newX * newX + b * newX * newX + c * newX + d;
564
565 if (NumericT<T>::abs(fx) < NumericT<T>::abs(newFx))
566 {
567 // the optimization failed
568 return nIteration;
569 }
570
571 root = newX;
572
573 // we have converged
574 if (NumericT<T>::isEqualEps(delta))
575 {
576 return nIteration + 1u;
577 }
578 }
579
580 return maxIterations;
581}
582
583template <typename T>
584unsigned 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)
585{
586 ocean_assert(maxIterations >= 1u);
587 ocean_assert(updateFactor > T(0) && updateFactor <= T(2));
588
589 // Newton-Raphson iteration: xNew = xOld - f(xOld) / f'(xOld)
590
591 // where f(x) = ax^4 + bx^3 + cx^2 + dx + e
592 // and f'(x) = 4ax^3 + 3bx^2 + 2cx + d
593
594 for (unsigned int nIteration = 0u; nIteration < maxIterations; ++nIteration)
595 {
596 const T x = root;
597 const T x2 = x * x;
598 const T x3 = x2 * x;
599 const T x4 = x3 * x;
600
601 const T fx = a * x4 + b * x3 + c * x2 + d * x + e;
602
604 {
605 return nIteration;
606 }
607
608 const T fdx = T(4) * a * x3 + T(3) * b * x2 + T(2) * c * x + d;
609
611 {
612 return nIteration;
613 }
614
615 const T delta = fx / fdx;
616 const T newX = x - delta * updateFactor;
617
618 const T newFx = a * newX * newX * newX * newX + b * newX * newX * newX + c * newX * newX + d * newX + e;
619
620 if (NumericT<T>::abs(fx) < NumericT<T>::abs(newFx))
621 {
622 // the optimization failed
623 return nIteration;
624 }
625
626 root = newX;
627
628 // we have converged
629 if (NumericT<T>::isEqualEps(delta))
630 {
631 return nIteration + 1u;
632 }
633 }
634
635 return maxIterations;
636}
637
638}
639
640#endif // META_OCEAN_MATH_EQUATION_H
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:532
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:584
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