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>
34 std::vector<Bracket>
res;
37 for (
unsigned int i = 0; i <
steps; ++i) {
42 if(f(
x1) * f(
x2) <= 0)
61 template<
typename RealFunction>
64 real tol = OPTIMIZATION_TOL,
65 unsigned int max_iter = OPTIMIZATION_BISECTION_ITER) {
72 if(f(a) * f(b) >= 0) {
73 TH_MATH_ERROR(
"root_bisect", f(a) * f(b), MathError::InvalidArgument);
81 unsigned int iter = 0;
83 while((x_max - x_min) > (2 * tol) && iter <= max_iter) {
85 x_avg = (x_max + x_min) / 2.0;
87 if(f(x_avg) * f(x_min) > 0)
96 TH_MATH_ERROR(
"root_bisect", x_avg, MathError::NoConvergence);
97 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(x_max - x_min) / 2.0);
124 template<
typename RealFunction>
126 RealFunction f,
real a,
real b,
real tol = OPTIMIZATION_TOL,
127 unsigned int n0 = 1,
real k1 = 0.0) {
142 TH_MATH_ERROR(
"root_itp", y_a * y_b, MathError::InvalidArgument);
147 const int monotone = (y_a < y_b) ? 1 : -1;
152 const long int n_max = n_half + n0;
154 real eps = tol * pow(2.0, n_max);
157 while((b - a) > (2 * tol) && iter <= n_max) {
161 const real x_f = (a * y_b - b * y_a) / (y_b - y_a);
162 const real x_half = 0.5 * (a + b);
166 const int sigma =
sgn(x_half - x_f);
167 const real delta = k1 * square(b - a);
169 if (delta <= abs(x_half - x_f))
170 x_t = x_f + sigma * delta;
176 const real r = eps - (b - a) / 2.0;
178 if (abs(x_t - x_half) <= r)
181 x_new = x_half - sigma * r;
185 const real y_new = f(x_new);
187 if (monotone * y_new > 0) {
190 }
else if (monotone * y_new < 0) {
202 if(abs(b - a) > 2 * tol) {
203 TH_MATH_ERROR(
"root_itp", (a + b) / 2.0, MathError::NoConvergence);
204 return iter_result<real>(ConvergenceStatus::MaxIterations, iter, abs(b - a) / 2.0);
222 template<
typename RealFunction>
224 RealFunction f, RealFunction Df,
real guess = 0.0,
225 real tol = OPTIMIZATION_TOL,
unsigned int max_iter = OPTIMIZATION_NEWTON_ITER) {
230 unsigned int iter = 0;
232 while(abs(f_x) > tol && iter <= max_iter) {
243 x = x - (f_x / Df_x);
247 if(iter > max_iter) {
270 real tol = OPTIMIZATION_TOL,
271 unsigned int max_iter = OPTIMIZATION_NEWTON_ITER) {
275 unsigned int iter = 0;
277 while(abs(s.
Re()) > tol && iter <= max_iter) {
282 x = x - (s.
Re() / s.
Dual());
286 if(iter > max_iter) {
307 typename Type = real,
308 typename ComplexFunction = std::function<complex<Type>(complex<Type>)>
312 real tol = OPTIMIZATION_TOL,
313 unsigned int max_iter = OPTIMIZATION_NEWTON_ITER) {
317 unsigned int iter = 0;
319 while(f_z * f_z.
conjugate() > (tol * tol) && iter <= max_iter) {
322 z = z - (f_z / df(z));
326 if(iter > max_iter) {
347 template<
typename RealFunction>
349 RealFunction f, RealFunction Df,
350 RealFunction D2f,
real guess = 0,
351 real tol = OPTIMIZATION_TOL,
352 unsigned int max_iter = OPTIMIZATION_HALLEY_ITER) {
356 unsigned int iter = 0;
358 while(abs(f_x) > tol && iter <= max_iter) {
361 const real df_x = Df(x);
363 x = x - (2 * f_x * df_x) / (2 * square(df_x) - f_x * D2f(x));
367 if(iter > max_iter) {
391 real tol = OPTIMIZATION_TOL,
392 unsigned int max_iter = OPTIMIZATION_HALLEY_ITER) {
396 unsigned int iter = 0;
398 while(abs(s.
Re()) > tol && iter <= max_iter) {
402 s = f(
dual2(x, 1, 0));
408 x = x - (2 * f_x * df_x) / (2 * square(df_x) - f_x * d2f_x);
412 if(iter > max_iter) {
438 template<
typename RealFunction>
440 RealFunction f, RealFunction Df,
441 RealFunction D2f,
real guess = 0,
442 real tol = OPTIMIZATION_TOL,
443 unsigned int max_iter = OPTIMIZATION_CHEBYSHEV_ITER) {
447 unsigned int iter = 0;
449 while(abs(f_x) > tol && iter <= max_iter) {
452 const real df_x = Df(x);
453 const real u = f_x / df_x;
455 x = x - u - square(u) * D2f(x) / (2.0 * df_x);
460 if(iter > max_iter) {
461 TH_MATH_ERROR(
"root_chebyshev", x, MathError::NoConvergence);
489 real tol = OPTIMIZATION_TOL,
490 unsigned int max_iter = OPTIMIZATION_CHEBYSHEV_ITER) {
494 unsigned int iter = 0;
496 while(abs(s.
Re()) > tol && iter <= max_iter) {
498 s = f(
dual2(x, 1.0, 0.0));
502 const real u = f_x / df_x;
504 x = x - u - square(u) * s.
Dual2() / (2.0 * df_x);
508 if(iter > max_iter) {
509 TH_MATH_ERROR(
"root_chebyshev", x, MathError::NoConvergence);
533 template<
typename RealFunction>
535 RealFunction f, RealFunction Df,
real guess = 0.0,
536 real tol = OPTIMIZATION_TOL,
537 unsigned int max_iter = OPTIMIZATION_OSTROWSKI_ITER) {
541 unsigned int iter = 0;
543 while(abs(f_x) > tol && iter <= max_iter) {
546 const real df_x = Df(x);
547 const real u = f_x / df_x;
548 const real f_xu = f(x - u);
550 x = x - u - (f_xu / df_x) * (f_x / (f_x - 2 * f_xu));
555 if(iter > max_iter) {
556 TH_MATH_ERROR(
"root_ostrowski", x, MathError::NoConvergence);
581 template<
typename RealFunction>
583 RealFunction f, RealFunction Df,
real guess = 0.0,
584 real tol = OPTIMIZATION_TOL,
585 unsigned int max_iter = OPTIMIZATION_JARRAT_ITER) {
589 unsigned int iter = 0;
591 while(abs(f_x) > tol && iter <= max_iter) {
594 const real df_x = Df(x);
595 const real u = f_x / df_x;
596 const real f_xu = Df(x - 2.0 * u / 3.0);
598 x = x - 0.5 * u + f_x / (df_x - 3 * f_xu);
602 if(iter > max_iter) {
624 template<
typename RealFunction>
627 real tol = OPTIMIZATION_TOL,
628 unsigned int max_iter = OPTIMIZATION_BISECTION_ITER) {
630 return root_itp(f, a, b, tol, max_iter);
648 template<
typename RealFunction,
typename Vector = vec<real>>
651 real tol = OPTIMIZATION_TOL,
real steps = 10) {
662 res.resize(intervals.size(),
nan());
666 for (
unsigned int i = 0; i < intervals.size(); ++i) {
671 res[idx] = intervals[i][0];
677 res[idx] = intervals[i][1];
705 template<
typename Field,
typename Vector = vec<Field>>
708 unsigned int steps = 0) {
711 const unsigned int p_order = p.find_order();
713 TH_MATH_ERROR(
"roots_polynomial", p.coeff[0], MathError::InvalidArgument);
722 for (
unsigned int i = 0; i < p_order - 1; ++i)
723 a_max =
max(a_max, abs(p_norm.coeff[i]));
726 const Field M = 1 + a_max;
728 return roots(p_norm, -M, M, tolerance, steps > 0 ? steps : 10 * p_order);
Complex number in algebraic form .
Definition complex.h:26
Type Re() const
Get the real part of the complex number.
Definition complex.h:74
Type norm() const
Compute the norm of the complex number.
Definition complex.h:134
complex conjugate() const
Compute the conjugate of the complex number.
Definition complex.h:122
Second order dual number class.
Definition dual2.h:29
real Dual2() const
Return second order dual part.
Definition dual2.h:95
real Re() const
Return real part.
Definition dual2.h:85
real Dual1() const
Return first order dual part.
Definition dual2.h:90
Dual number class.
Definition dual.h:28
const real & Dual() const
Return dual part.
Definition dual.h:96
const real & Re() const
Return real part.
Definition dual.h:75
A polynomial of arbitrary order with coefficients of a specified type.
Definition polynomial.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:219
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:90
dual2 log2(dual2 x)
Compute the natural logarithm of a second order dual number.
Definition dual2_functions.h:210
iter_result< 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:439
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:534
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
auto max(const Vector &X)
Finds the maximum value inside a dataset.
Definition dataset.h:326
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:649
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:74
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:62
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216
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:582
iter_result< 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:125
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(real x, int n)
Compute the n-th root of x.
Definition real_analysis.h:812
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:96
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:348
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:223
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:706
TH_CONSTEXPR int floor(real x)
Compute the floor of x, as the maximum integer number that is smaller than x.
Definition real_analysis.h:271
A structure returned by iterative algorithms containing the computed value, convergence information,...
Definition iter_result.h:45