6#ifndef THEORETICA_ROOTS_H
7#define THEORETICA_ROOTS_H
9#include "../core/function.h"
10#include "../calculus/deriv.h"
11#include "../autodiff/dual.h"
12#include "../autodiff/dual2.h"
13#include "../algebra/vec.h"
14#include "../complex/complex.h"
15#include "../core/iter_result.h"
30 template<
typename RealFunction,
typename Bracket = vec2>
32 RealFunction f,
real a,
real b,
unsigned int steps = 10) {
34 std::vector<Bracket> res;
35 const real dx = (b - a) / steps;
37 for (
unsigned int i = 0; i < steps; ++i) {
39 const real x1 = a + i * dx;
40 const real x2 = a + (i + 1) * dx;
42 if(f(x1) * f(x2) <= 0)
43 res.push_back({x1, x2});
60 template<
typename RealFunction>
63 real tol = OPTIMIZATION_TOL,
64 unsigned int max_iter = OPTIMIZATION_BISECTION_ITER) {
68 return iter_result<real>(ConvergenceStatus::InvalidInput);
71 if(f(a) * f(b) >= 0) {
72 TH_MATH_ERROR(
"root_bisect", f(a) * f(b), MathError::InvalidArgument);
73 return iter_result<real>(ConvergenceStatus::InvalidInput);
80 unsigned int iter = 0;
82 while((x_max - x_min) > (2 * tol) && iter <= max_iter) {
84 x_avg = (x_max + x_min) / 2.0;
86 if(f(x_avg) * f(x_min) > 0)
95 TH_MATH_ERROR(
"root_bisect", x_avg, MathError::NoConvergence);
96 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(b - a) / 2.0);
99 return iter_result<real>(x_avg, iter, abs(b - a) / 2.0);
122 template<
typename RealFunction>
124 RealFunction f,
real a,
real b,
real tol = OPTIMIZATION_TOL,
125 unsigned int n0 = 1,
real k1 = 0.0) {
133 return iter_result<real>(ConvergenceStatus::InvalidInput);
140 TH_MATH_ERROR(
"root_itp", y_a * y_b, MathError::InvalidArgument);
141 return iter_result<real>(ConvergenceStatus::InvalidInput);
145 const int monotone = (y_a < y_b) ? 1 : -1;
150 const long int n_max = n_half + n0;
152 real eps = tol * pow(2.0, n_max);
155 while((b - a) > (2 * tol) && iter <= n_max) {
159 const real x_f = (a * y_b - b * y_a) / (y_b - y_a);
160 const real x_half = 0.5 * (a + b);
164 const int sigma =
sgn(x_half - x_f);
165 const real delta = k1 * square(b - a);
167 if (delta <= abs(x_half - x_f))
168 x_t = x_f + sigma * delta;
174 const real r = eps - (b - a) / 2.0;
176 if (abs(x_t - x_half) <= r)
179 x_new = x_half - sigma * r;
183 const real y_new = f(x_new);
185 if (monotone * y_new > 0) {
188 }
else if (monotone * y_new < 0) {
199 if(abs(b - a) > 2 * tol) {
200 TH_MATH_ERROR(
"root_itp", (a + b) / 2.0, MathError::NoConvergence);
201 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(b - a) / 2.0);
204 return iter_result<real>((a + b) / 2.0, iter, abs(b - a) / 2.0);
219 template<
typename RealFunction>
221 RealFunction f, RealFunction Df,
real guess = 0.0,
222 real tol = OPTIMIZATION_TOL,
unsigned int max_iter = OPTIMIZATION_NEWTON_ITER) {
227 unsigned int iter = 0;
229 while(abs(f_x) > tol && iter <= max_iter) {
236 return iter_result<real>(ConvergenceStatus::Diverged, iter, f_x);
240 x = x - (f_x / Df_x);
244 if(iter > max_iter) {
246 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(f_x));
249 return iter_result<real>(x, iter, abs(f_x));
267 real tol = OPTIMIZATION_TOL,
268 unsigned int max_iter = OPTIMIZATION_NEWTON_ITER) {
272 unsigned int iter = 0;
274 while(abs(s.Re()) > tol && iter <= max_iter) {
279 x = x - (s.Re() / s.Dual());
283 if(iter > max_iter) {
285 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(s.Re()));
288 return iter_result<real>(x, iter, abs(s.Re()));
304 typename Type = real,
305 typename ComplexFunction = std::function<complex<Type>(complex<Type>)>
308 ComplexFunction f, ComplexFunction Df, complex<Type> guess,
309 real tol = OPTIMIZATION_TOL,
310 unsigned int max_iter = OPTIMIZATION_NEWTON_ITER) {
312 complex<Type> z = guess;
313 complex<Type> f_z = Type(
inf());
314 unsigned int iter = 0;
316 while(f_z * f_z.conjugate() > tol * tol && iter <= max_iter) {
319 z = z - (f_z / df(z));
323 if(iter > max_iter) {
324 TH_MATH_ERROR(
"root_newton", z.Re(), MathError::NoConvergence);
325 return iter_result<complex<Type>>(ConvergenceStatus::MaxIterations, iter, f_z.norm());
328 return iter_result<complex<Type>>(z, iter, f_z.norm());
344 template<
typename RealFunction>
346 RealFunction f, RealFunction Df,
347 RealFunction D2f,
real guess = 0,
348 real tol = OPTIMIZATION_TOL,
349 unsigned int max_iter = OPTIMIZATION_HALLEY_ITER) {
353 unsigned int iter = 0;
355 while(abs(f_x) > tol && iter <= max_iter) {
358 const real df_x = Df(x);
360 x = x - (2 * f_x * df_x) / (2 * square(df_x) - f_x * D2f(x));
364 if(iter > max_iter) {
366 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(f_x));
369 return iter_result<real>(x, iter, abs(f_x));
388 real tol = OPTIMIZATION_TOL,
389 unsigned int max_iter = OPTIMIZATION_HALLEY_ITER) {
393 unsigned int iter = 0;
395 while(abs(s.Re()) > tol && iter <= max_iter) {
399 s = f(
dual2(x, 1, 0));
401 const real f_x = s.Re();
402 const real df_x = s.Dual1();
403 const real d2f_x = s.Dual2();
405 x = x - (2 * f_x * df_x) / (2 * square(df_x) - f_x * d2f_x);
409 if(iter > max_iter) {
411 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(s.Re()));
414 return iter_result<real>(x, iter, abs(s.Re()));
428 template<
typename RealFunction>
430 RealFunction f,
real guess = 0,
431 real tol = OPTIMIZATION_TOL,
432 unsigned int max_iter = OPTIMIZATION_STEFFENSEN_ITER) {
436 unsigned int iter = 0;
438 while(abs(f_x) > tol && iter <= max_iter) {
440 const real f_x = f(x);
441 const real g_x = (f(x + f_x) / f_x) - 1;
447 if(iter > max_iter) {
448 TH_MATH_ERROR(
"root_steffensen", x, MathError::NoConvergence);
449 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(f_x));
452 return iter_result<real>(x, iter, abs(f_x));
473 template<
typename RealFunction>
475 RealFunction f, RealFunction Df,
476 RealFunction D2f,
real guess = 0,
477 real tol = OPTIMIZATION_TOL,
478 unsigned int max_iter = OPTIMIZATION_CHEBYSHEV_ITER) {
482 unsigned int iter = 0;
484 while(abs(f_x) > tol && iter <= max_iter) {
487 const real df_x = Df(x);
488 const real u = f_x / df_x;
490 x = x - u - square(u) * D2f(x) / (2.0 * df_x);
495 if(iter > max_iter) {
496 TH_MATH_ERROR(
"root_chebyshev", x, MathError::NoConvergence);
497 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(f_x));
500 return iter_result<real>(x, iter, abs(f_x));
524 real tol = OPTIMIZATION_TOL,
525 unsigned int max_iter = OPTIMIZATION_CHEBYSHEV_ITER) {
529 unsigned int iter = 0;
531 while(abs(s.Re()) > tol && iter <= max_iter) {
533 s = f(
dual2(x, 1.0, 0.0));
535 const real f_x = s.Re();
536 const real df_x = s.Dual1();
537 const real u = f_x / df_x;
539 x = x - u - square(u) * s.Dual2() / (2.0 * df_x);
543 if(iter > max_iter) {
544 TH_MATH_ERROR(
"root_chebyshev", x, MathError::NoConvergence);
545 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(s.Re()));
548 return iter_result<real>(x, iter, abs(s.Re()));
568 template<
typename RealFunction>
570 RealFunction f, RealFunction Df,
real guess = 0.0,
571 real tol = OPTIMIZATION_TOL,
572 unsigned int max_iter = OPTIMIZATION_OSTROWSKI_ITER) {
576 unsigned int iter = 0;
578 while(abs(f_x) > tol && iter <= max_iter) {
581 const real df_x = Df(x);
582 const real u = f_x / df_x;
583 const real f_xu = f(x - u);
585 x = x - u - (f_xu / df_x) * (f_x / (f_x - 2 * f_xu));
590 if(iter > max_iter) {
591 TH_MATH_ERROR(
"root_ostrowski", x, MathError::NoConvergence);
592 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(f_x));
595 return iter_result<real>(x, iter, abs(f_x));
616 template<
typename RealFunction>
618 RealFunction f, RealFunction Df,
real guess = 0.0,
619 real tol = OPTIMIZATION_TOL,
620 unsigned int max_iter = OPTIMIZATION_JARRAT_ITER) {
624 unsigned int iter = 0;
626 while(abs(f_x) > tol && iter <= max_iter) {
629 const real df_x = Df(x);
630 const real u = f_x / df_x;
631 const real f_xu = Df(x - 2.0 * u / 3.0);
633 x = x - 0.5 * u + f_x / (df_x - 3 * f_xu);
637 if(iter > max_iter) {
639 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(f_x));
642 return iter_result<real>(x, iter, abs(f_x));
660 template<
typename RealFunction,
typename Vector = vec<real>>
663 real tol = OPTIMIZATION_TOL,
real steps = 10) {
674 res.resize(intervals.size(),
nan());
678 for (
unsigned int i = 0; i < intervals.size(); ++i) {
683 res[idx] = intervals[i][0];
689 res[idx] = intervals[i][1];
717 template<
typename Field,
typename Vector = vec<Field>>
719 const polynomial<Field>& p,
real tolerance = OPTIMIZATION_TOL,
720 unsigned int steps = 0) {
723 const unsigned int p_order = p.find_order();
725 TH_MATH_ERROR(
"roots_polynomial", p.coeff[0], MathError::InvalidArgument);
730 polynomial<Field> p_norm = p / p.coeff[p_order];
734 for (
unsigned int i = 0; i < p_order - 1; ++i)
735 a_max =
max(a_max, abs(p_norm.coeff[i]));
738 const Field M = 1 + a_max;
740 return roots(p_norm, -M, M, tolerance, steps > 0 ? steps : 10 * p_order);
Second order dual number class.
Definition dual2.h:29
Dual number class.
Definition dual.h:28
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:238
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
double real
A real number, defined as a floating point type.
Definition constants.h:207
bool is_nan(const T &x)
Check whether a generic variable is (equivalent to) a NaN number.
Definition error.h:94
dual2 log2(dual2 x)
Compute the natural logarithm of a second order dual number.
Definition dual2_functions.h:166
iter_result< real > root_ostrowski(RealFunction f, RealFunction Df, real guess=0.0, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_OSTROWSKI_ITER)
Find a root of a univariate real function using Ostrowski's method.
Definition roots.h:569
iter_result< real > root_steffensen(RealFunction f, real guess=0, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_STEFFENSEN_ITER)
Find a root of a univariate real function using Steffensen's method.
Definition roots.h:429
auto max(const Vector &X)
Finds the maximum value inside a dataset.
Definition dataset.h:330
Vector roots(RealFunction f, real a, real b, real tol=OPTIMIZATION_TOL, real steps=10)
Find the roots of a univariate real function inside a given interval, by first searching for candidat...
Definition roots.h:661
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:78
iter_result< real > root_bisect(RealFunction f, real a, real b, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_BISECTION_ITER)
Find the root of a univariate real function using bisection inside a compact interval [a,...
Definition roots.h:61
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216
real root_itp(RealFunction f, real a, real b, real tol=OPTIMIZATION_TOL, unsigned int n0=1, real k1=0.0)
Find a root of a univariate real function using the ITP (Interpolate-Truncate-Project) method,...
Definition roots.h:123
iter_result< real > root_jarrat(RealFunction f, RealFunction Df, real guess=0.0, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_JARRAT_ITER)
Find a root of a univariate real function using Jarrat's method.
Definition roots.h:617
std::vector< Bracket > find_root_brackets(RealFunction f, real a, real b, unsigned int steps=10)
Find candidate intervals for root finding by evaluating a function at equidistant points inside an in...
Definition roots.h:31
real root_chebyshev(RealFunction f, RealFunction Df, RealFunction D2f, real guess=0, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_CHEBYSHEV_ITER)
Find a root of a univariate real function using Chebyshev's method.
Definition roots.h:474
int sgn(real x)
Return the sign of x (1 if positive, -1 if negative, 0 if null)
Definition real_analysis.h:259
TH_CONSTEXPR real inf()
Get positive infinity in floating point representation.
Definition error.h:100
iter_result< real > root_halley(RealFunction f, RealFunction Df, RealFunction D2f, real guess=0, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_HALLEY_ITER)
Find a root of a univariate real function using Halley's method.
Definition roots.h:345
iter_result< real > root_newton(RealFunction f, RealFunction Df, real guess=0.0, real tol=OPTIMIZATION_TOL, unsigned int max_iter=OPTIMIZATION_NEWTON_ITER)
Find a root of a univariate real function using Newton's method.
Definition roots.h:220
Vector roots_polynomial(const polynomial< Field > &p, real tolerance=OPTIMIZATION_TOL, unsigned int steps=0)
Find all the roots of a polynomial.
Definition roots.h:718
TH_CONSTEXPR int floor(real x)
Compute the floor of x Computes the maximum integer number that is smaller than x.
Definition real_analysis.h:271