1*bf2c3715SXin Li// This file is part of Eigen, a lightweight C++ template library 2*bf2c3715SXin Li// for linear algebra. 3*bf2c3715SXin Li// 4*bf2c3715SXin Li// 5*bf2c3715SXin Li// This Source Code Form is subject to the terms of the Mozilla 6*bf2c3715SXin Li// Public License v. 2.0. If a copy of the MPL was not distributed 7*bf2c3715SXin Li// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 8*bf2c3715SXin Li 9*bf2c3715SXin Li#ifndef EIGEN_POLYNOMIALS_MODULE_H 10*bf2c3715SXin Li#define EIGEN_POLYNOMIALS_MODULE_H 11*bf2c3715SXin Li 12*bf2c3715SXin Li#include "../../Eigen/Core" 13*bf2c3715SXin Li 14*bf2c3715SXin Li#include "../../Eigen/Eigenvalues" 15*bf2c3715SXin Li 16*bf2c3715SXin Li#include "../../Eigen/src/Core/util/DisableStupidWarnings.h" 17*bf2c3715SXin Li 18*bf2c3715SXin Li// Note that EIGEN_HIDE_HEAVY_CODE has to be defined per module 19*bf2c3715SXin Li#if (defined EIGEN_EXTERN_INSTANTIATIONS) && (EIGEN_EXTERN_INSTANTIATIONS>=2) 20*bf2c3715SXin Li #ifndef EIGEN_HIDE_HEAVY_CODE 21*bf2c3715SXin Li #define EIGEN_HIDE_HEAVY_CODE 22*bf2c3715SXin Li #endif 23*bf2c3715SXin Li#elif defined EIGEN_HIDE_HEAVY_CODE 24*bf2c3715SXin Li #undef EIGEN_HIDE_HEAVY_CODE 25*bf2c3715SXin Li#endif 26*bf2c3715SXin Li 27*bf2c3715SXin Li/** 28*bf2c3715SXin Li * \defgroup Polynomials_Module Polynomials module 29*bf2c3715SXin Li * \brief This module provides a QR based polynomial solver. 30*bf2c3715SXin Li * 31*bf2c3715SXin Li * To use this module, add 32*bf2c3715SXin Li * \code 33*bf2c3715SXin Li * #include <unsupported/Eigen/Polynomials> 34*bf2c3715SXin Li * \endcode 35*bf2c3715SXin Li * at the start of your source file. 36*bf2c3715SXin Li */ 37*bf2c3715SXin Li 38*bf2c3715SXin Li#include "src/Polynomials/PolynomialUtils.h" 39*bf2c3715SXin Li#include "src/Polynomials/Companion.h" 40*bf2c3715SXin Li#include "src/Polynomials/PolynomialSolver.h" 41*bf2c3715SXin Li 42*bf2c3715SXin Li/** 43*bf2c3715SXin Li \page polynomials Polynomials defines functions for dealing with polynomials 44*bf2c3715SXin Li and a QR based polynomial solver. 45*bf2c3715SXin Li \ingroup Polynomials_Module 46*bf2c3715SXin Li 47*bf2c3715SXin Li The remainder of the page documents first the functions for evaluating, computing 48*bf2c3715SXin Li polynomials, computing estimates about polynomials and next the QR based polynomial 49*bf2c3715SXin Li solver. 50*bf2c3715SXin Li 51*bf2c3715SXin Li \section polynomialUtils convenient functions to deal with polynomials 52*bf2c3715SXin Li \subsection roots_to_monicPolynomial 53*bf2c3715SXin Li The function 54*bf2c3715SXin Li \code 55*bf2c3715SXin Li void roots_to_monicPolynomial( const RootVector& rv, Polynomial& poly ) 56*bf2c3715SXin Li \endcode 57*bf2c3715SXin Li computes the coefficients \f$ a_i \f$ of 58*bf2c3715SXin Li 59*bf2c3715SXin Li \f$ p(x) = a_0 + a_{1}x + ... + a_{n-1}x^{n-1} + x^n \f$ 60*bf2c3715SXin Li 61*bf2c3715SXin Li where \f$ p \f$ is known through its roots i.e. \f$ p(x) = (x-r_1)(x-r_2)...(x-r_n) \f$. 62*bf2c3715SXin Li 63*bf2c3715SXin Li \subsection poly_eval 64*bf2c3715SXin Li The function 65*bf2c3715SXin Li \code 66*bf2c3715SXin Li T poly_eval( const Polynomials& poly, const T& x ) 67*bf2c3715SXin Li \endcode 68*bf2c3715SXin Li evaluates a polynomial at a given point using stabilized Hörner method. 69*bf2c3715SXin Li 70*bf2c3715SXin Li The following code: first computes the coefficients in the monomial basis of the monic polynomial that has the provided roots; 71*bf2c3715SXin Li then, it evaluates the computed polynomial, using a stabilized Hörner method. 72*bf2c3715SXin Li 73*bf2c3715SXin Li \include PolynomialUtils1.cpp 74*bf2c3715SXin Li Output: \verbinclude PolynomialUtils1.out 75*bf2c3715SXin Li 76*bf2c3715SXin Li \subsection Cauchy bounds 77*bf2c3715SXin Li The function 78*bf2c3715SXin Li \code 79*bf2c3715SXin Li Real cauchy_max_bound( const Polynomial& poly ) 80*bf2c3715SXin Li \endcode 81*bf2c3715SXin Li provides a maximum bound (the Cauchy one: \f$C(p)\f$) for the absolute value of a root of the given polynomial i.e. 82*bf2c3715SXin Li \f$ \forall r_i \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$, 83*bf2c3715SXin Li \f$ |r_i| \le C(p) = \sum_{k=0}^{d} \left | \frac{a_k}{a_d} \right | \f$ 84*bf2c3715SXin Li The leading coefficient \f$ p \f$: should be non zero \f$a_d \neq 0\f$. 85*bf2c3715SXin Li 86*bf2c3715SXin Li 87*bf2c3715SXin Li The function 88*bf2c3715SXin Li \code 89*bf2c3715SXin Li Real cauchy_min_bound( const Polynomial& poly ) 90*bf2c3715SXin Li \endcode 91*bf2c3715SXin Li provides a minimum bound (the Cauchy one: \f$c(p)\f$) for the absolute value of a non zero root of the given polynomial i.e. 92*bf2c3715SXin Li \f$ \forall r_i \neq 0 \f$ root of \f$ p(x) = \sum_{k=0}^d a_k x^k \f$, 93*bf2c3715SXin Li \f$ |r_i| \ge c(p) = \left( \sum_{k=0}^{d} \left | \frac{a_k}{a_0} \right | \right)^{-1} \f$ 94*bf2c3715SXin Li 95*bf2c3715SXin Li 96*bf2c3715SXin Li 97*bf2c3715SXin Li 98*bf2c3715SXin Li \section QR polynomial solver class 99*bf2c3715SXin Li Computes the complex roots of a polynomial by computing the eigenvalues of the associated companion matrix with the QR algorithm. 100*bf2c3715SXin Li 101*bf2c3715SXin Li The roots of \f$ p(x) = a_0 + a_1 x + a_2 x^2 + a_{3} x^3 + x^4 \f$ are the eigenvalues of 102*bf2c3715SXin Li \f$ 103*bf2c3715SXin Li \left [ 104*bf2c3715SXin Li \begin{array}{cccc} 105*bf2c3715SXin Li 0 & 0 & 0 & a_0 \\ 106*bf2c3715SXin Li 1 & 0 & 0 & a_1 \\ 107*bf2c3715SXin Li 0 & 1 & 0 & a_2 \\ 108*bf2c3715SXin Li 0 & 0 & 1 & a_3 109*bf2c3715SXin Li \end{array} \right ] 110*bf2c3715SXin Li \f$ 111*bf2c3715SXin Li 112*bf2c3715SXin Li However, the QR algorithm is not guaranteed to converge when there are several eigenvalues with same modulus. 113*bf2c3715SXin Li 114*bf2c3715SXin Li Therefore the current polynomial solver is guaranteed to provide a correct result only when the complex roots \f$r_1,r_2,...,r_d\f$ have distinct moduli i.e. 115*bf2c3715SXin Li 116*bf2c3715SXin Li \f$ \forall i,j \in [1;d],~ \| r_i \| \neq \| r_j \| \f$. 117*bf2c3715SXin Li 118*bf2c3715SXin Li With 32bit (float) floating types this problem shows up frequently. 119*bf2c3715SXin Li However, almost always, correct accuracy is reached even in these cases for 64bit 120*bf2c3715SXin Li (double) floating types and small polynomial degree (<20). 121*bf2c3715SXin Li 122*bf2c3715SXin Li \include PolynomialSolver1.cpp 123*bf2c3715SXin Li 124*bf2c3715SXin Li In the above example: 125*bf2c3715SXin Li 126*bf2c3715SXin Li -# a simple use of the polynomial solver is shown; 127*bf2c3715SXin Li -# the accuracy problem with the QR algorithm is presented: a polynomial with almost conjugate roots is provided to the solver. 128*bf2c3715SXin Li Those roots have almost same module therefore the QR algorithm failed to converge: the accuracy 129*bf2c3715SXin Li of the last root is bad; 130*bf2c3715SXin Li -# a simple way to circumvent the problem is shown: use doubles instead of floats. 131*bf2c3715SXin Li 132*bf2c3715SXin Li Output: \verbinclude PolynomialSolver1.out 133*bf2c3715SXin Li*/ 134*bf2c3715SXin Li 135*bf2c3715SXin Li#include "../../Eigen/src/Core/util/ReenableStupidWarnings.h" 136*bf2c3715SXin Li 137*bf2c3715SXin Li#endif // EIGEN_POLYNOMIALS_MODULE_H 138